From d9d36fc09996ed8c2574f9336c3594aa3cc56941 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 21 Dec 2005 13:13:10 +0100 Subject: Add initial draft of BitlBee schema --- doc/bitlbee.schema | 27 +++++++++++++++++++++++++++ storage.c | 2 ++ 2 files changed, 29 insertions(+) create mode 100644 doc/bitlbee.schema diff --git a/doc/bitlbee.schema b/doc/bitlbee.schema new file mode 100644 index 00000000..47d5e706 --- /dev/null +++ b/doc/bitlbee.schema @@ -0,0 +1,27 @@ +## LDAP Schema file for BitlBee +## +## We need the following object classes and related attributes: +## bitlBeeNick: +## - nick +## - password +## - setting (multiple values) +## +## bitlBeeAccount: +## - protocol (msn, oscar, jabber, yahoo, ...) +## - username +## - password +## - server name +## +## bitlBeeBuddy: +## - nick +## - handle + +## each bitlBeeNick has zero or more bitlBeeAccount subentries +## and bitlBeeAccount entries contain zero or more bitlBeeBuddy entries + +## The admin needs to setup the LDAP server to: +## - allow anonymous users to auth against bitlBeeNick objects on the +## password field +## - allow anonymous users to create new objects that start with nick= +## - allow read/write for a user that is authenticated only to his/her own +## object and subentries diff --git a/storage.c b/storage.c index b766c9e3..7a242c3c 100644 --- a/storage.c +++ b/storage.c @@ -6,6 +6,8 @@ /* Support for multiple storage backends */ +/* Copyright (C) 2005 Jelmer Vernooij */ + /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From a323a22773714a19254db34156500a67e5916451 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 12 Feb 2006 20:25:31 +1300 Subject: Add autoconnect property --- doc/bitlbee.schema | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/bitlbee.schema b/doc/bitlbee.schema index 47d5e706..9fc6895c 100644 --- a/doc/bitlbee.schema +++ b/doc/bitlbee.schema @@ -11,6 +11,7 @@ ## - username ## - password ## - server name +## - autoconnect (true/false) ## ## bitlBeeBuddy: ## - nick -- cgit v1.2.3 From f665dabdff831743ea35e755b6ec1e2fe2551d9c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 12 Feb 2006 21:02:03 +1300 Subject: Initial work on new LDB-based storage backend --- Makefile | 2 ++ configure | 35 +++++++++++++++++++++++++++++++++ storage_ldb.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 storage_ldb.c diff --git a/Makefile b/Makefile index 295fe69e..a32c2639 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,8 @@ objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o unix.o url.o user.o util.o subdirs = protocols +objects += $(LDB_OBJ) + # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) CFLAGS += -Wall diff --git a/configure b/configure index 2731d5b1..f0f2adcc 100755 --- a/configure +++ b/configure @@ -24,6 +24,7 @@ yahoo=1 debug=0 strip=1 ipv6=1 +ldb=auto ssl=auto arch=`uname -s` @@ -59,6 +60,8 @@ Option Description Default --ipv6=0/1 IPv6 socket support $ipv6 +--ldb=0/1/auto LDB support $ldb + --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl EOF @@ -210,6 +213,20 @@ EOF fi; } +detect_ldb() +{ + if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG ldb; then + cat<>Makefile.settings +EFLAGS+=`$PKG_CONFIG --libs ldb` +CFLAGS+=`$PKG_CONFIG --cflags ldb` +EOF + ldb=1 + ret=1 + else + ret=0 + fi +} + if [ "$msn" = 1 -o "$jabber" = 1 ]; then if [ "$ssl" = "auto" ]; then detect_gnutls @@ -270,6 +287,18 @@ if [ "$msn" = 1 -o "$jabber" = 1 ]; then echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings fi +if [ "$ldb" = "auto" ]; then + detect_ldb +fi + +if [ "$ldb" = 0 ]; then + echo "LDB_OBJ=\# no ldb" >> Makefile.settings + echo "#undef LDB" >> config.h +elif [ "$ldb" = 1 ]; then + echo "#define LDB 1" >> config.h + echo "LDB_OBJ=storage_ldb.o" >> Makefile.settings +fi + if [ "$strip" = 0 ]; then echo "STRIP=\# skip strip" >> Makefile.settings; else @@ -407,3 +436,9 @@ if [ -n "$protocols" ]; then else echo ' Building without IM-protocol support. We wish you a lot of fun...'; fi + +if [ "$ldb" = "0" ]; then + echo " LDB storage backend disabled." +else + echo " LDB storage backend enabled." +fi diff --git a/storage_ldb.c b/storage_ldb.c new file mode 100644 index 00000000..09d1452b --- /dev/null +++ b/storage_ldb.c @@ -0,0 +1,63 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Storage backend that uses the LDB embedded LDAP-like database */ + +/* Copyright (C) 2006 Jelmer Vernooij */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "bitlbee.h" +#include + +static void sldb_init (void) +{ +} + +static storage_status_t sldb_load ( const char *my_nick, const char* password, irc_t *irc ) +{ + return STORAGE_OK; +} + +static storage_status_t sldb_save( irc_t *irc, int overwrite ) +{ + return STORAGE_OK; +} + +static storage_status_t sldb_check_pass( const char *nick, const char *password ) +{ + return STORAGE_OK; +} + +static storage_status_t sldb_remove( const char *nick, const char *password ) +{ + return STORAGE_OK; +} + +storage_t storage_ldb = { + .name = "ldb", + .init = sldb_init, + .check_pass = sldb_check_pass, + .remove = sldb_remove, + .load = sldb_load, + .save = sldb_save +}; -- cgit v1.2.3 From f32d5578d7039f1e61e99b2e1f7bfd0a47828c8c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 24 Mar 2006 16:53:29 +0100 Subject: Switch from LDB to LDAP (LDB's authentication subsystem is not mature enough yet) --- Makefile | 2 +- configure | 30 +++++------ storage_ldap.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ storage_ldb.c | 63 ---------------------- 4 files changed, 178 insertions(+), 79 deletions(-) create mode 100644 storage_ldap.c delete mode 100644 storage_ldb.c diff --git a/Makefile b/Makefile index 9d16c53c..845beb1c 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_com headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h subdirs = protocols -objects += $(LDB_OBJ) +objects += $(LDAP_OBJ) # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) diff --git a/configure b/configure index 60d27b2e..6426a789 100755 --- a/configure +++ b/configure @@ -27,7 +27,7 @@ yahoo=1 debug=0 strip=1 ipv6=1 -ldb=auto +ldap=auto ssl=auto arch=`uname -s` @@ -64,7 +64,7 @@ Option Description Default --ipv6=0/1 IPv6 socket support $ipv6 ---ldb=0/1/auto LDB support $ldb +--ldap=0/1/auto LDAP support $ldap --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl @@ -223,14 +223,14 @@ EOF fi; } -detect_ldb() +detect_ldap() { if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG ldb; then cat<>Makefile.settings EFLAGS+=`$PKG_CONFIG --libs ldb` CFLAGS+=`$PKG_CONFIG --cflags ldb` EOF - ldb=1 + ldap=1 ret=1 else ret=0 @@ -297,16 +297,16 @@ if [ "$msn" = 1 -o "$jabber" = 1 ]; then echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings fi -if [ "$ldb" = "auto" ]; then - detect_ldb +if [ "$ldap" = "auto" ]; then + detect_ldap fi -if [ "$ldb" = 0 ]; then - echo "LDB_OBJ=\# no ldb" >> Makefile.settings - echo "#undef LDB" >> config.h -elif [ "$ldb" = 1 ]; then - echo "#define LDB 1" >> config.h - echo "LDB_OBJ=storage_ldb.o" >> Makefile.settings +if [ "$ldap" = 0 ]; then + echo "LDAP_OBJ=\# no ldap" >> Makefile.settings + echo "#undef LDAP" >> config.h +elif [ "$ldap" = 1 ]; then + echo "#define LDAP 1" >> config.h + echo "LDAP_OBJ=storage_ldap.o" >> Makefile.settings fi if [ "$strip" = 0 ]; then @@ -460,8 +460,8 @@ else echo ' Building without IM-protocol support. We wish you a lot of fun...'; fi -if [ "$ldb" = "0" ]; then - echo " LDB storage backend disabled." +if [ "$ldap" = "0" ]; then + echo " LDAP storage backend disabled." else - echo " LDB storage backend enabled." + echo " LDAP storage backend enabled." fi diff --git a/storage_ldap.c b/storage_ldap.c new file mode 100644 index 00000000..f6119168 --- /dev/null +++ b/storage_ldap.c @@ -0,0 +1,162 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Storage backend that uses a LDAP database */ + +/* Copyright (C) 2006 Jelmer Vernooij */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "bitlbee.h" +#include + +#define BB_LDAP_HOST "localhost" +#define BB_LDAP_BASE "" + +static char *nick_dn(const char *nick) +{ + return g_strdup_printf("bitlBeeNick=%s%s%s", nick, BB_LDAP_BASE?",":"", BB_LDAP_BASE?BB_LDAP_BASE:""); +} + +static storage_status_t nick_connect(const char *nick, const char *password, LDAP **ld) +{ + char *mydn; + int ret; + storage_status_t status; + *ld = ldap_init(BB_LDAP_HOST, LDAP_PORT); + + if (!ld) { + /* FIXME: report error */ + return STORAGE_OTHER_ERROR; + } + + mydn = nick_dn(nick); + + ret = ldap_simple_bind_s(*ld, mydn, password); + + switch (ret) { + case LDAP_SUCCESS: status = STORAGE_OK; break; + case LDAP_INVALID_CREDENTIALS: status = STORAGE_INVALID_PASSWORD; break; + default: + /* FIXME: Log */ + status = STORAGE_OTHER_ERROR; + break; + } + + g_free(mydn); + + return status; +} + +static void sldap_init (void) +{ +} + +static storage_status_t sldap_load ( const char *my_nick, const char* password, irc_t *irc ) +{ + LDAPMessage *res; + LDAP *ld; + int ret; + storage_status_t status; + char *mydn; + + status = nick_connect(my_nick, password, &ld); + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(my_nick); + + ret = ldap_search_s(ld, mydn, LDAP_SCOPE_ONELEVEL, "(objectClass=*)", NULL, 0, &res); + + g_free(mydn); + + /* FIXME: Check ret */ + + /* FIXME: Store in irc_t */ + + return STORAGE_OK; +} + +static storage_status_t sldap_save( irc_t *irc, int overwrite ) +{ + LDAP *ld; + char *mydn; + storage_status_t status; + + status = nick_connect(irc->nick, irc->password, &ld); + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(irc->nick); + + /* FIXME */ + + g_free(mydn); + + return STORAGE_OK; +} + +static storage_status_t sldap_check_pass( const char *nick, const char *password ) +{ + LDAP *ld; + storage_status_t status; + + status = nick_connect(nick, password, &ld); + + ldap_unbind_s(ld); + + return status; +} + +static storage_status_t sldap_remove( const char *nick, const char *password ) +{ + storage_status_t status; + LDAP *ld; + char *mydn; + int ret; + + status = nick_connect(nick, password, &ld); + + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(nick); + + ret = ldap_delete(ld, mydn); + + if (ret != LDAP_SUCCESS) { + /* FIXME: report */ + return STORAGE_OTHER_ERROR; + } + + g_free(mydn); + return STORAGE_OK; +} + +storage_t storage_ldap = { + .name = "ldap", + .init = sldap_init, + .check_pass = sldap_check_pass, + .remove = sldap_remove, + .load = sldap_load, + .save = sldap_save +}; diff --git a/storage_ldb.c b/storage_ldb.c deleted file mode 100644 index 09d1452b..00000000 --- a/storage_ldb.c +++ /dev/null @@ -1,63 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* Storage backend that uses the LDB embedded LDAP-like database */ - -/* Copyright (C) 2006 Jelmer Vernooij */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#define BITLBEE_CORE -#include "bitlbee.h" -#include - -static void sldb_init (void) -{ -} - -static storage_status_t sldb_load ( const char *my_nick, const char* password, irc_t *irc ) -{ - return STORAGE_OK; -} - -static storage_status_t sldb_save( irc_t *irc, int overwrite ) -{ - return STORAGE_OK; -} - -static storage_status_t sldb_check_pass( const char *nick, const char *password ) -{ - return STORAGE_OK; -} - -static storage_status_t sldb_remove( const char *nick, const char *password ) -{ - return STORAGE_OK; -} - -storage_t storage_ldb = { - .name = "ldb", - .init = sldb_init, - .check_pass = sldb_check_pass, - .remove = sldb_remove, - .load = sldb_load, - .save = sldb_save -}; -- cgit v1.2.3 From d5dfc3d7ff2756a5991356bb643630fa7b03f8d9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 24 Mar 2006 17:48:00 +0100 Subject: Start working on LDAP schema (OID's still need to be filled in) --- doc/bitlbee.schema | 65 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/doc/bitlbee.schema b/doc/bitlbee.schema index 9fc6895c..795f5854 100644 --- a/doc/bitlbee.schema +++ b/doc/bitlbee.schema @@ -1,17 +1,7 @@ ## LDAP Schema file for BitlBee +## Copyright (C) 2006 Jelmer Vernooij ## ## We need the following object classes and related attributes: -## bitlBeeNick: -## - nick -## - password -## - setting (multiple values) -## -## bitlBeeAccount: -## - protocol (msn, oscar, jabber, yahoo, ...) -## - username -## - password -## - server name -## - autoconnect (true/false) ## ## bitlBeeBuddy: ## - nick @@ -26,3 +16,56 @@ ## - allow anonymous users to create new objects that start with nick= ## - allow read/write for a user that is authenticated only to his/her own ## object and subentries + +## - userid +## - userPassword +## - setting (multiple values) +## depends: top, account + +#FIXME: Unique OID + +attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAutoConnect' + DESC 'Autoconnect setting' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) + +#FIXME: Unique OID + +attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAccountNo' + DESC 'Account number' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#FIXME: Unique OID + +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeAccount' SUP account STRUCTURAL + DESC 'BitlBee User Account ' + MUST ( userid, userPassword ) + MAY ( ) ) + +## bitlBeeAccount: +## - accountNo 1.3.6.1.4.1.1466.115.121.1.27 +## - protocol (msn, oscar, jabber, yahoo, ...) +## - username +## - password +## - server name +## - autoconnect (true/false) 1.3.6.1.4.1.1466.115.121.1.7 +## depends: top + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeIMAccount' SUP account STRUCTURAL + DESC 'BitlBee IM Account ' + MUST ( bitlBeeAccountNo, userid, userPassword ) + MAY ( host, bitlBeeAutoconnect ) ) + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeSetting' SUP top STRUCTURAL + DESC 'BitlBee Configuration Setting' + MUST ( bitlBeeSettingName ) + MAY ( bitlBeeSettingValue ) ) + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeBuddy' SUP top STRUCTURAL + DESC 'BitlBee Nick Mapping' + MUST ( bitlBeeBuddyHandle ) + MAY ( ircNick ) ) -- cgit v1.2.3 From a15c097fa32028394264cf66ef4fd31f56315eb3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 24 Mar 2006 17:48:16 +0100 Subject: More work on LDAP backend; report errors --- storage_ldap.c | 75 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/storage_ldap.c b/storage_ldap.c index f6119168..4bc99de5 100644 --- a/storage_ldap.c +++ b/storage_ldap.c @@ -45,7 +45,7 @@ static storage_status_t nick_connect(const char *nick, const char *password, LDA *ld = ldap_init(BB_LDAP_HOST, LDAP_PORT); if (!ld) { - /* FIXME: report error */ + log_message( LOGLVL_WARNING, "Unable to connect to LDAP server at %s", BB_LDAP_HOST ); return STORAGE_OTHER_ERROR; } @@ -57,7 +57,7 @@ static storage_status_t nick_connect(const char *nick, const char *password, LDA case LDAP_SUCCESS: status = STORAGE_OK; break; case LDAP_INVALID_CREDENTIALS: status = STORAGE_INVALID_PASSWORD; break; default: - /* FIXME: Log */ + log_message( LOGLVL_WARNING, "Unable to authenticate %s: %s", mydn, ldap_err2string(ret) ); status = STORAGE_OTHER_ERROR; break; } @@ -67,15 +67,11 @@ static storage_status_t nick_connect(const char *nick, const char *password, LDA return status; } -static void sldap_init (void) -{ -} - static storage_status_t sldap_load ( const char *my_nick, const char* password, irc_t *irc ) { - LDAPMessage *res; + LDAPMessage *res, *msg; LDAP *ld; - int ret; + int ret, i; storage_status_t status; char *mydn; @@ -85,32 +81,22 @@ static storage_status_t sldap_load ( const char *my_nick, const char* password, mydn = nick_dn(my_nick); - ret = ldap_search_s(ld, mydn, LDAP_SCOPE_ONELEVEL, "(objectClass=*)", NULL, 0, &res); + ret = ldap_search_s(ld, mydn, LDAP_SCOPE_BASE, "(objectClass=*)", NULL, 0, &res); + + if (ret != LDAP_SUCCESS) { + log_message( LOGLVL_WARNING, "Unable to search for %s: %s", mydn, ldap_err2string(ret) ); + ldap_unbind_s(ld); + return STORAGE_OTHER_ERROR; + } g_free(mydn); - /* FIXME: Check ret */ + for (msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) { + } /* FIXME: Store in irc_t */ - - return STORAGE_OK; -} - -static storage_status_t sldap_save( irc_t *irc, int overwrite ) -{ - LDAP *ld; - char *mydn; - storage_status_t status; - status = nick_connect(irc->nick, irc->password, &ld); - if (status != STORAGE_OK) - return status; - - mydn = nick_dn(irc->nick); - - /* FIXME */ - - g_free(mydn); + ldap_unbind_s(ld); return STORAGE_OK; } @@ -144,17 +130,46 @@ static storage_status_t sldap_remove( const char *nick, const char *password ) ret = ldap_delete(ld, mydn); if (ret != LDAP_SUCCESS) { - /* FIXME: report */ + log_message( LOGLVL_WARNING, "Error removing %s: %s", mydn, ldap_err2string(ret) ); + ldap_unbind_s(ld); return STORAGE_OTHER_ERROR; } + ldap_unbind_s(ld); + g_free(mydn); return STORAGE_OK; } +static storage_status_t sldap_save( irc_t *irc, int overwrite ) +{ + LDAP *ld; + char *mydn; + storage_status_t status; + LDAPMessage *msg; + + status = nick_connect(irc->nick, irc->password, &ld); + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(irc->nick); + + /* FIXME: Make this a bit more atomic? What if we crash after + * removing the old account but before adding the new one ? */ + if (overwrite) + sldap_remove(irc->nick, irc->password); + + g_free(mydn); + + ldap_unbind_s(ld); + + return STORAGE_OK; +} + + + storage_t storage_ldap = { .name = "ldap", - .init = sldap_init, .check_pass = sldap_check_pass, .remove = sldap_remove, .load = sldap_load, -- cgit v1.2.3 From a0d04d6253cf70877a11156059209e1f9a2efe31 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 7 May 2006 20:07:43 +0200 Subject: Got rid of all GLib GIOChannel-related calls outside proxy.c --- bitlbee.c | 55 ++++++++++++++++++++++++++----------------------------- bitlbee.h | 5 +++-- ipc.c | 29 +++++++++-------------------- irc.c | 28 +++++++++++----------------- irc.h | 1 - 5 files changed, 49 insertions(+), 69 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 3aca30c5..fb04897d 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -33,7 +33,7 @@ #include #include -gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data ); +void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condition ); int bitlbee_daemon_init() { @@ -43,7 +43,6 @@ int bitlbee_daemon_init() struct sockaddr_in listen_addr; #endif int i; - GIOChannel *ch; FILE *fp; log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG ); @@ -90,8 +89,7 @@ int bitlbee_daemon_init() return( -1 ); } - ch = g_io_channel_unix_new( global.listen_socket ); - global.listen_watch_source_id = g_io_add_watch( ch, G_IO_IN, bitlbee_io_new_client, NULL ); + global.listen_watch_source_id = gaim_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL ); #ifndef _WIN32 if( !global.conf->nofork ) @@ -146,34 +144,28 @@ int bitlbee_inetd_init() return( 0 ); } -gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condition, gpointer data ) +void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondition cond ) { irc_t *irc = data; char line[513]; int st; - if( condition & G_IO_ERR || condition & G_IO_HUP ) - { - irc_abort( irc, 1, "Read error" ); - return FALSE; - } - st = read( irc->fd, line, sizeof( line ) - 1 ); if( st == 0 ) { irc_abort( irc, 1, "Connection reset by peer" ); - return FALSE; + goto no_more_events; } else if( st < 0 ) { if( sockerr_again() ) { - return TRUE; + return; } else { irc_abort( irc, 1, "Read error: %s", strerror( errno ) ); - return FALSE; + goto no_more_events; } } @@ -194,27 +186,31 @@ gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condit if( !g_slist_find( irc_connection_list, irc ) ) { log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd ); - return FALSE; + goto no_more_events; } /* Very naughty, go read the RFCs! >:) */ if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) ) { irc_abort( irc, 0, "Maximum line length exceeded" ); - return FALSE; + goto no_more_events; } - return TRUE; + return; + +no_more_events: + gaim_input_remove( irc->r_watch_source_id ); + irc->r_watch_source_id = 0; } -gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data ) +void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondition cond ) { irc_t *irc = data; int st, size; char *temp; if( irc->sendbuffer == NULL ) - return( FALSE ); + goto no_more_events; size = strlen( irc->sendbuffer ); st = write( irc->fd, irc->sendbuffer, size ); @@ -222,23 +218,22 @@ gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condi if( st == 0 || ( st < 0 && !sockerr_again() ) ) { irc_abort( irc, 1, "Write error: %s", strerror( errno ) ); - return FALSE; + goto no_more_events; } else if( st < 0 ) /* && sockerr_again() */ { - return TRUE; + return; } if( st == size ) { g_free( irc->sendbuffer ); irc->sendbuffer = NULL; - irc->w_watch_source_id = 0; if( irc->status == USTATUS_SHUTDOWN ) irc_free( irc ); - return( FALSE ); + goto no_more_events; } else { @@ -246,13 +241,17 @@ gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condi g_free( irc->sendbuffer ); irc->sendbuffer = temp; - return( TRUE ); + return; } + +no_more_events: + gaim_input_remove( irc->w_watch_source_id ); + irc->w_watch_source_id = 0; } -gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data ) +void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condition ) { - size_t size = sizeof( struct sockaddr_in ); + socklen_t size = sizeof( struct sockaddr_in ); struct sockaddr_in conn_info; int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size ); pid_t client_pid = 0; @@ -260,7 +259,7 @@ gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpoi if( new_socket == -1 ) { log_message( LOGLVL_WARNING, "Could not accept new connection: %s", strerror( errno ) ); - return TRUE; + return; } if( global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -319,8 +318,6 @@ gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpoi log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); irc_new( new_socket ); } - - return TRUE; } void bitlbee_shutdown( gpointer data ) diff --git a/bitlbee.h b/bitlbee.h index 4da87ec6..00e5ce97 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -111,6 +111,7 @@ extern char *CONF_FILE; #include "query.h" #include "sock.h" #include "util.h" +#include "proxy.h" typedef struct global { /* In forked mode, child processes store the fd of the IPC socket here. */ @@ -127,8 +128,8 @@ typedef struct global { int bitlbee_daemon_init( void ); int bitlbee_inetd_init( void ); -gboolean bitlbee_io_current_client_read( GIOChannel *source, GIOCondition condition, gpointer data ); -gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condition, gpointer data ); +void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondition cond ); +void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondition cond ); void root_command_string( irc_t *irc, user_t *u, char *command, int flags ); void root_command( irc_t *irc, char *command[] ); diff --git a/ipc.c b/ipc.c index 48bd574a..c16acd72 100644 --- a/ipc.c +++ b/ipc.c @@ -462,25 +462,21 @@ void ipc_master_set_statefile( char *fn ) } -static gboolean new_ipc_client (GIOChannel *gio, GIOCondition cond, gpointer data) +static void new_ipc_client( gpointer data, gint serversock, GaimInputCondition cond ) { struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 ); - int serversock; - - serversock = g_io_channel_unix_get_fd(gio); - - child->ipc_fd = accept(serversock, NULL, 0); - - if (child->ipc_fd == -1) { + + child->ipc_fd = accept( serversock, NULL, 0 ); + + if( child->ipc_fd == -1 ) + { log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) ); - return TRUE; + return; } child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); - + child_list = g_slist_append( child_list, child ); - - return TRUE; } #ifndef _WIN32 @@ -488,7 +484,6 @@ int ipc_master_listen_socket() { struct sockaddr_un un_addr; int serversock; - GIOChannel *gio; /* Clean up old socket files that were hanging around.. */ if (unlink(IPCSOCKET) == -1 && errno != ENOENT) { @@ -516,14 +511,8 @@ int ipc_master_listen_socket() return 0; } - gio = g_io_channel_unix_new(serversock); + gaim_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL ); - if (gio == NULL) { - log_message( LOGLVL_WARNING, "Unable to create IO channel for unix socket" ); - return 0; - } - - g_io_add_watch(gio, G_IO_IN, new_ipc_client, NULL); return 1; } #else diff --git a/irc.c b/irc.c index 44fc9ad3..53dea8ba 100644 --- a/irc.c +++ b/irc.c @@ -53,15 +53,9 @@ irc_t *irc_new( int fd ) irc = g_new0( irc_t, 1 ); irc->fd = fd; - irc->io_channel = g_io_channel_unix_new( fd ); -#ifdef GLIB2 - g_io_channel_set_encoding (irc->io_channel, NULL, NULL); - g_io_channel_set_buffered (irc->io_channel, FALSE); - g_io_channel_set_flags( irc->io_channel, G_IO_FLAG_NONBLOCK, NULL ); -#else - fcntl( irc->fd, F_SETFL, O_NONBLOCK); -#endif - irc->r_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, bitlbee_io_current_client_read, irc ); + sock_make_nonblocking( irc->fd ); + + irc->r_watch_source_id = gaim_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc ); irc->status = USTATUS_OFFLINE; irc->last_pong = gettime(); @@ -228,7 +222,6 @@ void irc_free(irc_t * irc) if( irc->w_watch_source_id > 0 ) g_source_remove( irc->w_watch_source_id ); - g_io_channel_unref( irc->io_channel ); irc_connection_list = g_slist_remove( irc_connection_list, irc ); for (account = irc->accounts; account; account = account->next) { @@ -599,19 +592,20 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) } strcat( line, "\r\n" ); - if( irc->sendbuffer != NULL ) { + if( irc->sendbuffer != NULL ) + { size = strlen( irc->sendbuffer ) + strlen( line ); irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 ); strcpy( ( irc->sendbuffer + strlen( irc->sendbuffer ) ), line ); } - else - irc->sendbuffer = g_strdup(line); - - if( irc->w_watch_source_id == 0 ) + else { - irc->w_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_OUT, bitlbee_io_current_client_write, irc ); + irc->sendbuffer = g_strdup(line); } + if( irc->w_watch_source_id == 0 ) + irc->w_watch_source_id = gaim_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); + return; } @@ -635,7 +629,7 @@ void irc_write_all( int now, char *format, ... ) irc_vawrite( temp->data, format, params ); if( now ) { - bitlbee_io_current_client_write( irc->io_channel, G_IO_OUT, irc ); + bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ); } temp = temp->next; } diff --git a/irc.h b/irc.h index 86721058..394e1d54 100644 --- a/irc.h +++ b/irc.h @@ -92,7 +92,6 @@ typedef struct irc struct help *help; struct set *set; - GIOChannel *io_channel; gint r_watch_source_id; gint w_watch_source_id; gint ping_source_id; -- cgit v1.2.3 From ecf8fa820aa8fa3592bdf96ed3bdeec4ec94f036 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 9 May 2006 09:20:05 +0200 Subject: Split off event handling related functions (depending on GLib) to events_glib.c. --- protocols/Makefile | 2 +- protocols/events.h | 56 +++++++++++++++++++++++++++ protocols/events_glib.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ protocols/nogaim.c | 4 +- protocols/proxy.c | 62 ------------------------------ protocols/proxy.h | 13 ++----- 6 files changed, 161 insertions(+), 76 deletions(-) create mode 100644 protocols/events.h create mode 100644 protocols/events_glib.c diff --git a/protocols/Makefile b/protocols/Makefile index 4016e7fd..886f010b 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) +objects = events_glib.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into diff --git a/protocols/events.h b/protocols/events.h new file mode 100644 index 00000000..682a9c23 --- /dev/null +++ b/protocols/events.h @@ -0,0 +1,56 @@ +/* + * nogaim + * + * Copyright (C) 2006 Wilmer van der Gaast and others + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + * + */ + +/* + * Split off the event handling things from proxy.[ch] (and adding timer + * stuff. This to allow BitlBee to use other libs than GLib for event + * handling. + */ + + +#ifndef _EVENTS_H_ +#define _EVENTS_H_ + +#include +#ifndef _WIN32 +#include +#include +#include +#endif +#include +#include + +typedef enum { + GAIM_INPUT_READ = 1 << 0, + GAIM_INPUT_WRITE = 1 << 1 +} GaimInputCondition; +typedef void (*GaimInputFunction)(gpointer, gint, GaimInputCondition); + +#define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) +#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) +#define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) + +G_MODULE_EXPORT gint gaim_input_add(int fd, GaimInputCondition cond, GaimInputFunction func, gpointer data); +G_MODULE_EXPORT void gaim_input_remove(gint id); + +G_MODULE_EXPORT gint bee_timeout_add(gint timeout, GaimInputFunction func, gpointer data, gint priority); + +#endif /* _EVENTS_H_ */ diff --git a/protocols/events_glib.c b/protocols/events_glib.c new file mode 100644 index 00000000..f3b27565 --- /dev/null +++ b/protocols/events_glib.c @@ -0,0 +1,100 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2006 Wilmer van der Gaast and others * + \********************************************************************/ + +/* + * Event handling (using GLib) + */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#else +#include "sock.h" +#define ETIMEDOUT WSAETIMEDOUT +#define EINPROGRESS WSAEINPROGRESS +#endif +#include +#include +#include "proxy.h" + +typedef struct _GaimIOClosure { + GaimInputFunction function; + guint result; + gpointer data; +} GaimIOClosure; + +static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +{ + GaimIOClosure *closure = data; + GaimInputCondition gaim_cond = 0; + + if (condition & GAIM_READ_COND) + gaim_cond |= GAIM_INPUT_READ; + if (condition & GAIM_WRITE_COND) + gaim_cond |= GAIM_INPUT_WRITE; + + closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); + + return TRUE; +} + +static void gaim_io_destroy(gpointer data) +{ + g_free(data); +} + +gint gaim_input_add(gint source, GaimInputCondition condition, GaimInputFunction function, gpointer data) +{ + GaimIOClosure *closure = g_new0(GaimIOClosure, 1); + GIOChannel *channel; + GIOCondition cond = 0; + + closure->function = function; + closure->data = data; + + if (condition & GAIM_INPUT_READ) + cond |= GAIM_READ_COND; + if (condition & GAIM_INPUT_WRITE) + cond |= GAIM_WRITE_COND; + + channel = g_io_channel_unix_new(source); + closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + gaim_io_invoke, closure, gaim_io_destroy); + + g_io_channel_unref(channel); + return closure->result; +} + +void gaim_input_remove(gint tag) +{ + if (tag > 0) + g_source_remove(tag); +} diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 51d08e5a..4c2a3bb4 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2006 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -12,8 +12,6 @@ * This file contains functions called by the Gaim IM-modules. It's written * from scratch for BitlBee and doesn't contain any code from Gaim anymore * (except for the function names). - * - * Copyright 2002-2006 Wilmer van der Gaast and others */ /* diff --git a/protocols/proxy.c b/protocols/proxy.c index 1ca35dfe..57d804c6 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -20,10 +20,6 @@ * */ -/* this is a little piece of code to handle proxy connection */ -/* it is intended to : 1st handle http proxy, using the CONNECT command - , 2nd provide an easy way to add socks support */ - #define BITLBEE_CORE #include #include @@ -45,10 +41,6 @@ #include "nogaim.h" #include "proxy.h" -#define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) -#define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) - char proxyhost[128] = ""; int proxyport = 0; int proxytype = PROXY_NONE; @@ -64,12 +56,6 @@ struct PHB { gint inpa; }; -typedef struct _GaimIOClosure { - GaimInputFunction function; - guint result; - gpointer data; -} GaimIOClosure; - static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) @@ -91,26 +77,6 @@ static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) return &sin; } -static void gaim_io_destroy(gpointer data) -{ - g_free(data); -} - -static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) -{ - GaimIOClosure *closure = data; - GaimInputCondition gaim_cond = 0; - - if (condition & GAIM_READ_COND) - gaim_cond |= GAIM_INPUT_READ; - if (condition & GAIM_WRITE_COND) - gaim_cond |= GAIM_INPUT_WRITE; - - closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); - - return TRUE; -} - static void gaim_io_connected(gpointer data, gint source, GaimInputCondition cond) { struct PHB *phb = data; @@ -541,34 +507,6 @@ static int proxy_connect_socks5(const char *host, unsigned short port, struct PH /* Export functions */ -gint gaim_input_add(gint source, GaimInputCondition condition, GaimInputFunction function, gpointer data) -{ - GaimIOClosure *closure = g_new0(GaimIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & GAIM_INPUT_READ) - cond |= GAIM_READ_COND; - if (condition & GAIM_INPUT_WRITE) - cond |= GAIM_WRITE_COND; - - channel = g_io_channel_unix_new(source); - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - gaim_io_invoke, closure, gaim_io_destroy); - - g_io_channel_unref(channel); - return closure->result; -} - -void gaim_input_remove(gint tag) -{ - if (tag > 0) - g_source_remove(tag); -} - int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data) { struct PHB *phb; diff --git a/protocols/proxy.h b/protocols/proxy.h index 47c966d2..7094b334 100644 --- a/protocols/proxy.h +++ b/protocols/proxy.h @@ -1,5 +1,5 @@ /* - * gaim + * nogaim * * Copyright (C) 1998-1999, Mark Spencer * @@ -35,6 +35,8 @@ #include #include +#include "events.h" + #define PROXY_NONE 0 #define PROXY_HTTP 1 #define PROXY_SOCKS4 2 @@ -46,15 +48,6 @@ extern int proxytype; extern char proxyuser[128]; extern char proxypass[128]; -typedef enum { - GAIM_INPUT_READ = 1 << 0, - GAIM_INPUT_WRITE = 1 << 1 -} GaimInputCondition; -typedef void (*GaimInputFunction)(gpointer, gint, GaimInputCondition); - -G_MODULE_EXPORT gint gaim_input_add(int, GaimInputCondition, GaimInputFunction, gpointer); -G_MODULE_EXPORT void gaim_input_remove(gint); - G_MODULE_EXPORT int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data); #endif /* _PROXY_H_ */ -- cgit v1.2.3 From 67b6766489f1b9b5f2249659b0ddf260e6f8f51b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 9 May 2006 09:20:36 +0200 Subject: Some extra #defines in bitlbee.h to prevent the use of some GLib functions. --- bitlbee.h | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index 00e5ce97..f9bb70bb 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -57,23 +57,38 @@ /* The following functions should not be used if we want to maintain Windows compatibility... */ #undef free -#define free __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__ +#define free __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef malloc -#define malloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__ +#define malloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef calloc -#define calloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__ +#define calloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef realloc -#define realloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM_INSTEAD__ +#define realloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef strdup -#define strdup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM_INSTEAD__ +#define strdup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ #undef strndup -#define strndup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM_INSTEAD__ +#define strndup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ #undef snprintf -#define snprintf __PLEASE_USE_G_SNPRINTF_INSTEAD__ +#define snprintf __PLEASE_USE_G_SNPRINTF__ #undef strcasecmp -#define strcasecmp __PLEASE_USE_G_STRCASECMP_INSTEAD__ +#define strcasecmp __PLEASE_USE_G_STRCASECMP__ #undef strncasecmp -#define strncasecmp __PLEASE_USE_G_STRNCASECMP_INSTEAD__ +#define strncasecmp __PLEASE_USE_G_STRNCASECMP__ + +/* And the following functions shouldn't be used anymore to keep compatibility + with other event handling libs than GLib. */ +#undef g_timeout_add +#define g_timeout_add __PLEASE_USE_B_TIMEOUT_ADD__ +#undef g_timeout_add_full +#define g_timeout_add_full __PLEASE_USE_B_TIMEOUT_ADD__ +#undef g_source_remove +#define g_source_remove __PLEASE_USE_B_SOURCE_REMOVE__ +#undef g_source_remove_by_user_data +#define g_source_remove_by_user_data __PLEASE_USE_B_SOURCE_REMOVE_BY_USER_DATA__ +#undef g_main_run +#define g_main_run __PLEASE_USE_B_MAIN_RUN__ +#undef g_main_quit +#define g_main_quit __PLEASE_USE_B_MAIN_QUIT__ #ifndef F_OK #define F_OK 0 -- cgit v1.2.3 From ba9edaa568088900145bbd1004c864b7d408c38d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 10 May 2006 19:34:46 +0200 Subject: Moved everything to the BitlBee event handling API. --- bitlbee.c | 57 +++++++++++------------ bitlbee.h | 13 ++++-- ipc.c | 28 +++++++----- ipc.h | 4 +- irc.c | 36 +++++++-------- protocols/events.h | 14 ++++-- protocols/events_glib.c | 39 +++++++++++++--- protocols/http_client.c | 40 ++++++++-------- protocols/jabber/jabber.c | 28 +++++++----- protocols/msn/msn.h | 4 +- protocols/msn/ns.c | 20 +++++--- protocols/msn/sb.c | 20 +++++--- protocols/nogaim.c | 14 +++--- protocols/nogaim.h | 2 +- protocols/oscar/oscar.c | 99 +++++++++++++++++++++++----------------- protocols/proxy.c | 114 ++++++++++++++++++++++++++-------------------- protocols/proxy.h | 2 +- protocols/ssl_bogus.c | 2 +- protocols/ssl_client.h | 4 +- protocols/ssl_gnutls.c | 10 ++-- protocols/ssl_nss.c | 10 ++-- protocols/ssl_openssl.c | 10 ++-- protocols/yahoo/yahoo.c | 18 ++++---- unix.c | 6 +-- user.c | 2 +- 25 files changed, 342 insertions(+), 254 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index fb04897d..e52830be 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -33,7 +33,7 @@ #include #include -void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condition ); +static gboolean bitlbee_io_new_client( gpointer data, gint source, b_input_condition condition ); int bitlbee_daemon_init() { @@ -89,7 +89,7 @@ int bitlbee_daemon_init() return( -1 ); } - global.listen_watch_source_id = gaim_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL ); + global.listen_watch_source_id = b_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL ); #ifndef _WIN32 if( !global.conf->nofork ) @@ -144,7 +144,7 @@ int bitlbee_inetd_init() return( 0 ); } -void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondition cond ) +gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_condition cond ) { irc_t *irc = data; char line[513]; @@ -154,18 +154,18 @@ void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondit if( st == 0 ) { irc_abort( irc, 1, "Connection reset by peer" ); - goto no_more_events; + return FALSE; } else if( st < 0 ) { if( sockerr_again() ) { - return; + return TRUE; } else { irc_abort( irc, 1, "Read error: %s", strerror( errno ) ); - goto no_more_events; + return FALSE; } } @@ -186,31 +186,27 @@ void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondit if( !g_slist_find( irc_connection_list, irc ) ) { log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd ); - goto no_more_events; + return FALSE; } /* Very naughty, go read the RFCs! >:) */ if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) ) { irc_abort( irc, 0, "Maximum line length exceeded" ); - goto no_more_events; + return FALSE; } - return; - -no_more_events: - gaim_input_remove( irc->r_watch_source_id ); - irc->r_watch_source_id = 0; + return TRUE; } -void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondition cond ) +gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ) { irc_t *irc = data; int st, size; char *temp; if( irc->sendbuffer == NULL ) - goto no_more_events; + return FALSE; size = strlen( irc->sendbuffer ); st = write( irc->fd, irc->sendbuffer, size ); @@ -218,22 +214,23 @@ void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondi if( st == 0 || ( st < 0 && !sockerr_again() ) ) { irc_abort( irc, 1, "Write error: %s", strerror( errno ) ); - goto no_more_events; + return FALSE; } else if( st < 0 ) /* && sockerr_again() */ { - return; + return TRUE; } if( st == size ) { g_free( irc->sendbuffer ); irc->sendbuffer = NULL; + irc->w_watch_source_id = 0; if( irc->status == USTATUS_SHUTDOWN ) irc_free( irc ); - goto no_more_events; + return FALSE; } else { @@ -241,15 +238,11 @@ void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondi g_free( irc->sendbuffer ); irc->sendbuffer = temp; - return; + return TRUE; } - -no_more_events: - gaim_input_remove( irc->w_watch_source_id ); - irc->w_watch_source_id = 0; } -void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condition ) +static gboolean bitlbee_io_new_client( gpointer data, gint source, b_input_condition condition ) { socklen_t size = sizeof( struct sockaddr_in ); struct sockaddr_in conn_info; @@ -259,7 +252,7 @@ void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condi if( new_socket == -1 ) { log_message( LOGLVL_WARNING, "Could not accept new connection: %s", strerror( errno ) ); - return; + return TRUE; } if( global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -284,7 +277,7 @@ void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condi child = g_new0( struct bitlbee_child, 1 ); child->pid = client_pid; child->ipc_fd = fds[0]; - child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); + child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); child_list = g_slist_append( child_list, child ); log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid ); @@ -299,14 +292,14 @@ void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condi /* Close the listening socket, we're a client. */ close( global.listen_socket ); - g_source_remove( global.listen_watch_source_id ); + b_event_remove( global.listen_watch_source_id ); /* Make the connection. */ irc = irc_new( new_socket ); /* We can store the IPC fd there now. */ global.listen_socket = fds[1]; - global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc ); + global.listen_watch_source_id = b_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc ); close( fds[0] ); @@ -318,14 +311,18 @@ void bitlbee_io_new_client( gpointer data, gint source, GaimInputCondition condi log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); irc_new( new_socket ); } + + return TRUE; } -void bitlbee_shutdown( gpointer data ) +gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ) { /* Try to save data for all active connections (if desired). */ while( irc_connection_list != NULL ) irc_free( irc_connection_list->data ); /* We'll only reach this point when not running in inetd mode: */ - g_main_quit( global.loop ); + b_main_quit(); + + return FALSE; } diff --git a/bitlbee.h b/bitlbee.h index f9bb70bb..709856d8 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -81,8 +81,12 @@ #define g_timeout_add __PLEASE_USE_B_TIMEOUT_ADD__ #undef g_timeout_add_full #define g_timeout_add_full __PLEASE_USE_B_TIMEOUT_ADD__ +#undef g_io_add_watch +#define g_io_add_watch __PLEASE_USE_B_INPUT_ADD__ +#undef g_io_add_watch_full +#define g_io_add_watch_full __PLEASE_USE_B_INPUT_ADD__ #undef g_source_remove -#define g_source_remove __PLEASE_USE_B_SOURCE_REMOVE__ +#define g_source_remove __PLEASE_USE_B_EVENT_REMOVE__ #undef g_source_remove_by_user_data #define g_source_remove_by_user_data __PLEASE_USE_B_SOURCE_REMOVE_BY_USER_DATA__ #undef g_main_run @@ -136,19 +140,18 @@ typedef struct global { conf_t *conf; GList *storage; /* The first backend in the list will be used for saving */ char *helpfile; - GMainLoop *loop; int restart; } global_t; int bitlbee_daemon_init( void ); int bitlbee_inetd_init( void ); -void bitlbee_io_current_client_read( gpointer data, gint source, GaimInputCondition cond ); -void bitlbee_io_current_client_write( gpointer data, gint source, GaimInputCondition cond ); +gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_condition cond ); +gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); void root_command_string( irc_t *irc, user_t *u, char *command, int flags ); void root_command( irc_t *irc, char *command[] ); -void bitlbee_shutdown( gpointer data ); +gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); extern global_t global; diff --git a/ipc.c b/ipc.c index c16acd72..a8b110b6 100644 --- a/ipc.c +++ b/ipc.c @@ -59,7 +59,7 @@ static void ipc_master_cmd_die( irc_t *data, char **cmd ) if( global.conf->runmode == RUNMODE_FORKDAEMON ) ipc_to_children_str( "DIE\r\n" ); - bitlbee_shutdown( NULL ); + bitlbee_shutdown( NULL, -1, 0 ); } void ipc_master_cmd_rehash( irc_t *data, char **cmd ) @@ -90,7 +90,7 @@ void ipc_master_cmd_restart( irc_t *data, char **cmd ) } global.restart = -1; - bitlbee_shutdown( NULL ); + bitlbee_shutdown( NULL, -1, 0 ); } static const command_t ipc_master_commands[] = { @@ -245,7 +245,7 @@ static char *ipc_readline( int fd ) return buf; } -void ipc_master_read( gpointer data, gint source, GaimInputCondition cond ) +gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ) { char *buf, **cmd; @@ -271,9 +271,11 @@ void ipc_master_read( gpointer data, gint source, GaimInputCondition cond ) } } } + + return TRUE; } -void ipc_child_read( gpointer data, gint source, GaimInputCondition cond ) +gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ) { char *buf, **cmd; @@ -285,11 +287,13 @@ void ipc_child_read( gpointer data, gint source, GaimInputCondition cond ) } else { - gaim_input_remove( global.listen_watch_source_id ); + b_event_remove( global.listen_watch_source_id ); close( global.listen_socket ); global.listen_socket = -1; } + + return TRUE; } void ipc_to_master( char **cmd ) @@ -396,7 +400,7 @@ void ipc_to_children_str( char *format, ... ) void ipc_master_free_one( struct bitlbee_child *c ) { - gaim_input_remove( c->ipc_inpa ); + b_event_remove( c->ipc_inpa ); closesocket( c->ipc_fd ); g_free( c->host ); @@ -462,7 +466,7 @@ void ipc_master_set_statefile( char *fn ) } -static void new_ipc_client( gpointer data, gint serversock, GaimInputCondition cond ) +static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond ) { struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 ); @@ -471,12 +475,14 @@ static void new_ipc_client( gpointer data, gint serversock, GaimInputCondition c if( child->ipc_fd == -1 ) { log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) ); - return; + return TRUE; } - child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); + child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); child_list = g_slist_append( child_list, child ); + + return TRUE; } #ifndef _WIN32 @@ -511,7 +517,7 @@ int ipc_master_listen_socket() return 0; } - gaim_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL ); + b_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL ); return 1; } @@ -551,7 +557,7 @@ int ipc_master_load_state() fclose( fp ); return 0; } - child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); + child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); child_list = g_slist_append( child_list, child ); } diff --git a/ipc.h b/ipc.h index 7ff74a15..2b85426b 100644 --- a/ipc.h +++ b/ipc.h @@ -39,8 +39,8 @@ struct bitlbee_child }; -void ipc_master_read( gpointer data, gint source, GaimInputCondition cond ); -void ipc_child_read( gpointer data, gint source, GaimInputCondition cond ); +gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ); +gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ); void ipc_master_free_one( struct bitlbee_child *child ); void ipc_master_free_all(); diff --git a/irc.c b/irc.c index 53dea8ba..8112a3e8 100644 --- a/irc.c +++ b/irc.c @@ -28,7 +28,7 @@ #include "crypting.h" #include "ipc.h" -static gboolean irc_userping( gpointer _irc ); +static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); GSList *irc_connection_list = NULL; @@ -55,7 +55,7 @@ irc_t *irc_new( int fd ) irc->fd = fd; sock_make_nonblocking( irc->fd ); - irc->r_watch_source_id = gaim_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc ); + irc->r_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc ); irc->status = USTATUS_OFFLINE; irc->last_pong = gettime(); @@ -113,7 +113,7 @@ irc_t *irc_new( int fd ) if( !irc->myhost ) irc->myhost = g_strdup( "localhost." ); if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) - irc->ping_source_id = g_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); + irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" ); @@ -183,8 +183,8 @@ void irc_abort( irc_t *irc, int immed, char *format, ... ) to it that should shut down the connection in a second, just in case bitlbee_.._write doesn't do it first. */ - g_source_remove( irc->r_watch_source_id ); - irc->r_watch_source_id = g_timeout_add_full( G_PRIORITY_HIGH, 1000, (GSourceFunc) irc_free, irc, NULL ); + b_event_remove( irc->r_watch_source_id ); + irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc ); } else { @@ -217,10 +217,10 @@ void irc_free(irc_t * irc) closesocket( irc->fd ); if( irc->ping_source_id > 0 ) - g_source_remove( irc->ping_source_id ); - g_source_remove( irc->r_watch_source_id ); + b_event_remove( irc->ping_source_id ); + b_event_remove( irc->r_watch_source_id ); if( irc->w_watch_source_id > 0 ) - g_source_remove( irc->w_watch_source_id ); + b_event_remove( irc->w_watch_source_id ); irc_connection_list = g_slist_remove( irc_connection_list, irc ); @@ -271,7 +271,7 @@ void irc_free(irc_t * irc) if(user->user!=user->nick) g_free(user->user); if(user->host!=user->nick) g_free(user->host); if(user->realname!=user->nick) g_free(user->realname); - gaim_input_remove(user->sendbuf_timer); + b_event_remove(user->sendbuf_timer); usertmp = user; user = user->next; @@ -321,7 +321,7 @@ void irc_free(irc_t * irc) g_free(irc); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) - g_main_quit( global.loop ); + b_main_quit(); } /* USE WITH CAUTION! @@ -604,7 +604,7 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) } if( irc->w_watch_source_id == 0 ) - irc->w_watch_source_id = gaim_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); + irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); return; } @@ -1010,7 +1010,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) return( 0 ); } -gboolean buddy_send_handler_delayed( gpointer data ) +static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond ) { user_t *u = data; @@ -1023,7 +1023,7 @@ gboolean buddy_send_handler_delayed( gpointer data ) u->sendbuf_timer = 0; u->sendbuf_flags = 0; - return( FALSE ); + return FALSE; } void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) @@ -1037,8 +1037,8 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) if( u->sendbuf_len > 0 && u->sendbuf_flags != flags) { //Flush the buffer - g_source_remove( u->sendbuf_timer ); - buddy_send_handler_delayed( u ); + b_event_remove( u->sendbuf_timer ); + buddy_send_handler_delayed( u, -1, 0 ); } if( u->sendbuf_len == 0 ) @@ -1062,8 +1062,8 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) delay *= 1000; if( u->sendbuf_timer > 0 ) - g_source_remove( u->sendbuf_timer ); - u->sendbuf_timer = g_timeout_add( delay, buddy_send_handler_delayed, u ); + b_event_remove( u->sendbuf_timer ); + u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u ); } else { @@ -1147,7 +1147,7 @@ int irc_noticefrom( irc_t *irc, char *nick, char *msg ) timeout. The number returned is the number of seconds we received no pongs from the user. When not connected yet, we don't ping but drop the connection when the user fails to connect in IRC_LOGIN_TIMEOUT secs. */ -static gboolean irc_userping( gpointer _irc ) +static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ) { irc_t *irc = _irc; int rv = 0; diff --git a/protocols/events.h b/protocols/events.h index 682a9c23..e8ac5a17 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -41,16 +41,20 @@ typedef enum { GAIM_INPUT_READ = 1 << 0, GAIM_INPUT_WRITE = 1 << 1 -} GaimInputCondition; -typedef void (*GaimInputFunction)(gpointer, gint, GaimInputCondition); +} b_input_condition; +typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) -G_MODULE_EXPORT gint gaim_input_add(int fd, GaimInputCondition cond, GaimInputFunction func, gpointer data); -G_MODULE_EXPORT void gaim_input_remove(gint id); +G_MODULE_EXPORT void b_main_init(); +G_MODULE_EXPORT void b_main_run(); +G_MODULE_EXPORT void b_main_quit(); -G_MODULE_EXPORT gint bee_timeout_add(gint timeout, GaimInputFunction func, gpointer data, gint priority); +G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data); +G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data); +G_MODULE_EXPORT void b_event_remove(gint id); +G_MODULE_EXPORT gboolean b_event_remove_by_data(gpointer data); #endif /* _EVENTS_H_ */ diff --git a/protocols/events_glib.c b/protocols/events_glib.c index f3b27565..5a72b13c 100644 --- a/protocols/events_glib.c +++ b/protocols/events_glib.c @@ -46,24 +46,39 @@ #include "proxy.h" typedef struct _GaimIOClosure { - GaimInputFunction function; + b_event_handler function; guint result; gpointer data; } GaimIOClosure; +static GMainLoop *loop; + +void b_main_init() +{ + loop = g_main_new( FALSE ); +} + +void b_main_run() +{ + g_main_run( loop ); +} + +void b_main_quit() +{ + g_main_quit( loop ); +} + static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) { GaimIOClosure *closure = data; - GaimInputCondition gaim_cond = 0; + b_input_condition gaim_cond = 0; if (condition & GAIM_READ_COND) gaim_cond |= GAIM_INPUT_READ; if (condition & GAIM_WRITE_COND) gaim_cond |= GAIM_INPUT_WRITE; - closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); - - return TRUE; + return closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); } static void gaim_io_destroy(gpointer data) @@ -71,7 +86,7 @@ static void gaim_io_destroy(gpointer data) g_free(data); } -gint gaim_input_add(gint source, GaimInputCondition condition, GaimInputFunction function, gpointer data) +gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data) { GaimIOClosure *closure = g_new0(GaimIOClosure, 1); GIOChannel *channel; @@ -93,8 +108,18 @@ gint gaim_input_add(gint source, GaimInputCondition condition, GaimInputFunction return closure->result; } -void gaim_input_remove(gint tag) +gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) +{ + return g_timeout_add(timeout, func, data); +} + +void b_event_remove(gint tag) { if (tag > 0) g_source_remove(tag); } + +gboolean b_event_remove_by_data(gpointer data) +{ + return g_source_remove_by_user_data(data); +} diff --git a/protocols/http_client.c b/protocols/http_client.c index 9417e200..0142bb2e 100644 --- a/protocols/http_client.c +++ b/protocols/http_client.c @@ -31,9 +31,9 @@ #include "sock.h" -static void http_connected( gpointer data, int source, GaimInputCondition cond ); -static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond ); -static void http_incoming_data( gpointer data, int source, GaimInputCondition cond ); +static gboolean http_connected( gpointer data, int source, b_input_condition cond ); +static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ); +static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) @@ -72,7 +72,7 @@ void *http_dorequest( char *host, int port, int ssl, char *request, http_input_f /* This one is actually pretty simple... Might get more calls if we can't write the whole request at once. */ -static void http_connected( gpointer data, int source, GaimInputCondition cond ) +static gboolean http_connected( gpointer data, int source, b_input_condition cond ) { struct http_request *req = data; int st; @@ -81,7 +81,7 @@ static void http_connected( gpointer data, int source, GaimInputCondition cond ) goto error; if( req->inpa > 0 ) - gaim_input_remove( req->inpa ); + b_event_remove( req->inpa ); sock_make_nonblocking( req->fd ); @@ -116,13 +116,13 @@ static void http_connected( gpointer data, int source, GaimInputCondition cond ) req->bytes_written += st; if( req->bytes_written < req->request_length ) - req->inpa = gaim_input_add( source, - req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE, - http_connected, req ); + req->inpa = b_input_add( source, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE, + http_connected, req ); else - req->inpa = gaim_input_add( source, GAIM_INPUT_READ, http_incoming_data, req ); + req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req ); - return; + return FALSE; error: req->func( req ); @@ -130,10 +130,10 @@ error: g_free( req->request ); g_free( req ); - return; + return FALSE; } -static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond ) +static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ) { struct http_request *req = data; @@ -145,7 +145,7 @@ static void http_ssl_connected( gpointer data, void *source, GaimInputCondition return http_connected( data, req->fd, cond ); } -static void http_incoming_data( gpointer data, int source, GaimInputCondition cond ) +static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) { struct http_request *req = data; int evil_server = 0; @@ -154,7 +154,7 @@ static void http_incoming_data( gpointer data, int source, GaimInputCondition co int st; if( req->inpa > 0 ) - gaim_input_remove( req->inpa ); + b_event_remove( req->inpa ); if( req->ssl ) { @@ -201,11 +201,11 @@ static void http_incoming_data( gpointer data, int source, GaimInputCondition co } /* There will be more! */ - req->inpa = gaim_input_add( req->fd, - req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ, - http_incoming_data, req ); + req->inpa = b_input_add( req->fd, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ, + http_incoming_data, req ); - return; + return FALSE; got_reply: /* Zero termination is very convenient. */ @@ -361,7 +361,7 @@ got_reply: req->bytes_read = req->bytes_written = req->inpa = 0; req->reply_headers = req->reply_body = NULL; - return; + return FALSE; } /* Assume that a closed connection means we're finished, this indeed @@ -379,4 +379,6 @@ cleanup: g_free( req->request ); g_free( req->reply_headers ); g_free( req ); + + return FALSE; } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 54eed8a7..c9b7bc6e 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -470,12 +470,14 @@ static void endElement(void *userdata, const char *name) gjc->current = x; } -static void jabber_callback(gpointer data, gint source, GaimInputCondition condition) +static gboolean jabber_callback(gpointer data, gint source, b_input_condition condition) { struct gaim_connection *gc = (struct gaim_connection *)data; struct jabber_data *jd = (struct jabber_data *)gc->proto_data; gjab_recv(jd->gjc); + + return TRUE; } static void charData(void *userdata, const char *s, int slen) @@ -486,7 +488,7 @@ static void charData(void *userdata, const char *s, int slen) xmlnode_insert_cdata(gjc->current, s, slen); } -static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) +static gboolean gjab_connected(gpointer data, gint source, b_input_condition cond) { xmlnode x; char *t, *t2; @@ -496,7 +498,7 @@ static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) if (!g_slist_find(get_connections(), gc)) { closesocket(source); - return; + return FALSE; } jd = gc->proto_data; @@ -507,7 +509,7 @@ static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) if (source == -1) { STATE_EVT(JCONN_STATE_OFF) - return; + return FALSE; } gjc->state = JCONN_STATE_CONNECTED; @@ -529,10 +531,12 @@ static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) STATE_EVT(JCONN_STATE_ON); gc = GJ_GC(gjc); - gc->inpa = gaim_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); + gc->inpa = b_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); + + return FALSE; } -static void gjab_connected_ssl(gpointer data, void *source, GaimInputCondition cond) +static gboolean gjab_connected_ssl(gpointer data, void *source, b_input_condition cond) { struct gaim_connection *gc = data; struct jabber_data *jd; @@ -543,15 +547,15 @@ static void gjab_connected_ssl(gpointer data, void *source, GaimInputCondition c if (source == NULL) { STATE_EVT(JCONN_STATE_OFF) - return; + return FALSE; } if (!g_slist_find(get_connections(), gc)) { ssl_disconnect(source); - return; + return FALSE; } - gjab_connected(data, gjc->fd, cond); + return gjab_connected(data, gjc->fd, cond); } static void gjab_start(gjconn gjc) @@ -1542,7 +1546,7 @@ static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { return TRUE; } -static gboolean jabber_free(gpointer data) +static gboolean jabber_free(gpointer data, gint fd, b_input_condition cond) { struct jabber_data *jd = data; @@ -1585,10 +1589,10 @@ static void jabber_close(struct gaim_connection *gc) } } if (gc->inpa) - gaim_input_remove(gc->inpa); + b_event_remove(gc->inpa); if(jd) { - g_timeout_add(50, jabber_free, jd); + b_timeout_add(50, jabber_free, jd); if(jd->gjc != NULL) xmlnode_free(jd->gjc->current); } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 0cd174f2..dbbb6aa0 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -145,7 +145,7 @@ GSList *msn_connections; GSList *msn_switchboards; /* ns.c */ -void msn_ns_connected( gpointer data, gint source, GaimInputCondition cond ); +gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); /* msn_util.c */ int msn_write( struct gaim_connection *gc, char *s, int len ); @@ -172,4 +172,4 @@ struct msn_switchboard *msn_sb_spare( struct gaim_connection *gc ); int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); void msn_sb_to_chat( struct msn_switchboard *sb ); void msn_sb_destroy( struct msn_switchboard *sb ); -void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond ); +gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 90d525ef..af3793f2 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -29,26 +29,26 @@ #include "passport.h" #include "md5.h" -static void msn_ns_callback( gpointer data, gint source, GaimInputCondition cond ); +static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); static void msn_auth_got_passport_id( struct passport_reply *rep ); -void msn_ns_connected( gpointer data, gint source, GaimInputCondition cond ) +gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { struct gaim_connection *gc = data; struct msn_data *md; char s[1024]; if( !g_slist_find( msn_connections, gc ) ) - return; + return FALSE; if( source == -1 ) { hide_login_progress( gc, "Could not connect to server" ); signoff( gc ); - return; + return FALSE; } md = gc->proto_data; @@ -74,12 +74,14 @@ void msn_ns_connected( gpointer data, gint source, GaimInputCondition cond ) g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId ); if( msn_write( gc, s, strlen( s ) ) ) { - gc->inpa = gaim_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc ); + gc->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc ); set_login_progress( gc, 1, "Connected to server, waiting for reply" ); } + + return FALSE; } -void msn_ns_callback( gpointer data, gint source, GaimInputCondition cond ) +static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ) { struct gaim_connection *gc = data; struct msn_data *md = gc->proto_data; @@ -88,7 +90,11 @@ void msn_ns_callback( gpointer data, gint source, GaimInputCondition cond ) { hide_login_progress( gc, "Error while reading from server" ); signoff( gc ); + + return FALSE; } + else + return TRUE; } static int msn_ns_command( gpointer data, char **cmd, int num_parts ) @@ -129,7 +135,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 ) { - gaim_input_remove( gc->inpa ); + b_event_remove( gc->inpa ); gc->inpa = 0; closesocket( md->fd ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 234be1d6..54e89043 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -29,7 +29,7 @@ #include "passport.h" #include "md5.h" -static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond ); +static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); static int msn_sb_command( gpointer data, char **cmd, int num_parts ); static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); @@ -236,7 +236,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) g_free( sb->handler ); } - if( sb->inp ) gaim_input_remove( sb->inp ); + if( sb->inp ) b_event_remove( sb->inp ); closesocket( sb->fd ); msn_switchboards = g_slist_remove( msn_switchboards, sb ); @@ -244,7 +244,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) g_free( sb ); } -void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond ) +gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; struct gaim_connection *gc; @@ -253,7 +253,7 @@ void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond ) /* Are we still alive? */ if( !g_slist_find( msn_switchboards, sb ) ) - return; + return FALSE; gc = sb->gc; md = gc->proto_data; @@ -262,7 +262,7 @@ void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond ) { debug( "ERROR %d while connecting to switchboard server", 1 ); msn_sb_destroy( sb ); - return; + return FALSE; } /* Prepare the callback */ @@ -279,12 +279,14 @@ void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond ) g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, gc->username, sb->key, sb->session ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) - sb->inp = gaim_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); + sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); else debug( "ERROR %d while connecting to switchboard server", 2 ); + + return FALSE; } -static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond ) +static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; @@ -292,7 +294,11 @@ static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond { debug( "ERROR: Switchboard died" ); msn_sb_destroy( sb ); + + return FALSE; } + else + return TRUE; } static int msn_sb_command( gpointer data, char **cmd, int num_parts ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 4c2a3bb4..c3d810a3 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -327,7 +327,7 @@ void serv_got_crap( struct gaim_connection *gc, char *format, ... ) g_free( text ); } -static gboolean send_keepalive( gpointer d ) +static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) { struct gaim_connection *gc = d; @@ -351,7 +351,7 @@ void account_online( struct gaim_connection *gc ) serv_got_crap( gc, "Logged in" ); - gc->keepalive = g_timeout_add( 60000, send_keepalive, gc ); + gc->keepalive = b_timeout_add( 60000, send_keepalive, gc ); gc->flags |= OPT_LOGGED_IN; /* Also necessary when we're not away, at least for some of the @@ -359,7 +359,7 @@ void account_online( struct gaim_connection *gc ) proto_away( gc, u->away ); } -gboolean auto_reconnect( gpointer data ) +gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) { account_t *a = data; @@ -371,7 +371,7 @@ gboolean auto_reconnect( gpointer data ) void cancel_auto_reconnect( account_t *a ) { - while( g_source_remove_by_user_data( (gpointer) a ) ); + while( b_event_remove_by_data( (gpointer) a ) ); a->reconnect = 0; } @@ -383,10 +383,10 @@ void signoff( struct gaim_connection *gc ) serv_got_crap( gc, "Signing off.." ); - gaim_input_remove( gc->keepalive ); + b_event_remove( gc->keepalive ); gc->keepalive = 0; gc->prpl->close( gc ); - gaim_input_remove( gc->inpa ); + b_event_remove( gc->inpa ); while( u ) { @@ -416,7 +416,7 @@ void signoff( struct gaim_connection *gc ) serv_got_crap( gc, "Reconnecting in %d seconds..", delay ); a->reconnect = 1; - g_timeout_add( delay * 1000, auto_reconnect, a ); + b_timeout_add( delay * 1000, auto_reconnect, a ); } destroy_gaim_conn( gc ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 4251fbaa..3f88a9ef 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -200,7 +200,7 @@ void nogaim_init(); int proto_away( struct gaim_connection *gc, char *away ); char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value ); -gboolean auto_reconnect( gpointer data ); +gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); void cancel_auto_reconnect( struct account *a ); /* multi.c */ diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 53da1e27..ca3210ef 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -252,8 +252,8 @@ static char *msgerrreason[] = { }; static int msgerrreasonlen = 25; -static void oscar_callback(gpointer data, gint source, - GaimInputCondition condition) { +static gboolean oscar_callback(gpointer data, gint source, + b_input_condition condition) { aim_conn_t *conn = (aim_conn_t *)data; aim_session_t *sess = aim_conn_getsess(conn); struct gaim_connection *gc = sess ? sess->aux_data : NULL; @@ -261,13 +261,13 @@ static void oscar_callback(gpointer data, gint source, if (!gc) { /* gc is null. we return, else we seg SIGSEG on next line. */ - return; + return FALSE; } if (!g_slist_find(get_connections(), gc)) { /* oh boy. this is probably bad. i guess the only thing we * can really do is return? */ - return; + return FALSE; } odata = (struct oscar_data *)gc->proto_data; @@ -287,7 +287,7 @@ static void oscar_callback(gpointer data, gint source, char buf[BUF_LONG]; c->conn = NULL; if (c->inpa > 0) - gaim_input_remove(c->inpa); + b_event_remove(c->inpa); c->inpa = 0; c->fd = -1; aim_conn_kill(odata->sess, &conn); @@ -295,7 +295,7 @@ static void oscar_callback(gpointer data, gint source, do_error_dialog(sess->aux_data, buf, _("Chat Error!")); } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { if (odata->cnpa > 0) - gaim_input_remove(odata->cnpa); + b_event_remove(odata->cnpa); odata->cnpa = 0; while (odata->create_rooms) { struct create_room *cr = odata->create_rooms->data; @@ -309,17 +309,22 @@ static void oscar_callback(gpointer data, gint source, aim_conn_kill(odata->sess, &conn); } else if (conn->type == AIM_CONN_TYPE_AUTH) { if (odata->paspa > 0) - gaim_input_remove(odata->paspa); + b_event_remove(odata->paspa); odata->paspa = 0; aim_conn_kill(odata->sess, &conn); } else { aim_conn_kill(odata->sess, &conn); } } + } else { + /* WTF??? */ + return FALSE; } + + return TRUE; } -static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond) +static gboolean oscar_login_connect(gpointer data, gint source, b_input_condition cond) { struct gaim_connection *gc = data; struct oscar_data *odata; @@ -328,7 +333,7 @@ static void oscar_login_connect(gpointer data, gint source, GaimInputCondition c if (!g_slist_find(get_connections(), gc)) { closesocket(source); - return; + return FALSE; } odata = gc->proto_data; @@ -338,12 +343,14 @@ static void oscar_login_connect(gpointer data, gint source, GaimInputCondition c if (source < 0) { hide_login_progress(gc, _("Couldn't connect to host")); signoff(gc); - return; + return FALSE; } aim_conn_completeconnect(sess, conn); - gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, + gc->inpa = b_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn); + + return FALSE; } static void oscar_login(struct aim_user *user) { @@ -411,7 +418,7 @@ static void oscar_close(struct gaim_connection *gc) { while (odata->oscar_chats) { struct chat_connection *n = odata->oscar_chats->data; if (n->inpa > 0) - gaim_input_remove(n->inpa); + b_event_remove(n->inpa); g_free(n->name); g_free(n->show); odata->oscar_chats = g_slist_remove(odata->oscar_chats, n); @@ -430,11 +437,11 @@ static void oscar_close(struct gaim_connection *gc) { if (odata->oldp) g_free(odata->oldp); if (gc->inpa > 0) - gaim_input_remove(gc->inpa); + b_event_remove(gc->inpa); if (odata->cnpa > 0) - gaim_input_remove(odata->cnpa); + b_event_remove(odata->cnpa); if (odata->paspa > 0) - gaim_input_remove(odata->paspa); + b_event_remove(odata->paspa); aim_session_kill(odata->sess); g_free(odata->sess); odata->sess = NULL; @@ -442,7 +449,7 @@ static void oscar_close(struct gaim_connection *gc) { gc->proto_data = NULL; } -static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) { +static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond) { struct gaim_connection *gc = data; struct oscar_data *odata; aim_session_t *sess; @@ -450,7 +457,7 @@ static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition con if (!g_slist_find(get_connections(), gc)) { closesocket(source); - return; + return FALSE; } odata = gc->proto_data; @@ -460,13 +467,15 @@ static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition con if (source < 0) { hide_login_progress(gc, _("Could Not Connect")); signoff(gc); - return; + return FALSE; } aim_conn_completeconnect(sess, bosconn); - gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, + gc->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); set_login_progress(gc, 4, _("Connection established, cookie sent")); + + return FALSE; } static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { @@ -569,7 +578,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { return 0; } aim_sendcookie(sess, bosconn, info->cookie); - gaim_input_remove(gc->inpa); + b_event_remove(gc->inpa); return 1; } @@ -584,7 +593,7 @@ struct pieceofcrap { unsigned int inpa; }; -static void damn_you(gpointer data, gint source, GaimInputCondition c) +static gboolean damn_you(gpointer data, gint source, b_input_condition c) { struct pieceofcrap *pos = data; struct oscar_data *od = pos->gc->proto_data; @@ -604,21 +613,23 @@ static void damn_you(gpointer data, gint source, GaimInputCondition c) if (in != '\n') { do_error_dialog(pos->gc, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly.", "Login Error"); - gaim_input_remove(pos->inpa); + b_event_remove(pos->inpa); closesocket(pos->fd); g_free(pos); - return; + return FALSE; } /* [WvG] Wheeeee! Who needs error checking anyway? ;-) */ read(pos->fd, m, 16); m[16] = '\0'; - gaim_input_remove(pos->inpa); + b_event_remove(pos->inpa); closesocket(pos->fd); aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); g_free(pos); + + return FALSE; } -static void straight_to_hell(gpointer data, gint source, GaimInputCondition cond) { +static gboolean straight_to_hell(gpointer data, gint source, b_input_condition cond) { struct pieceofcrap *pos = data; char buf[BUF_LONG]; @@ -628,7 +639,7 @@ static void straight_to_hell(gpointer data, gint source, GaimInputCondition cond if (pos->modname) g_free(pos->modname); g_free(pos); - return; + return FALSE; } g_snprintf(buf, sizeof(buf), "GET " AIMHASHDATA @@ -637,8 +648,8 @@ static void straight_to_hell(gpointer data, gint source, GaimInputCondition cond write(pos->fd, buf, strlen(buf)); if (pos->modname) g_free(pos->modname); - pos->inpa = gaim_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos); - return; + pos->inpa = b_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos); + return FALSE; } /* size of icbmui.ocm, the largest module in AIM 3.5 */ @@ -760,7 +771,7 @@ static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) { +static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond) { struct gaim_connection *gc = data; struct oscar_data *odata; aim_session_t *sess; @@ -768,7 +779,7 @@ static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition if (!g_slist_find(get_connections(), gc)) { closesocket(source); - return; + return FALSE; } odata = gc->proto_data; @@ -777,15 +788,17 @@ static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition if (source < 0) { aim_conn_kill(sess, &tstconn); - return; + return FALSE; } aim_conn_completeconnect(sess, tstconn); - odata->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, + odata->cnpa = b_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); + + return FALSE; } -static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond) +static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition cond) { struct gaim_connection *gc = data; struct oscar_data *odata; @@ -794,7 +807,7 @@ static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition co if (!g_slist_find(get_connections(), gc)) { closesocket(source); - return; + return FALSE; } odata = gc->proto_data; @@ -803,15 +816,17 @@ static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition co if (source < 0) { aim_conn_kill(sess, &tstconn); - return; + return FALSE; } aim_conn_completeconnect(sess, tstconn); - odata->paspa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, + odata->paspa = b_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); + + return FALSE; } -static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond) +static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition cond) { struct chat_connection *ccon = data; struct gaim_connection *gc = ccon->gc; @@ -824,7 +839,7 @@ static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition co g_free(ccon->show); g_free(ccon->name); g_free(ccon); - return; + return FALSE; } odata = gc->proto_data; @@ -836,14 +851,16 @@ static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition co g_free(ccon->show); g_free(ccon->name); g_free(ccon); - return; + return FALSE; } aim_conn_completeconnect(sess, ccon->conn); - ccon->inpa = gaim_input_add(tstconn->fd, + ccon->inpa = b_input_add(tstconn->fd, GAIM_INPUT_READ, oscar_callback, tstconn); odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); + + return FALSE; } /* Hrmph. I don't know how to make this look better. --mid */ @@ -2557,7 +2574,7 @@ void oscar_chat_kill(struct gaim_connection *gc, struct chat_connection *cc) /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); if (cc->inpa > 0) - gaim_input_remove(cc->inpa); + b_event_remove(cc->inpa); aim_conn_kill(od->sess, &cc->conn); g_free(cc->name); g_free(cc->show); diff --git a/protocols/proxy.c b/protocols/proxy.c index 57d804c6..d6f3a4ca 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -48,7 +48,7 @@ char proxyuser[128] = ""; char proxypass[128] = ""; struct PHB { - GaimInputFunction func, proxy_func; + b_event_handler func, proxy_func; gpointer data, proxy_data; char *host; int port; @@ -77,7 +77,7 @@ static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) return &sin; } -static void gaim_io_connected(gpointer data, gint source, GaimInputCondition cond) +static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond) { struct PHB *phb = data; unsigned int len; @@ -87,24 +87,26 @@ static void gaim_io_connected(gpointer data, gint source, GaimInputCondition con #ifndef _WIN32 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { closesocket(source); - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); if( phb->proxy_func ) phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ); else { phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb); } - return; + return FALSE; } #endif sock_make_blocking(source); - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); if( phb->proxy_func ) phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ); else { phb->func(phb->data, source, GAIM_INPUT_READ); g_free(phb); } + + return FALSE; } static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb) @@ -126,7 +128,7 @@ static int proxy_connect_none(const char *host, unsigned short port, struct PHB if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { if (sockerr_again()) { - phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); + phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); phb->fd = fd; } else { closesocket(fd); @@ -144,14 +146,14 @@ static int proxy_connect_none(const char *host, unsigned short port, struct PHB #define HTTP_GOODSTRING "HTTP/1.0 200 Connection established" #define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established" -static void http_canread(gpointer data, gint source, GaimInputCondition cond) +static gboolean http_canread(gpointer data, gint source, b_input_condition cond) { int nlc = 0; int pos = 0; struct PHB *phb = data; char inputline[8192]; - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { if (inputline[pos - 1] == '\n') @@ -166,31 +168,32 @@ static void http_canread(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, source, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + + return FALSE; } -static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) +static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond) { char cmd[384]; struct PHB *phb = data; unsigned int len; int error = ETIMEDOUT; if (phb->inpa > 0) - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } sock_make_blocking(source); @@ -201,7 +204,7 @@ static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } if (proxyuser && *proxyuser) { @@ -216,7 +219,7 @@ static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } } @@ -226,10 +229,12 @@ static void http_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } - phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb); + phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb); + + return FALSE; } static int proxy_connect_http(const char *host, unsigned short port, struct PHB *phb) @@ -245,28 +250,30 @@ static int proxy_connect_http(const char *host, unsigned short port, struct PHB /* Connecting to SOCKS4 proxies */ -static void s4_canread(gpointer data, gint source, GaimInputCondition cond) +static gboolean s4_canread(gpointer data, gint source, b_input_condition cond) { unsigned char packet[12]; struct PHB *phb = data; - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); memset(packet, 0, sizeof(packet)); if (read(source, packet, 9) >= 4 && packet[1] == 90) { phb->func(phb->data, source, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); + + return FALSE; } -static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond) +static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) { unsigned char packet[12]; struct hostent *hp; @@ -274,14 +281,14 @@ static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond) unsigned int len; int error = ETIMEDOUT; if (phb->inpa > 0) - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } sock_make_blocking(source); @@ -291,7 +298,7 @@ static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } packet[0] = 4; @@ -308,10 +315,12 @@ static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } - phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb); + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb); + + return FALSE; } static int proxy_connect_socks4(const char *host, unsigned short port, struct PHB *phb) @@ -327,32 +336,33 @@ static int proxy_connect_socks4(const char *host, unsigned short port, struct PH /* Connecting to SOCKS5 proxies */ -static void s5_canread_again(gpointer data, gint source, GaimInputCondition cond) +static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond) { unsigned char buf[512]; struct PHB *phb = data; - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); if (read(source, buf, 10) < 10) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } if ((buf[0] != 0x05) || (buf[1] != 0x00)) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } phb->func(phb->data, source, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + + return FALSE; } static void s5_sendconnect(gpointer data, gint source) @@ -360,7 +370,7 @@ static void s5_sendconnect(gpointer data, gint source) unsigned char buf[512]; struct PHB *phb = data; int hlen = strlen(phb->host); - + buf[0] = 0x05; buf[1] = 0x01; /* CONNECT */ buf[2] = 0x00; /* reserved */ @@ -378,22 +388,22 @@ static void s5_sendconnect(gpointer data, gint source) return; } - phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); } -static void s5_readauth(gpointer data, gint source, GaimInputCondition cond) +static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond) { unsigned char buf[512]; struct PHB *phb = data; - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); if (read(source, buf, 2) < 2) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } if ((buf[0] != 0x01) || (buf[1] != 0x00)) { @@ -401,25 +411,27 @@ static void s5_readauth(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } s5_sendconnect(phb, source); + + return FALSE; } -static void s5_canread(gpointer data, gint source, GaimInputCondition cond) +static gboolean s5_canread(gpointer data, gint source, b_input_condition cond) { unsigned char buf[512]; struct PHB *phb = data; - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); if (read(source, buf, 2) < 2) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } if ((buf[0] != 0x05) || (buf[1] == 0xff)) { @@ -427,7 +439,7 @@ static void s5_canread(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } if (buf[1] == 0x02) { @@ -442,16 +454,18 @@ static void s5_canread(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } - phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); } else { s5_sendconnect(phb, source); } + + return FALSE; } -static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond) +static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) { unsigned char buf[512]; int i; @@ -459,14 +473,14 @@ static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond) unsigned int len; int error = ETIMEDOUT; if (phb->inpa > 0) - gaim_input_remove(phb->inpa); + b_event_remove(phb->inpa); len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } sock_make_blocking(source); @@ -488,10 +502,12 @@ static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond) phb->func(phb->data, -1, GAIM_INPUT_READ); g_free(phb->host); g_free(phb); - return; + return FALSE; } - phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb); + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb); + + return FALSE; } static int proxy_connect_socks5(const char *host, unsigned short port, struct PHB *phb) @@ -507,7 +523,7 @@ static int proxy_connect_socks5(const char *host, unsigned short port, struct PH /* Export functions */ -int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data) +int proxy_connect(const char *host, int port, b_event_handler func, gpointer data) { struct PHB *phb; diff --git a/protocols/proxy.h b/protocols/proxy.h index 7094b334..680790a5 100644 --- a/protocols/proxy.h +++ b/protocols/proxy.h @@ -48,6 +48,6 @@ extern int proxytype; extern char proxyuser[128]; extern char proxypass[128]; -G_MODULE_EXPORT int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data); +G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data); #endif /* _PROXY_H_ */ diff --git a/protocols/ssl_bogus.c b/protocols/ssl_bogus.c index 52406b75..00aaa7c4 100644 --- a/protocols/ssl_bogus.c +++ b/protocols/ssl_bogus.c @@ -51,7 +51,7 @@ int ssl_getfd( void *conn ) return( -1 ); } -GaimInputCondition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection( void *conn ) { return GAIM_INPUT_READ; } diff --git a/protocols/ssl_client.h b/protocols/ssl_client.h index 89189db9..1a9c79e9 100644 --- a/protocols/ssl_client.h +++ b/protocols/ssl_client.h @@ -32,11 +32,11 @@ extern int ssl_errno; -typedef void (*ssl_input_function)(gpointer, void*, GaimInputCondition); +typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition); G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); G_MODULE_EXPORT int ssl_getfd( void *conn ); -G_MODULE_EXPORT GaimInputCondition ssl_getdirection( void *conn ); +G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c index f2cb3e08..024dc423 100644 --- a/protocols/ssl_gnutls.c +++ b/protocols/ssl_gnutls.c @@ -47,7 +47,7 @@ struct scd gnutls_certificate_credentials xcred; }; -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); +static void ssl_connected( gpointer data, gint source, b_input_condition cond ); void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) @@ -80,9 +80,9 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return( conn ); } -static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ); +static void ssl_handshake( gpointer data, gint source, b_input_condition cond ); -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) +static void ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; @@ -104,7 +104,7 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) ssl_handshake( data, source, cond ); } -static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) +static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; int st; @@ -203,7 +203,7 @@ int ssl_getfd( void *conn ) return( ((struct scd*)conn)->fd ); } -GaimInputCondition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection( void *conn ) { return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? GAIM_INPUT_WRITE : GAIM_INPUT_READ ); diff --git a/protocols/ssl_nss.c b/protocols/ssl_nss.c index 00d32834..218b3a80 100644 --- a/protocols/ssl_nss.c +++ b/protocols/ssl_nss.c @@ -51,7 +51,7 @@ struct scd gboolean established; }; -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver) @@ -115,7 +115,7 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return( conn ); } -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; @@ -139,7 +139,7 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) conn->established = TRUE; conn->func( conn->data, conn, cond ); - return; + return FALSE; ssl_connected_failure: @@ -148,6 +148,8 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) PR_Close( conn -> prfd ); if( source >= 0 ) closesocket( source ); g_free( conn ); + + return FALSE; } int ssl_read( void *conn, char *buf, int len ) @@ -181,7 +183,7 @@ int ssl_getfd( void *conn ) return( ((struct scd*)conn)->fd ); } -GaimInputCondition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection( void *conn ) { /* Just in case someone calls us, let's return the most likely case: */ return GAIM_INPUT_READ; diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index b79088cc..df4aea2b 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -51,7 +51,7 @@ struct scd SSL_CTX *ssl_ctx; }; -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ); +static void ssl_connected( gpointer data, gint source, b_input_condition cond ); @@ -94,9 +94,9 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return( conn ); } -static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ); +static void ssl_handshake( gpointer data, gint source, b_input_condition cond ); -static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) +static void ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; @@ -110,7 +110,7 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond ) return ssl_handshake( data, source, cond ); } -static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond ) +static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; int st; @@ -220,7 +220,7 @@ int ssl_getfd( void *conn ) return( ((struct scd*)conn)->fd ); } -GaimInputCondition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection( void *conn ) { return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ ); } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index bf1dd1a0..1ce860eb 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -442,7 +442,7 @@ struct byahoo_connect_callback_data int id; }; -void byahoo_connect_callback( gpointer data, gint source, GaimInputCondition cond ) +void byahoo_connect_callback( gpointer data, gint source, b_input_condition cond ) { struct byahoo_connect_callback_data *d = data; @@ -464,7 +464,7 @@ struct byahoo_read_ready_data gpointer data; }; -void byahoo_read_ready_callback( gpointer data, gint source, GaimInputCondition cond ) +gboolean byahoo_read_ready_callback( gpointer data, gint source, b_input_condition cond ) { struct byahoo_read_ready_data *d = data; @@ -472,7 +472,7 @@ void byahoo_read_ready_callback( gpointer data, gint source, GaimInputCondition { /* WTF doesn't libyahoo clean this up? */ ext_yahoo_remove_handler( d->id, d->tag ); - return; + return FALSE; } yahoo_read_ready( d->id, d->fd, d->data ); @@ -486,7 +486,7 @@ struct byahoo_write_ready_data gpointer data; }; -void byahoo_write_ready_callback( gpointer data, gint source, GaimInputCondition cond ) +gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condition cond ) { struct byahoo_write_ready_data *d = data; @@ -494,7 +494,7 @@ void byahoo_write_ready_callback( gpointer data, gint source, GaimInputCondition { /* WTF doesn't libyahoo clean this up? */ ext_yahoo_remove_handler( d->id, d->tag ); - return; + return FALSE; } yahoo_write_ready( d->id, d->fd, d->data ); @@ -685,7 +685,7 @@ int ext_yahoo_add_handler( int id, int fd, yahoo_input_condition cond, void *dat d->data = data; inp->d = d; - d->tag = inp->h = gaim_input_add( fd, GAIM_INPUT_READ, (GaimInputFunction) byahoo_read_ready_callback, (gpointer) d ); + d->tag = inp->h = b_input_add( fd, GAIM_INPUT_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d ); } else if( cond == YAHOO_INPUT_WRITE ) { @@ -696,7 +696,7 @@ int ext_yahoo_add_handler( int id, int fd, yahoo_input_condition cond, void *dat d->data = data; inp->d = d; - d->tag = inp->h = gaim_input_add( fd, GAIM_INPUT_WRITE, (GaimInputFunction) byahoo_write_ready_callback, (gpointer) d ); + d->tag = inp->h = b_input_add( fd, GAIM_INPUT_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d ); } else { @@ -727,7 +727,7 @@ void ext_yahoo_remove_handler( int id, int tag ) l = l->next; } - gaim_input_remove( tag ); + b_event_remove( tag ); } int ext_yahoo_connect_async( int id, char *host, int port, yahoo_connect_callback callback, void *data ) @@ -736,7 +736,7 @@ int ext_yahoo_connect_async( int id, char *host, int port, yahoo_connect_callbac int fd; d = g_new0( struct byahoo_connect_callback_data, 1 ); - if( ( fd = proxy_connect( host, port, (GaimInputFunction) byahoo_connect_callback, (gpointer) d ) ) < 0 ) + if( ( fd = proxy_connect( host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d ) ) < 0 ) { g_free( d ); return( fd ); diff --git a/unix.c b/unix.c index 89bd65bf..360281ee 100644 --- a/unix.c +++ b/unix.c @@ -46,7 +46,7 @@ int main( int argc, char *argv[], char **envp ) memset( &global, 0, sizeof( global_t ) ); - global.loop = g_main_new( FALSE ); + b_main_init(); log_init(); @@ -116,7 +116,7 @@ int main( int argc, char *argv[], char **envp ) if( help_init( &(global.help) ) == NULL ) log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE ); - g_main_run( global.loop ); + b_main_run(); if( global.restart ) { @@ -164,7 +164,7 @@ static void sighandler( int signal ) the user data now (not to mention writing them to disk), so add a timer. */ log_message( LOGLVL_ERROR, "SIGTERM received, cleaning up process." ); - g_timeout_add_full( G_PRIORITY_LOW, 1, (GSourceFunc) bitlbee_shutdown, NULL, NULL ); + b_timeout_add( 1, (b_event_handler) bitlbee_shutdown, NULL ); first = 0; } diff --git a/user.c b/user.c index b795c864..b2c91ccd 100644 --- a/user.c +++ b/user.c @@ -108,7 +108,7 @@ int user_del( irc_t *irc, char *nick ) if( u->away ) g_free( u->away ); if( u->handle ) g_free( u->handle ); if( u->sendbuf ) g_free( u->sendbuf ); - if( u->sendbuf_timer ) g_source_remove( u->sendbuf_timer ); + if( u->sendbuf_timer ) b_event_remove( u->sendbuf_timer ); g_free( u ); if( !g_hash_table_lookup_extended( irc->userhash, key, &okey, &ovalue ) || ovalue != u ) -- cgit v1.2.3 From 13cc96cd2c57a96c16db9f333d594242f6aa36e3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 12 May 2006 20:03:02 +0200 Subject: events_libevent.c --- protocols/Makefile | 2 +- protocols/events_libevent.c | 144 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 protocols/events_libevent.c diff --git a/protocols/Makefile b/protocols/Makefile index 886f010b..aad1ecfe 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = events_glib.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) +objects = events_libevent.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c new file mode 100644 index 00000000..ee25f346 --- /dev/null +++ b/protocols/events_libevent.c @@ -0,0 +1,144 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2006 Wilmer van der Gaast and others * + \********************************************************************/ + +/* + * Event handling (using libevent) + */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include +#include +#include +#include +#include "proxy.h" + +#include +#include + +static guint id_next; +static GHashTable *id_hash; + + +struct b_event_data +{ + guint id; + struct event evinfo; + b_event_handler function; + void *data; +}; + +void b_main_init() +{ + event_init(); + + id_next = 1; + id_hash = g_hash_table_new( g_int_hash, g_int_equal ); +} + +void b_main_run() +{ + event_dispatch(); +} + +void b_main_quit() +{ + struct timeval tv; + + memset( &tv, 0, sizeof( struct timeval ) ); + event_loopexit( &tv ); +} + +static void b_event_passthrough( int fd, short event, void *data ) +{ + struct b_event_data *b_ev = data; + b_input_condition cond = 0; + + if( event & EV_READ ) + cond |= GAIM_INPUT_READ; + if( event & EV_WRITE ) + cond |= GAIM_INPUT_WRITE; + + if( !b_ev->function( b_ev->data, fd, cond ) ) + b_event_remove( b_ev->id ); +} + +gint b_input_add( gint source, b_input_condition condition, b_event_handler function, gpointer data ) +{ + struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); + GIOCondition cond; + + b_ev->id == id_next++; + b_ev->function = function; + b_ev->data = data; + + cond = EV_PERSIST; + if( condition & GAIM_INPUT_READ ) + cond |= EV_READ; + if( condition & GAIM_INPUT_WRITE ) + cond |= EV_WRITE; + + event_set( &b_ev->evinfo, source, cond, b_event_passthrough, b_ev ); + event_add( &b_ev->evinfo, NULL ); + + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); + + return b_ev->id; +} + +gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) +{ + struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); + struct timeval tv; + + b_ev->id == id_next++; + b_ev->function = function; + b_ev->data = data; + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); + evtimer_add( &b_ev->evinfo, &tv); + + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); + + return b_ev->id; +} + +void b_event_remove( gint tag ) +{ + struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &tag ); + + if( b_ev ) + { + event_del( &b_ev->evinfo ); + g_hash_table_remove( id_hash, &tag ); + g_free( b_ev ); + } +} + +gboolean b_event_remove_by_data( gpointer data ) +{ + /* FIXME! */ + return FALSE; +} -- cgit v1.2.3 From 09f8cd1fedff2022da395d8accc9ac71a16215ea Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 12 May 2006 20:31:44 +0200 Subject: Stable, almost finished. --- protocols/events_libevent.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index ee25f346..f892e3eb 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -38,7 +38,6 @@ static guint id_next; static GHashTable *id_hash; - struct b_event_data { guint id; @@ -72,12 +71,15 @@ static void b_event_passthrough( int fd, short event, void *data ) { struct b_event_data *b_ev = data; b_input_condition cond = 0; - - if( event & EV_READ ) - cond |= GAIM_INPUT_READ; - if( event & EV_WRITE ) - cond |= GAIM_INPUT_WRITE; - + + if( fd >= 0 ) + { + if( event & EV_READ ) + cond |= GAIM_INPUT_READ; + if( event & EV_WRITE ) + cond |= GAIM_INPUT_WRITE; + } + if( !b_ev->function( b_ev->data, fd, cond ) ) b_event_remove( b_ev->id ); } @@ -87,7 +89,7 @@ gint b_input_add( gint source, b_input_condition condition, b_event_handler func struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); GIOCondition cond; - b_ev->id == id_next++; + b_ev->id = id_next++; b_ev->function = function; b_ev->data = data; @@ -105,12 +107,13 @@ gint b_input_add( gint source, b_input_condition condition, b_event_handler func return b_ev->id; } +/* TODO: Persistence for timers! */ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) { struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); struct timeval tv; - b_ev->id == id_next++; + b_ev->id = id_next++; b_ev->function = function; b_ev->data = data; @@ -118,7 +121,7 @@ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) tv.tv_usec = ( timeout % 1000 ) * 1000; evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); - evtimer_add( &b_ev->evinfo, &tv); + evtimer_add( &b_ev->evinfo, &tv ); g_hash_table_insert( id_hash, &b_ev->id, b_ev ); @@ -132,7 +135,7 @@ void b_event_remove( gint tag ) if( b_ev ) { event_del( &b_ev->evinfo ); - g_hash_table_remove( id_hash, &tag ); + g_hash_table_remove( id_hash, &b_ev->id ); g_free( b_ev ); } } -- cgit v1.2.3 From b642f38161474516c8e9fda1a9942d45a4ea9f22 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 11:23:49 +0200 Subject: Added some debugging. --- protocols/events_libevent.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index f892e3eb..b9464093 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -80,28 +80,35 @@ static void b_event_passthrough( int fd, short event, void *data ) cond |= GAIM_INPUT_WRITE; } + event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); + if( !b_ev->function( b_ev->data, fd, cond ) ) + { + event_debug( "Handler returned FALSE: " ); b_event_remove( b_ev->id ); + } } -gint b_input_add( gint source, b_input_condition condition, b_event_handler function, gpointer data ) +gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) { struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); - GIOCondition cond; + GIOCondition out_cond; b_ev->id = id_next++; b_ev->function = function; b_ev->data = data; - cond = EV_PERSIST; + out_cond = EV_PERSIST; if( condition & GAIM_INPUT_READ ) - cond |= EV_READ; + out_cond |= EV_READ; if( condition & GAIM_INPUT_WRITE ) - cond |= EV_WRITE; + out_cond |= EV_WRITE; - event_set( &b_ev->evinfo, source, cond, b_event_passthrough, b_ev ); + event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); event_add( &b_ev->evinfo, NULL ); + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d\n", fd, condition, function, data, b_ev->id ); + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); return b_ev->id; @@ -123,25 +130,33 @@ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); evtimer_add( &b_ev->evinfo, &tv ); + event_debug( "b_timeout_add( %d, %d, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); return b_ev->id; } -void b_event_remove( gint tag ) +void b_event_remove( gint id ) { - struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &tag ); + struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id ); + event_debug( "b_event_remove( %d )\n", id ); if( b_ev ) { event_del( &b_ev->evinfo ); g_hash_table_remove( id_hash, &b_ev->id ); g_free( b_ev ); } + else + { + event_debug( "Invalid?\n" ); + } } gboolean b_event_remove_by_data( gpointer data ) { /* FIXME! */ + event_debug( "FALSE!\n" ); return FALSE; } -- cgit v1.2.3 From fc2ee0f84c1746cb17c448ee75c4206dca548325 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 12:29:53 +0200 Subject: It works, it works! \o/ --- protocols/Makefile | 1 + protocols/events.h | 2 ++ protocols/events_glib.c | 21 +++++++++++++++++++-- protocols/events_libevent.c | 9 +++++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/protocols/Makefile b/protocols/Makefile index aad1ecfe..4f61d6e4 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -10,6 +10,7 @@ # [SH] Program variables objects = events_libevent.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) +#objects = events_glib.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into diff --git a/protocols/events.h b/protocols/events.h index e8ac5a17..dcd45abe 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -48,6 +48,8 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) +#define event_debug( x... ) printf( x ) + G_MODULE_EXPORT void b_main_init(); G_MODULE_EXPORT void b_main_run(); G_MODULE_EXPORT void b_main_quit(); diff --git a/protocols/events_glib.c b/protocols/events_glib.c index 5a72b13c..01265fd8 100644 --- a/protocols/events_glib.c +++ b/protocols/events_glib.c @@ -72,17 +72,26 @@ static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpoin { GaimIOClosure *closure = data; b_input_condition gaim_cond = 0; + gboolean st; if (condition & GAIM_READ_COND) gaim_cond |= GAIM_INPUT_READ; if (condition & GAIM_WRITE_COND) gaim_cond |= GAIM_INPUT_WRITE; + + event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data ); - return closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); + st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); + + if( !st ) + event_debug( "Returned FALSE, cancelling.\n" ); + + return st; } static void gaim_io_destroy(gpointer data) { + event_debug( "gaim_io_destroy( 0x%x )\n", data ); g_free(data); } @@ -104,17 +113,25 @@ gint b_input_add(gint source, b_input_condition condition, b_event_handler funct closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, gaim_io_invoke, closure, gaim_io_destroy); + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure ); + g_io_channel_unref(channel); return closure->result; } gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) { - return g_timeout_add(timeout, func, data); + gint st = g_timeout_add(timeout, func, data); + + event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st ); + + return st; } void b_event_remove(gint tag) { + event_debug( "g_source_remove( %d )\n", tag ); + if (tag > 0) g_source_remove(tag); } diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index b9464093..bcfb3b45 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -71,6 +71,7 @@ static void b_event_passthrough( int fd, short event, void *data ) { struct b_event_data *b_ev = data; b_input_condition cond = 0; + int id; if( fd >= 0 ) { @@ -82,10 +83,14 @@ static void b_event_passthrough( int fd, short event, void *data ) event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); + /* Since the called function might cancel this handler already + (which free()s b_ev, we have to remember the ID here. */ + id = b_ev->id; + if( !b_ev->function( b_ev->data, fd, cond ) ) { event_debug( "Handler returned FALSE: " ); - b_event_remove( b_ev->id ); + b_event_remove( id ); } } @@ -150,7 +155,7 @@ void b_event_remove( gint id ) } else { - event_debug( "Invalid?\n" ); + event_debug( "Double remove?\n" ); } } -- cgit v1.2.3 From 2b7d2d1537040cac6841a63437e6c04d8a7441bc Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 12:42:37 +0200 Subject: Fixed GnuTLS support. --- protocols/events.h | 3 ++- protocols/ssl_gnutls.c | 26 +++++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/protocols/events.h b/protocols/events.h index dcd45abe..5b684f8c 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -48,7 +48,8 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) -#define event_debug( x... ) printf( x ) +// #define event_debug( x... ) printf( x ) +#define event_debug( x... ) G_MODULE_EXPORT void b_main_init(); G_MODULE_EXPORT void b_main_run(); diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c index 024dc423..3ebe1756 100644 --- a/protocols/ssl_gnutls.c +++ b/protocols/ssl_gnutls.c @@ -47,7 +47,7 @@ struct scd gnutls_certificate_credentials xcred; }; -static void ssl_connected( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) @@ -80,9 +80,9 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return( conn ); } -static void ssl_handshake( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); -static void ssl_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; @@ -95,32 +95,26 @@ static void ssl_connected( gpointer data, gint source, b_input_condition cond ) g_free( conn ); - return; + return FALSE; } sock_make_nonblocking( conn->fd ); gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); - ssl_handshake( data, source, cond ); + return ssl_handshake( data, source, cond ); } -static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; int st; - if( conn->inpa != -1 ) - { - gaim_input_remove( conn->inpa ); - conn->inpa = -1; - } - if( ( st = gnutls_handshake( conn->session ) ) < 0 ) { if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) { - conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), - ssl_handshake, data ); + conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), + ssl_handshake, data ); } else { @@ -141,6 +135,8 @@ static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) conn->established = TRUE; conn->func( conn->data, conn, cond ); } + + return FALSE; } int ssl_read( void *conn, char *buf, int len ) @@ -186,7 +182,7 @@ void ssl_disconnect( void *conn_ ) struct scd *conn = conn_; if( conn->inpa != -1 ) - gaim_input_remove( conn->inpa ); + b_event_remove( conn->inpa ); if( conn->established ) gnutls_bye( conn->session, GNUTLS_SHUT_WR ); -- cgit v1.2.3 From 309cb9e19395261d020f7ea649807ff1adbe76de Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 16:20:32 +0200 Subject: OpenSSL support. --- protocols/ssl_openssl.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index df4aea2b..54788ec3 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -51,8 +51,7 @@ struct scd SSL_CTX *ssl_ctx; }; -static void ssl_connected( gpointer data, gint source, b_input_condition cond ); - +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) @@ -94,30 +93,30 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return( conn ); } -static void ssl_handshake( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); -static void ssl_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; if( source == -1 ) return ssl_handshake( data, -1, cond ); - /* Make it non-blocking at least during the handshake... */ + /* We can do at least the handshake with non-blocking I/O */ sock_make_nonblocking( conn->fd ); SSL_set_fd( conn->ssl, conn->fd ); return ssl_handshake( data, source, cond ); } -static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) { struct scd *conn = data; int st; if( conn->inpa != -1 ) { - gaim_input_remove( conn->inpa ); + b_event_remove( conn->inpa ); conn->inpa = -1; } @@ -127,14 +126,14 @@ static void ssl_handshake( gpointer data, gint source, b_input_condition cond ) if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) goto ssl_connected_failure; - conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); - return; + conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); + return FALSE; } conn->established = TRUE; sock_make_blocking( conn->fd ); /* For now... */ conn->func( conn->data, conn, cond ); - return; + return FALSE; ssl_connected_failure: conn->func( conn->data, NULL, cond ); @@ -150,6 +149,8 @@ ssl_connected_failure: } if( source >= 0 ) closesocket( source ); g_free( conn ); + + return FALSE; } int ssl_read( void *conn, char *buf, int len ) @@ -203,7 +204,7 @@ void ssl_disconnect( void *conn_ ) struct scd *conn = conn_; if( conn->inpa != -1 ) - gaim_input_remove( conn->inpa ); + b_event_remove( conn->inpa ); if( conn->established ) SSL_shutdown( conn->ssl ); -- cgit v1.2.3 From 782d988a88582a0f3dd6539664d535fb790df024 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 21:01:14 +0200 Subject: libevent code works better with epoll() now in some (pretty common) situations. --- protocols/events.h | 8 ++--- protocols/events_glib.c | 2 +- protocols/events_libevent.c | 78 ++++++++++++++++++++++++++++++++++----------- protocols/ssl_openssl.c | 2 +- 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/protocols/events.h b/protocols/events.h index 5b684f8c..a61dc98c 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -39,8 +39,8 @@ #include typedef enum { - GAIM_INPUT_READ = 1 << 0, - GAIM_INPUT_WRITE = 1 << 1 + GAIM_INPUT_READ = 1 << 1, + GAIM_INPUT_WRITE = 1 << 2 } b_input_condition; typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); @@ -48,8 +48,8 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) -// #define event_debug( x... ) printf( x ) -#define event_debug( x... ) +#define event_debug( x... ) printf( x ) +// #define event_debug( x... ) G_MODULE_EXPORT void b_main_init(); G_MODULE_EXPORT void b_main_run(); diff --git a/protocols/events_glib.c b/protocols/events_glib.c index 01265fd8..ff6e5a74 100644 --- a/protocols/events_glib.c +++ b/protocols/events_glib.c @@ -130,7 +130,7 @@ gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) void b_event_remove(gint tag) { - event_debug( "g_source_remove( %d )\n", tag ); + event_debug( "b_event_remove( %d )\n", tag ); if (tag > 0) g_source_remove(tag); diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index bcfb3b45..d4767348 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -38,6 +38,13 @@ static guint id_next; static GHashTable *id_hash; +/* Since libevent doesn't handle two event handlers for one fd-condition + very well (which happens sometimes when BitlBee changes event handlers + for a combination), let's buid some indexes so we can delete them here + already, just in time. */ +static GHashTable *read_hash; +static GHashTable *write_hash; + struct b_event_data { guint id; @@ -52,6 +59,8 @@ void b_main_init() id_next = 1; id_hash = g_hash_table_new( g_int_hash, g_int_equal ); + read_hash = g_hash_table_new( g_int_hash, g_int_equal ); + write_hash = g_hash_table_new( g_int_hash, g_int_equal ); } void b_main_run() @@ -96,26 +105,49 @@ static void b_event_passthrough( int fd, short event, void *data ) gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) { - struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); - GIOCondition out_cond; - - b_ev->id = id_next++; - b_ev->function = function; - b_ev->data = data; + struct b_event_data *b_ev; - out_cond = EV_PERSIST; - if( condition & GAIM_INPUT_READ ) - out_cond |= EV_READ; - if( condition & GAIM_INPUT_WRITE ) - out_cond |= EV_WRITE; + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); - event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); - event_add( &b_ev->evinfo, NULL ); - - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d\n", fd, condition, function, data, b_ev->id ); + if( ( condition & GAIM_INPUT_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || + ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) + { + /* We'll stick with this libevent entry, but give it a new BitlBee id. */ + g_hash_table_remove( id_hash, &b_ev->id ); + + event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next ); + + b_ev->id = id_next++; + b_ev->function = function; + b_ev->data = data; + } + else + { + GIOCondition out_cond; + + event_debug( "(new) = %d\n", id_next ); + + b_ev = g_new0( struct b_event_data, 1 ); + b_ev->id = id_next++; + b_ev->function = function; + b_ev->data = data; + + out_cond = EV_PERSIST; + if( condition & GAIM_INPUT_READ ) + out_cond |= EV_READ; + if( condition & GAIM_INPUT_WRITE ) + out_cond |= EV_WRITE; + + event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); + event_add( &b_ev->evinfo, NULL ); + + if( out_cond & EV_READ ) + g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev ); + if( out_cond & EV_WRITE ) + g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev ); + } g_hash_table_insert( id_hash, &b_ev->id, b_ev ); - return b_ev->id; } @@ -135,7 +167,7 @@ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); evtimer_add( &b_ev->evinfo, &tv ); - event_debug( "b_timeout_add( %d, %d, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); + event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); g_hash_table_insert( id_hash, &b_ev->id, b_ev ); @@ -149,13 +181,21 @@ void b_event_remove( gint id ) event_debug( "b_event_remove( %d )\n", id ); if( b_ev ) { - event_del( &b_ev->evinfo ); g_hash_table_remove( id_hash, &b_ev->id ); + if( b_ev->evinfo.ev_fd >= 0 ) + { + if( b_ev->evinfo.ev_events & EV_READ ) + g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd ); + if( b_ev->evinfo.ev_events & EV_WRITE ) + g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd ); + } + + event_del( &b_ev->evinfo ); g_free( b_ev ); } else { - event_debug( "Double remove?\n" ); + event_debug( "Already removed?\n" ); } } diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index 54788ec3..5aa0263e 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -114,7 +114,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con struct scd *conn = data; int st; - if( conn->inpa != -1 ) + if( 0 && conn->inpa != -1 ) { b_event_remove( conn->inpa ); conn->inpa = -1; -- cgit v1.2.3 From 19ac9c5c98a8d5adf22bcf5b8e2d4141c82a3275 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 13 May 2006 21:44:59 +0200 Subject: Timeouts are now persistent. --- protocols/events_libevent.c | 11 +++++++++++ protocols/proxy.c | 4 +++- protocols/ssl_openssl.c | 6 ------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index d4767348..6e1ed98e 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -49,6 +49,7 @@ struct b_event_data { guint id; struct event evinfo; + gint timeout; b_event_handler function; void *data; }; @@ -101,6 +102,15 @@ static void b_event_passthrough( int fd, short event, void *data ) event_debug( "Handler returned FALSE: " ); b_event_remove( id ); } + else if( fd == -1 ) + { + struct timeval tv; + + tv.tv_sec = b_ev->timeout / 1000; + tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000; + + evtimer_add( &b_ev->evinfo, &tv ); + } } gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) @@ -158,6 +168,7 @@ gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) struct timeval tv; b_ev->id = id_next++; + b_ev->timeout = timeout; b_ev->function = function; b_ev->data = data; diff --git a/protocols/proxy.c b/protocols/proxy.c index d6f3a4ca..b8aa304d 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -125,7 +125,9 @@ static int proxy_connect_none(const char *host, unsigned short port, struct PHB } sock_make_nonblocking(fd); - + + event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); + if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { if (sockerr_again()) { phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c index 5aa0263e..b6f6c520 100644 --- a/protocols/ssl_openssl.c +++ b/protocols/ssl_openssl.c @@ -114,12 +114,6 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con struct scd *conn = data; int st; - if( 0 && conn->inpa != -1 ) - { - b_event_remove( conn->inpa ); - conn->inpa = -1; - } - if( ( st = SSL_connect( conn->ssl ) ) < 0 ) { conn->lasterr = SSL_get_error( conn->ssl, st ); -- cgit v1.2.3 From 0356ae3aa10bb6556d0ea881988831cad5e71f38 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 00:30:51 +0200 Subject: irc_vawrite() now first attempts to write() immediately (because that's usually not a problem) and only touches the event queue when the write() doesn't write everything. And got rid of a quit element in the irc_t structure that actually wasn't even used. --- irc.c | 12 ++++++++++-- irc.h | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/irc.c b/irc.c index 8112a3e8..6ae0e108 100644 --- a/irc.c +++ b/irc.c @@ -575,7 +575,8 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) int size; char line[IRC_MAX_LINE+1], *cs; - if( irc->quit ) + /* Don't try to write anything new anymore when shutting down. */ + if( irc->status == USTATUS_SHUTDOWN ) return; line[IRC_MAX_LINE] = 0; @@ -604,7 +605,14 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) } if( irc->w_watch_source_id == 0 ) - irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); + { + /* If the buffer is empty we can probably write, so call the write event handler + immediately. If it returns TRUE, it should be called again, so add the event to + the queue. If it's FALSE, we emptied the buffer and saved ourselves some work + in the event queue. */ + if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) + irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); + } return; } diff --git a/irc.h b/irc.h index 394e1d54..fdb016cb 100644 --- a/irc.h +++ b/irc.h @@ -60,7 +60,6 @@ typedef struct irc int pinging; char *sendbuffer; char *readbuffer; - int quit; int sentbytes; time_t oldtime; -- cgit v1.2.3 From 3f199fcf6242fc0cc0e4e767ce2a505792d80fef Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 01:28:31 +0200 Subject: Added a closesocket() that properly removes event handlers before closing a socket. --- protocols/events.h | 4 ++++ protocols/events_libevent.c | 17 +++++++++++++++++ sock.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/protocols/events.h b/protocols/events.h index a61dc98c..37b94aab 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -60,4 +60,8 @@ G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer G_MODULE_EXPORT void b_event_remove(gint id); G_MODULE_EXPORT gboolean b_event_remove_by_data(gpointer data); +#ifdef EVENTS_LIBEVENT +G_MODULE_EXPORT void closesocket(int fd); +#endif + #endif /* _EVENTS_H_ */ diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index 6e1ed98e..ad1864d2 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "proxy.h" @@ -216,3 +217,19 @@ gboolean b_event_remove_by_data( gpointer data ) event_debug( "FALSE!\n" ); return FALSE; } + +void closesocket( int fd ) +{ + struct b_event_data *b_ev; + + /* Since epoll() (the main reason we use libevent) automatically removes sockets from + the epoll() list when a socket gets closed and some modules have a habit of + closing sockets before removing event handlers, our and libevent's administration + get a little bit messed up. So this little function will remove the handlers + properly before closing a socket. */ + + if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) || ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) + b_event_remove( b_ev->id ); + + close( fd ); +} diff --git a/sock.h b/sock.h index 28d31de9..ff7034a6 100644 --- a/sock.h +++ b/sock.h @@ -17,7 +17,9 @@ #define sock_make_nonblocking(fd) fcntl(fd, F_SETFL, O_NONBLOCK) #define sock_make_blocking(fd) fcntl(fd, F_SETFL, 0) #define sockerr_again() (errno == EINPROGRESS || errno == EINTR) +#ifndef EVENTS_LIBEVENT #define closesocket(a) close(a) +#endif #else # include # ifndef _MSC_VER -- cgit v1.2.3 From df70eafa7ae30a18d646d918f959341d5bb047b1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 01:43:21 +0200 Subject: Disabled debugging, everything seems to be fine. --- protocols/events.h | 4 ++-- protocols/events_libevent.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/protocols/events.h b/protocols/events.h index 37b94aab..fc733bec 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -48,8 +48,8 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) -#define event_debug( x... ) printf( x ) -// #define event_debug( x... ) +// #define event_debug( x... ) printf( x ) +#define event_debug( x... ) G_MODULE_EXPORT void b_main_init(); G_MODULE_EXPORT void b_main_run(); diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index ad1864d2..429ca821 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -229,7 +229,10 @@ void closesocket( int fd ) properly before closing a socket. */ if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) || ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) + { + event_debug( "Warning: Had to clean up some event handlers before closing fd %d.\n", fd ); b_event_remove( b_ev->id ); + } close( fd ); } -- cgit v1.2.3 From 919c27cc6f1d7654505ac17e80d1fd7197a233f5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 10:41:05 +0200 Subject: Fixed a little memory access bug. --- bitlbee.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index e52830be..748b7bba 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -33,7 +33,7 @@ #include #include -static gboolean bitlbee_io_new_client( gpointer data, gint source, b_input_condition condition ); +static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ); int bitlbee_daemon_init() { @@ -144,7 +144,7 @@ int bitlbee_inetd_init() return( 0 ); } -gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_condition cond ) +gboolean bitlbee_io_current_client_read( gpointer data, gint fd, b_input_condition cond ) { irc_t *irc = data; char line[513]; @@ -185,7 +185,7 @@ gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_con /* Normally, irc_process() shouldn't call irc_free() but irc_abort(). Just in case: */ if( !g_slist_find( irc_connection_list, irc ) ) { - log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", irc->fd ); + log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", fd ); return FALSE; } @@ -199,7 +199,7 @@ gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_con return TRUE; } -gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ) +gboolean bitlbee_io_current_client_write( gpointer data, gint fd, b_input_condition cond ) { irc_t *irc = data; int st, size; @@ -242,7 +242,7 @@ gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_co } } -static gboolean bitlbee_io_new_client( gpointer data, gint source, b_input_condition condition ) +static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ) { socklen_t size = sizeof( struct sockaddr_in ); struct sockaddr_in conn_info; -- cgit v1.2.3 From 5330e3d7fdb323ee4176b36639b59f6f90c22617 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 11:05:41 +0200 Subject: Oops, closesocket() didn't handle sockets with both a read- and a write-handler very well yet. --- protocols/events_libevent.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index 429ca821..67f973b9 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -228,9 +228,14 @@ void closesocket( int fd ) get a little bit messed up. So this little function will remove the handlers properly before closing a socket. */ - if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) || ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) + if( b_ev = g_hash_table_lookup( read_hash, &fd ) ) { - event_debug( "Warning: Had to clean up some event handlers before closing fd %d.\n", fd ); + event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); + b_event_remove( b_ev->id ); + } + if( b_ev = g_hash_table_lookup( write_hash, &fd ) ) + { + event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); b_event_remove( b_ev->id ); } -- cgit v1.2.3 From 85cf37ff0121898d01e9830e237f41f3ddd7dfaa Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 14 May 2006 12:32:21 +0200 Subject: Added --events= flag to configure. --- configure | 45 +++++++++++++++++++++++++++++++++++++-------- protocols/Makefile | 3 +-- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/configure b/configure index a602fe3a..68baaa7e 100755 --- a/configure +++ b/configure @@ -13,11 +13,12 @@ etcdir='$prefix/etc/bitlbee/' mandir='$prefix/share/man/' datadir='$prefix/share/bitlbee/' config='/var/lib/bitlbee/' +plugindir='$prefix/lib/bitlbee/' +includedir='$prefix/include/bitlbee/' +libevent='/usr/' pidfile='/var/run/bitlbee.pid' ipcsocket='/var/run/bitlbee' -plugindir='$prefix/lib/bitlbee' pcdir='$prefix/lib/pkgconfig' -includedir='$prefix/include/bitlbee' msn=1 jabber=1 @@ -27,6 +28,8 @@ yahoo=1 debug=0 strip=1 ipv6=1 + +events=glib ssl=auto arch=`uname -s` @@ -63,6 +66,7 @@ Option Description Default --ipv6=0/1 IPv6 socket support $ipv6 +--events=... Event handler (glib, libevent) $events --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl EOF @@ -79,9 +83,11 @@ mandir=`eval echo "$mandir/" | sed 's/\/\{1,\}/\//g'` datadir=`eval echo "$datadir/" | sed 's/\/\{1,\}/\//g'` config=`eval echo "$config/" | sed 's/\/\{1,\}/\//g'` plugindir=`eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g'` +includedir=`eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g'` +libevent=`eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g'` + pidfile=`eval echo "$pidfile" | sed 's/\/\{1,\}/\//g'` ipcsocket=`eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g'` -includedir=`eval echo "$includedir" | sed 's/\/\{1,\}/\//g'` pcdir=`eval echo "$pcdir" | sed 's/\/\{1,\}/\//g'` cat<Makefile.settings @@ -182,12 +188,36 @@ fi if [ -r /usr/include/iconv.h ]; then :; elif [ -r /usr/local/include/iconv.h ]; then - echo CFLAGS+=-I/usr/local/include >> Makefile.settings; + echo CFLAGS+=-I/usr/local/include >> Makefile.settings else echo echo 'Warning: Could not find iconv.h, you might have to install it and/or modify' - echo 'Makefile.settings to tell where this file is.'; + echo 'Makefile.settings to tell where this file is.' +fi + + +if [ "$events" = "libevent" ]; then + if ! [ -e "${libevent}include/event.h" ]; then + echo + echo 'Warning: Could not find event.h, you might have to install it and/or specify' + echo 'its location using the --libevent= argument. (Example: If event.h is in' + echo '/usr/local/include and binaries are in /usr/local/lib: --libevent=/usr/local)' + fi + + echo '#define EVENTS_LIBEVENT' >> config.h + cat <>Makefile.settings +EFLAGS+=-levent -L${libevent}lib +CFLAGS+=-I${libevent}include +EOF +elif [ "$events" = "glib" ]; then + ## We already use glib anyway, so this is all we need (and in fact not even this, but just to be sure...): + echo '#define EVENTS_GLIB' >> config.h +else + echo + echo 'ERROR: Unknown event handler specified.' + exit 1 fi +echo 'EVENT_HANDLER=events_'$events'.o' >> Makefile.settings detect_gnutls() @@ -421,9 +451,8 @@ else echo ' Binary stripping disabled.'; fi -if [ "$msn" = "1" ]; then - echo ' Using SSL library: '$ssl; -fi +echo ' Using event handler: '$events; +echo ' Using SSL library: '$ssl; #if [ "$flood" = "0" ]; then # echo ' Flood protection disabled.'; diff --git a/protocols/Makefile b/protocols/Makefile index 4f61d6e4..b74212f4 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -9,8 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = events_libevent.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) -#objects = events_glib.o http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) +objects = $(EVENT_HANDLER) http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into -- cgit v1.2.3 From b8b8c6c65ce89f676d269a1897e3a938895cabde Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 15 May 2006 11:19:46 +0200 Subject: Shutting up annoying compilers. --- protocols/events_libevent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index 67f973b9..f878f093 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -228,12 +228,12 @@ void closesocket( int fd ) get a little bit messed up. So this little function will remove the handlers properly before closing a socket. */ - if( b_ev = g_hash_table_lookup( read_hash, &fd ) ) + if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) { event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); b_event_remove( b_ev->id ); } - if( b_ev = g_hash_table_lookup( write_hash, &fd ) ) + if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) { event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); b_event_remove( b_ev->id ); -- cgit v1.2.3 From 7a685f15d0e5774467a8721eb97d059726ce792b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 15 May 2006 11:26:54 +0200 Subject: Added correct return values for callbacks in yahoo.c. --- protocols/yahoo/yahoo.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 1ce860eb..fba5dfb8 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -469,13 +469,12 @@ gboolean byahoo_read_ready_callback( gpointer data, gint source, b_input_conditi struct byahoo_read_ready_data *d = data; if( !byahoo_get_gc_by_id( d->id ) ) - { /* WTF doesn't libyahoo clean this up? */ - ext_yahoo_remove_handler( d->id, d->tag ); return FALSE; - } yahoo_read_ready( d->id, d->fd, d->data ); + + return TRUE; } struct byahoo_write_ready_data @@ -491,13 +490,12 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit struct byahoo_write_ready_data *d = data; if( !byahoo_get_gc_by_id( d->id ) ) - { /* WTF doesn't libyahoo clean this up? */ - ext_yahoo_remove_handler( d->id, d->tag ); return FALSE; - } yahoo_write_ready( d->id, d->fd, d->data ); + + return FALSE; } void ext_yahoo_login_response( int id, int succ, char *url ) -- cgit v1.2.3 From c98be000bb619dd597194b3a50a06f9717649f80 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 15 May 2006 11:52:01 +0200 Subject: No more need for remove_by_user_data, hope the auto-reconnect code isn't too unreliable anymore. --- protocols/nogaim.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c3d810a3..06b629a5 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -247,7 +247,7 @@ struct gaim_connection *new_gaim_conn( struct aim_user *user ) /* [MD] BUGFIX: don't set gc->irc to the global IRC, but use the one from the struct aim_user. * This fixes daemon mode breakage where IRC doesn't point to the currently active connection. */ - gc->irc=user->irc; + gc->irc = user->irc; connections = g_slist_append( connections, gc ); @@ -371,7 +371,8 @@ gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) void cancel_auto_reconnect( account_t *a ) { - while( b_event_remove_by_data( (gpointer) a ) ); + /* while( b_event_remove_by_data( (gpointer) a ) ); */ + b_event_remove( a->reconnect ); a->reconnect = 0; } @@ -413,10 +414,9 @@ void signoff( struct gaim_connection *gc ) else if( !gc->wants_to_die && set_getint( irc, "auto_reconnect" ) ) { int delay = set_getint( irc, "auto_reconnect_delay" ); - serv_got_crap( gc, "Reconnecting in %d seconds..", delay ); - a->reconnect = 1; - b_timeout_add( delay * 1000, auto_reconnect, a ); + serv_got_crap( gc, "Reconnecting in %d seconds..", delay ); + a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); } destroy_gaim_conn( gc ); -- cgit v1.2.3 From af9980f76b1f79aab90addc0228417093993e96b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 15 May 2006 11:57:04 +0200 Subject: Removed g_event_remove_by_data(). --- protocols/events.h | 1 - protocols/events_glib.c | 5 ----- protocols/events_libevent.c | 7 ------- 3 files changed, 13 deletions(-) diff --git a/protocols/events.h b/protocols/events.h index fc733bec..781fca6a 100644 --- a/protocols/events.h +++ b/protocols/events.h @@ -58,7 +58,6 @@ G_MODULE_EXPORT void b_main_quit(); G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data); G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data); G_MODULE_EXPORT void b_event_remove(gint id); -G_MODULE_EXPORT gboolean b_event_remove_by_data(gpointer data); #ifdef EVENTS_LIBEVENT G_MODULE_EXPORT void closesocket(int fd); diff --git a/protocols/events_glib.c b/protocols/events_glib.c index ff6e5a74..620720cd 100644 --- a/protocols/events_glib.c +++ b/protocols/events_glib.c @@ -135,8 +135,3 @@ void b_event_remove(gint tag) if (tag > 0) g_source_remove(tag); } - -gboolean b_event_remove_by_data(gpointer data) -{ - return g_source_remove_by_user_data(data); -} diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index f878f093..3328f68b 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -211,13 +211,6 @@ void b_event_remove( gint id ) } } -gboolean b_event_remove_by_data( gpointer data ) -{ - /* FIXME! */ - event_debug( "FALSE!\n" ); - return FALSE; -} - void closesocket( int fd ) { struct b_event_data *b_ev; -- cgit v1.2.3 From 574af7e01a0cc738b4bbe7e903572943a85b9691 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 26 May 2006 01:20:54 +0200 Subject: Require GLib 2 --- configure | 35 +++++------------------------------ doc/README | 2 +- irc.c | 4 ---- util.c | 26 +++++++++----------------- 4 files changed, 15 insertions(+), 52 deletions(-) diff --git a/configure b/configure index 63047303..ac7ff3b6 100755 --- a/configure +++ b/configure @@ -162,38 +162,16 @@ if [ -z "$PKG_CONFIG" ]; then PKG_CONFIG=pkg-config fi -GLIB=0 - if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG glib-2.0; then cat<>Makefile.settings EFLAGS+=`$PKG_CONFIG --libs glib-2.0 gmodule-2.0` CFLAGS+=`$PKG_CONFIG --cflags glib-2.0 gmodule-2.0` EOF - echo '#define GLIB2' >> config.h - GLIB=2 -elif type glib-config > /dev/null 2> /dev/null; then - cat<>Makefile.settings -EFLAGS+=`glib-config --libs` -CFLAGS+=`glib-config --cflags` -EOF - echo '#define GLIB1' >> config.h - GLIB=1 else - echo 'Cannot find glib development libraries, aborting. (Install libglib-dev?)' + echo 'Cannot find glib2 development libraries, aborting. (Install libglib2-dev?)' exit 1; fi -if [ GLIB = 1 -o -r /usr/include/iconv.h ]; then - :; -elif [ -r /usr/local/include/iconv.h ]; then - echo CFLAGS+=-I/usr/local/include >> Makefile.settings; -else - echo - echo 'Warning: Could not find iconv.h, you might have to install it and/or modify' - echo 'Makefile.settings to tell where this file is.'; -fi - - detect_gnutls() { if libgnutls-config --version > /dev/null 2> /dev/null; then @@ -389,18 +367,15 @@ Linux ) GNU/* ) ;; *BSD ) - echo 'EFLAGS+=-liconv' >> Makefile.settings; -;; -SunOS ) - echo 'EFLAGS+=-lresolv -lnsl -lsocket' >> Makefile.settings - echo 'STRIP=\# skip strip' >> Makefile.settings - echo 'EFLAGS+=-liconv' >> Makefile.settings; ;; Darwin ) - echo 'EFLAGS+=-liconv' >> Makefile.settings; ;; IRIX ) ;; +SunOS ) + echo 'EFLAGS+=-lresolv -lnsl -lsocket' >> Makefile.settings + echo 'STRIP=\# skip strip' >> Makefile.settings +;; CYGWIN* ) echo 'Cygwin is not officially supported.' ;; diff --git a/doc/README b/doc/README index 12c21c51..c82c9aeb 100644 --- a/doc/README +++ b/doc/README @@ -46,7 +46,7 @@ DEPENDENCIES ============ BitlBee's only real dependency is GLib. This is available on virtually every -platform. Any recent version of GLib (including 1.x versions) will work. +platform. Any recent version of GLib (2.0 or higher) will work. These days, MSN Messenger clients have to connect to the MS Passport servers through HTTPS. BitlBee can use several SSL libraries for this: GnuTLS, NSS diff --git a/irc.c b/irc.c index fb85de62..db9f7aad 100644 --- a/irc.c +++ b/irc.c @@ -54,13 +54,9 @@ irc_t *irc_new( int fd ) irc->fd = fd; irc->io_channel = g_io_channel_unix_new( fd ); -#ifdef GLIB2 g_io_channel_set_encoding (irc->io_channel, NULL, NULL); g_io_channel_set_buffered (irc->io_channel, FALSE); g_io_channel_set_flags( irc->io_channel, G_IO_FLAG_NONBLOCK, NULL ); -#else - fcntl( irc->fd, F_SETFL, O_NONBLOCK); -#endif irc->r_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, bitlbee_io_current_client_read, irc ); irc->status = USTATUS_OFFLINE; diff --git a/util.c b/util.c index 8f8ec7b3..dfa0906b 100644 --- a/util.c +++ b/util.c @@ -38,14 +38,6 @@ #include #include #include -#ifdef GLIB2 -#define iconv_t GIConv -#define iconv_open g_iconv_open -#define iconv_close g_iconv_close -#define iconv g_iconv -#else -#include -#endif void strip_linefeed(gchar *text) { @@ -464,21 +456,21 @@ char *ipv6_unwrap( char *src ) */ signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ) { - iconv_t cd; + GIConv cd; size_t res; size_t inbytesleft, outbytesleft; char *inbuf = src; char *outbuf = dst; - cd = iconv_open( to_cs, from_cs ); - if( cd == (iconv_t) -1 ) + cd = g_iconv_open( to_cs, from_cs ); + if( cd == (GIConv) -1 ) return( -1 ); inbytesleft = size ? size : strlen( src ); outbytesleft = maxbuf - 1; - res = iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); *outbuf = '\0'; - iconv_close( cd ); + g_iconv_close( cd ); if( res == (size_t) -1 ) return( -1 ); @@ -488,15 +480,15 @@ signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t si char *set_eval_charset( irc_t *irc, set_t *set, char *value ) { - iconv_t cd; + GIConv cd; if ( g_strncasecmp( value, "none", 4 ) == 0 ) return( value ); - cd = iconv_open( "UTF-8", value ); - if( cd == (iconv_t) -1 ) + cd = g_iconv_open( "UTF-8", value ); + if( cd == (GIConv) -1 ) return( NULL ); - iconv_close( cd ); + g_iconv_close( cd ); return( value ); } -- cgit v1.2.3 From 7deb4471891059edf6000ffc7502a2a7bdc70e78 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 26 May 2006 20:32:50 +0200 Subject: Added status_string variable to http_client. --- protocols/http_client.c | 44 +++++++++++++++++++++++++++++++++++++++++++- protocols/http_client.h | 1 + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/protocols/http_client.c b/protocols/http_client.c index e181438c..88aadff3 100644 --- a/protocols/http_client.c +++ b/protocols/http_client.c @@ -156,6 +156,8 @@ static void http_connected( gpointer data, int source, GaimInputCondition cond ) return; error: + req->status_string = g_strdup( "Error while writing HTTP request" ); + req->func( req ); g_free( req->request ); @@ -215,6 +217,7 @@ static void http_incoming_data( gpointer data, int source, GaimInputCondition co { if( !sockerr_again() ) { + req->status_string = g_strdup( strerror( errno ) ); goto cleanup; } } @@ -242,7 +245,10 @@ got_reply: /* Maybe if the webserver is overloaded, or when there's bad SSL support... */ if( req->bytes_read == 0 ) + { + req->status_string = g_strdup( "Empty HTTP reply" ); goto cleanup; + } /* Zero termination is very convenient. */ req->reply_headers[req->bytes_read] = 0; @@ -263,6 +269,7 @@ got_reply: } else { + req->status_string = g_strdup( "Malformed HTTP reply" ); goto cleanup; } @@ -278,10 +285,31 @@ got_reply: if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) { if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 ) + { + req->status_string = g_strdup( "Can't parse status code" ); req->status_code = -1; + } + else + { + char *eol; + + if( evil_server ) + eol = strchr( end1, '\n' ); + else + eol = strchr( end1, '\r' ); + + req->status_string = g_strndup( end1 + 1, eol - end1 - 1 ); + + /* Just to be sure... */ + if( ( eol = strchr( req->status_string, '\r' ) ) ) + *eol = 0; + if( ( eol = strchr( req->status_string, '\n' ) ) ) + *eol = 0; + } } else { + req->status_string = g_strdup( "Can't locate status code" ); req->status_code = -1; } @@ -290,9 +318,16 @@ got_reply: char *loc, *new_request, *new_host; int error = 0, new_port, new_proto; + /* We might fill it again, so let's not leak any memory. */ + g_free( req->status_string ); + req->status_string = NULL; + loc = strstr( req->reply_headers, "\nLocation: " ); if( loc == NULL ) /* We can't handle this redirect... */ + { + req->status_string = g_strdup( "Can't locate Location: header" ); goto cleanup; + } loc += 11; while( *loc == ' ' ) @@ -309,6 +344,8 @@ got_reply: /* Since we don't cache the servername, and since we don't need this yet anyway, I won't implement it. */ + req->status_string = g_strdup( "Can't handle recursive redirects" ); + goto cleanup; } else @@ -326,6 +363,7 @@ got_reply: if( !url_set( url, loc ) ) { + req->status_string = g_strdup( "Malformed redirect URL" ); g_free( url ); goto cleanup; } @@ -340,6 +378,7 @@ got_reply: s = strchr( req->request, ' ' ); if( s == NULL ) { + req->status_string = g_strdup( "Error while rebuilding request string" ); g_free( new_request ); g_free( url ); goto cleanup; @@ -352,6 +391,7 @@ got_reply: s = strstr( req->request, "\r\n" ); if( s == NULL ) { + req->status_string = g_strdup( "Error while rebuilding request string" ); g_free( new_request ); g_free( url ); goto cleanup; @@ -371,7 +411,7 @@ got_reply: closesocket( req->fd ); req->fd = -1; - req->ssl = 0; + req->ssl = NULL; if( new_proto == PROTO_HTTPS ) { @@ -389,6 +429,7 @@ got_reply: if( error ) { + req->status_string = g_strdup( "Connection problem during redirect" ); g_free( new_request ); goto cleanup; } @@ -417,5 +458,6 @@ cleanup: g_free( req->request ); g_free( req->reply_headers ); + g_free( req->status_string ); g_free( req ); } diff --git a/protocols/http_client.h b/protocols/http_client.h index 860cdd86..50ee80cf 100644 --- a/protocols/http_client.h +++ b/protocols/http_client.h @@ -36,6 +36,7 @@ struct http_request char *request; int request_length; int status_code; + char *status_string; char *reply_headers; char *reply_body; int body_size; -- cgit v1.2.3 From fe237200e4b3921e190d13693402e14d63fe2fa4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 26 May 2006 20:35:16 +0200 Subject: Always use GET-requests on redirects. --- protocols/http_client.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/protocols/http_client.c b/protocols/http_client.c index 88aadff3..c793d9d4 100644 --- a/protocols/http_client.c +++ b/protocols/http_client.c @@ -374,19 +374,7 @@ got_reply: /* So, now I just allocated enough memory, so I'm going to use strcat(), whether you like it or not. :-) */ - /* First, find the GET/POST/whatever from the original request. */ - s = strchr( req->request, ' ' ); - if( s == NULL ) - { - req->status_string = g_strdup( "Error while rebuilding request string" ); - g_free( new_request ); - g_free( url ); - goto cleanup; - } - - *s = 0; - sprintf( new_request, "%s %s HTTP/1.0\r\n", req->request, url->file ); - *s = ' '; + sprintf( new_request, "GET %s HTTP/1.0", url->file ); s = strstr( req->request, "\r\n" ); if( s == NULL ) @@ -397,7 +385,7 @@ got_reply: goto cleanup; } - strcat( new_request, s + 2 ); + strcat( new_request, s ); new_host = g_strdup( url->host ); new_port = url->port; new_proto = url->proto; -- cgit v1.2.3 From a2582c84bda1ed8940c75bd842f9296cef3f50d4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 27 May 2006 00:44:48 +0200 Subject: Added error_string variable to Passport client. --- protocols/msn/ns.c | 9 ++++++++- protocols/msn/passport.c | 29 ++++++++++++++++++++++++----- protocols/msn/passport.h | 1 + 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 90d525ef..523de0ae 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -649,8 +649,15 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) if( key == NULL ) { - hide_login_progress( gc, "Error during Passport authentication" ); + char *err; + + err = g_strdup_printf( "Error during Passport authentication (%s)", + rep->error_string ? rep->error_string : "Unknown error" ); + + hide_login_progress( gc, err ); signoff( gc ); + + g_free( err ); } else { diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 34703432..5ef4fa18 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -68,8 +68,7 @@ static int passport_get_id_real( gpointer func, gpointer data, char *header ) return( 0 ); } - reqs = g_malloc( strlen( header ) + strlen( dummy ) + 128 ); - sprintf( reqs, "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); + reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); *dummy = 0; req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep ); @@ -87,13 +86,13 @@ static void passport_get_id_ready( struct http_request *req ) { struct passport_reply *rep = req->data; - if( !g_slist_find( msn_connections, rep->data ) || !req->finished || !req->reply_headers ) + if( !g_slist_find( msn_connections, rep->data ) ) { destroy_reply( rep ); return; } - if( req->status_code == 200 ) + if( req->finished && req->reply_headers && req->status_code == 200 ) { char *dummy; @@ -108,6 +107,15 @@ static void passport_get_id_ready( struct http_request *req ) rep->result = g_strdup( dummy ); } + else + { + rep->error_string = g_strdup( "Could not parse Passport server response" ); + } + } + else + { + rep->error_string = g_strdup_printf( "HTTP error: %s", + req->status_string ? req->status_string : "Unknown error" ); } rep->func( rep ); @@ -168,16 +176,26 @@ static void passport_retrieve_dalogin_ready( struct http_request *req ) char *dalogin; char *urlend; - if( !g_slist_find( msn_connections, rep->data ) || !req->finished || !req->reply_headers ) + if( !g_slist_find( msn_connections, rep->data ) ) { destroy_reply( rep ); return; } + if( !req->finished || !req->reply_headers || req->status_code != 200 ) + { + rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin (%s)", + req->status_string ? req->status_string : "Unknown error" ); + goto failure; + } + dalogin = strstr( req->reply_headers, "DALogin=" ); if( !dalogin ) + { + rep->error_string = g_strdup( "Parse error while fetching DALogin" ); goto failure; + } dalogin += strlen( "DALogin=" ); urlend = strchr( dalogin, ',' ); @@ -207,5 +225,6 @@ static void destroy_reply( struct passport_reply *rep ) { g_free( rep->result ); g_free( rep->header ); + g_free( rep->error_string ); g_free( rep ); } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index f7e6ebb6..9fd81a82 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -38,6 +38,7 @@ struct passport_reply void *data; char *result; char *header; + char *error_string; }; int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ); -- cgit v1.2.3 From db28304aed1fbe47f0a4076f3c97850059f262e6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 27 May 2006 00:49:28 +0200 Subject: Using http_dorequest_url() at one place in passport.c now. --- protocols/msn/passport.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 5ef4fa18..dd1d9b6f 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -152,7 +152,6 @@ static char *passport_create_header( char *cookie, char *email, char *pwd ) return( buffer ); } -#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n" static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) { struct passport_reply *rep = g_new0( struct passport_reply, 1 ); @@ -162,7 +161,7 @@ static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header rep->func = func; rep->header = header; - req = http_dorequest( "nexus.passport.com", 443, 1, PPR_REQUEST, passport_retrieve_dalogin_ready, rep ); + req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep ); if( !req ) destroy_reply( rep ); @@ -184,7 +183,7 @@ static void passport_retrieve_dalogin_ready( struct http_request *req ) if( !req->finished || !req->reply_headers || req->status_code != 200 ) { - rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin (%s)", + rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s", req->status_string ? req->status_string : "Unknown error" ); goto failure; } -- cgit v1.2.3 From cdca30b360c09399f1e5a2556d83ec997006cd75 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 27 May 2006 17:33:58 +0200 Subject: Making sure that event handlers don't get called anymore after a call to b_main_quit(). --- protocols/events_libevent.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c index 3328f68b..1119c2ab 100644 --- a/protocols/events_libevent.c +++ b/protocols/events_libevent.c @@ -38,6 +38,7 @@ static guint id_next; static GHashTable *id_hash; +static int quitting = 0; /* Since libevent doesn't handle two event handlers for one fd-condition very well (which happens sometimes when BitlBee changes event handlers @@ -74,6 +75,10 @@ void b_main_quit() { struct timeval tv; + /* libevent sometimes generates events before really quitting, + we want to stop them. */ + quitting = 1; + memset( &tv, 0, sizeof( struct timeval ) ); event_loopexit( &tv ); } @@ -98,6 +103,12 @@ static void b_event_passthrough( int fd, short event, void *data ) (which free()s b_ev, we have to remember the ID here. */ id = b_ev->id; + if( quitting ) + { + b_event_remove( id ); + return; + } + if( !b_ev->function( b_ev->data, fd, cond ) ) { event_debug( "Handler returned FALSE: " ); -- cgit v1.2.3 From 42616d147d9b6bfb5d09ea6dc237605917765853 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 28 May 2006 20:24:43 +0200 Subject: "ISON :nick1 nick2" works too now, which seems to be what the RFCs really want (although the example says "ISON nick1 nick2"). --- irc_commands.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/irc_commands.c b/irc_commands.c index fe67a534..f80f50f5 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -320,7 +320,7 @@ static void irc_cmd_userhost( irc_t *irc, char **cmd ) static void irc_cmd_ison( irc_t *irc, char **cmd ) { user_t *u; - char buff[IRC_MAX_LINE]; + char buff[IRC_MAX_LINE], *s; int lenleft, i; buff[0] = '\0'; @@ -330,28 +330,41 @@ static void irc_cmd_ison( irc_t *irc, char **cmd ) for( i = 1; cmd[i]; i ++ ) { - if( ( u = user_find( irc, cmd[i] ) ) && u->online ) + char *this, *next; + + this = cmd[i]; + while( *this ) { - /* [SH] Make sure we don't use too much buffer space. */ - lenleft -= strlen( u->nick ) + 1; + if( ( next = strchr( this, ' ' ) ) ) + *next = 0; - if( lenleft < 0 ) + if( ( u = user_find( irc, this ) ) && u->online ) { - break; + lenleft -= strlen( u->nick ) + 1; + + if( lenleft < 0 ) + break; + + strcat( buff, u->nick ); + strcat( buff, " " ); } - /* [SH] Add the nick to the buffer. Note - * that an extra space is always added. Even - * if it's the last nick in the list. Who - * cares? - */ - - strcat( buff, u->nick ); - strcat( buff, " " ); + if( next ) + { + *next = ' '; + this = next + 1; + } + else + { + break; + } } + + /* *sigh* */ + if( lenleft < 0 ) + break; } - /* [WvG] Well, maybe someone cares, so why not remove it? */ if( strlen( buff ) > 0 ) buff[strlen(buff)-1] = '\0'; -- cgit v1.2.3 From c38e9656987d0b56f233353d2d0fa63c68dcf365 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 29 May 2006 01:21:42 +0200 Subject: Removed a message that only applied to the MSN module that got replaced two years ago already. --- irc_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irc_commands.c b/irc_commands.c index f80f50f5..dc59f7ee 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -176,7 +176,7 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) if( !u->gc->prpl->chat_open( u->gc, u->handle ) ) { - irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick ); + irc_usermsg( irc, "Could not open a groupchat with %s.", u->nick ); } } else if( u ) -- cgit v1.2.3 From fb62f81f947c74e274b05e32d2e88e3a4d7e2613 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 3 Jun 2006 21:51:16 +0200 Subject: Implemented netsplits for "account off". --- irc.c | 26 ++++++++++++++++++++++++-- protocols/nogaim.c | 3 ++- protocols/nogaim.h | 6 ++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/irc.c b/irc.c index db9f7aad..3d3baca6 100644 --- a/irc.c +++ b/irc.c @@ -898,9 +898,31 @@ void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ) void irc_kill( irc_t *irc, user_t *u ) { - char *nick; + char *nick, *s; + char reason[64]; + + if( u->gc && u->gc->flags & OPT_LOGGING_OUT ) + { + if( u->gc->user->proto_opt[0][0] ) + g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, + u->gc->user->proto_opt[0] ); + else if( ( s = strchr( u->gc->username, '@' ) ) ) + g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, + s + 1 ); + else + g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, + u->gc->prpl->name, irc->myhost ); + + /* proto_opt might contain garbage after the : */ + if( ( s = strchr( reason, ':' ) ) ) + *s = 0; + } + else + { + strcpy( reason, "Leaving..." ); + } - irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, "Leaving..." ); + irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason ); nick = g_strdup( u->nick ); nick_lc( nick ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 04d48236..f95ddd8a 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -294,7 +294,8 @@ void signoff( struct gaim_connection *gc ) account_t *a; serv_got_crap( gc, "Signing off.." ); - + gc->flags |= OPT_LOGGING_OUT; + gaim_input_remove( gc->keepalive ); gc->keepalive = 0; gc->prpl->close( gc ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 8744054a..b143440a 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -53,10 +53,12 @@ #define WEBSITE "http://www.bitlbee.org/" #define IM_FLAG_AWAY 0x0020 -#define OPT_CONN_HTML 0x00000001 -#define OPT_LOGGED_IN 0x00010000 #define GAIM_AWAY_CUSTOM "Custom" +#define OPT_CONN_HTML 0x00000001 +#define OPT_LOGGED_IN 0x00010000 +#define OPT_LOGGING_OUT 0x00020000 + /* ok. now the fun begins. first we create a connection structure */ struct gaim_connection { -- cgit v1.2.3 From 5973412f44269f6cb796c9d6d38c151290c7367a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Jun 2006 22:52:40 +0200 Subject: Try to detect -lldap --- configure | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 97df1e27..c8a4c49f 100755 --- a/configure +++ b/configure @@ -142,16 +142,18 @@ echo CFLAGS+=-I`pwd` -I`pwd`/protocols -I. >> Makefile.settings echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings if [ -n "$CC" ]; then - echo "CC=$CC" >> Makefile.settings; + CC=$CC elif type gcc > /dev/null 2> /dev/null; then - echo "CC=gcc" >> Makefile.settings; + CC=gcc elif type cc > /dev/null 2> /dev/null; then - echo "CC=cc" >> Makefile.settings; + CC=cc else echo 'Cannot find a C compiler, aborting.' exit 1; fi +echo "CC=$CC" >> Makefile.settings; + if [ -n "$LD" ]; then echo "LD=$LD" >> Makefile.settings; elif type ld > /dev/null 2> /dev/null; then @@ -207,14 +209,17 @@ EOF detect_ldap() { - if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG ldb; then + TMPFILE=`mktemp` + if $CC -o $TMPFILE -shared -lldap 2>/dev/null >/dev/null; then cat<>Makefile.settings -EFLAGS+=`$PKG_CONFIG --libs ldb` -CFLAGS+=`$PKG_CONFIG --cflags ldb` +EFLAGS+=-lldap +CFLAGS+= EOF ldap=1 + rm -f $TMPFILE ret=1 else + ldap=0 ret=0 fi } @@ -285,9 +290,9 @@ fi if [ "$ldap" = 0 ]; then echo "LDAP_OBJ=\# no ldap" >> Makefile.settings - echo "#undef LDAP" >> config.h + echo "#undef WITH_LDAP" >> config.h elif [ "$ldap" = 1 ]; then - echo "#define LDAP 1" >> config.h + echo "#define WITH_LDAP 1" >> config.h echo "LDAP_OBJ=storage_ldap.o" >> Makefile.settings fi -- cgit v1.2.3 From 0025b5148725e524dfdc1da57b18fcd2be2608ee Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 3 Jun 2006 23:08:58 +0200 Subject: Use unique OID's and include BitlBee's OID (25873) --- doc/bitlbee.schema | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/doc/bitlbee.schema b/doc/bitlbee.schema index 795f5854..3322e057 100644 --- a/doc/bitlbee.schema +++ b/doc/bitlbee.schema @@ -22,23 +22,17 @@ ## - setting (multiple values) ## depends: top, account -#FIXME: Unique OID - -attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAutoConnect' +attributetype ( 1.3.6.1.4.1.25873.2.1.1 NAME 'bitlBeeAutoConnect' DESC 'Autoconnect setting' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) -#FIXME: Unique OID - -attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAccountNo' +attributetype ( 1.3.6.1.4.1.25873.2.1.2 NAME 'bitlBeeAccountNo' DESC 'Account number' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) -#FIXME: Unique OID - -objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeAccount' SUP account STRUCTURAL +objectclass ( 1.3.6.1.4.1.25873.2.2.3 NAME 'bitlBeeAccount' SUP account STRUCTURAL DESC 'BitlBee User Account ' MUST ( userid, userPassword ) MAY ( ) ) @@ -52,20 +46,17 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeAccount' SUP account STRUCTUR ## - autoconnect (true/false) 1.3.6.1.4.1.1466.115.121.1.7 ## depends: top -#FIXME: Unique OID -objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeIMAccount' SUP account STRUCTURAL +objectclass ( 1.3.6.1.4.1.25873.2.2.1 NAME 'bitlBeeIMAccount' SUP account STRUCTURAL DESC 'BitlBee IM Account ' MUST ( bitlBeeAccountNo, userid, userPassword ) MAY ( host, bitlBeeAutoconnect ) ) -#FIXME: Unique OID -objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeSetting' SUP top STRUCTURAL +objectclass ( 1.3.6.1.4.1.25873.2.2.2 NAME 'bitlBeeSetting' SUP top STRUCTURAL DESC 'BitlBee Configuration Setting' MUST ( bitlBeeSettingName ) MAY ( bitlBeeSettingValue ) ) -#FIXME: Unique OID -objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeBuddy' SUP top STRUCTURAL +objectclass ( 1.3.6.1.4.1.25873.2.2.3 NAME 'bitlBeeBuddy' SUP top STRUCTURAL DESC 'BitlBee Nick Mapping' MUST ( bitlBeeBuddyHandle ) MAY ( ircNick ) ) -- cgit v1.2.3 From a312b6bcbc6aa836850d94fc2abc70ceffe275cd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 7 Jun 2006 13:25:46 +0200 Subject: Added storage_xml.c --- account.c | 2 +- storage_xml.c | 412 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 storage_xml.c diff --git a/account.c b/account.c index 168d18c0..810f3a6f 100644 --- a/account.c +++ b/account.c @@ -34,7 +34,7 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) if( irc->accounts ) { for( a = irc->accounts; a->next; a = a->next ); - a = a->next = g_new0 ( account_t, 1 ); + a = a->next = g_new0( account_t, 1 ); } else { diff --git a/storage_xml.c b/storage_xml.c new file mode 100644 index 00000000..b27e63ad --- /dev/null +++ b/storage_xml.c @@ -0,0 +1,412 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2006 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Storage backend that uses an XMLish format for all data. */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "bitlbee.h" + +struct xml_parsedata +{ + irc_t *irc; + char *current_setting; + account_t *current_account; +}; + +static char *xml_attr( const gchar **attr_names, const gchar **attr_values, const gchar *key ) +{ + int i; + + for( i = 0; attr_names[i]; i ++ ) + if( g_strcasecmp( attr_names[i], key ) == 0 ) + return attr_values[i]; + + return NULL; +} + +static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) +{ + struct xml_parsedata *xd = data; + irc_t *irc = data->irc; + + if( g_strcasecmp( element_name, "user" ) == 0 ) + { + char *nick = xml_attr( attr_names, attr_values, "nick" ); + + if( nick && g_strcasecmp( nick, irc->nick ) == 0 ) + { + /* Okay! */ + } + } + else if( g_strcasecmp( element_name, "account" ) == 0 ) + { + char *protocol, *handle, *password; + struct prpl *prpl = NULL; + + handle = xml_attr( attr_names, attr_values, "handle" ); + password = xml_attr( attr_names, attr_values, "password" ); + + protocol = xml_attr( attr_names, attr_values, "protocol" ); + if( protocol ) + prpl = find_protocol( protocol ); + + if( handle && password && prpl ) + { + xd->current_account = account_add( irc, prpl, handle, password ) + } + } + else if( g_strcasecmp( element_name, "setting" ) == 0 ) + { + if( xd->current_account == NULL ) + { + current_setting = xml_attr( attr_names, attr_values, "name" ); + } + } + else if( g_strcasecmp( element_name, "buddy" ) == 0 ) + { + } + else if( g_strcasecmp( element_name, "password" ) == 0 ) + { + } + else + { + /* Return "unknown element" error. */ + } +} + +static void xml_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) +{ +} + +static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) +{ + struct xml_parsedata *xd = data; + irc_t *irc = data->irc; + + if( xd->current_setting ) + { + set_setstr( irc, xd->current_setting, text ); + } +} + +static void xml_error( GMarkupParseContext *ctx, GError *error, gpointer data ) +{ +} + +GMarkupParser xml_parser = +{ + xml_start_element, + xml_end_element, + xml_text, + NULL, + xml_error +}; + +static void xml_init( void ) +{ + if( access( global.conf->configdir, F_OK ) != 0 ) + log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG ); + else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 ) + log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); +} + +static storage_status_t xml_load ( const char *my_nick, const char* password, irc_t *irc ) +{ + GMarkupParseContext *ctx; + + ctx = g_markup_parse_context_new( parser, 0, xd, NULL ); + if( irc->status >= USTATUS_IDENTIFIED ) + return( 1 ); + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); + fp = fopen( s, "r" ); + if( !fp ) return STORAGE_NO_SUCH_USER; + + fscanf( fp, "%32[^\n]s", s ); + + if (checkpass (password, s) != 0) + { + fclose( fp ); + return STORAGE_INVALID_PASSWORD; + } + + /* Do this now. If the user runs with AuthMode = Registered, the + account command will not work otherwise. */ + irc->status = USTATUS_IDENTIFIED; + + while( fscanf( fp, "%511[^\n]s", s ) > 0 ) + { + fgetc( fp ); + line = deobfucrypt( s, password ); + if (line == NULL) return STORAGE_OTHER_ERROR; + root_command_string( irc, ru, line, 0 ); + g_free( line ); + } + fclose( fp ); + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" ); + fp = fopen( s, "r" ); + if( !fp ) return STORAGE_NO_SUCH_USER; + while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) + { + struct prpl *prpl; + + prpl = find_protocol_by_id(proto); + + if (!prpl) + continue; + + http_decode( s ); + nick_set( irc, s, prpl, nick ); + } + fclose( fp ); + + if( set_getint( irc, "auto_connect" ) ) + { + strcpy( s, "account on" ); /* Can't do this directly because r_c_s alters the string */ + root_command_string( irc, ru, s, 0 ); + } + + return STORAGE_OK; +} + +static storage_status_t text_save( irc_t *irc, int overwrite ) +{ + char s[512]; + char path[512], new_path[512]; + char *line; + nick_t *n; + set_t *set; + mode_t ou = umask( 0077 ); + account_t *a; + FILE *fp; + char *hash; + + if (!overwrite) { + g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); + if (access( path, F_OK ) != -1) + return STORAGE_ALREADY_EXISTS; + + g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); + if (access( path, F_OK ) != -1) + return STORAGE_ALREADY_EXISTS; + } + + /*\ + * [SH] Nothing should be saved if no password is set, because the + * password is not set if it was wrong, or if one is not identified + * yet. This means that a malicious user could easily overwrite + * files owned by someone else: + * a Bad Thing, methinks + \*/ + + /* [WVG] No? Really? */ + + /*\ + * [SH] Okay, okay, it wasn't really Wilmer who said that, it was + * me. I just thought it was funny. + \*/ + + hash = hashpass( irc->password ); + if( hash == NULL ) + { + irc_usermsg( irc, "Please register yourself if you want to save your settings." ); + return STORAGE_OTHER_ERROR; + } + + g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" ); + fp = fopen( path, "w" ); + if( !fp ) return STORAGE_OTHER_ERROR; + for( n = irc->nicks; n; n = n->next ) + { + strcpy( s, n->handle ); + s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */ + http_encode( s ); + g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", find_protocol_id(n->proto->name), n->nick ); + if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 ) + { + irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); + fclose( fp ); + return STORAGE_OTHER_ERROR; + } + } + if( fclose( fp ) != 0 ) + { + irc_usermsg( irc, "fclose() reported an error. Disk full?" ); + return STORAGE_OTHER_ERROR; + } + + g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); + if( unlink( new_path ) != 0 ) + { + if( errno != ENOENT ) + { + irc_usermsg( irc, "Error while removing old .nicks file" ); + return STORAGE_OTHER_ERROR; + } + } + if( rename( path, new_path ) != 0 ) + { + irc_usermsg( irc, "Error while renaming new .nicks file" ); + return STORAGE_OTHER_ERROR; + } + + g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" ); + fp = fopen( path, "w" ); + if( !fp ) return STORAGE_OTHER_ERROR; + if( fprintf( fp, "%s", hash ) != strlen( hash ) ) + { + irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); + fclose( fp ); + return STORAGE_OTHER_ERROR; + } + g_free( hash ); + + for( a = irc->accounts; a; a = a->next ) + { + if( !strcmp(a->prpl->name, "oscar") ) + g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server ); + else + g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"", + a->prpl->name, a->user, a->pass, a->server ? a->server : "" ); + + line = obfucrypt( s, irc->password ); + if( *line ) + { + if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) + { + irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); + fclose( fp ); + return STORAGE_OTHER_ERROR; + } + } + g_free( line ); + } + + for( set = irc->set; set; set = set->next ) + { + if( set->value && set->def ) + { + g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value ); + line = obfucrypt( s, irc->password ); + if( *line ) + { + if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) + { + irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); + fclose( fp ); + return STORAGE_OTHER_ERROR; + } + } + g_free( line ); + } + } + + if( strcmp( irc->mynick, ROOT_NICK ) != 0 ) + { + g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick ); + line = obfucrypt( s, irc->password ); + if( *line ) + { + if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) + { + irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); + fclose( fp ); + return STORAGE_OTHER_ERROR; + } + } + g_free( line ); + } + if( fclose( fp ) != 0 ) + { + irc_usermsg( irc, "fclose() reported an error. Disk full?" ); + return STORAGE_OTHER_ERROR; + } + + g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); + if( unlink( new_path ) != 0 ) + { + if( errno != ENOENT ) + { + irc_usermsg( irc, "Error while removing old .accounts file" ); + return STORAGE_OTHER_ERROR; + } + } + if( rename( path, new_path ) != 0 ) + { + irc_usermsg( irc, "Error while renaming new .accounts file" ); + return STORAGE_OTHER_ERROR; + } + + umask( ou ); + + return STORAGE_OK; +} + +static storage_status_t text_check_pass( const char *nick, const char *password ) +{ + char s[512]; + FILE *fp; + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" ); + fp = fopen( s, "r" ); + if (!fp) + return STORAGE_NO_SUCH_USER; + + fscanf( fp, "%32[^\n]s", s ); + fclose( fp ); + + if (checkpass( password, s) == -1) + return STORAGE_INVALID_PASSWORD; + + return STORAGE_OK; +} + +static storage_status_t text_remove( const char *nick, const char *password ) +{ + char s[512]; + storage_status_t status; + + status = text_check_pass( nick, password ); + if (status != STORAGE_OK) + return status; + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" ); + if (unlink( s ) == -1) + return STORAGE_OTHER_ERROR; + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" ); + if (unlink( s ) == -1) + return STORAGE_OTHER_ERROR; + + return STORAGE_OK; +} + +storage_t storage_xml = { + .name = "xml", + .init = xml_init, + .check_pass = xml_check_pass, + .remove = xml_remove, + .load = xml_load, + .save = xml_save +}; -- cgit v1.2.3 From 5a5c926ec0dffa4b28895929c092089c2a9b9d9f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 12 Jun 2006 08:58:20 +0200 Subject: Fixed a (very rare, AFAIK) NULL-pointer dereference. --- protocols/msn/msn.c | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 3c7064f8..bac9c427 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -63,33 +63,38 @@ static void msn_close( struct gaim_connection *gc ) struct msn_data *md = gc->proto_data; GSList *l; - if( md->fd >= 0 ) - closesocket( md->fd ); - - if( md->handler ) - { - if( md->handler->rxq ) g_free( md->handler->rxq ); - if( md->handler->cmd_text ) g_free( md->handler->cmd_text ); - g_free( md->handler ); - } - - while( md->switchboards ) - msn_sb_destroy( md->switchboards->data ); - - if( md->msgq ) + if( md ) { - struct msn_message *m; + if( md->fd >= 0 ) + closesocket( md->fd ); - for( l = md->msgq; l; l = l->next ) + if( md->handler ) { - m = l->data; + if( md->handler->rxq ) g_free( md->handler->rxq ); + if( md->handler->cmd_text ) g_free( md->handler->cmd_text ); + g_free( md->handler ); + } - serv_got_crap( gc, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); - g_free( m->who ); - g_free( m->text ); - g_free( m ); + while( md->switchboards ) + msn_sb_destroy( md->switchboards->data ); + + if( md->msgq ) + { + struct msn_message *m; + + for( l = md->msgq; l; l = l->next ) + { + m = l->data; + + serv_got_crap( gc, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); + g_free( m->who ); + g_free( m->text ); + g_free( m ); + } + g_slist_free( md->msgq ); } - g_slist_free( md->msgq ); + + g_free( md ); } for( l = gc->permit; l; l = l->next ) @@ -100,8 +105,6 @@ static void msn_close( struct gaim_connection *gc ) g_free( l->data ); g_slist_free( gc->deny ); - g_free( md ); - msn_connections = g_slist_remove( msn_connections, gc ); } -- cgit v1.2.3 From b4e4b958ac5db7f59f8a21c914b02d8d487de2a4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 13 Jun 2006 00:24:04 +0200 Subject: Remove unused variable. --- irc_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irc_commands.c b/irc_commands.c index dc59f7ee..75ab4dbd 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -320,7 +320,7 @@ static void irc_cmd_userhost( irc_t *irc, char **cmd ) static void irc_cmd_ison( irc_t *irc, char **cmd ) { user_t *u; - char buff[IRC_MAX_LINE], *s; + char buff[IRC_MAX_LINE]; int lenleft, i; buff[0] = '\0'; -- cgit v1.2.3 From c121f8945f7249520342ad86ff00f4986642ca0a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 14 Jun 2006 22:30:25 +0200 Subject: xml_load() works pretty well now. --- Makefile | 2 +- conf.c | 2 +- root_commands.c | 3 +- storage.c | 9 +- storage.h | 4 +- storage_xml.c | 390 ++++++++++++++++++++------------------------------------ 6 files changed, 147 insertions(+), 263 deletions(-) diff --git a/Makefile b/Makefile index 845beb1c..af710d59 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ -include Makefile.settings # Program variables -objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o unix.o url.o user.o util.o +objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o url.o user.o util.o headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h subdirs = protocols diff --git a/conf.c b/conf.c index 7538825d..dd3a0704 100644 --- a/conf.c +++ b/conf.c @@ -54,7 +54,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->port = 6667; conf->nofork = 0; conf->verbose = 0; - conf->primary_storage = "text"; + conf->primary_storage = "xml"; conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; conf->auth_pass = NULL; diff --git a/root_commands.c b/root_commands.c index 0e12e9ab..d44a36b7 100644 --- a/root_commands.c +++ b/root_commands.c @@ -141,8 +141,9 @@ static void cmd_identify( irc_t *irc, char **cmd ) irc_usermsg( irc, "Password accepted" ); irc_umode_set( irc, "+R", 1 ); break; + case STORAGE_OTHER_ERROR: default: - irc_usermsg( irc, "Something very weird happened" ); + irc_usermsg( irc, "Unknown error while loading configuration" ); break; } } diff --git a/storage.c b/storage.c index 7a242c3c..b8e07278 100644 --- a/storage.c +++ b/storage.c @@ -30,9 +30,9 @@ #include "crypting.h" extern storage_t storage_text; +extern storage_t storage_xml; -static GList text_entry = { &storage_text, NULL, NULL }; -static GList *storage_backends = &text_entry; +static GList *storage_backends = NULL; void register_storage_backend(storage_t *backend) { @@ -64,7 +64,10 @@ GList *storage_init(const char *primary, char **migrate) GList *ret = NULL; int i; storage_t *storage; - + + register_storage_backend(&storage_text); + register_storage_backend(&storage_xml); + storage = storage_init_single(primary); if (storage == NULL) return NULL; diff --git a/storage.h b/storage.h index 301b424c..3c641088 100644 --- a/storage.h +++ b/storage.h @@ -32,8 +32,8 @@ typedef enum { STORAGE_INVALID_PASSWORD, STORAGE_ALREADY_EXISTS, STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as - a database that is unreachable. log() will be - used for the exact error message */ + a database that is unreachable. log() will be + used for the exact error message */ } storage_status_t; typedef struct { diff --git a/storage_xml.c b/storage_xml.c index b27e63ad..29c01e07 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -26,11 +26,23 @@ #define BITLBEE_CORE #include "bitlbee.h" +typedef enum +{ + XML_PASS_CHECK_ONLY = -1, + XML_PASS_UNKNOWN = 0, + XML_PASS_OK +} xml_pass_st; + +#define XML_PASS_ERRORMSG "Wrong username or password" + struct xml_parsedata { irc_t *irc; char *current_setting; account_t *current_account; + char *given_nick; + char *given_pass; + xml_pass_st pass_st; }; static char *xml_attr( const gchar **attr_names, const gchar **attr_values, const gchar *key ) @@ -39,58 +51,118 @@ static char *xml_attr( const gchar **attr_names, const gchar **attr_values, cons for( i = 0; attr_names[i]; i ++ ) if( g_strcasecmp( attr_names[i], key ) == 0 ) - return attr_values[i]; + return (char*) attr_values[i]; return NULL; } +static void xml_destroy_xd( gpointer data ) +{ + struct xml_parsedata *xd = data; + + g_free( xd->given_nick ); + g_free( xd->given_pass ); + g_free( xd ); +} + static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) { struct xml_parsedata *xd = data; - irc_t *irc = data->irc; + irc_t *irc = xd->irc; if( g_strcasecmp( element_name, "user" ) == 0 ) { char *nick = xml_attr( attr_names, attr_values, "nick" ); + char *pass = xml_attr( attr_names, attr_values, "password" ); - if( nick && g_strcasecmp( nick, irc->nick ) == 0 ) + if( !nick || !pass ) { - /* Okay! */ + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attributes for %s element", element_name ); } + else if( strcmp( nick, xd->given_nick ) == 0 && + strcmp( pass, xd->given_pass ) == 0 ) + { + if( xd->pass_st != XML_PASS_CHECK_ONLY ) + xd->pass_st = XML_PASS_OK; + } + else + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + XML_PASS_ERRORMSG ); + } + } + else if( xd->pass_st < XML_PASS_OK ) + { + /* Let's not parse anything else if we only have to check + the password. */ } else if( g_strcasecmp( element_name, "account" ) == 0 ) { - char *protocol, *handle, *password; + char *protocol, *handle, *server, *password; struct prpl *prpl = NULL; handle = xml_attr( attr_names, attr_values, "handle" ); password = xml_attr( attr_names, attr_values, "password" ); + server = xml_attr( attr_names, attr_values, "server" ); protocol = xml_attr( attr_names, attr_values, "protocol" ); if( protocol ) prpl = find_protocol( protocol ); - if( handle && password && prpl ) + if( !handle || !password ) + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attributes for %s element", element_name ); + else if( !prpl ) + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing or unknown protocol %s element", element_name ); + else { - xd->current_account = account_add( irc, prpl, handle, password ) + xd->current_account = account_add( irc, prpl, handle, password ); + if( server ) + xd->current_account->server = g_strdup( server ); } } else if( g_strcasecmp( element_name, "setting" ) == 0 ) { if( xd->current_account == NULL ) { - current_setting = xml_attr( attr_names, attr_values, "name" ); + char *setting; + + if( xd->current_setting ) + { + g_free( xd->current_setting ); + xd->current_setting = NULL; + } + + if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) ) + xd->current_setting = g_strdup( setting ); + else + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attributes for %s element", element_name ); } } else if( g_strcasecmp( element_name, "buddy" ) == 0 ) { - } - else if( g_strcasecmp( element_name, "password" ) == 0 ) - { + char *handle, *nick; + + handle = xml_attr( attr_names, attr_values, "handle" ); + nick = xml_attr( attr_names, attr_values, "nick" ); + + if( xd->current_account && handle && nick ) + { + nick_set( irc, handle, xd->current_account->prpl, nick ); + } + else + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attributes for %s element", element_name ); + } } else { - /* Return "unknown element" error. */ + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unkown element: %s", element_name ); } } @@ -101,11 +173,19 @@ static void xml_end_element( GMarkupParseContext *ctx, const gchar *element_name static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) { struct xml_parsedata *xd = data; - irc_t *irc = data->irc; + irc_t *irc = xd->irc; - if( xd->current_setting ) + if( xd->pass_st < XML_PASS_OK ) + { + /* Let's not parse anything else if we only have to check + the password. */ + } + else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && + xd->current_setting && xd->current_account == NULL ) { - set_setstr( irc, xd->current_setting, text ); + set_setstr( irc, xd->current_setting, (char*) text ); + g_free( xd->current_setting ); + xd->current_setting = NULL; } } @@ -130,79 +210,66 @@ static void xml_init( void ) log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); } -static storage_status_t xml_load ( const char *my_nick, const char* password, irc_t *irc ) +static storage_status_t xml_load( const char *my_nick, const char *password, irc_t *irc ) { GMarkupParseContext *ctx; + struct xml_parsedata *xd; + char *fn, buf[512]; + GError *gerr = NULL; + int fd, st; - ctx = g_markup_parse_context_new( parser, 0, xd, NULL ); if( irc->status >= USTATUS_IDENTIFIED ) return( 1 ); - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); - fp = fopen( s, "r" ); - if( !fp ) return STORAGE_NO_SUCH_USER; + xd = g_new0( struct xml_parsedata, 1 ); + xd->irc = irc; + xd->given_nick = g_strdup( my_nick ); + xd->given_pass = g_strdup( password ); + nick_lc( xd->given_nick ); - fscanf( fp, "%32[^\n]s", s ); - - if (checkpass (password, s) != 0) + fn = g_strdup_printf( "%s%s%s", global.conf->configdir, xd->given_nick, ".xml" ); + if( ( fd = open( fn, O_RDONLY ) ) < 0 ) { - fclose( fp ); - return STORAGE_INVALID_PASSWORD; + xml_destroy_xd( xd ); + g_free( fn ); + return STORAGE_NO_SUCH_USER; } + g_free( fn ); - /* Do this now. If the user runs with AuthMode = Registered, the - account command will not work otherwise. */ - irc->status = USTATUS_IDENTIFIED; + ctx = g_markup_parse_context_new( &xml_parser, 0, xd, xml_destroy_xd ); - while( fscanf( fp, "%511[^\n]s", s ) > 0 ) + while( ( st = read( fd, buf, sizeof( buf ) ) ) > 0 ) { - fgetc( fp ); - line = deobfucrypt( s, password ); - if (line == NULL) return STORAGE_OTHER_ERROR; - root_command_string( irc, ru, line, 0 ); - g_free( line ); + if( !g_markup_parse_context_parse( ctx, buf, st, &gerr ) || gerr ) + { + g_markup_parse_context_free( ctx ); + + /* TODO: Display useful error msg */ + + if( gerr && strcmp( gerr->message, XML_PASS_ERRORMSG ) == 0 ) + return STORAGE_INVALID_PASSWORD; + else + return STORAGE_OTHER_ERROR; + } } - fclose( fp ); - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" ); - fp = fopen( s, "r" ); - if( !fp ) return STORAGE_NO_SUCH_USER; - while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) - { - struct prpl *prpl; - - prpl = find_protocol_by_id(proto); - - if (!prpl) - continue; - - http_decode( s ); - nick_set( irc, s, prpl, nick ); - } - fclose( fp ); + g_markup_parse_context_free( ctx ); + + irc->status = USTATUS_IDENTIFIED; if( set_getint( irc, "auto_connect" ) ) { - strcpy( s, "account on" ); /* Can't do this directly because r_c_s alters the string */ - root_command_string( irc, ru, s, 0 ); + /* Can't do this directly because r_c_s alters the string */ + strcpy( buf, "account on" ); + root_command_string( irc, NULL, buf, 0 ); } return STORAGE_OK; } -static storage_status_t text_save( irc_t *irc, int overwrite ) +static storage_status_t xml_save( irc_t *irc, int overwrite ) { - char s[512]; - char path[512], new_path[512]; - char *line; - nick_t *n; - set_t *set; - mode_t ou = umask( 0077 ); - account_t *a; - FILE *fp; - char *hash; - - if (!overwrite) { +/* if (!overwrite) { g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); if (access( path, F_OK ) != -1) return STORAGE_ALREADY_EXISTS; @@ -211,202 +278,15 @@ static storage_status_t text_save( irc_t *irc, int overwrite ) if (access( path, F_OK ) != -1) return STORAGE_ALREADY_EXISTS; } - - /*\ - * [SH] Nothing should be saved if no password is set, because the - * password is not set if it was wrong, or if one is not identified - * yet. This means that a malicious user could easily overwrite - * files owned by someone else: - * a Bad Thing, methinks - \*/ - - /* [WVG] No? Really? */ - - /*\ - * [SH] Okay, okay, it wasn't really Wilmer who said that, it was - * me. I just thought it was funny. - \*/ - - hash = hashpass( irc->password ); - if( hash == NULL ) - { - irc_usermsg( irc, "Please register yourself if you want to save your settings." ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - for( n = irc->nicks; n; n = n->next ) - { - strcpy( s, n->handle ); - s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */ - http_encode( s ); - g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", find_protocol_id(n->proto->name), n->nick ); - if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .nicks file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .nicks file" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - if( fprintf( fp, "%s", hash ) != strlen( hash ) ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - g_free( hash ); - - for( a = irc->accounts; a; a = a->next ) - { - if( !strcmp(a->prpl->name, "oscar") ) - g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server ); - else - g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"", - a->prpl->name, a->user, a->pass, a->server ? a->server : "" ); - - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - - for( set = irc->set; set; set = set->next ) - { - if( set->value && set->def ) - { - g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - } - - if( strcmp( irc->mynick, ROOT_NICK ) != 0 ) - { - g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .accounts file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .accounts file" ); - return STORAGE_OTHER_ERROR; - } - - umask( ou ); - - return STORAGE_OK; -} - -static storage_status_t text_check_pass( const char *nick, const char *password ) -{ - char s[512]; - FILE *fp; - - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" ); - fp = fopen( s, "r" ); - if (!fp) - return STORAGE_NO_SUCH_USER; - - fscanf( fp, "%32[^\n]s", s ); - fclose( fp ); - - if (checkpass( password, s) == -1) - return STORAGE_INVALID_PASSWORD; - - return STORAGE_OK; -} - -static storage_status_t text_remove( const char *nick, const char *password ) -{ - char s[512]; - storage_status_t status; - - status = text_check_pass( nick, password ); - if (status != STORAGE_OK) - return status; - - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" ); - if (unlink( s ) == -1) - return STORAGE_OTHER_ERROR; - - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" ); - if (unlink( s ) == -1) - return STORAGE_OTHER_ERROR; - +*/ return STORAGE_OK; } storage_t storage_xml = { .name = "xml", .init = xml_init, - .check_pass = xml_check_pass, - .remove = xml_remove, +// .check_pass = xml_check_pass, +// .remove = xml_remove, .load = xml_load, .save = xml_save }; -- cgit v1.2.3 From 79e826a028f4b4c62c0c16e20af1fb13a9636324 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 15 Jun 2006 14:22:17 +0200 Subject: Converted irc->status to binary flags. (This also fixes auto-save-on-quit that broke because of USTATUS_SHUTDOWN. :-( ) --- bitlbee.c | 2 +- ipc.c | 10 +++++----- irc.c | 10 +++++----- irc.h | 8 ++++---- irc_commands.c | 6 +++--- root_commands.c | 6 +++--- storage_text.c | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 3aca30c5..8cceca6f 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -235,7 +235,7 @@ gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condi irc->sendbuffer = NULL; irc->w_watch_source_id = 0; - if( irc->status == USTATUS_SHUTDOWN ) + if( irc->status & USTATUS_SHUTDOWN ) irc_free( irc ); return( FALSE ); diff --git a/ipc.c b/ipc.c index 18d3284e..5a23d1f9 100644 --- a/ipc.c +++ b/ipc.c @@ -114,7 +114,7 @@ static void ipc_child_cmd_die( irc_t *irc, char **cmd ) static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) { - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) return; if( strchr( irc->umode, 'w' ) ) @@ -123,7 +123,7 @@ static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) { - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) return; if( strchr( irc->umode, 's' ) ) @@ -132,7 +132,7 @@ static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd ) { - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) return; if( strchr( irc->umode, 'o' ) ) @@ -153,7 +153,7 @@ static void ipc_child_cmd_rehash( irc_t *irc, char **cmd ) static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) { - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) return; if( nick_cmp( cmd[1], irc->nick ) != 0 ) @@ -165,7 +165,7 @@ static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) static void ipc_child_cmd_hello( irc_t *irc, char **cmd ) { - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) ipc_to_master_str( "HELLO\r\n" ); else ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); diff --git a/irc.c b/irc.c index 3d3baca6..cd30d1c2 100644 --- a/irc.c +++ b/irc.c @@ -178,7 +178,7 @@ void irc_abort( irc_t *irc, int immed, char *format, ... ) irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" ); } - irc->status = USTATUS_SHUTDOWN; + irc->status |= USTATUS_SHUTDOWN; if( irc->sendbuffer && !immed ) { /* We won't read from this socket anymore. Instead, we'll connect a timer @@ -212,7 +212,7 @@ void irc_free(irc_t * irc) log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); - if( irc->status >= USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) ) + if( irc->status & USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) ) if( storage_save( irc, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); @@ -700,7 +700,7 @@ int irc_check_login( irc_t *irc ) { if( irc->user && irc->nick ) { - if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED ) + if( global.conf->authmode == AUTHMODE_CLOSED && ! irc->status & USTATUS_AUTHORIZED ) { irc_reply( irc, 464, ":This server is password-protected." ); return 0; @@ -757,7 +757,7 @@ void irc_login( irc_t *irc ) if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); - irc->status = USTATUS_LOGGED_IN; + irc->status |= USTATUS_LOGGED_IN; } void irc_motd( irc_t *irc ) @@ -1180,7 +1180,7 @@ static gboolean irc_userping( gpointer _irc ) irc_t *irc = _irc; int rv = 0; - if( irc->status < USTATUS_LOGGED_IN ) + if( ! irc->status & USTATUS_LOGGED_IN ) { if( gettime() > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) ) rv = gettime() - irc->last_pong; diff --git a/irc.h b/irc.h index 79faea0b..1dc12849 100644 --- a/irc.h +++ b/irc.h @@ -41,10 +41,10 @@ typedef enum { USTATUS_OFFLINE = 0, - USTATUS_AUTHORIZED, - USTATUS_LOGGED_IN, - USTATUS_IDENTIFIED, - USTATUS_SHUTDOWN = -1 + USTATUS_AUTHORIZED = 1, + USTATUS_LOGGED_IN = 2, + USTATUS_IDENTIFIED = 4, + USTATUS_SHUTDOWN = 8 } irc_status_t; typedef struct channel diff --git a/irc_commands.c b/irc_commands.c index dc59f7ee..519070db 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -31,7 +31,7 @@ static void irc_cmd_pass( irc_t *irc, char **cmd ) { if( global.conf->auth_pass && strcmp( cmd[1], global.conf->auth_pass ) == 0 ) { - irc->status = USTATUS_AUTHORIZED; + irc->status |= USTATUS_AUTHORIZED; irc_check_login( irc ); } else @@ -609,11 +609,11 @@ void irc_exec( irc_t *irc, char *cmd[] ) /* There should be no typo in the next line: */ for( n_arg = 0; cmd[n_arg]; n_arg ++ ); n_arg --; - if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status >= USTATUS_LOGGED_IN ) + if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) { irc_reply( irc, 462, ":Only allowed before logging in" ); } - else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && irc->status < USTATUS_LOGGED_IN ) + else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && ! irc->status & USTATUS_LOGGED_IN ) { irc_reply( irc, 451, ":Register first" ); } diff --git a/root_commands.c b/root_commands.c index 0e12e9ab..d8611347 100644 --- a/root_commands.c +++ b/root_commands.c @@ -162,7 +162,7 @@ static void cmd_register( irc_t *irc, char **cmd ) break; case STORAGE_OK: - irc->status = USTATUS_IDENTIFIED; + irc->status |= USTATUS_IDENTIFIED; irc_umode_set( irc, "+R", 1 ); break; @@ -186,7 +186,7 @@ static void cmd_drop( irc_t *irc, char **cmd ) break; case STORAGE_OK: irc_setpass( irc, NULL ); - irc->status = USTATUS_LOGGED_IN; + irc->status &= ~USTATUS_IDENTIFIED; irc_umode_set( irc, "-R", 1 ); irc_usermsg( irc, "Account `%s' removed", irc->nick ); break; @@ -200,7 +200,7 @@ static void cmd_account( irc_t *irc, char **cmd ) { account_t *a; - if( global.conf->authmode == AUTHMODE_REGISTERED && irc->status < USTATUS_IDENTIFIED ) + if( global.conf->authmode == AUTHMODE_REGISTERED && ! irc->status & USTATUS_IDENTIFIED ) { irc_usermsg( irc, "This server only accepts registered users" ); return; diff --git a/storage_text.c b/storage_text.c index f807cb3e..506c9f03 100644 --- a/storage_text.c +++ b/storage_text.c @@ -70,7 +70,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i FILE *fp; user_t *ru = user_find( irc, ROOT_NICK ); - if( irc->status >= USTATUS_IDENTIFIED ) + if( irc->status & USTATUS_IDENTIFIED ) return( 1 ); g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); @@ -87,7 +87,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i /* Do this now. If the user runs with AuthMode = Registered, the account command will not work otherwise. */ - irc->status = USTATUS_IDENTIFIED; + irc->status |= USTATUS_IDENTIFIED; while( fscanf( fp, "%511[^\n]s", s ) > 0 ) { -- cgit v1.2.3 From 3af70b06b2f0fb0fb41a041f6d86e3711b9eea3f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 15 Jun 2006 14:37:05 +0200 Subject: !x&y == (!x)&y, not !(x&y). --- ipc.c | 10 +++++----- irc.c | 4 ++-- irc_commands.c | 2 +- root_commands.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ipc.c b/ipc.c index 5a23d1f9..d7ef1020 100644 --- a/ipc.c +++ b/ipc.c @@ -114,7 +114,7 @@ static void ipc_child_cmd_die( irc_t *irc, char **cmd ) static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) { - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) return; if( strchr( irc->umode, 'w' ) ) @@ -123,7 +123,7 @@ static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) { - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) return; if( strchr( irc->umode, 's' ) ) @@ -132,7 +132,7 @@ static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd ) { - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) return; if( strchr( irc->umode, 'o' ) ) @@ -153,7 +153,7 @@ static void ipc_child_cmd_rehash( irc_t *irc, char **cmd ) static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) { - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) return; if( nick_cmp( cmd[1], irc->nick ) != 0 ) @@ -165,7 +165,7 @@ static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) static void ipc_child_cmd_hello( irc_t *irc, char **cmd ) { - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) ipc_to_master_str( "HELLO\r\n" ); else ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); diff --git a/irc.c b/irc.c index cd30d1c2..62af4b08 100644 --- a/irc.c +++ b/irc.c @@ -700,7 +700,7 @@ int irc_check_login( irc_t *irc ) { if( irc->user && irc->nick ) { - if( global.conf->authmode == AUTHMODE_CLOSED && ! irc->status & USTATUS_AUTHORIZED ) + if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) { irc_reply( irc, 464, ":This server is password-protected." ); return 0; @@ -1180,7 +1180,7 @@ static gboolean irc_userping( gpointer _irc ) irc_t *irc = _irc; int rv = 0; - if( ! irc->status & USTATUS_LOGGED_IN ) + if( !( irc->status & USTATUS_LOGGED_IN ) ) { if( gettime() > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) ) rv = gettime() - irc->last_pong; diff --git a/irc_commands.c b/irc_commands.c index 519070db..f410bb52 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -613,7 +613,7 @@ void irc_exec( irc_t *irc, char *cmd[] ) { irc_reply( irc, 462, ":Only allowed before logging in" ); } - else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && ! irc->status & USTATUS_LOGGED_IN ) + else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) { irc_reply( irc, 451, ":Register first" ); } diff --git a/root_commands.c b/root_commands.c index d8611347..3d3584b3 100644 --- a/root_commands.c +++ b/root_commands.c @@ -200,7 +200,7 @@ static void cmd_account( irc_t *irc, char **cmd ) { account_t *a; - if( global.conf->authmode == AUTHMODE_REGISTERED && ! irc->status & USTATUS_IDENTIFIED ) + if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) ) { irc_usermsg( irc, "This server only accepts registered users" ); return; -- cgit v1.2.3 From c2fa8279933a103d6576d891e85c1801d90c65ef Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 16 Jun 2006 13:48:52 +0200 Subject: Add unit testing infrastructure. --- .bzrignore | 1 + Makefile | 3 +++ tests/Makefile | 14 ++++++++++++++ tests/check.c | 17 +++++++++++++++++ tests/check_util.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 tests/Makefile create mode 100644 tests/check.c create mode 100644 tests/check_util.c diff --git a/.bzrignore b/.bzrignore index 802cb1a0..cddd9fb1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -11,3 +11,4 @@ decode encode bitlbee.pc .gdb_history +tests/check diff --git a/Makefile b/Makefile index 51ffc83f..6f1d2d4a 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,9 @@ distclean: clean $(subdirs) rm -f Makefile.settings config.h find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; +check: + $(MAKE) -C tests + install-doc: $(MAKE) -C doc install diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..3a27a430 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,14 @@ +include ../Makefile.settings + +LFLAGS +=-lcheck + +all: check + ./check + +check: check.o check_util.o ../util.o + @echo '*' Linking $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(EFLAGS) + +%.o: %.c + @echo '*' Compiling $< + @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/tests/check.c b/tests/check.c new file mode 100644 index 00000000..999da16a --- /dev/null +++ b/tests/check.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +/* From check_util.c */ +Suite *util_suite(void); + +int main (void) +{ + int nf; + SRunner *sr = srunner_create(util_suite()); + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed(sr); + srunner_free(sr); + return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/check_util.c b/tests/check_util.c new file mode 100644 index 00000000..52e8174c --- /dev/null +++ b/tests/check_util.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include "irc.h" +#include "set.h" +#include "util.h" + +START_TEST(test_strip_linefeed) +{ + int i; + const char *get[] = { "Test", "Test\r", "Test\rX\r", NULL }; + const char *expected[] = { "Test", "Test", "TestX", NULL }; + + for (i = 0; get[i]; i++) { + char copy[20]; + strcpy(copy, get[i]); + strip_linefeed(copy); + fail_unless (strcmp(copy, expected[i]) == 0, + "(%d) strip_linefeed broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); + } +} +END_TEST + +Suite *util_suite (void) +{ + Suite *s = suite_create("Util"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_strip_linefeed); + return s; +} -- cgit v1.2.3 From 1fc2958b1e503b782081692c1a503bc7bba19fe1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 16 Jun 2006 14:07:51 +0200 Subject: Add checks for nick functions as well, fix bug where nick lengths weren't being honored. --- nick.c | 4 ++-- tests/Makefile | 4 +++- tests/check.c | 15 ++++++++++++ tests/check_nick.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/check_util.c | 19 +++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 tests/check_nick.c diff --git a/nick.c b/nick.c index 771d2288..68dd9802 100644 --- a/nick.c +++ b/nick.c @@ -162,7 +162,7 @@ void nick_strip( char * nick ) { int i, j; - for( i = j = 0; nick[i] && i < MAX_NICK_LENGTH; i++ ) + for( i = j = 0; nick[i] && j < MAX_NICK_LENGTH; i++ ) { if( strchr( nick_lc_chars, nick[i] ) || strchr( nick_uc_chars, nick[i] ) ) @@ -171,7 +171,7 @@ void nick_strip( char * nick ) j++; } } - while( j < MAX_NICK_LENGTH ) + while( j <= MAX_NICK_LENGTH ) nick[j++] = '\0'; } diff --git a/tests/Makefile b/tests/Makefile index 3a27a430..ce8ed690 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,7 +5,9 @@ LFLAGS +=-lcheck all: check ./check -check: check.o check_util.o ../util.o +main_objs = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o url.o user.o util.o + +check: check.o check_util.o check_nick.o $(addprefix ../, $(main_objs)) ../protocols/protocols.o @echo '*' Linking $@ @$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(EFLAGS) diff --git a/tests/check.c b/tests/check.c index 999da16a..5cfb7dfd 100644 --- a/tests/check.c +++ b/tests/check.c @@ -2,14 +2,29 @@ #include #include #include +#include "bitlbee.h" + +global_t global; /* Against global namespace pollution */ + +double gettime() +{ + struct timeval time[1]; + + gettimeofday( time, 0 ); + return( (double) time->tv_sec + (double) time->tv_usec / 1000000 ); +} /* From check_util.c */ Suite *util_suite(void); +/* From check_nick.c */ +Suite *nick_suite(void); + int main (void) { int nf; SRunner *sr = srunner_create(util_suite()); + srunner_add_suite(sr, nick_suite()); srunner_run_all (sr, CK_NORMAL); nf = srunner_ntests_failed(sr); srunner_free(sr); diff --git a/tests/check_nick.c b/tests/check_nick.c new file mode 100644 index 00000000..5858e512 --- /dev/null +++ b/tests/check_nick.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include "irc.h" +#include "set.h" +#include "util.h" + +START_TEST(test_nick_strip) +{ + int i; + const char *get[] = { "test:", "test", "test\n", + "thisisaveryveryveryverylongnick", + "thisisave:ryveryveryverylongnick", + "t::::est", + NULL }; + const char *expected[] = { "test", "test", "test", + "thisisaveryveryveryveryl", + "thisisaveryveryveryveryl", + "test", + NULL }; + + for (i = 0; get[i]; i++) { + char copy[30]; + strcpy(copy, get[i]); + nick_strip(copy); + fail_unless (strcmp(copy, expected[i]) == 0, + "(%d) nick_strip broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); + } +} +END_TEST + +START_TEST(test_nick_ok_ok) +{ + const char *nicks[] = { "foo", "bar", "bla[", "blie]", + "BreEZaH", "\\od^~", NULL }; + int i; + + for (i = 0; nicks[i]; i++) { + fail_unless (nick_ok(nicks[i]) == 1, + "nick_ok() failed: %s", nicks[i]); + } +} +END_TEST + +START_TEST(test_nick_ok_notok) +{ + const char *nicks[] = { "thisisaveryveryveryveryveryveryverylongnick", + "\nillegalchar", "", "nick%", NULL }; + int i; + + for (i = 0; nicks[i]; i++) { + fail_unless (nick_ok(nicks[i]) == 0, + "nick_ok() succeeded for invalid: %s", nicks[i]); + } +} +END_TEST + +Suite *nick_suite (void) +{ + Suite *s = suite_create("Nick"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_nick_ok_ok); + tcase_add_test (tc_core, test_nick_ok_notok); + tcase_add_test (tc_core, test_nick_strip); + return s; +} diff --git a/tests/check_util.c b/tests/check_util.c index 52e8174c..e771238f 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -24,11 +24,30 @@ START_TEST(test_strip_linefeed) } END_TEST +START_TEST(test_strip_newlines) +{ + int i; + const char *get[] = { "Test", "Test\r\n", "Test\nX\n", NULL }; + const char *expected[] = { "Test", "Test ", "Test X ", NULL }; + + for (i = 0; get[i]; i++) { + char copy[20], *ret; + strcpy(copy, get[i]); + ret = strip_newlines(copy); + fail_unless (strcmp(copy, expected[i]) == 0, + "(%d) strip_newlines broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); + fail_unless (copy == ret, "Original string not returned"); + } +} +END_TEST + Suite *util_suite (void) { Suite *s = suite_create("Util"); TCase *tc_core = tcase_create("Core"); suite_add_tcase (s, tc_core); tcase_add_test (tc_core, test_strip_linefeed); + tcase_add_test (tc_core, test_strip_newlines); return s; } -- cgit v1.2.3 From 10efa911cbf0d3761d42cc3e57973c8cd1a92821 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 17 Jun 2006 13:39:17 +0200 Subject: Fixed bug in LDAP Makefile generation. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index b05aa155..05fb7cb4 100755 --- a/configure +++ b/configure @@ -318,7 +318,7 @@ if [ "$ldap" = "auto" ]; then fi if [ "$ldap" = 0 ]; then - echo "LDAP_OBJ=\# no ldap" >> Makefile.settings + echo "LDAP_OBJ=" >> Makefile.settings echo "#undef WITH_LDAP" >> config.h elif [ "$ldap" = 1 ]; then echo "#define WITH_LDAP 1" >> config.h -- cgit v1.2.3 From d28f3b35855c8f8de0be9589334004b30d1ac394 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 19 Jun 2006 01:07:28 +0200 Subject: Now saving the password's md5sum instead of the plaintext version. --- storage_xml.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index 5eda46cc..12afe472 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -25,6 +25,7 @@ #define BITLBEE_CORE #include "bitlbee.h" +#include "md5.h" typedef enum { @@ -80,16 +81,35 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } - else if( strcmp( nick, xd->given_nick ) == 0 && - strcmp( pass, xd->given_pass ) == 0 ) - { - if( xd->pass_st != XML_PASS_CHECK_ONLY ) - xd->pass_st = XML_PASS_OK; - } else { - g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - XML_PASS_ERRORMSG ); + md5_byte_t pass_md5[16]; + md5_state_t md5_state; + int pass_match, i, j; + + md5_init( &md5_state ); + md5_append( &md5_state, xd->given_pass, strlen( xd->given_pass ) ); + md5_finish( &md5_state, pass_md5 ); + + for( i = 0; i < 16 && pass[i*2] && pass[i*2+1]; i ++ ) + { + sscanf( pass + i * 2, "%2x", &j ); + if( j != pass_md5[i] ) + break; + } + /* If we reached the end of the loop, it was a match! */ + pass_match = i == 16; + + if( strcmp( nick, xd->given_nick ) == 0 && pass_match ) + { + if( xd->pass_st != XML_PASS_CHECK_ONLY ) + xd->pass_st = XML_PASS_OK; + } + else + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + XML_PASS_ERRORMSG ); + } } } else if( xd->pass_st < XML_PASS_OK ) -- cgit v1.2.3 From d028a77c97eeccc8d1345af008e2d8920116b637 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 19 Jun 2006 13:52:34 +0200 Subject: Better detection of incorrect MD5 password hashes. --- storage_xml.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index 12afe472..ff8f1351 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -85,31 +85,35 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { md5_byte_t pass_md5[16]; md5_state_t md5_state; - int pass_match, i, j; + int i, j; md5_init( &md5_state ); - md5_append( &md5_state, xd->given_pass, strlen( xd->given_pass ) ); + md5_append( &md5_state, (md5_byte_t*) xd->given_pass, strlen( xd->given_pass ) ); md5_finish( &md5_state, pass_md5 ); - for( i = 0; i < 16 && pass[i*2] && pass[i*2+1]; i ++ ) + for( i = 0; i < 16; i ++ ) { - sscanf( pass + i * 2, "%2x", &j ); + if( !isxdigit( pass[i*2] ) || !isxdigit( pass[i*2+1] ) || + sscanf( pass + i * 2, "%2x", &j ) != 1 ) + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Incorrect password MD5-hash" ); + break; + } if( j != pass_md5[i] ) + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + XML_PASS_ERRORMSG ); break; + } } - /* If we reached the end of the loop, it was a match! */ - pass_match = i == 16; - if( strcmp( nick, xd->given_nick ) == 0 && pass_match ) + /* If we reached the end of the loop, it was a match! */ + if( i == 16 ) { if( xd->pass_st != XML_PASS_CHECK_ONLY ) xd->pass_st = XML_PASS_OK; } - else - { - g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - XML_PASS_ERRORMSG ); - } } } else if( xd->pass_st < XML_PASS_OK ) -- cgit v1.2.3 From 84e9cea2a80d4e8b05bbadbde923301685d05497 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 20 Jun 2006 23:36:53 +0200 Subject: Added xml_remove() and xml_check_pass(). --- storage_xml.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index ff8f1351..57388f67 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -34,6 +34,8 @@ typedef enum XML_PASS_OK } xml_pass_st; +/* This isn't very clean, probably making a separate error class + code for + BitlBee would be a better solution. But this will work for now... */ #define XML_PASS_ERRORMSG "Wrong username or password" struct xml_parsedata @@ -193,7 +195,6 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na static void xml_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) { struct xml_parsedata *xd = data; - // irc_t *irc = xd->irc; if( g_strcasecmp( element_name, "setting" ) == 0 && xd->current_setting ) { @@ -214,7 +215,8 @@ static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_le if( xd->pass_st < XML_PASS_OK ) { /* Let's not parse anything else if we only have to check - the password. */ + the password, or if we didn't get the chance to check it + yet. */ } else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting && xd->current_account == NULL ) @@ -242,7 +244,7 @@ static void xml_init( void ) log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); } -static storage_status_t xml_load( const char *my_nick, const char *password, irc_t *irc ) +static storage_status_t xml_load_real( const char *my_nick, const char *password, irc_t *irc, xml_pass_st action ) { GMarkupParseContext *ctx; struct xml_parsedata *xd; @@ -250,13 +252,14 @@ static storage_status_t xml_load( const char *my_nick, const char *password, irc GError *gerr = NULL; int fd, st; - if( irc->status & USTATUS_IDENTIFIED ) + if( irc && irc->status & USTATUS_IDENTIFIED ) return( 1 ); xd = g_new0( struct xml_parsedata, 1 ); xd->irc = irc; xd->given_nick = g_strdup( my_nick ); xd->given_pass = g_strdup( password ); + xd->pass_st = action; nick_lc( xd->given_nick ); fn = g_strdup_printf( "%s%s%s", global.conf->configdir, xd->given_nick, ".xml" ); @@ -282,7 +285,7 @@ static storage_status_t xml_load( const char *my_nick, const char *password, irc return STORAGE_INVALID_PASSWORD; else { - if( gerr ) + if( gerr && irc ) irc_usermsg( irc, "Error from XML-parser: %s", gerr->message ); return STORAGE_OTHER_ERROR; @@ -293,6 +296,9 @@ static storage_status_t xml_load( const char *my_nick, const char *password, irc g_markup_parse_context_free( ctx ); close( fd ); + if( action == XML_PASS_CHECK_ONLY ) + return STORAGE_OK; + irc->status |= USTATUS_IDENTIFIED; if( set_getint( irc, "auto_connect" ) ) @@ -305,6 +311,18 @@ static storage_status_t xml_load( const char *my_nick, const char *password, irc return STORAGE_OK; } +static storage_status_t xml_load( const char *my_nick, const char *password, irc_t *irc ) +{ + return xml_load_real( my_nick, password, irc, XML_PASS_UNKNOWN ); +} + +static storage_status_t xml_check_pass( const char *my_nick, const char *password ) +{ + /* This is a little bit risky because we have to pass NULL for the + irc_t argument. This *should* be fine, if I didn't miss anything... */ + return xml_load_real( my_nick, password, NULL, XML_PASS_CHECK_ONLY ); +} + static int xml_printf( int fd, char *fmt, ... ) { va_list params; @@ -395,11 +413,27 @@ write_error: return STORAGE_OTHER_ERROR; } +static storage_status_t xml_remove( const char *nick, const char *password ) +{ + char s[512]; + storage_status_t status; + + status = xml_check_pass( nick, password ); + if( status != STORAGE_OK ) + return status; + + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".xml" ); + if( unlink( s ) == -1 ) + return STORAGE_OTHER_ERROR; + + return STORAGE_OK; +} + storage_t storage_xml = { .name = "xml", .init = xml_init, -// .check_pass = xml_check_pass, -// .remove = xml_remove, + .check_pass = xml_check_pass, + .remove = xml_remove, .load = xml_load, .save = xml_save }; -- cgit v1.2.3 From 2befb95e3bdaf5306b55342c175abca174e40ffb Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 20 Jun 2006 23:37:16 +0200 Subject: Added migration storage defaults. --- conf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf.c b/conf.c index dd3a0704..d70117f5 100644 --- a/conf.c +++ b/conf.c @@ -41,6 +41,7 @@ static int conf_loadini( conf_t *conf, char *file ); conf_t *conf_load( int argc, char *argv[] ) { + char *mig_list[2] = { "text", NULL }; conf_t *conf; int opt, i; @@ -55,6 +56,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->nofork = 0; conf->verbose = 0; conf->primary_storage = "xml"; + conf->migrate_storage = mig_list; conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; conf->auth_pass = NULL; -- cgit v1.2.3 From ece2cd2eba78088a8cf9d4744aafb3f34dc97c5b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 20 Jun 2006 23:48:28 +0200 Subject: xml_save() now stores the password's md5sum too. Kind of ... important.. --- storage_xml.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index 57388f67..87fbb693 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -342,11 +342,19 @@ static int xml_printf( int fd, char *fmt, ... ) static storage_status_t xml_save( irc_t *irc, int overwrite ) { - char path[512], *path2; + char path[512], *path2, md5_buf[33]; set_t *set; nick_t *nick; account_t *acc; - int fd; + int fd, i; + md5_byte_t pass_md5[16]; + md5_state_t md5_state; + + if( irc->password == NULL ) + { + irc_usermsg( irc, "Please register yourself if you want to save your settings." ); + return STORAGE_OTHER_ERROR; + } g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, irc->nick, ".xml" ); @@ -360,7 +368,13 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) return STORAGE_OTHER_ERROR; } - if( !xml_printf( fd, "\n", irc->nick, irc->password ) ) + md5_init( &md5_state ); + md5_append( &md5_state, (md5_byte_t*) irc->password, strlen( irc->password ) ); + md5_finish( &md5_state, pass_md5 ); + for( i = 0; i < 16; i ++ ) + g_snprintf( md5_buf + i * 2, 3, "%02x", pass_md5[i] ); + + if( !xml_printf( fd, "\n", irc->nick, md5_buf ) ) goto write_error; for( set = irc->set; set; set = set->next ) -- cgit v1.2.3 From 9b46b64b83314a177a7ca3f9f990ff8c78282a5a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 21 Jun 2006 00:05:04 +0200 Subject: Fixed error message for unknown protocols. --- storage_xml.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index 87fbb693..737f2091 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -136,12 +136,12 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na if( protocol ) prpl = find_protocol( protocol ); - if( !handle || !password ) + if( !handle || !password || !protocol ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); else if( !prpl ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Missing or unknown protocol %s element", element_name ); + "Unknown protocol: %s", protocol ); else { xd->current_account = account_add( irc, prpl, handle, password ); -- cgit v1.2.3 From 2b14eef99faf7e113cc6c17d68bf6402f87ddd66 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 21 Jun 2006 00:14:46 +0200 Subject: Implemented handling of autoconnect attribute. --- account.c | 1 + account.h | 1 + root_commands.c | 2 +- storage_xml.c | 9 +++++++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/account.c b/account.c index 810f3a6f..b75afa51 100644 --- a/account.c +++ b/account.c @@ -44,6 +44,7 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) a->prpl = prpl; a->user = g_strdup( user ); a->pass = g_strdup( pass ); + a->auto_connect = 1; a->irc = irc; return( a ); diff --git a/account.h b/account.h index 37cd8814..40efb101 100644 --- a/account.h +++ b/account.h @@ -33,6 +33,7 @@ typedef struct account char *pass; char *server; + int auto_connect; int reconnect; struct irc *irc; diff --git a/root_commands.c b/root_commands.c index 225912b7..d263bb84 100644 --- a/root_commands.c +++ b/root_commands.c @@ -306,7 +306,7 @@ static void cmd_account( irc_t *irc, char **cmd ) irc_usermsg( irc, "Trying to get all accounts connected..." ); for( a = irc->accounts; a; a = a->next ) - if( !a->gc ) + if( !a->gc && a->auto_connect ) account_on( irc, a ); } else diff --git a/storage_xml.c b/storage_xml.c index 737f2091..69e991d2 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -125,12 +125,13 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na } else if( g_strcasecmp( element_name, "account" ) == 0 ) { - char *protocol, *handle, *server, *password; + char *protocol, *handle, *server, *password, *autoconnect; struct prpl *prpl = NULL; handle = xml_attr( attr_names, attr_values, "handle" ); password = xml_attr( attr_names, attr_values, "password" ); server = xml_attr( attr_names, attr_values, "server" ); + autoconnect = xml_attr( attr_names, attr_values, "autoconnect" ); protocol = xml_attr( attr_names, attr_values, "protocol" ); if( protocol ) @@ -147,6 +148,10 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na xd->current_account = account_add( irc, prpl, handle, password ); if( server ) xd->current_account->server = g_strdup( server ); + if( autoconnect ) + /* Return value doesn't matter, since account_add() already sets + a default! */ + sscanf( autoconnect, "%d", &xd->current_account->auto_connect ); } } else if( g_strcasecmp( element_name, "setting" ) == 0 ) @@ -384,7 +389,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) for( acc = irc->accounts; acc; acc = acc->next ) { - if( !xml_printf( fd, "\tprpl->name, acc->user, acc->pass, "yes" ) ) + if( !xml_printf( fd, "\tprpl->name, acc->user, acc->pass, acc->auto_connect ) ) goto write_error; if( acc->server && acc->server[0] && !xml_printf( fd, " server=\"%s\"", acc->server ) ) goto write_error; -- cgit v1.2.3 From 59f5c42a86fe73e95aaed0bfe455c7c816f39d2b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 21 Jun 2006 18:56:16 +0200 Subject: Fixed md->grouplist memory leak. --- protocols/msn/msn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index bac9c427..6393f31d 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -94,6 +94,8 @@ static void msn_close( struct gaim_connection *gc ) g_slist_free( md->msgq ); } + g_free( md->grouplist ); + g_free( md ); } -- cgit v1.2.3 From 00ab35016e3646aa936ae0c3d7a8531ec68d6f24 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 21 Jun 2006 19:14:49 +0200 Subject: Fixed GError memory leak, correctly setting the migrate_storage default. --- conf.c | 3 +-- storage_xml.c | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/conf.c b/conf.c index d70117f5..3154eb9c 100644 --- a/conf.c +++ b/conf.c @@ -41,7 +41,6 @@ static int conf_loadini( conf_t *conf, char *file ); conf_t *conf_load( int argc, char *argv[] ) { - char *mig_list[2] = { "text", NULL }; conf_t *conf; int opt, i; @@ -56,7 +55,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->nofork = 0; conf->verbose = 0; conf->primary_storage = "xml"; - conf->migrate_storage = mig_list; + conf->migrate_storage = g_strsplit( "text", ",", -1 ); conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; conf->auth_pass = NULL; diff --git a/storage_xml.c b/storage_xml.c index 69e991d2..41a50d8c 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -287,16 +287,22 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password /* Slightly dirty... */ if( gerr && strcmp( gerr->message, XML_PASS_ERRORMSG ) == 0 ) + { + g_clear_error( &gerr ); return STORAGE_INVALID_PASSWORD; + } else { if( gerr && irc ) irc_usermsg( irc, "Error from XML-parser: %s", gerr->message ); + g_clear_error( &gerr ); return STORAGE_OTHER_ERROR; } } } + /* Just to be sure... */ + g_clear_error( &gerr ); g_markup_parse_context_free( ctx ); close( fd ); -- cgit v1.2.3 From 812a41362a9316da1734fdaa8b1aad36bde9cb5c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 23 Jun 2006 20:15:28 +0200 Subject: Added saner base64 encoding function (actually, moved the one from libyahoo2.c to core, with some changes), which I need for the XML format password garbling. --- protocols/yahoo/libyahoo2.c | 28 +------------- util.c | 89 +++++++++++++++++++-------------------------- util.h | 1 + 3 files changed, 41 insertions(+), 77 deletions(-) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index c691f18b..ee0f2f0e 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -694,34 +694,10 @@ static void yahoo_packet_dump(unsigned char *data, int len) } } -static char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789._"; -static void to_y64(unsigned char *out, const unsigned char *in, int inlen) /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */ +static void to_y64(unsigned char *out, const unsigned char *in, int inlen) { - 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'; + return base64_encode_real(in, inlen, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"); } static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, int length) diff --git a/util.c b/util.c index dfa0906b..d8d6a4c7 100644 --- a/util.c +++ b/util.c @@ -83,61 +83,48 @@ char *add_cr(char *text) return ret; } -static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/"; - -/* XXX Find bug */ char *tobase64(const char *text) { - char *out = NULL; - const char *c; - unsigned int tmp = 0; - int len = 0, n = 0; - - c = text; - - while (*c) { - tmp = tmp << 8; - tmp += *c; - n++; - - if (n == 3) { - out = g_realloc(out, len + 4); - out[len] = alphabet[(tmp >> 18) & 0x3f]; - out[len + 1] = alphabet[(tmp >> 12) & 0x3f]; - out[len + 2] = alphabet[(tmp >> 6) & 0x3f]; - out[len + 3] = alphabet[tmp & 0x3f]; - len += 4; - tmp = 0; - n = 0; - } - c++; + char *out; + int len; + + len = strlen(text); + out = g_malloc((len + 2) /* the == padding */ + / 3 /* every 3-byte block */ + * 4 /* becomes a 4-byte one */ + + 1); /* and of course, ASCIIZ! */ + + base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); + + return out; +} + +void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits) +{ + for (; inlen >= 3; inlen -= 3) + { + *out++ = b64digits[in[0] >> 2]; + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)]; + *out++ = b64digits[in[2] & 0x3f]; + in += 3; } - switch (n) { - - case 2: - tmp <<= 8; - out = g_realloc(out, len + 5); - out[len] = alphabet[(tmp >> 18) & 0x3f]; - out[len + 1] = alphabet[(tmp >> 12) & 0x3f]; - out[len + 2] = alphabet[(tmp >> 6) & 0x3f]; - out[len + 3] = '='; - out[len + 4] = 0; - break; - case 1: - tmp <<= 16; - out = g_realloc(out, len + 5); - out[len] = alphabet[(tmp >> 18) & 0x3f]; - out[len + 1] = alphabet[(tmp >> 12) & 0x3f]; - out[len + 2] = '='; - out[len + 3] = '='; - out[len + 4] = 0; - break; - case 0: - out = g_realloc(out, len + 1); - out[len] = 0; - break; + if (inlen > 0) + { + *out++ = b64digits[in[0] >> 2]; + if (inlen > 1) + { + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[((in[1]<<2) & 0x3c)]; + } + else + { + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[64]; + } + *out++ = b64digits[64]; } - return out; + *out = '\0'; } char *normalize(const char *s) diff --git a/util.h b/util.h index 8e13d9dd..c7eec19b 100644 --- a/util.h +++ b/util.h @@ -30,6 +30,7 @@ G_MODULE_EXPORT void strip_linefeed( gchar *text ); G_MODULE_EXPORT char *add_cr( char *text ); G_MODULE_EXPORT char *strip_newlines(char *source); G_MODULE_EXPORT char *tobase64( const char *text ); +G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits ); G_MODULE_EXPORT char *normalize( const char *s ); G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value ); -- cgit v1.2.3 From df1694b9559d4abec748b0506b5f44e684d022a8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 14:15:42 +0200 Subject: Moving all generic files to lib/ instead of having some in / and some in protocols/, and adding RC4 code. --- Makefile | 4 +- bitlbee.h | 2 +- conf.c | 2 +- configure | 2 +- ini.c | 90 ------- ini.h | 43 ---- irc_commands.c | 2 +- lib/Makefile | 37 +++ lib/events.h | 66 ++++++ lib/events_glib.c | 137 +++++++++++ lib/events_libevent.c | 247 ++++++++++++++++++++ lib/http_client.c | 453 ++++++++++++++++++++++++++++++++++++ lib/http_client.h | 57 +++++ lib/ini.c | 90 +++++++ lib/ini.h | 43 ++++ lib/md5.c | 392 +++++++++++++++++++++++++++++++ lib/md5.h | 85 +++++++ lib/misc.c | 481 ++++++++++++++++++++++++++++++++++++++ lib/misc.h | 51 ++++ lib/proxy.c | 556 ++++++++++++++++++++++++++++++++++++++++++++ lib/proxy.h | 53 +++++ lib/rc4.c | 179 ++++++++++++++ lib/rc4.h | 35 +++ lib/sha.c | 173 ++++++++++++++ lib/sha.h | 21 ++ lib/ssl_bogus.c | 57 +++++ lib/ssl_client.h | 42 ++++ lib/ssl_gnutls.c | 206 ++++++++++++++++ lib/ssl_nss.c | 190 +++++++++++++++ lib/ssl_openssl.c | 221 ++++++++++++++++++ lib/url.c | 107 +++++++++ lib/url.h | 44 ++++ protocols/Makefile | 2 +- protocols/events.h | 66 ------ protocols/events_glib.c | 137 ----------- protocols/events_libevent.c | 247 -------------------- protocols/http_client.c | 453 ------------------------------------ protocols/http_client.h | 57 ----- protocols/md5.c | 392 ------------------------------- protocols/md5.h | 85 ------- protocols/proxy.c | 556 -------------------------------------------- protocols/proxy.h | 53 ----- protocols/sha.c | 173 -------------- protocols/sha.h | 21 -- protocols/ssl_bogus.c | 57 ----- protocols/ssl_client.h | 42 ---- protocols/ssl_gnutls.c | 206 ---------------- protocols/ssl_nss.c | 190 --------------- protocols/ssl_openssl.c | 221 ------------------ url.c | 107 --------- url.h | 44 ---- util.c | 481 -------------------------------------- util.h | 51 ---- 53 files changed, 4030 insertions(+), 3779 deletions(-) delete mode 100644 ini.c delete mode 100644 ini.h create mode 100644 lib/Makefile create mode 100644 lib/events.h create mode 100644 lib/events_glib.c create mode 100644 lib/events_libevent.c create mode 100644 lib/http_client.c create mode 100644 lib/http_client.h create mode 100644 lib/ini.c create mode 100644 lib/ini.h create mode 100644 lib/md5.c create mode 100644 lib/md5.h create mode 100644 lib/misc.c create mode 100644 lib/misc.h create mode 100644 lib/proxy.c create mode 100644 lib/proxy.h create mode 100644 lib/rc4.c create mode 100644 lib/rc4.h create mode 100644 lib/sha.c create mode 100644 lib/sha.h create mode 100644 lib/ssl_bogus.c create mode 100644 lib/ssl_client.h create mode 100644 lib/ssl_gnutls.c create mode 100644 lib/ssl_nss.c create mode 100644 lib/ssl_openssl.c create mode 100644 lib/url.c create mode 100644 lib/url.h delete mode 100644 protocols/events.h delete mode 100644 protocols/events_glib.c delete mode 100644 protocols/events_libevent.c delete mode 100644 protocols/http_client.c delete mode 100644 protocols/http_client.h delete mode 100644 protocols/md5.c delete mode 100644 protocols/md5.h delete mode 100644 protocols/proxy.c delete mode 100644 protocols/proxy.h delete mode 100644 protocols/sha.c delete mode 100644 protocols/sha.h delete mode 100644 protocols/ssl_bogus.c delete mode 100644 protocols/ssl_client.h delete mode 100644 protocols/ssl_gnutls.c delete mode 100644 protocols/ssl_nss.c delete mode 100644 protocols/ssl_openssl.c delete mode 100644 url.c delete mode 100644 url.h delete mode 100644 util.c delete mode 100644 util.h diff --git a/Makefile b/Makefile index af710d59..73fee984 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,9 @@ -include Makefile.settings # Program variables -objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o url.o user.o util.o +objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o user.o headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h -subdirs = protocols +subdirs = protocols lib objects += $(LDAP_OBJ) diff --git a/bitlbee.h b/bitlbee.h index 709856d8..1462316f 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -129,7 +129,7 @@ extern char *CONF_FILE; #include "help.h" #include "query.h" #include "sock.h" -#include "util.h" +#include "misc.h" #include "proxy.h" typedef struct global { diff --git a/conf.c b/conf.c index 3154eb9c..d8b8be72 100644 --- a/conf.c +++ b/conf.c @@ -33,7 +33,7 @@ #include "url.h" #include "ipc.h" -#include "protocols/proxy.h" +#include "proxy.h" char *CONF_FILE; diff --git a/configure b/configure index 05fb7cb4..3a333029 100755 --- a/configure +++ b/configure @@ -143,7 +143,7 @@ else echo 'CFLAGS=-O3' >> Makefile.settings fi -echo CFLAGS+=-I`pwd` -I`pwd`/protocols -I. >> Makefile.settings +echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings diff --git a/ini.c b/ini.c deleted file mode 100644 index c63a132e..00000000 --- a/ini.c +++ /dev/null @@ -1,90 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2005 Wilmer van der Gaast and others * - \********************************************************************/ - -/* INI file reading code */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ -#define BITLBEE_CORE -#include "bitlbee.h" - -ini_t *ini_open( char *file ) -{ - ini_t *ini = g_new0( ini_t, 1 ); - - if( ( ini->fp = fopen( file, "r" ) ) == NULL ) - { - g_free( ini ); - return( NULL ); - } - - return( ini ); -} - -int ini_read( ini_t *file ) -{ - char key[MAX_STRING], s[MAX_STRING], *t; - int i; - - while( !feof( file->fp ) ) - { - *s = 0; - fscanf( file->fp, "%127[^\n#]s", s ); - fscanf( file->fp, "%*[^\n]s" ); - fgetc( file->fp ); /* Skip newline */ - file->line ++; - if( strchr( s, '=' ) ) - { - sscanf( s, "%[^ =]s", key ); - if( ( t = strchr( key, '.' ) ) ) - { - *t = 0; - strcpy( file->section, key ); - t ++; - } - else - { - strcpy( file->section, file->c_section ); - t = key; - } - sscanf( t, "%s", file->key ); - t = strchr( s, '=' ) + 1; - for( i = 0; t[i] == ' '; i ++ ); - strcpy( file->value, &t[i] ); - for( i = strlen( file->value ) - 1; file->value[i] == 32; i -- ) - file->value[i] = 0; - - return( 1 ); - } - else if( ( t = strchr( s, '[' ) ) ) - { - strcpy( file->c_section, t + 1 ); - t = strchr( file->c_section, ']' ); - *t = 0; - } - } - return( 0 ); -} - -void ini_close( ini_t *file ) -{ - fclose( file->fp ); - g_free( file ); -} diff --git a/ini.h b/ini.h deleted file mode 100644 index 5eab472b..00000000 --- a/ini.h +++ /dev/null @@ -1,43 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* INI file reading code */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef _INI_H -#define _INI_H - -typedef struct -{ - FILE *fp; - int line; - char c_section[MAX_STRING]; - char section[MAX_STRING]; - char key[MAX_STRING]; - char value[MAX_STRING]; -} ini_t; - -ini_t *ini_open( char *file ); -int ini_read( ini_t *file ); -void ini_close( ini_t *file ); - -#endif diff --git a/irc_commands.c b/irc_commands.c index f410bb52..3bb24fdb 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -320,7 +320,7 @@ static void irc_cmd_userhost( irc_t *irc, char **cmd ) static void irc_cmd_ison( irc_t *irc, char **cmd ) { user_t *u; - char buff[IRC_MAX_LINE], *s; + char buff[IRC_MAX_LINE]; int lenleft, i; buff[0] = '\0'; diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 00000000..80cdd9a5 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,37 @@ +########################### +## Makefile for BitlBee ## +## ## +## Copyright 2006 Lintux ## +########################### + +### DEFINITIONS + +-include ../Makefile.settings + +# [SH] Program variables +objects = $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o + +CFLAGS += -Wall +LFLAGS += -r + +# [SH] Phony targets +all: lib.o + +.PHONY: all clean distclean + +clean: $(subdirs) + rm -f *.o $(OUTFILE) core + +distclean: clean $(subdirs) + +### MAIN PROGRAM + +lib.o: $(objects) $(subdirs) + @echo '*' Linking lib.o + @$(LD) $(LFLAGS) $(objects) -o lib.o + +$(objects): ../Makefile.settings Makefile + +$(objects): %.o: %.c + @echo '*' Compiling $< + @$(CC) -c $(CFLAGS) $< -o $@ diff --git a/lib/events.h b/lib/events.h new file mode 100644 index 00000000..781fca6a --- /dev/null +++ b/lib/events.h @@ -0,0 +1,66 @@ +/* + * nogaim + * + * Copyright (C) 2006 Wilmer van der Gaast and others + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + * + */ + +/* + * Split off the event handling things from proxy.[ch] (and adding timer + * stuff. This to allow BitlBee to use other libs than GLib for event + * handling. + */ + + +#ifndef _EVENTS_H_ +#define _EVENTS_H_ + +#include +#ifndef _WIN32 +#include +#include +#include +#endif +#include +#include + +typedef enum { + GAIM_INPUT_READ = 1 << 1, + GAIM_INPUT_WRITE = 1 << 2 +} b_input_condition; +typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); + +#define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) +#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) +#define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) + +// #define event_debug( x... ) printf( x ) +#define event_debug( x... ) + +G_MODULE_EXPORT void b_main_init(); +G_MODULE_EXPORT void b_main_run(); +G_MODULE_EXPORT void b_main_quit(); + +G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data); +G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data); +G_MODULE_EXPORT void b_event_remove(gint id); + +#ifdef EVENTS_LIBEVENT +G_MODULE_EXPORT void closesocket(int fd); +#endif + +#endif /* _EVENTS_H_ */ diff --git a/lib/events_glib.c b/lib/events_glib.c new file mode 100644 index 00000000..620720cd --- /dev/null +++ b/lib/events_glib.c @@ -0,0 +1,137 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2006 Wilmer van der Gaast and others * + \********************************************************************/ + +/* + * Event handling (using GLib) + */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#else +#include "sock.h" +#define ETIMEDOUT WSAETIMEDOUT +#define EINPROGRESS WSAEINPROGRESS +#endif +#include +#include +#include "proxy.h" + +typedef struct _GaimIOClosure { + b_event_handler function; + guint result; + gpointer data; +} GaimIOClosure; + +static GMainLoop *loop; + +void b_main_init() +{ + loop = g_main_new( FALSE ); +} + +void b_main_run() +{ + g_main_run( loop ); +} + +void b_main_quit() +{ + g_main_quit( loop ); +} + +static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) +{ + GaimIOClosure *closure = data; + b_input_condition gaim_cond = 0; + gboolean st; + + if (condition & GAIM_READ_COND) + gaim_cond |= GAIM_INPUT_READ; + if (condition & GAIM_WRITE_COND) + gaim_cond |= GAIM_INPUT_WRITE; + + event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data ); + + st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); + + if( !st ) + event_debug( "Returned FALSE, cancelling.\n" ); + + return st; +} + +static void gaim_io_destroy(gpointer data) +{ + event_debug( "gaim_io_destroy( 0x%x )\n", data ); + g_free(data); +} + +gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data) +{ + GaimIOClosure *closure = g_new0(GaimIOClosure, 1); + GIOChannel *channel; + GIOCondition cond = 0; + + closure->function = function; + closure->data = data; + + if (condition & GAIM_INPUT_READ) + cond |= GAIM_READ_COND; + if (condition & GAIM_INPUT_WRITE) + cond |= GAIM_WRITE_COND; + + channel = g_io_channel_unix_new(source); + closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + gaim_io_invoke, closure, gaim_io_destroy); + + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure ); + + g_io_channel_unref(channel); + return closure->result; +} + +gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) +{ + gint st = g_timeout_add(timeout, func, data); + + event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st ); + + return st; +} + +void b_event_remove(gint tag) +{ + event_debug( "b_event_remove( %d )\n", tag ); + + if (tag > 0) + g_source_remove(tag); +} diff --git a/lib/events_libevent.c b/lib/events_libevent.c new file mode 100644 index 00000000..1119c2ab --- /dev/null +++ b/lib/events_libevent.c @@ -0,0 +1,247 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2006 Wilmer van der Gaast and others * + \********************************************************************/ + +/* + * Event handling (using libevent) + */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include +#include +#include +#include +#include +#include "proxy.h" + +#include +#include + +static guint id_next; +static GHashTable *id_hash; +static int quitting = 0; + +/* Since libevent doesn't handle two event handlers for one fd-condition + very well (which happens sometimes when BitlBee changes event handlers + for a combination), let's buid some indexes so we can delete them here + already, just in time. */ +static GHashTable *read_hash; +static GHashTable *write_hash; + +struct b_event_data +{ + guint id; + struct event evinfo; + gint timeout; + b_event_handler function; + void *data; +}; + +void b_main_init() +{ + event_init(); + + id_next = 1; + id_hash = g_hash_table_new( g_int_hash, g_int_equal ); + read_hash = g_hash_table_new( g_int_hash, g_int_equal ); + write_hash = g_hash_table_new( g_int_hash, g_int_equal ); +} + +void b_main_run() +{ + event_dispatch(); +} + +void b_main_quit() +{ + struct timeval tv; + + /* libevent sometimes generates events before really quitting, + we want to stop them. */ + quitting = 1; + + memset( &tv, 0, sizeof( struct timeval ) ); + event_loopexit( &tv ); +} + +static void b_event_passthrough( int fd, short event, void *data ) +{ + struct b_event_data *b_ev = data; + b_input_condition cond = 0; + int id; + + if( fd >= 0 ) + { + if( event & EV_READ ) + cond |= GAIM_INPUT_READ; + if( event & EV_WRITE ) + cond |= GAIM_INPUT_WRITE; + } + + event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); + + /* Since the called function might cancel this handler already + (which free()s b_ev, we have to remember the ID here. */ + id = b_ev->id; + + if( quitting ) + { + b_event_remove( id ); + return; + } + + if( !b_ev->function( b_ev->data, fd, cond ) ) + { + event_debug( "Handler returned FALSE: " ); + b_event_remove( id ); + } + else if( fd == -1 ) + { + struct timeval tv; + + tv.tv_sec = b_ev->timeout / 1000; + tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000; + + evtimer_add( &b_ev->evinfo, &tv ); + } +} + +gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) +{ + struct b_event_data *b_ev; + + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); + + if( ( condition & GAIM_INPUT_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || + ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) + { + /* We'll stick with this libevent entry, but give it a new BitlBee id. */ + g_hash_table_remove( id_hash, &b_ev->id ); + + event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next ); + + b_ev->id = id_next++; + b_ev->function = function; + b_ev->data = data; + } + else + { + GIOCondition out_cond; + + event_debug( "(new) = %d\n", id_next ); + + b_ev = g_new0( struct b_event_data, 1 ); + b_ev->id = id_next++; + b_ev->function = function; + b_ev->data = data; + + out_cond = EV_PERSIST; + if( condition & GAIM_INPUT_READ ) + out_cond |= EV_READ; + if( condition & GAIM_INPUT_WRITE ) + out_cond |= EV_WRITE; + + event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); + event_add( &b_ev->evinfo, NULL ); + + if( out_cond & EV_READ ) + g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev ); + if( out_cond & EV_WRITE ) + g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev ); + } + + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); + return b_ev->id; +} + +/* TODO: Persistence for timers! */ +gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) +{ + struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); + struct timeval tv; + + b_ev->id = id_next++; + b_ev->timeout = timeout; + b_ev->function = function; + b_ev->data = data; + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); + evtimer_add( &b_ev->evinfo, &tv ); + + event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); + + g_hash_table_insert( id_hash, &b_ev->id, b_ev ); + + return b_ev->id; +} + +void b_event_remove( gint id ) +{ + struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id ); + + event_debug( "b_event_remove( %d )\n", id ); + if( b_ev ) + { + g_hash_table_remove( id_hash, &b_ev->id ); + if( b_ev->evinfo.ev_fd >= 0 ) + { + if( b_ev->evinfo.ev_events & EV_READ ) + g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd ); + if( b_ev->evinfo.ev_events & EV_WRITE ) + g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd ); + } + + event_del( &b_ev->evinfo ); + g_free( b_ev ); + } + else + { + event_debug( "Already removed?\n" ); + } +} + +void closesocket( int fd ) +{ + struct b_event_data *b_ev; + + /* Since epoll() (the main reason we use libevent) automatically removes sockets from + the epoll() list when a socket gets closed and some modules have a habit of + closing sockets before removing event handlers, our and libevent's administration + get a little bit messed up. So this little function will remove the handlers + properly before closing a socket. */ + + if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) + { + event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); + b_event_remove( b_ev->id ); + } + if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) + { + event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); + b_event_remove( b_ev->id ); + } + + close( fd ); +} diff --git a/lib/http_client.c b/lib/http_client.c new file mode 100644 index 00000000..b00fcf98 --- /dev/null +++ b/lib/http_client.c @@ -0,0 +1,453 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* HTTP(S) module */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include "http_client.h" +#include "url.h" +#include "sock.h" + + +static gboolean http_connected( gpointer data, int source, b_input_condition cond ); +static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ); +static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); + + +void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) +{ + struct http_request *req; + int error = 0; + + req = g_new0( struct http_request, 1 ); + + if( ssl ) + { + req->ssl = ssl_connect( host, port, http_ssl_connected, req ); + if( req->ssl == NULL ) + error = 1; + } + else + { + req->fd = proxy_connect( host, port, http_connected, req ); + if( req->fd < 0 ) + error = 1; + } + + if( error ) + { + g_free( req ); + return( NULL ); + } + + req->func = func; + req->data = data; + req->request = g_strdup( request ); + req->request_length = strlen( request ); + + return( req ); +} + +void *http_dorequest_url( char *url_string, http_input_function func, gpointer data ) +{ + url_t *url = g_new0( url_t, 1 ); + char *request; + void *ret; + + if( !url_set( url, url_string ) ) + { + g_free( url ); + return NULL; + } + + if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS ) + { + g_free( url ); + return NULL; + } + + request = g_strdup_printf( "GET %s HTTP/1.0\r\n" + "Host: %s\r\n" + "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" + "\r\n", url->file, url->host ); + + ret = http_dorequest( url->host, url->port, + url->proto == PROTO_HTTPS, request, func, data ); + + g_free( url ); + g_free( request ); + return ret; +} + +/* This one is actually pretty simple... Might get more calls if we can't write + the whole request at once. */ +static gboolean http_connected( gpointer data, int source, b_input_condition cond ) +{ + struct http_request *req = data; + int st; + + if( source < 0 ) + goto error; + + if( req->inpa > 0 ) + b_event_remove( req->inpa ); + + sock_make_nonblocking( req->fd ); + + if( req->ssl ) + { + st = ssl_write( req->ssl, req->request + req->bytes_written, + req->request_length - req->bytes_written ); + if( st < 0 ) + { + if( ssl_errno != SSL_AGAIN ) + { + ssl_disconnect( req->ssl ); + goto error; + } + } + } + else + { + st = write( source, req->request + req->bytes_written, + req->request_length - req->bytes_written ); + if( st < 0 ) + { + if( !sockerr_again() ) + { + closesocket( req->fd ); + goto error; + } + } + } + + if( st > 0 ) + req->bytes_written += st; + + if( req->bytes_written < req->request_length ) + req->inpa = b_input_add( source, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE, + http_connected, req ); + else + req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req ); + + return FALSE; + +error: + req->status_string = g_strdup( "Error while writing HTTP request" ); + + req->func( req ); + + g_free( req->request ); + g_free( req ); + + return FALSE; +} + +static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ) +{ + struct http_request *req = data; + + if( source == NULL ) + return http_connected( data, -1, cond ); + + req->fd = ssl_getfd( source ); + + return http_connected( data, req->fd, cond ); +} + +static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) +{ + struct http_request *req = data; + int evil_server = 0; + char buffer[2048]; + char *end1, *end2; + int st; + + if( req->inpa > 0 ) + b_event_remove( req->inpa ); + + if( req->ssl ) + { + st = ssl_read( req->ssl, buffer, sizeof( buffer ) ); + if( st < 0 ) + { + if( ssl_errno != SSL_AGAIN ) + { + /* goto cleanup; */ + + /* YAY! We have to deal with crappy Microsoft + servers that LOVE to send invalid TLS + packets that abort connections! \o/ */ + + goto got_reply; + } + } + else if( st == 0 ) + { + goto got_reply; + } + } + else + { + st = read( req->fd, buffer, sizeof( buffer ) ); + if( st < 0 ) + { + if( !sockerr_again() ) + { + req->status_string = g_strdup( strerror( errno ) ); + goto cleanup; + } + } + else if( st == 0 ) + { + goto got_reply; + } + } + + if( st > 0 ) + { + req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 ); + memcpy( req->reply_headers + req->bytes_read, buffer, st ); + req->bytes_read += st; + } + + /* There will be more! */ + req->inpa = b_input_add( req->fd, + req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ, + http_incoming_data, req ); + + return FALSE; + +got_reply: + /* Maybe if the webserver is overloaded, or when there's bad SSL + support... */ + if( req->bytes_read == 0 ) + { + req->status_string = g_strdup( "Empty HTTP reply" ); + goto cleanup; + } + + /* Zero termination is very convenient. */ + req->reply_headers[req->bytes_read] = 0; + + /* Find the separation between headers and body, and keep stupid + webservers in mind. */ + end1 = strstr( req->reply_headers, "\r\n\r\n" ); + end2 = strstr( req->reply_headers, "\n\n" ); + + if( end2 && end2 < end1 ) + { + end1 = end2 + 1; + evil_server = 1; + } + else if( end1 ) + { + end1 += 2; + } + else + { + req->status_string = g_strdup( "Malformed HTTP reply" ); + goto cleanup; + } + + *end1 = 0; + + if( evil_server ) + req->reply_body = end1 + 1; + else + req->reply_body = end1 + 2; + + req->body_size = req->reply_headers + req->bytes_read - req->reply_body; + + if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) + { + if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 ) + { + req->status_string = g_strdup( "Can't parse status code" ); + req->status_code = -1; + } + else + { + char *eol; + + if( evil_server ) + eol = strchr( end1, '\n' ); + else + eol = strchr( end1, '\r' ); + + req->status_string = g_strndup( end1 + 1, eol - end1 - 1 ); + + /* Just to be sure... */ + if( ( eol = strchr( req->status_string, '\r' ) ) ) + *eol = 0; + if( ( eol = strchr( req->status_string, '\n' ) ) ) + *eol = 0; + } + } + else + { + req->status_string = g_strdup( "Can't locate status code" ); + req->status_code = -1; + } + + if( req->status_code == 301 || req->status_code == 302 ) + { + char *loc, *new_request, *new_host; + int error = 0, new_port, new_proto; + + /* We might fill it again, so let's not leak any memory. */ + g_free( req->status_string ); + req->status_string = NULL; + + loc = strstr( req->reply_headers, "\nLocation: " ); + if( loc == NULL ) /* We can't handle this redirect... */ + { + req->status_string = g_strdup( "Can't locate Location: header" ); + goto cleanup; + } + + loc += 11; + while( *loc == ' ' ) + loc ++; + + /* TODO/FIXME: Possibly have to handle relative redirections, + and rewrite Host: headers. Not necessary for now, it's + enough for passport authentication like this. */ + + if( *loc == '/' ) + { + /* Just a different pathname... */ + + /* Since we don't cache the servername, and since we + don't need this yet anyway, I won't implement it. */ + + req->status_string = g_strdup( "Can't handle recursive redirects" ); + + goto cleanup; + } + else + { + /* A whole URL */ + url_t *url; + char *s; + + s = strstr( loc, "\r\n" ); + if( s == NULL ) + goto cleanup; + + url = g_new0( url_t, 1 ); + *s = 0; + + if( !url_set( url, loc ) ) + { + req->status_string = g_strdup( "Malformed redirect URL" ); + g_free( url ); + goto cleanup; + } + + /* Okay, this isn't fun! We have to rebuild the request... :-( */ + new_request = g_malloc( req->request_length + strlen( url->file ) ); + + /* So, now I just allocated enough memory, so I'm + going to use strcat(), whether you like it or not. :-) */ + + sprintf( new_request, "GET %s HTTP/1.0", url->file ); + + s = strstr( req->request, "\r\n" ); + if( s == NULL ) + { + req->status_string = g_strdup( "Error while rebuilding request string" ); + g_free( new_request ); + g_free( url ); + goto cleanup; + } + + strcat( new_request, s ); + new_host = g_strdup( url->host ); + new_port = url->port; + new_proto = url->proto; + + g_free( url ); + } + + if( req->ssl ) + ssl_disconnect( req->ssl ); + else + closesocket( req->fd ); + + req->fd = -1; + req->ssl = NULL; + + if( new_proto == PROTO_HTTPS ) + { + req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req ); + if( req->ssl == NULL ) + error = 1; + } + else + { + req->fd = proxy_connect( new_host, new_port, http_connected, req ); + if( req->fd < 0 ) + error = 1; + } + g_free( new_host ); + + if( error ) + { + req->status_string = g_strdup( "Connection problem during redirect" ); + g_free( new_request ); + goto cleanup; + } + + g_free( req->request ); + g_free( req->reply_headers ); + req->request = new_request; + req->request_length = strlen( new_request ); + req->bytes_read = req->bytes_written = req->inpa = 0; + req->reply_headers = req->reply_body = NULL; + + return FALSE; + } + + /* Assume that a closed connection means we're finished, this indeed + breaks with keep-alive connections and faulty connections. */ + req->finished = 1; + +cleanup: + if( req->ssl ) + ssl_disconnect( req->ssl ); + else + closesocket( req->fd ); + + req->func( req ); + + g_free( req->request ); + g_free( req->reply_headers ); + g_free( req->status_string ); + g_free( req ); + + return FALSE; +} diff --git a/lib/http_client.h b/lib/http_client.h new file mode 100644 index 00000000..50ee80cf --- /dev/null +++ b/lib/http_client.h @@ -0,0 +1,57 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* HTTP(S) module */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include "ssl_client.h" + +struct http_request; + +typedef void (*http_input_function)( struct http_request * ); + +struct http_request +{ + char *request; + int request_length; + int status_code; + char *status_string; + char *reply_headers; + char *reply_body; + int body_size; + int finished; + + void *ssl; + int fd; + + int inpa; + int bytes_written; + int bytes_read; + + http_input_function func; + gpointer data; +}; + +void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); +void *http_dorequest_url( char *url_string, http_input_function func, gpointer data ); diff --git a/lib/ini.c b/lib/ini.c new file mode 100644 index 00000000..c63a132e --- /dev/null +++ b/lib/ini.c @@ -0,0 +1,90 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* INI file reading code */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ +#define BITLBEE_CORE +#include "bitlbee.h" + +ini_t *ini_open( char *file ) +{ + ini_t *ini = g_new0( ini_t, 1 ); + + if( ( ini->fp = fopen( file, "r" ) ) == NULL ) + { + g_free( ini ); + return( NULL ); + } + + return( ini ); +} + +int ini_read( ini_t *file ) +{ + char key[MAX_STRING], s[MAX_STRING], *t; + int i; + + while( !feof( file->fp ) ) + { + *s = 0; + fscanf( file->fp, "%127[^\n#]s", s ); + fscanf( file->fp, "%*[^\n]s" ); + fgetc( file->fp ); /* Skip newline */ + file->line ++; + if( strchr( s, '=' ) ) + { + sscanf( s, "%[^ =]s", key ); + if( ( t = strchr( key, '.' ) ) ) + { + *t = 0; + strcpy( file->section, key ); + t ++; + } + else + { + strcpy( file->section, file->c_section ); + t = key; + } + sscanf( t, "%s", file->key ); + t = strchr( s, '=' ) + 1; + for( i = 0; t[i] == ' '; i ++ ); + strcpy( file->value, &t[i] ); + for( i = strlen( file->value ) - 1; file->value[i] == 32; i -- ) + file->value[i] = 0; + + return( 1 ); + } + else if( ( t = strchr( s, '[' ) ) ) + { + strcpy( file->c_section, t + 1 ); + t = strchr( file->c_section, ']' ); + *t = 0; + } + } + return( 0 ); +} + +void ini_close( ini_t *file ) +{ + fclose( file->fp ); + g_free( file ); +} diff --git a/lib/ini.h b/lib/ini.h new file mode 100644 index 00000000..5eab472b --- /dev/null +++ b/lib/ini.h @@ -0,0 +1,43 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* INI file reading code */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _INI_H +#define _INI_H + +typedef struct +{ + FILE *fp; + int line; + char c_section[MAX_STRING]; + char section[MAX_STRING]; + char key[MAX_STRING]; + char value[MAX_STRING]; +} ini_t; + +ini_t *ini_open( char *file ); +int ini_read( ini_t *file ); +void ini_close( ini_t *file ); + +#endif diff --git a/lib/md5.c b/lib/md5.c new file mode 100644 index 00000000..e6273585 --- /dev/null +++ b/lib/md5.c @@ -0,0 +1,392 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" +#include + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/lib/md5.h b/lib/md5.h new file mode 100644 index 00000000..f24f2ff1 --- /dev/null +++ b/lib/md5.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2004-03-09 Jelmer Vernooij add G_MODULE_EXPORT for Bitlbee + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +#include +#include + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +G_MODULE_EXPORT void md5_init(md5_state_t *pms); + +/* Append a string to the message. */ +G_MODULE_EXPORT void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + +/* Finish the message and return the digest. */ +G_MODULE_EXPORT void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/lib/misc.c b/lib/misc.c new file mode 100644 index 00000000..d8d6a4c7 --- /dev/null +++ b/lib/misc.c @@ -0,0 +1,481 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* + * Various utility functions. Some are copied from Gaim to support the + * IM-modules, most are from BitlBee. + * + * Copyright (C) 1998-1999, Mark Spencer + * (and possibly other members of the Gaim team) + * Copyright 2002-2005 Wilmer van der Gaast + */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "nogaim.h" +#include +#include +#include +#include +#include +#include + +void strip_linefeed(gchar *text) +{ + int i, j; + gchar *text2 = g_malloc(strlen(text) + 1); + + for (i = 0, j = 0; text[i]; i++) + if (text[i] != '\r') + text2[j++] = text[i]; + text2[j] = '\0'; + + strcpy(text, text2); + g_free(text2); +} + +char *add_cr(char *text) +{ + char *ret = NULL; + int count = 0, j; + unsigned int i; + + if (text[0] == '\n') + count++; + for (i = 1; i < strlen(text); i++) + if (text[i] == '\n' && text[i - 1] != '\r') + count++; + + if (count == 0) + return g_strdup(text); + + ret = g_malloc0(strlen(text) + count + 1); + + i = 0; j = 0; + if (text[i] == '\n') + ret[j++] = '\r'; + ret[j++] = text[i++]; + for (; i < strlen(text); i++) { + if (text[i] == '\n' && text[i - 1] != '\r') + ret[j++] = '\r'; + ret[j++] = text[i]; + } + + return ret; +} + +char *tobase64(const char *text) +{ + char *out; + int len; + + len = strlen(text); + out = g_malloc((len + 2) /* the == padding */ + / 3 /* every 3-byte block */ + * 4 /* becomes a 4-byte one */ + + 1); /* and of course, ASCIIZ! */ + + base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); + + return out; +} + +void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits) +{ + for (; inlen >= 3; inlen -= 3) + { + *out++ = b64digits[in[0] >> 2]; + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)]; + *out++ = b64digits[in[2] & 0x3f]; + in += 3; + } + if (inlen > 0) + { + *out++ = b64digits[in[0] >> 2]; + if (inlen > 1) + { + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[((in[1]<<2) & 0x3c)]; + } + else + { + *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + *out++ = b64digits[64]; + } + *out++ = b64digits[64]; + } + *out = '\0'; +} + +char *normalize(const char *s) +{ + static char buf[BUF_LEN]; + char *t, *u; + int x = 0; + + g_return_val_if_fail((s != NULL), NULL); + + u = t = g_strdup(s); + + strcpy(t, s); + g_strdown(t); + + while (*t && (x < BUF_LEN - 1)) { + if (*t != ' ') { + buf[x] = *t; + x++; + } + t++; + } + buf[x] = '\0'; + g_free(u); + return buf; +} + +time_t get_time(int year, int month, int day, int hour, int min, int sec) +{ + struct tm tm; + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; + return mktime(&tm); +} + +typedef struct htmlentity +{ + char code[8]; + char is[4]; +} htmlentity_t; + +/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */ + +static const htmlentity_t ent[] = +{ + { "lt", "<" }, + { "gt", ">" }, + { "amp", "&" }, + { "quot", "\"" }, + { "aacute", "รก" }, + { "eacute", "รฉ" }, + { "iacute", "รฉ" }, + { "oacute", "รณ" }, + { "uacute", "รบ" }, + { "agrave", "ร " }, + { "egrave", "รจ" }, + { "igrave", "รฌ" }, + { "ograve", "รฒ" }, + { "ugrave", "รน" }, + { "acirc", "รข" }, + { "ecirc", "รช" }, + { "icirc", "รฎ" }, + { "ocirc", "รด" }, + { "ucirc", "รป" }, + { "auml", "รค" }, + { "euml", "รซ" }, + { "iuml", "รฏ" }, + { "ouml", "รถ" }, + { "uuml", "รผ" }, + { "nbsp", " " }, + { "", "" } +}; + +void strip_html( char *in ) +{ + char *start = in; + char *out = g_malloc( strlen( in ) + 1 ); + char *s = out, *cs; + int i, matched; + + memset( out, 0, strlen( in ) + 1 ); + + while( *in ) + { + if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) ) + { + /* If in points at a < and in+1 points at a letter or a slash, this is probably + a HTML-tag. Try to find a closing > and continue there. If the > can't be + found, assume that it wasn't a HTML-tag after all. */ + + cs = in; + + while( *in && *in != '>' ) + in ++; + + if( *in ) + { + if( g_strncasecmp( cs+1, "br", 2) == 0 ) + *(s++) = '\n'; + in ++; + } + else + { + in = cs; + *(s++) = *(in++); + } + } + else if( *in == '&' ) + { + cs = ++in; + while( *in && isalpha( *in ) ) + in ++; + + if( *in == ';' ) in ++; + matched = 0; + + for( i = 0; *ent[i].code; i ++ ) + if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 ) + { + int j; + + for( j = 0; ent[i].is[j]; j ++ ) + *(s++) = ent[i].is[j]; + + matched = 1; + break; + } + + /* None of the entities were matched, so return the string */ + if( !matched ) + { + in = cs - 1; + *(s++) = *(in++); + } + } + else + { + *(s++) = *(in++); + } + } + + strcpy( start, out ); + g_free( out ); +} + +char *escape_html( const char *html ) +{ + const char *c = html; + GString *ret; + char *str; + + if( html == NULL ) + return( NULL ); + + ret = g_string_new( "" ); + + while( *c ) + { + switch( *c ) + { + case '&': + ret = g_string_append( ret, "&" ); + break; + case '<': + ret = g_string_append( ret, "<" ); + break; + case '>': + ret = g_string_append( ret, ">" ); + break; + case '"': + ret = g_string_append( ret, """ ); + break; + default: + ret = g_string_append_c( ret, *c ); + } + c ++; + } + + str = ret->str; + g_string_free( ret, FALSE ); + return( str ); +} + +void info_string_append(GString *str, char *newline, char *name, char *value) +{ + if( value && value[0] ) + g_string_sprintfa( str, "%s%s: %s", newline, name, value ); +} + +/* Decode%20a%20file%20name */ +void http_decode( char *s ) +{ + char *t; + int i, j, k; + + t = g_new( char, strlen( s ) + 1 ); + + for( i = j = 0; s[i]; i ++, j ++ ) + { + if( s[i] == '%' ) + { + if( sscanf( s + i + 1, "%2x", &k ) ) + { + t[j] = k; + i += 2; + } + else + { + *t = 0; + break; + } + } + else + { + t[j] = s[i]; + } + } + t[j] = 0; + + strcpy( s, t ); + g_free( t ); +} + +/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */ +/* This fuction is safe, but make sure you call it safely as well! */ +void http_encode( char *s ) +{ + char *t; + int i, j; + + t = g_strdup( s ); + + for( i = j = 0; t[i]; i ++, j ++ ) + { + /* if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' ) */ + if( !isalnum( t[i] ) ) + { + sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] ); + j += 2; + } + else + { + s[j] = t[i]; + } + } + s[j] = 0; + + g_free( t ); +} + +/* Strip newlines from a string. Modifies the string passed to it. */ +char *strip_newlines( char *source ) +{ + int i; + + for( i = 0; source[i] != '\0'; i ++ ) + if( source[i] == '\n' || source[i] == '\r' ) + source[i] = ' '; + + return source; +} + +#ifdef IPV6 +/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */ +char *ipv6_wrap( char *src ) +{ + static char dst[64]; + int i; + + for( i = 0; src[i]; i ++ ) + if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) + break; + + /* Hmm, it's not even an IP... */ + if( src[i] ) + return src; + + g_snprintf( dst, sizeof( dst ), "::ffff:%s", src ); + + return dst; +} + +/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */ +char *ipv6_unwrap( char *src ) +{ + int i; + + if( g_strncasecmp( src, "::ffff:", 7 ) != 0 ) + return src; + + for( i = 7; src[i]; i ++ ) + if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) + break; + + /* Hmm, it's not even an IP... */ + if( src[i] ) + return src; + + return ( src + 7 ); +} +#endif + +/* Convert from one charset to another. + + from_cs, to_cs: Source and destination charsets + src, dst: Source and destination strings + size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though. + maxbuf: Maximum number of bytes to write to dst + + Returns the number of bytes written to maxbuf or -1 on an error. +*/ +signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ) +{ + GIConv cd; + size_t res; + size_t inbytesleft, outbytesleft; + char *inbuf = src; + char *outbuf = dst; + + cd = g_iconv_open( to_cs, from_cs ); + if( cd == (GIConv) -1 ) + return( -1 ); + + inbytesleft = size ? size : strlen( src ); + outbytesleft = maxbuf - 1; + res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + *outbuf = '\0'; + g_iconv_close( cd ); + + if( res == (size_t) -1 ) + return( -1 ); + else + return( outbuf - dst ); +} + +char *set_eval_charset( irc_t *irc, set_t *set, char *value ) +{ + GIConv cd; + + if ( g_strncasecmp( value, "none", 4 ) == 0 ) + return( value ); + + cd = g_iconv_open( "UTF-8", value ); + if( cd == (GIConv) -1 ) + return( NULL ); + + g_iconv_close( cd ); + return( value ); +} diff --git a/lib/misc.h b/lib/misc.h new file mode 100644 index 00000000..c7eec19b --- /dev/null +++ b/lib/misc.h @@ -0,0 +1,51 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Misc. functions */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _UTIL_H +#define _UTIL_H + +G_MODULE_EXPORT void strip_linefeed( gchar *text ); +G_MODULE_EXPORT char *add_cr( char *text ); +G_MODULE_EXPORT char *strip_newlines(char *source); +G_MODULE_EXPORT char *tobase64( const char *text ); +G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits ); +G_MODULE_EXPORT char *normalize( const char *s ); +G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value ); + +G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec ); +double gettime( void ); + +G_MODULE_EXPORT void strip_html( char *msg ); +G_MODULE_EXPORT char *escape_html( const char *html ); +G_MODULE_EXPORT void http_decode( char *s ); +G_MODULE_EXPORT void http_encode( char *s ); + +G_MODULE_EXPORT char *ipv6_wrap( char *src ); +G_MODULE_EXPORT char *ipv6_unwrap( char *src ); + +G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ); +char *set_eval_charset( irc_t *irc, set_t *set, char *value ); + +#endif diff --git a/lib/proxy.c b/lib/proxy.c new file mode 100644 index 00000000..b8aa304d --- /dev/null +++ b/lib/proxy.c @@ -0,0 +1,556 @@ +/* + * gaim + * + * Copyright (C) 1998-1999, Mark Spencer + * Copyright (C) 2002-2004, Wilmer van der Gaast, Jelmer Vernooij + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + * + */ + +#define BITLBEE_CORE +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#else +#include "sock.h" +#define ETIMEDOUT WSAETIMEDOUT +#define EINPROGRESS WSAEINPROGRESS +#endif +#include +#include +#include "nogaim.h" +#include "proxy.h" + +char proxyhost[128] = ""; +int proxyport = 0; +int proxytype = PROXY_NONE; +char proxyuser[128] = ""; +char proxypass[128] = ""; + +struct PHB { + b_event_handler func, proxy_func; + gpointer data, proxy_data; + char *host; + int port; + int fd; + gint inpa; +}; + + + +static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) +{ + static struct sockaddr_in sin; + + if (!inet_aton(host, &sin.sin_addr)) { + struct hostent *hp; + if (!(hp = gethostbyname(host))) { + return NULL; + } + memset(&sin, 0, sizeof(struct sockaddr_in)); + memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); + sin.sin_family = hp->h_addrtype; + } else + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + + return &sin; +} + +static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond) +{ + struct PHB *phb = data; + unsigned int len; + int error = ETIMEDOUT; + len = sizeof(error); + +#ifndef _WIN32 + if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + closesocket(source); + b_event_remove(phb->inpa); + if( phb->proxy_func ) + phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ); + else { + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb); + } + return FALSE; + } +#endif + sock_make_blocking(source); + b_event_remove(phb->inpa); + if( phb->proxy_func ) + phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ); + else { + phb->func(phb->data, source, GAIM_INPUT_READ); + g_free(phb); + } + + return FALSE; +} + +static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb) +{ + struct sockaddr_in *sin; + int fd = -1; + + if (!(sin = gaim_gethostbyname(host, port))) { + g_free(phb); + return -1; + } + + if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { + g_free(phb); + return -1; + } + + sock_make_nonblocking(fd); + + event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); + + if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { + if (sockerr_again()) { + phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); + phb->fd = fd; + } else { + closesocket(fd); + g_free(phb); + return -1; + } + } + + return fd; +} + + +/* Connecting to HTTP proxies */ + +#define HTTP_GOODSTRING "HTTP/1.0 200 Connection established" +#define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established" + +static gboolean http_canread(gpointer data, gint source, b_input_condition cond) +{ + int nlc = 0; + int pos = 0; + struct PHB *phb = data; + char inputline[8192]; + + b_event_remove(phb->inpa); + + while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { + if (inputline[pos - 1] == '\n') + nlc++; + else if (inputline[pos - 1] != '\r') + nlc = 0; + } + inputline[pos] = '\0'; + + if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) || + (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { + phb->func(phb->data, source, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + + return FALSE; +} + +static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond) +{ + char cmd[384]; + struct PHB *phb = data; + unsigned int len; + int error = ETIMEDOUT; + if (phb->inpa > 0) + b_event_remove(phb->inpa); + len = sizeof(error); + if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + sock_make_blocking(source); + + g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, + phb->host, phb->port); + if (send(source, cmd, strlen(cmd), 0) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + if (proxyuser && *proxyuser) { + char *t1, *t2; + t1 = g_strdup_printf("%s:%s", proxyuser, proxypass); + t2 = tobase64(t1); + g_free(t1); + g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); + g_free(t2); + if (send(source, cmd, strlen(cmd), 0) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + } + + g_snprintf(cmd, sizeof(cmd), "\r\n"); + if (send(source, cmd, strlen(cmd), 0) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb); + + return FALSE; +} + +static int proxy_connect_http(const char *host, unsigned short port, struct PHB *phb) +{ + phb->host = g_strdup(host); + phb->port = port; + phb->proxy_func = http_canwrite; + phb->proxy_data = phb; + + return( proxy_connect_none( proxyhost, proxyport, phb ) ); +} + + +/* Connecting to SOCKS4 proxies */ + +static gboolean s4_canread(gpointer data, gint source, b_input_condition cond) +{ + unsigned char packet[12]; + struct PHB *phb = data; + + b_event_remove(phb->inpa); + + memset(packet, 0, sizeof(packet)); + if (read(source, packet, 9) >= 4 && packet[1] == 90) { + phb->func(phb->data, source, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + + return FALSE; +} + +static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) +{ + unsigned char packet[12]; + struct hostent *hp; + struct PHB *phb = data; + unsigned int len; + int error = ETIMEDOUT; + if (phb->inpa > 0) + b_event_remove(phb->inpa); + len = sizeof(error); + if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + sock_make_blocking(source); + + /* XXX does socks4 not support host name lookups by the proxy? */ + if (!(hp = gethostbyname(phb->host))) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + packet[0] = 4; + packet[1] = 1; + packet[2] = phb->port >> 8; + packet[3] = phb->port & 0xff; + packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; + packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; + packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; + packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; + packet[8] = 0; + if (write(source, packet, 9) != 9) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb); + + return FALSE; +} + +static int proxy_connect_socks4(const char *host, unsigned short port, struct PHB *phb) +{ + phb->host = g_strdup(host); + phb->port = port; + phb->proxy_func = s4_canwrite; + phb->proxy_data = phb; + + return( proxy_connect_none( proxyhost, proxyport, phb ) ); +} + + +/* Connecting to SOCKS5 proxies */ + +static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond) +{ + unsigned char buf[512]; + struct PHB *phb = data; + + b_event_remove(phb->inpa); + + if (read(source, buf, 10) < 10) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + if ((buf[0] != 0x05) || (buf[1] != 0x00)) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + phb->func(phb->data, source, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + + return FALSE; +} + +static void s5_sendconnect(gpointer data, gint source) +{ + unsigned char buf[512]; + struct PHB *phb = data; + int hlen = strlen(phb->host); + + buf[0] = 0x05; + buf[1] = 0x01; /* CONNECT */ + buf[2] = 0x00; /* reserved */ + buf[3] = 0x03; /* address type -- host name */ + buf[4] = hlen; + memcpy(buf + 5, phb->host, hlen); + buf[5 + strlen(phb->host)] = phb->port >> 8; + buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; + + if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return; + } + + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); +} + +static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond) +{ + unsigned char buf[512]; + struct PHB *phb = data; + + b_event_remove(phb->inpa); + + if (read(source, buf, 2) < 2) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + if ((buf[0] != 0x01) || (buf[1] != 0x00)) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + s5_sendconnect(phb, source); + + return FALSE; +} + +static gboolean s5_canread(gpointer data, gint source, b_input_condition cond) +{ + unsigned char buf[512]; + struct PHB *phb = data; + + b_event_remove(phb->inpa); + + if (read(source, buf, 2) < 2) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + if ((buf[0] != 0x05) || (buf[1] == 0xff)) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + if (buf[1] == 0x02) { + unsigned int i = strlen(proxyuser), j = strlen(proxypass); + buf[0] = 0x01; /* version 1 */ + buf[1] = i; + memcpy(buf + 2, proxyuser, i); + buf[2 + i] = j; + memcpy(buf + 2 + i + 1, proxypass, j); + if (write(source, buf, 3 + i + j) < 3 + i + j) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); + } else { + s5_sendconnect(phb, source); + } + + return FALSE; +} + +static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) +{ + unsigned char buf[512]; + int i; + struct PHB *phb = data; + unsigned int len; + int error = ETIMEDOUT; + if (phb->inpa > 0) + b_event_remove(phb->inpa); + len = sizeof(error); + if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + sock_make_blocking(source); + + i = 0; + buf[0] = 0x05; /* SOCKS version 5 */ + if (proxyuser[0]) { + buf[1] = 0x02; /* two methods */ + buf[2] = 0x00; /* no authentication */ + buf[3] = 0x02; /* username/password authentication */ + i = 4; + } else { + buf[1] = 0x01; + buf[2] = 0x00; + i = 3; + } + + if (write(source, buf, i) < i) { + close(source); + phb->func(phb->data, -1, GAIM_INPUT_READ); + g_free(phb->host); + g_free(phb); + return FALSE; + } + + phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb); + + return FALSE; +} + +static int proxy_connect_socks5(const char *host, unsigned short port, struct PHB *phb) +{ + phb->host = g_strdup(host); + phb->port = port; + phb->proxy_func = s5_canwrite; + phb->proxy_data = phb; + + return( proxy_connect_none( proxyhost, proxyport, phb ) ); +} + + +/* Export functions */ + +int proxy_connect(const char *host, int port, b_event_handler func, gpointer data) +{ + struct PHB *phb; + + if (!host || !port || (port == -1) || !func || strlen(host) > 128) { + return -1; + } + + phb = g_new0(struct PHB, 1); + phb->func = func; + phb->data = data; + +#ifndef _WIN32 + sethostent(1); +#endif + + if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) + return proxy_connect_none(host, port, phb); + else if (proxytype == PROXY_HTTP) + return proxy_connect_http(host, port, phb); + else if (proxytype == PROXY_SOCKS4) + return proxy_connect_socks4(host, port, phb); + else if (proxytype == PROXY_SOCKS5) + return proxy_connect_socks5(host, port, phb); + + if (phb->host) g_free(phb); + g_free(phb); + return -1; +} diff --git a/lib/proxy.h b/lib/proxy.h new file mode 100644 index 00000000..680790a5 --- /dev/null +++ b/lib/proxy.h @@ -0,0 +1,53 @@ +/* + * nogaim + * + * Copyright (C) 1998-1999, Mark Spencer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU 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 + * + */ + +/* this is the export part of the proxy.c file. it does a little + prototype-ing stuff and redefine some net function to mask them + with some kind of transparent layer */ + +#ifndef _PROXY_H_ +#define _PROXY_H_ + +#include +#ifndef _WIN32 +#include +#include +#include +#endif +#include +#include + +#include "events.h" + +#define PROXY_NONE 0 +#define PROXY_HTTP 1 +#define PROXY_SOCKS4 2 +#define PROXY_SOCKS5 3 + +extern char proxyhost[128]; +extern int proxyport; +extern int proxytype; +extern char proxyuser[128]; +extern char proxypass[128]; + +G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data); + +#endif /* _PROXY_H_ */ diff --git a/lib/rc4.c b/lib/rc4.c new file mode 100644 index 00000000..3559f71e --- /dev/null +++ b/lib/rc4.c @@ -0,0 +1,179 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple (but secure) RC4 implementation for safer password storage. * +* * +* Copyright 2006 Wilmer van der Gaast * +* * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the 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. * +* * +\***************************************************************************/ + +/* + This file implements RC4-encryption, which will mainly be used to save IM + passwords safely in the new XML-format. Possibly other uses will come up + later. It's supposed to be quite reliable (thanks to the use of a 6-byte + IV/seed), certainly compared to the old format. The only realistic way to + crack BitlBee passwords now is to use a sniffer to get your hands on the + user's password. + + If you see that something's wrong in this implementation (I asked a + couple of people to look at it already, but who knows), please tell me. + + The reason I chose for RC4 is because it's pretty simple but effective, + so it will work without adding several KBs or an extra library dependency. +*/ + + +#include +#include +#include +#include "rc4.h" + +/* Add some seed to the password, to make sure we *never* use the same key. + This defines how many byes we use as a seed. */ +#define RC4_IV_LEN 6 + +/* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended + to shuffle S[] just a bit more before you start to use it. This defines how + many bytes we'll request before we'll really use them for encryption. */ +#define RC4_CYCLES 1024 + +struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ) +{ + struct rc4_state *st; + int i, j, tmp; + + st = g_malloc( sizeof( struct rc4_state ) ); + st->i = st->j = 0; + for( i = 0; i < 256; i ++ ) + st->S[i] = i; + + if( kl <= 0 ) + kl = strlen( (char*) key ); + + for( i = j = 0; i < 256; i ++ ) + { + j = ( j + st->S[i] + key[i%kl] ) & 0xff; + tmp = st->S[i]; + st->S[i] = st->S[j]; + st->S[j] = tmp; + } + + for( i = 0; i < cycles; i ++ ) + rc4_getbyte( st ); + + return st; +} + +/* + For those who don't know, RC4 is basically an algorithm that generates a + stream of bytes after you give it a key. Just get a byte from it and xor + it with your cleartext. To decrypt, just give it the same key again and + start xorring. + + The function above initializes the RC4 byte generator, the next function + can be used to get bytes from the generator (and shuffle things a bit). +*/ + +unsigned char rc4_getbyte( struct rc4_state *st ) +{ + unsigned char tmp; + + /* Unfortunately the st-> stuff doesn't really improve readability here... */ + st->i ++; + st->j += st->S[st->i]; + tmp = st->S[st->i]; + st->S[st->i] = st->S[st->j]; + st->S[st->j] = tmp; + + return st->S[(st->S[st->i] + st->S[st->j]) & 0xff]; +} + +/* + The following two functions can be used for reliable encryption and + decryption. Known plaintext attacks are prevented by adding some (6, + by default) random bytes to the password before setting up the RC4 + structures. These 6 bytes are also saved in the results, because of + course we'll need them in rc4_decode(). + + Because the length of the resulting string is unknown to the caller, + it should pass a char**. Since the encode/decode functions allocate + memory for the string, make sure the char** points at a NULL-pointer + (or at least to something you already free()d), or you'll leak + memory. And of course, don't forget to free() the result when you + don't need it anymore. + + Both functions return the number of bytes in the result string. +*/ + +int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ) +{ + struct rc4_state *st; + unsigned char *key; + int key_len, i; + + key_len = strlen( password ) + RC4_IV_LEN; + if( clear_len <= 0 ) + clear_len = strlen( (char*) clear ); + + /* Prepare buffers and the key + IV */ + *crypt = g_malloc( clear_len + RC4_IV_LEN ); + key = g_malloc( key_len ); + strcpy( (char*) key, password ); + for( i = 0; i < RC4_IV_LEN; i ++ ) + key[key_len-RC4_IV_LEN+i] = crypt[0][i] = rand() & 0xff; + + /* Generate the initial S[] from the IVed key. */ + st = rc4_keymaker( key, key_len, RC4_CYCLES ); + g_free( key ); + + for( i = 0; i < clear_len; i ++ ) + crypt[0][i+RC4_IV_LEN] = clear[i] ^ rc4_getbyte( st ); + + g_free( st ); + + return clear_len + RC4_IV_LEN; +} + +int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ) +{ + struct rc4_state *st; + unsigned char *key; + int key_len, clear_len, i; + + key_len = strlen( password ) + RC4_IV_LEN; + clear_len = crypt_len - RC4_IV_LEN; + + /* Prepare buffers and the key + IV */ + *clear = g_malloc( clear_len + 1 ); + key = g_malloc( key_len ); + strcpy( (char*) key, password ); + for( i = 0; i < RC4_IV_LEN; i ++ ) + key[key_len-RC4_IV_LEN+i] = crypt[i]; + + /* Generate the initial S[] from the IVed key. */ + st = rc4_keymaker( key, key_len, RC4_CYCLES ); + g_free( key ); + + for( i = 0; i < clear_len; i ++ ) + clear[0][i] = crypt[i+RC4_IV_LEN] ^ rc4_getbyte( st ); + clear[0][i] = 0; /* Nice to have for plaintexts. */ + + g_free( st ); + + return clear_len; +} diff --git a/lib/rc4.h b/lib/rc4.h new file mode 100644 index 00000000..8d50b508 --- /dev/null +++ b/lib/rc4.h @@ -0,0 +1,35 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple (but secure) RC4 implementation for safer password storage. * +* * +* Copyright 2006 Wilmer van der Gaast * +* * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the 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. * +* * +\***************************************************************************/ + + +struct rc4_state +{ + unsigned char S[256]; + unsigned char i, j; +}; + +struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ); +unsigned char rc4_getbyte( struct rc4_state *st ); +int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ); +int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ); diff --git a/lib/sha.c b/lib/sha.c new file mode 100644 index 00000000..895505a1 --- /dev/null +++ b/lib/sha.c @@ -0,0 +1,173 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is SHA 180-1 Reference Implementation (Compact version) + * + * The Initial Developer of the Original Code is Paul Kocher of + * Cryptography Research. Portions created by Paul Kocher are + * Copyright (C) 1995-9 by Cryptography Research, Inc. All + * Rights Reserved. + * + * Contributor(s): + * + */ + +#define BITLBEE_CORE +#include "nogaim.h" + +static void shaHashBlock(SHA_CTX *ctx); + +void shaInit(SHA_CTX *ctx) { + int i; + + ctx->lenW = 0; + ctx->sizeHi = ctx->sizeLo = 0; + + /* Initialize H with the magic constants (see FIPS180 for constants) + */ + ctx->H[0] = 0x67452301L; + ctx->H[1] = 0xefcdab89L; + ctx->H[2] = 0x98badcfeL; + ctx->H[3] = 0x10325476L; + ctx->H[4] = 0xc3d2e1f0L; + + for (i = 0; i < 80; i++) + ctx->W[i] = 0; +} + + +void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) { + int i; + + /* Read the data into W and process blocks as they get full + */ + for (i = 0; i < len; i++) { + ctx->W[ctx->lenW / 4] <<= 8; + ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i]; + if ((++ctx->lenW) % 64 == 0) { + shaHashBlock(ctx); + ctx->lenW = 0; + } + ctx->sizeLo += 8; + ctx->sizeHi += (ctx->sizeLo < 8); + } +} + + +void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) { + unsigned char pad0x80 = 0x80; + unsigned char pad0x00 = 0x00; + unsigned char padlen[8]; + int i; + + /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length + */ + padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); + padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); + padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); + padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); + padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); + padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); + padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); + padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); + shaUpdate(ctx, &pad0x80, 1); + while (ctx->lenW != 56) + shaUpdate(ctx, &pad0x00, 1); + shaUpdate(ctx, padlen, 8); + + /* Output hash + */ + for (i = 0; i < 20; i++) { + hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); + ctx->H[i / 4] <<= 8; + } + + /* + * Re-initialize the context (also zeroizes contents) + */ + shaInit(ctx); +} + + +void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { + SHA_CTX ctx; + + shaInit(&ctx); + shaUpdate(&ctx, dataIn, len); + shaFinal(&ctx, hashout); +} + + +#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL) + +static void shaHashBlock(SHA_CTX *ctx) { + int t; + guint32 A,B,C,D,E,TEMP; + + for (t = 16; t <= 79; t++) + ctx->W[t] = + SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + for (t = 0; t <= 19; t++) { + TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL; + E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; + } + for (t = 20; t <= 39; t++) { + TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL; + E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; + } + for (t = 40; t <= 59; t++) { + TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL; + E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; + } + for (t = 60; t <= 79; t++) { + TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL; + E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; + } + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + +/*---------------------------------------------------------------------------- + * + * This code added by Thomas "temas" Muldowney for Jabber compatability + * + *---------------------------------------------------------------------------*/ +char *shahash(char *str) +{ + static char final[41]; + char *pos; + unsigned char hashval[20]; + int x; + + if(!str || strlen(str) == 0) + return NULL; + + shaBlock((unsigned char *)str, strlen(str), hashval); + + pos = final; + for(x=0;x<20;x++) + { + g_snprintf(pos, 3, "%02x", hashval[x]); + pos += 2; + } + return (char *)final; +} diff --git a/lib/sha.h b/lib/sha.h new file mode 100644 index 00000000..e8152b1b --- /dev/null +++ b/lib/sha.h @@ -0,0 +1,21 @@ +#ifndef __SHA_H__ +#define __SHA_H__ + +#include + +G_MODULE_EXPORT int strprintsha(char *dest, int *hashval); + +typedef struct { + guint32 H[5]; + guint32 W[80]; + int lenW; + guint32 sizeHi,sizeLo; +} SHA_CTX; + +G_MODULE_EXPORT void shaInit(SHA_CTX *ctx); +G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); +G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); +G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); +G_MODULE_EXPORT char *shahash(char *str); + +#endif diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c new file mode 100644 index 00000000..00aaa7c4 --- /dev/null +++ b/lib/ssl_bogus.c @@ -0,0 +1,57 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* SSL module - dummy version */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ssl_client.h" + +int ssl_errno; + +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) +{ + return( NULL ); +} + +int ssl_read( void *conn, char *buf, int len ) +{ + return( -1 ); +} + +int ssl_write( void *conn, const char *buf, int len ) +{ + return( -1 ); +} + +void ssl_disconnect( void *conn_ ) +{ +} + +int ssl_getfd( void *conn ) +{ + return( -1 ); +} + +b_input_condition ssl_getdirection( void *conn ) +{ + return GAIM_INPUT_READ; +} diff --git a/lib/ssl_client.h b/lib/ssl_client.h new file mode 100644 index 00000000..1a9c79e9 --- /dev/null +++ b/lib/ssl_client.h @@ -0,0 +1,42 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* SSL module */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include "proxy.h" + +#define SSL_OK 0 +#define SSL_NOHANDSHAKE 1 +#define SSL_AGAIN 2 + +extern int ssl_errno; + +typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition); + +G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); +G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); +G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); +G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); +G_MODULE_EXPORT int ssl_getfd( void *conn ); +G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c new file mode 100644 index 00000000..3ebe1756 --- /dev/null +++ b/lib/ssl_gnutls.c @@ -0,0 +1,206 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* SSL module - GnuTLS version */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "proxy.h" +#include "ssl_client.h" +#include "sock.h" +#include "stdlib.h" + +int ssl_errno = 0; + +static gboolean initialized = FALSE; + +struct scd +{ + ssl_input_function func; + gpointer data; + int fd; + gboolean established; + int inpa; + + gnutls_session session; + gnutls_certificate_credentials xcred; +}; + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); + + +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) +{ + struct scd *conn = g_new0( struct scd, 1 ); + + conn->fd = proxy_connect( host, port, ssl_connected, conn ); + conn->func = func; + conn->data = data; + conn->inpa = -1; + + if( conn->fd < 0 ) + { + g_free( conn ); + return( NULL ); + } + + if( !initialized ) + { + gnutls_global_init(); + initialized = TRUE; + atexit( gnutls_global_deinit ); + } + + gnutls_certificate_allocate_credentials( &conn->xcred ); + gnutls_init( &conn->session, GNUTLS_CLIENT ); + gnutls_set_default_priority( conn->session ); + gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred ); + + return( conn ); +} + +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + + if( source == -1 ) + { + conn->func( conn->data, NULL, cond ); + + gnutls_deinit( conn->session ); + gnutls_certificate_free_credentials( conn->xcred ); + + g_free( conn ); + + return FALSE; + } + + sock_make_nonblocking( conn->fd ); + gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); + + return ssl_handshake( data, source, cond ); +} + +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + int st; + + if( ( st = gnutls_handshake( conn->session ) ) < 0 ) + { + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + { + conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), + ssl_handshake, data ); + } + else + { + conn->func( conn->data, NULL, cond ); + + gnutls_deinit( conn->session ); + gnutls_certificate_free_credentials( conn->xcred ); + closesocket( conn->fd ); + + g_free( conn ); + } + } + else + { + /* For now we can't handle non-blocking perfectly everywhere... */ + sock_make_blocking( conn->fd ); + + conn->established = TRUE; + conn->func( conn->data, conn, cond ); + } + + return FALSE; +} + +int ssl_read( void *conn, char *buf, int len ) +{ + int st; + + if( !((struct scd*)conn)->established ) + { + ssl_errno = SSL_NOHANDSHAKE; + return( -1 ); + } + + st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len ); + + ssl_errno = SSL_OK; + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + ssl_errno = SSL_AGAIN; + + return st; +} + +int ssl_write( void *conn, const char *buf, int len ) +{ + int st; + + if( !((struct scd*)conn)->established ) + { + ssl_errno = SSL_NOHANDSHAKE; + return( -1 ); + } + + st = gnutls_record_send( ((struct scd*)conn)->session, buf, len ); + + ssl_errno = SSL_OK; + if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + ssl_errno = SSL_AGAIN; + + return st; +} + +void ssl_disconnect( void *conn_ ) +{ + struct scd *conn = conn_; + + if( conn->inpa != -1 ) + b_event_remove( conn->inpa ); + + if( conn->established ) + gnutls_bye( conn->session, GNUTLS_SHUT_WR ); + + closesocket( conn->fd ); + + gnutls_deinit( conn->session ); + gnutls_certificate_free_credentials( conn->xcred ); + g_free( conn ); +} + +int ssl_getfd( void *conn ) +{ + return( ((struct scd*)conn)->fd ); +} + +b_input_condition ssl_getdirection( void *conn ) +{ + return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? + GAIM_INPUT_WRITE : GAIM_INPUT_READ ); +} diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c new file mode 100644 index 00000000..218b3a80 --- /dev/null +++ b/lib/ssl_nss.c @@ -0,0 +1,190 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* SSL module - NSS version */ + +/* Copyright 2005 Jelmer Vernooij */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bitlbee.h" +#include "proxy.h" +#include "ssl_client.h" +#include "sock.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int ssl_errno = 0; + +static gboolean initialized = FALSE; + +struct scd +{ + ssl_input_function func; + gpointer data; + int fd; + PRFileDesc *prfd; + gboolean established; +}; + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); + + +static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver) +{ + return SECSuccess; +} + +static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) +{ + PRErrorCode err; + + if(!arg) return SECFailure; + + *(PRErrorCode *)arg = err = PORT_GetError(); + + switch(err) { + case SEC_ERROR_INVALID_AVA: + case SEC_ERROR_INVALID_TIME: + case SEC_ERROR_BAD_SIGNATURE: + case SEC_ERROR_EXPIRED_CERTIFICATE: + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_UNTRUSTED_CERT: + case SEC_ERROR_CERT_VALID: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_CRL_EXPIRED: + case SEC_ERROR_CRL_BAD_SIGNATURE: + case SEC_ERROR_EXTENSION_VALUE_INVALID: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_CERT_USAGES_INVALID: + case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: + return SECSuccess; + + default: + return SECFailure; + } +} + + +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) +{ + struct scd *conn = g_new0( struct scd, 1 ); + + conn->fd = proxy_connect( host, port, ssl_connected, conn ); + conn->func = func; + conn->data = data; + + if( conn->fd < 0 ) + { + g_free( conn ); + return( NULL ); + } + + if( !initialized ) + { + PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + NSS_NoDB_Init(NULL); + NSS_SetDomesticPolicy(); + } + + + return( conn ); +} + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + + if( source == -1 ) + goto ssl_connected_failure; + + /* Until we find out how to handle non-blocking I/O with NSS... */ + sock_make_blocking( conn->fd ); + + conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); + SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); + SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); + SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL); + SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB()); + SSL_ResetHandshake(conn->prfd, PR_FALSE); + + if (SSL_ForceHandshake(conn->prfd)) { + goto ssl_connected_failure; + } + + + conn->established = TRUE; + conn->func( conn->data, conn, cond ); + return FALSE; + + ssl_connected_failure: + + conn->func( conn->data, NULL, cond ); + + PR_Close( conn -> prfd ); + if( source >= 0 ) closesocket( source ); + g_free( conn ); + + return FALSE; +} + +int ssl_read( void *conn, char *buf, int len ) +{ + if( !((struct scd*)conn)->established ) + return( 0 ); + + return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) ); +} + +int ssl_write( void *conn, const char *buf, int len ) +{ + if( !((struct scd*)conn)->established ) + return( 0 ); + + return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); +} + +void ssl_disconnect( void *conn_ ) +{ + struct scd *conn = conn_; + + PR_Close( conn->prfd ); + closesocket( conn->fd ); + + g_free( conn ); +} + +int ssl_getfd( void *conn ) +{ + return( ((struct scd*)conn)->fd ); +} + +b_input_condition ssl_getdirection( void *conn ) +{ + /* Just in case someone calls us, let's return the most likely case: */ + return GAIM_INPUT_READ; +} diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c new file mode 100644 index 00000000..b6f6c520 --- /dev/null +++ b/lib/ssl_openssl.c @@ -0,0 +1,221 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* SSL module - OpenSSL version */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include + +#include "proxy.h" +#include "ssl_client.h" +#include "sock.h" + +int ssl_errno = 0; + +static gboolean initialized = FALSE; + +struct scd +{ + ssl_input_function func; + gpointer data; + int fd; + gboolean established; + + int inpa; + int lasterr; /* Necessary for SSL_get_error */ + SSL *ssl; + SSL_CTX *ssl_ctx; +}; + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); + + +void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) +{ + struct scd *conn = g_new0( struct scd, 1 ); + SSL_METHOD *meth; + + conn->fd = proxy_connect( host, port, ssl_connected, conn ); + conn->func = func; + conn->data = data; + + if( conn->fd < 0 ) + { + g_free( conn ); + return( NULL ); + } + + if( !initialized ) + { + initialized = TRUE; + SSLeay_add_ssl_algorithms(); + } + + meth = TLSv1_client_method(); + conn->ssl_ctx = SSL_CTX_new( meth ); + if( conn->ssl_ctx == NULL ) + { + conn->fd = -1; + return( NULL ); + } + + conn->ssl = SSL_new( conn->ssl_ctx ); + if( conn->ssl == NULL ) + { + conn->fd = -1; + return( NULL ); + } + + return( conn ); +} + +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + + if( source == -1 ) + return ssl_handshake( data, -1, cond ); + + /* We can do at least the handshake with non-blocking I/O */ + sock_make_nonblocking( conn->fd ); + SSL_set_fd( conn->ssl, conn->fd ); + + return ssl_handshake( data, source, cond ); +} + +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + int st; + + if( ( st = SSL_connect( conn->ssl ) ) < 0 ) + { + conn->lasterr = SSL_get_error( conn->ssl, st ); + if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) + goto ssl_connected_failure; + + conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); + return FALSE; + } + + conn->established = TRUE; + sock_make_blocking( conn->fd ); /* For now... */ + conn->func( conn->data, conn, cond ); + return FALSE; + +ssl_connected_failure: + conn->func( conn->data, NULL, cond ); + + if( conn->ssl ) + { + SSL_shutdown( conn->ssl ); + SSL_free( conn->ssl ); + } + if( conn->ssl_ctx ) + { + SSL_CTX_free( conn->ssl_ctx ); + } + if( source >= 0 ) closesocket( source ); + g_free( conn ); + + return FALSE; +} + +int ssl_read( void *conn, char *buf, int len ) +{ + int st; + + if( !((struct scd*)conn)->established ) + { + ssl_errno = SSL_NOHANDSHAKE; + return -1; + } + + st = SSL_read( ((struct scd*)conn)->ssl, buf, len ); + + ssl_errno = SSL_OK; + if( st <= 0 ) + { + ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); + if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) + ssl_errno = SSL_AGAIN; + } + + return st; +} + +int ssl_write( void *conn, const char *buf, int len ) +{ + int st; + + if( !((struct scd*)conn)->established ) + { + ssl_errno = SSL_NOHANDSHAKE; + return -1; + } + + st = SSL_write( ((struct scd*)conn)->ssl, buf, len ); + + ssl_errno = SSL_OK; + if( st <= 0 ) + { + ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); + if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) + ssl_errno = SSL_AGAIN; + } + + return st; +} + +void ssl_disconnect( void *conn_ ) +{ + struct scd *conn = conn_; + + if( conn->inpa != -1 ) + b_event_remove( conn->inpa ); + + if( conn->established ) + SSL_shutdown( conn->ssl ); + + closesocket( conn->fd ); + + SSL_free( conn->ssl ); + SSL_CTX_free( conn->ssl_ctx ); + g_free( conn ); +} + +int ssl_getfd( void *conn ) +{ + return( ((struct scd*)conn)->fd ); +} + +b_input_condition ssl_getdirection( void *conn ) +{ + return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ ); +} diff --git a/lib/url.c b/lib/url.c new file mode 100644 index 00000000..e4deac78 --- /dev/null +++ b/lib/url.c @@ -0,0 +1,107 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2001-2005 Wilmer van der Gaast and others * + \********************************************************************/ + +/* URL/mirror stuff - Stolen from Axel */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "url.h" + +/* Convert an URL to a url_t structure */ +int url_set( url_t *url, char *set_url ) +{ + char s[MAX_STRING]; + char *i; + + /* protocol:// */ + if( ( i = strstr( set_url, "://" ) ) == NULL ) + { + url->proto = PROTO_DEFAULT; + strncpy( s, set_url, MAX_STRING ); + } + else + { + if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) + url->proto = PROTO_HTTP; + else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) + url->proto = PROTO_HTTPS; + else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 ) + url->proto = PROTO_SOCKS4; + else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 ) + url->proto = PROTO_SOCKS5; + else + { + return( 0 ); + } + strncpy( s, i + 3, MAX_STRING ); + } + + /* Split */ + if( ( i = strchr( s, '/' ) ) == NULL ) + { + strcpy( url->file, "/" ); + } + else + { + strncpy( url->file, i, MAX_STRING ); + *i = 0; + } + strncpy( url->host, s, MAX_STRING ); + + /* Check for username in host field */ + if( strrchr( url->host, '@' ) != NULL ) + { + strncpy( url->user, url->host, MAX_STRING ); + i = strrchr( url->user, '@' ); + *i = 0; + strcpy( url->host, i + 1 ); + *url->pass = 0; + } + /* If not: Fill in defaults */ + else + { + *url->user = *url->pass = 0; + } + + /* Password? */ + if( ( i = strchr( url->user, ':' ) ) != NULL ) + { + *i = 0; + strcpy( url->pass, i + 1 ); + } + /* Port number? */ + if( ( i = strchr( url->host, ':' ) ) != NULL ) + { + *i = 0; + sscanf( i + 1, "%d", &url->port ); + } + else + { + if( url->proto == PROTO_HTTP ) + url->port = 80; + else if( url->proto == PROTO_HTTPS ) + url->port = 443; + else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 ) + url->port = 1080; + } + + return( url->port > 0 ); +} diff --git a/lib/url.h b/lib/url.h new file mode 100644 index 00000000..e9e1ecfe --- /dev/null +++ b/lib/url.h @@ -0,0 +1,44 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2001-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* URL/mirror stuff - Stolen from Axel */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bitlbee.h" + +#define PROTO_HTTP 2 +#define PROTO_HTTPS 5 +#define PROTO_SOCKS4 3 +#define PROTO_SOCKS5 4 +#define PROTO_DEFAULT PROTO_HTTP + +typedef struct url +{ + int proto; + int port; + char host[MAX_STRING]; + char file[MAX_STRING]; + char user[MAX_STRING]; + char pass[MAX_STRING]; +} url_t; + +int url_set( url_t *url, char *set_url ); diff --git a/protocols/Makefile b/protocols/Makefile index b74212f4..cc45fb09 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = $(EVENT_HANDLER) http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) +objects = nogaim.o # [SH] The next two lines should contain the directory name (in $(subdirs)) # and the name of the object file, which should be linked into diff --git a/protocols/events.h b/protocols/events.h deleted file mode 100644 index 781fca6a..00000000 --- a/protocols/events.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * nogaim - * - * Copyright (C) 2006 Wilmer van der Gaast and others - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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 - * - */ - -/* - * Split off the event handling things from proxy.[ch] (and adding timer - * stuff. This to allow BitlBee to use other libs than GLib for event - * handling. - */ - - -#ifndef _EVENTS_H_ -#define _EVENTS_H_ - -#include -#ifndef _WIN32 -#include -#include -#include -#endif -#include -#include - -typedef enum { - GAIM_INPUT_READ = 1 << 1, - GAIM_INPUT_WRITE = 1 << 2 -} b_input_condition; -typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); - -#define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) -#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) -#define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) - -// #define event_debug( x... ) printf( x ) -#define event_debug( x... ) - -G_MODULE_EXPORT void b_main_init(); -G_MODULE_EXPORT void b_main_run(); -G_MODULE_EXPORT void b_main_quit(); - -G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data); -G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data); -G_MODULE_EXPORT void b_event_remove(gint id); - -#ifdef EVENTS_LIBEVENT -G_MODULE_EXPORT void closesocket(int fd); -#endif - -#endif /* _EVENTS_H_ */ diff --git a/protocols/events_glib.c b/protocols/events_glib.c deleted file mode 100644 index 620720cd..00000000 --- a/protocols/events_glib.c +++ /dev/null @@ -1,137 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2006 Wilmer van der Gaast and others * - \********************************************************************/ - -/* - * Event handling (using GLib) - */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#define BITLBEE_CORE -#include -#include -#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#include -#else -#include "sock.h" -#define ETIMEDOUT WSAETIMEDOUT -#define EINPROGRESS WSAEINPROGRESS -#endif -#include -#include -#include "proxy.h" - -typedef struct _GaimIOClosure { - b_event_handler function; - guint result; - gpointer data; -} GaimIOClosure; - -static GMainLoop *loop; - -void b_main_init() -{ - loop = g_main_new( FALSE ); -} - -void b_main_run() -{ - g_main_run( loop ); -} - -void b_main_quit() -{ - g_main_quit( loop ); -} - -static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) -{ - GaimIOClosure *closure = data; - b_input_condition gaim_cond = 0; - gboolean st; - - if (condition & GAIM_READ_COND) - gaim_cond |= GAIM_INPUT_READ; - if (condition & GAIM_WRITE_COND) - gaim_cond |= GAIM_INPUT_WRITE; - - event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data ); - - st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); - - if( !st ) - event_debug( "Returned FALSE, cancelling.\n" ); - - return st; -} - -static void gaim_io_destroy(gpointer data) -{ - event_debug( "gaim_io_destroy( 0x%x )\n", data ); - g_free(data); -} - -gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data) -{ - GaimIOClosure *closure = g_new0(GaimIOClosure, 1); - GIOChannel *channel; - GIOCondition cond = 0; - - closure->function = function; - closure->data = data; - - if (condition & GAIM_INPUT_READ) - cond |= GAIM_READ_COND; - if (condition & GAIM_INPUT_WRITE) - cond |= GAIM_WRITE_COND; - - channel = g_io_channel_unix_new(source); - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - gaim_io_invoke, closure, gaim_io_destroy); - - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure ); - - g_io_channel_unref(channel); - return closure->result; -} - -gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) -{ - gint st = g_timeout_add(timeout, func, data); - - event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st ); - - return st; -} - -void b_event_remove(gint tag) -{ - event_debug( "b_event_remove( %d )\n", tag ); - - if (tag > 0) - g_source_remove(tag); -} diff --git a/protocols/events_libevent.c b/protocols/events_libevent.c deleted file mode 100644 index 1119c2ab..00000000 --- a/protocols/events_libevent.c +++ /dev/null @@ -1,247 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2006 Wilmer van der Gaast and others * - \********************************************************************/ - -/* - * Event handling (using libevent) - */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#define BITLBEE_CORE -#include -#include -#include -#include -#include -#include "proxy.h" - -#include -#include - -static guint id_next; -static GHashTable *id_hash; -static int quitting = 0; - -/* Since libevent doesn't handle two event handlers for one fd-condition - very well (which happens sometimes when BitlBee changes event handlers - for a combination), let's buid some indexes so we can delete them here - already, just in time. */ -static GHashTable *read_hash; -static GHashTable *write_hash; - -struct b_event_data -{ - guint id; - struct event evinfo; - gint timeout; - b_event_handler function; - void *data; -}; - -void b_main_init() -{ - event_init(); - - id_next = 1; - id_hash = g_hash_table_new( g_int_hash, g_int_equal ); - read_hash = g_hash_table_new( g_int_hash, g_int_equal ); - write_hash = g_hash_table_new( g_int_hash, g_int_equal ); -} - -void b_main_run() -{ - event_dispatch(); -} - -void b_main_quit() -{ - struct timeval tv; - - /* libevent sometimes generates events before really quitting, - we want to stop them. */ - quitting = 1; - - memset( &tv, 0, sizeof( struct timeval ) ); - event_loopexit( &tv ); -} - -static void b_event_passthrough( int fd, short event, void *data ) -{ - struct b_event_data *b_ev = data; - b_input_condition cond = 0; - int id; - - if( fd >= 0 ) - { - if( event & EV_READ ) - cond |= GAIM_INPUT_READ; - if( event & EV_WRITE ) - cond |= GAIM_INPUT_WRITE; - } - - event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); - - /* Since the called function might cancel this handler already - (which free()s b_ev, we have to remember the ID here. */ - id = b_ev->id; - - if( quitting ) - { - b_event_remove( id ); - return; - } - - if( !b_ev->function( b_ev->data, fd, cond ) ) - { - event_debug( "Handler returned FALSE: " ); - b_event_remove( id ); - } - else if( fd == -1 ) - { - struct timeval tv; - - tv.tv_sec = b_ev->timeout / 1000; - tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000; - - evtimer_add( &b_ev->evinfo, &tv ); - } -} - -gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) -{ - struct b_event_data *b_ev; - - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); - - if( ( condition & GAIM_INPUT_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || - ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) - { - /* We'll stick with this libevent entry, but give it a new BitlBee id. */ - g_hash_table_remove( id_hash, &b_ev->id ); - - event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next ); - - b_ev->id = id_next++; - b_ev->function = function; - b_ev->data = data; - } - else - { - GIOCondition out_cond; - - event_debug( "(new) = %d\n", id_next ); - - b_ev = g_new0( struct b_event_data, 1 ); - b_ev->id = id_next++; - b_ev->function = function; - b_ev->data = data; - - out_cond = EV_PERSIST; - if( condition & GAIM_INPUT_READ ) - out_cond |= EV_READ; - if( condition & GAIM_INPUT_WRITE ) - out_cond |= EV_WRITE; - - event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); - event_add( &b_ev->evinfo, NULL ); - - if( out_cond & EV_READ ) - g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev ); - if( out_cond & EV_WRITE ) - g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev ); - } - - g_hash_table_insert( id_hash, &b_ev->id, b_ev ); - return b_ev->id; -} - -/* TODO: Persistence for timers! */ -gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) -{ - struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); - struct timeval tv; - - b_ev->id = id_next++; - b_ev->timeout = timeout; - b_ev->function = function; - b_ev->data = data; - - tv.tv_sec = timeout / 1000; - tv.tv_usec = ( timeout % 1000 ) * 1000; - - evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); - evtimer_add( &b_ev->evinfo, &tv ); - - event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); - - g_hash_table_insert( id_hash, &b_ev->id, b_ev ); - - return b_ev->id; -} - -void b_event_remove( gint id ) -{ - struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id ); - - event_debug( "b_event_remove( %d )\n", id ); - if( b_ev ) - { - g_hash_table_remove( id_hash, &b_ev->id ); - if( b_ev->evinfo.ev_fd >= 0 ) - { - if( b_ev->evinfo.ev_events & EV_READ ) - g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd ); - if( b_ev->evinfo.ev_events & EV_WRITE ) - g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd ); - } - - event_del( &b_ev->evinfo ); - g_free( b_ev ); - } - else - { - event_debug( "Already removed?\n" ); - } -} - -void closesocket( int fd ) -{ - struct b_event_data *b_ev; - - /* Since epoll() (the main reason we use libevent) automatically removes sockets from - the epoll() list when a socket gets closed and some modules have a habit of - closing sockets before removing event handlers, our and libevent's administration - get a little bit messed up. So this little function will remove the handlers - properly before closing a socket. */ - - if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) - { - event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); - b_event_remove( b_ev->id ); - } - if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) - { - event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); - b_event_remove( b_ev->id ); - } - - close( fd ); -} diff --git a/protocols/http_client.c b/protocols/http_client.c deleted file mode 100644 index b00fcf98..00000000 --- a/protocols/http_client.c +++ /dev/null @@ -1,453 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2005 Wilmer van der Gaast and others * - \********************************************************************/ - -/* HTTP(S) module */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include - -#include "http_client.h" -#include "url.h" -#include "sock.h" - - -static gboolean http_connected( gpointer data, int source, b_input_condition cond ); -static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ); -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); - - -void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) -{ - struct http_request *req; - int error = 0; - - req = g_new0( struct http_request, 1 ); - - if( ssl ) - { - req->ssl = ssl_connect( host, port, http_ssl_connected, req ); - if( req->ssl == NULL ) - error = 1; - } - else - { - req->fd = proxy_connect( host, port, http_connected, req ); - if( req->fd < 0 ) - error = 1; - } - - if( error ) - { - g_free( req ); - return( NULL ); - } - - req->func = func; - req->data = data; - req->request = g_strdup( request ); - req->request_length = strlen( request ); - - return( req ); -} - -void *http_dorequest_url( char *url_string, http_input_function func, gpointer data ) -{ - url_t *url = g_new0( url_t, 1 ); - char *request; - void *ret; - - if( !url_set( url, url_string ) ) - { - g_free( url ); - return NULL; - } - - if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS ) - { - g_free( url ); - return NULL; - } - - request = g_strdup_printf( "GET %s HTTP/1.0\r\n" - "Host: %s\r\n" - "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" - "\r\n", url->file, url->host ); - - ret = http_dorequest( url->host, url->port, - url->proto == PROTO_HTTPS, request, func, data ); - - g_free( url ); - g_free( request ); - return ret; -} - -/* This one is actually pretty simple... Might get more calls if we can't write - the whole request at once. */ -static gboolean http_connected( gpointer data, int source, b_input_condition cond ) -{ - struct http_request *req = data; - int st; - - if( source < 0 ) - goto error; - - if( req->inpa > 0 ) - b_event_remove( req->inpa ); - - sock_make_nonblocking( req->fd ); - - if( req->ssl ) - { - st = ssl_write( req->ssl, req->request + req->bytes_written, - req->request_length - req->bytes_written ); - if( st < 0 ) - { - if( ssl_errno != SSL_AGAIN ) - { - ssl_disconnect( req->ssl ); - goto error; - } - } - } - else - { - st = write( source, req->request + req->bytes_written, - req->request_length - req->bytes_written ); - if( st < 0 ) - { - if( !sockerr_again() ) - { - closesocket( req->fd ); - goto error; - } - } - } - - if( st > 0 ) - req->bytes_written += st; - - if( req->bytes_written < req->request_length ) - req->inpa = b_input_add( source, - req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE, - http_connected, req ); - else - req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req ); - - return FALSE; - -error: - req->status_string = g_strdup( "Error while writing HTTP request" ); - - req->func( req ); - - g_free( req->request ); - g_free( req ); - - return FALSE; -} - -static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond ) -{ - struct http_request *req = data; - - if( source == NULL ) - return http_connected( data, -1, cond ); - - req->fd = ssl_getfd( source ); - - return http_connected( data, req->fd, cond ); -} - -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) -{ - struct http_request *req = data; - int evil_server = 0; - char buffer[2048]; - char *end1, *end2; - int st; - - if( req->inpa > 0 ) - b_event_remove( req->inpa ); - - if( req->ssl ) - { - st = ssl_read( req->ssl, buffer, sizeof( buffer ) ); - if( st < 0 ) - { - if( ssl_errno != SSL_AGAIN ) - { - /* goto cleanup; */ - - /* YAY! We have to deal with crappy Microsoft - servers that LOVE to send invalid TLS - packets that abort connections! \o/ */ - - goto got_reply; - } - } - else if( st == 0 ) - { - goto got_reply; - } - } - else - { - st = read( req->fd, buffer, sizeof( buffer ) ); - if( st < 0 ) - { - if( !sockerr_again() ) - { - req->status_string = g_strdup( strerror( errno ) ); - goto cleanup; - } - } - else if( st == 0 ) - { - goto got_reply; - } - } - - if( st > 0 ) - { - req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 ); - memcpy( req->reply_headers + req->bytes_read, buffer, st ); - req->bytes_read += st; - } - - /* There will be more! */ - req->inpa = b_input_add( req->fd, - req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ, - http_incoming_data, req ); - - return FALSE; - -got_reply: - /* Maybe if the webserver is overloaded, or when there's bad SSL - support... */ - if( req->bytes_read == 0 ) - { - req->status_string = g_strdup( "Empty HTTP reply" ); - goto cleanup; - } - - /* Zero termination is very convenient. */ - req->reply_headers[req->bytes_read] = 0; - - /* Find the separation between headers and body, and keep stupid - webservers in mind. */ - end1 = strstr( req->reply_headers, "\r\n\r\n" ); - end2 = strstr( req->reply_headers, "\n\n" ); - - if( end2 && end2 < end1 ) - { - end1 = end2 + 1; - evil_server = 1; - } - else if( end1 ) - { - end1 += 2; - } - else - { - req->status_string = g_strdup( "Malformed HTTP reply" ); - goto cleanup; - } - - *end1 = 0; - - if( evil_server ) - req->reply_body = end1 + 1; - else - req->reply_body = end1 + 2; - - req->body_size = req->reply_headers + req->bytes_read - req->reply_body; - - if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) - { - if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 ) - { - req->status_string = g_strdup( "Can't parse status code" ); - req->status_code = -1; - } - else - { - char *eol; - - if( evil_server ) - eol = strchr( end1, '\n' ); - else - eol = strchr( end1, '\r' ); - - req->status_string = g_strndup( end1 + 1, eol - end1 - 1 ); - - /* Just to be sure... */ - if( ( eol = strchr( req->status_string, '\r' ) ) ) - *eol = 0; - if( ( eol = strchr( req->status_string, '\n' ) ) ) - *eol = 0; - } - } - else - { - req->status_string = g_strdup( "Can't locate status code" ); - req->status_code = -1; - } - - if( req->status_code == 301 || req->status_code == 302 ) - { - char *loc, *new_request, *new_host; - int error = 0, new_port, new_proto; - - /* We might fill it again, so let's not leak any memory. */ - g_free( req->status_string ); - req->status_string = NULL; - - loc = strstr( req->reply_headers, "\nLocation: " ); - if( loc == NULL ) /* We can't handle this redirect... */ - { - req->status_string = g_strdup( "Can't locate Location: header" ); - goto cleanup; - } - - loc += 11; - while( *loc == ' ' ) - loc ++; - - /* TODO/FIXME: Possibly have to handle relative redirections, - and rewrite Host: headers. Not necessary for now, it's - enough for passport authentication like this. */ - - if( *loc == '/' ) - { - /* Just a different pathname... */ - - /* Since we don't cache the servername, and since we - don't need this yet anyway, I won't implement it. */ - - req->status_string = g_strdup( "Can't handle recursive redirects" ); - - goto cleanup; - } - else - { - /* A whole URL */ - url_t *url; - char *s; - - s = strstr( loc, "\r\n" ); - if( s == NULL ) - goto cleanup; - - url = g_new0( url_t, 1 ); - *s = 0; - - if( !url_set( url, loc ) ) - { - req->status_string = g_strdup( "Malformed redirect URL" ); - g_free( url ); - goto cleanup; - } - - /* Okay, this isn't fun! We have to rebuild the request... :-( */ - new_request = g_malloc( req->request_length + strlen( url->file ) ); - - /* So, now I just allocated enough memory, so I'm - going to use strcat(), whether you like it or not. :-) */ - - sprintf( new_request, "GET %s HTTP/1.0", url->file ); - - s = strstr( req->request, "\r\n" ); - if( s == NULL ) - { - req->status_string = g_strdup( "Error while rebuilding request string" ); - g_free( new_request ); - g_free( url ); - goto cleanup; - } - - strcat( new_request, s ); - new_host = g_strdup( url->host ); - new_port = url->port; - new_proto = url->proto; - - g_free( url ); - } - - if( req->ssl ) - ssl_disconnect( req->ssl ); - else - closesocket( req->fd ); - - req->fd = -1; - req->ssl = NULL; - - if( new_proto == PROTO_HTTPS ) - { - req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req ); - if( req->ssl == NULL ) - error = 1; - } - else - { - req->fd = proxy_connect( new_host, new_port, http_connected, req ); - if( req->fd < 0 ) - error = 1; - } - g_free( new_host ); - - if( error ) - { - req->status_string = g_strdup( "Connection problem during redirect" ); - g_free( new_request ); - goto cleanup; - } - - g_free( req->request ); - g_free( req->reply_headers ); - req->request = new_request; - req->request_length = strlen( new_request ); - req->bytes_read = req->bytes_written = req->inpa = 0; - req->reply_headers = req->reply_body = NULL; - - return FALSE; - } - - /* Assume that a closed connection means we're finished, this indeed - breaks with keep-alive connections and faulty connections. */ - req->finished = 1; - -cleanup: - if( req->ssl ) - ssl_disconnect( req->ssl ); - else - closesocket( req->fd ); - - req->func( req ); - - g_free( req->request ); - g_free( req->reply_headers ); - g_free( req->status_string ); - g_free( req ); - - return FALSE; -} diff --git a/protocols/http_client.h b/protocols/http_client.h deleted file mode 100644 index 50ee80cf..00000000 --- a/protocols/http_client.h +++ /dev/null @@ -1,57 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2005 Wilmer van der Gaast and others * - \********************************************************************/ - -/* HTTP(S) module */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include - -#include "ssl_client.h" - -struct http_request; - -typedef void (*http_input_function)( struct http_request * ); - -struct http_request -{ - char *request; - int request_length; - int status_code; - char *status_string; - char *reply_headers; - char *reply_body; - int body_size; - int finished; - - void *ssl; - int fd; - - int inpa; - int bytes_written; - int bytes_read; - - http_input_function func; - gpointer data; -}; - -void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); -void *http_dorequest_url( char *url_string, http_input_function func, gpointer data ); diff --git a/protocols/md5.c b/protocols/md5.c deleted file mode 100644 index e6273585..00000000 --- a/protocols/md5.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -#include "md5.h" -#include - -#ifdef TEST -/* - * Compile with -DTEST to create a self-contained executable test program. - * The test program should print out the same values as given in section - * A.5 of RFC 1321, reproduced below. - */ -#include -main() -{ - static const char *const test[7] = { - "", /*d41d8cd98f00b204e9800998ecf8427e*/ - "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ - "abc", /*900150983cd24fb0d6963f7d28e17f72*/ - "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ - "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - /*d174ab98d277d9f5a5611c2c9f419d9f*/ - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ - }; - int i; - - for (i = 0; i < 7; ++i) { - md5_state_t state; - md5_byte_t digest[16]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); - md5_finish(&state, digest); - printf("MD5 (\"%s\") = ", test[i]); - for (di = 0; di < 16; ++di) - printf("%02x", digest[di]); - printf("\n"); - } - return 0; -} -#endif /* TEST */ - - -/* - * For reference, here is the program that computed the T values. - */ -#if 0 -#include -main() -{ - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - printf("#define T%d 0x%08lx\n", i, v); - } - return 0; -} -#endif -/* - * End of T computation program. - */ -#define T1 0xd76aa478 -#define T2 0xe8c7b756 -#define T3 0x242070db -#define T4 0xc1bdceee -#define T5 0xf57c0faf -#define T6 0x4787c62a -#define T7 0xa8304613 -#define T8 0xfd469501 -#define T9 0x698098d8 -#define T10 0x8b44f7af -#define T11 0xffff5bb1 -#define T12 0x895cd7be -#define T13 0x6b901122 -#define T14 0xfd987193 -#define T15 0xa679438e -#define T16 0x49b40821 -#define T17 0xf61e2562 -#define T18 0xc040b340 -#define T19 0x265e5a51 -#define T20 0xe9b6c7aa -#define T21 0xd62f105d -#define T22 0x02441453 -#define T23 0xd8a1e681 -#define T24 0xe7d3fbc8 -#define T25 0x21e1cde6 -#define T26 0xc33707d6 -#define T27 0xf4d50d87 -#define T28 0x455a14ed -#define T29 0xa9e3e905 -#define T30 0xfcefa3f8 -#define T31 0x676f02d9 -#define T32 0x8d2a4c8a -#define T33 0xfffa3942 -#define T34 0x8771f681 -#define T35 0x6d9d6122 -#define T36 0xfde5380c -#define T37 0xa4beea44 -#define T38 0x4bdecfa9 -#define T39 0xf6bb4b60 -#define T40 0xbebfbc70 -#define T41 0x289b7ec6 -#define T42 0xeaa127fa -#define T43 0xd4ef3085 -#define T44 0x04881d05 -#define T45 0xd9d4d039 -#define T46 0xe6db99e5 -#define T47 0x1fa27cf8 -#define T48 0xc4ac5665 -#define T49 0xf4292244 -#define T50 0x432aff97 -#define T51 0xab9423a7 -#define T52 0xfc93a039 -#define T53 0x655b59c3 -#define T54 0x8f0ccc92 -#define T55 0xffeff47d -#define T56 0x85845dd1 -#define T57 0x6fa87e4f -#define T58 0xfe2ce6e0 -#define T59 0xa3014314 -#define T60 0x4e0811a1 -#define T61 0xf7537e82 -#define T62 0xbd3af235 -#define T63 0x2ad7d2bb -#define T64 0xeb86d391 - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - -#ifndef ARCH_IS_BIG_ENDIAN -# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ -#endif -#if ARCH_IS_BIG_ENDIAN - - /* - * On big-endian machines, we must arrange the bytes in the right - * order. (This also works on machines of unknown byte order.) - */ - md5_word_t X[16]; - const md5_byte_t *xp = data; - int i; - - for (i = 0; i < 16; ++i, xp += 4) - X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - -#else /* !ARCH_IS_BIG_ENDIAN */ - - /* - * On little-endian machines, we can process properly aligned data - * without copying it. - */ - md5_word_t xbuf[16]; - const md5_word_t *X; - - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } -#endif - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = 0xefcdab89; - pms->abcd[2] = 0x98badcfe; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/protocols/md5.h b/protocols/md5.h deleted file mode 100644 index f24f2ff1..00000000 --- a/protocols/md5.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.h is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2004-03-09 Jelmer Vernooij add G_MODULE_EXPORT for Bitlbee - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . - 1999-05-03 lpd Original version. - */ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -#include -#include - -/* - * This code has some adaptations for the Ghostscript environment, but it - * will compile and run correctly in any environment with 8-bit chars and - * 32-bit ints. Specifically, it assumes that if the following are - * defined, they have the same meaning as in Ghostscript: P1, P2, P3, - * ARCH_IS_BIG_ENDIAN. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -G_MODULE_EXPORT void md5_init(md5_state_t *pms); - -/* Append a string to the message. */ -G_MODULE_EXPORT void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - -/* Finish the message and return the digest. */ -G_MODULE_EXPORT void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* md5_INCLUDED */ diff --git a/protocols/proxy.c b/protocols/proxy.c deleted file mode 100644 index b8aa304d..00000000 --- a/protocols/proxy.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * gaim - * - * Copyright (C) 1998-1999, Mark Spencer - * Copyright (C) 2002-2004, Wilmer van der Gaast, Jelmer Vernooij - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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 - * - */ - -#define BITLBEE_CORE -#include -#include -#include -#include -#ifndef _WIN32 -#include -#include -#include -#include -#include -#else -#include "sock.h" -#define ETIMEDOUT WSAETIMEDOUT -#define EINPROGRESS WSAEINPROGRESS -#endif -#include -#include -#include "nogaim.h" -#include "proxy.h" - -char proxyhost[128] = ""; -int proxyport = 0; -int proxytype = PROXY_NONE; -char proxyuser[128] = ""; -char proxypass[128] = ""; - -struct PHB { - b_event_handler func, proxy_func; - gpointer data, proxy_data; - char *host; - int port; - int fd; - gint inpa; -}; - - - -static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) -{ - static struct sockaddr_in sin; - - if (!inet_aton(host, &sin.sin_addr)) { - struct hostent *hp; - if (!(hp = gethostbyname(host))) { - return NULL; - } - memset(&sin, 0, sizeof(struct sockaddr_in)); - memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; - } else - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - - return &sin; -} - -static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond) -{ - struct PHB *phb = data; - unsigned int len; - int error = ETIMEDOUT; - len = sizeof(error); - -#ifndef _WIN32 - if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - closesocket(source); - b_event_remove(phb->inpa); - if( phb->proxy_func ) - phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ); - else { - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb); - } - return FALSE; - } -#endif - sock_make_blocking(source); - b_event_remove(phb->inpa); - if( phb->proxy_func ) - phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ); - else { - phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb); - } - - return FALSE; -} - -static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb) -{ - struct sockaddr_in *sin; - int fd = -1; - - if (!(sin = gaim_gethostbyname(host, port))) { - g_free(phb); - return -1; - } - - if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { - g_free(phb); - return -1; - } - - sock_make_nonblocking(fd); - - event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); - - if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { - if (sockerr_again()) { - phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); - phb->fd = fd; - } else { - closesocket(fd); - g_free(phb); - return -1; - } - } - - return fd; -} - - -/* Connecting to HTTP proxies */ - -#define HTTP_GOODSTRING "HTTP/1.0 200 Connection established" -#define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established" - -static gboolean http_canread(gpointer data, gint source, b_input_condition cond) -{ - int nlc = 0; - int pos = 0; - struct PHB *phb = data; - char inputline[8192]; - - b_event_remove(phb->inpa); - - while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { - if (inputline[pos - 1] == '\n') - nlc++; - else if (inputline[pos - 1] != '\r') - nlc = 0; - } - inputline[pos] = '\0'; - - if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) || - (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { - phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - - return FALSE; -} - -static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond) -{ - char cmd[384]; - struct PHB *phb = data; - unsigned int len; - int error = ETIMEDOUT; - if (phb->inpa > 0) - b_event_remove(phb->inpa); - len = sizeof(error); - if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - sock_make_blocking(source); - - g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, - phb->host, phb->port); - if (send(source, cmd, strlen(cmd), 0) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - if (proxyuser && *proxyuser) { - char *t1, *t2; - t1 = g_strdup_printf("%s:%s", proxyuser, proxypass); - t2 = tobase64(t1); - g_free(t1); - g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2); - g_free(t2); - if (send(source, cmd, strlen(cmd), 0) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - } - - g_snprintf(cmd, sizeof(cmd), "\r\n"); - if (send(source, cmd, strlen(cmd), 0) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb); - - return FALSE; -} - -static int proxy_connect_http(const char *host, unsigned short port, struct PHB *phb) -{ - phb->host = g_strdup(host); - phb->port = port; - phb->proxy_func = http_canwrite; - phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); -} - - -/* Connecting to SOCKS4 proxies */ - -static gboolean s4_canread(gpointer data, gint source, b_input_condition cond) -{ - unsigned char packet[12]; - struct PHB *phb = data; - - b_event_remove(phb->inpa); - - memset(packet, 0, sizeof(packet)); - if (read(source, packet, 9) >= 4 && packet[1] == 90) { - phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - - return FALSE; -} - -static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) -{ - unsigned char packet[12]; - struct hostent *hp; - struct PHB *phb = data; - unsigned int len; - int error = ETIMEDOUT; - if (phb->inpa > 0) - b_event_remove(phb->inpa); - len = sizeof(error); - if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - sock_make_blocking(source); - - /* XXX does socks4 not support host name lookups by the proxy? */ - if (!(hp = gethostbyname(phb->host))) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - packet[0] = 4; - packet[1] = 1; - packet[2] = phb->port >> 8; - packet[3] = phb->port & 0xff; - packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; - packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; - packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; - packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; - packet[8] = 0; - if (write(source, packet, 9) != 9) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb); - - return FALSE; -} - -static int proxy_connect_socks4(const char *host, unsigned short port, struct PHB *phb) -{ - phb->host = g_strdup(host); - phb->port = port; - phb->proxy_func = s4_canwrite; - phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); -} - - -/* Connecting to SOCKS5 proxies */ - -static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond) -{ - unsigned char buf[512]; - struct PHB *phb = data; - - b_event_remove(phb->inpa); - - if (read(source, buf, 10) < 10) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - if ((buf[0] != 0x05) || (buf[1] != 0x00)) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - phb->func(phb->data, source, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - - return FALSE; -} - -static void s5_sendconnect(gpointer data, gint source) -{ - unsigned char buf[512]; - struct PHB *phb = data; - int hlen = strlen(phb->host); - - buf[0] = 0x05; - buf[1] = 0x01; /* CONNECT */ - buf[2] = 0x00; /* reserved */ - buf[3] = 0x03; /* address type -- host name */ - buf[4] = hlen; - memcpy(buf + 5, phb->host, hlen); - buf[5 + strlen(phb->host)] = phb->port >> 8; - buf[5 + strlen(phb->host) + 1] = phb->port & 0xff; - - if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return; - } - - phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb); -} - -static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond) -{ - unsigned char buf[512]; - struct PHB *phb = data; - - b_event_remove(phb->inpa); - - if (read(source, buf, 2) < 2) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - if ((buf[0] != 0x01) || (buf[1] != 0x00)) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - s5_sendconnect(phb, source); - - return FALSE; -} - -static gboolean s5_canread(gpointer data, gint source, b_input_condition cond) -{ - unsigned char buf[512]; - struct PHB *phb = data; - - b_event_remove(phb->inpa); - - if (read(source, buf, 2) < 2) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - if ((buf[0] != 0x05) || (buf[1] == 0xff)) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - if (buf[1] == 0x02) { - unsigned int i = strlen(proxyuser), j = strlen(proxypass); - buf[0] = 0x01; /* version 1 */ - buf[1] = i; - memcpy(buf + 2, proxyuser, i); - buf[2 + i] = j; - memcpy(buf + 2 + i + 1, proxypass, j); - if (write(source, buf, 3 + i + j) < 3 + i + j) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb); - } else { - s5_sendconnect(phb, source); - } - - return FALSE; -} - -static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) -{ - unsigned char buf[512]; - int i; - struct PHB *phb = data; - unsigned int len; - int error = ETIMEDOUT; - if (phb->inpa > 0) - b_event_remove(phb->inpa); - len = sizeof(error); - if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - sock_make_blocking(source); - - i = 0; - buf[0] = 0x05; /* SOCKS version 5 */ - if (proxyuser[0]) { - buf[1] = 0x02; /* two methods */ - buf[2] = 0x00; /* no authentication */ - buf[3] = 0x02; /* username/password authentication */ - i = 4; - } else { - buf[1] = 0x01; - buf[2] = 0x00; - i = 3; - } - - if (write(source, buf, i) < i) { - close(source); - phb->func(phb->data, -1, GAIM_INPUT_READ); - g_free(phb->host); - g_free(phb); - return FALSE; - } - - phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb); - - return FALSE; -} - -static int proxy_connect_socks5(const char *host, unsigned short port, struct PHB *phb) -{ - phb->host = g_strdup(host); - phb->port = port; - phb->proxy_func = s5_canwrite; - phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); -} - - -/* Export functions */ - -int proxy_connect(const char *host, int port, b_event_handler func, gpointer data) -{ - struct PHB *phb; - - if (!host || !port || (port == -1) || !func || strlen(host) > 128) { - return -1; - } - - phb = g_new0(struct PHB, 1); - phb->func = func; - phb->data = data; - -#ifndef _WIN32 - sethostent(1); -#endif - - if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) - return proxy_connect_none(host, port, phb); - else if (proxytype == PROXY_HTTP) - return proxy_connect_http(host, port, phb); - else if (proxytype == PROXY_SOCKS4) - return proxy_connect_socks4(host, port, phb); - else if (proxytype == PROXY_SOCKS5) - return proxy_connect_socks5(host, port, phb); - - if (phb->host) g_free(phb); - g_free(phb); - return -1; -} diff --git a/protocols/proxy.h b/protocols/proxy.h deleted file mode 100644 index 680790a5..00000000 --- a/protocols/proxy.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * nogaim - * - * Copyright (C) 1998-1999, Mark Spencer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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 - * - */ - -/* this is the export part of the proxy.c file. it does a little - prototype-ing stuff and redefine some net function to mask them - with some kind of transparent layer */ - -#ifndef _PROXY_H_ -#define _PROXY_H_ - -#include -#ifndef _WIN32 -#include -#include -#include -#endif -#include -#include - -#include "events.h" - -#define PROXY_NONE 0 -#define PROXY_HTTP 1 -#define PROXY_SOCKS4 2 -#define PROXY_SOCKS5 3 - -extern char proxyhost[128]; -extern int proxyport; -extern int proxytype; -extern char proxyuser[128]; -extern char proxypass[128]; - -G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data); - -#endif /* _PROXY_H_ */ diff --git a/protocols/sha.c b/protocols/sha.c deleted file mode 100644 index 895505a1..00000000 --- a/protocols/sha.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - */ - -#define BITLBEE_CORE -#include "nogaim.h" - -static void shaHashBlock(SHA_CTX *ctx); - -void shaInit(SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301L; - ctx->H[1] = 0xefcdab89L; - ctx->H[2] = 0x98badcfeL; - ctx->H[3] = 0x10325476L; - ctx->H[4] = 0xc3d2e1f0L; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) { - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - shaUpdate(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - shaUpdate(ctx, &pad0x00, 1); - shaUpdate(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - shaInit(ctx); -} - - -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { - SHA_CTX ctx; - - shaInit(&ctx); - shaUpdate(&ctx, dataIn, len); - shaFinal(&ctx, hashout); -} - - -#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL) - -static void shaHashBlock(SHA_CTX *ctx) { - int t; - guint32 A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -/*---------------------------------------------------------------------------- - * - * This code added by Thomas "temas" Muldowney for Jabber compatability - * - *---------------------------------------------------------------------------*/ -char *shahash(char *str) -{ - static char final[41]; - char *pos; - unsigned char hashval[20]; - int x; - - if(!str || strlen(str) == 0) - return NULL; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = final; - for(x=0;x<20;x++) - { - g_snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - return (char *)final; -} diff --git a/protocols/sha.h b/protocols/sha.h deleted file mode 100644 index e8152b1b..00000000 --- a/protocols/sha.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SHA_H__ -#define __SHA_H__ - -#include - -G_MODULE_EXPORT int strprintsha(char *dest, int *hashval); - -typedef struct { - guint32 H[5]; - guint32 W[80]; - int lenW; - guint32 sizeHi,sizeLo; -} SHA_CTX; - -G_MODULE_EXPORT void shaInit(SHA_CTX *ctx); -G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); -G_MODULE_EXPORT char *shahash(char *str); - -#endif diff --git a/protocols/ssl_bogus.c b/protocols/ssl_bogus.c deleted file mode 100644 index 00aaa7c4..00000000 --- a/protocols/ssl_bogus.c +++ /dev/null @@ -1,57 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module - dummy version */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ssl_client.h" - -int ssl_errno; - -void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) -{ - return( NULL ); -} - -int ssl_read( void *conn, char *buf, int len ) -{ - return( -1 ); -} - -int ssl_write( void *conn, const char *buf, int len ) -{ - return( -1 ); -} - -void ssl_disconnect( void *conn_ ) -{ -} - -int ssl_getfd( void *conn ) -{ - return( -1 ); -} - -b_input_condition ssl_getdirection( void *conn ) -{ - return GAIM_INPUT_READ; -} diff --git a/protocols/ssl_client.h b/protocols/ssl_client.h deleted file mode 100644 index 1a9c79e9..00000000 --- a/protocols/ssl_client.h +++ /dev/null @@ -1,42 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include "proxy.h" - -#define SSL_OK 0 -#define SSL_NOHANDSHAKE 1 -#define SSL_AGAIN 2 - -extern int ssl_errno; - -typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition); - -G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); -G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); -G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); -G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); -G_MODULE_EXPORT int ssl_getfd( void *conn ); -G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); diff --git a/protocols/ssl_gnutls.c b/protocols/ssl_gnutls.c deleted file mode 100644 index 3ebe1756..00000000 --- a/protocols/ssl_gnutls.c +++ /dev/null @@ -1,206 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module - GnuTLS version */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include "proxy.h" -#include "ssl_client.h" -#include "sock.h" -#include "stdlib.h" - -int ssl_errno = 0; - -static gboolean initialized = FALSE; - -struct scd -{ - ssl_input_function func; - gpointer data; - int fd; - gboolean established; - int inpa; - - gnutls_session session; - gnutls_certificate_credentials xcred; -}; - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); - - -void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) -{ - struct scd *conn = g_new0( struct scd, 1 ); - - conn->fd = proxy_connect( host, port, ssl_connected, conn ); - conn->func = func; - conn->data = data; - conn->inpa = -1; - - if( conn->fd < 0 ) - { - g_free( conn ); - return( NULL ); - } - - if( !initialized ) - { - gnutls_global_init(); - initialized = TRUE; - atexit( gnutls_global_deinit ); - } - - gnutls_certificate_allocate_credentials( &conn->xcred ); - gnutls_init( &conn->session, GNUTLS_CLIENT ); - gnutls_set_default_priority( conn->session ); - gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred ); - - return( conn ); -} - -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - - if( source == -1 ) - { - conn->func( conn->data, NULL, cond ); - - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); - - g_free( conn ); - - return FALSE; - } - - sock_make_nonblocking( conn->fd ); - gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); - - return ssl_handshake( data, source, cond ); -} - -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - int st; - - if( ( st = gnutls_handshake( conn->session ) ) < 0 ) - { - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) - { - conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), - ssl_handshake, data ); - } - else - { - conn->func( conn->data, NULL, cond ); - - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); - closesocket( conn->fd ); - - g_free( conn ); - } - } - else - { - /* For now we can't handle non-blocking perfectly everywhere... */ - sock_make_blocking( conn->fd ); - - conn->established = TRUE; - conn->func( conn->data, conn, cond ); - } - - return FALSE; -} - -int ssl_read( void *conn, char *buf, int len ) -{ - int st; - - if( !((struct scd*)conn)->established ) - { - ssl_errno = SSL_NOHANDSHAKE; - return( -1 ); - } - - st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len ); - - ssl_errno = SSL_OK; - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) - ssl_errno = SSL_AGAIN; - - return st; -} - -int ssl_write( void *conn, const char *buf, int len ) -{ - int st; - - if( !((struct scd*)conn)->established ) - { - ssl_errno = SSL_NOHANDSHAKE; - return( -1 ); - } - - st = gnutls_record_send( ((struct scd*)conn)->session, buf, len ); - - ssl_errno = SSL_OK; - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) - ssl_errno = SSL_AGAIN; - - return st; -} - -void ssl_disconnect( void *conn_ ) -{ - struct scd *conn = conn_; - - if( conn->inpa != -1 ) - b_event_remove( conn->inpa ); - - if( conn->established ) - gnutls_bye( conn->session, GNUTLS_SHUT_WR ); - - closesocket( conn->fd ); - - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); - g_free( conn ); -} - -int ssl_getfd( void *conn ) -{ - return( ((struct scd*)conn)->fd ); -} - -b_input_condition ssl_getdirection( void *conn ) -{ - return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? - GAIM_INPUT_WRITE : GAIM_INPUT_READ ); -} diff --git a/protocols/ssl_nss.c b/protocols/ssl_nss.c deleted file mode 100644 index 218b3a80..00000000 --- a/protocols/ssl_nss.c +++ /dev/null @@ -1,190 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2005 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module - NSS version */ - -/* Copyright 2005 Jelmer Vernooij */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "bitlbee.h" -#include "proxy.h" -#include "ssl_client.h" -#include "sock.h" -#include -#include -#include -#include -#include -#include -#include -#include - -int ssl_errno = 0; - -static gboolean initialized = FALSE; - -struct scd -{ - ssl_input_function func; - gpointer data; - int fd; - PRFileDesc *prfd; - gboolean established; -}; - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); - - -static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver) -{ - return SECSuccess; -} - -static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) -{ - PRErrorCode err; - - if(!arg) return SECFailure; - - *(PRErrorCode *)arg = err = PORT_GetError(); - - switch(err) { - case SEC_ERROR_INVALID_AVA: - case SEC_ERROR_INVALID_TIME: - case SEC_ERROR_BAD_SIGNATURE: - case SEC_ERROR_EXPIRED_CERTIFICATE: - case SEC_ERROR_UNKNOWN_ISSUER: - case SEC_ERROR_UNTRUSTED_CERT: - case SEC_ERROR_CERT_VALID: - case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: - case SEC_ERROR_CRL_EXPIRED: - case SEC_ERROR_CRL_BAD_SIGNATURE: - case SEC_ERROR_EXTENSION_VALUE_INVALID: - case SEC_ERROR_CA_CERT_INVALID: - case SEC_ERROR_CERT_USAGES_INVALID: - case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: - return SECSuccess; - - default: - return SECFailure; - } -} - - -void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) -{ - struct scd *conn = g_new0( struct scd, 1 ); - - conn->fd = proxy_connect( host, port, ssl_connected, conn ); - conn->func = func; - conn->data = data; - - if( conn->fd < 0 ) - { - g_free( conn ); - return( NULL ); - } - - if( !initialized ) - { - PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); - NSS_NoDB_Init(NULL); - NSS_SetDomesticPolicy(); - } - - - return( conn ); -} - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - - if( source == -1 ) - goto ssl_connected_failure; - - /* Until we find out how to handle non-blocking I/O with NSS... */ - sock_make_blocking( conn->fd ); - - conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); - SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); - SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); - SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL); - SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB()); - SSL_ResetHandshake(conn->prfd, PR_FALSE); - - if (SSL_ForceHandshake(conn->prfd)) { - goto ssl_connected_failure; - } - - - conn->established = TRUE; - conn->func( conn->data, conn, cond ); - return FALSE; - - ssl_connected_failure: - - conn->func( conn->data, NULL, cond ); - - PR_Close( conn -> prfd ); - if( source >= 0 ) closesocket( source ); - g_free( conn ); - - return FALSE; -} - -int ssl_read( void *conn, char *buf, int len ) -{ - if( !((struct scd*)conn)->established ) - return( 0 ); - - return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) ); -} - -int ssl_write( void *conn, const char *buf, int len ) -{ - if( !((struct scd*)conn)->established ) - return( 0 ); - - return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); -} - -void ssl_disconnect( void *conn_ ) -{ - struct scd *conn = conn_; - - PR_Close( conn->prfd ); - closesocket( conn->fd ); - - g_free( conn ); -} - -int ssl_getfd( void *conn ) -{ - return( ((struct scd*)conn)->fd ); -} - -b_input_condition ssl_getdirection( void *conn ) -{ - /* Just in case someone calls us, let's return the most likely case: */ - return GAIM_INPUT_READ; -} diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c deleted file mode 100644 index b6f6c520..00000000 --- a/protocols/ssl_openssl.c +++ /dev/null @@ -1,221 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* SSL module - OpenSSL version */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include - -#include "proxy.h" -#include "ssl_client.h" -#include "sock.h" - -int ssl_errno = 0; - -static gboolean initialized = FALSE; - -struct scd -{ - ssl_input_function func; - gpointer data; - int fd; - gboolean established; - - int inpa; - int lasterr; /* Necessary for SSL_get_error */ - SSL *ssl; - SSL_CTX *ssl_ctx; -}; - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); - - -void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) -{ - struct scd *conn = g_new0( struct scd, 1 ); - SSL_METHOD *meth; - - conn->fd = proxy_connect( host, port, ssl_connected, conn ); - conn->func = func; - conn->data = data; - - if( conn->fd < 0 ) - { - g_free( conn ); - return( NULL ); - } - - if( !initialized ) - { - initialized = TRUE; - SSLeay_add_ssl_algorithms(); - } - - meth = TLSv1_client_method(); - conn->ssl_ctx = SSL_CTX_new( meth ); - if( conn->ssl_ctx == NULL ) - { - conn->fd = -1; - return( NULL ); - } - - conn->ssl = SSL_new( conn->ssl_ctx ); - if( conn->ssl == NULL ) - { - conn->fd = -1; - return( NULL ); - } - - return( conn ); -} - -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - - if( source == -1 ) - return ssl_handshake( data, -1, cond ); - - /* We can do at least the handshake with non-blocking I/O */ - sock_make_nonblocking( conn->fd ); - SSL_set_fd( conn->ssl, conn->fd ); - - return ssl_handshake( data, source, cond ); -} - -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - int st; - - if( ( st = SSL_connect( conn->ssl ) ) < 0 ) - { - conn->lasterr = SSL_get_error( conn->ssl, st ); - if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) - goto ssl_connected_failure; - - conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); - return FALSE; - } - - conn->established = TRUE; - sock_make_blocking( conn->fd ); /* For now... */ - conn->func( conn->data, conn, cond ); - return FALSE; - -ssl_connected_failure: - conn->func( conn->data, NULL, cond ); - - if( conn->ssl ) - { - SSL_shutdown( conn->ssl ); - SSL_free( conn->ssl ); - } - if( conn->ssl_ctx ) - { - SSL_CTX_free( conn->ssl_ctx ); - } - if( source >= 0 ) closesocket( source ); - g_free( conn ); - - return FALSE; -} - -int ssl_read( void *conn, char *buf, int len ) -{ - int st; - - if( !((struct scd*)conn)->established ) - { - ssl_errno = SSL_NOHANDSHAKE; - return -1; - } - - st = SSL_read( ((struct scd*)conn)->ssl, buf, len ); - - ssl_errno = SSL_OK; - if( st <= 0 ) - { - ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); - if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) - ssl_errno = SSL_AGAIN; - } - - return st; -} - -int ssl_write( void *conn, const char *buf, int len ) -{ - int st; - - if( !((struct scd*)conn)->established ) - { - ssl_errno = SSL_NOHANDSHAKE; - return -1; - } - - st = SSL_write( ((struct scd*)conn)->ssl, buf, len ); - - ssl_errno = SSL_OK; - if( st <= 0 ) - { - ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); - if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) - ssl_errno = SSL_AGAIN; - } - - return st; -} - -void ssl_disconnect( void *conn_ ) -{ - struct scd *conn = conn_; - - if( conn->inpa != -1 ) - b_event_remove( conn->inpa ); - - if( conn->established ) - SSL_shutdown( conn->ssl ); - - closesocket( conn->fd ); - - SSL_free( conn->ssl ); - SSL_CTX_free( conn->ssl_ctx ); - g_free( conn ); -} - -int ssl_getfd( void *conn ) -{ - return( ((struct scd*)conn)->fd ); -} - -b_input_condition ssl_getdirection( void *conn ) -{ - return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ ); -} diff --git a/url.c b/url.c deleted file mode 100644 index e4deac78..00000000 --- a/url.c +++ /dev/null @@ -1,107 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2001-2005 Wilmer van der Gaast and others * - \********************************************************************/ - -/* URL/mirror stuff - Stolen from Axel */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "url.h" - -/* Convert an URL to a url_t structure */ -int url_set( url_t *url, char *set_url ) -{ - char s[MAX_STRING]; - char *i; - - /* protocol:// */ - if( ( i = strstr( set_url, "://" ) ) == NULL ) - { - url->proto = PROTO_DEFAULT; - strncpy( s, set_url, MAX_STRING ); - } - else - { - if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) - url->proto = PROTO_HTTP; - else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) - url->proto = PROTO_HTTPS; - else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 ) - url->proto = PROTO_SOCKS4; - else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 ) - url->proto = PROTO_SOCKS5; - else - { - return( 0 ); - } - strncpy( s, i + 3, MAX_STRING ); - } - - /* Split */ - if( ( i = strchr( s, '/' ) ) == NULL ) - { - strcpy( url->file, "/" ); - } - else - { - strncpy( url->file, i, MAX_STRING ); - *i = 0; - } - strncpy( url->host, s, MAX_STRING ); - - /* Check for username in host field */ - if( strrchr( url->host, '@' ) != NULL ) - { - strncpy( url->user, url->host, MAX_STRING ); - i = strrchr( url->user, '@' ); - *i = 0; - strcpy( url->host, i + 1 ); - *url->pass = 0; - } - /* If not: Fill in defaults */ - else - { - *url->user = *url->pass = 0; - } - - /* Password? */ - if( ( i = strchr( url->user, ':' ) ) != NULL ) - { - *i = 0; - strcpy( url->pass, i + 1 ); - } - /* Port number? */ - if( ( i = strchr( url->host, ':' ) ) != NULL ) - { - *i = 0; - sscanf( i + 1, "%d", &url->port ); - } - else - { - if( url->proto == PROTO_HTTP ) - url->port = 80; - else if( url->proto == PROTO_HTTPS ) - url->port = 443; - else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 ) - url->port = 1080; - } - - return( url->port > 0 ); -} diff --git a/url.h b/url.h deleted file mode 100644 index e9e1ecfe..00000000 --- a/url.h +++ /dev/null @@ -1,44 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2001-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* URL/mirror stuff - Stolen from Axel */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "bitlbee.h" - -#define PROTO_HTTP 2 -#define PROTO_HTTPS 5 -#define PROTO_SOCKS4 3 -#define PROTO_SOCKS5 4 -#define PROTO_DEFAULT PROTO_HTTP - -typedef struct url -{ - int proto; - int port; - char host[MAX_STRING]; - char file[MAX_STRING]; - char user[MAX_STRING]; - char pass[MAX_STRING]; -} url_t; - -int url_set( url_t *url, char *set_url ); diff --git a/util.c b/util.c deleted file mode 100644 index d8d6a4c7..00000000 --- a/util.c +++ /dev/null @@ -1,481 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* - * Various utility functions. Some are copied from Gaim to support the - * IM-modules, most are from BitlBee. - * - * Copyright (C) 1998-1999, Mark Spencer - * (and possibly other members of the Gaim team) - * Copyright 2002-2005 Wilmer van der Gaast - */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#define BITLBEE_CORE -#include "nogaim.h" -#include -#include -#include -#include -#include -#include - -void strip_linefeed(gchar *text) -{ - int i, j; - gchar *text2 = g_malloc(strlen(text) + 1); - - for (i = 0, j = 0; text[i]; i++) - if (text[i] != '\r') - text2[j++] = text[i]; - text2[j] = '\0'; - - strcpy(text, text2); - g_free(text2); -} - -char *add_cr(char *text) -{ - char *ret = NULL; - int count = 0, j; - unsigned int i; - - if (text[0] == '\n') - count++; - for (i = 1; i < strlen(text); i++) - if (text[i] == '\n' && text[i - 1] != '\r') - count++; - - if (count == 0) - return g_strdup(text); - - ret = g_malloc0(strlen(text) + count + 1); - - i = 0; j = 0; - if (text[i] == '\n') - ret[j++] = '\r'; - ret[j++] = text[i++]; - for (; i < strlen(text); i++) { - if (text[i] == '\n' && text[i - 1] != '\r') - ret[j++] = '\r'; - ret[j++] = text[i]; - } - - return ret; -} - -char *tobase64(const char *text) -{ - char *out; - int len; - - len = strlen(text); - out = g_malloc((len + 2) /* the == padding */ - / 3 /* every 3-byte block */ - * 4 /* becomes a 4-byte one */ - + 1); /* and of course, ASCIIZ! */ - - base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); - - return out; -} - -void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits) -{ - for (; inlen >= 3; inlen -= 3) - { - *out++ = b64digits[in[0] >> 2]; - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)]; - *out++ = b64digits[in[2] & 0x3f]; - in += 3; - } - if (inlen > 0) - { - *out++ = b64digits[in[0] >> 2]; - if (inlen > 1) - { - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[((in[1]<<2) & 0x3c)]; - } - else - { - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[64]; - } - *out++ = b64digits[64]; - } - *out = '\0'; -} - -char *normalize(const char *s) -{ - static char buf[BUF_LEN]; - char *t, *u; - int x = 0; - - g_return_val_if_fail((s != NULL), NULL); - - u = t = g_strdup(s); - - strcpy(t, s); - g_strdown(t); - - while (*t && (x < BUF_LEN - 1)) { - if (*t != ' ') { - buf[x] = *t; - x++; - } - t++; - } - buf[x] = '\0'; - g_free(u); - return buf; -} - -time_t get_time(int year, int month, int day, int hour, int min, int sec) -{ - struct tm tm; - - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; - return mktime(&tm); -} - -typedef struct htmlentity -{ - char code[8]; - char is[4]; -} htmlentity_t; - -/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */ - -static const htmlentity_t ent[] = -{ - { "lt", "<" }, - { "gt", ">" }, - { "amp", "&" }, - { "quot", "\"" }, - { "aacute", "รก" }, - { "eacute", "รฉ" }, - { "iacute", "รฉ" }, - { "oacute", "รณ" }, - { "uacute", "รบ" }, - { "agrave", "ร " }, - { "egrave", "รจ" }, - { "igrave", "รฌ" }, - { "ograve", "รฒ" }, - { "ugrave", "รน" }, - { "acirc", "รข" }, - { "ecirc", "รช" }, - { "icirc", "รฎ" }, - { "ocirc", "รด" }, - { "ucirc", "รป" }, - { "auml", "รค" }, - { "euml", "รซ" }, - { "iuml", "รฏ" }, - { "ouml", "รถ" }, - { "uuml", "รผ" }, - { "nbsp", " " }, - { "", "" } -}; - -void strip_html( char *in ) -{ - char *start = in; - char *out = g_malloc( strlen( in ) + 1 ); - char *s = out, *cs; - int i, matched; - - memset( out, 0, strlen( in ) + 1 ); - - while( *in ) - { - if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) ) - { - /* If in points at a < and in+1 points at a letter or a slash, this is probably - a HTML-tag. Try to find a closing > and continue there. If the > can't be - found, assume that it wasn't a HTML-tag after all. */ - - cs = in; - - while( *in && *in != '>' ) - in ++; - - if( *in ) - { - if( g_strncasecmp( cs+1, "br", 2) == 0 ) - *(s++) = '\n'; - in ++; - } - else - { - in = cs; - *(s++) = *(in++); - } - } - else if( *in == '&' ) - { - cs = ++in; - while( *in && isalpha( *in ) ) - in ++; - - if( *in == ';' ) in ++; - matched = 0; - - for( i = 0; *ent[i].code; i ++ ) - if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 ) - { - int j; - - for( j = 0; ent[i].is[j]; j ++ ) - *(s++) = ent[i].is[j]; - - matched = 1; - break; - } - - /* None of the entities were matched, so return the string */ - if( !matched ) - { - in = cs - 1; - *(s++) = *(in++); - } - } - else - { - *(s++) = *(in++); - } - } - - strcpy( start, out ); - g_free( out ); -} - -char *escape_html( const char *html ) -{ - const char *c = html; - GString *ret; - char *str; - - if( html == NULL ) - return( NULL ); - - ret = g_string_new( "" ); - - while( *c ) - { - switch( *c ) - { - case '&': - ret = g_string_append( ret, "&" ); - break; - case '<': - ret = g_string_append( ret, "<" ); - break; - case '>': - ret = g_string_append( ret, ">" ); - break; - case '"': - ret = g_string_append( ret, """ ); - break; - default: - ret = g_string_append_c( ret, *c ); - } - c ++; - } - - str = ret->str; - g_string_free( ret, FALSE ); - return( str ); -} - -void info_string_append(GString *str, char *newline, char *name, char *value) -{ - if( value && value[0] ) - g_string_sprintfa( str, "%s%s: %s", newline, name, value ); -} - -/* Decode%20a%20file%20name */ -void http_decode( char *s ) -{ - char *t; - int i, j, k; - - t = g_new( char, strlen( s ) + 1 ); - - for( i = j = 0; s[i]; i ++, j ++ ) - { - if( s[i] == '%' ) - { - if( sscanf( s + i + 1, "%2x", &k ) ) - { - t[j] = k; - i += 2; - } - else - { - *t = 0; - break; - } - } - else - { - t[j] = s[i]; - } - } - t[j] = 0; - - strcpy( s, t ); - g_free( t ); -} - -/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */ -/* This fuction is safe, but make sure you call it safely as well! */ -void http_encode( char *s ) -{ - char *t; - int i, j; - - t = g_strdup( s ); - - for( i = j = 0; t[i]; i ++, j ++ ) - { - /* if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' ) */ - if( !isalnum( t[i] ) ) - { - sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] ); - j += 2; - } - else - { - s[j] = t[i]; - } - } - s[j] = 0; - - g_free( t ); -} - -/* Strip newlines from a string. Modifies the string passed to it. */ -char *strip_newlines( char *source ) -{ - int i; - - for( i = 0; source[i] != '\0'; i ++ ) - if( source[i] == '\n' || source[i] == '\r' ) - source[i] = ' '; - - return source; -} - -#ifdef IPV6 -/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */ -char *ipv6_wrap( char *src ) -{ - static char dst[64]; - int i; - - for( i = 0; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) - break; - - /* Hmm, it's not even an IP... */ - if( src[i] ) - return src; - - g_snprintf( dst, sizeof( dst ), "::ffff:%s", src ); - - return dst; -} - -/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */ -char *ipv6_unwrap( char *src ) -{ - int i; - - if( g_strncasecmp( src, "::ffff:", 7 ) != 0 ) - return src; - - for( i = 7; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) - break; - - /* Hmm, it's not even an IP... */ - if( src[i] ) - return src; - - return ( src + 7 ); -} -#endif - -/* Convert from one charset to another. - - from_cs, to_cs: Source and destination charsets - src, dst: Source and destination strings - size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though. - maxbuf: Maximum number of bytes to write to dst - - Returns the number of bytes written to maxbuf or -1 on an error. -*/ -signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ) -{ - GIConv cd; - size_t res; - size_t inbytesleft, outbytesleft; - char *inbuf = src; - char *outbuf = dst; - - cd = g_iconv_open( to_cs, from_cs ); - if( cd == (GIConv) -1 ) - return( -1 ); - - inbytesleft = size ? size : strlen( src ); - outbytesleft = maxbuf - 1; - res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); - *outbuf = '\0'; - g_iconv_close( cd ); - - if( res == (size_t) -1 ) - return( -1 ); - else - return( outbuf - dst ); -} - -char *set_eval_charset( irc_t *irc, set_t *set, char *value ) -{ - GIConv cd; - - if ( g_strncasecmp( value, "none", 4 ) == 0 ) - return( value ); - - cd = g_iconv_open( "UTF-8", value ); - if( cd == (GIConv) -1 ) - return( NULL ); - - g_iconv_close( cd ); - return( value ); -} diff --git a/util.h b/util.h deleted file mode 100644 index c7eec19b..00000000 --- a/util.h +++ /dev/null @@ -1,51 +0,0 @@ - /********************************************************************\ - * BitlBee -- An IRC to other IM-networks gateway * - * * - * Copyright 2002-2004 Wilmer van der Gaast and others * - \********************************************************************/ - -/* Misc. functions */ - -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License with - the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, - Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef _UTIL_H -#define _UTIL_H - -G_MODULE_EXPORT void strip_linefeed( gchar *text ); -G_MODULE_EXPORT char *add_cr( char *text ); -G_MODULE_EXPORT char *strip_newlines(char *source); -G_MODULE_EXPORT char *tobase64( const char *text ); -G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits ); -G_MODULE_EXPORT char *normalize( const char *s ); -G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value ); - -G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec ); -double gettime( void ); - -G_MODULE_EXPORT void strip_html( char *msg ); -G_MODULE_EXPORT char *escape_html( const char *html ); -G_MODULE_EXPORT void http_decode( char *s ); -G_MODULE_EXPORT void http_encode( char *s ); - -G_MODULE_EXPORT char *ipv6_wrap( char *src ); -G_MODULE_EXPORT char *ipv6_unwrap( char *src ); - -G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ); -char *set_eval_charset( irc_t *irc, set_t *set, char *value ); - -#endif -- cgit v1.2.3 From 7ed3199067034b4fda4055778e02274f83bcfcb8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 16:07:01 +0200 Subject: Moved Base64-related functions to a separate file and added decode funtions. --- lib/Makefile | 2 +- lib/base64.c | 153 ++++++++++++++++++++++++++++++++++++++++++++ lib/base64.h | 33 ++++++++++ lib/misc.c | 44 ------------- lib/misc.h | 2 - lib/proxy.c | 1 + lib/rc4.c | 1 - lib/rc4.h | 1 - protocols/yahoo/libyahoo2.c | 4 +- 9 files changed, 191 insertions(+), 50 deletions(-) create mode 100644 lib/base64.c create mode 100644 lib/base64.h diff --git a/lib/Makefile b/lib/Makefile index 80cdd9a5..6408c5ba 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o +objects = base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o CFLAGS += -Wall LFLAGS += -r diff --git a/lib/base64.c b/lib/base64.c new file mode 100644 index 00000000..69069dae --- /dev/null +++ b/lib/base64.c @@ -0,0 +1,153 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Base64 handling functions. encode_real() is mostly based on the y64 en- * +* coder from libyahoo2. Moving it to a new file because it's getting big. * +* * +* Copyright 2006 Wilmer van der Gaast * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the 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 +#include +#include "base64.h" + +static const char real_b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +char *tobase64(const char *text) +{ + return base64_encode(text, strlen(text)); +} + +char *base64_encode(const char *in, int len) +{ + char *out; + + out = g_malloc((len + 2) /* the == padding */ + / 3 /* every 3-byte block */ + * 4 /* becomes a 4-byte one */ + + 1); /* and of course, ASCIIZ! */ + + base64_encode_real((unsigned char*) in, len, (unsigned char*) out, real_b64); + + return out; +} + +int base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, const char *b64digits) +{ + int outlen = 0; + + for (; inlen >= 3; inlen -= 3) + { + out[outlen++] = b64digits[in[0] >> 2]; + out[outlen++] = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + out[outlen++] = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)]; + out[outlen++] = b64digits[in[2] & 0x3f]; + in += 3; + } + if (inlen > 0) + { + out[outlen++] = b64digits[in[0] >> 2]; + if (inlen > 1) + { + out[outlen++] = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; + out[outlen++] = b64digits[((in[1]<<2) & 0x3c)]; + } + else + { + out[outlen++] = b64digits[((in[0]<<4) & 0x30)]; + out[outlen++] = b64digits[64]; + } + out[outlen++] = b64digits[64]; + } + out[outlen] = 0; + + return outlen; +} + +/* Just a simple wrapper, but usually not very convenient because of zero + termination. */ +char *frombase64(const char *in) +{ + unsigned char *out; + + base64_decode(in, &out); + + return (char*) out; +} + +/* FIXME: Lookup table stuff is not threadsafe! (But for now BitlBee is not threaded.) */ +int base64_decode(const char *in, unsigned char **out) +{ + static char b64rev[256] = { 0 }; + int len, i; + + /* Create a reverse-lookup for the Base64 sequence. */ + if( b64rev[0] == 0 ) + { + memset( b64rev, 0xff, 256 ); + for( i = 0; i <= 64; i ++ ) + b64rev[(int)real_b64[i]] = i; + } + + len = strlen( in ); + *out = g_malloc( ( len + 6 ) / 4 * 3 ); + len = base64_decode_real( (unsigned char*) in, *out, b64rev ); + *out = g_realloc( *out, len + 1 ); + out[0][len] = 0; /* Zero termination can't hurt. */ + + return len; +} + +int base64_decode_real(const unsigned char *in, unsigned char *out, char *b64rev) +{ + int i, outlen = 0; + + for( i = 0; in[i]; i += 4 ) + { + int sx; + + sx = b64rev[(int)in[i+0]]; + if( sx >= 64 ) + break; + out[outlen] = ( sx << 2 ) & 0xfc; + + sx = b64rev[(int)in[i+1]]; + if( sx >= 64 ) + break; + out[outlen] |= ( sx >> 4 ) & 0x03; + outlen ++; + out[outlen] = ( sx << 4 ) & 0xf0; + + sx = b64rev[(int)in[i+2]]; + if( sx >= 64 ) + break; + out[outlen] |= ( sx >> 2 ) & 0x0f; + outlen ++; + out[outlen] = ( sx << 6 ) & 0xc0; + + sx = b64rev[(int)in[i+3]]; + if( sx >= 64 ) + break; + out[outlen] |= sx; + outlen ++; + } + + /* If sx > 64 the base64 string was damaged. Should we ignore this? */ + + return outlen; +} diff --git a/lib/base64.h b/lib/base64.h new file mode 100644 index 00000000..570f2b14 --- /dev/null +++ b/lib/base64.h @@ -0,0 +1,33 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Base64 handling functions. encode_real() is mostly based on the y64 en- * +* coder from libyahoo2. Moving it to a new file because it's getting big. * +* * +* Copyright 2006 Wilmer van der Gaast * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the 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 +#include + +G_MODULE_EXPORT char *tobase64( const char *text ); +G_MODULE_EXPORT char *base64_encode( const char *in, int len ); +G_MODULE_EXPORT int base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, const char *b64digits ); +G_MODULE_EXPORT char *frombase64( const char *in ); +G_MODULE_EXPORT int base64_decode( const char *in, unsigned char **out ); +G_MODULE_EXPORT int base64_decode_real( const unsigned char *in, unsigned char *out, char *b64reverse ); diff --git a/lib/misc.c b/lib/misc.c index d8d6a4c7..9f592289 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -83,50 +83,6 @@ char *add_cr(char *text) return ret; } -char *tobase64(const char *text) -{ - char *out; - int len; - - len = strlen(text); - out = g_malloc((len + 2) /* the == padding */ - / 3 /* every 3-byte block */ - * 4 /* becomes a 4-byte one */ - + 1); /* and of course, ASCIIZ! */ - - base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); - - return out; -} - -void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits) -{ - for (; inlen >= 3; inlen -= 3) - { - *out++ = b64digits[in[0] >> 2]; - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)]; - *out++ = b64digits[in[2] & 0x3f]; - in += 3; - } - if (inlen > 0) - { - *out++ = b64digits[in[0] >> 2]; - if (inlen > 1) - { - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[((in[1]<<2) & 0x3c)]; - } - else - { - *out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)]; - *out++ = b64digits[64]; - } - *out++ = b64digits[64]; - } - *out = '\0'; -} - char *normalize(const char *s) { static char buf[BUF_LEN]; diff --git a/lib/misc.h b/lib/misc.h index c7eec19b..ed019bd8 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -29,8 +29,6 @@ G_MODULE_EXPORT void strip_linefeed( gchar *text ); G_MODULE_EXPORT char *add_cr( char *text ); G_MODULE_EXPORT char *strip_newlines(char *source); -G_MODULE_EXPORT char *tobase64( const char *text ); -G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits ); G_MODULE_EXPORT char *normalize( const char *s ); G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value ); diff --git a/lib/proxy.c b/lib/proxy.c index b8aa304d..453cde91 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -40,6 +40,7 @@ #include #include "nogaim.h" #include "proxy.h" +#include "base64.h" char proxyhost[128] = ""; int proxyport = 0; diff --git a/lib/rc4.c b/lib/rc4.c index 3559f71e..2b732ba2 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -5,7 +5,6 @@ * * * Copyright 2006 Wilmer van der Gaast * * * -* * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * diff --git a/lib/rc4.h b/lib/rc4.h index 8d50b508..6c9ea6b9 100644 --- a/lib/rc4.h +++ b/lib/rc4.h @@ -5,7 +5,6 @@ * * * Copyright 2006 Wilmer van der Gaast * * * -* * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index ee0f2f0e..69b63baa 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -89,6 +89,8 @@ char *strchr (), *strrchr (); #define vsnprintf _vsnprintf #endif +#include "base64.h" + #ifdef USE_STRUCT_CALLBACKS struct yahoo_callbacks *yc=NULL; @@ -697,7 +699,7 @@ static void yahoo_packet_dump(unsigned char *data, int len) /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */ static void to_y64(unsigned char *out, const unsigned char *in, int inlen) { - return base64_encode_real(in, inlen, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"); + base64_encode_real(in, inlen, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"); } static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, int length) -- cgit v1.2.3 From 4b1a75af236ad968346749d6115c785b74126f85 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 17:16:44 +0200 Subject: Disabling call to sethostent() because it causes major problems on OpenBSD (and because I don't see any use for it anyway). --- protocols/proxy.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/protocols/proxy.c b/protocols/proxy.c index b8aa304d..70a2158d 100644 --- a/protocols/proxy.c +++ b/protocols/proxy.c @@ -537,10 +537,6 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat phb->func = func; phb->data = data; -#ifndef _WIN32 - sethostent(1); -#endif - if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) return proxy_connect_none(host, port, phb); else if (proxytype == PROXY_HTTP) -- cgit v1.2.3 From 38cc9d4d7a994e4c6b2fc76897591c70e9c14b99 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 18:40:00 +0200 Subject: Fixed a memory leak (u->group). --- user.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/user.c b/user.c index b412a42d..5f0952f5 100644 --- a/user.c +++ b/user.c @@ -105,9 +105,10 @@ int user_del( irc_t *irc, char *nick ) if( u->nick != u->user ) g_free( u->user ); if( u->nick != u->host ) g_free( u->host ); if( u->nick != u->realname ) g_free( u->realname ); - if( u->away ) g_free( u->away ); - if( u->handle ) g_free( u->handle ); - if( u->sendbuf ) g_free( u->sendbuf ); + g_free( u->group ); + g_free( u->away ); + g_free( u->handle ); + g_free( u->sendbuf ); if( u->sendbuf_timer ) b_event_remove( u->sendbuf_timer ); g_free( u ); -- cgit v1.2.3 From 6e1fed7057ee26f21b0e59a5aeb292d4f3f0e8ae Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 19:07:25 +0200 Subject: Using salted MD5 checksums for the user's BitlBee password and salted RC4 encryption for the IM account passwords, plus some calls to srand() to keep the salts secure and unique. --- bitlbee.c | 4 ++++ irc.c | 3 +-- storage_xml.c | 77 +++++++++++++++++++++++++++++++++++++++++++++-------------- unix.c | 14 +++++------ 4 files changed, 70 insertions(+), 28 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 1d4e2b34..cbad61dc 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -290,6 +290,10 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition { irc_t *irc; + /* Since we're fork()ing here, let's make sure we won't + get the same random numbers as the parent/siblings. */ + srand( time( NULL ) ^ getpid() ); + /* Close the listening socket, we're a client. */ close( global.listen_socket ); b_event_remove( global.listen_watch_source_id ); diff --git a/irc.c b/irc.c index c045d12b..b5751859 100644 --- a/irc.c +++ b/irc.c @@ -328,11 +328,10 @@ void irc_free(irc_t * irc) Sets pass without checking */ void irc_setpass (irc_t *irc, const char *pass) { - if (irc->password) g_free (irc->password); + g_free (irc->password); if (pass) { irc->password = g_strdup (pass); - irc_usermsg (irc, "Password successfully changed"); } else { irc->password = NULL; } diff --git a/storage_xml.c b/storage_xml.c index 41a50d8c..35d74935 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -25,6 +25,8 @@ #define BITLBEE_CORE #include "bitlbee.h" +#include "base64.h" +#include "rc4.h" #include "md5.h" typedef enum @@ -77,32 +79,32 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { char *nick = xml_attr( attr_names, attr_values, "nick" ); char *pass = xml_attr( attr_names, attr_values, "password" ); + md5_byte_t *pass_dec = NULL; if( !nick || !pass ) { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } + else if( base64_decode( pass, &pass_dec ) != 21 ) + { + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Error while decoding password attribute" ); + } else { md5_byte_t pass_md5[16]; md5_state_t md5_state; - int i, j; + int i; md5_init( &md5_state ); md5_append( &md5_state, (md5_byte_t*) xd->given_pass, strlen( xd->given_pass ) ); + md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */ md5_finish( &md5_state, pass_md5 ); for( i = 0; i < 16; i ++ ) { - if( !isxdigit( pass[i*2] ) || !isxdigit( pass[i*2+1] ) || - sscanf( pass + i * 2, "%2x", &j ) != 1 ) - { - g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Incorrect password MD5-hash" ); - break; - } - if( j != pass_md5[i] ) + if( pass_dec[i] != pass_md5[i] ) { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, XML_PASS_ERRORMSG ); @@ -117,6 +119,8 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na xd->pass_st = XML_PASS_OK; } } + + g_free( pass_dec ); } else if( xd->pass_st < XML_PASS_OK ) { @@ -126,10 +130,12 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na else if( g_strcasecmp( element_name, "account" ) == 0 ) { char *protocol, *handle, *server, *password, *autoconnect; + char *pass_b64 = NULL, *pass_rc4 = NULL; + int pass_len; struct prpl *prpl = NULL; handle = xml_attr( attr_names, attr_values, "handle" ); - password = xml_attr( attr_names, attr_values, "password" ); + pass_b64 = xml_attr( attr_names, attr_values, "password" ); server = xml_attr( attr_names, attr_values, "server" ); autoconnect = xml_attr( attr_names, attr_values, "autoconnect" ); @@ -137,13 +143,15 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na if( protocol ) prpl = find_protocol( protocol ); - if( !handle || !password || !protocol ) + if( !handle || !pass_b64 || !protocol ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); else if( !prpl ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown protocol: %s", protocol ); - else + else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_rc4 ) ) && + rc4_decode( (unsigned char*) pass_rc4, pass_len, + (unsigned char**) &password, xd->given_pass ) ) { xd->current_account = account_add( irc, prpl, handle, password ); if( server ) @@ -153,6 +161,16 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na a default! */ sscanf( autoconnect, "%d", &xd->current_account->auto_connect ); } + else + { + /* Actually the _decode functions don't even return error codes, + but maybe they will later... */ + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Error while decrypting account password" ); + } + + g_free( pass_rc4 ); + g_free( password ); } else if( g_strcasecmp( element_name, "setting" ) == 0 ) { @@ -353,12 +371,12 @@ static int xml_printf( int fd, char *fmt, ... ) static storage_status_t xml_save( irc_t *irc, int overwrite ) { - char path[512], *path2, md5_buf[33]; + char path[512], *path2, *pass_buf = NULL; set_t *set; nick_t *nick; account_t *acc; int fd, i; - md5_byte_t pass_md5[16]; + md5_byte_t pass_md5[21]; md5_state_t md5_state; if( irc->password == NULL ) @@ -379,15 +397,23 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) return STORAGE_OTHER_ERROR; } + /* Generate a salted md5sum of the password. Use 5 bytes for the salt + (to prevent dictionary lookups of passwords) to end up with a 21- + byte password hash, more convenient for base64 encoding. */ + for( i = 0; i < 5; i ++ ) + pass_md5[16+i] = rand() & 0xff; md5_init( &md5_state ); md5_append( &md5_state, (md5_byte_t*) irc->password, strlen( irc->password ) ); + md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ md5_finish( &md5_state, pass_md5 ); - for( i = 0; i < 16; i ++ ) - g_snprintf( md5_buf + i * 2, 3, "%02x", pass_md5[i] ); + /* Save the hash in base64-encoded form. */ + pass_buf = base64_encode( (char*) pass_md5, 21 ); - if( !xml_printf( fd, "\n", irc->nick, md5_buf ) ) + if( !xml_printf( fd, "\n", irc->nick, pass_buf ) ) goto write_error; + g_free( pass_buf ); + for( set = irc->set; set; set = set->next ) if( set->value && set->def ) if( !xml_printf( fd, "\t%s\n", set->key, set->value ) ) @@ -395,8 +421,21 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) for( acc = irc->accounts; acc; acc = acc->next ) { - if( !xml_printf( fd, "\tprpl->name, acc->user, acc->pass, acc->auto_connect ) ) + char *pass_rc4, *pass_b64; + int pass_len; + + pass_len = rc4_encode( (unsigned char*) acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); + pass_b64 = base64_encode( pass_rc4, pass_len ); + + if( !xml_printf( fd, "\tprpl->name, acc->user, pass_b64, acc->auto_connect ) ) + { + g_free( pass_rc4 ); + g_free( pass_b64 ); goto write_error; + } + g_free( pass_rc4 ); + g_free( pass_b64 ); + if( acc->server && acc->server[0] && !xml_printf( fd, " server=\"%s\"", acc->server ) ) goto write_error; if( !xml_printf( fd, ">\n" ) ) @@ -432,6 +471,8 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) return STORAGE_OK; write_error: + g_free( pass_buf ); + irc_usermsg( irc, "Write error. Disk full?" ); close( fd ); diff --git a/unix.c b/unix.c index 360281ee..23ae1b91 100644 --- a/unix.c +++ b/unix.c @@ -47,20 +47,18 @@ int main( int argc, char *argv[], char **envp ) memset( &global, 0, sizeof( global_t ) ); b_main_init(); - log_init(); - nogaim_init(); - - CONF_FILE = g_strdup( CONF_FILE_DEF ); + srand( time( NULL ) ^ getpid() ); + + CONF_FILE = g_strdup( CONF_FILE_DEF ); global.helpfile = g_strdup( HELP_FILE ); - + global.conf = conf_load( argc, argv ); if( global.conf == NULL ) return( 1 ); - - + if( global.conf->runmode == RUNMODE_INETD ) { i = bitlbee_inetd_init(); @@ -88,7 +86,7 @@ int main( int argc, char *argv[], char **envp ) } if( i != 0 ) return( i ); - + global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage ); if ( global.storage == NULL) { log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage ); -- cgit v1.2.3 From 88086dbd9002123be39d00c53460f1ec9f2b719a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 19:23:27 +0200 Subject: Added versioning information to the XML-file (convenient for later format changes), got rid of confusing "Password successfully changed" message when the user uses the identify-command and protected rc4_decode() against short inputs. --- irc.c | 7 ++++--- lib/rc4.c | 6 ++++++ storage_xml.c | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/irc.c b/irc.c index b5751859..c07a3ea3 100644 --- a/irc.c +++ b/irc.c @@ -32,10 +32,11 @@ static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); GSList *irc_connection_list = NULL; -static char *passchange (irc_t *irc, void *set, char *value) +static char *passchange( irc_t *irc, void *set, char *value ) { - irc_setpass (irc, value); - return (NULL); + irc_setpass( irc, value ); + irc_usermsg( irc, "Password successfully changed" ); + return NULL; } irc_t *irc_new( int fd ) diff --git a/lib/rc4.c b/lib/rc4.c index 2b732ba2..cbe0e2c0 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -157,6 +157,12 @@ int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char key_len = strlen( password ) + RC4_IV_LEN; clear_len = crypt_len - RC4_IV_LEN; + if( clear_len < 0 ) + { + *clear = g_strdup( "" ); + return 0; + } + /* Prepare buffers and the key + IV */ *clear = g_malloc( clear_len + 1 ); key = g_malloc( key_len ); diff --git a/storage_xml.c b/storage_xml.c index 35d74935..0bbcd99a 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -39,6 +39,7 @@ typedef enum /* This isn't very clean, probably making a separate error class + code for BitlBee would be a better solution. But this will work for now... */ #define XML_PASS_ERRORMSG "Wrong username or password" +#define XML_FORMAT_VERSION 1 struct xml_parsedata { @@ -409,7 +410,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) /* Save the hash in base64-encoded form. */ pass_buf = base64_encode( (char*) pass_md5, 21 ); - if( !xml_printf( fd, "\n", irc->nick, pass_buf ) ) + if( !xml_printf( fd, "\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) ) goto write_error; g_free( pass_buf ); -- cgit v1.2.3 From 6ee9d2d65ec05d3871e69c2b03b860c6bdd509e9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 20:25:13 +0200 Subject: Forgot to initialize pass_rc4 (which caused memory management mess when trying to load a damaged XML-file). --- root_commands.c | 2 +- storage_xml.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/root_commands.c b/root_commands.c index d263bb84..e69b9981 100644 --- a/root_commands.c +++ b/root_commands.c @@ -138,7 +138,7 @@ static void cmd_identify( irc_t *irc, char **cmd ) irc_usermsg( irc, "The nick is (probably) not registered" ); break; case STORAGE_OK: - irc_usermsg( irc, "Password accepted" ); + irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); irc_umode_set( irc, "+R", 1 ); break; case STORAGE_OTHER_ERROR: diff --git a/storage_xml.c b/storage_xml.c index 0bbcd99a..7d72c781 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -130,7 +130,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na } else if( g_strcasecmp( element_name, "account" ) == 0 ) { - char *protocol, *handle, *server, *password, *autoconnect; + char *protocol, *handle, *server, *password = NULL, *autoconnect; char *pass_b64 = NULL, *pass_rc4 = NULL; int pass_len; struct prpl *prpl = NULL; -- cgit v1.2.3 From 9b63df67847e72abb00246fdfc82830137153c3c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 21:20:14 +0200 Subject: Why did I forget this one? *sigh* --- irc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irc.c b/irc.c index 52b80d41..c045d12b 100644 --- a/irc.c +++ b/irc.c @@ -576,7 +576,7 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) char line[IRC_MAX_LINE+1], *cs; /* Don't try to write anything new anymore when shutting down. */ - if( irc->status == USTATUS_SHUTDOWN ) + if( irc->status & USTATUS_SHUTDOWN ) return; line[IRC_MAX_LINE] = 0; -- cgit v1.2.3 From 2f1322291d06a3a401f730802d501ea3cae6f4e3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 25 Jun 2006 21:55:18 +0200 Subject: IRC protocol compliance fixes (closes: #158, #159, #160). --- irc.c | 31 +++++++++++++++++++++++++------ irc_commands.c | 7 ++++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/irc.c b/irc.c index c045d12b..5f69b2ea 100644 --- a/irc.c +++ b/irc.c @@ -656,7 +656,7 @@ void irc_names( irc_t *irc, char *channel ) if( !control ) c = conv_findchannel( channel ); - /* RFC's say there is no error reply allowed on NAMES, so when the + /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ if( control || c ) while( u ) @@ -670,7 +670,7 @@ void irc_names( irc_t *irc, char *channel ) else s = ""; - irc_reply( irc, 353, "@ %s :%s%s", channel, s, u->nick ); + irc_reply( irc, 353, "= %s :%s%s", channel, s, u->nick ); } else if( !u->gc ) { @@ -681,7 +681,7 @@ void irc_names( irc_t *irc, char *channel ) else s = ""; - irc_reply( irc, 353, "@ %s :%s%s", channel, s, u->nick ); + irc_reply( irc, 353, "= %s :%s%s", channel, s, u->nick ); } } @@ -696,7 +696,7 @@ void irc_names( irc_t *irc, char *channel ) for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->gc, l->data ) ) ) - irc_reply( irc, 353, "@ %s :%s%s", channel, "", u->nick ); + irc_reply( irc, 353, "= %s :%s%s", channel, "", u->nick ); } irc_reply( irc, 366, "%s :End of /NAMES list", channel ); @@ -734,6 +734,7 @@ void irc_login( irc_t *irc ) irc_reply( irc, 4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); irc_reply( irc, 5, "PREFIX=(ov)@+ CHANTYPES=#& CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server", CMODES, MAX_NICK_LENGTH - 1 ); irc_motd( irc ); + irc->umode[0] = '\0'; irc_umode_set( irc, "+" UMODE, 1 ); u = user_add( irc, irc->mynick ); @@ -841,19 +842,33 @@ void irc_umode_set( irc_t *irc, char *s, int allow_priv ) to set a "privileged" mode (+o, +R, etc). */ char m[256], st = 1, *t; int i; + char changes[512], *p, st2 = 2; + char badflag = 0; memset( m, 0, sizeof( m ) ); for( t = irc->umode; *t; t ++ ) m[(int)*t] = 1; - + + p = changes; for( t = s; *t; t ++ ) { if( *t == '+' || *t == '-' ) st = *t == '+'; else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) ) + { + if( m[(int)*t] != st) + { + if( st != st2 ) + st2 = st, *p++ = st ? '+' : '-'; + *p++ = *t; + } m[(int)*t] = st; + } + else + badflag = 1; } + *p = '\0'; memset( irc->umode, 0, sizeof( irc->umode ) ); @@ -861,7 +876,11 @@ void irc_umode_set( irc_t *irc, char *s, int allow_priv ) if( m[i] ) irc->umode[strlen(irc->umode)] = i; - irc_reply( irc, 221, "+%s", irc->umode ); + if( badflag ) + irc_reply( irc, 501, ":Unknown MODE flag" ); + /* Deliberately no !user@host on the prefix here */ + if( *changes ) + irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes ); } void irc_spawn( irc_t *irc, user_t *u ) diff --git a/irc_commands.c b/irc_commands.c index 3bb24fdb..3a7ace1c 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -118,6 +118,8 @@ static void irc_cmd_mode( irc_t *irc, char **cmd ) { if( cmd[2] ) irc_umode_set( irc, cmd[2], 0 ); + else + irc_reply( irc, 221, "+%s", irc->umode ); } else irc_reply( irc, 502, ":Don't touch their modes" ); @@ -636,6 +638,9 @@ void irc_exec( irc_t *irc, char *cmd[] ) irc_commands[i].execute( irc, cmd ); } - break; + return; } + + if( irc->status >= USTATUS_LOGGED_IN ) + irc_reply( irc, 421, "%s :Unknown command", cmd[0] ); } -- cgit v1.2.3 From c9f0c79af4d1d02e3e37c3d98c0ed33355bce113 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 26 Jun 2006 14:04:21 +0200 Subject: Implemented cleaner way of passing the "Incorrect password" error. --- storage_xml.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/storage_xml.c b/storage_xml.c index 7d72c781..20f3c6a9 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -33,12 +33,11 @@ typedef enum { XML_PASS_CHECK_ONLY = -1, XML_PASS_UNKNOWN = 0, + XML_PASS_WRONG, XML_PASS_OK } xml_pass_st; -/* This isn't very clean, probably making a separate error class + code for - BitlBee would be a better solution. But this will work for now... */ -#define XML_PASS_ERRORMSG "Wrong username or password" +/* To make it easier later when extending the format: */ #define XML_FORMAT_VERSION 1 struct xml_parsedata @@ -107,8 +106,9 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { if( pass_dec[i] != pass_md5[i] ) { + xd->pass_st = XML_PASS_WRONG; g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - XML_PASS_ERRORMSG ); + "Password mismatch" ); break; } } @@ -301,11 +301,12 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password { if( !g_markup_parse_context_parse( ctx, buf, st, &gerr ) || gerr ) { + xml_pass_st pass_st = xd->pass_st; + g_markup_parse_context_free( ctx ); close( fd ); - /* Slightly dirty... */ - if( gerr && strcmp( gerr->message, XML_PASS_ERRORMSG ) == 0 ) + if( pass_st == XML_PASS_WRONG ) { g_clear_error( &gerr ); return STORAGE_INVALID_PASSWORD; @@ -331,6 +332,7 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password irc->status |= USTATUS_IDENTIFIED; + /* TODO: This really shouldn't be here, I think... */ if( set_getint( irc, "auto_connect" ) ) { /* Can't do this directly because r_c_s alters the string */ -- cgit v1.2.3 From 90bbb0efeae19bcc6a1096d8c89fbf3981c83503 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 26 Jun 2006 18:50:47 +0200 Subject: Moved the call to "account on" to the right place. --- root_commands.c | 5 +++++ storage_text.c | 6 ------ storage_xml.c | 8 -------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/root_commands.c b/root_commands.c index e69b9981..47143531 100644 --- a/root_commands.c +++ b/root_commands.c @@ -126,9 +126,12 @@ static void cmd_help( irc_t *irc, char **cmd ) } } +static void cmd_account( irc_t *irc, char **cmd ); + static void cmd_identify( irc_t *irc, char **cmd ) { storage_status_t status = storage_load( irc->nick, cmd[1], irc ); + char *account_on[] = { "account", "on", NULL }; switch (status) { case STORAGE_INVALID_PASSWORD: @@ -140,6 +143,8 @@ static void cmd_identify( irc_t *irc, char **cmd ) case STORAGE_OK: irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); irc_umode_set( irc, "+R", 1 ); + if( set_getint( irc, "auto_connect" ) ) + cmd_account( irc, account_on ); break; case STORAGE_OTHER_ERROR: default: diff --git a/storage_text.c b/storage_text.c index 506c9f03..06d278aa 100644 --- a/storage_text.c +++ b/storage_text.c @@ -116,12 +116,6 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i } fclose( fp ); - if( set_getint( irc, "auto_connect" ) ) - { - strcpy( s, "account on" ); /* Can't do this directly because r_c_s alters the string */ - root_command_string( irc, ru, s, 0 ); - } - return STORAGE_OK; } diff --git a/storage_xml.c b/storage_xml.c index 20f3c6a9..cc3498af 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -332,14 +332,6 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password irc->status |= USTATUS_IDENTIFIED; - /* TODO: This really shouldn't be here, I think... */ - if( set_getint( irc, "auto_connect" ) ) - { - /* Can't do this directly because r_c_s alters the string */ - strcpy( buf, "account on" ); - root_command_string( irc, NULL, buf, 0 ); - } - return STORAGE_OK; } -- cgit v1.2.3 From 3f9440db856c1b1cde54eb919543cfc23ea09983 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 26 Jun 2006 23:50:12 +0200 Subject: /NAMES replies are more efficient now. --- irc.c | 69 +++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/irc.c b/irc.c index 5f69b2ea..816b69d9 100644 --- a/irc.c +++ b/irc.c @@ -648,57 +648,56 @@ void irc_write_all( int now, char *format, ... ) void irc_names( irc_t *irc, char *channel ) { - user_t *u = irc->users; - char *s; - int control = ( g_strcasecmp( channel, irc->channel ) == 0 ); + user_t *u; + char namelist[385] = ""; struct conversation *c = NULL; - if( !control ) - c = conv_findchannel( channel ); - /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ - if( control || c ) while( u ) + if( g_strcasecmp( channel, irc->channel ) == 0 ) { - if( u->online ) + for( u = irc->users; u; u = u->next ) if( u->online ) { - if( u->gc && control ) + if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) { - if( set_getint( irc, "away_devoice" ) && !u->away ) - s = "+"; - else - s = ""; - - irc_reply( irc, 353, "= %s :%s%s", channel, s, u->nick ); - } - else if( !u->gc ) - { - if( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "root" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) ) - s = "@"; - else if( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "user" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) ) - s = "@"; - else - s = ""; - - irc_reply( irc, 353, "= %s :%s%s", channel, s, u->nick ); + irc_reply( irc, 353, "= %s :%s", channel, namelist ); + *namelist = 0; } + + if( u->gc && !u->away && set_getint( irc, "away_devoice" ) ) + strcat( namelist, "+" ); + + strcat( namelist, u->nick ); + strcat( namelist, " " ); } - - u = u->next; } - - /* For non-controlchannel channels (group conversations) only root and - you are listed now. Time to show the channel people: */ - if( !control && c ) + else if( ( c = conv_findchannel( channel ) ) ) { GList *l; + char *ops = set_getstr( irc, "ops" ); - for( l = c->in_room; l; l = l->next ) - if( ( u = user_findhandle( c->gc, l->data ) ) ) - irc_reply( irc, 353, "= %s :%s%s", channel, "", u->nick ); + /* root and the user aren't in the channel userlist but should + show up in /NAMES, so list them first: */ + sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick, + strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick ); + + for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->gc, l->data ) ) ) + { + if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) + { + irc_reply( irc, 353, "= %s :%s", channel, namelist ); + *namelist = 0; + } + + strcat( namelist, u->nick ); + strcat( namelist, " " ); + } } + if( *namelist ) + irc_reply( irc, 353, "= %s :%s", channel, namelist ); + irc_reply( irc, 366, "%s :End of /NAMES list", channel ); } -- cgit v1.2.3 From b3c467bc312114eb7cdd45e6bc36a3d87bee6064 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 28 Jun 2006 11:59:33 +0200 Subject: Cleaned up Makefiles + configure: Cleaning up bitlbee.pc, removed the second piece of libevent probing code that mysteriously appeared (?), better handling of storage backends, an SSL module is now always included (so BitlBee can be compiled again when building without MSN- and Jabber-support (http_client also depends on SSL libs and can't be disabled)), oh, and fixed a compiler warning. --- Makefile | 6 +-- configure | 179 +++++++++++++++++++++++++++----------------------------------- storage.c | 2 +- 3 files changed, 80 insertions(+), 107 deletions(-) diff --git a/Makefile b/Makefile index 36afa236..54e03401 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,10 @@ -include Makefile.settings # Program variables -objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o user.o +objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h subdirs = protocols lib -objects += $(LDAP_OBJ) - # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) CFLAGS += -Wall @@ -43,7 +41,7 @@ clean: $(subdirs) rm -f *.o $(OUTFILE) core utils/bitlbeed encode decode distclean: clean $(subdirs) - rm -f Makefile.settings config.h + rm -f Makefile.settings config.h bitlbee.pc find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; check: diff --git a/configure b/configure index fc9caffe..7cc99b41 100755 --- a/configure +++ b/configure @@ -206,29 +206,6 @@ else fi echo 'EVENT_HANDLER=events_'$events'.o' >> Makefile.settings -if [ "$events" = "libevent" ]; then - if ! [ -e "${libevent}include/event.h" ]; then - echo - echo 'Warning: Could not find event.h, you might have to install it and/or specify' - echo 'its location using the --libevent= argument. (Example: If event.h is in' - echo '/usr/local/include and binaries are in /usr/local/lib: --libevent=/usr/local)' - fi - - echo '#define EVENTS_LIBEVENT' >> config.h - cat <>Makefile.settings -EFLAGS+=-levent -L${libevent}lib -CFLAGS+=-I${libevent}include -EOF -elif [ "$events" = "glib" ]; then - ## We already use glib anyway, so this is all we need (and in fact not even this, but just to be sure...): - echo '#define EVENTS_GLIB' >> config.h -else - echo - echo 'ERROR: Unknown event handler specified.' - exit 1 -fi -echo 'EVENT_HANDLER=events_'$events'.o' >> Makefile.settings - detect_gnutls() { if libgnutls-config --version > /dev/null 2> /dev/null; then @@ -276,78 +253,89 @@ EOF fi } -if [ "$msn" = 1 -o "$jabber" = 1 ]; then - if [ "$ssl" = "auto" ]; then - detect_gnutls - if [ "$ret" = "0" ]; then - detect_nss - fi; - elif [ "$ssl" = "gnutls" ]; then - detect_gnutls; - elif [ "$ssl" = "nss" ]; then - detect_nss; - elif [ "$ssl" = "openssl" ]; then - echo - echo 'No detection code exists for OpenSSL. Make sure that you have a complete' - echo 'install of OpenSSL (including devel/header files) before reporting' - echo 'compilation problems.' - echo - echo 'Also, keep in mind that the OpenSSL is, according to some people, not' - echo 'completely GPL-compatible. Using GnuTLS or NSS is recommended and better' - echo 'supported by us. However, on many BSD machines, OpenSSL can be considered' - echo 'part of the operating system, which makes it GPL-compatible.' - echo - echo 'For more info, see: http://www.openssl.org/support/faq.html#LEGAL2' - echo ' http://www.gnome.org/~markmc/openssl-and-the-gpl.html' - echo - echo 'Please note that distributing a BitlBee binary which links to OpenSSL is' - echo 'probably illegal. If you want to create and distribute a binary BitlBee' - echo 'package, you really should use GnuTLS or NSS instead.' - echo - echo 'Also, the OpenSSL license requires us to say this:' - echo ' * "This product includes software developed by the OpenSSL Project' - echo ' * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"' - - echo 'EFLAGS+=-lssl -lcrypto' >> Makefile.settings - - ret=1; - elif [ "$ssl" = "bogus" ]; then - echo - echo 'Using bogus SSL code. This will not make the MSN module work, but it will' - echo 'allow you to use the Jabber module - although without working SSL support.' - - ret=1; - else - echo - echo 'ERROR: Unknown SSL library specified.' - exit 1; +if [ "$ssl" = "auto" ]; then + detect_gnutls + if [ "$ret" = "0" ]; then + detect_nss fi +elif [ "$ssl" = "gnutls" ]; then + detect_gnutls +elif [ "$ssl" = "nss" ]; then + detect_nss +elif [ "$ssl" = "openssl" ]; then + echo + echo 'No detection code exists for OpenSSL. Make sure that you have a complete' + echo 'install of OpenSSL (including devel/header files) before reporting' + echo 'compilation problems.' + echo + echo 'Also, keep in mind that the OpenSSL is, according to some people, not' + echo 'completely GPL-compatible. Using GnuTLS or NSS is recommended and better' + echo 'supported by us. However, on many BSD machines, OpenSSL can be considered' + echo 'part of the operating system, which makes it GPL-compatible.' + echo + echo 'For more info, see: http://www.openssl.org/support/faq.html#LEGAL2' + echo ' http://www.gnome.org/~markmc/openssl-and-the-gpl.html' + echo + echo 'Please note that distributing a BitlBee binary which links to OpenSSL is' + echo 'probably illegal. If you want to create and distribute a binary BitlBee' + echo 'package, you really should use GnuTLS or NSS instead.' + echo + echo 'Also, the OpenSSL license requires us to say this:' + echo ' * "This product includes software developed by the OpenSSL Project' + echo ' * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"' - if [ "$ret" = "0" ]; then + echo 'EFLAGS+=-lssl -lcrypto' >> Makefile.settings + + ret=1 +elif [ "$ssl" = "bogus" ]; then + echo + echo 'Using bogus SSL code. This means some features have to be disabled.' + + ## Yes, you, at the console! How can you authenticate if you don't have any SSL!? + if [ "$msn" = "1" ]; then echo - echo 'ERROR: Could not find a suitable SSL library (GnuTLS, libnss or OpenSSL).' - echo ' This is necessary for MSN and full Jabber support. To continue,' - echo ' install a suitable SSL library or disable MSN support (--msn=0).' - echo ' If you want Jabber without SSL support you can try --ssl=bogus.' - - exit 1; - fi; + echo 'Real SSL support is necessary for MSN authentication, will build without' + echo 'MSN protocol support.' + msn=0 + fi - echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings + ret=1 +else + echo + echo 'ERROR: Unknown SSL library specified.' + exit 1 fi +if [ "$ret" = "0" ]; then + echo + echo 'ERROR: Could not find a suitable SSL library (GnuTLS, libnss or OpenSSL).' + echo ' Please note that this script doesn'\''t have detection code for OpenSSL,' + echo ' so if you want to use that, you have to select it by hand. If you don'\''t' + echo ' need SSL support, you can select the "bogus" SSL library. (--ssl=bogus)' + + exit 1 +fi; + +echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings + +STORAGES="text xml" + if [ "$ldap" = "auto" ]; then detect_ldap fi if [ "$ldap" = 0 ]; then - echo "LDAP_OBJ=" >> Makefile.settings echo "#undef WITH_LDAP" >> config.h elif [ "$ldap" = 1 ]; then echo "#define WITH_LDAP 1" >> config.h - echo "LDAP_OBJ=storage_ldap.o" >> Makefile.settings + STORAGES="$STORAGES ldap" fi +for i in $STORAGES; do + STORAGE_OBJS="$STORAGE_OBJS storage_$i.o" +done +echo "STORAGE_OBJS="$STORAGE_OBJS >> Makefile.settings + if [ "$strip" = 0 ]; then echo "STRIP=\# skip strip" >> Makefile.settings; else @@ -360,8 +348,6 @@ else echo "STRIP=$STRIP" >> Makefile.settings; elif type strip > /dev/null 2> /dev/null; then echo "STRIP=strip" >> Makefile.settings; - elif /bin/test -x /usr/ccs/bin/strip; then - echo "STRIP=/usr/ccs/bin/strip" >> Makefile.settings; else echo echo 'No strip utility found, cannot remove unnecessary parts from executable.' @@ -440,7 +426,7 @@ fi if [ "$protocols" = "PROTOCOLS = " ]; then echo "WARNING: You haven't selected any communication protocol to compile!" - echo " Bitlbee will run, but you will be unable to connect to IM servers!" + echo " BitlBee will run, but you will be unable to connect to IM servers!" fi echo "PROTOCOLS = $protocols" >> Makefile.settings @@ -475,34 +461,23 @@ echo echo 'Configuration done:' if [ "$debug" = "1" ]; then - echo ' Debugging enabled.'; + echo ' Debugging enabled.' else - echo ' Debugging disabled.'; + echo ' Debugging disabled.' fi if [ "$strip" = "1" ]; then - echo ' Binary stripping enabled.'; + echo ' Binary stripping enabled.' else - echo ' Binary stripping disabled.'; + echo ' Binary stripping disabled.' fi -echo ' Using event handler: '$events; -echo ' Using SSL library: '$ssl; - -#if [ "$flood" = "0" ]; then -# echo ' Flood protection disabled.'; -#else -# echo ' Flood protection enabled.'; -#fi +echo ' Using event handler: '$events +echo ' Using SSL library: '$ssl +echo ' Building with these storage backends: '$STORAGES if [ -n "$protocols" ]; then - echo ' Building with these protocols:' $protocols; -else - echo ' Building without IM-protocol support. We wish you a lot of fun...'; -fi - -if [ "$ldap" = "0" ]; then - echo " LDAP storage backend disabled." + echo ' Building with these protocols:' $protocols else - echo " LDAP storage backend enabled." + echo ' Building without IM-protocol support. We wish you a lot of fun...' fi diff --git a/storage.c b/storage.c index b8e07278..807d5bb4 100644 --- a/storage.c +++ b/storage.c @@ -42,7 +42,7 @@ void register_storage_backend(storage_t *backend) static storage_t *storage_init_single(const char *name) { GList *gl; - storage_t *st; + storage_t *st = NULL; for (gl = storage_backends; gl; gl = gl->next) { st = gl->data; -- cgit v1.2.3 From 171946457cccb7280f0918201093e79bbc9eac72 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 28 Jun 2006 16:47:05 +0200 Subject: Added random_bytes() function for better/more reliable randomization and moved set_eval_ops() to a slightly more suitable place. --- lib/misc.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++----------- lib/misc.h | 10 +++++--- lib/rc4.c | 9 +++++-- set.c | 14 +++++++++++ set.h | 4 +-- storage_xml.c | 5 ++-- 6 files changed, 96 insertions(+), 24 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 9f592289..784d80d6 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2006 Wilmer van der Gaast and others * \********************************************************************/ /* @@ -10,7 +10,7 @@ * * Copyright (C) 1998-1999, Mark Spencer * (and possibly other members of the Gaim team) - * Copyright 2002-2005 Wilmer van der Gaast + * Copyright 2002-2006 Wilmer van der Gaast */ /* @@ -421,17 +421,67 @@ signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t si return( outbuf - dst ); } -char *set_eval_charset( irc_t *irc, set_t *set, char *value ) +/* A pretty reliable random number generator. Tries to use the /dev/random + devices first, and falls back to the random number generator from libc + when it fails. Opens randomizer devices with O_NONBLOCK to make sure a + lack of entropy won't halt BitlBee. */ +void random_bytes( unsigned char *buf, int count ) { - GIConv cd; - - if ( g_strncasecmp( value, "none", 4 ) == 0 ) - return( value ); - - cd = g_iconv_open( "UTF-8", value ); - if( cd == (GIConv) -1 ) - return( NULL ); - - g_iconv_close( cd ); - return( value ); + static int use_dev = -1; + + /* Actually this probing code isn't really necessary, is it? */ + if( use_dev == -1 ) + { + if( access( "/dev/random", R_OK ) == 0 || access( "/dev/urandom", R_OK ) == 0 ) + use_dev = 1; + else + { + use_dev = 0; + srand( ( getpid() << 16 ) ^ time( NULL ) ); + } + } + + if( use_dev ) + { + int fd; + + /* At least on Linux, /dev/random can block if there's not + enough entropy. We really don't want that, so if it can't + give anything, use /dev/urandom instead. */ + if( ( fd = open( "/dev/random", O_RDONLY | O_NONBLOCK ) ) >= 0 ) + if( read( fd, buf, count ) == count ) + { + close( fd ); + return; + } + close( fd ); + + /* urandom isn't supposed to block at all, but just to be + sure. If it blocks, we'll disable use_dev and use the libc + randomizer instead. */ + if( ( fd = open( "/dev/urandom", O_RDONLY | O_NONBLOCK ) ) >= 0 ) + if( read( fd, buf, count ) == count ) + { + close( fd ); + return; + } + close( fd ); + + /* If /dev/random blocks once, we'll still try to use it + again next time. If /dev/urandom also fails for some + reason, stick with libc during this session. */ + + use_dev = 0; + srand( ( getpid() << 16 ) ^ time( NULL ) ); + } + + if( !use_dev ) + { + int i; + + /* Possibly the LSB of rand() isn't very random on some + platforms. Seems okay on at least Linux and OSX though. */ + for( i = 0; i < count; i ++ ) + buf[i] = rand() & 0xff; + } } diff --git a/lib/misc.h b/lib/misc.h index ed019bd8..57ff3e37 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -23,8 +23,11 @@ Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _UTIL_H -#define _UTIL_H +#ifndef _MISC_H +#define _MISC_H + +#include +#include G_MODULE_EXPORT void strip_linefeed( gchar *text ); G_MODULE_EXPORT char *add_cr( char *text ); @@ -44,6 +47,7 @@ G_MODULE_EXPORT char *ipv6_wrap( char *src ); G_MODULE_EXPORT char *ipv6_unwrap( char *src ); G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ); -char *set_eval_charset( irc_t *irc, set_t *set, char *value ); + +G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); #endif diff --git a/lib/rc4.c b/lib/rc4.c index cbe0e2c0..86b74ef5 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -38,8 +38,10 @@ #include +#include #include #include +#include "misc.h" #include "rc4.h" /* Add some seed to the password, to make sure we *never* use the same key. @@ -133,8 +135,11 @@ int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *crypt = g_malloc( clear_len + RC4_IV_LEN ); key = g_malloc( key_len ); strcpy( (char*) key, password ); - for( i = 0; i < RC4_IV_LEN; i ++ ) - key[key_len-RC4_IV_LEN+i] = crypt[0][i] = rand() & 0xff; + + /* Add the salt. Save it for later (when decrypting) and, of course, + add it to the encryption key. */ + random_bytes( crypt[0], RC4_IV_LEN ); + memcpy( key + key_len - RC4_IV_LEN, crypt[0], RC4_IV_LEN ); /* Generate the initial S[] from the IVed key. */ st = rc4_keymaker( key, key_len, RC4_CYCLES ); diff --git a/set.c b/set.c index 60912e10..a26bc17b 100644 --- a/set.c +++ b/set.c @@ -223,3 +223,17 @@ char *set_eval_ops( irc_t *irc, set_t *set, char *value ) return( NULL ); } +char *set_eval_charset( irc_t *irc, set_t *set, char *value ) +{ + GIConv cd; + + if ( g_strncasecmp( value, "none", 4 ) == 0 ) + return( value ); + + cd = g_iconv_open( "UTF-8", value ); + if( cd == (GIConv) -1 ) + return( NULL ); + + g_iconv_close( cd ); + return( value ); +} diff --git a/set.h b/set.h index ebebf2d0..8a7b6747 100644 --- a/set.h +++ b/set.h @@ -46,7 +46,7 @@ void set_del( irc_t *irc, char *key ); char *set_eval_int( irc_t *irc, set_t *set, char *value ); char *set_eval_bool( irc_t *irc, set_t *set, char *value ); + char *set_eval_to_char( irc_t *irc, set_t *set, char *value ); char *set_eval_ops( irc_t *irc, set_t *set, char *value ); - - +char *set_eval_charset( irc_t *irc, set_t *set, char *value ); diff --git a/storage_xml.c b/storage_xml.c index cc3498af..5a8b51ef 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -370,7 +370,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) set_t *set; nick_t *nick; account_t *acc; - int fd, i; + int fd; md5_byte_t pass_md5[21]; md5_state_t md5_state; @@ -395,8 +395,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) /* Generate a salted md5sum of the password. Use 5 bytes for the salt (to prevent dictionary lookups of passwords) to end up with a 21- byte password hash, more convenient for base64 encoding. */ - for( i = 0; i < 5; i ++ ) - pass_md5[16+i] = rand() & 0xff; + random_bytes( pass_md5 + 16, 5 ); md5_init( &md5_state ); md5_append( &md5_state, (md5_byte_t*) irc->password, strlen( irc->password ) ); md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ -- cgit v1.2.3 From 5c9512ffa716f2bc8bbf9e2c31ee40624a0ff842 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 30 Jun 2006 11:17:18 +0200 Subject: Made set.c API more generic so it's not specific to irc_t structures anymore, but can be used for account_t structures too, for example. --- conf.c | 2 +- irc.c | 58 ++++++++++++------------- irc_commands.c | 2 +- nick.c | 2 +- protocols/nogaim.c | 53 +++++++++++------------ protocols/nogaim.h | 2 +- query.c | 4 +- root_commands.c | 6 +-- set.c | 121 +++++++++++++++++++++++++---------------------------- set.h | 36 ++++++++-------- storage_xml.c | 5 +-- user.c | 2 +- 12 files changed, 143 insertions(+), 150 deletions(-) diff --git a/conf.c b/conf.c index d8b8be72..13f150a7 100644 --- a/conf.c +++ b/conf.c @@ -322,7 +322,7 @@ void conf_loaddefaults( irc_t *irc ) { if( g_strcasecmp( ini->section, "defaults" ) == 0 ) { - set_t *s = set_find( irc, ini->key ); + set_t *s = set_find( &irc->set, ini->key ); if( s ) { diff --git a/irc.c b/irc.c index f6e7cbb7..60769735 100644 --- a/irc.c +++ b/irc.c @@ -120,26 +120,26 @@ irc_t *irc_new( int fd ) irc_connection_list = g_slist_append( irc_connection_list, irc ); - set_add( irc, "away_devoice", "true", set_eval_away_devoice ); - set_add( irc, "auto_connect", "true", set_eval_bool ); - set_add( irc, "auto_reconnect", "false", set_eval_bool ); - set_add( irc, "auto_reconnect_delay", "300", set_eval_int ); - set_add( irc, "buddy_sendbuffer", "false", set_eval_bool ); - set_add( irc, "buddy_sendbuffer_delay", "200", set_eval_int ); - set_add( irc, "charset", "iso8859-1", set_eval_charset ); - set_add( irc, "debug", "false", set_eval_bool ); - set_add( irc, "default_target", "root", NULL ); - set_add( irc, "display_namechanges", "false", set_eval_bool ); - set_add( irc, "handle_unknown", "root", NULL ); - set_add( irc, "lcnicks", "true", set_eval_bool ); - set_add( irc, "ops", "both", set_eval_ops ); - set_add( irc, "private", "true", set_eval_bool ); - set_add( irc, "query_order", "lifo", NULL ); - set_add( irc, "save_on_quit", "true", set_eval_bool ); - set_add( irc, "strip_html", "true", NULL ); - set_add( irc, "to_char", ": ", set_eval_to_char ); - set_add( irc, "typing_notice", "false", set_eval_bool ); - set_add( irc, "password", NULL, passchange); + set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); + set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); + set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc ); + set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc ); + set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); + set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); + set_add( &irc->set, "charset", "iso8859-1", set_eval_charset, irc ); + set_add( &irc->set, "debug", "false", set_eval_bool, irc ); + set_add( &irc->set, "default_target", "root", NULL, irc ); + set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); + set_add( &irc->set, "handle_unknown", "root", NULL, irc ); + set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); + set_add( &irc->set, "ops", "both", set_eval_ops, irc ); + set_add( &irc->set, "password", NULL, passchange, irc ); + set_add( &irc->set, "private", "true", set_eval_bool, irc ); + set_add( &irc->set, "query_order", "lifo", NULL, irc ); + set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); + set_add( &irc->set, "strip_html", "true", NULL, irc ); + set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); + set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); conf_loaddefaults( irc ); @@ -211,7 +211,7 @@ void irc_free(irc_t * irc) log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); - if( irc->status & USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) ) + if( irc->status & USTATUS_IDENTIFIED && set_getint( &irc->set, "save_on_quit" ) ) if( storage_save( irc, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); @@ -363,7 +363,7 @@ void irc_process( irc_t *irc ) break; } - if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) + if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) { conv[IRC_MAX_LINE] = 0; if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) != -1 ) @@ -583,7 +583,7 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); strip_newlines( line ); - if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) + if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) { char conv[IRC_MAX_LINE+1]; @@ -665,7 +665,7 @@ void irc_names( irc_t *irc, char *channel ) { if( u->gc && control ) { - if( set_getint( irc, "away_devoice" ) && !u->away ) + if( set_getint( &irc->set, "away_devoice" ) && !u->away ) s = "+"; else s = ""; @@ -674,9 +674,9 @@ void irc_names( irc_t *irc, char *channel ) } else if( !u->gc ) { - if( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "root" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) ) + if( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( set_getstr( &irc->set, "ops" ), "root" ) == 0 || strcmp( set_getstr( &irc->set, "ops" ), "both" ) == 0 ) ) s = "@"; - else if( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( set_getstr( irc, "ops" ), "user" ) == 0 || strcmp( set_getstr( irc, "ops" ), "both" ) == 0 ) ) + else if( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( set_getstr( &irc->set, "ops" ), "user" ) == 0 || strcmp( set_getstr( &irc->set, "ops" ), "both" ) == 0 ) ) s = "@"; else s = ""; @@ -1083,7 +1083,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) { if( !u || !u->gc ) return; - if( set_getint( irc, "buddy_sendbuffer" ) && set_getint( irc, "buddy_sendbuffer_delay" ) > 0 ) + if( set_getint( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) { int delay; @@ -1110,7 +1110,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) strcat( u->sendbuf, msg ); strcat( u->sendbuf, "\n" ); - delay = set_getint( irc, "buddy_sendbuffer_delay" ); + delay = set_getint( &irc->set, "buddy_sendbuffer_delay" ); if( delay <= 5 ) delay *= 1000; @@ -1175,7 +1175,7 @@ int irc_msgfrom( irc_t *irc, char *nick, char *msg ) { int len = strlen( irc->nick) + 3; prefix = g_new (char, len ); - g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( irc, "to_char" ) ); + g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) ); prefix[len-1] = 0; } else diff --git a/irc_commands.c b/irc_commands.c index 3a7ace1c..a3fa0e6e 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -229,7 +229,7 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd ) if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) { unsigned int i; - char *t = set_getstr( irc, "default_target" ); + char *t = set_getstr( &irc->set, "default_target" ); if( g_strcasecmp( t, "last" ) == 0 && irc->last_target ) cmd[1] = irc->last_target; diff --git a/nick.c b/nick.c index 68dd9802..56d6d378 100644 --- a/nick.c +++ b/nick.c @@ -85,7 +85,7 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname ); nick_strip( nick ); - if (set_getint(irc, "lcnicks")) + if( set_getint( &irc->set, "lcnicks" ) ) nick_lc( nick ); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 04d1ee3e..f94d936d 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -219,8 +219,8 @@ void serv_got_crap( struct gaim_connection *gc, char *format, ... ) text = g_strdup_vprintf( format, params ); va_end( params ); - if( ( g_strcasecmp( set_getstr( gc->irc, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) strip_html( text ); /* Try to find a different connection on the same protocol. */ @@ -323,9 +323,9 @@ void signoff( struct gaim_connection *gc ) { /* Uhm... This is very sick. */ } - else if( !gc->wants_to_die && set_getint( irc, "auto_reconnect" ) ) + else if( !gc->wants_to_die && set_getint( &irc->set, "auto_reconnect" ) ) { - int delay = set_getint( irc, "auto_reconnect_delay" ); + int delay = set_getint( &irc->set, "auto_reconnect_delay" ); serv_got_crap( gc, "Reconnecting in %d seconds..", delay ); a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); @@ -364,12 +364,12 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea char *s; irc_t *irc = gc->irc; - if( set_getint( irc, "debug" ) && 0 ) /* This message is too useless */ + if( set_getint( &irc->set, "debug" ) && 0 ) /* This message is too useless */ serv_got_crap( gc, "Receiving user add from handle: %s", handle ); if( user_findhandle( gc, handle ) ) { - if( set_getint( irc, "debug" ) ) + if( set_getint( &irc->set, "debug" ) ) serv_got_crap( gc, "User already exists, ignoring add request: %s", handle ); return; @@ -457,7 +457,7 @@ void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname u->realname = g_strdup( realname ); - if( ( gc->flags & OPT_LOGGED_IN ) && set_getint( gc->irc, "display_namechanges" ) ) + if( ( gc->flags & OPT_LOGGED_IN ) && set_getint( &gc->irc->set, "display_namechanges" ) ) serv_got_crap( gc, "User `%s' changed name to `%s'", u->nick, u->realname ); } } @@ -513,14 +513,14 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in if( !u ) { - if( g_strcasecmp( set_getstr( gc->irc, "handle_unknown" ), "add" ) == 0 ) + if( g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "add" ) == 0 ) { add_buddy( gc, NULL, handle, NULL ); u = user_findhandle( gc, handle ); } else { - if( set_getint( gc->irc, "debug" ) || g_strcasecmp( set_getstr( gc->irc, "handle_unknown" ), "ignore" ) != 0 ) + if( set_getint( &gc->irc->set, "debug" ) || g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { serv_got_crap( gc, "serv_got_update() for handle %s:", handle ); serv_got_crap( gc, "loggedin = %d, type = %d", loggedin, type ); @@ -579,7 +579,7 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in u->away = NULL; /* LISPy... */ - if( ( set_getint( gc->irc, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ + if( ( set_getint( &gc->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ ( u->online ) && /* Don't touch offline people */ ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ @@ -598,18 +598,18 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f if( !u ) { - char *h = set_getstr( irc, "handle_unknown" ); + char *h = set_getstr( &irc->set, "handle_unknown" ); if( g_strcasecmp( h, "ignore" ) == 0 ) { - if( set_getint( irc, "debug" ) ) + if( set_getint( &irc->set, "debug" ) ) serv_got_crap( gc, "Ignoring message from unknown handle %s", handle ); return; } else if( g_strncasecmp( h, "add", 3 ) == 0 ) { - int private = set_getint( irc, "private" ); + int private = set_getint( &irc->set, "private" ); if( h[3] ) { @@ -630,8 +630,8 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f } } - if( ( g_strcasecmp( set_getstr( gc->irc, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) strip_html( msg ); while( strlen( msg ) > 425 ) @@ -671,7 +671,7 @@ void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int { user_t *u; - if( !set_getint( gc->irc, "typing_notice" ) ) + if( !set_getint( &gc->irc->set, "typing_notice" ) ) return; if( ( u = user_findhandle( gc, handle ) ) ) { @@ -693,7 +693,7 @@ void serv_got_chat_left( struct gaim_connection *gc, int id ) struct conversation *c, *l = NULL; GList *ir; - if( set_getint( gc->irc, "debug" ) ) + if( set_getint( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "You were removed from conversation %d", (int) id ); for( c = gc->conversations; c && c->id != id; c = (l=c)->next ); @@ -738,8 +738,8 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe u = user_findhandle( gc, who ); for( c = gc->conversations; c && c->id != id; c = c->next ); - if( ( g_strcasecmp( set_getstr( gc->irc, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) strip_html( msg ); if( c && u ) @@ -772,7 +772,7 @@ struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, c c->channel = g_strdup( s ); g_free( s ); - if( set_getint( gc->irc, "debug" ) ) + if( set_getint( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "Creating new conversation: (id=%d,handle=%s)", id, handle ); return( c ); @@ -786,7 +786,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) user_t *u = user_findhandle( b->gc, handle ); int me = 0; - if( set_getint( b->gc->irc, "debug" ) ) + if( set_getint( &b->gc->irc->set, "debug" ) ) serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); /* It might be yourself! */ @@ -820,7 +820,7 @@ void remove_chat_buddy( struct conversation *b, char *handle, char *reason ) user_t *u; int me = 0; - if( set_getint( b->gc->irc, "debug" ) ) + if( set_getint( &b->gc->irc->set, "debug" ) ) serv_got_crap( b->gc, "User %s removed from conversation %d (%s)", handle, b->id, reason ? reason : "" ); /* It might be yourself! */ @@ -882,8 +882,9 @@ struct conversation *conv_findchannel( char *channel ) return( NULL ); } -char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value ) +char *set_eval_away_devoice( set_t *set, char *value ) { + irc_t *irc = set->data; int st; if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) @@ -897,7 +898,7 @@ char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value ) /* Horror.... */ - if( st != set_getint( irc, "away_devoice" ) ) + if( st != set_getint( &irc->set, "away_devoice" ) ) { char list[80] = ""; user_t *u = irc->users; @@ -937,7 +938,7 @@ char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value ) irc->channel, pm, v, list ); } - return( set_eval_bool( irc, set, value ) ); + return( set_eval_bool( set, value ) ); } @@ -1017,7 +1018,7 @@ int bim_set_away( struct gaim_connection *gc, char *away ) if( s ) { gc->prpl->set_away( gc, s, away ); - if( set_getint( gc->irc, "debug" ) ) + if( set_getint( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "Setting away state to %s", s ); } else diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 2080465c..4d71da24 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -205,7 +205,7 @@ void bim_add_block( struct gaim_connection *gc, char *handle ); void bim_rem_block( struct gaim_connection *gc, char *handle ); void nogaim_init(); -char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value ); +char *set_eval_away_devoice( set_t *set, char *value ); gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); void cancel_auto_reconnect( struct account *a ); diff --git a/query.c b/query.c index 39821f3a..40dbb439 100644 --- a/query.c +++ b/query.c @@ -62,7 +62,7 @@ query_t *query_add( irc_t *irc, struct gaim_connection *gc, char *question, void irc->queries = q; } - if( g_strcasecmp( set_getstr( irc, "query_order" ), "lifo" ) == 0 || irc->queries == q ) + if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "lifo" ) == 0 || irc->queries == q ) query_display( irc, q ); return( q ); @@ -171,7 +171,7 @@ static query_t *query_default( irc_t *irc ) { query_t *q; - if( g_strcasecmp( set_getstr( irc, "query_order" ), "fifo" ) == 0 ) + if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 ) q = irc->queries; else for( q = irc->queries; q && q->next; q = q->next ); diff --git a/root_commands.c b/root_commands.c index 47143531..815d618b 100644 --- a/root_commands.c +++ b/root_commands.c @@ -143,7 +143,7 @@ static void cmd_identify( irc_t *irc, char **cmd ) case STORAGE_OK: irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); irc_umode_set( irc, "+R", 1 ); - if( set_getint( irc, "auto_connect" ) ) + if( set_getint( &irc->set, "auto_connect" ) ) cmd_account( irc, account_on ); break; case STORAGE_OTHER_ERROR: @@ -671,14 +671,14 @@ static void cmd_set( irc_t *irc, char **cmd ) { if( cmd[1] && cmd[2] ) { - set_setstr( irc, cmd[1], cmd[2] ); + set_setstr( &irc->set, cmd[1], cmd[2] ); if( ( strcmp( cmd[2], "=" ) ) == 0 && cmd[3] ) irc_usermsg( irc, "Warning: Correct syntax: \002set \002 (without =)" ); } if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ { - char *s = set_getstr( irc, cmd[1] ); + char *s = set_getstr( &irc->set, cmd[1] ); if( s ) irc_usermsg( irc, "%s = `%s'", cmd[1], s ); } diff --git a/set.c b/set.c index a26bc17b..b511a358 100644 --- a/set.c +++ b/set.c @@ -25,23 +25,24 @@ #define BITLBEE_CORE #include "bitlbee.h" -set_t *set_add( irc_t *irc, char *key, char *def, void *eval ) +set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ) { - set_t *s = set_find( irc, key ); + set_t *s = set_find( head, key ); + /* Possibly the setting already exists. If it doesn't exist yet, + we create it. If it does, we'll just change the default. */ if( !s ) { - if( ( s = irc->set ) ) + if( ( s = *head ) ) { while( s->next ) s = s->next; - s->next = g_new ( set_t, 1 ); + s->next = g_new0( set_t, 1 ); s = s->next; } else { - s = irc->set = g_new( set_t, 1 ); + s = *head = g_new0( set_t, 1 ); } - memset( s, 0, sizeof( set_t ) ); s->key = g_strdup( key ); } @@ -52,19 +53,15 @@ set_t *set_add( irc_t *irc, char *key, char *def, void *eval ) } if( def ) s->def = g_strdup( def ); - if( s->eval ) - { - g_free( s->eval ); - s->eval = NULL; - } - if( eval ) s->eval = eval; + s->eval = eval; + s->data = data; - return( s ); + return s; } -set_t *set_find( irc_t *irc, char *key ) +set_t *set_find( set_t **head, char *key ) { - set_t *s = irc->set; + set_t *s = *head; while( s ) { @@ -73,46 +70,46 @@ set_t *set_find( irc_t *irc, char *key ) s = s->next; } - return( s ); + return s; } -char *set_getstr( irc_t *irc, char *key ) +char *set_getstr( set_t **head, char *key ) { - set_t *s = set_find( irc, key ); + set_t *s = set_find( head, key ); if( !s || ( !s->value && !s->def ) ) - return( NULL ); + return NULL; - return( s->value?s->value:s->def ); + return s->value ? s->value : s->def; } -int set_getint( irc_t *irc, char *key ) +int set_getint( set_t **head, char *key ) { - char *s = set_getstr( irc, key ); + char *s = set_getstr( head, key ); int i = 0; if( !s ) - return( 0 ); + return 0; if( ( g_strcasecmp( s, "true" ) == 0 ) || ( g_strcasecmp( s, "yes" ) == 0 ) || ( g_strcasecmp( s, "on" ) == 0 ) ) - return( 1 ); + return 1; if( sscanf( s, "%d", &i ) != 1 ) - return( 0 ); + return 0; - return( i ); + return i; } -int set_setstr( irc_t *irc, char *key, char *value ) +int set_setstr( set_t **head, char *key, char *value ) { - set_t *s = set_find( irc, key ); + set_t *s = set_find( head, key ); char *nv = value; if( !s ) - s = set_add( irc, key, NULL, NULL ); + s = set_add( head, key, NULL, NULL, NULL ); - if( s->eval && !( nv = s->eval( irc, s, value ) ) ) - return( 0 ); + if( s->eval && !( nv = s->eval( s, value ) ) ) + return 0; if( s->value ) { @@ -120,26 +117,28 @@ int set_setstr( irc_t *irc, char *key, char *value ) s->value = NULL; } + /* If there's a default setting and it's equal to what we're trying to + set, stick with s->value = NULL. Otherwise, remember the setting. */ if( !s->def || ( strcmp( nv, s->def ) != 0 ) ) s->value = g_strdup( nv ); if( nv != value ) g_free( nv ); - return( 1 ); + return 1; } -int set_setint( irc_t *irc, char *key, int value ) +int set_setint( set_t **head, char *key, int value ) { char s[24]; /* Not quite 128-bit clean eh? ;-) */ - sprintf( s, "%d", value ); - return( set_setstr( irc, key, s ) ); + g_snprintf( s, sizeof( s ), "%d", value ); + return set_setstr( head, key, s ); } -void set_del( irc_t *irc, char *key ) +void set_del( set_t **head, char *key ) { - set_t *s = irc->set, *t = NULL; + set_t *s = *head, *t = NULL; while( s ) { @@ -152,7 +151,7 @@ void set_del( irc_t *irc, char *key ) if( t ) t->next = s->next; else - irc->set = s->next; + *head = s->next; g_free( s->key ); if( s->value ) g_free( s->value ); @@ -161,27 +160,27 @@ void set_del( irc_t *irc, char *key ) } } -char *set_eval_int( irc_t *irc, set_t *set, char *value ) +char *set_eval_int( set_t *set, char *value ) { - char *s = value; + char *s; - for( ; *s; s ++ ) + for( s = value; *s; s ++ ) if( *s < '0' || *s > '9' ) - return( NULL ); + return NULL; - return( value ); + return value; } -char *set_eval_bool( irc_t *irc, set_t *set, char *value ) +char *set_eval_bool( set_t *set, char *value ) { if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) return( value ); if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) return( value ); - return( set_eval_int( irc, set, value ) ); + return( set_eval_int( set, value ) ); } -char *set_eval_to_char( irc_t *irc, set_t *set, char *value ) +char *set_eval_to_char( set_t *set, char *value ) { char *s = g_new( char, 3 ); @@ -190,50 +189,42 @@ char *set_eval_to_char( irc_t *irc, set_t *set, char *value ) else sprintf( s, "%c ", *value ); - return( s ); + return s; } -char *set_eval_ops( irc_t *irc, set_t *set, char *value ) +char *set_eval_ops( set_t *set, char *value ) { + irc_t *irc = set->data; + if( g_strcasecmp( value, "user" ) == 0 ) - { irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, irc->channel, "+o-o", irc->nick, irc->mynick ); - return( value ); - } else if( g_strcasecmp( value, "root" ) == 0 ) - { irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, irc->channel, "-o+o", irc->nick, irc->mynick ); - return( value ); - } else if( g_strcasecmp( value, "both" ) == 0 ) - { irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, irc->channel, "+oo", irc->nick, irc->mynick ); - return( value ); - } else if( g_strcasecmp( value, "none" ) == 0 ) - { irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, irc->channel, "-oo", irc->nick, irc->mynick ); - return( value ); - } + else + return NULL; - return( NULL ); + return value; } -char *set_eval_charset( irc_t *irc, set_t *set, char *value ) +char *set_eval_charset( set_t *set, char *value ) { GIConv cd; if ( g_strncasecmp( value, "none", 4 ) == 0 ) - return( value ); + return value; cd = g_iconv_open( "UTF-8", value ); if( cd == (GIConv) -1 ) - return( NULL ); + return NULL; g_iconv_close( cd ); - return( value ); + return value; } diff --git a/set.h b/set.h index 8a7b6747..15e97b5d 100644 --- a/set.h +++ b/set.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2006 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to register, handle and save user preferences */ @@ -25,28 +25,30 @@ typedef struct set { + void *data; + char *key; char *value; char *def; /* Default */ - /* Eval: Returns NULL if the value is incorrect. Can return a - corrected value. set_setstr() should be able to free() the - returned string! */ - char *(*eval) ( irc_t *irc, struct set *set, char *value ); + /* Eval: Returns NULL if the value is incorrect or exactly the + passed value variable. When returning a corrected value, + set_setstr() should be able to free() the returned string! */ + char *(*eval) ( struct set *set, char *value ); struct set *next; } set_t; -set_t *set_add( irc_t *irc, char *key, char *def, void *eval ); -G_MODULE_EXPORT set_t *set_find( irc_t *irc, char *key ); -G_MODULE_EXPORT char *set_getstr( irc_t *irc, char *key ); -G_MODULE_EXPORT int set_getint( irc_t *irc, char *key ); -int set_setstr( irc_t *irc, char *key, char *value ); -int set_setint( irc_t *irc, char *key, int value ); -void set_del( irc_t *irc, char *key ); +set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ); +G_MODULE_EXPORT set_t *set_find( set_t **head, char *key ); +G_MODULE_EXPORT char *set_getstr( set_t **head, char *key ); +G_MODULE_EXPORT int set_getint( set_t **head, char *key ); +int set_setstr( set_t **head, char *key, char *value ); +int set_setint( set_t **head, char *key, int value ); +void set_del( set_t **head, char *key ); -char *set_eval_int( irc_t *irc, set_t *set, char *value ); -char *set_eval_bool( irc_t *irc, set_t *set, char *value ); +char *set_eval_int( set_t *set, char *value ); +char *set_eval_bool( set_t *set, char *value ); -char *set_eval_to_char( irc_t *irc, set_t *set, char *value ); -char *set_eval_ops( irc_t *irc, set_t *set, char *value ); -char *set_eval_charset( irc_t *irc, set_t *set, char *value ); +char *set_eval_to_char( set_t *set, char *value ); +char *set_eval_ops( set_t *set, char *value ); +char *set_eval_charset( set_t *set, char *value ); diff --git a/storage_xml.c b/storage_xml.c index 5a8b51ef..e0ffc481 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -245,7 +245,7 @@ static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_le else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting && xd->current_account == NULL ) { - set_setstr( irc, xd->current_setting, (char*) text ); + set_setstr( &irc->set, xd->current_setting, (char*) text ); g_free( xd->current_setting ); xd->current_setting = NULL; } @@ -420,14 +420,13 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) pass_len = rc4_encode( (unsigned char*) acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); pass_b64 = base64_encode( pass_rc4, pass_len ); + g_free( pass_rc4 ); if( !xml_printf( fd, "\tprpl->name, acc->user, pass_b64, acc->auto_connect ) ) { - g_free( pass_rc4 ); g_free( pass_b64 ); goto write_error; } - g_free( pass_rc4 ); g_free( pass_b64 ); if( acc->server && acc->server[0] && !xml_printf( fd, " server=\"%s\"", acc->server ) ) diff --git a/user.c b/user.c index 5f0952f5..30228c70 100644 --- a/user.c +++ b/user.c @@ -66,7 +66,7 @@ user_t *user_add( irc_t *irc, char *nick ) } u->user = u->realname = u->host = u->nick = g_strdup( nick ); - u->is_private = set_getint( irc, "private" ); + u->is_private = set_getint( &irc->set, "private" ); key = g_strdup( nick ); nick_lc( key ); -- cgit v1.2.3 From 0a3c243b6659dc10efb227e507f324c2711d6dcd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 1 Jul 2006 01:18:56 +0200 Subject: Got rid of struct aim_user (now using account_t everywhere). Needs some more testing though. --- account.c | 13 +------ irc.c | 14 +++---- irc_commands.c | 16 ++++---- protocols/jabber/jabber.c | 24 ++++++------ protocols/msn/msn.c | 6 +-- protocols/nogaim.c | 99 ++++++++++++++++++++--------------------------- protocols/nogaim.h | 24 ++---------- protocols/oscar/oscar.c | 35 +++++++---------- protocols/yahoo/yahoo.c | 8 ++-- root_commands.c | 35 +++++++++-------- user.c | 2 +- 11 files changed, 115 insertions(+), 161 deletions(-) diff --git a/account.c b/account.c index b75afa51..ced62e25 100644 --- a/account.c +++ b/account.c @@ -142,8 +142,6 @@ void account_del( irc_t *irc, account_t *acc ) void account_on( irc_t *irc, account_t *a ) { - struct aim_user *u; - if( a->gc ) { /* Trying to enable an already-enabled account */ @@ -152,17 +150,8 @@ void account_on( irc_t *irc, account_t *a ) cancel_auto_reconnect( a ); - u = g_new0 ( struct aim_user, 1 ); - u->irc = irc; - u->prpl = a->prpl; - strncpy( u->username, a->user, sizeof( u->username ) - 1 ); - strncpy( u->password, a->pass, sizeof( u->password ) - 1 ); - if( a->server) strncpy( u->proto_opt[0], a->server, sizeof( u->proto_opt[0] ) - 1 ); - - a->gc = (struct gaim_connection *) u; /* Bit hackish :-/ */ a->reconnect = 0; - - a->prpl->login( u ); + a->prpl->login( a ); } void account_off( irc_t *irc, account_t *a ) diff --git a/irc.c b/irc.c index 60769735..d93fbe44 100644 --- a/irc.c +++ b/irc.c @@ -924,19 +924,19 @@ void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker ) void irc_kill( irc_t *irc, user_t *u ) { char *nick, *s; - char reason[64]; + char reason[128]; if( u->gc && u->gc->flags & OPT_LOGGING_OUT ) { - if( u->gc->user->proto_opt[0][0] ) + if( u->gc->acc->server ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, - u->gc->user->proto_opt[0] ); + u->gc->acc->server ); else if( ( s = strchr( u->gc->username, '@' ) ) ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, s + 1 ); else g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, - u->gc->prpl->name, irc->myhost ); + u->gc->acc->prpl->name, irc->myhost ); /* proto_opt might contain garbage after the : */ if( ( s = strchr( reason, ':' ) ) ) @@ -1012,13 +1012,13 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) } else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 ) { - if( u && u->gc && u->gc->prpl->send_typing && strlen( s ) >= 10 ) + if( u && u->gc && u->gc->acc->prpl->send_typing && strlen( s ) >= 10 ) { time_t current_typing_notice = time( NULL ); if( current_typing_notice - u->last_typing_notice >= 5 ) { - u->gc->prpl->send_typing( u->gc, u->handle, s[8] == '1' ); + u->gc->acc->prpl->send_typing( u->gc, u->handle, s[8] == '1' ); u->last_typing_notice = current_typing_notice; } } @@ -1051,7 +1051,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) return 1; } } - else if( c && c->gc && c->gc->prpl ) + else if( c && c->gc && c->gc->acc && c->gc->acc->prpl ) { return( bim_chat_msg( c->gc, c->id, s ) ); } diff --git a/irc_commands.c b/irc_commands.c index a3fa0e6e..889de9da 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -149,10 +149,10 @@ static void irc_cmd_part( irc_t *irc, char **cmd ) irc_part( irc, u, c->channel ); - if( c->gc && c->gc->prpl ) + if( c->gc ) { c->joined = 0; - c->gc->prpl->chat_leave( c->gc, c->id ); + c->gc->acc->prpl->chat_leave( c->gc, c->id ); } } else @@ -172,11 +172,11 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) { user_t *u = user_find( irc, cmd[1] + 1 ); - if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open ) + if( u && u->gc && u->gc->acc->prpl->chat_open ) { irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] ); - if( !u->gc->prpl->chat_open( u->gc, u->handle ) ) + if( !u->gc->acc->prpl->chat_open( u->gc, u->handle ) ) { irc_usermsg( irc, "Could not open a groupchat with %s.", u->nick ); } @@ -204,9 +204,9 @@ static void irc_cmd_invite( irc_t *irc, char **cmd ) user_t *u = user_find( irc, nick ); if( u && c && ( u->gc == c->gc ) ) - if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite ) + if( c->gc && c->gc->acc->prpl->chat_invite ) { - c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle ); + c->gc->acc->prpl->chat_invite( c->gc, c->id, "", u->handle ); irc_reply( irc, 341, "%s %s", nick, channel ); return; } @@ -476,8 +476,8 @@ static void irc_cmd_whois( irc_t *irc, char **cmd ) irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname ); if( u->gc ) - irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username, - *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name ); + irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->acc->user, + *u->gc->acc->server ? u->gc->acc->server : "", u->gc->acc->prpl->name ); else irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 029473fd..c8e8ceca 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -560,29 +560,29 @@ static gboolean gjab_connected_ssl(gpointer data, void *source, b_input_conditio static void gjab_start(gjconn gjc) { - struct aim_user *user; + account_t *acc; int port = -1, ssl = 0; char *server = NULL, *s; if (!gjc || gjc->state != JCONN_STATE_OFF) return; - user = GJ_GC(gjc)->user; - if (*user->proto_opt[0]) { + acc = GJ_GC(gjc)->acc; + if (acc->server) { /* If there's a dot, assume there's a hostname in the beginning */ - if (strchr(user->proto_opt[0], '.')) { - server = g_strdup(user->proto_opt[0]); + if (strchr(acc->server, '.')) { + server = g_strdup(acc->server); if ((s = strchr(server, ':'))) *s = 0; } /* After the hostname, there can be a port number */ - s = strchr(user->proto_opt[0], ':'); + s = strchr(acc->server, ':'); if (s && isdigit(s[1])) sscanf(s + 1, "%d", &port); /* And if there's the string ssl, the user wants an SSL-connection */ - if (strstr(user->proto_opt[0], ":ssl") || g_strcasecmp(user->proto_opt[0], "ssl") == 0) + if (strstr(acc->server, ":ssl") || g_strcasecmp(acc->server, "ssl") == 0) ssl = 1; } @@ -615,7 +615,7 @@ static void gjab_start(gjconn gjc) g_free(server); - if (!user->gc || (gjc->fd < 0)) { + if (!acc->gc || (gjc->fd < 0)) { STATE_EVT(JCONN_STATE_OFF) return; } @@ -1515,18 +1515,18 @@ static void jabber_handlestate(gjconn gjc, int state) return; } -static void jabber_login(struct aim_user *user) +static void jabber_login(account_t *acc) { - struct gaim_connection *gc = new_gaim_conn(user); + struct gaim_connection *gc = new_gaim_conn(acc); struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); - char *loginname = create_valid_jid(user->username, DEFAULT_SERVER, "BitlBee"); + char *loginname = create_valid_jid(acc->user, DEFAULT_SERVER, "BitlBee"); jd->hash = g_hash_table_new(g_str_hash, g_str_equal); jd->chats = NULL; /* we have no chats yet */ set_login_progress(gc, 1, _("Connecting")); - if (!(jd->gjc = gjab_new(loginname, user->password, gc))) { + if (!(jd->gjc = gjab_new(loginname, acc->pass, gc))) { g_free(loginname); hide_login_progress(gc, _("Unable to connect")); signoff(gc); diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 6393f31d..b00354c9 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -26,9 +26,9 @@ #include "nogaim.h" #include "msn.h" -static void msn_login( struct aim_user *acct ) +static void msn_login( account_t *acc ) { - struct gaim_connection *gc = new_gaim_conn( acct ); + struct gaim_connection *gc = new_gaim_conn( acc ); struct msn_data *md = g_new0( struct msn_data, 1 ); set_login_progress( gc, 1, "Connecting" ); @@ -36,7 +36,7 @@ static void msn_login( struct aim_user *acct ) gc->proto_data = md; md->fd = -1; - if( strchr( acct->username, '@' ) == NULL ) + if( strchr( acc->user, '@' ) == NULL ) { hide_login_progress( gc, "Invalid account name" ); signoff( gc ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index f94d936d..8346f5fa 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -144,33 +144,21 @@ GSList *get_connections() { return connections; } /* multi.c */ -struct gaim_connection *new_gaim_conn( struct aim_user *user ) +struct gaim_connection *new_gaim_conn( account_t *acc ) { struct gaim_connection *gc; - account_t *a; gc = g_new0( struct gaim_connection, 1 ); - gc->prpl = user->prpl; - g_snprintf( gc->username, sizeof( gc->username ), "%s", user->username ); - g_snprintf( gc->password, sizeof( gc->password ), "%s", user->password ); - /* [MD] BUGFIX: don't set gc->irc to the global IRC, but use the one from the struct aim_user. - * This fixes daemon mode breakage where IRC doesn't point to the currently active connection. - */ - gc->irc = user->irc; - - connections = g_slist_append( connections, gc ); + /* Maybe we should get rid of this memory waste later. ;-) */ + g_snprintf( gc->username, sizeof( gc->username ), "%s", acc->user ); + g_snprintf( gc->password, sizeof( gc->password ), "%s", acc->pass ); - user->gc = gc; - gc->user = user; + gc->irc = acc->irc; + gc->acc = acc; + acc->gc = gc; - // Find the account_t so we can set its gc pointer - for( a = gc->irc->accounts; a; a = a->next ) - if( ( struct aim_user * ) a->gc == user ) - { - a->gc = gc; - break; - } + connections = g_slist_append( connections, gc ); return( gc ); } @@ -188,7 +176,6 @@ void destroy_gaim_conn( struct gaim_connection *gc ) } connections = g_slist_remove( connections, gc ); - g_free( gc->user ); g_free( gc ); } @@ -225,14 +212,14 @@ void serv_got_crap( struct gaim_connection *gc, char *format, ... ) /* Try to find a different connection on the same protocol. */ for( a = gc->irc->accounts; a; a = a->next ) - if( a->prpl == gc->prpl && a->gc != gc ) + if( a->prpl == gc->acc->prpl && a->gc != gc ) break; /* If we found one, include the screenname in the message. */ if( a ) - irc_usermsg( gc->irc, "%s(%s) - %s", gc->prpl->name, gc->username, text ); + irc_usermsg( gc->irc, "%s(%s) - %s", gc->acc->prpl->name, gc->username, text ); else - irc_usermsg( gc->irc, "%s - %s", gc->prpl->name, text ); + irc_usermsg( gc->irc, "%s - %s", gc->acc->prpl->name, text ); g_free( text ); } @@ -241,8 +228,8 @@ static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) { struct gaim_connection *gc = d; - if( gc->prpl && gc->prpl->keepalive ) - gc->prpl->keepalive( gc ); + if( gc->acc->prpl->keepalive ) + gc->acc->prpl->keepalive( gc ); return TRUE; } @@ -298,7 +285,7 @@ void signoff( struct gaim_connection *gc ) gc->flags |= OPT_LOGGING_OUT; gc->keepalive = 0; - gc->prpl->close( gc ); + gc->acc->prpl->close( gc ); b_event_remove( gc->inpa ); while( u ) @@ -378,7 +365,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( gc->irc, handle, gc->prpl, realname ) ); + strcpy( nick, nick_get( gc->irc, handle, gc->acc->prpl, realname ) ); u = user_add( gc->irc, nick ); @@ -390,15 +377,15 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea u->host = g_strdup( s + 1 ); u->user = g_strndup( handle, s - handle ); } - else if( gc->user->proto_opt[0] && *gc->user->proto_opt[0] ) + else if( *gc->acc->server ) { char *colon; - if( ( colon = strchr( gc->user->proto_opt[0], ':' ) ) ) - u->host = g_strndup( gc->user->proto_opt[0], - colon - gc->user->proto_opt[0] ); + if( ( colon = strchr( gc->acc->server, ':' ) ) ) + u->host = g_strndup( gc->acc->server, + colon - gc->acc->server ); else - u->host = g_strdup( gc->user->proto_opt[0] ); + u->host = g_strdup( gc->acc->server ); u->user = g_strdup( handle ); @@ -409,7 +396,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } else { - u->host = g_strdup( gc->user->prpl->name ); + u->host = g_strdup( gc->acc->prpl->name ); u->user = g_strdup( handle ); } @@ -479,7 +466,7 @@ void show_got_added_no( gpointer w, struct show_got_added_data *data ) void show_got_added_yes( gpointer w, struct show_got_added_data *data ) { - data->gc->prpl->add_buddy( data->gc, data->handle ); + data->gc->acc->prpl->add_buddy( data->gc, data->handle ); add_buddy( data->gc, NULL, data->handle, data->handle ); return show_got_added_no( w, data ); @@ -558,11 +545,11 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in remove_chat_buddy_silent( c, handle ); } - if( ( type & UC_UNAVAILABLE ) && ( !strcmp(gc->prpl->name, "oscar") || !strcmp(gc->prpl->name, "icq")) ) + if( ( type & UC_UNAVAILABLE ) && ( strcmp( gc->acc->prpl->name, "oscar" ) == 0 || strcmp( gc->acc->prpl->name, "icq" ) == 0 ) ) { u->away = g_strdup( "Away" ); } - else if( ( type & UC_UNAVAILABLE ) && ( !strcmp(gc->prpl->name, "jabber") ) ) + else if( ( type & UC_UNAVAILABLE ) && ( strcmp( gc->acc->prpl->name, "jabber" ) == 0 ) ) { if( type & UC_DND ) u->away = g_strdup( "Do Not Disturb" ); @@ -571,9 +558,9 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in else // if( type & UC_AWAY ) u->away = g_strdup( "Away" ); } - else if( ( type & UC_UNAVAILABLE ) && gc->prpl->get_status_string ) + else if( ( type & UC_UNAVAILABLE ) && gc->acc->prpl->get_status_string ) { - u->away = g_strdup( gc->prpl->get_status_string( gc, type ) ); + u->away = g_strdup( gc->acc->prpl->get_status_string( gc, type ) ); } else u->away = NULL; @@ -732,7 +719,7 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe user_t *u; /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ - if( g_strcasecmp( who, gc->user->username ) == 0 ) + if( g_strcasecmp( who, gc->username ) == 0 ) return; u = user_findhandle( gc, who ); @@ -790,7 +777,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); /* It might be yourself! */ - if( b->gc->prpl->cmp_buddynames( handle, b->gc->user->username ) == 0 ) + if( b->gc->acc->prpl->cmp_buddynames( handle, b->gc->username ) == 0 ) { u = user_find( b->gc->irc, b->gc->irc->nick ); if( !b->joined ) @@ -824,7 +811,7 @@ void remove_chat_buddy( struct conversation *b, char *handle, char *reason ) serv_got_crap( b->gc, "User %s removed from conversation %d (%s)", handle, b->id, reason ? reason : "" ); /* It might be yourself! */ - if( g_strcasecmp( handle, b->gc->user->username ) == 0 ) + if( g_strcasecmp( handle, b->gc->username ) == 0 ) { u = user_find( b->gc->irc, b->gc->irc->nick ); b->joined = 0; @@ -958,7 +945,7 @@ int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flag msg = buf; } - st = gc->prpl->send_im( gc, handle, msg, strlen( msg ), flags ); + st = gc->acc->prpl->send_im( gc, handle, msg, strlen( msg ), flags ); g_free( buf ); return st; @@ -975,7 +962,7 @@ int bim_chat_msg( struct gaim_connection *gc, int id, char *msg ) msg = buf; } - st = gc->prpl->chat_send( gc, id, msg ); + st = gc->acc->prpl->chat_send( gc, id, msg ); g_free( buf ); return st; @@ -989,7 +976,7 @@ int bim_set_away( struct gaim_connection *gc, char *away ) char *s; if( !away ) away = ""; - ms = m = gc->prpl->away_states( gc ); + ms = m = gc->acc->prpl->away_states( gc ); while( m ) { @@ -1010,19 +997,19 @@ int bim_set_away( struct gaim_connection *gc, char *away ) if( m ) { - gc->prpl->set_away( gc, m->data, *away ? away : NULL ); + gc->acc->prpl->set_away( gc, m->data, *away ? away : NULL ); } else { s = bim_away_alias_find( ms, away ); if( s ) { - gc->prpl->set_away( gc, s, away ); + gc->acc->prpl->set_away( gc, s, away ); if( set_getint( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "Setting away state to %s", s ); } else - gc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away ); + gc->acc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away ); } g_list_free( ms ); @@ -1074,46 +1061,46 @@ static char *bim_away_alias_find( GList *gcm, char *away ) void bim_add_allow( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) { gc->permit = g_slist_prepend( gc->permit, g_strdup( handle ) ); } - gc->prpl->add_permit( gc, handle ); + gc->acc->prpl->add_permit( gc, handle ); } void bim_rem_allow( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) { g_free( l->data ); gc->permit = g_slist_delete_link( gc->permit, l ); } - gc->prpl->rem_permit( gc, handle ); + gc->acc->prpl->rem_permit( gc, handle ); } void bim_add_block( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) { gc->deny = g_slist_prepend( gc->deny, g_strdup( handle ) ); } - gc->prpl->add_deny( gc, handle ); + gc->acc->prpl->add_deny( gc, handle ); } void bim_rem_block( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) { g_free( l->data ); gc->deny = g_slist_delete_link( gc->deny, l ); } - gc->prpl->rem_deny( gc, handle ); + gc->acc->prpl->rem_deny( gc, handle ); } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 4d71da24..8c6519c1 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -38,6 +38,7 @@ #define _NOGAIM_H #include "bitlbee.h" +#include "account.h" #include "proxy.h" #include "md5.h" #include "sha.h" @@ -62,7 +63,7 @@ /* ok. now the fun begins. first we create a connection structure */ struct gaim_connection { - struct prpl *prpl; + account_t *acc; guint32 flags; /* each connection then can have its own protocol-specific data */ @@ -78,8 +79,6 @@ struct gaim_connection GSList *deny; int permdeny; - struct aim_user *user; - char username[64]; char displayname[128]; char password[32]; @@ -125,26 +124,11 @@ struct buddy { struct gaim_connection *gc; /* the connection it belongs to */ }; -struct aim_user { - char username[64]; - char alias[SELF_ALIAS_LEN]; - char password[32]; - char user_info[2048]; - int options; - struct prpl *prpl; - /* prpls can use this to save information about the user, - * like which server to connect to, etc */ - char proto_opt[7][256]; - - struct gaim_connection *gc; - irc_t *irc; -}; - struct prpl { int options; const char *name; - void (* login) (struct aim_user *); + void (* login) (account_t *); void (* keepalive) (struct gaim_connection *); void (* close) (struct gaim_connection *); @@ -211,7 +195,7 @@ gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); void cancel_auto_reconnect( struct account *a ); /* multi.c */ -G_MODULE_EXPORT struct gaim_connection *new_gaim_conn( struct aim_user *user ); +G_MODULE_EXPORT struct gaim_connection *new_gaim_conn( account_t *acc ); G_MODULE_EXPORT void destroy_gaim_conn( struct gaim_connection *gc ); G_MODULE_EXPORT void set_login_progress( struct gaim_connection *gc, int step, char *msg ); G_MODULE_EXPORT void hide_login_progress( struct gaim_connection *gc, char *msg ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 7c76533a..d55ce3f2 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -355,18 +355,18 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio return FALSE; } -static void oscar_login(struct aim_user *user) { +static void oscar_login(account_t *acc) { aim_session_t *sess; aim_conn_t *conn; char buf[256]; - struct gaim_connection *gc = new_gaim_conn(user); + struct gaim_connection *gc = new_gaim_conn(acc); struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1); - if (isdigit(*user->username)) { + if (isdigit(acc->user[0])) { odata->icq = TRUE; /* This is odd but it's necessary for a proper do_import and do_export. We don't do those anymore, but let's stick with it, just in case - it accidentally fixes something else too... */ + it accidentally fixes something else too... */ gc->password[8] = 0; } else { gc->flags |= OPT_CONN_HTML; @@ -389,9 +389,9 @@ static void oscar_login(struct aim_user *user) { return; } - if (g_strcasecmp(user->proto_opt[USEROPT_AUTH], "login.icq.com") != 0 && - g_strcasecmp(user->proto_opt[USEROPT_AUTH], "login.oscar.aol.com") != 0) { - serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",user->proto_opt[USEROPT_AUTH]); + if (g_strcasecmp(acc->server, "login.icq.com") != 0 && + g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { + serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); } g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username); @@ -401,11 +401,7 @@ static void oscar_login(struct aim_user *user) { aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); conn->status |= AIM_CONN_STATUS_INPROGRESS; - conn->fd = proxy_connect(user->proto_opt[USEROPT_AUTH][0] ? - user->proto_opt[USEROPT_AUTH] : AIM_DEFAULT_LOGIN_SERVER, - user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : AIM_LOGIN_PORT, - oscar_login_connect, gc); + conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, gc); if (conn->fd < 0) { hide_login_progress(gc, _("Couldn't connect to host")); signoff(gc); @@ -484,14 +480,11 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; struct aim_authresp_info *info; int i; char *host; int port; - struct aim_user *user; aim_conn_t *bosconn; struct gaim_connection *gc = sess->aux_data; struct oscar_data *od = gc->proto_data; - user = gc->user; - port = user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : AIM_LOGIN_PORT, + port = AIM_LOGIN_PORT; va_start(ap, fr); info = va_arg(ap, struct aim_authresp_info *); @@ -870,19 +863,16 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; struct aim_redirect_data *redir; struct gaim_connection *gc = sess->aux_data; - struct aim_user *user = gc->user; aim_conn_t *tstconn; int i; char *host; int port; - port = user->proto_opt[USEROPT_AUTHPORT][0] ? - atoi(user->proto_opt[USEROPT_AUTHPORT]) : AIM_LOGIN_PORT, - va_start(ap, fr); redir = va_arg(ap, struct aim_redirect_data *); va_end(ap); + port = AIM_LOGIN_PORT; for (i = 0; i < (int)strlen(redir->ip); i++) { if (redir->ip[i] == ':') { port = atoi(&(redir->ip[i+1])); @@ -1722,8 +1712,11 @@ static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) odata->rights.maxsiglen = odata->rights.maxawaymsglen = (guint)maxsiglen; + /* FIXME: It seems we're not really using this, and it broke now that + struct aim_user is dead. aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps); - + */ + return 1; } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 79c0febb..c21779ba 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -120,16 +120,16 @@ static char *byahoo_strip( char *in ) return( g_strndup( in, len ) ); } -static void byahoo_login( struct aim_user *user ) +static void byahoo_login( account_t *acc ) { - struct gaim_connection *gc = new_gaim_conn( user ); + struct gaim_connection *gc = new_gaim_conn( acc ); struct byahoo_data *yd = gc->proto_data = g_new0( struct byahoo_data, 1 ); yd->logged_in = FALSE; yd->current_status = YAHOO_STATUS_AVAILABLE; set_login_progress( gc, 1, "Connecting" ); - yd->y2_id = yahoo_init( user->username, user->password ); + yd->y2_id = yahoo_init( acc->user, acc->pass ); yahoo_login( yd->y2_id, yd->current_status ); } @@ -424,7 +424,7 @@ static struct gaim_connection *byahoo_get_gc_by_id( int id ) gc = l->data; yd = gc->proto_data; - if( !strcmp(gc->prpl->name, "yahoo") && yd->y2_id == id ) + if( strcmp( gc->acc->prpl->name, "yahoo" ) == 0 && yd->y2_id == id ) return( gc ); } diff --git a/root_commands.c b/root_commands.c index 815d618b..3bd80e5e 100644 --- a/root_commands.c +++ b/root_commands.c @@ -399,14 +399,14 @@ static void cmd_add( irc_t *irc, char **cmd ) } else { - nick_set( irc, cmd[2], a->gc->prpl, cmd[3] ); + nick_set( irc, cmd[2], a->gc->acc->prpl, cmd[3] ); } } /* By making this optional, you can talk to people without having to add them to your *real* (server-side) contact list. */ if( add_for_real ) - a->gc->prpl->add_buddy( a->gc, cmd[2] ); + a->gc->acc->prpl->add_buddy( a->gc, cmd[2] ); add_buddy( a->gc, NULL, cmd[2], cmd[2] ); @@ -440,13 +440,13 @@ static void cmd_info( irc_t *irc, char **cmd ) return; } - if( !gc->prpl->get_info ) + if( !gc->acc->prpl->get_info ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } else { - gc->prpl->get_info( gc, cmd[2] ); + gc->acc->prpl->get_info( gc, cmd[2] ); } } @@ -481,7 +481,7 @@ static void cmd_rename( irc_t *irc, char **cmd ) } else if( u->send_handler == buddy_send_handler ) { - nick_set( irc, u->handle, u->gc->prpl, cmd[2] ); + nick_set( irc, u->handle, u->gc->acc->prpl, cmd[2] ); } irc_usermsg( irc, "Nick successfully changed" ); @@ -500,7 +500,7 @@ static void cmd_remove( irc_t *irc, char **cmd ) } s = g_strdup( u->handle ); - u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); + u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); user_del( irc, cmd[1] ); nick_del( irc, cmd[1] ); @@ -557,7 +557,7 @@ static void cmd_block( irc_t *irc, char **cmd ) return; } - if( !gc->prpl->add_deny || !gc->prpl->rem_permit ) + if( !gc->acc->prpl->add_deny || !gc->acc->prpl->rem_permit ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } @@ -616,7 +616,7 @@ static void cmd_allow( irc_t *irc, char **cmd ) return; } - if( !gc->prpl->rem_deny || !gc->prpl->add_permit ) + if( !gc->acc->prpl->rem_deny || !gc->acc->prpl->add_permit ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } @@ -732,7 +732,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( online == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, "Online" ); } @@ -743,7 +743,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( away == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, u->away ); } n_away ++; @@ -753,7 +753,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( offline == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, "Offline" ); } n_offline ++; @@ -778,7 +778,7 @@ static void cmd_nick( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Your name is `%s'" , a->gc->displayname ? a->gc->displayname : "NULL" ); } - else if ( !a->gc->prpl->set_info ) + else if ( !a->prpl->set_info ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } @@ -786,7 +786,7 @@ static void cmd_nick( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); - a->gc->prpl->set_info( a->gc, cmd[2] ); + a->prpl->set_info( a->gc, cmd[2] ); } } @@ -805,7 +805,7 @@ static void cmd_qlist( irc_t *irc, char **cmd ) for( num = 0; q; q = q->next, num ++ ) if( q->gc ) /* Not necessary yet, but it might come later */ - irc_usermsg( irc, "%d, %s(%s): %s", num, q->gc->prpl->name, q->gc->username, q->question ); + irc_usermsg( irc, "%d, %s(%s): %s", num, q->gc->acc->prpl->name, q->gc->username, q->question ); else irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } @@ -833,10 +833,11 @@ static void cmd_import_buddies( irc_t *irc, char **cmd ) { user_t *u; + /* FIXME: Hmmm, this is actually pretty dangerous code... REMOVEME? :-) */ for( u = irc->users; u; u = u->next ) if( u->gc == gc ) { - u->gc->prpl->remove_buddy( u->gc, u->handle, NULL ); + u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); user_del( irc, u->nick ); } @@ -851,9 +852,9 @@ static void cmd_import_buddies( irc_t *irc, char **cmd ) for( n = gc->irc->nicks; n; n = n->next ) { - if( n->proto == gc->prpl && !user_findhandle( gc, n->handle ) ) + if( n->proto == gc->acc->prpl && !user_findhandle( gc, n->handle ) ) { - gc->prpl->add_buddy( gc, n->handle ); + gc->acc->prpl->add_buddy( gc, n->handle ); add_buddy( gc, NULL, n->handle, NULL ); } } diff --git a/user.c b/user.c index 30228c70..cb70ab68 100644 --- a/user.c +++ b/user.c @@ -146,7 +146,7 @@ user_t *user_findhandle( struct gaim_connection *gc, char *handle ) while( u ) { - if( u->gc == gc && u->handle && gc->prpl->cmp_buddynames ( u->handle, handle ) == 0 ) + if( u->gc == gc && u->handle && gc->acc->prpl->cmp_buddynames ( u->handle, handle ) == 0 ) break; u = u->next; } -- cgit v1.2.3 From 5100caa16bb707d89f1873aca99b5f87abc1dd56 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 1 Jul 2006 17:52:05 +0200 Subject: Added "account set" command. --- account.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ account.h | 5 +++++ lib/misc.c | 34 ++++++++++++++++++++++++++++ lib/misc.h | 3 +++ lib/rc4.c | 2 +- root_commands.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- set.c | 18 ++++++++++----- set.h | 4 +++- storage_xml.c | 65 ++++++++++++++++++++++++++++------------------------- 9 files changed, 220 insertions(+), 40 deletions(-) diff --git a/account.c b/account.c index ced62e25..4e399e8a 100644 --- a/account.c +++ b/account.c @@ -27,9 +27,12 @@ #include "bitlbee.h" #include "account.h" +char *set_eval_account( set_t *set, char *value ); + account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) { account_t *a; + set_t *s; if( irc->accounts ) { @@ -47,9 +50,63 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) a->auto_connect = 1; a->irc = irc; + s = set_add( &a->set, "auto_connect", NULL, set_eval_account, a ); + s->flags |= ACC_SET_NOSAVE; + + s = set_add( &a->set, "password", NULL, set_eval_account, a ); + s->flags |= ACC_SET_NOSAVE; + + s = set_add( &a->set, "server", NULL, set_eval_account, a ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; + + s = set_add( &a->set, "username", NULL, set_eval_account, a ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; + set_setstr( &a->set, "username", user ); + return( a ); } +char *set_eval_account( set_t *set, char *value ) +{ + account_t *acc = set->data; + + /* Double-check: We refuse to edit on-line accounts. */ + if( acc->gc ) + return NULL; + + if( strcmp( set->key, "username" ) == 0 ) + { + g_free( acc->user ); + acc->user = g_strdup( value ); + return value; + } + else if( strcmp( set->key, "password" ) == 0 ) + { + g_free( acc->pass ); + acc->pass = g_strdup( value ); + return NULL; /* password shouldn't be visible in plaintext! */ + } + else if( strcmp( set->key, "server" ) == 0 ) + { + g_free( acc->server ); + if( *value ) + acc->server = g_strdup( value ); + else + acc->server = NULL; + return value; + } + else if( strcmp( set->key, "auto_connect" ) == 0 ) + { + if( !is_bool( value ) ) + return NULL; + + acc->auto_connect = bool2int( value ); + return value; + } + + return NULL; +} + account_t *account_get( irc_t *irc, char *id ) { account_t *a, *ret = NULL; @@ -129,6 +186,9 @@ void account_del( irc_t *irc, account_t *acc ) irc->accounts = a->next; } + while( a->set ) + set_del( &a->set, a->set->key ); + g_free( a->user ); g_free( a->pass ); if( a->server ) g_free( a->server ); diff --git a/account.h b/account.h index 40efb101..9fed399e 100644 --- a/account.h +++ b/account.h @@ -36,6 +36,8 @@ typedef struct account int auto_connect; int reconnect; + set_t *set; + struct irc *irc; struct gaim_connection *gc; struct account *next; @@ -47,4 +49,7 @@ void account_del( irc_t *irc, account_t *acc ); void account_on( irc_t *irc, account_t *a ); void account_off( irc_t *irc, account_t *a ); +#define ACC_SET_NOSAVE 1 +#define ACC_SET_OFFLINE_ONLY 2 + #endif diff --git a/lib/misc.c b/lib/misc.c index 784d80d6..17599946 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -485,3 +485,37 @@ void random_bytes( unsigned char *buf, int count ) buf[i] = rand() & 0xff; } } + +int is_bool( char *value ) +{ + if( *value == 0 ) + return 0; + + if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) + return 1; + if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) + return 1; + + while( *value ) + if( !isdigit( *value ) ) + return 0; + else + value ++; + + return 1; +} + +int bool2int( char *value ) +{ + int i; + + if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) + return 1; + if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) + return 0; + + if( sscanf( value, "%d", &i ) == 1 ) + return i; + + return 0; +} diff --git a/lib/misc.h b/lib/misc.h index 57ff3e37..b021e642 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -50,4 +50,7 @@ G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); +G_MODULE_EXPORT int is_bool( char *value ); +G_MODULE_EXPORT int bool2int( char *value ); + #endif diff --git a/lib/rc4.c b/lib/rc4.c index 86b74ef5..5e334507 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -164,7 +164,7 @@ int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char if( clear_len < 0 ) { - *clear = g_strdup( "" ); + *clear = (unsigned char*) g_strdup( "" ); return 0; } diff --git a/root_commands.c b/root_commands.c index 3bd80e5e..b975b0f4 100644 --- a/root_commands.c +++ b/root_commands.c @@ -231,9 +231,8 @@ static void cmd_account( irc_t *irc, char **cmd ) } a = account_add( irc, prpl, cmd[3], cmd[4] ); - if( cmd[5] ) - a->server = g_strdup( cmd[5] ); + set_setstr( &a->set, "server", cmd[5] ); irc_usermsg( irc, "Account successfully added" ); } @@ -357,6 +356,68 @@ static void cmd_account( irc_t *irc, char **cmd ) return; } } + else if( g_strcasecmp( cmd[1], "set" ) == 0 ) + { + char *acc_handle, *set_name = NULL, *tmp; + + if( !cmd[2] ) + { + irc_usermsg( irc, "Not enough parameters given (need %d)", 2 ); + return; + } + + acc_handle = g_strdup( cmd[2] ); + if( ( tmp = strchr( acc_handle, '/' ) ) ) + { + *tmp = 0; + set_name = tmp + 1; + } + a = account_get( irc, acc_handle ); + + if( a == NULL ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + + if( cmd[3] ) + { + set_t *s = set_find( &a->set, set_name ); + + if( a->gc && s && s->flags & ACC_SET_OFFLINE_ONLY ) + { + irc_usermsg( irc, "This setting can only be changed when the account is off-line" ); + return; + } + + set_setstr( &a->set, set_name, cmd[3] ); + + if( ( strcmp( cmd[3], "=" ) ) == 0 && cmd[4] ) + irc_usermsg( irc, "Warning: Correct syntax: \002account set \002 (without =)" ); + } + if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ + { + char *s = set_getstr( &a->set, set_name ); + if( s ) + irc_usermsg( irc, "%s = `%s'", set_name, s ); + else + irc_usermsg( irc, "%s is empty", set_name ); + } + else + { + set_t *s = a->set; + while( s ) + { + if( s->value || s->def ) + irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); + else + irc_usermsg( irc, "%s is empty", s->key ); + s = s->next; + } + } + + g_free( acc_handle ); + } else { irc_usermsg( irc, "Unknown command: account %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[1] ); @@ -681,6 +742,8 @@ static void cmd_set( irc_t *irc, char **cmd ) char *s = set_getstr( &irc->set, cmd[1] ); if( s ) irc_usermsg( irc, "%s = `%s'", cmd[1], s ); + else + irc_usermsg( irc, "%s is empty", cmd[1] ); } else { @@ -689,6 +752,8 @@ static void cmd_set( irc_t *irc, char **cmd ) { if( s->value || s->def ) irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); + else + irc_usermsg( irc, "%s is empty", s->key ); s = s->next; } } diff --git a/set.c b/set.c index b511a358..4620264f 100644 --- a/set.c +++ b/set.c @@ -100,6 +100,16 @@ int set_getint( set_t **head, char *key ) return i; } +int set_getbool( set_t **head, char *key ) +{ + char *s = set_getstr( head, key ); + + if( !s ) + return 0; + + return bool2int( s ); +} + int set_setstr( set_t **head, char *key, char *value ) { set_t *s = set_find( head, key ); @@ -165,7 +175,7 @@ char *set_eval_int( set_t *set, char *value ) char *s; for( s = value; *s; s ++ ) - if( *s < '0' || *s > '9' ) + if( !isdigit( *s ) ) return NULL; return value; @@ -173,11 +183,7 @@ char *set_eval_int( set_t *set, char *value ) char *set_eval_bool( set_t *set, char *value ) { - if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) - return( value ); - if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) - return( value ); - return( set_eval_int( set, value ) ); + return is_bool( value ) ? value : NULL; } char *set_eval_to_char( set_t *set, char *value ) diff --git a/set.h b/set.h index 15e97b5d..4731f80a 100644 --- a/set.h +++ b/set.h @@ -31,6 +31,8 @@ typedef struct set char *value; char *def; /* Default */ + int flags; + /* Eval: Returns NULL if the value is incorrect or exactly the passed value variable. When returning a corrected value, set_setstr() should be able to free() the returned string! */ @@ -39,7 +41,7 @@ typedef struct set } set_t; set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ); -G_MODULE_EXPORT set_t *set_find( set_t **head, char *key ); +set_t *set_find( set_t **head, char *key ); G_MODULE_EXPORT char *set_getstr( set_t **head, char *key ); G_MODULE_EXPORT int set_getint( set_t **head, char *key ); int set_setstr( set_t **head, char *key, char *value ); diff --git a/storage_xml.c b/storage_xml.c index e0ffc481..701d5144 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -156,11 +156,9 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { xd->current_account = account_add( irc, prpl, handle, password ); if( server ) - xd->current_account->server = g_strdup( server ); + set_setstr( &xd->current_account->set, "server", server ); if( autoconnect ) - /* Return value doesn't matter, since account_add() already sets - a default! */ - sscanf( autoconnect, "%d", &xd->current_account->auto_connect ); + set_setstr( &xd->current_account->set, "auto_connect", autoconnect ); } else { @@ -175,22 +173,19 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na } else if( g_strcasecmp( element_name, "setting" ) == 0 ) { - if( xd->current_account == NULL ) + char *setting; + + if( xd->current_setting ) { - char *setting; - - if( xd->current_setting ) - { - g_free( xd->current_setting ); - xd->current_setting = NULL; - } - - if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) ) - xd->current_setting = g_strdup( setting ); - else - g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Missing attributes for %s element", element_name ); + g_free( xd->current_setting ); + xd->current_setting = NULL; } + + if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) ) + xd->current_setting = g_strdup( setting ); + else + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Missing attributes for %s element", element_name ); } else if( g_strcasecmp( element_name, "buddy" ) == 0 ) { @@ -242,10 +237,10 @@ static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_le the password, or if we didn't get the chance to check it yet. */ } - else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && - xd->current_setting && xd->current_account == NULL ) + else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting ) { - set_setstr( &irc->set, xd->current_setting, (char*) text ); + set_setstr( xd->current_account ? &xd->current_account->set : &irc->set, + xd->current_setting, (char*) text ); g_free( xd->current_setting ); xd->current_setting = NULL; } @@ -347,12 +342,17 @@ static storage_status_t xml_check_pass( const char *my_nick, const char *passwor return xml_load_real( my_nick, password, NULL, XML_PASS_CHECK_ONLY ); } -static int xml_printf( int fd, char *fmt, ... ) +static int xml_printf( int fd, int indent, char *fmt, ... ) { va_list params; char *out; + char tabs[9] = "\t\t\t\t\t\t\t\t"; int len; + /* Maybe not very clean, but who needs more than 8 levels of indentation anyway? */ + if( write( fd, tabs, indent <= 8 ? indent : 8 ) != indent ) + return 0; + va_start( params, fmt ); out = g_markup_vprintf_escaped( fmt, params ); va_end( params ); @@ -403,14 +403,14 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) /* Save the hash in base64-encoded form. */ pass_buf = base64_encode( (char*) pass_md5, 21 ); - if( !xml_printf( fd, "\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) ) + if( !xml_printf( fd, 0, "\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) ) goto write_error; g_free( pass_buf ); for( set = irc->set; set; set = set->next ) if( set->value && set->def ) - if( !xml_printf( fd, "\t%s\n", set->key, set->value ) ) + if( !xml_printf( fd, 1, "%s\n", set->key, set->value ) ) goto write_error; for( acc = irc->accounts; acc; acc = acc->next ) @@ -422,28 +422,33 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) pass_b64 = base64_encode( pass_rc4, pass_len ); g_free( pass_rc4 ); - if( !xml_printf( fd, "\tprpl->name, acc->user, pass_b64, acc->auto_connect ) ) + if( !xml_printf( fd, 1, "prpl->name, acc->user, pass_b64, acc->auto_connect ) ) { g_free( pass_b64 ); goto write_error; } g_free( pass_b64 ); - if( acc->server && acc->server[0] && !xml_printf( fd, " server=\"%s\"", acc->server ) ) + if( acc->server && acc->server[0] && !xml_printf( fd, 0, " server=\"%s\"", acc->server ) ) goto write_error; - if( !xml_printf( fd, ">\n" ) ) + if( !xml_printf( fd, 0, ">\n" ) ) goto write_error; + for( set = acc->set; set; set = set->next ) + if( set->value && set->def && !( set->flags & ACC_SET_NOSAVE ) ) + if( !xml_printf( fd, 2, "%s\n", set->key, set->value ) ) + goto write_error; + for( nick = irc->nicks; nick; nick = nick->next ) if( nick->proto == acc->prpl ) - if( !xml_printf( fd, "\t\t\n", nick->handle, nick->nick ) ) + if( !xml_printf( fd, 2, "\n", nick->handle, nick->nick ) ) goto write_error; - if( !xml_printf( fd, "\t\n" ) ) + if( !xml_printf( fd, 1, "\n" ) ) goto write_error; } - if( !xml_printf( fd, "\n" ) ) + if( !xml_printf( fd, 0, "\n" ) ) goto write_error; close( fd ); -- cgit v1.2.3 From 96863f65118767e968469e82ba6b02006e36b81c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Jul 2006 11:49:31 +0200 Subject: Added protocol-specific settings, made the server setting specific to only OSCAR and Jabber. --- account.c | 12 +++---- account.h | 2 ++ protocols/jabber/jabber.c | 89 ++++++++++++++++++++++++++++++++--------------- protocols/nogaim.h | 1 + protocols/oscar/oscar.c | 15 ++++++++ 5 files changed, 84 insertions(+), 35 deletions(-) diff --git a/account.c b/account.c index 186565dd..1f2ec165 100644 --- a/account.c +++ b/account.c @@ -27,8 +27,6 @@ #include "bitlbee.h" #include "account.h" -char *set_eval_account( set_t *set, char *value ); - account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) { account_t *a; @@ -50,19 +48,21 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) a->auto_connect = 1; a->irc = irc; - s = set_add( &a->set, "auto_connect", NULL, set_eval_account, a ); + s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; s = set_add( &a->set, "password", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; - s = set_add( &a->set, "server", NULL, set_eval_account, a ); - s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; - s = set_add( &a->set, "username", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; set_setstr( &a->set, "username", user ); + /* This function adds some more settings (and might want to do more + things that have to be done now, although I can't think of anything. */ + if( prpl->acc_init ) + prpl->acc_init( a ); + return( a ); } diff --git a/account.h b/account.h index 9fed399e..adb63f9e 100644 --- a/account.h +++ b/account.h @@ -49,6 +49,8 @@ void account_del( irc_t *irc, account_t *acc ); void account_on( irc_t *irc, account_t *a ); void account_off( irc_t *irc, account_t *a ); +char *set_eval_account( set_t *set, char *value ); + #define ACC_SET_NOSAVE 1 #define ACC_SET_OFFLINE_ONLY 2 diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index c8e8ceca..e7f4534e 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -562,35 +562,17 @@ static void gjab_start(gjconn gjc) { account_t *acc; int port = -1, ssl = 0; - char *server = NULL, *s; + char *server = NULL; if (!gjc || gjc->state != JCONN_STATE_OFF) return; acc = GJ_GC(gjc)->acc; - if (acc->server) { - /* If there's a dot, assume there's a hostname in the beginning */ - if (strchr(acc->server, '.')) { - server = g_strdup(acc->server); - if ((s = strchr(server, ':'))) - *s = 0; - } - - /* After the hostname, there can be a port number */ - s = strchr(acc->server, ':'); - if (s && isdigit(s[1])) - sscanf(s + 1, "%d", &port); - - /* And if there's the string ssl, the user wants an SSL-connection */ - if (strstr(acc->server, ":ssl") || g_strcasecmp(acc->server, "ssl") == 0) - ssl = 1; - } + server = acc->server; + port = set_getint(&acc->set, "port"); + ssl = set_getbool(&acc->set, "ssl"); - if (port == -1 && !ssl) - port = DEFAULT_PORT; - else if (port == -1 && ssl) - port = DEFAULT_PORT_SSL; - else if (port < JABBER_PORT_MIN || port > JABBER_PORT_MAX) { + if (port < JABBER_PORT_MIN || port > JABBER_PORT_MAX) { serv_got_crap(GJ_GC(gjc), "For security reasons, the Jabber port number must be in the %d-%d range.", JABBER_PORT_MIN, JABBER_PORT_MAX); STATE_EVT(JCONN_STATE_OFF) return; @@ -613,8 +595,6 @@ static void gjab_start(gjconn gjc) gjc->fd = proxy_connect(server, port, gjab_connected, GJ_GC(gjc)); } - g_free(server); - if (!acc->gc || (gjc->fd < 0)) { STATE_EVT(JCONN_STATE_OFF) return; @@ -1515,12 +1495,62 @@ static void jabber_handlestate(gjconn gjc, int state) return; } -static void jabber_login(account_t *acc) +static void jabber_acc_init(account_t *acc) { - struct gaim_connection *gc = new_gaim_conn(acc); - struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); - char *loginname = create_valid_jid(acc->user, DEFAULT_SERVER, "BitlBee"); + set_t *s; + + s = set_add( &acc->set, "port", "5222", set_eval_int, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; +} +static void jabber_login(account_t *acc) +{ + struct gaim_connection *gc; + struct jabber_data *jd; + char *resource, *loginname; + + /* Time to move some data/things from the old syntax to the new one: */ + if (acc->server) { + char *s, *tmp_server; + int port; + + if (g_strcasecmp(acc->server, "ssl") == 0) { + set_setstr(&acc->set, "server", ""); + set_setint(&acc->set, "port", DEFAULT_PORT_SSL); + set_setstr(&acc->set, "ssl", "true"); + + g_free(acc->server); + acc->server = NULL; + } else if ((s = strchr(acc->server, ':'))) { + if (strstr(acc->server, ":ssl")) { + set_setint(&acc->set, "port", DEFAULT_PORT_SSL); + set_setstr(&acc->set, "ssl", "true"); + } + if (isdigit(s[1])) { + if (sscanf(s + 1, "%d", &port) == 1) + set_setint(&acc->set, "port", port); + } + tmp_server = g_strndup(acc->server, s - acc->server); + set_setstr(&acc->set, "server", tmp_server); + g_free(tmp_server); + } + } + + gc = new_gaim_conn(acc); + jd = gc->proto_data = g_new0(struct jabber_data, 1); + + resource = set_getstr(&acc->set, "resource"); + loginname = create_valid_jid(acc->user, DEFAULT_SERVER, resource); + jd->hash = g_hash_table_new(g_str_hash, g_str_equal); jd->chats = NULL; /* we have no chats yet */ @@ -2336,6 +2366,7 @@ void jabber_init() ret->name = "jabber"; ret->away_states = jabber_away_states; + ret->acc_init = jabber_acc_init; ret->login = jabber_login; ret->close = jabber_close; ret->send_im = jabber_send_im; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 8c6519c1..c0a867d6 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -128,6 +128,7 @@ struct prpl { int options; const char *name; + void (* acc_init) (account_t *); void (* login) (account_t *); void (* keepalive) (struct gaim_connection *); void (* close) (struct gaim_connection *); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index d55ce3f2..28239812 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -355,6 +355,14 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio return FALSE; } +static void oscar_acc_init(account_t *acc) +{ + set_t *s; + + s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; +} + static void oscar_login(account_t *acc) { aim_session_t *sess; aim_conn_t *conn; @@ -389,6 +397,12 @@ static void oscar_login(account_t *acc) { return; } + if (acc->server == NULL) { + hide_login_progress(gc, "No servername specified"); + signoff(gc); + return; + } + if (g_strcasecmp(acc->server, "login.icq.com") != 0 && g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); @@ -2648,6 +2662,7 @@ void oscar_init() ret->name = "oscar"; ret->away_states = oscar_away_states; ret->login = oscar_login; + ret->acc_init = oscar_acc_init; ret->close = oscar_close; ret->send_im = oscar_send_im; ret->get_info = oscar_get_info; -- cgit v1.2.3 From 911f2eb7060f6af6fe8e4e02144cfb7c4bb4cc8b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 3 Jul 2006 01:20:27 +0200 Subject: Added display_name setting for MSN connections. (Should replace the nick command later.) --- account.h | 1 + protocols/msn/msn.c | 90 +++++++++++++++++++++++++++++++++++------------------ protocols/msn/ns.c | 16 ++++++++++ root_commands.c | 7 ++++- 4 files changed, 83 insertions(+), 31 deletions(-) diff --git a/account.h b/account.h index adb63f9e..9cf6987d 100644 --- a/account.h +++ b/account.h @@ -53,5 +53,6 @@ char *set_eval_account( set_t *set, char *value ); #define ACC_SET_NOSAVE 1 #define ACC_SET_OFFLINE_ONLY 2 +#define ACC_SET_ONLINE_ONLY 4 #endif diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index b00354c9..790b372a 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -26,6 +26,16 @@ #include "nogaim.h" #include "msn.h" +static char *msn_set_display_name( set_t *set, char *value ); + +static void msn_acc_init( account_t *acc ) +{ + set_t *s; + + s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; +} + static void msn_login( account_t *acc ) { struct gaim_connection *gc = new_gaim_conn( acc ); @@ -209,36 +219,7 @@ static void msn_set_away( struct gaim_connection *gc, char *state, char *message static void msn_set_info( struct gaim_connection *gc, char *info ) { - int i; - char buf[1024], *fn, *s; - struct msn_data *md = gc->proto_data; - - if( strlen( info ) > 129 ) - { - do_error_dialog( gc, "Maximum name length exceeded", "MSN" ); - return; - } - - /* Of course we could use http_encode() here, but when we encode - every character, the server is less likely to complain about the - chosen name. However, the MSN server doesn't seem to like escaped - non-ASCII chars, so we keep those unescaped. */ - s = fn = g_new0( char, strlen( info ) * 3 + 1 ); - for( i = 0; info[i]; i ++ ) - if( info[i] & 128 ) - { - *s = info[i]; - s ++; - } - else - { - g_snprintf( s, 4, "%%%02X", info[i] ); - s += 3; - } - - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, gc->username, fn ); - msn_write( gc, buf, strlen( buf ) ); - g_free( fn ); + msn_set_display_name( set_find( &gc->acc->set, "display_name" ), info ); } static void msn_get_info(struct gaim_connection *gc, char *who) @@ -377,11 +358,60 @@ static int msn_send_typing( struct gaim_connection *gc, char *who, int typing ) return( 1 ); } +static char *msn_set_display_name( set_t *set, char *value ) +{ + account_t *acc = set->data; + struct gaim_connection *gc = acc->gc; + struct msn_data *md; + char buf[1024], *fn, *s; + int i; + + /* Double-check. */ + if( gc == NULL ) + return NULL; + + md = gc->proto_data; + + if( strlen( value ) > 129 ) + { + serv_got_crap( gc, "Maximum name length exceeded" ); + return NULL; + } + + /* Of course we could use http_encode() here, but when we encode + every character, the server is less likely to complain about the + chosen name. However, the MSN server doesn't seem to like escaped + non-ASCII chars, so we keep those unescaped. */ + s = fn = g_new0( char, strlen( value ) * 3 + 1 ); + for( i = 0; value[i]; i ++ ) + if( value[i] & 128 ) + { + *s = value[i]; + s ++; + } + else + { + g_snprintf( s, 4, "%%%02X", value[i] ); + s += 3; + } + + g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, gc->username, fn ); + msn_write( gc, buf, strlen( buf ) ); + g_free( fn ); + + /* Returning NULL would be better, because the server still has to + confirm the name change. However, it looks a bit confusing to the + user. */ + return value; +} + void msn_init() { struct prpl *ret = g_new0(struct prpl, 1); + ret->name = "msn"; ret->login = msn_login; + ret->acc_init = msn_acc_init; ret->close = msn_close; ret->send_im = msn_send_im; ret->away_states = msn_away_states; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index e4c2b68c..9774f3e2 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -222,11 +222,19 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 ) { + set_t *s; + http_decode( cmd[4] ); strncpy( gc->displayname, cmd[4], sizeof( gc->displayname ) ); gc->displayname[sizeof(gc->displayname)-1] = 0; + if( ( s = set_find( &gc->acc->set, "display_name" ) ) ) + { + g_free( s->value ); + s->value = g_strdup( cmd[4] ); + } + set_login_progress( gc, 1, "Authenticated, getting buddy list" ); g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); @@ -516,9 +524,17 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( g_strcasecmp( cmd[3], gc->username ) == 0 ) { + set_t *s; + http_decode( cmd[4] ); strncpy( gc->displayname, cmd[4], sizeof( gc->displayname ) ); gc->displayname[sizeof(gc->displayname)-1] = 0; + + if( ( s = set_find( &gc->acc->set, "display_name" ) ) ) + { + g_free( s->value ); + s->value = g_strdup( cmd[4] ); + } } else { diff --git a/root_commands.c b/root_commands.c index b975b0f4..42e113ed 100644 --- a/root_commands.c +++ b/root_commands.c @@ -386,7 +386,12 @@ static void cmd_account( irc_t *irc, char **cmd ) if( a->gc && s && s->flags & ACC_SET_OFFLINE_ONLY ) { - irc_usermsg( irc, "This setting can only be changed when the account is off-line" ); + irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" ); + return; + } + else if( !a->gc && s && s->flags & ACC_SET_ONLINE_ONLY ) + { + irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" ); return; } -- cgit v1.2.3 From bf25fa3627c00f80bad624bb4549c46e4b084279 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 3 Jul 2006 23:16:35 +0200 Subject: Completed [167]. (Memory leak wasn't completely fixed yet.) --- protocols/msn/msn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 6393f31d..a8d85a66 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -94,6 +94,8 @@ static void msn_close( struct gaim_connection *gc ) g_slist_free( md->msgq ); } + while( md->groupcount > 0 ) + g_free( md->grouplist[--md->groupcount] ); g_free( md->grouplist ); g_free( md ); -- cgit v1.2.3 From 5b52a4895e5a59ff6509f7771f4d8665737688c3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 3 Jul 2006 23:22:45 +0200 Subject: Implemented per-account nick lists instead of per-protocol nick lists. nick_t is dead, instead nicks are just saves in a per-account_t GLib hash table. While doing this, the import_buddies command finally died and text_save() disappeared, because the old file format can't handle most of the new features in this branch anyway. Still have to implement support for the new nick lists in text_load()! --- account.c | 6 +- account.h | 1 + bitlbee.h | 1 + irc.c | 43 ++--------- irc.h | 2 +- irc_commands.c | 3 +- nick.c | 111 ++++++++++++----------------- nick.h | 14 +--- protocols/jabber/jabber.c | 2 +- protocols/msn/msn.c | 2 +- protocols/nogaim.c | 14 ++-- protocols/nogaim.h | 2 +- protocols/oscar/oscar.c | 3 +- protocols/yahoo/yahoo.c | 3 +- root_commands.c | 59 +-------------- storage_text.c | 178 +--------------------------------------------- storage_xml.c | 23 ++++-- user.c | 26 ++++--- 18 files changed, 118 insertions(+), 375 deletions(-) diff --git a/account.c b/account.c index 1f2ec165..28c33d3b 100644 --- a/account.c +++ b/account.c @@ -58,6 +58,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; set_setstr( &a->set, "username", user ); + a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); + /* This function adds some more settings (and might want to do more things that have to be done now, although I can't think of anything. */ if( prpl->acc_init ) @@ -125,7 +127,7 @@ account_t *account_get( irc_t *irc, char *id ) { for( a = irc->accounts; a; a = a->next ) if( a->prpl == proto && - a->prpl->cmp_buddynames( handle, a->user ) == 0 ) + a->prpl->handle_cmp( handle, a->user ) == 0 ) ret = a; } @@ -189,6 +191,8 @@ void account_del( irc_t *irc, account_t *acc ) while( a->set ) set_del( &a->set, a->set->key ); + g_hash_table_destroy( a->nicks ); + g_free( a->user ); g_free( a->pass ); if( a->server ) g_free( a->server ); diff --git a/account.h b/account.h index 9cf6987d..83f47a89 100644 --- a/account.h +++ b/account.h @@ -37,6 +37,7 @@ typedef struct account int reconnect; set_t *set; + GHashTable *nicks; struct irc *irc; struct gaim_connection *gc; diff --git a/bitlbee.h b/bitlbee.h index 1462316f..f068aeac 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -123,6 +123,7 @@ extern char *CONF_FILE; #include "nogaim.h" #include "commands.h" #include "account.h" +#include "nick.h" #include "conf.h" #include "log.h" #include "ini.h" diff --git a/irc.c b/irc.c index bac91198..fe55a02c 100644 --- a/irc.c +++ b/irc.c @@ -203,11 +203,9 @@ static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) /* Because we have no garbage collection, this is quite annoying */ void irc_free(irc_t * irc) { - account_t *account, *accounttmp; + account_t *account; user_t *user, *usertmp; - nick_t *nick, *nicktmp; help_t *helpnode, *helpnodetmp; - set_t *setnode, *setnodetmp; log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); @@ -251,17 +249,11 @@ void irc_free(irc_t * irc) while (irc->queries != NULL) query_del(irc, irc->queries); - if (irc->accounts != NULL) { - account = irc->accounts; - while (account != NULL) { - g_free(account->user); - g_free(account->pass); - g_free(account->server); - accounttmp = account; - account = account->next; - g_free(accounttmp); - } - } + while (irc->accounts) + account_del(irc, irc->accounts); + + while (irc->set) + set_del(&irc->set, irc->set->key); if (irc->users != NULL) { user = irc->users; @@ -286,17 +278,6 @@ void irc_free(irc_t * irc) g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); g_hash_table_destroy(irc->watches); - if (irc->nicks != NULL) { - nick = irc->nicks; - while (nick != NULL) { - g_free(nick->nick); - g_free(nick->handle); - - nicktmp = nick; - nick = nick->next; - g_free(nicktmp); - } - } if (irc->help != NULL) { helpnode = irc->help; while (helpnode != NULL) { @@ -307,18 +288,6 @@ void irc_free(irc_t * irc) g_free(helpnodetmp); } } - if (irc->set != NULL) { - setnode = irc->set; - while (setnode != NULL) { - g_free(setnode->key); - g_free(setnode->def); - g_free(setnode->value); - - setnodetmp = setnode; - setnode = setnode->next; - g_free(setnodetmp); - } - } g_free(irc); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) diff --git a/irc.h b/irc.h index ad52f42f..5b770180 100644 --- a/irc.h +++ b/irc.h @@ -97,7 +97,7 @@ typedef struct irc } irc_t; #include "user.h" -#include "nick.h" +// #include "nick.h" extern GSList *irc_connection_list; diff --git a/irc_commands.c b/irc_commands.c index 889de9da..47d9e8cb 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -477,7 +477,8 @@ static void irc_cmd_whois( irc_t *irc, char **cmd ) if( u->gc ) irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->acc->user, - *u->gc->acc->server ? u->gc->acc->server : "", u->gc->acc->prpl->name ); + u->gc->acc->server && *u->gc->acc->server ? u->gc->acc->server : "", + u->gc->acc->prpl->name ); else irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); diff --git a/nick.c b/nick.c index 56d6d378..14794bf3 100644 --- a/nick.c +++ b/nick.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2006 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to fetch, save and handle nicknames for your buddies */ @@ -26,50 +26,48 @@ #define BITLBEE_CORE #include "bitlbee.h" -void nick_set( irc_t *irc, const char *handle, struct prpl *proto, const char *nick ) +/* Store handles in lower case and strip spaces, because AIM is braindead. */ +static char *clean_handle( const char *orig ) { - nick_t *m = NULL, *n = irc->nicks; + char *new = g_malloc( strlen( orig ) + 1 ); + int i = 0; - while( n ) - { - if( ( g_strcasecmp( n->handle, handle ) == 0 ) && n->proto == proto ) - { - g_free( n->nick ); - n->nick = nick_dup( nick ); - nick_strip( n->nick ); - - return; - } - n = ( m = n )->next; // :-P + do { + if (*orig != ' ') + new[i++] = tolower( *orig ); } + while (*(orig++)); - if( m ) - n = m->next = g_new0( nick_t, 1 ); - else - n = irc->nicks = g_new0( nick_t, 1 ); + return new; +} + +void nick_set( account_t *acc, const char *handle, const char *nick ) +{ + char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 ); - n->handle = g_strdup( handle ); - n->proto = proto; - n->nick = nick_dup( nick ); + store_handle = clean_handle( handle ); + strncpy( store_nick, nick, MAX_NICK_LENGTH ); + nick_strip( store_nick ); - nick_strip( n->nick ); + g_hash_table_replace( acc->nicks, store_handle, store_nick ); } -char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *realname ) +char *nick_get( account_t *acc, const char *handle, const char *realname ) { static char nick[MAX_NICK_LENGTH+1]; - nick_t *n = irc->nicks; + char *store_handle, *found_nick; int inf_protection = 256; memset( nick, 0, MAX_NICK_LENGTH + 1 ); - while( n && !*nick ) - if( ( n->proto == proto ) && ( g_strcasecmp( n->handle, handle ) == 0 ) ) - strcpy( nick, n->nick ); - else - n = n->next; - - if( !n ) + store_handle = clean_handle( handle ); + /* Find out if we stored a nick for this person already. If not, try + to generate a sane nick automatically. */ + if( ( found_nick = g_hash_table_lookup( acc->nicks, store_handle ) ) ) + { + strncpy( nick, found_nick, MAX_NICK_LENGTH ); + } + else { char *s; @@ -85,11 +83,14 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname ); nick_strip( nick ); - if( set_getint( &irc->set, "lcnicks" ) ) + if( set_getbool( &acc->irc->set, "lcnicks" ) ) nick_lc( nick ); } + g_free( store_handle ); - while( !nick_ok( nick ) || user_find( irc, nick ) ) + /* Now, find out if the nick is already in use at the moment, and make + subtle changes to make it unique. */ + while( !nick_ok( nick ) || user_find( acc->irc, nick ) ) { if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) { @@ -105,19 +106,19 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * { int i; - irc_usermsg( irc, "WARNING: Almost had an infinite loop in nick_get()! " - "This used to be a fatal BitlBee bug, but we tried to fix it. " - "This message should *never* appear anymore. " - "If it does, please *do* send us a bug report! " - "Please send all the following lines in your report:" ); + irc_usermsg( acc->irc, "WARNING: Almost had an infinite loop in nick_get()! " + "This used to be a fatal BitlBee bug, but we tried to fix it. " + "This message should *never* appear anymore. " + "If it does, please *do* send us a bug report! " + "Please send all the following lines in your report:" ); - irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); + irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle ); for( i = 0; i < MAX_NICK_LENGTH; i ++ ) - irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); + irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] ); - irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " - "Good luck, and please don't forget to paste the lines up here " - "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); + irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. " + "Good luck, and please don't forget to paste the lines up here " + "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); @@ -125,30 +126,12 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * } } - return( nick ); + return nick; } -void nick_del( irc_t *irc, const char *nick ) +void nick_del( account_t *acc, const char *handle ) { - nick_t *l = NULL, *n = irc->nicks; - - while( n ) - { - if( g_strcasecmp( n->nick, nick ) == 0 ) - { - if( l ) - l->next = n->next; - else - irc->nicks = n->next; - - g_free( n->handle ); - g_free( n->nick ); - g_free( n ); - - break; - } - n = (l=n)->next; - } + g_hash_table_remove( acc->nicks, handle ); } diff --git a/nick.h b/nick.h index 9ab1ef1e..5274cb13 100644 --- a/nick.h +++ b/nick.h @@ -23,17 +23,9 @@ Suite 330, Boston, MA 02111-1307 USA */ -typedef struct __NICK -{ - char *handle; - struct prpl *proto; - char *nick; - struct __NICK *next; -} nick_t; - -void nick_set( irc_t *irc, const char *handle, struct prpl *proto, const char *nick ); -char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *realname ); -void nick_del( irc_t *irc, const char *nick ); +void nick_set( account_t *acc, const char *handle, const char *nick ); +char *nick_get( account_t *acc, const char *handle, const char *realname ); +void nick_del( account_t *acc, const char *handle ); void nick_strip( char *nick ); int nick_ok( const char *nick ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e7f4534e..7147a78c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -2379,7 +2379,7 @@ void jabber_init() ret->keepalive = jabber_keepalive; ret->alias_buddy = jabber_roster_update; ret->group_buddy = jabber_group_change; - ret->cmp_buddynames = g_strcasecmp; + ret->handle_cmp = g_strcasecmp; register_protocol (ret); } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 790b372a..db4563dc 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -431,7 +431,7 @@ void msn_init() ret->add_deny = msn_add_deny; ret->rem_deny = msn_rem_deny; ret->send_typing = msn_send_typing; - ret->cmp_buddynames = g_strcasecmp; + ret->handle_cmp = g_strcasecmp; register_protocol(ret); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 8346f5fa..54965b84 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -365,7 +365,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( gc->irc, handle, gc->acc->prpl, realname ) ); + strcpy( nick, nick_get( gc->acc, handle, realname ) ); u = user_add( gc->irc, nick ); @@ -377,7 +377,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea u->host = g_strdup( s + 1 ); u->user = g_strndup( handle, s - handle ); } - else if( *gc->acc->server ) + else if( gc->acc->server ) { char *colon; @@ -777,7 +777,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); /* It might be yourself! */ - if( b->gc->acc->prpl->cmp_buddynames( handle, b->gc->username ) == 0 ) + if( b->gc->acc->prpl->handle_cmp( handle, b->gc->username ) == 0 ) { u = user_find( b->gc->irc, b->gc->irc->nick ); if( !b->joined ) @@ -1061,7 +1061,7 @@ static char *bim_away_alias_find( GList *gcm, char *away ) void bim_add_allow( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) { gc->permit = g_slist_prepend( gc->permit, g_strdup( handle ) ); } @@ -1073,7 +1073,7 @@ void bim_rem_allow( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); gc->permit = g_slist_delete_link( gc->permit, l ); @@ -1084,7 +1084,7 @@ void bim_rem_allow( struct gaim_connection *gc, char *handle ) void bim_add_block( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) { gc->deny = g_slist_prepend( gc->deny, g_strdup( handle ) ); } @@ -1096,7 +1096,7 @@ void bim_rem_block( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); gc->deny = g_slist_delete_link( gc->deny, l ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index c0a867d6..bae4489f 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -164,7 +164,7 @@ struct prpl { GList *(* away_states)(struct gaim_connection *gc); /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ - int (* cmp_buddynames) (const char *who1, const char *who2); + int (* handle_cmp) (const char *who1, const char *who2); }; #define UC_UNAVAILABLE 1 diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 28239812..f65332dc 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2680,9 +2680,10 @@ void oscar_init() ret->rem_deny = oscar_rem_deny; ret->set_permit_deny = oscar_set_permit_deny; ret->keepalive = oscar_keepalive; - ret->cmp_buddynames = aim_sncmp; ret->get_status_string = oscar_get_status_string; ret->send_typing = oscar_send_typing; + + ret->handle_cmp = aim_sncmp; register_protocol(ret); } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index c21779ba..23c6f813 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -408,7 +408,8 @@ void byahoo_init( ) ret->chat_invite = byahoo_chat_invite; ret->chat_leave = byahoo_chat_leave; ret->chat_open = byahoo_chat_open; - ret->cmp_buddynames = g_strcasecmp; + + ret->handle_cmp = g_strcasecmp; register_protocol(ret); } diff --git a/root_commands.c b/root_commands.c index 42e113ed..2cf67134 100644 --- a/root_commands.c +++ b/root_commands.c @@ -465,7 +465,7 @@ static void cmd_add( irc_t *irc, char **cmd ) } else { - nick_set( irc, cmd[2], a->gc->acc->prpl, cmd[3] ); + nick_set( a, cmd[2], cmd[3] ); } } @@ -547,7 +547,7 @@ static void cmd_rename( irc_t *irc, char **cmd ) } else if( u->send_handler == buddy_send_handler ) { - nick_set( irc, u->handle, u->gc->acc->prpl, cmd[2] ); + nick_set( u->gc->acc, u->handle, cmd[2] ); } irc_usermsg( irc, "Nick successfully changed" ); @@ -568,7 +568,7 @@ static void cmd_remove( irc_t *irc, char **cmd ) u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); user_del( irc, cmd[1] ); - nick_del( irc, cmd[1] ); + nick_del( u->gc->acc, u->handle ); irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); g_free( s ); @@ -880,58 +880,6 @@ static void cmd_qlist( irc_t *irc, char **cmd ) irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } -static void cmd_import_buddies( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - nick_t *n; - - if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return; - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return; - } - - if( cmd[2] ) - { - if( g_strcasecmp( cmd[2], "clear" ) == 0 ) - { - user_t *u; - - /* FIXME: Hmmm, this is actually pretty dangerous code... REMOVEME? :-) */ - for( u = irc->users; u; u = u->next ) - if( u->gc == gc ) - { - u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); - user_del( irc, u->nick ); - } - - irc_usermsg( irc, "Old buddy list cleared." ); - } - else - { - irc_usermsg( irc, "Invalid argument: %s", cmd[2] ); - return; - } - } - - for( n = gc->irc->nicks; n; n = n->next ) - { - if( n->proto == gc->acc->prpl && !user_findhandle( gc, n->handle ) ) - { - gc->acc->prpl->add_buddy( gc, n->handle ); - add_buddy( gc, NULL, n->handle, NULL ); - } - } - - irc_usermsg( irc, "Sent all add requests. Please wait for a while, the server needs some time to handle all the adds." ); -} - const command_t commands[] = { { "help", 0, cmd_help, 0 }, { "identify", 1, cmd_identify, 0 }, @@ -950,7 +898,6 @@ const command_t commands[] = { { "no", 0, cmd_yesno, 0 }, { "blist", 0, cmd_blist, 0 }, { "nick", 1, cmd_nick, 0 }, - { "import_buddies", 1, cmd_import_buddies, 0 }, { "qlist", 0, cmd_qlist, 0 }, { NULL } }; diff --git a/storage_text.c b/storage_text.c index 06d278aa..ac197685 100644 --- a/storage_text.c +++ b/storage_text.c @@ -112,186 +112,13 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i continue; http_decode( s ); - nick_set( irc, s, prpl, nick ); + // FIXME!!!! nick_set( irc, s, prpl, nick ); } fclose( fp ); return STORAGE_OK; } -static storage_status_t text_save( irc_t *irc, int overwrite ) -{ - char s[512]; - char path[512], new_path[512]; - char *line; - nick_t *n; - set_t *set; - mode_t ou = umask( 0077 ); - account_t *a; - FILE *fp; - char *hash; - - if (!overwrite) { - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); - if (access( path, F_OK ) != -1) - return STORAGE_ALREADY_EXISTS; - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); - if (access( path, F_OK ) != -1) - return STORAGE_ALREADY_EXISTS; - } - - /*\ - * [SH] Nothing should be saved if no password is set, because the - * password is not set if it was wrong, or if one is not identified - * yet. This means that a malicious user could easily overwrite - * files owned by someone else: - * a Bad Thing, methinks - \*/ - - /* [WVG] No? Really? */ - - /*\ - * [SH] Okay, okay, it wasn't really Wilmer who said that, it was - * me. I just thought it was funny. - \*/ - - hash = hashpass( irc->password ); - if( hash == NULL ) - { - irc_usermsg( irc, "Please register yourself if you want to save your settings." ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - for( n = irc->nicks; n; n = n->next ) - { - strcpy( s, n->handle ); - s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */ - http_encode( s ); - g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", find_protocol_id(n->proto->name), n->nick ); - if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .nicks file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .nicks file" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - if( fprintf( fp, "%s", hash ) != strlen( hash ) ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - g_free( hash ); - - for( a = irc->accounts; a; a = a->next ) - { - if( !strcmp(a->prpl->name, "oscar") ) - g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server ); - else - g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"", - a->prpl->name, a->user, a->pass, a->server ? a->server : "" ); - - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - - for( set = irc->set; set; set = set->next ) - { - if( set->value && set->def ) - { - g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - } - - if( strcmp( irc->mynick, ROOT_NICK ) != 0 ) - { - g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .accounts file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .accounts file" ); - return STORAGE_OTHER_ERROR; - } - - umask( ou ); - - return STORAGE_OK; -} - static storage_status_t text_check_pass( const char *nick, const char *password ) { char s[512]; @@ -336,6 +163,5 @@ storage_t storage_text = { .init = text_init, .check_pass = text_check_pass, .remove = text_remove, - .load = text_load, - .save = text_save + .load = text_load }; diff --git a/storage_xml.c b/storage_xml.c index 701d5144..b01f35d6 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -196,7 +196,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na if( xd->current_account && handle && nick ) { - nick_set( irc, handle, xd->current_account->prpl, nick ); + nick_set( xd->current_account, handle, nick ); } else { @@ -364,11 +364,12 @@ static int xml_printf( int fd, int indent, char *fmt, ... ) return len == 0; } +static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data ); + static storage_status_t xml_save( irc_t *irc, int overwrite ) { char path[512], *path2, *pass_buf = NULL; set_t *set; - nick_t *nick; account_t *acc; int fd; md5_byte_t pass_md5[21]; @@ -439,10 +440,15 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) if( !xml_printf( fd, 2, "%s\n", set->key, set->value ) ) goto write_error; - for( nick = irc->nicks; nick; nick = nick->next ) - if( nick->proto == acc->prpl ) - if( !xml_printf( fd, 2, "\n", nick->handle, nick->nick ) ) - goto write_error; + /* This probably looks pretty strange. g_hash_table_foreach + is quite a PITA already (but it can't get much better in + C without using #define, I'm afraid), and since it + doesn't seem to be possible to abort the foreach on write + errors, so instead let's use the _find function and + return TRUE on write errors. Which means, if we found + something, there was an error. :-) */ + if( g_hash_table_find( acc->nicks, xml_save_nick, (gpointer) fd ) ) + goto write_error; if( !xml_printf( fd, 1, "\n" ) ) goto write_error; @@ -477,6 +483,11 @@ write_error: return STORAGE_OTHER_ERROR; } +static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data ) +{ + return !xml_printf( (int) data, 2, "\n", key, value ); +} + static storage_status_t xml_remove( const char *nick, const char *password ) { char s[512]; diff --git a/user.c b/user.c index cb70ab68..0892a23c 100644 --- a/user.c +++ b/user.c @@ -142,16 +142,22 @@ user_t *user_find( irc_t *irc, char *nick ) user_t *user_findhandle( struct gaim_connection *gc, char *handle ) { - user_t *u = gc->irc->users; - - while( u ) - { - if( u->gc == gc && u->handle && gc->acc->prpl->cmp_buddynames ( u->handle, handle ) == 0 ) - break; - u = u->next; - } - - return( u ); + user_t *u; + char *nick; + + /* First, let's try a hash lookup. If it works, it's probably faster. */ + if( ( nick = g_hash_table_lookup( gc->acc->nicks, handle ) ) && + ( u = user_find( gc->irc, nick ) ) && + ( gc->acc->prpl->handle_cmp( handle, u->handle ) == 0 ) ) + return u; + + /* However, it doesn't always work, so in that case we'll have to dig + through the whole userlist. :-( */ + for( u = gc->irc->users; u; u = u->next ) + if( u->gc == gc && u->handle && gc->acc->prpl->handle_cmp( u->handle, handle ) == 0 ) + return u; + + return NULL; } void user_rename( irc_t *irc, char *oldnick, char *newnick ) -- cgit v1.2.3 From 7e3592e96b27ec8375e4b28354bcf9ed4cf5943b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 5 Jul 2006 20:34:31 +0200 Subject: Fixed text_load(), added detection of primary storage backends without save support (which shouldn't be allowed) and added a call to nick_lc() to xml_save() so at least nicks should now be case-insensitive. --- storage.c | 2 +- storage_text.c | 57 +++++++++++++++++++++++---------------------------------- storage_xml.c | 5 ++++- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/storage.c b/storage.c index 807d5bb4..06044f80 100644 --- a/storage.c +++ b/storage.c @@ -69,7 +69,7 @@ GList *storage_init(const char *primary, char **migrate) register_storage_backend(&storage_xml); storage = storage_init_single(primary); - if (storage == NULL) + if (storage == NULL && storage->save == NULL) return NULL; ret = g_list_append(ret, storage); diff --git a/storage_text.c b/storage_text.c index ac197685..acc9eefe 100644 --- a/storage_text.c +++ b/storage_text.c @@ -27,32 +27,6 @@ #include "bitlbee.h" #include "crypting.h" -/* DO NOT USE THIS FUNCTION IN NEW CODE. This - * function is here merely because the save/load code still uses - * ids rather than names */ -static struct prpl *find_protocol_by_id(int id) -{ - switch (id) { - case 0: case 1: case 3: return find_protocol("oscar"); - case 4: return find_protocol("msn"); - case 2: return find_protocol("yahoo"); - case 8: return find_protocol("jabber"); - default: break; - } - return NULL; -} - -static int find_protocol_id(const char *name) -{ - if (!strcmp(name, "oscar")) return 1; - if (!strcmp(name, "msn")) return 4; - if (!strcmp(name, "yahoo")) return 2; - if (!strcmp(name, "jabber")) return 8; - - return -1; -} - - static void text_init (void) { if( access( global.conf->configdir, F_OK ) != 0 ) @@ -69,6 +43,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i char nick[MAX_NICK_LENGTH+1]; FILE *fp; user_t *ru = user_find( irc, ROOT_NICK ); + account_t *acc, *acc_lookup[9]; if( irc->status & USTATUS_IDENTIFIED ) return( 1 ); @@ -79,7 +54,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i fscanf( fp, "%32[^\n]s", s ); - if (checkpass (password, s) != 0) + if( checkpass( password, s ) != 0 ) { fclose( fp ); return STORAGE_INVALID_PASSWORD; @@ -99,20 +74,34 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i } fclose( fp ); + /* Build a list with the first listed account of every protocol + number. So if the user had nicks defined for a second account on + the same IM network, those nicks will be added to the wrong + account, and the user should rename those buddies again. But at + least from now on things will be saved properly. */ + memset( acc_lookup, 0, sizeof( acc_lookup ) ); + for( acc = irc->accounts; acc; acc = acc->next ) + { + if( acc_lookup[0] == NULL && strcmp( acc->prpl->name, "oscar" ) == 0 ) + acc_lookup[0] = acc_lookup[1] = acc_lookup[3] = acc; + else if( acc_lookup[2] == NULL && strcmp( acc->prpl->name, "yahoo" ) == 0 ) + acc_lookup[2] = acc; + else if( acc_lookup[4] == NULL && strcmp( acc->prpl->name, "msn" ) == 0 ) + acc_lookup[4] = acc; + else if( acc_lookup[8] == NULL && strcmp( acc->prpl->name, "jabber" ) == 0 ) + acc_lookup[8] = acc; + } + g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" ); fp = fopen( s, "r" ); if( !fp ) return STORAGE_NO_SUCH_USER; while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) { - struct prpl *prpl; - - prpl = find_protocol_by_id(proto); - - if (!prpl) + if( ( acc = acc_lookup[proto] ) == NULL ) continue; - + http_decode( s ); - // FIXME!!!! nick_set( irc, s, prpl, nick ); + nick_set( acc, s, nick ); } fclose( fp ); diff --git a/storage_xml.c b/storage_xml.c index b01f35d6..2585b475 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -381,7 +381,10 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) return STORAGE_OTHER_ERROR; } - g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, irc->nick, ".xml" ); + path2 = g_strdup( irc->nick ); + nick_lc( path2 ); + g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); + g_free( path2 ); if( !overwrite && access( path, F_OK ) != -1 ) return STORAGE_ALREADY_EXISTS; -- cgit v1.2.3 From 66b9e86eafc3709c491f96c917069db8b6a0c895 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 7 Jul 2006 15:33:31 +0200 Subject: Add support for checking test suite coverage using gcov. --- .bzrignore | 3 +++ Makefile | 9 +++++++-- configure | 7 +++++++ protocols/Makefile | 3 +++ protocols/jabber/Makefile | 1 + protocols/msn/Makefile | 3 +++ protocols/oscar/Makefile | 3 +++ protocols/yahoo/Makefile | 3 +++ tests/Makefile | 9 +++++++-- tests/check_nick.c | 2 +- 10 files changed, 38 insertions(+), 5 deletions(-) diff --git a/.bzrignore b/.bzrignore index cddd9fb1..1c18013a 100644 --- a/.bzrignore +++ b/.bzrignore @@ -12,3 +12,6 @@ encode bitlbee.pc .gdb_history tests/check +*.gcda +*.gcov +*.gcno diff --git a/Makefile b/Makefile index 6f1d2d4a..aa4589b5 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ # Program variables objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o unix.o url.o user.o util.o headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h -subdirs = protocols +subdirs = protocols # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) @@ -39,14 +39,19 @@ Makefile.settings: clean: $(subdirs) rm -f *.o $(OUTFILE) core utils/bitlbeed encode decode + $(MAKE) -C tests clean distclean: clean $(subdirs) rm -f Makefile.settings config.h find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; + $(MAKE) -C test distclean -check: +check: all $(MAKE) -C tests +gcov: check + gcov *.c + install-doc: $(MAKE) -C doc install diff --git a/configure b/configure index a3c16e75..43bd2f95 100755 --- a/configure +++ b/configure @@ -27,6 +27,7 @@ yahoo=1 debug=0 strip=1 +gcov=0 ipv6=1 events=glib @@ -63,6 +64,7 @@ Option Description Default --debug=0/1 Disable/enable debugging $debug --strip=0/1 Disable/enable binary stripping $strip +--gcov=0/1 Disable/enable test coverage reporting $gcov --ipv6=0/1 IPv6 socket support $ipv6 @@ -313,6 +315,11 @@ else fi; fi +if [ "$gcov" = "1" ]; then + echo "CFLAGS+=-ftest-coverage -fprofile-arcs" >> Makefile.settings + echo "EFLAGS+=-lgcov" >> Makefile.settings +fi + echo if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then nick=`bzr nick` diff --git a/protocols/Makefile b/protocols/Makefile index b74212f4..8f58ecd6 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -25,6 +25,9 @@ LFLAGS += -r # [SH] Phony targets all: protocols.o +check: all +gcov: + gcov *.c .PHONY: all clean distclean $(subdirs) diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 9b414dc8..abfc7478 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -16,6 +16,7 @@ LFLAGS += -r # [SH] Phony targets all: jabber_mod.o +check: all .PHONY: all clean distclean diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 873c831c..f53b34ba 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -16,6 +16,9 @@ LFLAGS += -r # [SH] Phony targets all: msn_mod.o +check: all +gcov: + gcov *.c .PHONY: all clean distclean diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index 97a27299..ed2d7f83 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -16,6 +16,9 @@ LFLAGS += -r # [SH] Phony targets all: oscar_mod.o +check: all +gcov: + gcov *.c .PHONY: all clean distclean diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index b4014f8a..34c3551a 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -16,6 +16,9 @@ LFLAGS += -r # [SH] Phony targets all: yahoo_mod.o +check: all +gcov: + gcov *.c .PHONY: all clean distclean diff --git a/tests/Makefile b/tests/Makefile index ce8ed690..206331f4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,12 +2,17 @@ include ../Makefile.settings LFLAGS +=-lcheck -all: check +all: check ./check +clean: + rm -f check *.o + main_objs = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o url.o user.o util.o -check: check.o check_util.o check_nick.o $(addprefix ../, $(main_objs)) ../protocols/protocols.o +test_objs = check.o check_util.o check_nick.o + +check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o @echo '*' Linking $@ @$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(EFLAGS) diff --git a/tests/check_nick.c b/tests/check_nick.c index 5858e512..b235d260 100644 --- a/tests/check_nick.c +++ b/tests/check_nick.c @@ -22,7 +22,7 @@ START_TEST(test_nick_strip) NULL }; for (i = 0; get[i]; i++) { - char copy[30]; + char copy[60]; strcpy(copy, get[i]); nick_strip(copy); fail_unless (strcmp(copy, expected[i]) == 0, -- cgit v1.2.3 From f4aa393b221dcc709f189ed04945ee67e956872a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 7 Jul 2006 15:34:01 +0200 Subject: Ignore *.o files (removed from global ignores in bzr 0.9) --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 1c18013a..12dd9c10 100644 --- a/.bzrignore +++ b/.bzrignore @@ -15,3 +15,4 @@ tests/check *.gcda *.gcov *.gcno +*.o -- cgit v1.2.3 From a93e3c822a697562c2e05906059922ed28f51ca5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 9 Jul 2006 12:54:45 +0200 Subject: Fixed irc_names() (forgot to add @s for user/root in the new version). --- irc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/irc.c b/irc.c index 816b69d9..1a7579b8 100644 --- a/irc.c +++ b/irc.c @@ -651,6 +651,7 @@ void irc_names( irc_t *irc, char *channel ) user_t *u; char namelist[385] = ""; struct conversation *c = NULL; + char *ops = set_getstr( irc, "ops" ); /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ @@ -667,6 +668,9 @@ void irc_names( irc_t *irc, char *channel ) if( u->gc && !u->away && set_getint( irc, "away_devoice" ) ) strcat( namelist, "+" ); + else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) || + ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ) + strcat( namelist, "@" ); strcat( namelist, u->nick ); strcat( namelist, " " ); @@ -675,7 +679,6 @@ void irc_names( irc_t *irc, char *channel ) else if( ( c = conv_findchannel( channel ) ) ) { GList *l; - char *ops = set_getstr( irc, "ops" ); /* root and the user aren't in the channel userlist but should show up in /NAMES, so list them first: */ -- cgit v1.2.3 From b0a33a50735d93e1414a2e6c2007884d756429a3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 11 Jul 2006 11:28:44 +0200 Subject: Better handling of situations where IPv6 is not available at run-time. --- bitlbee.c | 46 ++++++++++++++++++++++++++++++++++------------ irc.c | 41 ++++++++++++++++++++++------------------- sock.h | 7 ------- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 1d4e2b34..f3cc3d4a 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -35,20 +35,31 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ); +#undef AF_INET6 +#define AF_INET6 666 + int bitlbee_daemon_init() { #ifdef IPV6 - struct sockaddr_in6 listen_addr; -#else - struct sockaddr_in listen_addr; + int use_ipv6 = 1; + struct sockaddr_in6 listen_addr6; #endif + struct sockaddr_in listen_addr; int i; FILE *fp; log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG ); log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG ); - global.listen_socket = socket( AF_INETx, SOCK_STREAM, 0 ); +#ifdef IPV6 + if( ( global.listen_socket = socket( AF_INET6, SOCK_STREAM, 0 ) ) == -1 ) + { + use_ipv6 = 0; +#endif + global.listen_socket = socket( AF_INET, SOCK_STREAM, 0 ); +#ifdef IPV6 + } +#endif if( global.listen_socket == -1 ) { log_error( "socket" ); @@ -60,13 +71,21 @@ int bitlbee_daemon_init() setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); #ifdef IPV6 - listen_addr.sin6_family = AF_INETx; - listen_addr.sin6_port = htons( global.conf->port ); - i = inet_pton( AF_INETx, ipv6_wrap( global.conf->iface ), &listen_addr.sin6_addr ); -#else - listen_addr.sin_family = AF_INETx; - listen_addr.sin_port = htons( global.conf->port ); - i = inet_pton( AF_INETx, global.conf->iface, &listen_addr.sin_addr ); + listen_addr6.sin6_family = AF_INET6; + listen_addr6.sin6_port = htons( global.conf->port ); + if( ( i = inet_pton( AF_INET6, ipv6_wrap( global.conf->iface ), &listen_addr6.sin6_addr ) ) != 1 ) + { + /* Forget about IPv6 in this function. */ + use_ipv6 = 0; +#endif + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons( global.conf->port ); + if( strcmp( global.conf->iface, "::" ) == 0 ) + i = inet_pton( AF_INET, "0.0.0.0", &listen_addr.sin_addr ); + else + i = inet_pton( AF_INET, global.conf->iface, &listen_addr.sin_addr ); +#ifdef IPV6 + } #endif if( i != 1 ) @@ -75,7 +94,10 @@ int bitlbee_daemon_init() return( -1 ); } - i = bind( global.listen_socket, (struct sockaddr *) &listen_addr, sizeof( listen_addr ) ); +#ifdef IPV6 + if( !use_ipv6 || ( i = bind( global.listen_socket, (struct sockaddr *) &listen_addr6, sizeof( listen_addr6 ) ) ) == -1 ) +#endif + i = bind( global.listen_socket, (struct sockaddr *) &listen_addr, sizeof( listen_addr ) ); if( i == -1 ) { log_error( "bind" ); diff --git a/irc.c b/irc.c index 1a7579b8..53ca7c4c 100644 --- a/irc.c +++ b/irc.c @@ -45,10 +45,10 @@ irc_t *irc_new( int fd ) unsigned int i; char buf[128]; #ifdef IPV6 - struct sockaddr_in6 sock[1]; -#else - struct sockaddr_in sock[1]; + struct sockaddr_in6 sock6[1]; + unsigned int i6; #endif + struct sockaddr_in sock[1]; irc = g_new0( irc_t, 1 ); @@ -68,45 +68,48 @@ irc_t *irc_new( int fd ) irc->channel = g_strdup( ROOT_CHAN ); i = sizeof( *sock ); +#ifdef IPV6 + i6 = sizeof( *sock6 ); +#endif if( global.conf->hostname ) irc->myhost = g_strdup( global.conf->hostname ); #ifdef IPV6 - else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin6_family == AF_INETx ) + else if( getsockname( irc->fd, (struct sockaddr*) sock6, &i6 ) == 0 && sock6->sin6_family == AF_INET6 ) { - if( ( peer = gethostbyaddr( (char*) &sock->sin6_addr, sizeof( sock->sin6_addr ), AF_INETx ) ) ) + if( ( peer = gethostbyaddr( (char*) &sock6->sin6_addr, sizeof( sock6->sin6_addr ), AF_INET6 ) ) ) irc->myhost = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INETx, &sock->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) + else if( inet_ntop( AF_INET6, &sock6->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) irc->myhost = g_strdup( ipv6_unwrap( buf ) ); } -#else - else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INETx ) +#endif + else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INET ) { - if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INETx ) ) ) + if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INET ) ) ) irc->myhost = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INETx, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) + else if( inet_ntop( AF_INET, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) irc->myhost = g_strdup( buf ); } -#endif i = sizeof( *sock ); #ifdef IPV6 - if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin6_family == AF_INETx ) + i6 = sizeof( *sock6 ); + if( getpeername( irc->fd, (struct sockaddr*) sock6, &i6 ) == 0 && sock6->sin6_family == AF_INET6 ) { - if( ( peer = gethostbyaddr( (char*) &sock->sin6_addr, sizeof( sock->sin6_addr ), AF_INETx ) ) ) + if( ( peer = gethostbyaddr( (char*) &sock6->sin6_addr, sizeof( sock6->sin6_addr ), AF_INET6 ) ) ) irc->host = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INETx, &sock->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) + else if( inet_ntop( AF_INET6, &sock6->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) irc->host = g_strdup( ipv6_unwrap( buf ) ); } -#else - if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INETx ) + else +#endif + if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INET ) { - if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INETx ) ) ) + if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INET ) ) ) irc->host = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INETx, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) + else if( inet_ntop( AF_INET, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) irc->host = g_strdup( buf ); } -#endif /* Rare, but possible. */ if( !irc->host ) irc->host = g_strdup( "localhost." ); diff --git a/sock.h b/sock.h index ff7034a6..c3c0428e 100644 --- a/sock.h +++ b/sock.h @@ -1,13 +1,6 @@ #include #include -/* To cut down on the ifdef stuff a little bit in other places */ -#ifdef IPV6 -#define AF_INETx AF_INET6 -#else -#define AF_INETx AF_INET -#endif - #ifndef _WIN32 #include #include -- cgit v1.2.3 From 639809488bb4ab59a4a4f15ef2d4cd34037a68a4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 12 Jul 2006 10:07:47 +0200 Subject: Removed #defines used to simulate systems without IPv6 support. --- bitlbee.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index f3cc3d4a..85ae4621 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -35,9 +35,6 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ); -#undef AF_INET6 -#define AF_INET6 666 - int bitlbee_daemon_init() { #ifdef IPV6 -- cgit v1.2.3 From 75a4b85ea060c5b63e9742ee9d1591bd618ba5c2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 14 Jul 2006 11:25:48 +0200 Subject: Fixed a memory leak, added a check for valid Jabber handles, and updated documentation (added information about "account set" and sorted the list of settings because it was a bit too random). --- doc/user-guide/commands.xml | 263 ++++++++++++++++++++++++++++---------------- doc/user-guide/help.xsl | 2 +- protocols/jabber/jabber.c | 7 ++ root_commands.c | 3 + 4 files changed, 177 insertions(+), 98 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 44a9882f..d28a8531 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -10,7 +10,7 @@ - Available actions: add, del, list, on, off. See help account <action> for more information. + Available actions: add, del, list, on, off and set. See help account <action> for more information. @@ -25,28 +25,28 @@ - account add jabber <handle> <password> [<servertag>] + account add jabber <handle@server.tld> <password> [<servertag>] - Note that the servertag argument is optional. You only have to use it if the part after the @ in your handle isn't the hostname of your Jabber server, or if you want to use SSL/connect to a non-standard port number. The format is simple: [<servername>[:<portnumber>][:ssl]]. For example, this is how you can connect to Google Talk: + Note that the servertag argument is optional. You only have to use it if the part after the @ in your handle isn't the hostname of your Jabber server, or if you want to use SSL/connect to a non-standard port number. The format is simple: [<servername>[:<portnumber>][:ssl]]. - - account add jabber example@gmail.com hobbelmeeuw talk.google.com:5223:ssl - Account successfully added - - - Note that Google talk is SSL-only, but officially reachable over both port 5222 and 5223. However, for some people only port 5222 works, for some people only 5223. This is something you'll have to try out. + Google Talk uses the Jabber protocol. Please note that Google talk is SSL-only, but officially reachable over both port 5222 and 5223. Usually BitlBee users have to connect via port 5223, for example like this: + + + account add jabber example@gmail.com hobbelmeeuw talk.google.com:5223:ssl + Account successfully added + - account add msn <handle> <password> + account add msn <handle@server.tld> <password> @@ -102,7 +102,7 @@ - This command will try to log into the specified account. If no account is specified, BitlBee will log into all the accounts. (Including accounts awaiting a reconnection) + This command will try to log into the specified account. If no account is specified, BitlBee will log into all the accounts that have the auto_connect flag set. @@ -117,7 +117,7 @@ - This command disconnects the connection for the specified account. If no account is specified, BitlBee will deactivate all active accounts. (Including accounts awaiting a reconnection) + This command disconnects the connection for the specified account. If no account is specified, BitlBee will deactivate all active accounts and cancel all pending reconnects. @@ -135,6 +135,26 @@ + + + account set <account id> + account set <account id>/<setting> + account set <account id>/<setting> <value> + + + + This account can be used to change various settings for IM accounts. For all protocols, this command can be used to change the handle or the password BitlBee uses to log in and if it should be logged in automatically. Some protocols have additional settings. You can see the settings available for a connection by typing account set <account id>. + + + + For more infomation about a setting, see help set <setting>. + + + + The account ID can be a number (see account list), the protocol name or (part of) the screenname, as long as it matches only one connection. + + + @@ -275,120 +295,145 @@ - - iso8859-1 - you can get a list of all possible values by doing 'iconv -l' in a shell + + True - The charset setting enables you to use different character sets in BitlBee. These get converted to UTF-8 before sending and from UTF-8 when receiving. + With this option enabled, when you identify BitlBee will automatically connect to your accounts, with this disabled it will not do this. - + - If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://czyborra.com/charsets/iso8859.html + This setting can also be changed for specific accounts using the account set command. (However, these values will be ignored if the global auto_connect setting is disabled!) - - - True + + False - - If value is true, messages from users will appear in separate query windows. If false, messages from users will appear in the control channel. + If an IM-connections breaks, you're supposed to bring it back up yourself. Having BitlBee do this automatically might not always be a good idea, for several reasons. If you want the connections to be restored automatically, you can enable this setting. - This setting is remembered (during one session) per-user, this setting only changes the default state. This option takes effect as soon as you reconnect. + See also the auto_reconnect_delay setting. + - - True + + 300 - If enabled causes BitlBee to save all current settings and account details when user disconnects. This is enabled by default, and these days there's not really a reason to have it disabled anymore. + Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours. + + + + See also the auto_reconnect setting. - + True - Determines what BitlBee should do with HTML in messages. Normally this is turned on and HTML will be stripped from messages, if BitlBee thinks there is HTML. - - - If BitlBee fails to detect this sometimes (most likely in AIM messages over an ICQ connection), you can set this setting to always, but this might sometimes accidentally strip non-HTML things too. + With this option enabled, the root user devoices people when they go away (just away, not offline) and gives the voice back when they come back. You might dislike the voice-floods you'll get if your contact list is huge, so this option can be disabled. - + False - Some debugging messages can be sent to the control channel if you wish. They're probably not really useful for you, unless you're doing some development on BitlBee. + By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data. + + + + Using the buddy_sendbuffer_delay setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent. + + + + Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases. - - ": " + + 200 - It's customary that messages meant for one specific person on an IRC channel are prepended by his/her alias followed by a colon ':'. BitlBee does this by default. If you prefer a different character, you can set it using set to_char. + Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds. - Please note that this setting is only used for incoming messages. For outgoing messages you can use ':' (colon) or ',' to separate the destination nick from the message, and this is not configurable. + See also the buddy_sendbuffer setting. - - False + + iso8859-1 + you can get a list of all possible values by doing 'iconv -l' in a shell - Sends you a /notice when a user starts typing a message (if the protocol supports it, MSN for example). This is a bug, not a feature. (But please don't report it.. ;-) You don't want to use it. Really. In fact the typing-notification is just one of the least useful 'innovations' ever. It's just there because some guy will probably ask me about it anyway. ;-) + The charset setting enables you to use different character sets in BitlBee. These get converted to UTF-8 before sending and from UTF-8 when receiving. + + + + If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://czyborra.com/charsets/iso8859.html + - - both - both, root, user, none + + False - Some people prefer themself and root to have operator status in &bitlbee, other people don't. You can change these states using this setting. + Some debugging messages can be sent to the control channel if you wish. They're probably not really useful for you, unless you're doing some development on BitlBee. + + + + + root + root, last + - The value "both" means both user and root get ops. "root" means, well, just root. "user" means just the user. "none" means nobody will get operator status. + With this value set to root, lines written in the control channel without any nickname in front of them will be interpreted as commands. If you want BitlBee to send those lines to the last person you addressed in the control channel, set this to last. - - True - + - With this option enabled, the root user devoices people when they go away (just away, not offline) and gives the voice back when they come back. You might dislike the voice-floods you'll get if your contact list is huge, so this option can be disabled. + Currently only available for MSN connections. This setting allows you to read and change your "friendly name" for this connection. Since this is a server-side setting, it can't be changed when the account is off-line. + + False + + + With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name". + + + root root, add, add_private, add_channel, ignore @@ -416,134 +461,158 @@ - + True - With this option enabled, when you identify BitlBee will automatically connect to your accounts, with this disabled it will not do this. + Hereby you can change whether you want all lower case nick names or leave the case as it intended by your peer. + - - False + + both + both, root, user, none - If an IM-connections breaks, you're supposed to bring it back up yourself. Having BitlBee do this automatically might not always be a good idea, for several reasons. If you want the connections to be restored automatically, you can enable this setting. + Some people prefer themself and root to have operator status in &bitlbee, other people don't. You can change these states using this setting. - See also the auto_reconnect_delay setting. + The value "both" means both user and root get ops. "root" means, well, just root. "user" means just the user. "none" means nobody will get operator status. - - - 300 - + - - Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours. + Use this global setting to change your "NickServ" password. - + - See also the auto_reconnect setting. + This setting is also available for all IM accounts to change the password BitlBee uses to connect to the service. + + + + Note that BitlBee will always say this setting is empty. This doesn't mean there is no password, it just means that, for security reasons, BitlBee stores passwords somewhere else so they can't just be retrieved in plain text. - - - False - + + - - By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data. + Currently only available for Jabber connections. Specifies the port number to connect to. Usually this should be set to 5222, or 5223 for SSL-connections. + + + + + True + - Using the buddy_sendbuffer_delay setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent. + If value is true, messages from users will appear in separate query windows. If false, messages from users will appear in the control channel. - Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases. + This setting is remembered (during one session) per-user, this setting only changes the default state. This option takes effect as soon as you reconnect. - - - 200 + + lifo + lifo, fifo - - Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds. + This changes the order in which the questions from root (usually authorization requests from buddies) should be answered. When set to lifo, BitlBee immediately displays all new questions and they should be answered in reverse order. When this is set to fifo, BitlBee displays the first question which comes in and caches all the others until you answer the first one. - See also the buddy_sendbuffer setting. + Although the fifo setting might sound more logical (and used to be the default behaviour in older BitlBee versions), it turned out not to be very convenient for many users when they missed the first question (and never received the next ones). + + + BitlBee + + + + Can be set for Jabber connections. You can use this to connect to your Jabber account from multiple clients at once, with every client using a different resource string. + + - - root - root, last + + True - With this value set to root, lines written in the control channel without any nickname in front of them will be interpreted as commands. If you want BitlBee to send those lines to the last person you addressed in the control channel, set this to last. + If enabled causes BitlBee to save all current settings and account details when user disconnects. This is enabled by default, and these days there's not really a reason to have it disabled anymore. + + + + + Can be set for Jabber- and OSCAR-connections. For OSCAR, this must be set to login.icq.com if it's an ICQ connection, or login.oscar.aol.com if it's an AIM connection. For Jabber, you have to set this if the servername isn't equal to the part after the @ in the Jabber handle. + + - + False - - With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name". - + + + Currently only available for Jabber connections. Set this to true if the server accepts SSL connections. + + - + + True + - Use this setting to change your "NickServ" password. + Determines what BitlBee should do with HTML in messages. Normally this is turned on and HTML will be stripped from messages, if BitlBee thinks there is HTML. + + + If BitlBee fails to detect this sometimes (most likely in AIM messages over an ICQ connection), you can set this setting to always, but this might sometimes accidentally strip non-HTML things too. - - lifo - lifo, fifo + + ": " - This changes the order in which the questions from root (usually authorization requests from buddies) should be answered. When set to lifo, BitlBee immediately displays all new questions and they should be answered in reverse order. When this is set to fifo, BitlBee displays the first question which comes in and caches all the others until you answer the first one. + It's customary that messages meant for one specific person on an IRC channel are prepended by his/her alias followed by a colon ':'. BitlBee does this by default. If you prefer a different character, you can set it using set to_char. - Although the fifo setting might sound more logical (and used to be the default behaviour in older BitlBee versions), it turned out not to be very convenient for many users when they missed the first question (and never received the next ones). + Please note that this setting is only used for incoming messages. For outgoing messages you can use ':' (colon) or ',' to separate the destination nick from the message, and this is not configurable. - - True + + False - Hereby you can change whether you want all lower case nick names or leave the case as it intended by your peer. + Sends you a /notice when a user starts typing a message (if the protocol supports it, MSN for example). This is a bug, not a feature. (But please don't report it.. ;-) You don't want to use it. Really. In fact the typing-notification is just one of the least useful 'innovations' ever. It's just there because some guy will probably ask me about it anyway. ;-) - diff --git a/doc/user-guide/help.xsl b/doc/user-guide/help.xsl index 0eb1a88b..394530a7 100644 --- a/doc/user-guide/help.xsl +++ b/doc/user-guide/help.xsl @@ -6,7 +6,7 @@ - + diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 7147a78c..e765a475 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -1548,6 +1548,13 @@ static void jabber_login(account_t *acc) gc = new_gaim_conn(acc); jd = gc->proto_data = g_new0(struct jabber_data, 1); + if( strchr( acc->user, '@' ) == NULL ) + { + hide_login_progress( gc, "Invalid account name" ); + signoff( gc ); + return; + } + resource = set_getstr(&acc->set, "resource"); loginname = create_valid_jid(acc->user, DEFAULT_SERVER, resource); diff --git a/root_commands.c b/root_commands.c index 2cf67134..389266eb 100644 --- a/root_commands.c +++ b/root_commands.c @@ -376,6 +376,7 @@ static void cmd_account( irc_t *irc, char **cmd ) if( a == NULL ) { + g_free( acc_handle ); irc_usermsg( irc, "Invalid account" ); return; } @@ -386,11 +387,13 @@ static void cmd_account( irc_t *irc, char **cmd ) if( a->gc && s && s->flags & ACC_SET_OFFLINE_ONLY ) { + g_free( acc_handle ); irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" ); return; } else if( !a->gc && s && s->flags & ACC_SET_ONLINE_ONLY ) { + g_free( acc_handle ); irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" ); return; } -- cgit v1.2.3 From 00a52700d1dbab0736c7ace63c8be2f17b08b8f6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 14 Jul 2006 20:24:59 +0200 Subject: Added a per-connection auto_reconnect setting. --- account.c | 2 ++ protocols/nogaim.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/account.c b/account.c index 28c33d3b..86e35f76 100644 --- a/account.c +++ b/account.c @@ -51,6 +51,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; + s = set_add( &a->set, "auto_reconnect", "true", set_eval_account, a ); + s = set_add( &a->set, "password", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 54965b84..f0008385 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -310,7 +310,8 @@ void signoff( struct gaim_connection *gc ) { /* Uhm... This is very sick. */ } - else if( !gc->wants_to_die && set_getint( &irc->set, "auto_reconnect" ) ) + else if( !gc->wants_to_die && set_getbool( &irc->set, "auto_reconnect" ) && + set_getbool( &a->set, "auto_reconnect" ) ) { int delay = set_getint( &irc->set, "auto_reconnect_delay" ); -- cgit v1.2.3 From 89a180978d3e5d81300b82923e8a208ee085d754 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 14 Jul 2006 20:27:02 +0200 Subject: More documentation updates: Added a Scope: line for every setting (for per-account and global settings) and leaving out the Default: line when there is no default specified in XML (like with the display_name setting). --- doc/user-guide/Makefile | 2 +- doc/user-guide/commands.xml | 79 +++++++++++++++++++++++---------------------- doc/user-guide/help.xsl | 5 ++- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/doc/user-guide/Makefile b/doc/user-guide/Makefile index 98c4e99f..eb31fc0f 100644 --- a/doc/user-guide/Makefile +++ b/doc/user-guide/Makefile @@ -27,7 +27,7 @@ help.xml: commands.xml %.db.xml: %.xml docbook.xsl xsltproc --xinclude --output $@ docbook.xsl $< -help.txt: help.xml help.xsl +help.txt: help.xml help.xsl commands.xml misc.xml quickstart.xml xsltproc --stringparam extraparanewline "$(EXTRAPARANEWLINE)" --xinclude help.xsl $< | perl -0077 -pe 's/\n\n%/\n%/s; s/_b_/\002/g;' > $@ clean: diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index d28a8531..fd855360 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -295,8 +295,8 @@ - - True + + true @@ -309,8 +309,8 @@ - - False + + false @@ -320,11 +320,14 @@ See also the auto_reconnect_delay setting. - + + This setting can also be changed for specific accounts using the account set command. (However, these values will be ignored if the global auto_reconnect setting is disabled!) + + - + 300 @@ -338,8 +341,8 @@ - - True + + true @@ -348,8 +351,8 @@ - - False + + false @@ -366,7 +369,7 @@ - + 200 @@ -381,7 +384,7 @@ - + iso8859-1 you can get a list of all possible values by doing 'iconv -l' in a shell @@ -397,8 +400,8 @@ - - False + + false @@ -407,7 +410,7 @@ - + root root, last @@ -418,7 +421,7 @@ - + Currently only available for MSN connections. This setting allows you to read and change your "friendly name" for this connection. Since this is a server-side setting, it can't be changed when the account is off-line. @@ -426,15 +429,15 @@ - - False + + false With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name". - + root root, add, add_private, add_channel, ignore @@ -461,8 +464,8 @@ - - True + + true @@ -472,7 +475,7 @@ - + both both, root, user, none @@ -487,7 +490,7 @@ - + Use this global setting to change your "NickServ" password. @@ -503,7 +506,7 @@ - + Currently only available for Jabber connections. Specifies the port number to connect to. Usually this should be set to 5222, or 5223 for SSL-connections. @@ -511,8 +514,8 @@ - - True + + true @@ -525,7 +528,7 @@ - + lifo lifo, fifo @@ -540,7 +543,7 @@ - + BitlBee @@ -550,8 +553,8 @@ - - True + + true @@ -560,7 +563,7 @@ - + Can be set for Jabber- and OSCAR-connections. For OSCAR, this must be set to login.icq.com if it's an ICQ connection, or login.oscar.aol.com if it's an AIM connection. For Jabber, you have to set this if the servername isn't equal to the part after the @ in the Jabber handle. @@ -568,8 +571,8 @@ - - False + + false @@ -578,8 +581,8 @@ - - True + + true @@ -591,7 +594,7 @@ - + ": " @@ -605,8 +608,8 @@ - - False + + false diff --git a/doc/user-guide/help.xsl b/doc/user-guide/help.xsl index 394530a7..dec6a671 100644 --- a/doc/user-guide/help.xsl +++ b/doc/user-guide/help.xsl @@ -57,7 +57,10 @@ Processing setting '' ?set _b_Type:_b_ - _b_Default:_b_ + _b_Scope:_b_ + + _b_Default:_b_ + _b_Possible Values:_b_ -- cgit v1.2.3 From 04026d44c29f2b7d64f81bb2d2d061a7d111662f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 15 Jul 2006 19:26:13 +0200 Subject: Fixed a broken call to set_get() (CRASH), shut up a compiler warning in events_glib and now using the right evaluator for acc->"auto_reconnect". --- account.c | 2 +- irc.c | 2 +- lib/events_glib.c | 5 ++++- lib/events_libevent.c | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/account.c b/account.c index 86e35f76..95aa9b7c 100644 --- a/account.c +++ b/account.c @@ -51,7 +51,7 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; - s = set_add( &a->set, "auto_reconnect", "true", set_eval_account, a ); + s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); s = set_add( &a->set, "password", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE; diff --git a/irc.c b/irc.c index 9feb9f4e..fcb59c86 100644 --- a/irc.c +++ b/irc.c @@ -623,7 +623,7 @@ void irc_names( irc_t *irc, char *channel ) user_t *u; char namelist[385] = ""; struct conversation *c = NULL; - char *ops = set_getstr( irc, "ops" ); + char *ops = set_getstr( &irc->set, "ops" ); /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ diff --git a/lib/events_glib.c b/lib/events_glib.c index 620720cd..38938380 100644 --- a/lib/events_glib.c +++ b/lib/events_glib.c @@ -121,7 +121,10 @@ gint b_input_add(gint source, b_input_condition condition, b_event_handler funct gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) { - gint st = g_timeout_add(timeout, func, data); + /* GSourceFunc and the BitlBee event handler function aren't + really the same, but they're "compatible". ;-) It will do + for now, BitlBee only looks at the "data" argument. */ + gint st = g_timeout_add(timeout, (GSourceFunc) func, data); event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st ); diff --git a/lib/events_libevent.c b/lib/events_libevent.c index 1119c2ab..f2b4d15c 100644 --- a/lib/events_libevent.c +++ b/lib/events_libevent.c @@ -100,7 +100,7 @@ static void b_event_passthrough( int fd, short event, void *data ) event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); /* Since the called function might cancel this handler already - (which free()s b_ev, we have to remember the ID here. */ + (which free()s b_ev), we have to remember the ID here. */ id = b_ev->id; if( quitting ) -- cgit v1.2.3 From 0aaca60fdc1a6793b438ecc926bd937073d22685 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 19 Jul 2006 18:52:38 +0200 Subject: Added some (more) comments to .h files in lib/ and some minor fixes/cleanups. --- doc/user-guide/commands.xml | 4 ++++ irc.c | 1 - lib/events.h | 31 ++++++++++++++++++++++++++----- lib/http_client.h | 45 +++++++++++++++++++++++++++++++++++---------- lib/rc4.h | 2 ++ lib/ssl_client.h | 30 ++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 16 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index fd855360..0016d190 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -745,6 +745,10 @@ This command allows to set the friendly name of an im account. If no new name is specified the command will report the current name. When the name contains spaces, don't forget to quote the whole nick in double quotes. Currently this command is only supported by the MSN protocol. + + + It is recommended to use the per-account display_name setting to read and change this information. The nick command is deprecated. + diff --git a/irc.c b/irc.c index fcb59c86..0373f176 100644 --- a/irc.c +++ b/irc.c @@ -651,7 +651,6 @@ void irc_names( irc_t *irc, char *channel ) else if( ( c = conv_findchannel( channel ) ) ) { GList *l; - char *ops = set_getstr( &irc->set, "ops" ); /* root and the user aren't in the channel userlist but should show up in /NAMES, so list them first: */ diff --git a/lib/events.h b/lib/events.h index 781fca6a..0588547f 100644 --- a/lib/events.h +++ b/lib/events.h @@ -19,11 +19,17 @@ * */ -/* - * Split off the event handling things from proxy.[ch] (and adding timer - * stuff. This to allow BitlBee to use other libs than GLib for event - * handling. - */ +/* This stuff used to be in proxy.c too, but I split it off so BitlBee can + use other libraries (like libevent) to handle events. proxy.c is one very + nice piece of work from Gaim. It connects to a TCP server in the back- + ground and calls a callback function once the connection is ready to use. + This function (proxy_connect()) can be found in proxy.c. (It also + transparently handles HTTP/SOCKS proxies, when necessary.) + + This file offers some extra event handling toys, which will be handled + by GLib or libevent. The advantage of using libevent is that it can use + more advanced I/O polling functions like epoll() in recent Linux + kernels. This should improve BitlBee's scalability. */ #ifndef _EVENTS_H_ @@ -38,12 +44,15 @@ #include #include +/* The conditions you can pass to gaim_input_add()/that will be passed to + the given callback function. */ typedef enum { GAIM_INPUT_READ = 1 << 1, GAIM_INPUT_WRITE = 1 << 2 } b_input_condition; typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); +/* For internal use. */ #define GAIM_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR) #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) @@ -51,14 +60,26 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co // #define event_debug( x... ) printf( x ) #define event_debug( x... ) +/* Call this once when the program starts. It'll initialize the event handler + library (if necessary) and then return immediately. */ G_MODULE_EXPORT void b_main_init(); + +/* This one enters the event loop. It shouldn't return until one of the event + handlers calls b_main_quit(). */ G_MODULE_EXPORT void b_main_run(); G_MODULE_EXPORT void b_main_quit(); + +/* Add event handlers (for I/O or a timeout). The event handler will be called + every time the event "happens", until your event handler returns FALSE (or + until you remove it using b_event_remove(). As usual, the data argument + can be used to pass your own data to the event handler. */ G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data); G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data); G_MODULE_EXPORT void b_event_remove(gint id); +/* For now, closesocket() is only a function when using libevent. With GLib + it's a preprocessor macro. */ #ifdef EVENTS_LIBEVENT G_MODULE_EXPORT void closesocket(int fd); #endif diff --git a/lib/http_client.h b/lib/http_client.h index 50ee80cf..78d6dbd1 100644 --- a/lib/http_client.h +++ b/lib/http_client.h @@ -23,24 +23,48 @@ Suite 330, Boston, MA 02111-1307 USA */ -#include +/* http_client allows you to talk (asynchronously, again) to HTTP servers. + In the "background" it will send the whole query and wait for a complete + response to come back. Right now it's only used by the MSN Passport + authentication code, but it might be useful for other things too (for + example the AIM usericon patch uses this so icons can be stored on + webservers instead of the local filesystem). + + Didn't test this too much, but it seems to work well. Just don't look + at the code that handles HTTP 30x redirects. ;-) The function is + probably not very useful for downloading lots of data since it keeps + everything in a memory buffer until the download is completed (and + can't pass any data or whatever before then). It's very useful for + doing quick requests without blocking the whole program, though. */ +#include #include "ssl_client.h" struct http_request; +/* Your callback function should look like this: */ typedef void (*http_input_function)( struct http_request * ); +/* This structure will be filled in by the http_dorequest* functions, and + it will be passed to the callback function. Use the data field to add + your own data. */ struct http_request { - char *request; - int request_length; - int status_code; - char *status_string; + char *request; /* The request to send to the server. */ + int request_length; /* Its size. */ + int status_code; /* The numeric HTTP status code. (Or -1 + if something really went wrong) */ + char *status_string; /* The error text. */ char *reply_headers; char *reply_body; - int body_size; - int finished; + int body_size; /* The number of bytes in reply_body. */ + int finished; /* Set to non-0 if the request was completed + successfully. */ + + http_input_function func; + gpointer data; + + /* Please don't touch the things down here, you shouldn't need them. */ void *ssl; int fd; @@ -48,10 +72,11 @@ struct http_request int inpa; int bytes_written; int bytes_read; - - http_input_function func; - gpointer data; }; +/* The _url variant is probably more useful than the raw version. The raw + version is probably only useful if you want to do POST requests or if + you want to add some extra headers. As you can see, HTTPS connections + are also supported (using ssl_client). */ void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); void *http_dorequest_url( char *url_string, http_input_function func, gpointer data ); diff --git a/lib/rc4.h b/lib/rc4.h index 6c9ea6b9..2d4d3cc8 100644 --- a/lib/rc4.h +++ b/lib/rc4.h @@ -22,6 +22,8 @@ \***************************************************************************/ +/* See rc4.c for more information. */ + struct rc4_state { unsigned char S[256]; diff --git a/lib/ssl_client.h b/lib/ssl_client.h index 1a9c79e9..964caee4 100644 --- a/lib/ssl_client.h +++ b/lib/ssl_client.h @@ -23,20 +23,50 @@ Suite 330, Boston, MA 02111-1307 USA */ +/* ssl_client makes it easier to open SSL connections to servers. (It + doesn't offer SSL server functionality yet, but it could be useful + to add it later.) Different ssl_client modules are available, and + ssl_client tries to make them all behave the same. It's very simple + and basic, it just imitates the proxy_connect() function from the + Gaim libs and passes the socket to the program once the handshake + is completed. */ + #include #include "proxy.h" +/* Some generic error codes. Especially SSL_AGAIN is important if you + want to do asynchronous I/O. */ #define SSL_OK 0 #define SSL_NOHANDSHAKE 1 #define SSL_AGAIN 2 extern int ssl_errno; +/* This is what your callback function should look like. */ typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition); + +/* Connect to host:port, call the given function when the connection is + ready to be used for SSL traffic. This is all done asynchronously, no + blocking I/O! (Except for the DNS lookups, for now...) */ G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); + +/* Obviously you need special read/write functions to read data. */ G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); + +/* Abort the SSL connection and disconnect the socket. Do not use close() + directly, both the SSL library and the peer will be unhappy! */ G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); + +/* Get the fd for this connection, you will usually need it for event + handling. */ G_MODULE_EXPORT int ssl_getfd( void *conn ); + +/* This function returns GAIM_INPUT_READ/WRITE. With SSL connections it's + possible that something has to be read while actually were trying to + write something (think about key exchange/refresh/etc). So when an + SSL operation returned SSL_AGAIN, *always* use this function when + adding an event handler to the queue. (And it should perform exactly + the same action as the handler that just received the SSL_AGAIN.) */ G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); -- cgit v1.2.3 From 2811940d678bd9340055e08a0462c21e710d5714 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 27 Jul 2006 16:55:53 +0200 Subject: Copy-paste considered harmful + Fixed double handling of gc->permit/deny which actually broke the block/allow commands. --- protocols/msn/msn_util.c | 35 ----------------------------------- root_commands.c | 2 +- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index c3bd73cc..4e748099 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -53,19 +53,8 @@ int msn_logged_in( struct gaim_connection *gc ) int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char *realname_ ) { struct msn_data *md = gc->proto_data; - GSList *l, **lp = NULL; char buf[1024], *realname; - if( strcmp( list, "AL" ) == 0 ) - lp = &gc->permit; - else if( strcmp( list, "BL" ) == 0 ) - lp = &gc->deny; - - if( lp ) - for( l = *lp; l; l = l->next ) - if( g_strcasecmp( l->data, who ) == 0 ) - return( 1 ); - realname = g_new0( char, strlen( realname_ ) * 3 + 1 ); strcpy( realname, realname_ ); http_encode( realname ); @@ -75,9 +64,6 @@ int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char { g_free( realname ); - if( lp ) - *lp = g_slist_append( *lp, g_strdup( who ) ); - return( 1 ); } @@ -89,32 +75,11 @@ int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char int msn_buddy_list_remove( struct gaim_connection *gc, char *list, char *who ) { struct msn_data *md = gc->proto_data; - GSList *l = NULL, **lp = NULL; char buf[1024]; - if( strcmp( list, "AL" ) == 0 ) - lp = &gc->permit; - else if( strcmp( list, "BL" ) == 0 ) - lp = &gc->deny; - - if( lp ) - { - for( l = *lp; l; l = l->next ) - if( g_strcasecmp( l->data, who ) == 0 ) - break; - - if( !l ) - return( 1 ); - } - g_snprintf( buf, sizeof( buf ), "REM %d %s %s\r\n", ++md->trId, list, who ); if( msn_write( gc, buf, strlen( buf ) ) ) - { - if( lp ) - *lp = g_slist_remove( *lp, l->data ); - return( 1 ); - } return( 0 ); } diff --git a/root_commands.c b/root_commands.c index 3d3584b3..040d885c 100644 --- a/root_commands.c +++ b/root_commands.c @@ -579,7 +579,7 @@ static void cmd_allow( irc_t *irc, char **cmd ) format = "%-32.32s %-16.16s"; irc_usermsg( irc, format, "Handle", "Nickname" ); - for( l = a->gc->deny; l; l = l->next ) + for( l = a->gc->permit; l; l = l->next ) { user_t *u = user_findhandle( a->gc, l->data ); irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); -- cgit v1.2.3 From a36b030d747a39fed8224e6350d56d55b2aec4e2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Thu, 27 Jul 2006 21:18:33 +0200 Subject: The Yahoo! module now properly sets away states instead of away messages. (So other BitlBees can read your Yahoo! away states better and others can see the proper icons again.) --- protocols/yahoo/yahoo.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 79c0febb..28735432 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -191,13 +191,18 @@ static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg gc->away = NULL; - if( msg ) + if( state && msg && g_strcasecmp( state, msg ) != 0 ) { yd->current_status = YAHOO_STATUS_CUSTOM; gc->away = ""; } - if( state ) + else if( state ) { + /* Set msg to NULL since (if it isn't NULL already) it's equal + to state. msg must be empty if we want to use an existing + away state. */ + msg = NULL; + gc->away = ""; if( g_strcasecmp( state, "Available" ) == 0 ) { @@ -234,10 +239,7 @@ static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg else yd->current_status = YAHOO_STATUS_AVAILABLE; - if( yd->current_status == YAHOO_STATUS_INVISIBLE ) - yahoo_set_away( yd->y2_id, yd->current_status, NULL, gc->away != NULL ); - else - yahoo_set_away( yd->y2_id, yd->current_status, msg, gc->away != NULL ); + yahoo_set_away( yd->y2_id, yd->current_status, msg, gc->away != NULL ); } static GList *byahoo_away_states( struct gaim_connection *gc ) -- cgit v1.2.3 From d3a672c0b70eb7b50dcd2908d6cd6928d4f7d874 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 4 Aug 2006 15:56:53 +0200 Subject: Added a per-account web_aware setting for ICQ connections. --- protocols/oscar/oscar.c | 5 +++++ protocols/oscar/service.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index f65332dc..d30ebbe8 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -361,6 +361,11 @@ static void oscar_acc_init(account_t *acc) s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; + + if (isdigit(acc->user[0])) { + s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + } } static void oscar_login(account_t *acc) { diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index 4596974f..d55e0987 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -731,8 +731,12 @@ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status) aim_tlvlist_t *tl = NULL; guint32 data; int tlvlen; + struct gaim_connection *gc = sess ? sess->aux_data : NULL; data = AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */ + + if (gc && set_getbool(&gc->acc->set, "web_aware")) + data |= AIM_ICQ_STATE_WEBAWARE; tlvlen = aim_addtlvtochain32(&tl, 0x0006, data); -- cgit v1.2.3 From 846cec61f2b94be60c7bae7f4d0de8952e2d45fa Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 13 Aug 2006 21:08:38 +0200 Subject: Added help information for the web_aware setting. --- doc/user-guide/commands.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 0016d190..790e89f6 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -618,6 +618,20 @@ + + false + + + + ICQ allows people to see if you're on-line via a CGI-script. (http://status.icq.com/online.gif?icq=UIN) This can be nice to put on your website, but it seems that spammers also use it to see if you're online without having to add you to their contact list. So to prevent ICQ spamming, recent versions of BitlBee disable this feature by default. + + + + Unless you really intend to use this feature somewhere (on forums or maybe a website), it's probably better to keep this setting disabled. + + + + Rename (renick) a buddy rename <oldnick> <newnick> -- cgit v1.2.3 From d5ccd83c5235528df2481003502647b86b41fdc4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 13 Aug 2006 21:15:23 +0200 Subject: Extra comments in set.h and now properly using set_getbool() instead of set_getint(). --- irc.c | 4 ++-- protocols/nogaim.c | 34 +++++++++++++++++----------------- protocols/oscar/oscar.c | 4 ---- protocols/oscar/rxhandlers.c | 4 ---- root_commands.c | 2 +- set.h | 36 +++++++++++++++++++++++++++++++++--- user.c | 2 +- 7 files changed, 54 insertions(+), 32 deletions(-) diff --git a/irc.c b/irc.c index 0373f176..87cc4c78 100644 --- a/irc.c +++ b/irc.c @@ -212,7 +212,7 @@ void irc_free(irc_t * irc) log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); - if( irc->status & USTATUS_IDENTIFIED && set_getint( &irc->set, "save_on_quit" ) ) + if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) ) if( storage_save( irc, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); @@ -1057,7 +1057,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) { if( !u || !u->gc ) return; - if( set_getint( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) + if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) { int delay; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index f0008385..47e2bda6 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -207,7 +207,7 @@ void serv_got_crap( struct gaim_connection *gc, char *format, ... ) va_end( params ); if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) + ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) strip_html( text ); /* Try to find a different connection on the same protocol. */ @@ -352,12 +352,12 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea char *s; irc_t *irc = gc->irc; - if( set_getint( &irc->set, "debug" ) && 0 ) /* This message is too useless */ + if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */ serv_got_crap( gc, "Receiving user add from handle: %s", handle ); if( user_findhandle( gc, handle ) ) { - if( set_getint( &irc->set, "debug" ) ) + if( set_getbool( &irc->set, "debug" ) ) serv_got_crap( gc, "User already exists, ignoring add request: %s", handle ); return; @@ -445,7 +445,7 @@ void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname u->realname = g_strdup( realname ); - if( ( gc->flags & OPT_LOGGED_IN ) && set_getint( &gc->irc->set, "display_namechanges" ) ) + if( ( gc->flags & OPT_LOGGED_IN ) && set_getbool( &gc->irc->set, "display_namechanges" ) ) serv_got_crap( gc, "User `%s' changed name to `%s'", u->nick, u->realname ); } } @@ -508,7 +508,7 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in } else { - if( set_getint( &gc->irc->set, "debug" ) || g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "ignore" ) != 0 ) + if( set_getbool( &gc->irc->set, "debug" ) || g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { serv_got_crap( gc, "serv_got_update() for handle %s:", handle ); serv_got_crap( gc, "loggedin = %d, type = %d", loggedin, type ); @@ -567,7 +567,7 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in u->away = NULL; /* LISPy... */ - if( ( set_getint( &gc->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ + if( ( set_getbool( &gc->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ ( u->online ) && /* Don't touch offline people */ ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ @@ -590,14 +590,14 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f if( g_strcasecmp( h, "ignore" ) == 0 ) { - if( set_getint( &irc->set, "debug" ) ) + if( set_getbool( &irc->set, "debug" ) ) serv_got_crap( gc, "Ignoring message from unknown handle %s", handle ); return; } else if( g_strncasecmp( h, "add", 3 ) == 0 ) { - int private = set_getint( &irc->set, "private" ); + int private = set_getbool( &irc->set, "private" ); if( h[3] ) { @@ -619,7 +619,7 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f } if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) + ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) strip_html( msg ); while( strlen( msg ) > 425 ) @@ -659,7 +659,7 @@ void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int { user_t *u; - if( !set_getint( &gc->irc->set, "typing_notice" ) ) + if( !set_getbool( &gc->irc->set, "typing_notice" ) ) return; if( ( u = user_findhandle( gc, handle ) ) ) { @@ -681,7 +681,7 @@ void serv_got_chat_left( struct gaim_connection *gc, int id ) struct conversation *c, *l = NULL; GList *ir; - if( set_getint( &gc->irc->set, "debug" ) ) + if( set_getbool( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "You were removed from conversation %d", (int) id ); for( c = gc->conversations; c && c->id != id; c = (l=c)->next ); @@ -727,7 +727,7 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe for( c = gc->conversations; c && c->id != id; c = c->next ); if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getint( &gc->irc->set, "strip_html" ) ) ) + ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) strip_html( msg ); if( c && u ) @@ -760,7 +760,7 @@ struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, c c->channel = g_strdup( s ); g_free( s ); - if( set_getint( &gc->irc->set, "debug" ) ) + if( set_getbool( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "Creating new conversation: (id=%d,handle=%s)", id, handle ); return( c ); @@ -774,7 +774,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) user_t *u = user_findhandle( b->gc, handle ); int me = 0; - if( set_getint( &b->gc->irc->set, "debug" ) ) + if( set_getbool( &b->gc->irc->set, "debug" ) ) serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); /* It might be yourself! */ @@ -808,7 +808,7 @@ void remove_chat_buddy( struct conversation *b, char *handle, char *reason ) user_t *u; int me = 0; - if( set_getint( &b->gc->irc->set, "debug" ) ) + if( set_getbool( &b->gc->irc->set, "debug" ) ) serv_got_crap( b->gc, "User %s removed from conversation %d (%s)", handle, b->id, reason ? reason : "" ); /* It might be yourself! */ @@ -886,7 +886,7 @@ char *set_eval_away_devoice( set_t *set, char *value ) /* Horror.... */ - if( st != set_getint( &irc->set, "away_devoice" ) ) + if( st != set_getbool( &irc->set, "away_devoice" ) ) { char list[80] = ""; user_t *u = irc->users; @@ -1006,7 +1006,7 @@ int bim_set_away( struct gaim_connection *gc, char *away ) if( s ) { gc->acc->prpl->set_away( gc, s, away ); - if( set_getint( &gc->irc->set, "debug" ) ) + if( set_getbool( &gc->irc->set, "debug" ) ) serv_got_crap( gc, "Setting away state to %s", s ); } else diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index d30ebbe8..b8cf521b 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1251,10 +1251,6 @@ static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) { channel = va_arg(ap, int); userinfo = va_arg(ap, aim_userinfo_t *); - if (set_getint(sess->aux_data, "debug")) { - serv_got_crap(sess->aux_data, "channel %i called", channel); - } - switch (channel) { case 1: { /* standard message */ struct aim_incomingim_ch1_args *args; diff --git a/protocols/oscar/rxhandlers.c b/protocols/oscar/rxhandlers.c index be8aba44..7014e693 100644 --- a/protocols/oscar/rxhandlers.c +++ b/protocols/oscar/rxhandlers.c @@ -112,10 +112,6 @@ static int consumesnac(aim_session_t *sess, aim_frame_t *rx) /* Following SNAC will be related */ } - if (set_getint(sess->aux_data, "debug")) { - serv_got_crap(sess->aux_data, "snac %x/%x received", snac.family, snac.subtype); - } - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && diff --git a/root_commands.c b/root_commands.c index 389266eb..13567e8a 100644 --- a/root_commands.c +++ b/root_commands.c @@ -143,7 +143,7 @@ static void cmd_identify( irc_t *irc, char **cmd ) case STORAGE_OK: irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); irc_umode_set( irc, "+R", 1 ); - if( set_getint( &irc->set, "auto_connect" ) ) + if( set_getbool( &irc->set, "auto_connect" ) ) cmd_account( irc, account_on ); break; case STORAGE_OTHER_ERROR: diff --git a/set.h b/set.h index 48bc8145..14043c2f 100644 --- a/set.h +++ b/set.h @@ -23,15 +23,30 @@ Suite 330, Boston, MA 02111-1307 USA */ +/* This used to be specific to irc_t structures, but it's more generic now + (so it can also be used for account_t structs). It's pretty simple, but + so far pretty useful. + + In short, it just keeps a linked list of settings/variables and it also + remembers a default value for every setting. And to prevent the user + from setting invalid values, you can write an evaluator function for + every setting, which can check a new value and block it by returning + NULL, or replace it by returning a new value. See struct set.eval. */ + typedef struct set { - void *data; + void *data; /* Here you can save a pointer to the + object this settings belongs to. */ char *key; char *value; - char *def; /* Default */ + char *def; /* Default value. If the set_setstr() function + notices a new value is exactly the same as + the default, value gets set to NULL. So when + you read a setting, don't forget about this! */ - int flags; + int flags; /* See account.h, for example. set.c doesn't use + this (yet?). */ /* Eval: Returns NULL if the value is incorrect or exactly the passed value variable. When returning a corrected value, @@ -40,18 +55,33 @@ typedef struct set struct set *next; } set_t; +/* Should be pretty clear. */ set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ); + +/* Returns the raw set_t. Might be useful sometimes. */ set_t *set_find( set_t **head, char *key ); + +/* Returns a pointer to the string value of this setting. Don't modify the + returned string, and don't free() it! */ G_MODULE_EXPORT char *set_getstr( set_t **head, char *key ); + +/* Get an integer. Right now this also converts true/false/on/off/etc to + numbers, but this is for historical reasons, please use set_getbool() + for booleans instead. */ G_MODULE_EXPORT int set_getint( set_t **head, char *key ); G_MODULE_EXPORT int set_getbool( set_t **head, char *key ); + +/* set_setstr() strdup()s the given value, so after using this function + you can free() it, if you want. */ int set_setstr( set_t **head, char *key, char *value ); int set_setint( set_t **head, char *key, int value ); void set_del( set_t **head, char *key ); +/* Two very useful generic evaluators. */ char *set_eval_int( set_t *set, char *value ); char *set_eval_bool( set_t *set, char *value ); +/* Some not very generic evaluators that really shouldn't be here... */ char *set_eval_to_char( set_t *set, char *value ); char *set_eval_ops( set_t *set, char *value ); char *set_eval_charset( set_t *set, char *value ); diff --git a/user.c b/user.c index 0892a23c..ff65fe66 100644 --- a/user.c +++ b/user.c @@ -66,7 +66,7 @@ user_t *user_add( irc_t *irc, char *nick ) } u->user = u->realname = u->host = u->nick = g_strdup( nick ); - u->is_private = set_getint( &irc->set, "private" ); + u->is_private = set_getbool( &irc->set, "private" ); key = g_strdup( nick ); nick_lc( key ); -- cgit v1.2.3 From 08cdb93834bcc1b67e4e7f44e8bc90b42c686658 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 14 Aug 2006 15:25:05 +0200 Subject: Updated the note about encryption in the README file. --- doc/README | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/doc/README b/doc/README index c82c9aeb..75988004 100644 --- a/doc/README +++ b/doc/README @@ -154,17 +154,27 @@ http://code.bitlbee.org/ A NOTE ON ENCRYPTION ==================== -BitlBee stores the accounts and settings (not your contact list though) in -some sort of encrypted/obfuscated format. - -*** THIS IS NOT A SAFE FORMAT! *** - -You should still make sure the rights to the configuration directory and -files are set so that only root and the BitlBee user can read/write them. - -This format is not to prevent malicicous users from running with your -passwords, but to prevent accidental glimpses of the administrators to cause -any harm. You have no choice but to trust root though. +There used to be a note here about the simple obfuscation method used to +make the passwords in the configuration files unreadable. However, BitlBee +now uses a better format (and real encryption (salted MD5 and RC4)) to store +the passwords. This means that people who somehow get their hands on your +configuration files can't easily extract your passwords from them anymore. + +However, once you log into the BitlBee server and send your password, an +intruder with tcpdump can still read your passwords. This can't really be +avoided, of course. The new format is a lot more reliable (because it can't +be cracked with just very basic crypto analysis anymore), but you still have +to be careful. The main extra protection offered by the new format is that +the files can only be cracked with some help from the user (by sending the +password at login time). + +So if you run a public server, it's most important that you don't give root +access to people who like to play with tcpdump. Also, it's a good idea to +delete all *.nicks/*.accounts files as soon as BitlBee converted them to the +new format (which happens as soon as the user logs in, it can't be done +automatically because it needs the password for that account). You won't +need them anymore (unless you want to switch back to an older BitlBee +version) and they only make it easier for others to crack your passwords. LEGAL @@ -191,5 +201,5 @@ also licensed under the GPL. BitlBee - An IRC to other chat networks gateway - Copyright (C) 2002-2005 Wilmer van der Gaast + Copyright (C) 2002-2006 Wilmer van der Gaast and others -- cgit v1.2.3 From d1f8759e5034dacb489123719ca86c5d802f154d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 14 Aug 2006 21:32:43 +0200 Subject: Just a little typo in rc4.c --- lib/rc4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rc4.c b/lib/rc4.c index 5e334507..6223077a 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -45,7 +45,7 @@ #include "rc4.h" /* Add some seed to the password, to make sure we *never* use the same key. - This defines how many byes we use as a seed. */ + This defines how many bytes we use as a seed. */ #define RC4_IV_LEN 6 /* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended -- cgit v1.2.3 From 9829ae028dc1f0d8ab60cb18293234f2d4cc19b8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 14 Aug 2006 22:17:54 +0200 Subject: Added information about the new file format to CHANGES. --- doc/CHANGES | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/CHANGES b/doc/CHANGES index 7b95e8cb..cd100741 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,3 +1,27 @@ +Version x.x: +- Most important change: New file format for user data (accounts, nicks and + settings). Migration to the new format should happen transparently, + BitlBee will read the old files and once you quit/save it will save in the + new format. It is recommended to delete the old files (BitlBee doesn't do + this automatically, it will just ignore them) since they won't be used + anymore (and since the old file format is a security risk). Some advantages + of this file format switch: + * Safer format, since the identify-password is now salted before generating + a checksum. This way one can't use MD5 reverse lookup databases to crack + passwords. Also, the IM-account passwords are encrypted using RC4 instead + of the simple obfuscation scheme which BitlBee used so far. + * Easier to extend than the previous format (at least the .nicks format was + horribly limited). + * Nicknames for buddies are now saved per-account instead of per-protocol. + So far having one buddy on multiple accounts of the same protocol was a + problem because the nicks generated for the two "instances" of this buddy + were very unpredictable. + NOTE: This also means that "account del" removes not just the account, + BUT ALSO ALL NICKNAMES! If you're changing IM accounts and don't want to + lose the nicknames, you can now use "account set" to change the username + and password for the existing connection. + * Per-account settings (see the new "account set" command). + Version 1.0: - Removed some crashy debugging code. - QUIT command now works before logging in. (Mainly an RFC-compliancy fix.) -- cgit v1.2.3 From 0383943c38ee308805798974bfccbd3327369c6a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 25 Aug 2006 00:06:52 +0200 Subject: Added message on successful creation of accounts and fixed "set password" command. --- irc.c | 4 +++- root_commands.c | 1 + set.c | 2 +- set.h | 6 ++++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/irc.c b/irc.c index 87cc4c78..8f79b535 100644 --- a/irc.c +++ b/irc.c @@ -32,8 +32,10 @@ static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); GSList *irc_connection_list = NULL; -static char *passchange( irc_t *irc, void *set, char *value ) +static char *passchange( set_t *set, char *value ) { + irc_t *irc = set->data; + irc_setpass( irc, value ); irc_usermsg( irc, "Password successfully changed" ); return NULL; diff --git a/root_commands.c b/root_commands.c index 13567e8a..3097dc81 100644 --- a/root_commands.c +++ b/root_commands.c @@ -168,6 +168,7 @@ static void cmd_register( irc_t *irc, char **cmd ) break; case STORAGE_OK: + irc_usermsg( irc, "Account successfully created" ); irc->status |= USTATUS_IDENTIFIED; irc_umode_set( irc, "+R", 1 ); break; diff --git a/set.c b/set.c index 4620264f..6a45fd14 100644 --- a/set.c +++ b/set.c @@ -25,7 +25,7 @@ #define BITLBEE_CORE #include "bitlbee.h" -set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ) +set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data ) { set_t *s = set_find( head, key ); diff --git a/set.h b/set.h index 14043c2f..37d2430f 100644 --- a/set.h +++ b/set.h @@ -33,6 +33,8 @@ every setting, which can check a new value and block it by returning NULL, or replace it by returning a new value. See struct set.eval. */ +typedef char *(*set_eval) ( struct set *set, char *value ); + typedef struct set { void *data; /* Here you can save a pointer to the @@ -51,12 +53,12 @@ typedef struct set /* Eval: Returns NULL if the value is incorrect or exactly the passed value variable. When returning a corrected value, set_setstr() should be able to free() the returned string! */ - char *(*eval) ( struct set *set, char *value ); + set_eval eval; struct set *next; } set_t; /* Should be pretty clear. */ -set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data ); +set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data ); /* Returns the raw set_t. Might be useful sometimes. */ set_t *set_find( set_t **head, char *key ); -- cgit v1.2.3 From 54794b8e01b5cce0675e9cfbd7282d011ebcb99e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 25 Aug 2006 14:34:36 +0200 Subject: Added msn_http_encode() so it can be used in msn_buddy_list_add() too. Most likely fixes #198. --- protocols/msn/msn.c | 20 ++------------------ protocols/msn/msn.h | 1 + protocols/msn/msn_util.c | 30 +++++++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index a8d85a66..0d2d7283 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -211,8 +211,7 @@ static void msn_set_away( struct gaim_connection *gc, char *state, char *message static void msn_set_info( struct gaim_connection *gc, char *info ) { - int i; - char buf[1024], *fn, *s; + char buf[1024], *fn; struct msn_data *md = gc->proto_data; if( strlen( info ) > 129 ) @@ -221,22 +220,7 @@ static void msn_set_info( struct gaim_connection *gc, char *info ) return; } - /* Of course we could use http_encode() here, but when we encode - every character, the server is less likely to complain about the - chosen name. However, the MSN server doesn't seem to like escaped - non-ASCII chars, so we keep those unescaped. */ - s = fn = g_new0( char, strlen( info ) * 3 + 1 ); - for( i = 0; info[i]; i ++ ) - if( info[i] & 128 ) - { - *s = info[i]; - s ++; - } - else - { - g_snprintf( s, 4, "%%%02X", info[i] ); - s += 3; - } + fn = msn_http_encode( info ); g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, gc->username, fn ); msn_write( gc, buf, strlen( buf ) ); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index dbbb6aa0..b4777d41 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -156,6 +156,7 @@ void msn_buddy_ask( struct gaim_connection *gc, char *handle, char *realname ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); +char *msn_http_encode( const char *input ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 4e748099..ff4c148c 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -55,9 +55,7 @@ int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char struct msn_data *md = gc->proto_data; char buf[1024], *realname; - realname = g_new0( char, strlen( realname_ ) * 3 + 1 ); - strcpy( realname, realname_ ); - http_encode( realname ); + realname = msn_http_encode( realname_ ); g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s\r\n", ++md->trId, list, who, realname ); if( msn_write( gc, buf, strlen( buf ) ) ) @@ -314,3 +312,29 @@ int msn_handler( struct msn_handler_data *h ) return( 1 ); } + +/* The difference between this function and the normal http_encode() function + is that this one escapes every 7-bit ASCII character because this is said + to avoid some lame server-side checks when setting a real-name. Also, + non-ASCII characters are not escaped because MSN servers don't seem to + appreciate that! */ +char *msn_http_encode( const char *input ) +{ + char *ret, *s; + int i; + + ret = s = g_new0( char, strlen( input ) * 3 + 1 ); + for( i = 0; input[i]; i ++ ) + if( input[i] & 128 ) + { + *s = input[i]; + s ++; + } + else + { + g_snprintf( s, 4, "%%%02X", input[i] ); + s += 3; + } + + return ret; +} -- cgit v1.2.3 From 8320a7a0012f868e5878a5a9f52676a5fece02e1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 17 Sep 2006 17:30:35 +0200 Subject: Strings passed to xml_text aren't necessarily \0-terminated, so don't count on that anymore. --- storage_xml.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/storage_xml.c b/storage_xml.c index 2585b475..52240a36 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -226,11 +226,15 @@ static void xml_end_element( GMarkupParseContext *ctx, const gchar *element_name } } -static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) +static void xml_text( GMarkupParseContext *ctx, const gchar *text_orig, gsize text_len, gpointer data, GError **error ) { + char text[text_len+1]; struct xml_parsedata *xd = data; irc_t *irc = xd->irc; + strncpy( text, text_orig, text_len ); + text[text_len] = 0; + if( xd->pass_st < XML_PASS_OK ) { /* Let's not parse anything else if we only have to check -- cgit v1.2.3 From 51fdc4512cc77fd6b59b582f27887657d7c3721e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 17 Sep 2006 17:56:16 +0200 Subject: add_cr() is not used anymore, and HTML entity handling got UTFized some time ago already, so no need for that FIXME comment. --- lib/misc.c | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 17599946..64666492 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -53,36 +53,6 @@ void strip_linefeed(gchar *text) g_free(text2); } -char *add_cr(char *text) -{ - char *ret = NULL; - int count = 0, j; - unsigned int i; - - if (text[0] == '\n') - count++; - for (i = 1; i < strlen(text); i++) - if (text[i] == '\n' && text[i - 1] != '\r') - count++; - - if (count == 0) - return g_strdup(text); - - ret = g_malloc0(strlen(text) + count + 1); - - i = 0; j = 0; - if (text[i] == '\n') - ret[j++] = '\r'; - ret[j++] = text[i++]; - for (; i < strlen(text); i++) { - if (text[i] == '\n' && text[i - 1] != '\r') - ret[j++] = '\r'; - ret[j++] = text[i]; - } - - return ret; -} - char *normalize(const char *s) { static char buf[BUF_LEN]; @@ -123,12 +93,10 @@ time_t get_time(int year, int month, int day, int hour, int min, int sec) typedef struct htmlentity { - char code[8]; - char is[4]; + char code[7]; + char is[3]; } htmlentity_t; -/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */ - static const htmlentity_t ent[] = { { "lt", "<" }, -- cgit v1.2.3 From 9544acba1fecb11b0b6a0e6260e302890d4c2337 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 20 Sep 2006 11:34:02 +0200 Subject: Using LGPL for generic parts, where possible. --- lib/rc4.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/rc4.c b/lib/rc4.c index 6223077a..f2c76f54 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -5,19 +5,19 @@ * * * Copyright 2006 Wilmer van der Gaast * * * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU 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 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, version * +* 2.1. * * * -* This program is distributed in the hope that it will be useful, * +* 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 General Public License for more details. * +* 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 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. * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * * \***************************************************************************/ -- cgit v1.2.3 From 8f243add8b64f9936c49bbeafac77aa9961cf264 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 20 Sep 2006 11:36:53 +0200 Subject: Removed old Jabber module, started to fill in the new stuff. (xmltree developed outside this tree) --- protocols/jabber/Makefile | 2 +- protocols/jabber/asciitab.h | 62 - protocols/jabber/expat.c | 54 - protocols/jabber/hashtable.c | 142 --- protocols/jabber/hashtable.h | 69 -- protocols/jabber/iasciitab.h | 63 - protocols/jabber/jabber.c | 2392 ------------------------------------ protocols/jabber/jabber.h | 315 ----- protocols/jabber/jid.c | 170 --- protocols/jabber/jpacket.c | 159 --- protocols/jabber/jutil.c | 122 -- protocols/jabber/latin1tab.h | 62 - protocols/jabber/lib.h | 343 ------ protocols/jabber/libxode.h | 398 ------ protocols/jabber/log.c | 44 - protocols/jabber/log.h | 36 - protocols/jabber/nametab.h | 150 --- protocols/jabber/pool.c | 247 ---- protocols/jabber/str.c | 215 ---- protocols/jabber/utf8tab.h | 63 - protocols/jabber/xmldef.h | 34 - protocols/jabber/xmlnode.c | 705 ----------- protocols/jabber/xmlparse.c | 2640 ---------------------------------------- protocols/jabber/xmlparse.h | 476 -------- protocols/jabber/xmlrole.c | 1104 ----------------- protocols/jabber/xmlrole.h | 111 -- protocols/jabber/xmltok.c | 1518 ----------------------- protocols/jabber/xmltok.h | 307 ----- protocols/jabber/xmltok_impl.c | 1737 -------------------------- protocols/jabber/xmltok_impl.h | 71 -- protocols/jabber/xmltok_ns.c | 117 -- protocols/jabber/xmltree.c | 481 ++++++++ protocols/jabber/xmltree.h | 90 ++ 33 files changed, 572 insertions(+), 13927 deletions(-) delete mode 100644 protocols/jabber/asciitab.h delete mode 100644 protocols/jabber/expat.c delete mode 100644 protocols/jabber/hashtable.c delete mode 100644 protocols/jabber/hashtable.h delete mode 100644 protocols/jabber/iasciitab.h delete mode 100644 protocols/jabber/jabber.c delete mode 100644 protocols/jabber/jabber.h delete mode 100644 protocols/jabber/jid.c delete mode 100644 protocols/jabber/jpacket.c delete mode 100644 protocols/jabber/jutil.c delete mode 100644 protocols/jabber/latin1tab.h delete mode 100644 protocols/jabber/lib.h delete mode 100644 protocols/jabber/libxode.h delete mode 100644 protocols/jabber/log.c delete mode 100644 protocols/jabber/log.h delete mode 100644 protocols/jabber/nametab.h delete mode 100644 protocols/jabber/pool.c delete mode 100644 protocols/jabber/str.c delete mode 100644 protocols/jabber/utf8tab.h delete mode 100644 protocols/jabber/xmldef.h delete mode 100644 protocols/jabber/xmlnode.c delete mode 100644 protocols/jabber/xmlparse.c delete mode 100644 protocols/jabber/xmlparse.h delete mode 100644 protocols/jabber/xmlrole.c delete mode 100644 protocols/jabber/xmlrole.h delete mode 100644 protocols/jabber/xmltok.c delete mode 100644 protocols/jabber/xmltok.h delete mode 100644 protocols/jabber/xmltok_impl.c delete mode 100644 protocols/jabber/xmltok_impl.h delete mode 100644 protocols/jabber/xmltok_ns.c create mode 100644 protocols/jabber/xmltree.c create mode 100644 protocols/jabber/xmltree.h diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 9b414dc8..ee34ec73 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = expat.o hashtable.o jid.o jpacket.o jutil.o log.o pool.o str.o xmlnode.o xmlparse.o xmlrole.o xmltok.o jabber.o +objects = jabber.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/asciitab.h b/protocols/jabber/asciitab.h deleted file mode 100644 index 8a8a2dd3..00000000 --- a/protocols/jabber/asciitab.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/protocols/jabber/expat.c b/protocols/jabber/expat.c deleted file mode 100644 index 0eedb321..00000000 --- a/protocols/jabber/expat.c +++ /dev/null @@ -1,54 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "lib.h" -#include - -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts) -{ - int i = 0; - if (atts == NULL) return; - while (atts[i] != '\0') - { - xmlnode_put_attrib(owner, atts[i], atts[i+1]); - i += 2; - } -} diff --git a/protocols/jabber/hashtable.c b/protocols/jabber/hashtable.c deleted file mode 100644 index 82c33bc3..00000000 --- a/protocols/jabber/hashtable.c +++ /dev/null @@ -1,142 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -csompliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" - -#ifdef XML_UNICODE_WCHAR_T -#ifndef XML_UNICODE -#define XML_UNICODE -#endif -#endif - -#include "hashtable.h" - -#define INIT_SIZE 64 - -static -int keyeq(KEY s1, KEY s2) -{ - for (; *s1 == *s2; s1++, s2++) - if (*s1 == 0) - return 1; - return 0; -} - -static -unsigned long hash(KEY s) -{ - unsigned long h = 0; - while (*s) - h = (h << 5) + h + (unsigned char)*s++; - return h; -} - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) -{ - size_t i; - if (table->size == 0) { - if (!createSize) - return 0; - table->v = calloc(INIT_SIZE, sizeof(NAMED *)); - if (!table->v) - return 0; - table->size = INIT_SIZE; - table->usedLim = INIT_SIZE / 2; - i = hash(name) & (table->size - 1); - } - else { - unsigned long h = hash(name); - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) { - if (keyeq(name, table->v[i]->name)) - return table->v[i]; - } - if (!createSize) - return 0; - if (table->used == table->usedLim) { - /* check for overflow */ - size_t newSize = table->size * 2; - NAMED **newV = calloc(newSize, sizeof(NAMED *)); - if (!newV) - return 0; - for (i = 0; i < table->size; i++) - if (table->v[i]) { - size_t j; - for (j = hash(table->v[i]->name) & (newSize - 1); - newV[j]; - j == 0 ? j = newSize - 1 : --j) - ; - newV[j] = table->v[i]; - } - g_free(table->v); - table->v = newV; - table->size = newSize; - table->usedLim = newSize/2; - for (i = h & (table->size - 1); - table->v[i]; - i == 0 ? i = table->size - 1 : --i) - ; - } - } - table->v[i] = calloc(1, createSize); - if (!table->v[i]) - return 0; - table->v[i]->name = name; - (table->used)++; - return table->v[i]; -} - -void hashTableDestroy(HASH_TABLE *table) -{ - size_t i; - for (i = 0; i < table->size; i++) { - NAMED *p = table->v[i]; - if (p) - g_free(p); - } - g_free(table->v); -} - -void hashTableInit(HASH_TABLE *p) -{ - p->size = 0; - p->usedLim = 0; - p->used = 0; - p->v = 0; -} - -void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) -{ - iter->p = table->v; - iter->end = iter->p + table->size; -} - -NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) -{ - while (iter->p != iter->end) { - NAMED *tem = *(iter->p)++; - if (tem) - return tem; - } - return 0; -} - diff --git a/protocols/jabber/hashtable.h b/protocols/jabber/hashtable.h deleted file mode 100644 index df8ab8a4..00000000 --- a/protocols/jabber/hashtable.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -#include - -#ifdef XML_UNICODE - -#ifdef XML_UNICODE_WCHAR_T -typedef const wchar_t *KEY; -#else /* not XML_UNICODE_WCHAR_T */ -typedef const unsigned short *KEY; -#endif /* not XML_UNICODE_WCHAR_T */ - -#else /* not XML_UNICODE */ - -typedef const char *KEY; - -#endif /* not XML_UNICODE */ - -typedef struct { - KEY name; -} NAMED; - -typedef struct { - NAMED **v; - size_t size; - size_t used; - size_t usedLim; -} HASH_TABLE; - -NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize); -void hashTableInit(HASH_TABLE *); -void hashTableDestroy(HASH_TABLE *); - -typedef struct { - NAMED **p; - NAMED **end; -} HASH_TABLE_ITER; - -void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); -NAMED *hashTableIterNext(HASH_TABLE_ITER *); diff --git a/protocols/jabber/iasciitab.h b/protocols/jabber/iasciitab.h deleted file mode 100644 index 333d6bb7..00000000 --- a/protocols/jabber/iasciitab.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ -/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, -/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, -/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, -/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, -/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, -/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, -/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, -/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, -/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, -/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, -/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, -/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, -/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, -/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c deleted file mode 100644 index e765a475..00000000 --- a/protocols/jabber/jabber.c +++ /dev/null @@ -1,2392 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * gaim - * - * Some code copyright (C) 1998-1999, Mark Spencer - * libfaim code copyright 1998, 1999 Adam Fritzler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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 _WIN32 -#include -#endif -#include -#include -#include -#include -#include -#include -#include "jabber.h" -#include "nogaim.h" -#include "bitlbee.h" -#include "proxy.h" -#include "ssl_client.h" - -/* The priv member of gjconn's is a gaim_connection for now. */ -#define GJ_GC(x) ((struct gaim_connection *)(x)->priv) - -#define IQID_AUTH "__AUTH__" - -#define IQ_NONE -1 -#define IQ_AUTH 0 -#define IQ_ROSTER 1 - -#define UC_AWAY (0x02 | UC_UNAVAILABLE) -#define UC_CHAT 0x04 -#define UC_XA (0x08 | UC_UNAVAILABLE) -#define UC_DND (0x10 | UC_UNAVAILABLE) - -#define DEFAULT_SERVER "jabber.org" -#define DEFAULT_GROUPCHAT "conference.jabber.org" -#define DEFAULT_PORT 5222 -#define DEFAULT_PORT_SSL 5223 -#define JABBER_PORT_MIN 5220 -#define JABBER_PORT_MAX 5229 - -#define JABBER_GROUP "Friends" - -/* i18n disabled - Bitlbee */ -#define N_(String) String - -/* - * Note: "was_connected" may seem redundant, but it was needed and I - * didn't want to touch the Jabber state stuff not specific to Gaim. - */ -typedef struct gjconn_struct { - /* Core structure */ - pool p; /* Memory allocation pool */ - int state; /* Connection state flag */ - int was_connected; /* We were once connected */ - int fd; /* Connection file descriptor */ - void *ssl; /* SSL connection */ - jid user; /* User info */ - char *pass; /* User passwd */ - - /* Stream stuff */ - int id; /* id counter for jab_getid() function */ - char idbuf[9]; /* temporary storage for jab_getid() */ - char *sid; /* stream id from server, for digest auth */ - XML_Parser parser; /* Parser instance */ - xmlnode current; /* Current node in parsing instance.. */ - - /* Event callback ptrs */ - void (*on_state)(struct gjconn_struct *gjc, int state); - void (*on_packet)(struct gjconn_struct *gjc, jpacket p); - - GHashTable *queries; /* query tracker */ - - void *priv; -} *gjconn, gjconn_struct; - -typedef void (*gjconn_state_h)(gjconn gjc, int state); -typedef void (*gjconn_packet_h)(gjconn gjc, jpacket p); - -static gjconn gjab_new(char *user, char *pass, void *priv); -static void gjab_delete(gjconn gjc); -static void gjab_state_handler(gjconn gjc, gjconn_state_h h); -static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h); -static void gjab_start(gjconn gjc); -static void gjab_stop(gjconn gjc); -/* -static int gjab_getfd(gjconn gjc); -static jid gjab_getjid(gjconn gjc); -static char *gjab_getsid(gjconn gjc); -*/ -static char *gjab_getid(gjconn gjc); -static void gjab_send(gjconn gjc, xmlnode x); -static void gjab_send_raw(gjconn gjc, const char *str); -static void gjab_recv(gjconn gjc); -static void gjab_auth(gjconn gjc); - -/* - * It is *this* to which we point the gaim_connection proto_data - */ -struct jabber_data { - gjconn gjc; - gboolean did_import; - GSList *chats; - GHashTable *hash; - time_t idle; - gboolean die; -}; - -/* - * Jabber "chat group" info. Pointers to these go in jabber_data - * pending and existing chats lists. - */ -struct jabber_chat { - jid Jid; - struct gaim_connection *gc; - struct conversation *b; - int id; - int state; -}; - -/* - * Jabber chat states... - * - * Note: due to a bug in one version of the Jabber server, subscriptions - * to chat groups aren't (always?) properly removed at the server. The - * result is clients receive Jabber "presence" notifications for JIDs - * they no longer care about. The problem with such vestigial notifies is - * that we really have no way of telling if it's vestigial or if it's a - * valid "buddy" presence notification. So we keep jabber_chat structs - * around after leaving a chat group and simply mark them "closed." That - * way we can test for such errant presence notifications. I.e.: if we - * get a presence notfication from a JID that matches a chat group JID, - * we disregard it. - */ -#define JCS_PENDING 1 /* pending */ -#define JCS_ACTIVE 2 /* active */ -#define JCS_CLOSED 3 /* closed */ - - -#define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); } - -static void jabber_remove_buddy(struct gaim_connection *gc, char *name, char *group); -static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from); - -static char *create_valid_jid(const char *given, char *server, char *resource) -{ - char *valid; - - if (!strchr(given, '@')) - valid = g_strdup_printf("%s@%s/%s", given, server, resource); - else if (!strchr(strchr(given, '@'), '/')) - valid = g_strdup_printf("%s/%s", given, resource); - else - valid = g_strdup(given); - - return valid; -} - -static gjconn gjab_new(char *user, char *pass, void *priv) -{ - pool p; - gjconn gjc; - - if (!user) - return (NULL); - - p = pool_new(); - if (!p) - return (NULL); - gjc = pmalloc_x(p, sizeof(gjconn_struct), 0); - if (!gjc) { - pool_free(p); /* no need for this anymore! */ - return (NULL); - } - gjc->p = p; - - if((gjc->user = jid_new(p, user)) == NULL) { - pool_free(p); /* no need for this anymore! */ - return (NULL); - } - gjc->pass = pstrdup(p, pass); - - gjc->state = JCONN_STATE_OFF; - gjc->was_connected = 0; - gjc->id = 1; - gjc->fd = -1; - - gjc->priv = priv; - - return gjc; -} - -static void gjab_delete(gjconn gjc) -{ - if (!gjc) - return; - - gjab_stop(gjc); - pool_free(gjc->p); -} - -static void gjab_state_handler(gjconn gjc, gjconn_state_h h) -{ - if (!gjc) - return; - - gjc->on_state = h; -} - -static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h) -{ - if (!gjc) - return; - - gjc->on_packet = h; -} - -static void gjab_stop(gjconn gjc) -{ - if (!gjc || gjc->state == JCONN_STATE_OFF) - return; - - gjab_send_raw(gjc, ""); - gjc->state = JCONN_STATE_OFF; - gjc->was_connected = 0; - if (gjc->ssl) { - ssl_disconnect(gjc->ssl); - gjc->ssl = NULL; - } else { - closesocket(gjc->fd); - } - gjc->fd = -1; - XML_ParserFree(gjc->parser); - gjc->parser = NULL; -} - -/* -static int gjab_getfd(gjconn gjc) -{ - if (gjc) - return gjc->fd; - else - return -1; -} - -static jid gjab_getjid(gjconn gjc) -{ - if (gjc) - return (gjc->user); - else - return NULL; -} - -static char *gjab_getsid(gjconn gjc) -{ - if (gjc) - return (gjc->sid); - else - return NULL; -} -*/ - -static char *gjab_getid(gjconn gjc) -{ - g_snprintf(gjc->idbuf, 8, "%d", gjc->id++); - return &gjc->idbuf[0]; -} - -static void gjab_send(gjconn gjc, xmlnode x) -{ - if (gjc && gjc->state != JCONN_STATE_OFF) { - char *buf = xmlnode2str(x); - if (!buf) - return; - else if (gjc->ssl) - ssl_write(gjc->ssl, buf, strlen(buf)); - else - write(gjc->fd, buf, strlen(buf)); - } -} - -static void gjab_send_raw(gjconn gjc, const char *str) -{ - if (gjc && gjc->state != JCONN_STATE_OFF) { - int len; - - /* - * JFIXME: No error detection?!?! - */ - if (gjc->ssl) - len = ssl_write(gjc->ssl, str, strlen(str)); - else - len = write(gjc->fd, str, strlen(str)); - - if(len < 0) { - /* Do NOT write to stdout/stderr directly, IRC clients - might get confused, and we don't want that... - fprintf(stderr, "DBG: Problem sending. Error: %d\n", errno); - fflush(stderr); */ - } - } -} - -static void gjab_reqroster(gjconn gjc) -{ - xmlnode x; - - x = jutil_iqnew(JPACKET__GET, NS_ROSTER); - xmlnode_put_attrib(x, "id", gjab_getid(gjc)); - - gjab_send(gjc, x); - xmlnode_free(x); -} - -static void gjab_reqauth(gjconn gjc) -{ - xmlnode x, y, z; - char *user; - - if (!gjc) - return; - - x = jutil_iqnew(JPACKET__GET, NS_AUTH); - xmlnode_put_attrib(x, "id", IQID_AUTH); - y = xmlnode_get_tag(x, "query"); - - user = gjc->user->user; - - if (user) { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - gjab_send(gjc, x); - xmlnode_free(x); -} - -static void gjab_auth(gjconn gjc) -{ - xmlnode x, y, z; - char *hash, *user; - - if (!gjc) - return; - - x = jutil_iqnew(JPACKET__SET, NS_AUTH); - xmlnode_put_attrib(x, "id", IQID_AUTH); - y = xmlnode_get_tag(x, "query"); - - user = gjc->user->user; - - if (user) { - z = xmlnode_insert_tag(y, "username"); - xmlnode_insert_cdata(z, user, -1); - } - - z = xmlnode_insert_tag(y, "resource"); - xmlnode_insert_cdata(z, gjc->user->resource, -1); - - if (gjc->sid) { - z = xmlnode_insert_tag(y, "digest"); - hash = pmalloc(x->p, strlen(gjc->sid) + strlen(gjc->pass) + 1); - strcpy(hash, gjc->sid); - strcat(hash, gjc->pass); - hash = shahash(hash); - xmlnode_insert_cdata(z, hash, 40); - } else { - z = xmlnode_insert_tag(y, "password"); - xmlnode_insert_cdata(z, gjc->pass, -1); - } - - gjab_send(gjc, x); - xmlnode_free(x); - - return; -} - -static void gjab_recv(gjconn gjc) -{ - static char buf[4096]; - int len; - - if (!gjc || gjc->state == JCONN_STATE_OFF) - return; - - if (gjc->ssl) - len = ssl_read(gjc->ssl, buf, sizeof(buf) - 1); - else - len = read(gjc->fd, buf, sizeof(buf) - 1); - - if (len > 0) { - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - buf[len] = '\0'; - XML_Parse(gjc->parser, buf, len, 0); - if (jd->die) - signoff(GJ_GC(gjc)); - } else if (len == 0 || (len < 0 && (!sockerr_again() || gjc->ssl))) { - STATE_EVT(JCONN_STATE_OFF) - } -} - -static void startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - gjconn gjc = (gjconn) userdata; - - if (gjc->current) { - /* Append the node to the current one */ - x = xmlnode_insert_tag(gjc->current, name); - xmlnode_put_expat_attribs(x, attribs); - - gjc->current = x; - } else { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - if (strcmp(name, "stream:stream") == 0) { - /* special case: name == stream:stream */ - /* id attrib of stream is stored for digest auth */ - gjc->sid = g_strdup(xmlnode_get_attrib(x, "id")); - /* STATE_EVT(JCONN_STATE_AUTH) */ - xmlnode_free(x); - } else { - gjc->current = x; - } - } -} - -static void endElement(void *userdata, const char *name) -{ - gjconn gjc = (gjconn) userdata; - xmlnode x; - jpacket p; - - if (gjc->current == NULL) { - /* we got */ - STATE_EVT(JCONN_STATE_OFF) - return; - } - - x = xmlnode_get_parent(gjc->current); - - if (!x) { - /* it is time to fire the event */ - p = jpacket_new(gjc->current); - - if (gjc->on_packet) - (gjc->on_packet) (gjc, p); - else - xmlnode_free(gjc->current); - } - - gjc->current = x; -} - -static gboolean jabber_callback(gpointer data, gint source, b_input_condition condition) -{ - struct gaim_connection *gc = (struct gaim_connection *)data; - struct jabber_data *jd = (struct jabber_data *)gc->proto_data; - - gjab_recv(jd->gjc); - - return TRUE; -} - -static void charData(void *userdata, const char *s, int slen) -{ - gjconn gjc = (gjconn) userdata; - - if (gjc->current) - xmlnode_insert_cdata(gjc->current, s, slen); -} - -static gboolean gjab_connected(gpointer data, gint source, b_input_condition cond) -{ - xmlnode x; - char *t, *t2; - struct gaim_connection *gc = data; - struct jabber_data *jd; - gjconn gjc; - - if (!g_slist_find(get_connections(), gc)) { - closesocket(source); - return FALSE; - } - - jd = gc->proto_data; - gjc = jd->gjc; - - if (gjc->fd != source) - gjc->fd = source; - - if (source == -1) { - STATE_EVT(JCONN_STATE_OFF) - return FALSE; - } - - gjc->state = JCONN_STATE_CONNECTED; - STATE_EVT(JCONN_STATE_CONNECTED) - - /* start stream */ - x = jutil_header(NS_CLIENT, gjc->user->server); - t = xmlnode2str(x); - /* this is ugly, we can create the string here instead of jutil_header */ - /* what do you think about it? -madcat */ - t2 = strstr(t, "/>"); - *t2++ = '>'; - *t2 = '\0'; - gjab_send_raw(gjc, ""); - gjab_send_raw(gjc, t); - xmlnode_free(x); - - gjc->state = JCONN_STATE_ON; - STATE_EVT(JCONN_STATE_ON); - - gc = GJ_GC(gjc); - gc->inpa = b_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); - - return FALSE; -} - -static gboolean gjab_connected_ssl(gpointer data, void *source, b_input_condition cond) -{ - struct gaim_connection *gc = data; - struct jabber_data *jd; - gjconn gjc; - - jd = gc->proto_data; - gjc = jd->gjc; - - if (source == NULL) { - STATE_EVT(JCONN_STATE_OFF) - return FALSE; - } - - if (!g_slist_find(get_connections(), gc)) { - ssl_disconnect(source); - return FALSE; - } - - return gjab_connected(data, gjc->fd, cond); -} - -static void gjab_start(gjconn gjc) -{ - account_t *acc; - int port = -1, ssl = 0; - char *server = NULL; - - if (!gjc || gjc->state != JCONN_STATE_OFF) - return; - - acc = GJ_GC(gjc)->acc; - server = acc->server; - port = set_getint(&acc->set, "port"); - ssl = set_getbool(&acc->set, "ssl"); - - if (port < JABBER_PORT_MIN || port > JABBER_PORT_MAX) { - serv_got_crap(GJ_GC(gjc), "For security reasons, the Jabber port number must be in the %d-%d range.", JABBER_PORT_MIN, JABBER_PORT_MAX); - STATE_EVT(JCONN_STATE_OFF) - return; - } - - if (server == NULL) - server = g_strdup(gjc->user->server); - - gjc->parser = XML_ParserCreate(NULL); - XML_SetUserData(gjc->parser, (void *)gjc); - XML_SetElementHandler(gjc->parser, startElement, endElement); - XML_SetCharacterDataHandler(gjc->parser, charData); - - if (ssl) { - if ((gjc->ssl = ssl_connect(server, port, gjab_connected_ssl, GJ_GC(gjc)))) - gjc->fd = ssl_getfd(gjc->ssl); - else - gjc->fd = -1; - } else { - gjc->fd = proxy_connect(server, port, gjab_connected, GJ_GC(gjc)); - } - - if (!acc->gc || (gjc->fd < 0)) { - STATE_EVT(JCONN_STATE_OFF) - return; - } -} - -/* - * Find existing/active Jabber chat - */ -static struct jabber_chat *find_existing_chat(struct gaim_connection *gc, jid chat) -{ - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc = NULL; - - while (jcs) { - jc = jcs->data; - if (jc->state == JCS_ACTIVE && !jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER)) - break; - jc = NULL; - jcs = jcs->next; - } - - return jc; -} - -/* - * Find pending chat - */ -static struct jabber_chat *find_pending_chat(struct gaim_connection *gc, jid chat) -{ - GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; - struct jabber_chat *jc = NULL; - - while (jcs) { - jc = jcs->data; - if (jc->state == JCS_PENDING && !jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER)) - break; - jc = NULL; - jcs = jcs->next; - } - - return jc; -} - -static gboolean find_chat_buddy(struct conversation *b, char *name) -{ - GList *m = b->in_room; - - while (m) { - if (!strcmp(m->data, name)) - return TRUE; - m = m->next; - } - - return FALSE; -} - -/* - * Remove a buddy from the (gaim) buddylist (if he's on it) - */ -static void jabber_remove_gaim_buddy(struct gaim_connection *gc, char *buddyname) -{ - struct buddy *b; - - if ((b = find_buddy(gc, buddyname)) != NULL) { - /* struct group *group; - - group = find_group_by_buddy(gc, buddyname); - remove_buddy(gc, group, b); */ - jabber_remove_buddy(gc, b->name, JABBER_GROUP); - } -} - -/* - * keep track of away msg same as yahoo plugin - */ -static void jabber_track_away(gjconn gjc, jpacket p, char *name, char *type) -{ - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - gpointer val = g_hash_table_lookup(jd->hash, name); - char *show; - char *vshow = NULL; - char *status = NULL; - char *msg = NULL; - - if (type && (g_strcasecmp(type, "unavailable") == 0)) { - vshow = _("Unavailable"); - } else { - if((show = xmlnode_get_tag_data(p->x, "show")) != NULL) { - if (!g_strcasecmp(show, "away")) { - vshow = _("Away"); - } else if (!g_strcasecmp(show, "chat")) { - vshow = _("Online"); - } else if (!g_strcasecmp(show, "xa")) { - vshow = _("Extended Away"); - } else if (!g_strcasecmp(show, "dnd")) { - vshow = _("Do Not Disturb"); - } - } - } - - status = xmlnode_get_tag_data(p->x, "status"); - - if(vshow != NULL || status != NULL ) { - /* kinda hokey, but it works :-) */ - msg = g_strdup_printf("%s%s%s", - (vshow == NULL? "" : vshow), - (vshow == NULL || status == NULL? "" : ": "), - (status == NULL? "" : status)); - } else { - msg = g_strdup(_("Online")); - } - - if (val) { - g_free(val); - g_hash_table_insert(jd->hash, name, msg); - } else { - g_hash_table_insert(jd->hash, g_strdup(name), msg); - } -} - -static time_t iso8601_to_time(char *timestamp) -{ - struct tm t; - time_t retval = 0; - - if(sscanf(timestamp,"%04d%02d%02dT%02d:%02d:%02d", - &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec)) - { - t.tm_year -= 1900; - t.tm_mon -= 1; - t.tm_isdst = 0; - retval = mktime(&t); -# ifdef HAVE_TM_GMTOFF - retval += t.tm_gmtoff; -# else -# ifdef HAVE_TIMEZONE - tzset(); /* making sure */ - retval -= timezone; -# endif -# endif - } - - return retval; -} - -static void jabber_handlemessage(gjconn gjc, jpacket p) -{ - xmlnode y, xmlns, z; - time_t time_sent = time(NULL); - - char *from = NULL, *msg = NULL, *type = NULL; - char m[BUF_LONG * 2]; - - type = xmlnode_get_attrib(p->x, "type"); - - z = xmlnode_get_firstchild(p->x); - - while(z) - { - if(NSCHECK(z,NS_DELAY)) - { - char *timestamp = xmlnode_get_attrib(z,"stamp"); - time_sent = iso8601_to_time(timestamp); - } - z = xmlnode_get_nextsibling(z); - } - - if (!type || !g_strcasecmp(type, "normal") || !g_strcasecmp(type, "chat")) { - - /* XXX namespaces could be handled better. (mid) */ - if ((xmlns = xmlnode_get_tag(p->x, "x"))) - type = xmlnode_get_attrib(xmlns, "xmlns"); - - from = jid_full(p->from); - /* - if ((y = xmlnode_get_tag(p->x, "html"))) { - msg = xmlnode_get_data(y); - } else - */ - if ((y = xmlnode_get_tag(p->x, "body"))) { - msg = xmlnode_get_data(y); - } - - - if (!from) - return; - - if (type && !g_strcasecmp(type, "jabber:x:conference")) { - /* do nothing */ - } else if (msg) { /* whisper */ - struct jabber_chat *jc; - g_snprintf(m, sizeof(m), "%s", msg); - if (((jc = find_existing_chat(GJ_GC(gjc), p->from)) != NULL) && jc->b) - serv_got_chat_in(GJ_GC(gjc), jc->b->id, p->from->resource, 1, m, time_sent); - else { - int flags = 0; - - if(p->from->user) { - from = g_strdup_printf("%s@%s", p->from->user, p->from->server); - } else { - /* server message? */ - from = g_strdup(p->from->server); - } - serv_got_im(GJ_GC(gjc), from, m, flags, time_sent, -1); - g_free(from); - } - } - - } else if (!g_strcasecmp(type, "error")) { - if ((y = xmlnode_get_tag(p->x, "error"))) { - type = xmlnode_get_attrib(y, "code"); - msg = xmlnode_get_data(y); - } - - if (msg) { - from = g_strdup_printf("Error %s", type ? type : ""); - do_error_dialog(GJ_GC(gjc), msg, from); - g_free(from); - } - } else if (!g_strcasecmp(type, "headline")) { - char *subject, *body, *url; - - y = xmlnode_get_tag( p->x, "body" ); - body = y ? g_strdup( xmlnode_get_data( y ) ) : NULL; - - y = xmlnode_get_tag( p->x, "subject" ); - subject = y ? g_strdup( xmlnode_get_data( y ) ) : NULL; - - url = NULL; - z = xmlnode_get_firstchild(p->x); - while( z ) - { - char *xtype = xmlnode_get_attrib( z, "xmlns" ); - - if( xtype && g_strcasecmp( xtype, "jabber:x:oob" ) == 0 && - ( y = xmlnode_get_tag( z, "url" ) ) ) - { - url = g_strdup( xmlnode_get_data( y ) ); - break; - } - - z = xmlnode_get_nextsibling( z ); - } - - g_snprintf( m, BUF_LONG, "Subject: %s\nURL: %s\nMessage:\n%s", subject ? subject : "(none)", - url ? url : "(none)", body ? body : "(none)" ); - - if( p->from->user ) - from = g_strdup_printf( "%s@%s", p->from->user, p->from->server ); - else - from = g_strdup( p->from->server ); - - serv_got_im( GJ_GC(gjc), from, m, 0, time_sent, -1 ); - - g_free( from ); - g_free( subject ); - g_free( body ); - g_free( url ); - } -} - -static void jabber_handlepresence(gjconn gjc, jpacket p) -{ - char *to, *from, *type; - struct buddy *b = NULL; - jid who; - char *buddy; - xmlnode y; - char *show; - int state = 0; - GSList *resources; - char *res; - struct conversation *cnv = NULL; - struct jabber_chat *jc = NULL; - - to = xmlnode_get_attrib(p->x, "to"); - from = xmlnode_get_attrib(p->x, "from"); - type = xmlnode_get_attrib(p->x, "type"); - - if (type && g_strcasecmp(type, "error") == 0) { - return; - } - else if ((y = xmlnode_get_tag(p->x, "show"))) { - show = xmlnode_get_data(y); - if (!show) { - state = 0; - } else if (!g_strcasecmp(show, "away")) { - state = UC_AWAY; - } else if (!g_strcasecmp(show, "chat")) { - state = UC_CHAT; - } else if (!g_strcasecmp(show, "xa")) { - state = UC_XA; - } else if (!g_strcasecmp(show, "dnd")) { - state = UC_DND; - } - } else { - state = 0; - } - - who = jid_new(gjc->p, from); - if (who->user == NULL) { - /* FIXME: transport */ - return; - } - - buddy = g_strdup_printf("%s@%s", who->user, who->server); - - /* um. we're going to check if it's a chat. if it isn't, and there are pending - * chats, create the chat. if there aren't pending chats and we don't have the - * buddy on our list, simply bail out. */ - if ((cnv = NULL) == NULL) { - static int i = 0x70; - if ((jc = find_pending_chat(GJ_GC(gjc), who)) != NULL) { - jc->b = cnv = serv_got_joined_chat(GJ_GC(gjc), i++, who->user); - jc->id = jc->b->id; - jc->state = JCS_ACTIVE; - } else if ((b = find_buddy(GJ_GC(gjc), buddy)) == NULL) { - g_free(buddy); - return; - } - } - - if (!cnv) { - resources = b->proto_data; - res = who->resource; - if (res) - while (resources) { - if (!strcmp(res, resources->data)) - break; - resources = resources->next; - } - - /* keep track of away msg same as yahoo plugin */ - jabber_track_away(gjc, p, normalize(b->name), type); - - if (type && (g_strcasecmp(type, "unavailable") == 0)) { - if (resources) { - g_free(resources->data); - b->proto_data = g_slist_remove(b->proto_data, resources->data); - } - if (!b->proto_data) { - serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0, 0); - } - } else { - if (!resources) { - b->proto_data = g_slist_append(b->proto_data, g_strdup(res)); - } - - serv_got_update(GJ_GC(gjc), buddy, 1, 0, b->signon, b->idle, state, 0); - - } - } else { - if (who->resource) { - char *buf; - - buf = g_strdup_printf("%s@%s/%s", who->user, who->server, who->resource); - jabber_track_away(gjc, p, buf, type); - g_free(buf); - - if (type && !g_strcasecmp(type, "unavailable")) { - struct jabber_data *jd; - if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), who))) { - g_free(buddy); - return; - } - jd = jc->gc->proto_data; - /* if it's not ourselves...*/ - if (strcmp(who->resource, jc->Jid->resource) && jc->b) { - remove_chat_buddy(jc->b, who->resource, NULL); - g_free(buddy); - return; - } - - jc->state = JCS_CLOSED; - serv_got_chat_left(GJ_GC(gjc), jc->id); - /* - * TBD: put back some day? - jd->chats = g_slist_remove(jd->chats, jc); - g_free(jc); - */ - } else { - if ((!jc && !(jc = find_existing_chat(GJ_GC(gjc), who))) || !jc->b) { - g_free(buddy); - return; - } - if (!find_chat_buddy(jc->b, who->resource)) { - add_chat_buddy(jc->b, who->resource); - } - } - } - } - - g_free(buddy); - - return; -} - -/* - * Used only by Jabber accept/deny add stuff just below - */ -struct jabber_add_permit { - gjconn gjc; - gchar *user; -}; - -/* - * Common part for Jabber accept/deny adds - * - * "type" says whether we'll permit/deny the subscribe request - */ -static void jabber_accept_deny_add(struct jabber_add_permit *jap, const char *type) -{ - xmlnode g = xmlnode_new_tag("presence"); - - xmlnode_put_attrib(g, "to", jap->user); - xmlnode_put_attrib(g, "type", type); - gjab_send(jap->gjc, g); - - xmlnode_free(g); -} - -/* - * Callback from "accept" in do_ask_dialog() invoked by jabber_handles10n() - */ -static void jabber_accept_add(gpointer w, struct jabber_add_permit *jap) -{ - jabber_accept_deny_add(jap, "subscribed"); - /* - * If we don't already have the buddy on *our* buddylist, - * ask if we want him or her added. - */ - if(find_buddy(GJ_GC(jap->gjc), jap->user) == NULL) { - show_got_added(GJ_GC(jap->gjc), jap->user, NULL); - } - g_free(jap->user); - g_free(jap); -} - -/* - * Callback from "deny/cancel" in do_ask_dialog() invoked by jabber_handles10n() - */ -static void jabber_deny_add(gpointer w, struct jabber_add_permit *jap) -{ - jabber_accept_deny_add(jap, "unsubscribed"); - g_free(jap->user); - g_free(jap); -} - -/* - * Handle subscription requests - */ -static void jabber_handles10n(gjconn gjc, jpacket p) -{ - xmlnode g; - char *Jid = xmlnode_get_attrib(p->x, "from"); - char *type = xmlnode_get_attrib(p->x, "type"); - - g = xmlnode_new_tag("presence"); - xmlnode_put_attrib(g, "to", Jid); - - if (!strcmp(type, "subscribe")) { - /* - * A "subscribe to us" request was received - put up the approval dialog - */ - struct jabber_add_permit *jap = g_new0(struct jabber_add_permit, 1); - gchar *msg = g_strdup_printf(_("The user %s wants to add you to his/her buddy list."), - Jid); - - jap->gjc = gjc; - jap->user = g_strdup(Jid); - do_ask_dialog(GJ_GC(gjc), msg, jap, jabber_accept_add, jabber_deny_add); - - g_free(msg); - xmlnode_free(g); /* Never needed it here anyway */ - return; - - } else if (!strcmp(type, "unsubscribe")) { - /* - * An "unsubscribe to us" was received - simply "approve" it - */ - xmlnode_put_attrib(g, "type", "unsubscribed"); - } else { - /* - * Did we attempt to subscribe to somebody and they do not exist? - */ - if (!strcmp(type, "unsubscribed")) { - xmlnode y; - char *status; - if((y = xmlnode_get_tag(p->x, "status")) && (status = xmlnode_get_data(y)) && - !strcmp(status, "Not Found")) { - char *msg = g_strdup_printf("%s: \"%s\"", _("No such user"), - xmlnode_get_attrib(p->x, "from")); - do_error_dialog(GJ_GC(gjc), msg, _("Jabber Error")); - g_free(msg); - } - } - - xmlnode_free(g); - return; - } - - gjab_send(gjc, g); - xmlnode_free(g); -} - -/* - * Pending subscription to a buddy? - */ -#define BUD_SUB_TO_PEND(sub, ask) ((!g_strcasecmp((sub), "none") || !g_strcasecmp((sub), "from")) && \ - (ask) != NULL && !g_strcasecmp((ask), "subscribe")) - -/* - * Subscribed to a buddy? - */ -#define BUD_SUBD_TO(sub, ask) ((!g_strcasecmp((sub), "to") || !g_strcasecmp((sub), "both")) && \ - ((ask) == NULL || !g_strcasecmp((ask), "subscribe"))) - -/* - * Pending unsubscription to a buddy? - */ -#define BUD_USUB_TO_PEND(sub, ask) ((!g_strcasecmp((sub), "to") || !g_strcasecmp((sub), "both")) && \ - (ask) != NULL && !g_strcasecmp((ask), "unsubscribe")) - -/* - * Unsubscribed to a buddy? - */ -#define BUD_USUBD_TO(sub, ask) ((!g_strcasecmp((sub), "none") || !g_strcasecmp((sub), "from")) && \ - ((ask) == NULL || !g_strcasecmp((ask), "unsubscribe"))) - -/* - * If a buddy is added or removed from the roster on another resource - * jabber_handlebuddy is called - * - * Called with roster item node. - */ -static void jabber_handlebuddy(gjconn gjc, xmlnode x) -{ - xmlnode g; - char *Jid, *name, *sub, *ask; - jid who; - struct buddy *b = NULL; - char *buddyname, *groupname = NULL; - - Jid = xmlnode_get_attrib(x, "jid"); - name = xmlnode_get_attrib(x, "name"); - sub = xmlnode_get_attrib(x, "subscription"); - ask = xmlnode_get_attrib(x, "ask"); - who = jid_new(gjc->p, Jid); - - /* JFIXME: jabber_handleroster() had a "FIXME: transport" at this - * equivilent point. So... - * - * We haven't allocated any memory or done anything interesting to - * this point, so we'll violate Good Coding Structure here by - * simply bailing out. - */ - if (!who || !who->user) { - return; - } - - buddyname = g_strdup_printf("%s@%s", who->user, who->server); - - if((g = xmlnode_get_tag(x, "group")) != NULL) { - groupname = xmlnode_get_data(g); - } - - /* - * Add or remove a buddy? Change buddy's alias or group? - */ - if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) { - if ((b = find_buddy(GJ_GC(gjc), buddyname)) == NULL) { - add_buddy(GJ_GC(gjc), groupname ? groupname : _("Buddies"), buddyname, - name ? name : buddyname); - } else { - /* struct group *c_grp = find_group_by_buddy(GJ_GC(gjc), buddyname); */ - - /* - * If the buddy's in a new group or his/her alias is changed... - */ - if(groupname) { - int present = b->present; /* save presence state */ - int uc = b->uc; /* and away state (?) */ - int idle = b->idle; - int signon = b->signon; - - /* - * seems rude, but it seems to be the only way... - */ - /* remove_buddy(GJ_GC(gjc), c_grp, b); */ - jabber_remove_buddy(GJ_GC(gjc), b->name, JABBER_GROUP); - - add_buddy(GJ_GC(gjc), groupname, buddyname, - name ? name : buddyname); - if(present) { - serv_got_update(GJ_GC(gjc), buddyname, 1, 0, signon, idle, uc, 0); - } - } else if(name != NULL && strcmp(b->show, name)) { - strncpy(b->show, name, BUDDY_ALIAS_MAXLEN); - b->show[BUDDY_ALIAS_MAXLEN - 1] = '\0'; /* cheap safety feature */ - serv_buddy_rename(GJ_GC(gjc), buddyname, b->show); - } - } - } else if (BUD_USUB_TO_PEND(sub, ask) || BUD_USUBD_TO(sub, ask) || !g_strcasecmp(sub, "remove")) { - jabber_remove_gaim_buddy(GJ_GC(gjc), buddyname); - } - g_free(buddyname); - -} - -static void jabber_handleroster(gjconn gjc, xmlnode querynode) -{ - xmlnode x; - - x = xmlnode_get_firstchild(querynode); - while (x) { - jabber_handlebuddy(gjc, x); - x = xmlnode_get_nextsibling(x); - } - - account_online(GJ_GC(gjc)); -} - -static void jabber_handleauthresp(gjconn gjc, jpacket p) -{ - if (jpacket_subtype(p) == JPACKET__RESULT) { - if (xmlnode_has_children(p->x)) { - xmlnode query = xmlnode_get_tag(p->x, "query"); - set_login_progress(GJ_GC(gjc), 4, _("Authenticating")); - if (!xmlnode_get_tag(query, "digest")) { - g_free(gjc->sid); - gjc->sid = NULL; - } - gjab_auth(gjc); - } else { - gjab_reqroster(gjc); - - ((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE; - } - } else { - xmlnode xerr; - char *errmsg = NULL; - int errcode = 0; - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - - xerr = xmlnode_get_tag(p->x, "error"); - if (xerr) { - char msg[BUF_LONG]; - errmsg = xmlnode_get_data(xerr); - if (xmlnode_get_attrib(xerr, "code")) { - errcode = atoi(xmlnode_get_attrib(xerr, "code")); - g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg ? errmsg : "Unknown error"); - } else - g_snprintf(msg, sizeof(msg), "%s", errmsg); - hide_login_progress(GJ_GC(gjc), msg); - } else { - hide_login_progress(GJ_GC(gjc), _("Unknown login error")); - } - - jd->die = TRUE; - } -} - -static void jabber_handleversion(gjconn gjc, xmlnode iqnode) { - xmlnode querynode, x; - char *id, *from; - char os[1024]; -#ifndef _WIN32 - struct utsname osinfo; - - uname(&osinfo); - g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); -#else - g_snprintf(os, sizeof os, "Windows %d %d", _winmajor, _winminor); -#endif - - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querynode = xmlnode_get_tag(x, "query"); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), BITLBEE_VERSION, -1); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1); - - gjab_send(gjc, x); - - xmlnode_free(x); -} - -static void jabber_handletime(gjconn gjc, xmlnode iqnode) { - xmlnode querynode, x; - char *id, *from; - time_t now_t; - struct tm *now; - char buf[1024]; - - time(&now_t); - now = localtime(&now_t); - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, NS_TIME); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querynode = xmlnode_get_tag(x, "query"); - - strftime(buf, 1024, "%Y%m%dT%T", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1); - strftime(buf, 1024, "%Z", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1); - strftime(buf, 1024, "%d %b %Y %T", now); - xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1); - - gjab_send(gjc, x); - - xmlnode_free(x); -} - -static void jabber_handlelast(gjconn gjc, xmlnode iqnode) { - xmlnode x, querytag; - char *id, *from; - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - char idle_time[32]; - - id = xmlnode_get_attrib(iqnode, "id"); - from = xmlnode_get_attrib(iqnode, "from"); - - x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); - - xmlnode_put_attrib(x, "to", from); - xmlnode_put_attrib(x, "id", id); - querytag = xmlnode_get_tag(x, "query"); - g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0); - xmlnode_put_attrib(querytag, "seconds", idle_time); - - gjab_send(gjc, x); - xmlnode_free(x); -} - -/* - * delete == TRUE: delete found entry - * - * returns pointer to (local) copy of value if found, NULL otherwise - * - * Note: non-reentrant! Local static storage re-used on subsequent calls. - * If you're going to need to keep the returned value, make a copy! - */ -static gchar *jabber_track_queries(GHashTable *queries, gchar *key, gboolean delete) -{ - gpointer my_key, my_val; - static gchar *ret_val = NULL; - - if(ret_val != NULL) { - g_free(ret_val); - ret_val = NULL; - } - - /* self-protection */ - if(queries != NULL && key != NULL) { - if(g_hash_table_lookup_extended(queries, key, &my_key, &my_val)) { - ret_val = g_strdup((gchar *) my_val); - if(delete) { - g_hash_table_remove(queries, key); - g_free(my_key); - g_free(my_val); - } - } - } - - return(ret_val); -} - -static void jabber_handlepacket(gjconn gjc, jpacket p) -{ - char *id; - switch (p->type) { - case JPACKET_MESSAGE: - jabber_handlemessage(gjc, p); - break; - case JPACKET_PRESENCE: - jabber_handlepresence(gjc, p); - break; - case JPACKET_IQ: - id = xmlnode_get_attrib(p->x, "id"); - if (id != NULL && !strcmp(id, IQID_AUTH)) { - jabber_handleauthresp(gjc, p); - break; - } - - if (jpacket_subtype(p) == JPACKET__SET) { - xmlnode querynode; - querynode = xmlnode_get_tag(p->x, "query"); - if (NSCHECK(querynode, "jabber:iq:roster")) { - jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode)); - } - } else if (jpacket_subtype(p) == JPACKET__GET) { - xmlnode querynode; - querynode = xmlnode_get_tag(p->x, "query"); - if (NSCHECK(querynode, NS_VERSION)) { - jabber_handleversion(gjc, p->x); - } else if (NSCHECK(querynode, NS_TIME)) { - jabber_handletime(gjc, p->x); - } else if (NSCHECK(querynode, "jabber:iq:last")) { - jabber_handlelast(gjc, p->x); - } - } else if (jpacket_subtype(p) == JPACKET__RESULT) { - xmlnode querynode, vcard; - /* char *xmlns; */ - char *from; - - /* - * TBD: ISTM maybe this part could use a serious re-work? - */ - from = xmlnode_get_attrib(p->x, "from"); - querynode = xmlnode_get_tag(p->x, "query"); - vcard = xmlnode_get_tag(p->x, "vCard"); - if (!vcard) - vcard = xmlnode_get_tag(p->x, "VCARD"); - - if (NSCHECK(querynode, NS_ROSTER)) { - jabber_handleroster(gjc, querynode); - } else if (NSCHECK(querynode, NS_VCARD)) { - jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ - jabber_handlevcard(gjc, querynode, from); - } else if (vcard) { - jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ - jabber_handlevcard(gjc, vcard, from); - } else { - char *val; - - /* handle "null" query results */ - if((val = jabber_track_queries(gjc->queries, id, TRUE)) != NULL) { - if (!g_strncasecmp(val, "vcard", 5)) { - jabber_handlevcard(gjc, NULL, from); - } - - /* No-op */ - } - } - - } else if (jpacket_subtype(p) == JPACKET__ERROR) { - xmlnode xerr; - char *from, *errmsg = NULL; - int errcode = 0; - - from = xmlnode_get_attrib(p->x, "from"); - xerr = xmlnode_get_tag(p->x, "error"); - if (xerr) { - errmsg = xmlnode_get_data(xerr); - if (xmlnode_get_attrib(xerr, "code")) - errcode = atoi(xmlnode_get_attrib(xerr, "code")); - } - - from = g_strdup_printf("Error %d (%s)", errcode, from); - do_error_dialog(GJ_GC(gjc), errmsg, from); - g_free(from); - - } - - break; - case JPACKET_S10N: - jabber_handles10n(gjc, p); - break; - } - - xmlnode_free(p->x); - - return; -} - -static void jabber_handlestate(gjconn gjc, int state) -{ - switch (state) { - case JCONN_STATE_OFF: - if(gjc->was_connected) { - hide_login_progress_error(GJ_GC(gjc), _("Connection lost")); - } else { - hide_login_progress(GJ_GC(gjc), _("Unable to connect")); - } - signoff(GJ_GC(gjc)); - break; - case JCONN_STATE_CONNECTED: - gjc->was_connected = 1; - set_login_progress(GJ_GC(gjc), 2, _("Connected")); - break; - case JCONN_STATE_ON: - set_login_progress(GJ_GC(gjc), 3, _("Requesting Authentication Method")); - gjab_reqauth(gjc); - break; - } - return; -} - -static void jabber_acc_init(account_t *acc) -{ - set_t *s; - - s = set_add( &acc->set, "port", "5222", set_eval_int, acc ); - s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); - s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); - s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); - s->flags |= ACC_SET_OFFLINE_ONLY; -} - -static void jabber_login(account_t *acc) -{ - struct gaim_connection *gc; - struct jabber_data *jd; - char *resource, *loginname; - - /* Time to move some data/things from the old syntax to the new one: */ - if (acc->server) { - char *s, *tmp_server; - int port; - - if (g_strcasecmp(acc->server, "ssl") == 0) { - set_setstr(&acc->set, "server", ""); - set_setint(&acc->set, "port", DEFAULT_PORT_SSL); - set_setstr(&acc->set, "ssl", "true"); - - g_free(acc->server); - acc->server = NULL; - } else if ((s = strchr(acc->server, ':'))) { - if (strstr(acc->server, ":ssl")) { - set_setint(&acc->set, "port", DEFAULT_PORT_SSL); - set_setstr(&acc->set, "ssl", "true"); - } - if (isdigit(s[1])) { - if (sscanf(s + 1, "%d", &port) == 1) - set_setint(&acc->set, "port", port); - } - tmp_server = g_strndup(acc->server, s - acc->server); - set_setstr(&acc->set, "server", tmp_server); - g_free(tmp_server); - } - } - - gc = new_gaim_conn(acc); - jd = gc->proto_data = g_new0(struct jabber_data, 1); - - if( strchr( acc->user, '@' ) == NULL ) - { - hide_login_progress( gc, "Invalid account name" ); - signoff( gc ); - return; - } - - resource = set_getstr(&acc->set, "resource"); - loginname = create_valid_jid(acc->user, DEFAULT_SERVER, resource); - - jd->hash = g_hash_table_new(g_str_hash, g_str_equal); - jd->chats = NULL; /* we have no chats yet */ - - set_login_progress(gc, 1, _("Connecting")); - - if (!(jd->gjc = gjab_new(loginname, acc->pass, gc))) { - g_free(loginname); - hide_login_progress(gc, _("Unable to connect")); - signoff(gc); - return; - } - - g_free(loginname); - gjab_state_handler(jd->gjc, jabber_handlestate); - gjab_packet_handler(jd->gjc, jabber_handlepacket); - jd->gjc->queries = g_hash_table_new(g_str_hash, g_str_equal); - gjab_start(jd->gjc); -} - -static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { - g_free(key); - g_free(val); - return TRUE; -} - -static gboolean jabber_free(gpointer data, gint fd, b_input_condition cond) -{ - struct jabber_data *jd = data; - - if(jd->gjc != NULL) { - gjab_delete(jd->gjc); - /* YAY for modules with their own memory pool managers!... - g_free(jd->gjc->sid); - And a less sarcastic yay for valgrind. :-) */ - jd->gjc = NULL; - } - g_free(jd); - - return FALSE; -} - -static void jabber_close(struct gaim_connection *gc) -{ - struct jabber_data *jd = gc->proto_data; - - if(jd) { - GSList *jcs = jd->chats; - - /* Free-up the jabber_chat struct allocs and the list */ - while (jcs) { - g_free(jcs->data); - jcs = jcs->next; - } - g_slist_free(jd->chats); - - /* Free-up the away status memories and the list */ - if(jd->hash != NULL) { - g_hash_table_foreach_remove(jd->hash, jabber_destroy_hash, NULL); - g_hash_table_destroy(jd->hash); - jd->hash = NULL; - } - - /* Free-up the pending queries memories and the list */ - if(jd->gjc != NULL && jd->gjc->queries != NULL) { - g_hash_table_foreach_remove(jd->gjc->queries, jabber_destroy_hash, NULL); - g_hash_table_destroy(jd->gjc->queries); - jd->gjc->queries = NULL; - } - } - if (gc->inpa) - b_event_remove(gc->inpa); - - if(jd) { - b_timeout_add(50, jabber_free, jd); - if(jd->gjc != NULL) - xmlnode_free(jd->gjc->current); - } - gc->proto_data = NULL; -} - -static int jabber_send_im(struct gaim_connection *gc, char *who, char *message, int len, int flags) -{ - xmlnode x, y; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if (!who || !message) - return 0; - - x = xmlnode_new_tag("message"); - /* Bare username and "username" not the server itself? */ - if (!strchr(who, '@') && strcmp(who, gjc->user->server) != 0) - realwho = g_strdup_printf("%s@%s", who, gjc->user->server); - else - realwho = g_strdup(who); - xmlnode_put_attrib(x, "to", realwho); - g_free(realwho); - - xmlnode_insert_tag(x, "bitlbee"); - xmlnode_put_attrib(x, "type", "chat"); - - if (message && strlen(message)) { - y = xmlnode_insert_tag(x, "body"); - xmlnode_insert_cdata(y, message, -1); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - return 1; -} - -/* - * Add/update buddy's roster entry on server - */ -static void jabber_roster_update(struct gaim_connection *gc, char *name) -{ - xmlnode x, y; - char *realwho; - gjconn gjc; - struct buddy *buddy = NULL; - /* struct group *buddy_group = NULL; */ - - if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) { - gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if (!strchr(name, '@')) - realwho = g_strdup_printf("%s@%s", name, gjc->user->server); - else { - jid who = jid_new(gjc->p, name); - if (who->user == NULL) { - /* FIXME: transport */ - return; - } - realwho = g_strdup_printf("%s@%s", who->user, who->server); - } - - - x = jutil_iqnew(JPACKET__SET, NS_ROSTER); - y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); - xmlnode_put_attrib(y, "jid", realwho); - - - /* If we can find the buddy, there's an alias for him, it's not 0-length - * and it doesn't match his JID, add the "name" attribute. - */ - if((buddy = find_buddy(gc, realwho)) != NULL && - buddy->show != NULL && buddy->show[0] != '\0' && strcmp(realwho, buddy->show)) { - - xmlnode_put_attrib(y, "name", buddy->show); - } - - /* - * Find out what group the buddy's in and send that along - * with the roster item. - */ - /* ** Bitlbee disabled ** - if((buddy_group = NULL) != NULL) { - xmlnode z; - z = xmlnode_insert_tag(y, "group"); - xmlnode_insert_cdata(z, buddy_group->name, -1); - } - ** End - Bitlbee ** */ - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - - xmlnode_free(x); - g_free(realwho); - } -} - -/* - * Change buddy's group on server roster - */ -static void jabber_group_change(struct gaim_connection *gc, char *name, char *old_group, char *new_group) -{ - if(strcmp(old_group, new_group)) { - jabber_roster_update(gc, name); - } -} - -static void jabber_add_buddy(struct gaim_connection *gc, char *name) -{ - xmlnode x; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if (!((struct jabber_data *)gc->proto_data)->did_import) - return; - - if (!name) - return; - - if (!strcmp(gc->username, name)) - return; - - if (!strchr(name, '@')) - realwho = g_strdup_printf("%s@%s", name, gjc->user->server); - else { - jid who; - - if((who = jid_new(gjc->p, name)) == NULL) { - char *msg = g_strdup_printf("%s: \"%s\"", _("Invalid Jabber I.D."), name); - do_error_dialog(GJ_GC(gjc), msg, _("Jabber Error")); - g_free(msg); - jabber_remove_gaim_buddy(gc, name); - return; - } - if (who->user == NULL) { - /* FIXME: transport */ - return; - } - realwho = g_strdup_printf("%s@%s", who->user, who->server); - } - - x = xmlnode_new_tag("presence"); - xmlnode_put_attrib(x, "to", realwho); - xmlnode_put_attrib(x, "type", "subscribe"); - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - - jabber_roster_update(gc, realwho); - - g_free(realwho); -} - -static void jabber_remove_buddy(struct gaim_connection *gc, char *name, char *group) -{ - xmlnode x; - char *realwho; - gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; - - if (!name) - return; - - if (!strchr(name, '@')) - realwho = g_strdup_printf("%s@%s", name, gjc->user->server); - else - realwho = g_strdup(name); - - x = xmlnode_new_tag("presence"); - xmlnode_put_attrib(x, "to", realwho); - xmlnode_put_attrib(x, "type", "unsubscribe"); - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - g_free(realwho); - xmlnode_free(x); -} - -static void jabber_get_info(struct gaim_connection *gc, char *who) { - xmlnode x; - char *id; - char *realwho; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - - x = jutil_iqnew(JPACKET__GET, NS_VCARD); - /* Bare username? */ - if (!strchr(who, '@')) { - realwho = g_strdup_printf("%s@%s", who, gjc->user->server); - } else { - realwho = g_strdup(who); - } - xmlnode_put_attrib(x, "to", realwho); - g_free(realwho); - - id = gjab_getid(gjc); - xmlnode_put_attrib(x, "id", id); - - g_hash_table_insert(jd->gjc->queries, g_strdup(id), g_strdup("vCard")); - - gjab_send(gjc, x); - - xmlnode_free(x); - -} - -static void jabber_get_away_msg(struct gaim_connection *gc, char *who) { - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - char *status; - - /* space for all elements: Jabber I.D. + "status" + NULL (list terminator) */ - gchar **str_arr = (gchar **) g_new(gpointer, 3); - gchar **ap = str_arr; - gchar *realwho, *final; - - /* Bare username? */ - if (!strchr(who, '@')) { - realwho = g_strdup_printf("%s@%s", who, gjc->user->server); - } else { - realwho = g_strdup(who); - } - *ap++ = g_strdup_printf("Jabber ID: %s
\n", realwho); - - if((status = g_hash_table_lookup(jd->hash, realwho)) == NULL) { - status = _("Unknown"); - } - *ap++ = g_strdup_printf("Status: %s
\n", status); - - *ap = NULL; - - final= g_strjoinv(NULL, str_arr); - g_strfreev(str_arr); - - g_free(realwho); - g_free(final); - -} - -static GList *jabber_away_states(struct gaim_connection *gc) { - GList *m = NULL; - - m = g_list_append(m, "Online"); - m = g_list_append(m, "Chatty"); - m = g_list_append(m, "Away"); - m = g_list_append(m, "Extended Away"); - m = g_list_append(m, "Do Not Disturb"); - - return m; -} - -static void jabber_set_away(struct gaim_connection *gc, char *state, char *message) -{ - xmlnode x, y; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - - gc->away = NULL; /* never send an auto-response */ - - x = xmlnode_new_tag("presence"); - - if (!strcmp(state, GAIM_AWAY_CUSTOM)) { - /* oh goody. Gaim is telling us what to do. */ - if (message) { - /* Gaim wants us to be away */ - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "away", -1); - y = xmlnode_insert_tag(x, "status"); - xmlnode_insert_cdata(y, message, -1); - gc->away = ""; - } else { - /* Gaim wants us to not be away */ - /* but for Jabber, we can just send presence with no other information. */ - } - } else { - /* state is one of our own strings. it won't be NULL. */ - if (!g_strcasecmp(state, "Online")) { - /* once again, we don't have to put anything here */ - } else if (!g_strcasecmp(state, "Chatty")) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "chat", -1); - } else if (!g_strcasecmp(state, "Away")) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "away", -1); - gc->away = ""; - } else if (!g_strcasecmp(state, "Extended Away")) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "xa", -1); - gc->away = ""; - } else if (!g_strcasecmp(state, "Do Not Disturb")) { - y = xmlnode_insert_tag(x, "show"); - xmlnode_insert_cdata(y, "dnd", -1); - gc->away = ""; - } - } - - gjab_send(gjc, x); - xmlnode_free(x); -} - -static void jabber_keepalive(struct gaim_connection *gc) { - struct jabber_data *jd = (struct jabber_data *)gc->proto_data; - gjab_send_raw(jd->gjc, " \t "); -} - -/*---------------------------------------*/ -/* Jabber "set info" (vCard) support */ -/*---------------------------------------*/ - -/* - * V-Card format: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * <ROLE/> - * <DESC/> - * <BDAY/> - * </vCard> - * - * See also: - * - * http://docs.jabber.org/proto/html/vcard-temp.html - * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd - */ - -/* - * Cross-reference user-friendly V-Card entry labels to vCard XML tags - * and attributes. - * - * Order is (or should be) unimportant. For example: we have no way of - * knowing in what order real data will arrive. - * - * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag - * name, XML tag's parent tag "path" (relative to vCard node). - * - * List is terminated by a NULL label pointer. - * - * Entries with no label text, but with XML tag and parent tag - * entries, are used by V-Card XML construction routines to - * "automagically" construct the appropriate XML node tree. - * - * Thoughts on future direction/expansion - * - * This is a "simple" vCard. - * - * It is possible for nodes other than the "vCard" node to have - * attributes. Should that prove necessary/desirable, add an - * "attributes" pointer to the vcard_template struct, create the - * necessary tag_attr structs, and add 'em to the vcard_dflt_data - * array. - * - * The above changes will (obviously) require changes to the vCard - * construction routines. - */ - -static struct vcard_template { - char *label; /* label text pointer */ - char *text; /* entry text pointer */ - int visible; /* should entry field be "visible?" */ - int editable; /* should entry field be editable? */ - char *tag; /* tag text */ - char *ptag; /* parent tag "path" text */ - char *url; /* vCard display format if URL */ -} vcard_template_data[] = { - {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, - {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, - {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, - {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, - {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, - {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, - {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, - {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, - {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, - {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, - {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, - {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, - {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, - {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, - {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, - {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, - {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, - {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, - {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, - {"", NULL, TRUE, TRUE, "N", NULL, NULL}, - {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, - {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, - {NULL, NULL, 0, 0, NULL, NULL, NULL} -}; - -/* - * Used by routines to parse an XML-encoded string into an xmlnode tree - */ -typedef struct { - XML_Parser parser; - xmlnode current; -} *xmlstr2xmlnode_parser, xmlstr2xmlnode_parser_struct; - - -/* - * Used by XML_Parse on parsing CDATA - */ -static void xmlstr2xmlnode_charData(void *userdata, const char *s, int slen) -{ - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - - if (xmlp->current) - xmlnode_insert_cdata(xmlp->current, s, slen); -} - -/* - * Used by XML_Parse to start or append to an xmlnode - */ -static void xmlstr2xmlnode_startElement(void *userdata, const char *name, const char **attribs) -{ - xmlnode x; - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - - if (xmlp->current) { - /* Append the node to the current one */ - x = xmlnode_insert_tag(xmlp->current, name); - xmlnode_put_expat_attribs(x, attribs); - - xmlp->current = x; - } else { - x = xmlnode_new_tag(name); - xmlnode_put_expat_attribs(x, attribs); - xmlp->current = x; - } -} - -/* - * Used by XML_Parse to end an xmlnode - */ -static void xmlstr2xmlnode_endElement(void *userdata, const char *name) -{ - xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; - xmlnode x; - - if (xmlp->current != NULL && (x = xmlnode_get_parent(xmlp->current)) != NULL) { - xmlp->current = x; - } -} - -/* - * Parse an XML-encoded string into an xmlnode tree - * - * Caller is responsible for freeing the returned xmlnode - */ -static xmlnode xmlstr2xmlnode(char *xmlstring) -{ - xmlstr2xmlnode_parser my_parser = g_new(xmlstr2xmlnode_parser_struct, 1); - xmlnode x = NULL; - - my_parser->parser = XML_ParserCreate(NULL); - my_parser->current = NULL; - - XML_SetUserData(my_parser->parser, (void *)my_parser); - XML_SetElementHandler(my_parser->parser, xmlstr2xmlnode_startElement, xmlstr2xmlnode_endElement); - XML_SetCharacterDataHandler(my_parser->parser, xmlstr2xmlnode_charData); - XML_Parse(my_parser->parser, xmlstring, strlen(xmlstring), 0); - - x = my_parser->current; - - XML_ParserFree(my_parser->parser); - g_free(my_parser); - - return(x); -} - -/* - * Insert a tag node into an xmlnode tree, recursively inserting parent tag - * nodes as necessary - * - * Returns pointer to inserted node - * - * Note to hackers: this code is designed to be re-entrant (it's recursive--it - * calls itself), so don't put any "static"s in here! - */ -static xmlnode insert_tag_to_parent_tag(xmlnode start, const char *parent_tag, const char *new_tag) -{ - xmlnode x = NULL; - - /* - * If the parent tag wasn't specified, see if we can get it - * from the vCard template struct. - */ - if(parent_tag == NULL) { - struct vcard_template *vc_tp = vcard_template_data; - - while(vc_tp->label != NULL) { - if(strcmp(vc_tp->tag, new_tag) == 0) { - parent_tag = vc_tp->ptag; - break; - } - ++vc_tp; - } - } - - /* - * If we have a parent tag... - */ - if(parent_tag != NULL ) { - /* - * Try to get the parent node for a tag - */ - if((x = xmlnode_get_tag(start, parent_tag)) == NULL) { - /* - * Descend? - */ - char *grand_parent = strcpy(g_malloc(strlen(parent_tag) + 1), parent_tag); - char *parent; - - if((parent = strrchr(grand_parent, '/')) != NULL) { - *(parent++) = '\0'; - x = insert_tag_to_parent_tag(start, grand_parent, parent); - } else { - x = xmlnode_insert_tag(start, grand_parent); - } - g_free(grand_parent); - } else { - /* - * We found *something* to be the parent node. - * Note: may be the "root" node! - */ - xmlnode y; - if((y = xmlnode_get_tag(x, new_tag)) != NULL) { - return(y); - } - } - } - - /* - * insert the new tag into its parent node - */ - return(xmlnode_insert_tag((x == NULL? start : x), new_tag)); -} - -/* - * Send vCard info to Jabber server - */ -static void jabber_set_info(struct gaim_connection *gc, char *info) -{ - xmlnode x, vc_node; - char *id; - struct jabber_data *jd = gc->proto_data; - gjconn gjc = jd->gjc; - - x = xmlnode_new_tag("iq"); - xmlnode_put_attrib(x,"type","set"); - - id = gjab_getid(gjc); - - xmlnode_put_attrib(x, "id", id); - - /* - * Send only if there's actually any *information* to send - */ - if((vc_node = xmlstr2xmlnode(info)) != NULL && xmlnode_get_name(vc_node) != NULL && - g_strncasecmp(xmlnode_get_name(vc_node), "vcard", 5) == 0) { - xmlnode_insert_tag_node(x, vc_node); - gjab_send(gjc, x); - } - - xmlnode_free(x); -} - -/* - * displays a Jabber vCard - */ -static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from) -{ - struct jabber_data *jd = GJ_GC(gjc)->proto_data; - jid who = jid_new(gjc->p, from); - char *status = NULL, *text = NULL; - GString *str = g_string_sized_new(100); - xmlnode child; - - gchar *buddy = NULL; - - if(querynode == NULL) { - serv_got_crap(GJ_GC(gjc), "%s - Received empty info reply from %s", _("User Info"), from); - return; - } - - if(who->resource != NULL && (who->resource)[0] != '\0') { - buddy = g_strdup_printf("%s@%s/%s", who->user, who->server, who->resource); - } else { - buddy = g_strdup_printf("%s@%s", who->user, who->server); - } - - if((status = g_hash_table_lookup(jd->hash, buddy)) == NULL) { - status = _("Unknown"); - } - - g_string_sprintfa(str, "%s: %s - %s: %s", _("Jabber ID"), buddy, _("Status"), - status); - - for(child = querynode->firstchild; child; child = child->next) - { - xmlnode child2; - - if(child->type != NTYPE_TAG) - continue; - - text = xmlnode_get_data(child); - if(text && !strcmp(child->name, "FN")) { - info_string_append(str, "\n", _("Full Name"), text); - } else if (!strcmp(child->name, "N")) { - for (child2 = child->firstchild; child2; child2 = child2->next) { - char *text2 = NULL; - - if (child2->type != NTYPE_TAG) - continue; - - text2 = xmlnode_get_data(child2); - if (text2 && !strcmp(child2->name, "FAMILY")) { - info_string_append(str, "\n", _("Family Name"), text2); - } else if (text2 && !strcmp(child2->name, "GIVEN")) { - info_string_append(str, "\n", _("Given Name"), text2); - } else if (text2 && !strcmp(child2->name, "MIDDLE")) { - info_string_append(str, "\n", _("Middle Name"), text2); - } - } - } else if (text && !strcmp(child->name, "NICKNAME")) { - info_string_append(str, "\n", _("Nickname"), text); - } else if (text && !strcmp(child->name, "BDAY")) { - info_string_append(str, "\n", _("Birthday"), text); - } else if (!strcmp(child->name, "ADR")) { - /* show wich address it is */ - /* Just for the beauty of bitlbee - if (child->firstchild) - g_string_sprintfa(str, "%s:\n", _("Address")); - */ - for(child2 = child->firstchild; child2; child2 = child2->next) { - char *text2 = NULL; - - if(child2->type != NTYPE_TAG) - continue; - - text2 = xmlnode_get_data(child2); - if(text2 && !strcmp(child2->name, "POBOX")) { - info_string_append(str, "\n", - _("P.O. Box"), text2); - } else if(text2 && !strcmp(child2->name, "EXTADR")) { - info_string_append(str, "\n", - _("Extended Address"), text2); - } else if(text2 && !strcmp(child2->name, "STREET")) { - info_string_append(str, "\n", - _("Street Address"), text2); - } else if(text2 && !strcmp(child2->name, "LOCALITY")) { - info_string_append(str, "\n", - _("Locality"), text2); - } else if(text2 && !strcmp(child2->name, "REGION")) { - info_string_append(str, "\n", - _("Region"), text2); - } else if(text2 && !strcmp(child2->name, "PCODE")) { - info_string_append(str, "\n", - _("Postal Code"), text2); - } else if(text2 && (!strcmp(child2->name, "CTRY") - || !strcmp(child2->name, "COUNTRY"))) { - info_string_append(str, "\n", _("Country"), text2); - } - } - } else if(!strcmp(child->name, "TEL")) { - char *number = NULL; - if ((child2 = xmlnode_get_tag(child, "NUMBER"))) { - /* show what kind of number it is */ - number = xmlnode_get_data(child2); - if(number) { - info_string_append(str, "\n", _("Telephone"), number); - } - } else if((number = xmlnode_get_data(child))) { - /* lots of clients (including gaim) do this, - * but it's out of spec */ - info_string_append(str, "\n", _("Telephone"), number); - } - } else if(!strcmp(child->name, "EMAIL")) { - char *userid = NULL; - if((child2 = xmlnode_get_tag(child, "USERID"))) { - /* show what kind of email it is */ - userid = xmlnode_get_data(child2); - if(userid) { - info_string_append(str, "\n", _("Email"), userid); - } - } else if((userid = xmlnode_get_data(child))) { - /* lots of clients (including gaim) do this, - * but it's out of spec */ - info_string_append(str, "\n", _("Email"), userid); - } - } else if(!strcmp(child->name, "ORG")) { - for(child2 = child->firstchild; child2; child2 = child2->next) { - char *text2 = NULL; - - if(child2->type != NTYPE_TAG) - continue; - - text2 = xmlnode_get_data(child2); - if(text2 && !strcmp(child2->name, "ORGNAME")) { - info_string_append(str, "\n", _("Organization Name"), text2); - } else if(text2 && !strcmp(child2->name, "ORGUNIT")) { - info_string_append(str, "\n", _("Organization Unit"), text2); - } - } - } else if(text && !strcmp(child->name, "TITLE")) { - info_string_append(str, "\n", _("Title"), text); - } else if(text && !strcmp(child->name, "ROLE")) { - info_string_append(str, "\n", _("Role"), text); - } else if(text && !strcmp(child->name, "DESC")) { - g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Description"), - text, _("End of Description")); - } - } - - serv_got_crap(GJ_GC(gjc), "%s\n%s", _("User Info"), str->str); - - g_free(buddy); - g_string_free(str, TRUE); -} - -void jabber_init() -{ - struct prpl *ret = g_new0(struct prpl, 1); - - ret->name = "jabber"; - ret->away_states = jabber_away_states; - ret->acc_init = jabber_acc_init; - ret->login = jabber_login; - ret->close = jabber_close; - ret->send_im = jabber_send_im; - ret->set_info = jabber_set_info; - ret->get_info = jabber_get_info; - ret->set_away = jabber_set_away; - ret->get_away = jabber_get_away_msg; - ret->add_buddy = jabber_add_buddy; - ret->remove_buddy = jabber_remove_buddy; - ret->keepalive = jabber_keepalive; - ret->alias_buddy = jabber_roster_update; - ret->group_buddy = jabber_group_change; - ret->handle_cmp = g_strcasecmp; - - register_protocol (ret); -} diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h deleted file mode 100644 index 0b907500..00000000 --- a/protocols/jabber/jabber.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <stdarg.h> -#include <time.h> -#include <ctype.h> -#ifdef _WIN32 -#undef DATADIR -#include "sock.h" -#endif - -#include "lib.h" - - -#ifndef INCL_JABBER_H -#define INCL_JABBER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* --------------------------------------------------------- */ -/* */ -/* JID structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JID_RESOURCE 1 -#define JID_USER 2 -#define JID_SERVER 4 - -typedef struct jid_struct -{ - pool p; - char* resource; - char* user; - char* server; - char* full; - struct jid_struct *next; /* for lists of jids */ -} *jid; - -jid jid_new(pool p, char *idstr); /* Creates a jabber id from the idstr */ -void jid_set(jid id, char *str, int item); /* Individually sets jid components */ -char* jid_full(jid id); /* Builds a string type=user/resource@server from the jid data */ -int jid_cmp(jid a, jid b); /* Compares two jid's, returns 0 for perfect match */ -int jid_cmpx(jid a, jid b, int parts); /* Compares just the parts specified as JID_|JID_ */ -jid jid_append(jid a, jid b); /* Appending b to a (list), no dups */ -xmlnode jid_xres(jid id); /* Returns xmlnode representation of the resource?query=string */ -xmlnode jid_nodescan(jid id, xmlnode x); /* Scans the children of the node for a matching jid attribute */ -jid jid_user(jid a); /* returns the same jid but just of the user@host part */ - - -/* --------------------------------------------------------- */ -/* */ -/* JPacket structures & constants */ -/* */ -/* --------------------------------------------------------- */ -#define JPACKET_UNKNOWN 0x00 -#define JPACKET_MESSAGE 0x01 -#define JPACKET_PRESENCE 0x02 -#define JPACKET_IQ 0x04 -#define JPACKET_S10N 0x08 - -#define JPACKET__UNKNOWN 0 -#define JPACKET__NONE 1 -#define JPACKET__ERROR 2 -#define JPACKET__CHAT 3 -#define JPACKET__GROUPCHAT 4 -#define JPACKET__GET 5 -#define JPACKET__SET 6 -#define JPACKET__RESULT 7 -#define JPACKET__SUBSCRIBE 8 -#define JPACKET__SUBSCRIBED 9 -#define JPACKET__UNSUBSCRIBE 10 -#define JPACKET__UNSUBSCRIBED 11 -#define JPACKET__AVAILABLE 12 -#define JPACKET__UNAVAILABLE 13 -#define JPACKET__PROBE 14 -#define JPACKET__HEADLINE 15 -#define JPACKET__INVISIBLE 16 - -typedef struct jpacket_struct -{ - unsigned char type; - int subtype; - int flag; - void* aux1; - xmlnode x; - jid to; - jid from; - char* iqns; - xmlnode iq; - pool p; -} *jpacket, _jpacket; - -jpacket jpacket_new(xmlnode x); /* Creates a jabber packet from the xmlnode */ -int jpacket_subtype(jpacket p); /* Returns the subtype value (looks at xmlnode for it) */ - - -/* --------------------------------------------------------- */ -/* */ -/* Presence Proxy DB structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct ppdb_struct -{ - jid id; /* entry data */ - int pri; - xmlnode x; - struct ppdb_struct* user; /* linked list for user@server */ - pool p; /* db-level data */ - struct ppdb_struct* next; -} _ppdb, *ppdb; - -ppdb ppdb_insert(ppdb db, jid id, xmlnode x); /* Inserts presence into the proxy */ -xmlnode ppdb_primary(ppdb db, jid id); /* Fetches the matching primary presence for the id */ -void ppdb_free(ppdb db); /* Frees the db and all entries */ -xmlnode ppdb_get(ppdb db, jid id); /* Called successively to return each presence xmlnode */ - /* for the id and children, returns NULL at the end */ - - -/* --------------------------------------------------------- */ -/* */ -/* Simple Jabber Rate limit functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct jlimit_struct -{ - char *key; - int start; - int points; - int maxt, maxp; - pool p; -} *jlimit, _jlimit; - -jlimit jlimit_new(int maxt, int maxp); -void jlimit_free(jlimit r); -int jlimit_check(jlimit r, char *key, int points); - - -/* --------------------------------------------------------- */ -/* */ -/* Error structures & constants */ -/* */ -/* --------------------------------------------------------- */ -typedef struct terror_struct -{ - int code; - char msg[64]; -} terror; - -#define TERROR_BAD (terror){400,"Bad Request"} -#define TERROR_AUTH (terror){401,"Unauthorized"} -#define TERROR_PAY (terror){402,"Payment Required"} -#define TERROR_FORBIDDEN (terror){403,"Forbidden"} -#define TERROR_NOTFOUND (terror){404,"Not Found"} -#define TERROR_NOTALLOWED (terror){405,"Not Allowed"} -#define TERROR_NOTACCEPTABLE (terror){406,"Not Acceptable"} -#define TERROR_REGISTER (terror){407,"Registration Required"} -#define TERROR_REQTIMEOUT (terror){408,"Request Timeout"} -#define TERROR_CONFLICT (terror){409,"Conflict"} - -#define TERROR_INTERNAL (terror){500,"Internal Server Error"} -#define TERROR_NOTIMPL (terror){501,"Not Implemented"} -#define TERROR_EXTERNAL (terror){502,"Remote Server Error"} -#define TERROR_UNAVAIL (terror){503,"Service Unavailable"} -#define TERROR_EXTTIMEOUT (terror){504,"Remote Server Timeout"} -#define TERROR_DISCONNECTED (terror){510,"Disconnected"} - -/* --------------------------------------------------------- */ -/* */ -/* Namespace constants */ -/* */ -/* --------------------------------------------------------- */ -#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0) - -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" -#define NS_AUTH "jabber:iq:auth" -#define NS_REGISTER "jabber:iq:register" -#define NS_ROSTER "jabber:iq:roster" -#define NS_OFFLINE "jabber:x:offline" -#define NS_AGENT "jabber:iq:agent" -#define NS_AGENTS "jabber:iq:agents" -#define NS_DELAY "jabber:x:delay" -#define NS_VERSION "jabber:iq:version" -#define NS_TIME "jabber:iq:time" -#define NS_VCARD "vcard-temp" -#define NS_PRIVATE "jabber:iq:private" -#define NS_SEARCH "jabber:iq:search" -#define NS_OOB "jabber:iq:oob" -#define NS_XOOB "jabber:x:oob" -#define NS_ADMIN "jabber:iq:admin" -#define NS_FILTER "jabber:iq:filter" -#define NS_AUTH_0K "jabber:iq:auth:0k" - - -/* --------------------------------------------------------- */ -/* */ -/* Message Types */ -/* */ -/* --------------------------------------------------------- */ -#define TMSG_NORMAL "normal" -#define TMSG_ERROR "error" -#define TMSG_CHAT "chat" -#define TMSG_GROUPCHAT "groupchat" -#define TMSG_HEADLINE "headline" - - -/* --------------------------------------------------------- */ -/* */ -/* JUtil functions */ -/* */ -/* --------------------------------------------------------- */ -xmlnode jutil_presnew(int type, char *to, char *status); /* Create a skeleton presence packet */ -xmlnode jutil_iqnew(int type, char *ns); /* Create a skeleton iq packet */ -xmlnode jutil_msgnew(char *type, char *to, char *subj, char *body); - /* Create a skeleton message packet */ -xmlnode jutil_header(char* xmlns, char* server); /* Create a skeleton stream packet */ -int jutil_priority(xmlnode x); /* Determine priority of this packet */ -void jutil_tofrom(xmlnode x); /* Swaps to/from fields on a packet */ -xmlnode jutil_iqresult(xmlnode x); /* Generate a skeleton iq/result, given a iq/query */ -char* jutil_timestamp(void); /* Get stringified timestamp */ -void jutil_error(xmlnode x, terror E); /* Append an <error> node to x */ -void jutil_delay(xmlnode msg, char *reason); /* Append a delay packet to msg */ -char* jutil_regkey(char *key, char *seed); /* pass a seed to generate a key, pass the key again to validate (returns it) */ - - -/* --------------------------------------------------------- */ -/* */ -/* JConn structures & functions */ -/* */ -/* --------------------------------------------------------- */ -#define JCONN_STATE_OFF 0 -#define JCONN_STATE_CONNECTED 1 -#define JCONN_STATE_ON 2 -#define JCONN_STATE_AUTH 3 - -typedef struct jconn_struct -{ - /* Core structure */ - pool p; /* Memory allocation pool */ - int state; /* Connection state flag */ - int fd; /* Connection file descriptor */ - jid user; /* User info */ - char *pass; /* User passwd */ - - /* Stream stuff */ - int id; /* id counter for jab_getid() function */ - char idbuf[9]; /* temporary storage for jab_getid() */ - char *sid; /* stream id from server, for digest auth */ - XML_Parser parser; /* Parser instance */ - xmlnode current; /* Current node in parsing instance.. */ - - /* Event callback ptrs */ - void (*on_state)(struct jconn_struct *j, int state); - void (*on_packet)(struct jconn_struct *j, jpacket p); - -} *jconn, jconn_struct; - -typedef void (*jconn_state_h)(jconn j, int state); -typedef void (*jconn_packet_h)(jconn j, jpacket p); - - -jconn jab_new(char *user, char *pass); -void jab_delete(jconn j); -void jab_state_handler(jconn j, jconn_state_h h); -void jab_packet_handler(jconn j, jconn_packet_h h); -void jab_start(jconn j); -void jab_stop(jconn j); - -int jab_getfd(jconn j); -jid jab_getjid(jconn j); -char *jab_getsid(jconn j); -char *jab_getid(jconn j); - -void jab_send(jconn j, xmlnode x); -void jab_send_raw(jconn j, const char *str); -void jab_recv(jconn j); -void jab_poll(jconn j, int timeout); - -char *jab_auth(jconn j); -char *jab_reg(jconn j); - - - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_JABBER_H */ diff --git a/protocols/jabber/jid.c b/protocols/jabber/jid.c deleted file mode 100644 index ed2b9ba1..00000000 --- a/protocols/jabber/jid.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -#include <glib.h> - -static jid jid_safe(jid id) -{ - char *str; - - if(strlen(id->server) == 0 || strlen(id->server) > 255) - return NULL; - - /* lowercase the hostname, make sure it's valid characters */ - for(str = id->server; *str != '\0'; str++) - { - *str = tolower(*str); - if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return NULL; - } - - /* cut off the user */ - if(id->user != NULL && strlen(id->user) > 64) - id->user[64] = '\0'; - - /* check for low and invalid ascii characters in the username */ - if(id->user != NULL) - for(str = id->user; *str != '\0'; str++) - if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return NULL; - - return id; -} - -jid jid_new(pool p, char *idstr) -{ - char *server, *resource, *type, *str; - jid id; - - if(p == NULL || idstr == NULL || strlen(idstr) == 0) - return NULL; - - /* user@server/resource */ - - str = pstrdup(p, idstr); - - id = pmalloco(p,sizeof(struct jid_struct)); - id->p = p; - - resource = strstr(str,"/"); - if(resource != NULL) - { - *resource = '\0'; - ++resource; - if(strlen(resource) > 0) - id->resource = resource; - }else{ - resource = str + strlen(str); /* point to end */ - } - - type = strstr(str,":"); - if(type != NULL && type < resource) - { - *type = '\0'; - ++type; - str = type; /* ignore the type: prefix */ - } - - server = strstr(str,"@"); - if(server == NULL || server > resource) - { /* if there's no @, it's just the server address */ - id->server = str; - }else{ - *server = '\0'; - ++server; - id->server = server; - if(strlen(str) > 0) - id->user = str; - } - - return jid_safe(id); -} - -char *jid_full(jid id) -{ - spool s; - - if(id == NULL) - return NULL; - - /* use cached copy */ - if(id->full != NULL) - return id->full; - - s = spool_new(id->p); - - if(id->user != NULL) - spooler(s, id->user,"@",s); - - spool_add(s, id->server); - - if(id->resource != NULL) - spooler(s, "/",id->resource,s); - - id->full = spool_print(s); - return id->full; -} - -/* local utils */ -static int _jid_nullstrcmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return strcmp(a,b); -} -static int _jid_nullstrcasecmp(char *a, char *b) -{ - if(a == NULL && b == NULL) return 0; - if(a == NULL || b == NULL) return -1; - return g_strcasecmp(a,b); -} - -/* suggested by Anders Qvist <quest@valdez.netg.se> */ -int jid_cmpx(jid a, jid b, int parts) -{ - if(a == NULL || b == NULL) - return -1; - - if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1; - if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1; - if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1; - - return 0; -} diff --git a/protocols/jabber/jpacket.c b/protocols/jabber/jpacket.c deleted file mode 100644 index 9c7ce00d..00000000 --- a/protocols/jabber/jpacket.c +++ /dev/null @@ -1,159 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -static jpacket jpacket_reset(jpacket p); - -jpacket jpacket_new(xmlnode x) -{ - jpacket p; - - if(x == NULL) - return NULL; - - p = pmalloc(xmlnode_pool(x),sizeof(_jpacket)); - p->x = x; - - return jpacket_reset(p); -} - -static jpacket jpacket_reset(jpacket p) -{ - char *val; - xmlnode x; - - x = p->x; - memset(p,0,sizeof(_jpacket)); - p->x = x; - p->p = xmlnode_pool(x); - - if(strncmp(xmlnode_get_name(x),"message",7) == 0) - { - p->type = JPACKET_MESSAGE; - }else if(strncmp(xmlnode_get_name(x),"presence",8) == 0) - { - p->type = JPACKET_PRESENCE; - val = xmlnode_get_attrib(x, "type"); - if(val == NULL) - p->subtype = JPACKET__AVAILABLE; - else if(strcmp(val,"unavailable") == 0) - p->subtype = JPACKET__UNAVAILABLE; - else if(strcmp(val,"probe") == 0) - p->subtype = JPACKET__PROBE; - else if(strcmp(val,"error") == 0) - p->subtype = JPACKET__ERROR; - else if(strcmp(val,"invisible") == 0) - p->subtype = JPACKET__INVISIBLE; - else if(*val == 's' || *val == 'u') - p->type = JPACKET_S10N; - else if(strcmp(val,"available") == 0) - { /* someone is using type='available' which is frowned upon */ - xmlnode_hide_attrib(x,"type"); - p->subtype = JPACKET__AVAILABLE; - }else - p->type = JPACKET_UNKNOWN; - }else if(strncmp(xmlnode_get_name(x),"iq",2) == 0) - { - p->type = JPACKET_IQ; - p->iq = xmlnode_get_tag(x,"?xmlns"); - p->iqns = xmlnode_get_attrib(p->iq,"xmlns"); - } - - /* set up the jids if any, flag packet as unknown if they are unparseable */ - val = xmlnode_get_attrib(x,"to"); - if(val != NULL) - if((p->to = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - val = xmlnode_get_attrib(x,"from"); - if(val != NULL) - if((p->from = jid_new(p->p, val)) == NULL) - p->type = JPACKET_UNKNOWN; - - return p; -} - - -int jpacket_subtype(jpacket p) -{ - char *type; - int ret = p->subtype; - - if(ret != JPACKET__UNKNOWN) - return ret; - - ret = JPACKET__NONE; /* default, when no type attrib is specified */ - type = xmlnode_get_attrib(p->x, "type"); - if(j_strcmp(type,"error") == 0) - ret = JPACKET__ERROR; - else - switch(p->type) - { - case JPACKET_MESSAGE: - if(j_strcmp(type,"chat") == 0) - ret = JPACKET__CHAT; - else if(j_strcmp(type,"groupchat") == 0) - ret = JPACKET__GROUPCHAT; - else if(j_strcmp(type,"headline") == 0) - ret = JPACKET__HEADLINE; - break; - case JPACKET_S10N: - if(j_strcmp(type,"subscribe") == 0) - ret = JPACKET__SUBSCRIBE; - else if(j_strcmp(type,"subscribed") == 0) - ret = JPACKET__SUBSCRIBED; - else if(j_strcmp(type,"unsubscribe") == 0) - ret = JPACKET__UNSUBSCRIBE; - else if(j_strcmp(type,"unsubscribed") == 0) - ret = JPACKET__UNSUBSCRIBED; - break; - case JPACKET_IQ: - if(j_strcmp(type,"get") == 0) - ret = JPACKET__GET; - else if(j_strcmp(type,"set") == 0) - ret = JPACKET__SET; - else if(j_strcmp(type,"result") == 0) - ret = JPACKET__RESULT; - break; - } - - p->subtype = ret; - return ret; -} diff --git a/protocols/jabber/jutil.c b/protocols/jabber/jutil.c deleted file mode 100644 index dd367ac9..00000000 --- a/protocols/jabber/jutil.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -#include <glib.h> -#include "nogaim.h" - -/* util for making presence packets */ -xmlnode jutil_presnew(int type, char *to, char *status) -{ - xmlnode pres; - - pres = xmlnode_new_tag("presence"); - switch(type) - { - case JPACKET__SUBSCRIBE: - xmlnode_put_attrib(pres,"type","subscribe"); - break; - case JPACKET__UNSUBSCRIBE: - xmlnode_put_attrib(pres,"type","unsubscribe"); - break; - case JPACKET__SUBSCRIBED: - xmlnode_put_attrib(pres,"type","subscribed"); - break; - case JPACKET__UNSUBSCRIBED: - xmlnode_put_attrib(pres,"type","unsubscribed"); - break; - case JPACKET__PROBE: - xmlnode_put_attrib(pres,"type","probe"); - break; - case JPACKET__UNAVAILABLE: - xmlnode_put_attrib(pres,"type","unavailable"); - break; - case JPACKET__INVISIBLE: - xmlnode_put_attrib(pres,"type","invisible"); - break; - } - if(to != NULL) - xmlnode_put_attrib(pres,"to",to); - if(status != NULL) - xmlnode_insert_cdata(xmlnode_insert_tag(pres,"status"),status,strlen(status)); - - return pres; -} - -/* util for making IQ packets */ -xmlnode jutil_iqnew(int type, char *ns) -{ - xmlnode iq; - - iq = xmlnode_new_tag("iq"); - switch(type) - { - case JPACKET__GET: - xmlnode_put_attrib(iq,"type","get"); - break; - case JPACKET__SET: - xmlnode_put_attrib(iq,"type","set"); - break; - case JPACKET__RESULT: - xmlnode_put_attrib(iq,"type","result"); - break; - case JPACKET__ERROR: - xmlnode_put_attrib(iq,"type","error"); - break; - } - xmlnode_put_attrib(xmlnode_insert_tag(iq,"query"),"xmlns",ns); - - return iq; -} - -/* util for making stream packets */ -xmlnode jutil_header(char* xmlns, char* server) -{ - xmlnode result; - if ((xmlns == NULL)||(server == NULL)) - return NULL; - result = xmlnode_new_tag("stream:stream"); - xmlnode_put_attrib(result, "xmlns:stream", "http://etherx.jabber.org/streams"); - xmlnode_put_attrib(result, "xmlns", xmlns); - xmlnode_put_attrib(result, "to", server); - - return result; -} diff --git a/protocols/jabber/latin1tab.h b/protocols/jabber/latin1tab.h deleted file mode 100644 index 48609aa8..00000000 --- a/protocols/jabber/latin1tab.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, -/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, -/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, -/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, -/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, -/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, diff --git a/protocols/jabber/lib.h b/protocols/jabber/lib.h deleted file mode 100644 index ce0669e5..00000000 --- a/protocols/jabber/lib.h +++ /dev/null @@ -1,343 +0,0 @@ - -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <stdarg.h> -#include <ctype.h> -#include <time.h> - -#include "xmlparse.h" - -int j_strcmp(const char *a, const char *b); - -/* -** Arrange to use either varargs or stdargs -*/ - -#define MAXSHORTSTR 203 /* max short string length */ -#define QUAD_T unsigned long long - -#if defined(__STDC__) || defined(_WIN32) - -#include <stdarg.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_END va_end(ap) - -#else /* __STDC__ */ - -# include <varargs.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) -# define VA_END va_end(ap) - -#endif /* __STDC__ */ - - -#ifndef INCL_LIB_H -#define INCL_LIB_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* --------------------------------------------------------- */ -/* */ -/* Pool-based memory management routines */ -/* */ -/* --------------------------------------------------------- */ - -#undef POOL_DEBUG -/* - flip these, this should be a prime number for top # of pools debugging -#define POOL_DEBUG 40009 -*/ - -/* pheap - singular allocation of memory */ -struct pheap -{ - void *block; - int size, used; -}; - -/* pool_cleaner - callback type which is associated - with a pool entry; invoked when the pool entry is - free'd */ -typedef void (*pool_cleaner)(void *arg); - -/* pfree - a linked list node which stores an - allocation chunk, plus a callback */ -struct pfree -{ - pool_cleaner f; - void *arg; - struct pheap *heap; - struct pfree *next; -}; - -/* pool - base node for a pool. Maintains a linked list - of pool entries (pfree) */ -typedef struct pool_struct -{ - int size; - struct pfree *cleanup; - struct pheap *heap; -#ifdef POOL_DEBUG - char name[8], zone[32]; - int lsize; -} _pool, *pool; -#define pool_new() _pool_new(ZONE) -#define pool_heap(i) _pool_new_heap(i,ZONE) -#else -} _pool, *pool; -#define pool_heap(i) _pool_new_heap(i,NULL) -#define pool_new() _pool_new(NULL) -#endif - -pool _pool_new(char *zone); /* new pool :) */ -pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */ -void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */ -void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */ -void *pmalloco(pool p, int size); /* YAPW for zeroing the block */ -char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */ -void pool_stat(int full); /* print to stderr the changed pools and reset */ -void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */ -void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */ - - - - -/* --------------------------------------------------------- */ -/* */ -/* Socket helper stuff */ -/* */ -/* --------------------------------------------------------- */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define NETSOCKET_SERVER 0 -#define NETSOCKET_CLIENT 1 -#define NETSOCKET_UDP 2 - -#ifndef WIN32 -int make_netsocket(u_short port, char *host, int type); -struct in_addr *make_addr(char *host); -int set_fd_close_on_exec(int fd, int flag); -#endif - - -/* --------------------------------------------------------- */ -/* */ -/* Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef struct xhn_struct -{ - struct xhn_struct *next; - const char *key; - void *val; -} *xhn, _xhn; - -char *strescape(pool p, char *); - - -/* --------------------------------------------------------- */ -/* */ -/* String pools (spool) functions */ -/* */ -/* --------------------------------------------------------- */ -struct spool_node -{ - char *c; - struct spool_node *next; -}; - -typedef struct spool_struct -{ - pool p; - int len; - struct spool_node *last; - struct spool_node *first; -} *spool; - -spool spool_new(pool p); /* create a string pool */ -void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */ -char *spool_print(spool s); /* return a big string */ -void spool_add(spool s, char *str); /* add a single char to the pool */ - - -/* --------------------------------------------------------- */ -/* */ -/* xmlnodes - Document Object Model */ -/* */ -/* --------------------------------------------------------- */ -#define NTYPE_TAG 0 -#define NTYPE_ATTRIB 1 -#define NTYPE_CDATA 2 - -#define NTYPE_LAST 2 -#define NTYPE_UNDEF -1 - -/* -------------------------------------------------------------------------- - Node structure. Do not use directly! Always use accessor macros - and methods! - -------------------------------------------------------------------------- */ -typedef struct xmlnode_t -{ - char* name; - unsigned short type; - char* data; - int data_sz; - int complete; - pool p; - struct xmlnode_t* parent; - struct xmlnode_t* firstchild; - struct xmlnode_t* lastchild; - struct xmlnode_t* prev; - struct xmlnode_t* next; - struct xmlnode_t* firstattrib; - struct xmlnode_t* lastattrib; -} _xmlnode, *xmlnode; - -/* Node creation routines */ -xmlnode xmlnode_wrap(xmlnode x,const char* wrapper); -xmlnode xmlnode_new_tag(const char* name); -xmlnode xmlnode_new_tag_pool(pool p, const char* name); -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name); -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size); -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node); -xmlnode xmlnode_str(char *str, int len); -xmlnode xmlnode_dup(xmlnode x); /* duplicate x */ -xmlnode xmlnode_dup_pool(pool p, xmlnode x); - -/* Node Memory Pool */ -pool xmlnode_pool(xmlnode node); - -/* Node editing */ -void xmlnode_hide(xmlnode child); -void xmlnode_hide_attrib(xmlnode parent, const char *name); - -/* Node deletion routine, also frees the node pool! */ -void xmlnode_free(xmlnode node); - -/* Locates a child tag by name and returns it */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name); -char* xmlnode_get_tag_data(xmlnode parent, const char* name); - -/* Attribute accessors */ -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value); -char* xmlnode_get_attrib(xmlnode owner, const char* name); -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts); - -/* Bastard am I, but these are fun for internal use ;-) */ -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value); -void* xmlnode_get_vattrib(xmlnode owner, const char* name); - -/* Node traversal routines */ -xmlnode xmlnode_get_firstchild(xmlnode parent); -xmlnode xmlnode_get_lastchild(xmlnode parent); -xmlnode xmlnode_get_nextsibling(xmlnode sibling); -xmlnode xmlnode_get_prevsibling(xmlnode sibling); -xmlnode xmlnode_get_parent(xmlnode node); - -/* Node information routines */ -char* xmlnode_get_name(xmlnode node); -char* xmlnode_get_data(xmlnode node); - -int xmlnode_has_children(xmlnode node); - -/* Node-to-string translation */ -char* xmlnode2str(xmlnode node); - -/********** END OLD libxode.h BEGIN OLD jabber.h *************/ - - -// #define KARMA_DEBUG -// default to disable karma -#define KARMA_READ_MAX(k) (abs(k)*100) /* how much you are allowed to read off the sock */ -#define KARMA_INIT 5 /* internal "init" value */ -#define KARMA_HEARTBEAT 2 /* seconds to register for heartbeat */ -#define KARMA_MAX 10 /* total max karma you can have */ -#define KARMA_INC 1 /* how much to increment every KARMA_HEARTBEAT seconds */ -#define KARMA_DEC 0 /* how much to penalize for reading KARMA_READ_MAX in - KARMA_HEARTBEAT seconds */ -#define KARMA_PENALTY -5 /* where you go when you hit 0 karma */ -#define KARMA_RESTORE 5 /* where you go when you payed your penelty or INIT */ -#define KARMA_RESETMETER 0 /* Reset byte meter on restore default is falst */ - -struct karma -{ - int init; /* struct initialized */ - int reset_meter; /* reset the byte meter on restore */ - int val; /* current karma value */ - long bytes; /* total bytes read (in that time period) */ - int max; /* max karma you can have */ - int inc,dec; /* how much to increment/decrement */ - int penalty,restore; /* what penalty (<0) or restore (>0) */ - time_t last_update; /* time this was last incremented */ -}; - -struct karma *karma_new(pool p); /* creates a new karma object, with default values */ -void karma_copy(struct karma *new, struct karma *old); /* makes a copy of old in new */ -void karma_increment(struct karma *k); /* inteligently increments karma */ -void karma_decrement(struct karma *k, long bytes_read); /* inteligently decrements karma */ -int karma_check(struct karma *k,long bytes_read); /* checks to see if we have good karma */ - - - -/* --------------------------------------------------------- */ -/* */ -/* Namespace constants */ -/* */ -/* --------------------------------------------------------- */ -#define NSCHECK(x,n) (j_strcmp(xmlnode_get_attrib(x,"xmlns"),n) == 0) - -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" -#define NS_AUTH "jabber:iq:auth" -#define NS_REGISTER "jabber:iq:register" -#define NS_ROSTER "jabber:iq:roster" -#define NS_OFFLINE "jabber:x:offline" -#define NS_AGENT "jabber:iq:agent" -#define NS_AGENTS "jabber:iq:agents" -#define NS_DELAY "jabber:x:delay" -#define NS_VERSION "jabber:iq:version" -#define NS_TIME "jabber:iq:time" -#define NS_VCARD "vcard-temp" -#define NS_PRIVATE "jabber:iq:private" -#define NS_SEARCH "jabber:iq:search" -#define NS_OOB "jabber:iq:oob" -#define NS_XOOB "jabber:x:oob" -#define NS_ADMIN "jabber:iq:admin" -#define NS_FILTER "jabber:iq:filter" -#define NS_AUTH_0K "jabber:iq:auth:0k" -#define NS_BROWSE "jabber:iq:browse" -#define NS_EVENT "jabber:x:event" -#define NS_CONFERENCE "jabber:iq:conference" -#define NS_SIGNED "jabber:x:signed" -#define NS_ENCRYPTED "jabber:x:encrypted" -#define NS_GATEWAY "jabber:iq:gateway" -#define NS_LAST "jabber:iq:last" -#define NS_ENVELOPE "jabber:x:envelope" -#define NS_EXPIRE "jabber:x:expire" -#define NS_XHTML "http://www.w3.org/1999/xhtml" - -#define NS_XDBGINSERT "jabber:xdb:ginsert" -#define NS_XDBNSLIST "jabber:xdb:nslist" - - - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_LIB_H */ diff --git a/protocols/jabber/libxode.h b/protocols/jabber/libxode.h deleted file mode 100644 index 2ed3fd83..00000000 --- a/protocols/jabber/libxode.h +++ /dev/null @@ -1,398 +0,0 @@ -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <setjmp.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <syslog.h> -#include <strings.h> -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> - -#ifndef __CYGWIN__ -#include <arpa/nameser.h> -#include <resolv.h> -#endif - -#include <sys/time.h> -#include <time.h> - -#include "xmlparse.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - -/* -** Arrange to use either varargs or stdargs -*/ - -#define MAXSHORTSTR 203 /* max short string length */ -#define QUAD_T unsigned long long - -#ifdef __STDC__ - -#include <stdarg.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_END va_end(ap) - -#else /* __STDC__ */ - -# include <varargs.h> - -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) -# define VA_END va_end(ap) - -#endif /* __STDC__ */ - - -#ifndef INCL_LIBXODE_H -#define INCL_LIBXODE_H - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef HAVE_SNPRINTF -extern int ap_snprintf(char *, size_t, const char *, ...); -#define snprintf ap_snprintf -#endif - -#ifndef HAVE_VSNPRINTF -extern int ap_vsnprintf(char *, size_t, const char *, va_list ap); -#define vsnprintf ap_vsnprintf -#endif - -#define ZONE zonestr(__FILE__,__LINE__) -char *zonestr(char *file, int line); - -/* --------------------------------------------------------- */ -/* */ -/* Pool-based memory management routines */ -/* */ -/* --------------------------------------------------------- */ - -#undef POOL_DEBUG -/* - flip these, this should be a prime number for top # of pools debugging -#define POOL_DEBUG 40009 -*/ - -/* pheap - singular allocation of memory */ -struct pheap -{ - void *block; - int size, used; -}; - -/* pool_cleaner - callback type which is associated - with a pool entry; invoked when the pool entry is - free'd */ -typedef void (*pool_cleaner)(void *arg); - -/* pfree - a linked list node which stores an - allocation chunk, plus a callback */ -struct pfree -{ - pool_cleaner f; - void *arg; - struct pheap *heap; - struct pfree *next; -}; - -/* pool - base node for a pool. Maintains a linked list - of pool entries (pfree) */ -typedef struct pool_struct -{ - int size; - struct pfree *cleanup; - struct pheap *heap; -#ifdef POOL_DEBUG - char name[8], zone[32]; - int lsize; -} _pool, *pool; -#define pool_new() _pool_new(ZONE) -#define pool_heap(i) _pool_new_heap(i,ZONE) -#else -} _pool, *pool; -#define pool_heap(i) _pool_new_heap(i,NULL) -#define pool_new() _pool_new(NULL) -#endif - -pool _pool_new(char *zone); /* new pool :) */ -pool _pool_new_heap(int size, char *zone); /* creates a new memory pool with an initial heap size */ -void *pmalloc(pool p, int size); /* wrapper around malloc, takes from the pool, cleaned up automatically */ -void *pmalloc_x(pool p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */ -void *pmalloco(pool p, int size); /* YAPW for zeroing the block */ -char *pstrdup(pool p, const char *src); /* wrapper around strdup, gains mem from pool */ -void pool_stat(int full); /* print to stderr the changed pools and reset */ -void pool_cleanup(pool p, pool_cleaner f, void *arg); /* calls f(arg) before the pool is freed during cleanup */ -void pool_free(pool p); /* calls the cleanup functions, frees all the data on the pool, and deletes the pool itself */ - - - - -/* --------------------------------------------------------- */ -/* */ -/* Socket helper stuff */ -/* */ -/* --------------------------------------------------------- */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define NETSOCKET_SERVER 0 -#define NETSOCKET_CLIENT 1 -#define NETSOCKET_UDP 2 - -#ifndef WIN32 -int make_netsocket(u_short port, char *host, int type); -struct in_addr *make_addr(char *host); -int set_fd_close_on_exec(int fd, int flag); -#endif - - -/* --------------------------------------------------------- */ -/* */ -/* SHA calculations */ -/* */ -/* --------------------------------------------------------- */ -#if (SIZEOF_INT == 4) -typedef unsigned int uint32; -#elif (SIZEOF_SHORT == 4) -typedef unsigned short uint32; -#else -typedef unsigned int uint32; -#endif /* HAVEUINT32 */ - -int sha_hash(int *data, int *hash); -int sha_init(int *hash); -char *shahash(char *str); /* NOT THREAD SAFE */ -void shahash_r(const char* str, char hashbuf[40]); /* USE ME */ - -int strprintsha(char *dest, int *hashval); - - -/* --------------------------------------------------------- */ -/* */ -/* Hashtable functions */ -/* */ -/* --------------------------------------------------------- */ -typedef int (*KEYHASHFUNC)(const void *key); -typedef int (*KEYCOMPAREFUNC)(const void *key1, const void *key2); -typedef int (*TABLEWALKFUNC)(void *user_data, const void *key, void *data); - -typedef void *HASHTABLE; - -HASHTABLE ghash_create(int buckets, KEYHASHFUNC hash, KEYCOMPAREFUNC cmp); -void ghash_destroy(HASHTABLE tbl); -void *ghash_get(HASHTABLE tbl, const void *key); -int ghash_put(HASHTABLE tbl, const void *key, void *value); -int ghash_remove(HASHTABLE tbl, const void *key); -int ghash_walk(HASHTABLE tbl, TABLEWALKFUNC func, void *user_data); -int str_hash_code(const char *s); - - -/* --------------------------------------------------------- */ -/* */ -/* XML escaping utils */ -/* */ -/* --------------------------------------------------------- */ -char *strescape(pool p, char *buf); /* Escape <>&'" chars */ - - -/* --------------------------------------------------------- */ -/* */ -/* String pools (spool) functions */ -/* */ -/* --------------------------------------------------------- */ -struct spool_node -{ - char *c; - struct spool_node *next; -}; - -typedef struct spool_struct -{ - pool p; - int len; - struct spool_node *last; - struct spool_node *first; -} *spool; - -spool spool_new(pool p); /* create a string pool */ -void spooler(spool s, ...); /* append all the char * args to the pool, terminate args with s again */ -char *spool_print(spool s); /* return a big string */ -void spool_add(spool s, char *str); /* add a single char to the pool */ -char *spools(pool p, ...); /* wrap all the spooler stuff in one function, the happy fun ball! */ - - -/* --------------------------------------------------------- */ -/* */ -/* xmlnodes - Document Object Model */ -/* */ -/* --------------------------------------------------------- */ -#define NTYPE_TAG 0 -#define NTYPE_ATTRIB 1 -#define NTYPE_CDATA 2 - -#define NTYPE_LAST 2 -#define NTYPE_UNDEF -1 - -/* -------------------------------------------------------------------------- - Node structure. Do not use directly! Always use accessor macros - and methods! - -------------------------------------------------------------------------- */ -typedef struct xmlnode_t -{ - char* name; - unsigned short type; - char* data; - int data_sz; - int complete; - pool p; - struct xmlnode_t* parent; - struct xmlnode_t* firstchild; - struct xmlnode_t* lastchild; - struct xmlnode_t* prev; - struct xmlnode_t* next; - struct xmlnode_t* firstattrib; - struct xmlnode_t* lastattrib; -} _xmlnode, *xmlnode; - -/* Node creation routines */ -xmlnode xmlnode_wrap(xmlnode x,const char* wrapper); -xmlnode xmlnode_new_tag(const char* name); -xmlnode xmlnode_new_tag_pool(pool p, const char* name); -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name); -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size); -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node); -void xmlnode_insert_node(xmlnode parent, xmlnode node); -xmlnode xmlnode_str(char *str, int len); -xmlnode xmlnode_file(char *file); -xmlnode xmlnode_dup(xmlnode x); /* duplicate x */ -xmlnode xmlnode_dup_pool(pool p, xmlnode x); - -/* Node Memory Pool */ -pool xmlnode_pool(xmlnode node); -xmlnode _xmlnode_new(pool p, const char *name, unsigned int type); - -/* Node editing */ -void xmlnode_hide(xmlnode child); -void xmlnode_hide_attrib(xmlnode parent, const char *name); - -/* Node deletion routine, also frees the node pool! */ -void xmlnode_free(xmlnode node); - -/* Locates a child tag by name and returns it */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name); -char* xmlnode_get_tag_data(xmlnode parent, const char* name); - -/* Attribute accessors */ -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value); -char* xmlnode_get_attrib(xmlnode owner, const char* name); -void xmlnode_put_expat_attribs(xmlnode owner, const char** atts); - -/* Bastard am I, but these are fun for internal use ;-) */ -void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value); -void* xmlnode_get_vattrib(xmlnode owner, const char* name); - -/* Node traversal routines */ -xmlnode xmlnode_get_firstattrib(xmlnode parent); -xmlnode xmlnode_get_firstchild(xmlnode parent); -xmlnode xmlnode_get_lastchild(xmlnode parent); -xmlnode xmlnode_get_nextsibling(xmlnode sibling); -xmlnode xmlnode_get_prevsibling(xmlnode sibling); -xmlnode xmlnode_get_parent(xmlnode node); - -/* Node information routines */ -char* xmlnode_get_name(xmlnode node); -char* xmlnode_get_data(xmlnode node); -int xmlnode_get_datasz(xmlnode node); -int xmlnode_get_type(xmlnode node); - -int xmlnode_has_children(xmlnode node); -int xmlnode_has_attribs(xmlnode node); - -/* Node-to-string translation */ -char* xmlnode2str(xmlnode node); - -/* Node-to-terminated-string translation - -- useful for interfacing w/ scripting langs */ -char* xmlnode2tstr(xmlnode node); - -int xmlnode_cmp(xmlnode a, xmlnode b); /* compares a and b for equality */ - -int xmlnode2file(char *file, xmlnode node); /* writes node to file */ - -/* Expat callbacks */ -void expat_startElement(void* userdata, const char* name, const char** atts); -void expat_endElement(void* userdata, const char* name); -void expat_charData(void* userdata, const char* s, int len); - -/* SHA.H */ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Header File - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - * Paul Kocher - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -typedef struct { - unsigned long H[5]; - unsigned long W[80]; - int lenW; - unsigned long sizeHi,sizeLo; -} SHA_CTX; - - -void shaInit(SHA_CTX *ctx); -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); - - -/* END SHA.H */ - -#ifdef __cplusplus -} -#endif - -#endif /* INCL_LIBXODE_H */ diff --git a/protocols/jabber/log.c b/protocols/jabber/log.c deleted file mode 100644 index 86d19e1d..00000000 --- a/protocols/jabber/log.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#include "jabber.h" -#include "log.h" - -#ifdef DEBUG - -void jdebug(char *zone, const char *msgfmt, ...) -{ - va_list ap; - static char loghdr[LOGSIZE_HDR]; - static char logmsg[LOGSIZE_TAIL]; - static int size; - - /* XXX: We may want to check the sizes eventually */ - size = g_snprintf(loghdr, LOGSIZE_HDR, "debug/%s %s\n", zone, msgfmt); - - va_start(ap, msgfmt); - size = vsnprintf(logmsg, LOGSIZE_TAIL, loghdr, ap); - - fprintf(stderr,"%s",logmsg); - - return; -} - - -#endif /* DEBUG */ diff --git a/protocols/jabber/log.h b/protocols/jabber/log.h deleted file mode 100644 index 9bce9e12..00000000 --- a/protocols/jabber/log.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU 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. - * - * Jabber - * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ - */ - -#ifndef INCL_LOG_H -#define INCL_LOG_H - -#define LOGSIZE_HDR 1024 -#define LOGSIZE_TAIL 2048 - - -#ifdef DEBUG - void jdebug(char *zone, const char *msgfmt, ...); -#else - #define jdebug if(0) warn -#endif - - - -#endif /* INCL_LOG_H */ - diff --git a/protocols/jabber/nametab.h b/protocols/jabber/nametab.h deleted file mode 100644 index b05e62c7..00000000 --- a/protocols/jabber/nametab.h +++ /dev/null @@ -1,150 +0,0 @@ -static const unsigned namingBitmap[] = { -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, -0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, -0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, -0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, -0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, -0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, -0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, -0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, -0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, -0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, -0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, -0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, -0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, -0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, -0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, -0x40000000, 0xF580C900, 0x00000007, 0x02010800, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, -0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, -0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, -0x00000000, 0x00004C40, 0x00000000, 0x00000000, -0x00000007, 0x00000000, 0x00000000, 0x00000000, -0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, -0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, -0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, -0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, -0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, -0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, -0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, -0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, -0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, -0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, -0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, -0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, -0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, -0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, -0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, -0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, -0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, -0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, -0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, -0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, -0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, -0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, -0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, -0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, -0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, -0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, -0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, -0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, -}; -static const unsigned char nmstrtPages[] = { -0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, -0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const unsigned char namePages[] = { -0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, -0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, -0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff --git a/protocols/jabber/pool.c b/protocols/jabber/pool.c deleted file mode 100644 index 8b88d747..00000000 --- a/protocols/jabber/pool.c +++ /dev/null @@ -1,247 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -#include "bitlbee.h" -#include <glib.h> - - -#ifdef POOL_DEBUG -int pool__total = 0; -int pool__ltotal = 0; -HASHTABLE pool__disturbed = NULL; -void *_pool__malloc(size_t size) -{ - pool__total++; - return g_malloc(size); -} -void _pool__free(void *block) -{ - pool__total--; - g_free(block); -} -#else -#define _pool__malloc g_malloc -#define _pool__free g_free -#endif - - -/* make an empty pool */ -pool _pool_new(char *zone) -{ - pool p; - while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1); - p->cleanup = NULL; - p->heap = NULL; - p->size = 0; - -#ifdef POOL_DEBUG - p->lsize = -1; - p->zone[0] = '\0'; - strcat(p->zone,zone); - sprintf(p->name,"%X",p); - - if(pool__disturbed == NULL) - { - pool__disturbed = 1; /* reentrancy flag! */ - pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp); - } - if(pool__disturbed != 1) - ghash_put(pool__disturbed,p->name,p); -#endif - - return p; -} - -/* free a heap */ -static void _pool_heap_free(void *arg) -{ - struct pheap *h = (struct pheap *)arg; - - _pool__free(h->block); - _pool__free(h); -} - -/* mem should always be freed last */ -static void _pool_cleanup_append(pool p, struct pfree *pf) -{ - struct pfree *cur; - - if(p->cleanup == NULL) - { - p->cleanup = pf; - return; - } - - /* fast forward to end of list */ - for(cur = p->cleanup; cur->next != NULL; cur = cur->next); - - cur->next = pf; -} - -/* create a cleanup tracker */ -static struct pfree *_pool_free(pool p, pool_cleaner f, void *arg) -{ - struct pfree *ret; - - /* make the storage for the tracker */ - while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1); - ret->f = f; - ret->arg = arg; - ret->next = NULL; - - return ret; -} - -/* create a heap and make sure it get's cleaned up */ -static struct pheap *_pool_heap(pool p, int size) -{ - struct pheap *ret; - struct pfree *clean; - - /* make the return heap */ - while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1); - while((ret->block = _pool__malloc(size)) == NULL) sleep(1); - ret->size = size; - p->size += size; - ret->used = 0; - - /* append to the cleanup list */ - clean = _pool_free(p, _pool_heap_free, (void *)ret); - clean->heap = ret; /* for future use in finding used mem for pstrdup */ - _pool_cleanup_append(p, clean); - - return ret; -} - -pool _pool_new_heap(int size, char *zone) -{ - pool p; - p = _pool_new(zone); - p->heap = _pool_heap(p,size); - return p; -} - -void *pmalloc(pool p, int size) -{ - void *block; - - if(p == NULL) - { - fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n"); - abort(); - } - - /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */ - if(p->heap == NULL || size > (p->heap->size / 2)) - { - while((block = _pool__malloc(size)) == NULL) sleep(1); - p->size += size; - _pool_cleanup_append(p, _pool_free(p, _pool__free, block)); - return block; - } - - /* we have to preserve boundaries, long story :) */ - if(size >= 4) - while(p->heap->used&7) p->heap->used++; - - /* if we don't fit in the old heap, replace it */ - if(size > (p->heap->size - p->heap->used)) - p->heap = _pool_heap(p, p->heap->size); - - /* the current heap has room */ - block = (char *)p->heap->block + p->heap->used; - p->heap->used += size; - return block; -} - -void *pmalloc_x(pool p, int size, char c) -{ - void* result = pmalloc(p, size); - if (result != NULL) - memset(result, c, size); - return result; -} - -/* easy safety utility (for creating blank mem for structs, etc) */ -void *pmalloco(pool p, int size) -{ - void *block = pmalloc(p, size); - memset(block, 0, size); - return block; -} - -/* XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is within a block in this pool */ -char *pstrdup(pool p, const char *src) -{ - char *ret; - - if(src == NULL) - return NULL; - - ret = pmalloc(p,strlen(src) + 1); - strcpy(ret,src); - - return ret; -} - -void pool_free(pool p) -{ - struct pfree *cur, *stub; - - if(p == NULL) return; - - cur = p->cleanup; - while(cur != NULL) - { - (*cur->f)(cur->arg); - stub = cur->next; - _pool__free(cur); - cur = stub; - } - -#ifdef POOL_DEBUG - ghash_remove(pool__disturbed,p->name); -#endif - - _pool__free(p); - -} diff --git a/protocols/jabber/str.c b/protocols/jabber/str.c deleted file mode 100644 index a8454b44..00000000 --- a/protocols/jabber/str.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -#include <glib.h> - -static char *j_strcat(char *dest, char *txt) -{ - if(!txt) return(dest); - - while(*txt) - *dest++ = *txt++; - *dest = '\0'; - - return(dest); -} - -int j_strcmp(const char *a, const char *b) -{ - if(a == NULL || b == NULL) - return -1; - - while(*a == *b && *a != '\0' && *b != '\0'){ a++; b++; } - - if(*a == *b) return 0; - - return -1; -} - -spool spool_new(pool p) -{ - spool s; - - s = pmalloc(p, sizeof(struct spool_struct)); - s->p = p; - s->len = 0; - s->last = NULL; - s->first = NULL; - return s; -} - -void spool_add(spool s, char *str) -{ - struct spool_node *sn; - int len; - - if(str == NULL) - return; - - len = strlen(str); - if(len == 0) - return; - - sn = pmalloc(s->p, sizeof(struct spool_node)); - sn->c = pstrdup(s->p, str); - sn->next = NULL; - - s->len += len; - if(s->last != NULL) - s->last->next = sn; - s->last = sn; - if(s->first == NULL) - s->first = sn; -} - -void spooler(spool s, ...) -{ - va_list ap; - char *arg = NULL; - - if(s == NULL) - return; - - VA_START(s); - - /* loop till we hfit our end flag, the first arg */ - while(1) - { - arg = va_arg(ap,char *); - if((spool)arg == s) - break; - else - spool_add(s, arg); - } - - va_end(ap); -} - -char *spool_print(spool s) -{ - char *ret,*tmp; - struct spool_node *next; - - if(s == NULL || s->len == 0 || s->first == NULL) - return NULL; - - ret = pmalloc(s->p, s->len + 1); - *ret = '\0'; - - next = s->first; - tmp = ret; - while(next != NULL) - { - tmp = j_strcat(tmp,next->c); - next = next->next; - } - - return ret; -} - -char *strescape(pool p, char *buf) -{ - int i,j,oldlen,newlen; - char *temp; - - if (p == NULL || buf == NULL) return(NULL); - - oldlen = newlen = strlen(buf); - for(i=0;i<oldlen;i++) - { - switch(buf[i]) - { - case '&': - newlen+=5; - break; - case '\'': - newlen+=6; - break; - case '\"': - newlen+=6; - break; - case '<': - newlen+=4; - break; - case '>': - newlen+=4; - break; - } - } - - if(oldlen == newlen) return buf; - - temp = pmalloc(p,newlen+1); - - if (temp==NULL) return(NULL); - - for(i=j=0;i<oldlen;i++) - { - switch(buf[i]) - { - case '&': - memcpy(&temp[j],"&",5); - j += 5; - break; - case '\'': - memcpy(&temp[j],"'",6); - j += 6; - break; - case '\"': - memcpy(&temp[j],""",6); - j += 6; - break; - case '<': - memcpy(&temp[j],"<",4); - j += 4; - break; - case '>': - memcpy(&temp[j],">",4); - j += 4; - break; - default: - temp[j++] = buf[i]; - } - } - temp[j] = '\0'; - return temp; -} diff --git a/protocols/jabber/utf8tab.h b/protocols/jabber/utf8tab.h deleted file mode 100644 index a38fe624..00000000 --- a/protocols/jabber/utf8tab.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - - -/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, -/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, -/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, -/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, -/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, -/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, diff --git a/protocols/jabber/xmldef.h b/protocols/jabber/xmldef.h deleted file mode 100644 index 8b2b2308..00000000 --- a/protocols/jabber/xmldef.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#include <glib.h> -#include <string.h> -#include <stdlib.h> - diff --git a/protocols/jabber/xmlnode.c b/protocols/jabber/xmlnode.c deleted file mode 100644 index 88dd4eef..00000000 --- a/protocols/jabber/xmlnode.c +++ /dev/null @@ -1,705 +0,0 @@ -/* -------------------------------------------------------------------------- - * - * License - * - * The contents of this file are subject to the Jabber Open Source License - * Version 1.0 (the "JOSL"). You may not copy or use this file, in either - * source code or executable form, except in compliance with the JOSL. You - * may obtain a copy of the JOSL at http://www.jabber.org/ or at - * http://www.opensource.org/. - * - * Software distributed under the JOSL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL - * for the specific language governing rights and limitations under the - * JOSL. - * - * Copyrights - * - * Portions created by or assigned to Jabber.com, Inc. are - * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact - * information for Jabber.com, Inc. is available at http://www.jabber.com/. - * - * Portions Copyright (c) 1998-1999 Jeremie Miller. - * - * Acknowledgements - * - * Special thanks to the Jabber Open Source Contributors for their - * suggestions and support of Jabber. - * - * Alternatively, the contents of this file may be used under the terms of the - * GNU General Public License Version 2 or later (the "GPL"), in which case - * the provisions of the GPL are applicable instead of those above. If you - * wish to allow use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the JOSL, - * indicate your decision by deleting the provisions above and replace them - * with the notice and other provisions required by the GPL. If you do not - * delete the provisions above, a recipient may use your version of this file - * under either the JOSL or the GPL. - * - * - * --------------------------------------------------------------------------*/ - -#include "jabber.h" -#include <glib.h> - -static xmlnode xmlnode_get_firstattrib(xmlnode parent); -static int xmlnode_get_type(xmlnode node); -static void xmlnode_insert_node(xmlnode parent, xmlnode node); - -/* Internal routines */ -static xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) -{ - xmlnode result = NULL; - if (type > NTYPE_LAST) - return NULL; - - if (type != NTYPE_CDATA && name == NULL) - return NULL; - - if (p == NULL) - { - p = pool_heap(1*1024); - } - - /* Allocate & zero memory */ - result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); - - /* Initialize fields */ - if (type != NTYPE_CDATA) - result->name = pstrdup(p,name); - result->type = type; - result->p = p; - return result; -} - -static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type) -{ - xmlnode result; - - result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); - if (result != NULL) - { - /* Setup sibling pointers */ - result->prev = lastsibling; - lastsibling->next = result; - } - return result; -} - -static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) -{ - xmlnode result; - - if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL; - - /* If parent->firstchild is NULL, simply create a new node for the first child */ - if (parent->firstchild == NULL) - { - result = _xmlnode_new(parent->p, name, type); - parent->firstchild = result; - } - /* Otherwise, append this to the lastchild */ - else - { - result= _xmlnode_append_sibling(parent->lastchild, name, type); - } - result->parent = parent; - parent->lastchild = result; - return result; - -} - -static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) -{ - xmlnode current; - - /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with - the specified name */ - current = firstsibling; - while (current != NULL) - { - if ((current->type == type) && (j_strcmp(current->name, name) == 0)) - return current; - else - current = current->next; - } - return NULL; -} - -static void _xmlnode_merge(xmlnode data) -{ - xmlnode cur; - char *merge, *scur; - int imerge; - - /* get total size of all merged cdata */ - imerge = 0; - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - imerge += cur->data_sz; - - /* copy in current data and then spin through all of them and merge */ - scur = merge = pmalloc(data->p,imerge + 1); - for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) - { - memcpy(scur,cur->data,cur->data_sz); - scur += cur->data_sz; - } - *scur = '\0'; - - /* this effectively hides all of the merged-in chunks */ - data->next = cur; - if(cur == NULL) - data->parent->lastchild = data; - else - cur->prev = data; - - /* reset data */ - data->data = merge; - data->data_sz = imerge; - -} - -static void _xmlnode_hide_sibling(xmlnode child) -{ - if(child == NULL) - return; - - if(child->prev != NULL) - child->prev->next = child->next; - if(child->next != NULL) - child->next->prev = child->prev; -} - -static void _xmlnode_tag2str(spool s, xmlnode node, int flag) -{ - xmlnode tmp; - - if(flag==0 || flag==1) - { - spooler(s,"<",xmlnode_get_name(node),s); - tmp = xmlnode_get_firstattrib(node); - while(tmp) { - spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); - tmp = xmlnode_get_nextsibling(tmp); - } - if(flag==0) - spool_add(s,"/>"); - else - spool_add(s,">"); - } - else - { - spooler(s,"</",xmlnode_get_name(node),">",s); - } -} - -static spool _xmlnode2spool(xmlnode node) -{ - spool s; - int level=0,dir=0; - xmlnode tmp; - - if(!node || xmlnode_get_type(node)!=NTYPE_TAG) - return NULL; - - s = spool_new(xmlnode_pool(node)); - if(!s) return(NULL); - - while(1) - { - if(dir==0) - { - if(xmlnode_get_type(node) == NTYPE_TAG) - { - if(xmlnode_has_children(node)) - { - _xmlnode_tag2str(s,node,1); - node = xmlnode_get_firstchild(node); - level++; - continue; - }else{ - _xmlnode_tag2str(s,node,0); - } - }else{ - spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); - } - } - - tmp = xmlnode_get_nextsibling(node); - if(!tmp) - { - node = xmlnode_get_parent(node); - level--; - if(level>=0) _xmlnode_tag2str(s,node,2); - if(level<1) break; - dir = 1; - }else{ - node = tmp; - dir = 0; - } - } - - return s; -} - - -/* External routines */ - - -/* - * xmlnode_new_tag -- create a tag node - * Automatically creates a memory pool for the node. - * - * parameters - * name -- name of the tag - * - * returns - * a pointer to the tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_new_tag(const char* name) -{ - return _xmlnode_new(NULL, name, NTYPE_TAG); -} - - -/* - * xmlnode_insert_tag -- append a child tag to a tag - * - * parameters - * parent -- pointer to the parent tag - * name -- name of the child tag - * - * returns - * a pointer to the child tag node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_tag(xmlnode parent, const char* name) -{ - return _xmlnode_insert(parent, name, NTYPE_TAG); -} - - -/* - * xmlnode_insert_cdata -- append character data to a tag - * - * parameters - * parent -- parent tag - * CDATA -- character data - * size -- size of CDATA - * or -1 for null-terminated CDATA strings - * - * returns - * a pointer to the child CDATA node - * or NULL if it was unsuccessfull - */ -xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size) -{ - xmlnode result; - - if(CDATA == NULL || parent == NULL) - return NULL; - - if(size == -1) - size = strlen(CDATA); - - result = _xmlnode_insert(parent, NULL, NTYPE_CDATA); - if (result != NULL) - { - result->data = (char*)pmalloc(result->p, size + 1); - memcpy(result->data, CDATA, size); - result->data[size] = '\0'; - result->data_sz = size; - } - - return result; -} - - -/* - * xmlnode_get_tag -- find given tag in an xmlnode tree - * - * parameters - * parent -- pointer to the parent tag - * name -- "name" for the child tag of that name - * "name/name" for a sub child (recurses) - * "?attrib" to match the first tag with that attrib defined - * "?attrib=value" to match the first tag with that attrib and value - * "=cdata" to match the cdata contents of the child - * or any combination: "name/name/?attrib", "name=cdata", etc - * - * results - * a pointer to the tag matching search criteria - * or NULL if search was unsuccessfull - */ -xmlnode xmlnode_get_tag(xmlnode parent, const char* name) -{ - char *str, *slash, *qmark, *equals; - xmlnode step, ret; - - - if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; - - if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) - return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); - - str = g_strdup(name); - slash = strstr(str, "/"); - qmark = strstr(str, "?"); - equals = strstr(str, "="); - - if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) - { /* of type =cdata */ - - *equals = '\0'; - equals++; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; - - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(j_strcmp(xmlnode_get_data(step),equals) != 0) - continue; - - break; - } - - g_free(str); - return step; - } - - - if(qmark != NULL && (slash == NULL || qmark < slash)) - { /* of type ?attrib */ - - *qmark = '\0'; - qmark++; - if(equals != NULL) - { - *equals = '\0'; - equals++; - } - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) - continue; - - if(*str != '\0') - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - if(xmlnode_get_attrib(step,qmark) == NULL) - continue; - - if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) - continue; - - break; - } - - g_free(str); - return step; - } - - - *slash = '\0'; - ++slash; - - for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) - { - if(xmlnode_get_type(step) != NTYPE_TAG) continue; - - if(j_strcmp(xmlnode_get_name(step),str) != 0) - continue; - - ret = xmlnode_get_tag(step, slash); - if(ret != NULL) - { - g_free(str); - return ret; - } - } - - g_free(str); - return NULL; -} - - -/* return the cdata from any tag */ -char *xmlnode_get_tag_data(xmlnode parent, const char *name) -{ - xmlnode tag; - - tag = xmlnode_get_tag(parent, name); - if(tag == NULL) return NULL; - - return xmlnode_get_data(tag); -} - - -void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value) -{ - xmlnode attrib; - - if(owner == NULL || name == NULL || value == NULL) return; - - /* If there are no existing attributs, allocate a new one to start - the list */ - if (owner->firstattrib == NULL) - { - attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB); - owner->firstattrib = attrib; - owner->lastattrib = attrib; - } - else - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - { - attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB); - owner->lastattrib = attrib; - } - } - /* Update the value of the attribute */ - attrib->data_sz = strlen(value); - attrib->data = pstrdup(owner->p, value); - -} - -char* xmlnode_get_attrib(xmlnode owner, const char* name) -{ - xmlnode attrib; - - if (owner != NULL && owner->firstattrib != NULL) - { - attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); - if (attrib != NULL) - return (char*)attrib->data; - } - return NULL; -} - -static xmlnode xmlnode_get_firstattrib(xmlnode parent) -{ - if (parent != NULL) - return parent->firstattrib; - return NULL; -} - -xmlnode xmlnode_get_firstchild(xmlnode parent) -{ - if (parent != NULL) - return parent->firstchild; - return NULL; -} - -xmlnode xmlnode_get_nextsibling(xmlnode sibling) -{ - if (sibling != NULL) - return sibling->next; - return NULL; -} - -xmlnode xmlnode_get_parent(xmlnode node) -{ - if (node != NULL) - return node->parent; - return NULL; -} - -char* xmlnode_get_name(xmlnode node) -{ - if (node != NULL) - return node->name; - return NULL; -} - -char* xmlnode_get_data(xmlnode node) -{ - if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */ - for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node)) - if(xmlnode_get_type(node) == NTYPE_CDATA) break; - - if(node == NULL) return NULL; - - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - - return node->data; -} - -static int xmlnode_get_datasz(xmlnode node) -{ - if(xmlnode_get_type(node) != NTYPE_CDATA) return 0; - - /* check for a dirty node w/ unassembled cdata chunks */ - if(xmlnode_get_type(node->next) == NTYPE_CDATA) - _xmlnode_merge(node); - return node->data_sz; -} - -static int xmlnode_get_type(xmlnode node) -{ - if (node != NULL) - return node->type; - return NTYPE_UNDEF; -} - -int xmlnode_has_children(xmlnode node) -{ - if ((node != NULL) && (node->firstchild != NULL)) - return 1; - return 0; -} - -static int xmlnode_has_attribs(xmlnode node) -{ - if ((node != NULL) && (node->firstattrib != NULL)) - return 1; - return 0; -} - -pool xmlnode_pool(xmlnode node) -{ - if (node != NULL) - return node->p; - return (pool)NULL; -} - -void xmlnode_hide_attrib(xmlnode parent, const char *name) -{ - xmlnode attrib; - - if(parent == NULL || parent->firstattrib == NULL || name == NULL) - return; - - attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB); - if(attrib == NULL) - return; - - /* first fix up at the child level */ - _xmlnode_hide_sibling(attrib); - - /* next fix up at the parent level */ - if(parent->firstattrib == attrib) - parent->firstattrib = attrib->next; - if(parent->lastattrib == attrib) - parent->lastattrib = attrib->prev; -} - - - -/* - * xmlnode2str -- convert given xmlnode tree into a string - * - * parameters - * node -- pointer to the xmlnode structure - * - * results - * a pointer to the created string - * or NULL if it was unsuccessfull - */ -char *xmlnode2str(xmlnode node) -{ - return spool_print(_xmlnode2spool(node)); -} - -/* loop through both a and b comparing everything, attribs, cdata, children, etc */ -static int xmlnode_cmp(xmlnode a, xmlnode b) -{ - int ret = 0; - - while(1) - { - if(a == NULL && b == NULL) - return 0; - - if(a == NULL || b == NULL) - return -1; - - if(xmlnode_get_type(a) != xmlnode_get_type(b)) - return -1; - - switch(xmlnode_get_type(a)) - { - case NTYPE_ATTRIB: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - break; - case NTYPE_TAG: - ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); - if(ret != 0) - return -1; - ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); - if(ret != 0) - return -1; - break; - case NTYPE_CDATA: - ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); - if(ret != 0) - return -1; - } - a = xmlnode_get_nextsibling(a); - b = xmlnode_get_nextsibling(b); - } -} - - -xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node) -{ - xmlnode child; - - child = xmlnode_insert_tag(parent, xmlnode_get_name(node)); - if (xmlnode_has_attribs(node)) - xmlnode_insert_node(child, xmlnode_get_firstattrib(node)); - if (xmlnode_has_children(node)) - xmlnode_insert_node(child, xmlnode_get_firstchild(node)); - - return child; -} - -/* places copy of node and node's siblings in parent */ -static void xmlnode_insert_node(xmlnode parent, xmlnode node) -{ - if(node == NULL || parent == NULL) - return; - - while(node != NULL) - { - switch(xmlnode_get_type(node)) - { - case NTYPE_ATTRIB: - xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node)); - break; - case NTYPE_TAG: - xmlnode_insert_tag_node(parent, node); - break; - case NTYPE_CDATA: - xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node)); - } - node = xmlnode_get_nextsibling(node); - } -} - - -void xmlnode_free(xmlnode node) -{ - if(node == NULL) - return; - - pool_free(node->p); -} diff --git a/protocols/jabber/xmlparse.c b/protocols/jabber/xmlparse.c deleted file mode 100644 index bbef7d59..00000000 --- a/protocols/jabber/xmlparse.c +++ /dev/null @@ -1,2640 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmlparse.h" - -#ifdef XML_UNICODE -#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX -#define XmlConvert XmlUtf16Convert -#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS -#define XmlEncode XmlUtf16Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) -typedef unsigned short ICHAR; -#else -#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX -#define XmlConvert XmlUtf8Convert -#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding -#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS -#define XmlEncode XmlUtf8Encode -#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) -typedef char ICHAR; -#endif - - -#ifndef XML_NS - -#define XmlInitEncodingNS XmlInitEncoding -#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding -#undef XmlGetInternalEncodingNS -#define XmlGetInternalEncodingNS XmlGetInternalEncoding -#define XmlParseXmlDeclNS XmlParseXmlDecl - -#endif - - -#ifdef XML_UNICODE_WCHAR_T -#define XML_T(x) L ## x -#else -#define XML_T(x) x -#endif - -/* Round up n to be a multiple of sz, where sz is a power of 2. */ -#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) - -#include "xmltok.h" -#include "xmlrole.h" -#include "hashtable.h" - -#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ -#define INIT_DATA_BUF_SIZE 1024 -#define INIT_ATTS_SIZE 16 -#define INIT_BLOCK_SIZE 1024 -#define INIT_BUFFER_SIZE 1024 - -#define EXPAND_SPARE 24 - -typedef struct binding { - struct prefix *prefix; - struct binding *nextTagBinding; - struct binding *prevPrefixBinding; - const struct attribute_id *attId; - XML_Char *uri; - int uriLen; - int uriAlloc; -} BINDING; - -typedef struct prefix { - const XML_Char *name; - BINDING *binding; -} PREFIX; - -typedef struct { - const XML_Char *str; - const XML_Char *localPart; - int uriLen; -} TAG_NAME; - -typedef struct tag { - struct tag *parent; - const char *rawName; - int rawNameLength; - TAG_NAME name; - char *buf; - char *bufEnd; - BINDING *bindings; -} TAG; - -typedef struct { - const XML_Char *name; - const XML_Char *textPtr; - int textLen; - const XML_Char *systemId; - const XML_Char *base; - const XML_Char *publicId; - const XML_Char *notation; - char open; -} ENTITY; - -typedef struct block { - struct block *next; - int size; - XML_Char s[1]; -} BLOCK; - -typedef struct { - BLOCK *blocks; - BLOCK *freeBlocks; - const XML_Char *end; - XML_Char *ptr; - XML_Char *start; -} STRING_POOL; - -/* The XML_Char before the name is used to determine whether -an attribute has been specified. */ -typedef struct attribute_id { - XML_Char *name; - PREFIX *prefix; - char maybeTokenized; - char xmlns; -} ATTRIBUTE_ID; - -typedef struct { - const ATTRIBUTE_ID *id; - char isCdata; - const XML_Char *value; -} DEFAULT_ATTRIBUTE; - -typedef struct { - const XML_Char *name; - PREFIX *prefix; - int nDefaultAtts; - int allocDefaultAtts; - DEFAULT_ATTRIBUTE *defaultAtts; -} ELEMENT_TYPE; - -typedef struct { - HASH_TABLE generalEntities; - HASH_TABLE elementTypes; - HASH_TABLE attributeIds; - HASH_TABLE prefixes; - STRING_POOL pool; - int complete; - int standalone; - const XML_Char *base; - PREFIX defaultPrefix; -} DTD; - -typedef struct open_internal_entity { - const char *internalEventPtr; - const char *internalEventEndPtr; - struct open_internal_entity *next; - ENTITY *entity; -} OPEN_INTERNAL_ENTITY; - -typedef enum XML_Error Processor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr); - -static Processor prologProcessor; -static Processor prologInitProcessor; -static Processor contentProcessor; -static Processor cdataSectionProcessor; -static Processor epilogProcessor; - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); -static enum XML_Error -initializeEncoding(XML_Parser parser); -static enum XML_Error -doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, - const char *start, const char *end, const char **endPtr); -static enum XML_Error -doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, - TAG_NAME *tagNamePtr, BINDING **bindingsPtr); -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, int isCdata, const XML_Char *dfltValue); -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, - STRING_POOL *); -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); -static enum XML_Error -storeEntityValue(XML_Parser parser, const char *start, const char *end); -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); - -static const XML_Char *getContext(XML_Parser parser); -static void normalizePublicId(XML_Char *s); -static int dtdInit(DTD *); -static void dtdDestroy(DTD *); -static void poolInit(STRING_POOL *); -static void poolClear(STRING_POOL *); -static void poolDestroy(STRING_POOL *); -static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end); -static int poolGrow(STRING_POOL *pool); -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s); -static void *XML_GetBuffer(XML_Parser parser, int len); -static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal); - -#define poolStart(pool) ((pool)->start) -#define poolEnd(pool) ((pool)->ptr) -#define poolLength(pool) ((pool)->ptr - (pool)->start) -#define poolChop(pool) ((void)--(pool->ptr)) -#define poolLastChar(pool) (((pool)->ptr)[-1]) -#define poolDiscard(pool) ((pool)->ptr = (pool)->start) -#define poolFinish(pool) ((pool)->start = (pool)->ptr) -#define poolAppendChar(pool, c) \ - (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ - ? 0 \ - : ((*((pool)->ptr)++ = c), 1)) - -typedef struct { - /* The first member must be userData so that the XML_GetUserData macro works. */ - void *m_userData; - void *m_handlerArg; - char *m_buffer; - /* first character to be parsed */ - const char *m_bufferPtr; - /* past last character to be parsed */ - char *m_bufferEnd; - /* allocated end of buffer */ - const char *m_bufferLim; - long m_parseEndByteIndex; - const char *m_parseEndPtr; - XML_Char *m_dataBuf; - XML_Char *m_dataBufEnd; - XML_StartElementHandler m_startElementHandler; - XML_EndElementHandler m_endElementHandler; - XML_CharacterDataHandler m_characterDataHandler; - XML_ProcessingInstructionHandler m_processingInstructionHandler; - XML_CommentHandler m_commentHandler; - XML_StartCdataSectionHandler m_startCdataSectionHandler; - XML_EndCdataSectionHandler m_endCdataSectionHandler; - XML_DefaultHandler m_defaultHandler; - XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; - XML_NotationDeclHandler m_notationDeclHandler; - XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; - XML_NotStandaloneHandler m_notStandaloneHandler; - XML_ExternalEntityRefHandler m_externalEntityRefHandler; - void *m_externalEntityRefHandlerArg; - XML_UnknownEncodingHandler m_unknownEncodingHandler; - const ENCODING *m_encoding; - INIT_ENCODING m_initEncoding; - const XML_Char *m_protocolEncodingName; - int m_ns; - void *m_unknownEncodingMem; - void *m_unknownEncodingData; - void *m_unknownEncodingHandlerData; - void (*m_unknownEncodingRelease)(void *); - PROLOG_STATE m_prologState; - Processor *m_processor; - enum XML_Error m_errorCode; - const char *m_eventPtr; - const char *m_eventEndPtr; - const char *m_positionPtr; - OPEN_INTERNAL_ENTITY *m_openInternalEntities; - int m_defaultExpandInternalEntities; - int m_tagLevel; - ENTITY *m_declEntity; - const XML_Char *m_declNotationName; - const XML_Char *m_declNotationPublicId; - ELEMENT_TYPE *m_declElementType; - ATTRIBUTE_ID *m_declAttributeId; - char m_declAttributeIsCdata; - DTD m_dtd; - TAG *m_tagStack; - TAG *m_freeTagList; - BINDING *m_inheritedBindings; - BINDING *m_freeBindingList; - int m_attsSize; - int m_nSpecifiedAtts; - ATTRIBUTE *m_atts; - POSITION m_position; - STRING_POOL m_tempPool; - STRING_POOL m_temp2Pool; - char *m_groupConnector; - unsigned m_groupSize; - int m_hadExternalDoctype; - XML_Char m_namespaceSeparator; -} Parser; - -#define userData (((Parser *)parser)->m_userData) -#define handlerArg (((Parser *)parser)->m_handlerArg) -#define startElementHandler (((Parser *)parser)->m_startElementHandler) -#define endElementHandler (((Parser *)parser)->m_endElementHandler) -#define characterDataHandler (((Parser *)parser)->m_characterDataHandler) -#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) -#define commentHandler (((Parser *)parser)->m_commentHandler) -#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) -#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) -#define defaultHandler (((Parser *)parser)->m_defaultHandler) -#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) -#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) -#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) -#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) -#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) -#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) -#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) -#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) -#define encoding (((Parser *)parser)->m_encoding) -#define initEncoding (((Parser *)parser)->m_initEncoding) -#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) -#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) -#define unknownEncodingHandlerData \ - (((Parser *)parser)->m_unknownEncodingHandlerData) -#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) -#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) -#define ns (((Parser *)parser)->m_ns) -#define prologState (((Parser *)parser)->m_prologState) -#define processor (((Parser *)parser)->m_processor) -#define errorCode (((Parser *)parser)->m_errorCode) -#define eventPtr (((Parser *)parser)->m_eventPtr) -#define eventEndPtr (((Parser *)parser)->m_eventEndPtr) -#define positionPtr (((Parser *)parser)->m_positionPtr) -#define position (((Parser *)parser)->m_position) -#define openInternalEntities (((Parser *)parser)->m_openInternalEntities) -#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) -#define tagLevel (((Parser *)parser)->m_tagLevel) -#define buffer (((Parser *)parser)->m_buffer) -#define bufferPtr (((Parser *)parser)->m_bufferPtr) -#define bufferEnd (((Parser *)parser)->m_bufferEnd) -#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) -#define parseEndPtr (((Parser *)parser)->m_parseEndPtr) -#define bufferLim (((Parser *)parser)->m_bufferLim) -#define dataBuf (((Parser *)parser)->m_dataBuf) -#define dataBufEnd (((Parser *)parser)->m_dataBufEnd) -#define dtd (((Parser *)parser)->m_dtd) -#define declEntity (((Parser *)parser)->m_declEntity) -#define declNotationName (((Parser *)parser)->m_declNotationName) -#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) -#define declElementType (((Parser *)parser)->m_declElementType) -#define declAttributeId (((Parser *)parser)->m_declAttributeId) -#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) -#define freeTagList (((Parser *)parser)->m_freeTagList) -#define freeBindingList (((Parser *)parser)->m_freeBindingList) -#define inheritedBindings (((Parser *)parser)->m_inheritedBindings) -#define tagStack (((Parser *)parser)->m_tagStack) -#define atts (((Parser *)parser)->m_atts) -#define attsSize (((Parser *)parser)->m_attsSize) -#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) -#define tempPool (((Parser *)parser)->m_tempPool) -#define temp2Pool (((Parser *)parser)->m_temp2Pool) -#define groupConnector (((Parser *)parser)->m_groupConnector) -#define groupSize (((Parser *)parser)->m_groupSize) -#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) -#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) - -#ifdef _MSC_VER -#ifdef _DEBUG -Parser *asParser(XML_Parser parser) -{ - return parser; -} -#endif -#endif - -XML_Parser XML_ParserCreate(const XML_Char *encodingName) -{ - XML_Parser parser = malloc(sizeof(Parser)); - if (!parser) - return parser; - processor = prologInitProcessor; - XmlPrologStateInit(&prologState); - userData = 0; - handlerArg = 0; - startElementHandler = 0; - endElementHandler = 0; - characterDataHandler = 0; - processingInstructionHandler = 0; - commentHandler = 0; - startCdataSectionHandler = 0; - endCdataSectionHandler = 0; - defaultHandler = 0; - unparsedEntityDeclHandler = 0; - notationDeclHandler = 0; - startNamespaceDeclHandler = 0; - endNamespaceDeclHandler = 0; - notStandaloneHandler = 0; - externalEntityRefHandler = 0; - externalEntityRefHandlerArg = parser; - unknownEncodingHandler = 0; - buffer = 0; - bufferPtr = 0; - bufferEnd = 0; - parseEndByteIndex = 0; - parseEndPtr = 0; - bufferLim = 0; - declElementType = 0; - declAttributeId = 0; - declEntity = 0; - declNotationName = 0; - declNotationPublicId = 0; - memset(&position, 0, sizeof(POSITION)); - errorCode = XML_ERROR_NONE; - eventPtr = 0; - eventEndPtr = 0; - positionPtr = 0; - openInternalEntities = 0; - tagLevel = 0; - tagStack = 0; - freeTagList = 0; - freeBindingList = 0; - inheritedBindings = 0; - attsSize = INIT_ATTS_SIZE; - atts = malloc(attsSize * sizeof(ATTRIBUTE)); - nSpecifiedAtts = 0; - dataBuf = malloc(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); - groupSize = 0; - groupConnector = 0; - hadExternalDoctype = 0; - unknownEncodingMem = 0; - unknownEncodingRelease = 0; - unknownEncodingData = 0; - unknownEncodingHandlerData = 0; - namespaceSeparator = '!'; - ns = 0; - poolInit(&tempPool); - poolInit(&temp2Pool); - protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0; - if (!dtdInit(&dtd) || !atts || !dataBuf - || (encodingName && !protocolEncodingName)) { - XML_ParserFree(parser); - return 0; - } - dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; - XmlInitEncoding(&initEncoding, &encoding, 0); - return parser; -} - -static -void destroyBindings(BINDING *bindings) -{ - for (;;) { - BINDING *b = bindings; - if (!b) - break; - bindings = b->nextTagBinding; - g_free(b->uri); - g_free(b); - } -} - -void XML_ParserFree(XML_Parser parser) -{ - for (;;) { - TAG *p; - if (tagStack == 0) { - if (freeTagList == 0) - break; - tagStack = freeTagList; - freeTagList = 0; - } - p = tagStack; - tagStack = tagStack->parent; - g_free(p->buf); - destroyBindings(p->bindings); - g_free(p); - } - destroyBindings(freeBindingList); - destroyBindings(inheritedBindings); - poolDestroy(&tempPool); - poolDestroy(&temp2Pool); - dtdDestroy(&dtd); - g_free((void *)atts); - g_free(groupConnector); - g_free(buffer); - g_free(dataBuf); - g_free(unknownEncodingMem); - if (unknownEncodingRelease) - unknownEncodingRelease(unknownEncodingData); - g_free(parser); -} - -void XML_SetUserData(XML_Parser parser, void *p) -{ - if (handlerArg == userData) - handlerArg = userData = p; - else - userData = p; -} - -void XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end) -{ - startElementHandler = start; - endElementHandler = end; -} - -void XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler) -{ - characterDataHandler = handler; -} - -int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) -{ - if (len == 0) { - if (!isFinal) - return 1; - positionPtr = bufferPtr; - errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - else if (bufferPtr == bufferEnd) { - const char *end; - int nLeftOver; - parseEndByteIndex += len; - positionPtr = s; - if (isFinal) { - errorCode = processor(parser, s, parseEndPtr = s + len, 0); - if (errorCode == XML_ERROR_NONE) - return 1; - eventEndPtr = eventPtr; - return 0; - } - errorCode = processor(parser, s, parseEndPtr = s + len, &end); - if (errorCode != XML_ERROR_NONE) { - eventEndPtr = eventPtr; - return 0; - } - XmlUpdatePosition(encoding, positionPtr, end, &position); - nLeftOver = s + len - end; - if (nLeftOver) { - if (buffer == 0 || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - buffer = buffer == 0 ? malloc(len * 2) : realloc(buffer, len * 2); - if (!buffer) { - errorCode = XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = 0; - return 0; - } - bufferLim = buffer + len * 2; - } - memcpy(buffer, end, nLeftOver); - bufferPtr = buffer; - bufferEnd = buffer + nLeftOver; - } - return 1; - } - else { - memcpy(XML_GetBuffer(parser, len), s, len); - return XML_ParseBuffer(parser, len, isFinal); - } -} - -static int XML_ParseBuffer(XML_Parser parser, int len, int isFinal) -{ - const char *start = bufferPtr; - positionPtr = start; - bufferEnd += len; - parseEndByteIndex += len; - errorCode = processor(parser, start, parseEndPtr = bufferEnd, - isFinal ? (const char **)0 : &bufferPtr); - if (errorCode == XML_ERROR_NONE) { - if (!isFinal) - XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); - return 1; - } - else { - eventEndPtr = eventPtr; - return 0; - } -} - -static void *XML_GetBuffer(XML_Parser parser, int len) -{ - if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ - int neededSize = len + (bufferEnd - bufferPtr); - if (neededSize <= bufferLim - buffer) { - memmove(buffer, bufferPtr, bufferEnd - bufferPtr); - bufferEnd = buffer + (bufferEnd - bufferPtr); - bufferPtr = buffer; - } - else { - char *newBuf; - int bufferSize = bufferLim - bufferPtr; - if (bufferSize == 0) - bufferSize = INIT_BUFFER_SIZE; - do { - bufferSize *= 2; - } while (bufferSize < neededSize); - newBuf = malloc(bufferSize); - if (newBuf == 0) { - errorCode = XML_ERROR_NO_MEMORY; - return 0; - } - bufferLim = newBuf + bufferSize; - if (bufferPtr) { - memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); - g_free(buffer); - } - bufferEnd = newBuf + (bufferEnd - bufferPtr); - bufferPtr = buffer = newBuf; - } - } - return bufferEnd; -} - -static -enum XML_Error contentProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - return doContent(parser, 0, encoding, start, end, endPtr); -} - -static enum XML_Error -doContent(XML_Parser parser, - int startTagLevel, - const ENCODING *enc, - const char *s, - const char *end, - const char **nextPtr) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - for (;;) { - const char *next = s; /* XmlContentTok doesn't always set the last arg */ - int tok = XmlContentTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - *eventEndPP = end; - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) - return XML_ERROR_NO_ELEMENTS; - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (startTagLevel > 0) { - if (tagLevel != startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - return XML_ERROR_NONE; - } - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (characterDataHandler) - characterDataHandler(handlerArg, &ch, 1); - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - name = poolStoreString(&dtd.pool, enc, - s + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&dtd.pool); - if (!entity) { - if (dtd.complete || dtd.standalone) - return XML_ERROR_UNDEFINED_ENTITY; - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - if (entity->open) - return XML_ERROR_RECURSIVE_ENTITY_REF; - if (entity->notation) - return XML_ERROR_BINARY_ENTITY_REF; - if (entity) { - if (entity->textPtr) { - enum XML_Error result; - OPEN_INTERNAL_ENTITY openEntity; - if (defaultHandler && !defaultExpandInternalEntities) { - reportDefault(parser, enc, s, next); - break; - } - entity->open = 1; - openEntity.next = openInternalEntities; - openInternalEntities = &openEntity; - openEntity.entity = entity; - openEntity.internalEventPtr = 0; - openEntity.internalEventEndPtr = 0; - result = doContent(parser, - tagLevel, - internalEnc, - (char *)entity->textPtr, - (char *)(entity->textPtr + entity->textLen), - 0); - entity->open = 0; - openInternalEntities = openEntity.next; - if (result) - return result; - } - else if (externalEntityRefHandler) { - const XML_Char *context; - entity->open = 1; - context = getContext(parser); - entity->open = 0; - if (!context) - return XML_ERROR_NO_MEMORY; - if (!externalEntityRefHandler(externalEntityRefHandlerArg, - context, - dtd.base, - entity->systemId, - entity->publicId)) - return XML_ERROR_EXTERNAL_ENTITY_HANDLING; - poolDiscard(&tempPool); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_START_TAG_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_START_TAG_NO_ATTS: - { - TAG *tag; - if (freeTagList) { - tag = freeTagList; - freeTagList = freeTagList->parent; - } - else { - tag = malloc(sizeof(TAG)); - if (!tag) - return XML_ERROR_NO_MEMORY; - tag->buf = malloc(INIT_TAG_BUF_SIZE); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; - } - tag->bindings = 0; - tag->parent = tagStack; - tagStack = tag; - tag->name.localPart = 0; - tag->rawName = s + enc->minBytesPerChar; - tag->rawNameLength = XmlNameLength(enc, tag->rawName); - if (nextPtr) { - /* Need to guarantee that: - tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */ - if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { - int bufSize = tag->rawNameLength * 4; - bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - } - memcpy(tag->buf, tag->rawName, tag->rawNameLength); - tag->rawName = tag->buf; - } - ++tagLevel; - if (startElementHandler) { - enum XML_Error result; - XML_Char *toPtr; - for (;;) { - const char *rawNameEnd = tag->rawName + tag->rawNameLength; - const char *fromPtr = tag->rawName; - int bufSize; - if (nextPtr) - toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char))); - else - toPtr = (XML_Char *)tag->buf; - tag->name.str = toPtr; - XmlConvert(enc, - &fromPtr, rawNameEnd, - (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); - if (fromPtr == rawNameEnd) - break; - bufSize = (tag->bufEnd - tag->buf) << 1; - tag->buf = realloc(tag->buf, bufSize); - if (!tag->buf) - return XML_ERROR_NO_MEMORY; - tag->bufEnd = tag->buf + bufSize; - if (nextPtr) - tag->rawName = tag->buf; - } - *toPtr = XML_T('\0'); - result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); - if (result) - return result; - startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); - poolClear(&tempPool); - } - else { - tag->name.str = 0; - if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - } - case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: - if (!startElementHandler) { - enum XML_Error result = storeAtts(parser, enc, s, 0, 0); - if (result) - return result; - } - /* fall through */ - case XML_TOK_EMPTY_ELEMENT_NO_ATTS: - if (startElementHandler || endElementHandler) { - const char *rawName = s + enc->minBytesPerChar; - enum XML_Error result; - BINDING *bindings = 0; - TAG_NAME name; - name.str = poolStoreString(&tempPool, enc, rawName, - rawName + XmlNameLength(enc, rawName)); - if (!name.str) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - result = storeAtts(parser, enc, s, &name, &bindings); - if (result) - return result; - poolFinish(&tempPool); - if (startElementHandler) - startElementHandler(handlerArg, name.str, (const XML_Char **)atts); - if (endElementHandler) { - if (startElementHandler) - *eventPP = *eventEndPP; - endElementHandler(handlerArg, name.str); - } - poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - break; - case XML_TOK_END_TAG: - if (tagLevel == startTagLevel) - return XML_ERROR_ASYNC_ENTITY; - else { - int len; - const char *rawName; - TAG *tag = tagStack; - tagStack = tag->parent; - tag->parent = freeTagList; - freeTagList = tag; - rawName = s + enc->minBytesPerChar*2; - len = XmlNameLength(enc, rawName); - if (len != tag->rawNameLength - || memcmp(tag->rawName, rawName, len) != 0) { - *eventPP = rawName; - return XML_ERROR_TAG_MISMATCH; - } - --tagLevel; - if (endElementHandler && tag->name.str) { - if (tag->name.localPart) { - XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen; - const XML_Char *from = tag->name.localPart; - while ((*to++ = *from++) != 0) - ; - } - endElementHandler(handlerArg, tag->name.str); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - while (tag->bindings) { - BINDING *b = tag->bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - tag->bindings = tag->bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } - if (tagLevel == 0) - return epilogProcessor(parser, next, end, nextPtr); - } - break; - case XML_TOK_CHAR_REF: - { - int n = XmlCharRefNumber(enc, s); - if (n < 0) - return XML_ERROR_BAD_CHAR_REF; - if (characterDataHandler) { - XML_Char buf[XML_ENCODE_MAX]; - characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - } - break; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_CDATA_SECT_OPEN: - { - enum XML_Error result; - if (startCdataSectionHandler) - startCdataSectionHandler(handlerArg); -#if 0 - /* Suppose you doing a transformation on a document that involves - changing only the character data. You set up a defaultHandler - and a characterDataHandler. The defaultHandler simply copies - characters through. The characterDataHandler does the transformation - and writes the characters out escaping them as necessary. This case - will fail to work if we leave out the following two lines (because & - and < inside CDATA sections will be incorrectly escaped). - - However, now we have a start/endCdataSectionHandler, so it seems - easier to let the user deal with this. */ - - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - result = doCdataSection(parser, enc, &next, end, nextPtr); - if (!next) { - processor = cdataSectionProcessor; - return result; - } - } - break; - case XML_TOK_TRAILING_RSQB: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)end - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, end); - if (startTagLevel == 0) { - *eventPP = end; - return XML_ERROR_NO_ELEMENTS; - } - if (tagLevel != startTagLevel) { - *eventPP = end; - return XML_ERROR_ASYNC_ENTITY; - } - return XML_ERROR_NONE; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, enc, s, next)) - return XML_ERROR_NO_MEMORY; - break; - default: - if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - } - *eventPP = s = next; - } - /* not reached */ -} - -/* If tagNamePtr is non-null, build a real list of attributes, -otherwise just check the attributes for well-formedness. */ - -static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, - const char *s, TAG_NAME *tagNamePtr, - BINDING **bindingsPtr) -{ - ELEMENT_TYPE *elementType = 0; - int nDefaultAtts = 0; - const XML_Char **appAtts; - int attIndex = 0; - int i; - int n; - int nPrefixes = 0; - BINDING *binding; - const XML_Char *localPart; - - if (tagNamePtr) { - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, 0); - if (!elementType) { - tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); - if (!tagNamePtr->str) - return XML_ERROR_NO_MEMORY; - elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); - if (!elementType) - return XML_ERROR_NO_MEMORY; - if (ns && !setElementTypePrefix(parser, elementType)) - return XML_ERROR_NO_MEMORY; - } - nDefaultAtts = elementType->nDefaultAtts; - } - n = XmlGetAttributes(enc, s, attsSize, atts); - if (n + nDefaultAtts > attsSize) { - int oldAttsSize = attsSize; - attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; - atts = realloc((void *)atts, attsSize * sizeof(ATTRIBUTE)); - if (!atts) - return XML_ERROR_NO_MEMORY; - if (n > oldAttsSize) - XmlGetAttributes(enc, s, n, atts); - } - appAtts = (const XML_Char **)atts; - for (i = 0; i < n; i++) { - ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, - atts[i].name - + XmlNameLength(enc, atts[i].name)); - if (!attId) - return XML_ERROR_NO_MEMORY; - if ((attId->name)[-1]) { - if (enc == encoding) - eventPtr = atts[i].name; - return XML_ERROR_DUPLICATE_ATTRIBUTE; - } - (attId->name)[-1] = 1; - appAtts[attIndex++] = attId->name; - if (!atts[i].normalized) { - enum XML_Error result; - int isCdata = 1; - - if (attId->maybeTokenized) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - if (attId == elementType->defaultAtts[j].id) { - isCdata = elementType->defaultAtts[j].isCdata; - break; - } - } - } - - result = storeAttributeValue(parser, enc, isCdata, - atts[i].valuePtr, atts[i].valueEnd, - &tempPool); - if (result) - return result; - if (tagNamePtr) { - appAtts[attIndex] = poolStart(&tempPool); - poolFinish(&tempPool); - } - else - poolDiscard(&tempPool); - } - else if (tagNamePtr) { - appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); - if (appAtts[attIndex] == 0) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - if (attId->prefix && tagNamePtr) { - if (attId->xmlns) { - if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr)) - return XML_ERROR_NO_MEMORY; - --attIndex; - } - else { - attIndex++; - nPrefixes++; - (attId->name)[-1] = 2; - } - } - else - attIndex++; - } - nSpecifiedAtts = attIndex; - if (tagNamePtr) { - int j; - for (j = 0; j < nDefaultAtts; j++) { - const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; - if (!(da->id->name)[-1] && da->value) { - if (da->id->prefix) { - if (da->id->xmlns) { - if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr)) - return XML_ERROR_NO_MEMORY; - } - else { - (da->id->name)[-1] = 2; - nPrefixes++; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - else { - (da->id->name)[-1] = 1; - appAtts[attIndex++] = da->id->name; - appAtts[attIndex++] = da->value; - } - } - } - appAtts[attIndex] = 0; - } - i = 0; - if (nPrefixes) { - for (; i < attIndex; i += 2) { - if (appAtts[i][-1] == 2) { - ATTRIBUTE_ID *id; - ((XML_Char *)(appAtts[i]))[-1] = 0; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); - if (id->prefix->binding) { - int j; - const BINDING *b = id->prefix->binding; - const XML_Char *s = appAtts[i]; - for (j = 0; j < b->uriLen; j++) { - if (!poolAppendChar(&tempPool, b->uri[j])) - return XML_ERROR_NO_MEMORY; - } - while (*s++ != ':') - ; - do { - if (!poolAppendChar(&tempPool, *s)) - return XML_ERROR_NO_MEMORY; - } while (*s++); - appAtts[i] = poolStart(&tempPool); - poolFinish(&tempPool); - } - if (!--nPrefixes) - break; - } - else - ((XML_Char *)(appAtts[i]))[-1] = 0; - } - } - for (; i < attIndex; i += 2) - ((XML_Char *)(appAtts[i]))[-1] = 0; - if (!tagNamePtr) - return XML_ERROR_NONE; - for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) - binding->attId->name[-1] = 0; - if (elementType->prefix) { - binding = elementType->prefix->binding; - if (!binding) - return XML_ERROR_NONE; - localPart = tagNamePtr->str; - while (*localPart++ != XML_T(':')) - ; - } - else if (dtd.defaultPrefix.binding) { - binding = dtd.defaultPrefix.binding; - localPart = tagNamePtr->str; - } - else - return XML_ERROR_NONE; - tagNamePtr->localPart = localPart; - tagNamePtr->uriLen = binding->uriLen; - i = binding->uriLen; - do { - if (i == binding->uriAlloc) { - binding->uri = realloc(binding->uri, binding->uriAlloc *= 2); - if (!binding->uri) - return XML_ERROR_NO_MEMORY; - } - binding->uri[i++] = *localPart; - } while (*localPart++); - tagNamePtr->str = binding->uri; - return XML_ERROR_NONE; -} - -static -int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) -{ - BINDING *b; - int len; - for (len = 0; uri[len]; len++) - ; - if (namespaceSeparator) - len++; - if (freeBindingList) { - b = freeBindingList; - if (len > b->uriAlloc) { - b->uri = realloc(b->uri, len + EXPAND_SPARE); - if (!b->uri) - return 0; - b->uriAlloc = len + EXPAND_SPARE; - } - freeBindingList = b->nextTagBinding; - } - else { - b = malloc(sizeof(BINDING)); - if (!b) - return 0; - b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE); - if (!b->uri) { - g_free(b); - return 0; - } - b->uriAlloc = len; - } - b->uriLen = len; - memcpy(b->uri, uri, len * sizeof(XML_Char)); - if (namespaceSeparator) - b->uri[len - 1] = namespaceSeparator; - b->prefix = prefix; - b->attId = attId; - b->prevPrefixBinding = prefix->binding; - if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) - prefix->binding = 0; - else - prefix->binding = b; - b->nextTagBinding = *bindingsPtr; - *bindingsPtr = b; - if (startNamespaceDeclHandler) - startNamespaceDeclHandler(handlerArg, prefix->name, - prefix->binding ? uri : 0); - return 1; -} - -/* The idea here is to avoid using stack for each CDATA section when -the whole file is parsed with one call. */ - -static -enum XML_Error cdataSectionProcessor(XML_Parser parser, - const char *start, - const char *end, - const char **endPtr) -{ - enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); - if (start) { - processor = contentProcessor; - return contentProcessor(parser, start, end, endPtr); - } - return result; -} - -/* startPtr gets set to non-null is the section is closed, and to null if -the section is not yet closed. */ - -static -enum XML_Error doCdataSection(XML_Parser parser, - const ENCODING *enc, - const char **startPtr, - const char *end, - const char **nextPtr) -{ - const char *s = *startPtr; - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - *eventPP = s; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - *eventPP = s; - *startPtr = 0; - for (;;) { - const char *next; - int tok = XmlCdataSectionTok(enc, s, end, &next); - *eventEndPP = next; - switch (tok) { - case XML_TOK_CDATA_SECT_CLOSE: - if (endCdataSectionHandler) - endCdataSectionHandler(handlerArg); -#if 0 - /* see comment under XML_TOK_CDATA_SECT_OPEN */ - else if (characterDataHandler) - characterDataHandler(handlerArg, dataBuf, 0); -#endif - else if (defaultHandler) - reportDefault(parser, enc, s, next); - *startPtr = next; - return XML_ERROR_NONE; - case XML_TOK_DATA_NEWLINE: - if (characterDataHandler) { - XML_Char c = 0xA; - characterDataHandler(handlerArg, &c, 1); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_DATA_CHARS: - if (characterDataHandler) { - if (MUST_CONVERT(enc, s)) { - for (;;) { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = next; - characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - if (s == next) - break; - *eventPP = s; - } - } - else - characterDataHandler(handlerArg, - (XML_Char *)s, - (XML_Char *)next - (XML_Char *)s); - } - else if (defaultHandler) - reportDefault(parser, enc, s, next); - break; - case XML_TOK_INVALID: - *eventPP = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_PARTIAL: - case XML_TOK_NONE: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_CDATA_SECTION; - default: - abort(); - } - *eventPP = s = next; - } - /* not reached */ -} - -static enum XML_Error -initializeEncoding(XML_Parser parser) -{ - const char *s; -#ifdef XML_UNICODE - char encodingBuf[128]; - if (!protocolEncodingName) - s = 0; - else { - int i; - for (i = 0; protocolEncodingName[i]; i++) { - if (i == sizeof(encodingBuf) - 1 - || protocolEncodingName[i] >= 0x80 - || protocolEncodingName[i] < 0) { - encodingBuf[0] = '\0'; - break; - } - encodingBuf[i] = (char)protocolEncodingName[i]; - } - encodingBuf[i] = '\0'; - s = encodingBuf; - } -#else -s = protocolEncodingName; -#endif - if (ns ? XmlInitEncodingNS(&initEncoding, &encoding, s) : XmlInitEncoding(&initEncoding, &encoding, s)) - return XML_ERROR_NONE; - return handleUnknownEncoding(parser, protocolEncodingName); -} - -static enum XML_Error -processXmlDecl(XML_Parser parser, int isGeneralTextEntity, - const char *s, const char *next) -{ - const char *encodingName = 0; - const ENCODING *newEncoding = 0; - const char *version; - int standalone = -1; - if (!(ns - ? XmlParseXmlDeclNS(isGeneralTextEntity, - encoding, - s, - next, - &eventPtr, - &version, - &encodingName, - &newEncoding, - &standalone) - : XmlParseXmlDecl(isGeneralTextEntity, - encoding, - s, - next, - &eventPtr, - &version, - &encodingName, - &newEncoding, - &standalone))) - return XML_ERROR_SYNTAX; - if (!isGeneralTextEntity && standalone == 1) - dtd.standalone = 1; - if (defaultHandler) - reportDefault(parser, encoding, s, next); - if (!protocolEncodingName) { - if (newEncoding) { - if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { - eventPtr = encodingName; - return XML_ERROR_INCORRECT_ENCODING; - } - encoding = newEncoding; - } - else if (encodingName) { - enum XML_Error result; - const XML_Char *s = poolStoreString(&tempPool, - encoding, - encodingName, - encodingName - + XmlNameLength(encoding, encodingName)); - if (!s) - return XML_ERROR_NO_MEMORY; - result = handleUnknownEncoding(parser, s); - poolDiscard(&tempPool); - if (result == XML_ERROR_UNKNOWN_ENCODING) - eventPtr = encodingName; - return result; - } - } - return XML_ERROR_NONE; -} - -static enum XML_Error -handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) -{ - if (unknownEncodingHandler) { - XML_Encoding info; - int i; - for (i = 0; i < 256; i++) - info.map[i] = -1; - info.convert = 0; - info.data = 0; - info.release = 0; - if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { - ENCODING *enc; - unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding()); - if (!unknownEncodingMem) { - if (info.release) - info.release(info.data); - return XML_ERROR_NO_MEMORY; - } - enc = (ns - ? XmlInitUnknownEncodingNS(unknownEncodingMem, - info.map, - info.convert, - info.data) - : XmlInitUnknownEncoding(unknownEncodingMem, - info.map, - info.convert, - info.data)); - if (enc) { - unknownEncodingData = info.data; - unknownEncodingRelease = info.release; - encoding = enc; - return XML_ERROR_NONE; - } - } - if (info.release) - info.release(info.data); - } - return XML_ERROR_UNKNOWN_ENCODING; -} - -static enum XML_Error -prologInitProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - enum XML_Error result = initializeEncoding(parser); - if (result != XML_ERROR_NONE) - return result; - processor = prologProcessor; - return prologProcessor(parser, s, end, nextPtr); -} - -static enum XML_Error -prologProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - if (tok <= 0) { - if (nextPtr != 0 && tok != XML_TOK_INVALID) { - *nextPtr = s; - return XML_ERROR_NONE; - } - switch (tok) { - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_NONE: - return XML_ERROR_NO_ELEMENTS; - case XML_TOK_PARTIAL: - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - return XML_ERROR_PARTIAL_CHAR; - case XML_TOK_TRAILING_CR: - eventPtr = s + encoding->minBytesPerChar; - return XML_ERROR_NO_ELEMENTS; - default: - abort(); - } - } - switch (XmlTokenRole(&prologState, tok, s, next, encoding)) { - case XML_ROLE_XML_DECL: - { - enum XML_Error result = processXmlDecl(parser, 0, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_DOCTYPE_SYSTEM_ID: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - hadExternalDoctype = 1; - break; - case XML_ROLE_DOCTYPE_PUBLIC_ID: - case XML_ROLE_ENTITY_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declEntity) { - XML_Char *tem = poolStoreString(&dtd.pool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declEntity->publicId = tem; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_INSTANCE_START: - processor = contentProcessor; - if (hadExternalDoctype) - dtd.complete = 0; - return contentProcessor(parser, s, end, nextPtr); - case XML_ROLE_ATTLIST_ELEMENT_NAME: - { - const XML_Char *name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - declElementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); - if (!declElementType) - return XML_ERROR_NO_MEMORY; - if (declElementType->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!setElementTypePrefix(parser, declElementType)) - return XML_ERROR_NO_MEMORY; - } - break; - } - case XML_ROLE_ATTRIBUTE_NAME: - declAttributeId = getAttributeId(parser, encoding, s, next); - if (!declAttributeId) - return XML_ERROR_NO_MEMORY; - declAttributeIsCdata = 0; - break; - case XML_ROLE_ATTRIBUTE_TYPE_CDATA: - declAttributeIsCdata = 1; - break; - case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: - case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0)) - return XML_ERROR_NO_MEMORY; - break; - case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: - case XML_ROLE_FIXED_ATTRIBUTE_VALUE: - { - const XML_Char *attVal; - enum XML_Error result - = storeAttributeValue(parser, encoding, declAttributeIsCdata, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar, - &dtd.pool); - if (result) - return result; - attVal = poolStart(&dtd.pool); - poolFinish(&dtd.pool); - if (dtd.complete - && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, attVal)) - return XML_ERROR_NO_MEMORY; - break; - } - case XML_ROLE_ENTITY_VALUE: - { - enum XML_Error result = storeEntityValue(parser, s, next); - if (result != XML_ERROR_NONE) - return result; - } - break; - case XML_ROLE_ENTITY_SYSTEM_ID: - if (declEntity) { - declEntity->systemId = poolStoreString(&dtd.pool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!declEntity->systemId) - return XML_ERROR_NO_MEMORY; - declEntity->base = dtd.base; - poolFinish(&dtd.pool); - } - break; - case XML_ROLE_ENTITY_NOTATION_NAME: - if (declEntity) { - declEntity->notation = poolStoreString(&dtd.pool, encoding, s, next); - if (!declEntity->notation) - return XML_ERROR_NO_MEMORY; - poolFinish(&dtd.pool); - if (unparsedEntityDeclHandler) { - eventPtr = eventEndPtr = s; - unparsedEntityDeclHandler(handlerArg, - declEntity->name, - declEntity->base, - declEntity->systemId, - declEntity->publicId, - declEntity->notation); - } - - } - break; - case XML_ROLE_GENERAL_ENTITY_NAME: - { - const XML_Char *name; - if (XmlPredefinedEntityName(encoding, s, next)) { - declEntity = 0; - break; - } - name = poolStoreString(&dtd.pool, encoding, s, next); - if (!name) - return XML_ERROR_NO_MEMORY; - if (dtd.complete) { - declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY)); - if (!declEntity) - return XML_ERROR_NO_MEMORY; - if (declEntity->name != name) { - poolDiscard(&dtd.pool); - declEntity = 0; - } - else - poolFinish(&dtd.pool); - } - else { - poolDiscard(&dtd.pool); - declEntity = 0; - } - } - break; - case XML_ROLE_PARAM_ENTITY_NAME: - declEntity = 0; - break; - case XML_ROLE_NOTATION_NAME: - declNotationPublicId = 0; - declNotationName = 0; - if (notationDeclHandler) { - declNotationName = poolStoreString(&tempPool, encoding, s, next); - if (!declNotationName) - return XML_ERROR_NO_MEMORY; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_PUBLIC_ID: - if (!XmlIsPublicId(encoding, s, next, &eventPtr)) - return XML_ERROR_SYNTAX; - if (declNotationName) { - XML_Char *tem = poolStoreString(&tempPool, - encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!tem) - return XML_ERROR_NO_MEMORY; - normalizePublicId(tem); - declNotationPublicId = tem; - poolFinish(&tempPool); - } - break; - case XML_ROLE_NOTATION_SYSTEM_ID: - if (declNotationName && notationDeclHandler) { - const XML_Char *systemId - = poolStoreString(&tempPool, encoding, - s + encoding->minBytesPerChar, - next - encoding->minBytesPerChar); - if (!systemId) - return XML_ERROR_NO_MEMORY; - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - systemId, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_NOTATION_NO_SYSTEM_ID: - if (declNotationPublicId && notationDeclHandler) { - eventPtr = eventEndPtr = s; - notationDeclHandler(handlerArg, - declNotationName, - dtd.base, - 0, - declNotationPublicId); - } - poolClear(&tempPool); - break; - case XML_ROLE_ERROR: - eventPtr = s; - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - return XML_ERROR_PARAM_ENTITY_REF; - case XML_TOK_XML_DECL: - return XML_ERROR_MISPLACED_XML_PI; - default: - return XML_ERROR_SYNTAX; - } - case XML_ROLE_GROUP_OPEN: - if (prologState.level >= groupSize) { - if (groupSize) - groupConnector = realloc(groupConnector, groupSize *= 2); - else - groupConnector = malloc(groupSize = 32); - if (!groupConnector) - return XML_ERROR_NO_MEMORY; - } - groupConnector[prologState.level] = 0; - break; - case XML_ROLE_GROUP_SEQUENCE: - if (groupConnector[prologState.level] == '|') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = ','; - break; - case XML_ROLE_GROUP_CHOICE: - if (groupConnector[prologState.level] == ',') { - eventPtr = s; - return XML_ERROR_SYNTAX; - } - groupConnector[prologState.level] = '|'; - break; - case XML_ROLE_PARAM_ENTITY_REF: - if (!dtd.standalone - && notStandaloneHandler - && !notStandaloneHandler(handlerArg)) - return XML_ERROR_NOT_STANDALONE; - dtd.complete = 0; - break; - case XML_ROLE_NONE: - switch (tok) { - case XML_TOK_PI: - eventPtr = s; - eventEndPtr = next; - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - eventPtr = s; - eventEndPtr = next; - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - } - break; - } - if (defaultHandler) { - switch (tok) { - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - case XML_TOK_XML_DECL: - break; - default: - eventPtr = s; - eventEndPtr = next; - reportDefault(parser, encoding, s, next); - } - } - s = next; - } - /* not reached */ -} - -static -enum XML_Error epilogProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) -{ - processor = epilogProcessor; - eventPtr = s; - for (;;) { - const char *next; - int tok = XmlPrologTok(encoding, s, end, &next); - eventEndPtr = next; - switch (tok) { - case XML_TOK_TRAILING_CR: - if (defaultHandler) { - eventEndPtr = end; - reportDefault(parser, encoding, s, end); - } - /* fall through */ - case XML_TOK_NONE: - if (nextPtr) - *nextPtr = end; - return XML_ERROR_NONE; - case XML_TOK_PROLOG_S: - if (defaultHandler) - reportDefault(parser, encoding, s, next); - break; - case XML_TOK_PI: - if (!reportProcessingInstruction(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_COMMENT: - if (!reportComment(parser, encoding, s, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_UNCLOSED_TOKEN; - case XML_TOK_PARTIAL_CHAR: - if (nextPtr) { - *nextPtr = s; - return XML_ERROR_NONE; - } - return XML_ERROR_PARTIAL_CHAR; - default: - return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; - } - eventPtr = s = next; - } -} - -static enum XML_Error -storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); - if (result) - return result; - if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) - poolChop(pool); - if (!poolAppendChar(pool, XML_T('\0'))) - return XML_ERROR_NO_MEMORY; - return XML_ERROR_NONE; -} - -static enum XML_Error -appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, - const char *ptr, const char *end, - STRING_POOL *pool) -{ - const ENCODING *internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - for (;;) { - const char *next; - int tok = XmlAttributeValueTok(enc, ptr, end, &next); - switch (tok) { - case XML_TOK_NONE: - return XML_ERROR_NONE; - case XML_TOK_INVALID: - if (enc == encoding) - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_PARTIAL: - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(enc, ptr); - if (n < 0) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - if (!isCdata - && n == 0x20 /* space */ - && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (!poolAppendChar(pool, buf[i])) - return XML_ERROR_NO_MEMORY; - } - } - break; - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, enc, ptr, next)) - return XML_ERROR_NO_MEMORY; - break; - break; - case XML_TOK_TRAILING_CR: - next = ptr + enc->minBytesPerChar; - /* fall through */ - case XML_TOK_ATTRIBUTE_VALUE_S: - case XML_TOK_DATA_NEWLINE: - if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) - break; - if (!poolAppendChar(pool, 0x20)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_ENTITY_REF: - { - const XML_Char *name; - ENTITY *entity; - XML_Char ch = XmlPredefinedEntityName(enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (ch) { - if (!poolAppendChar(pool, ch)) - return XML_ERROR_NO_MEMORY; - break; - } - name = poolStoreString(&temp2Pool, enc, - ptr + enc->minBytesPerChar, - next - enc->minBytesPerChar); - if (!name) - return XML_ERROR_NO_MEMORY; - entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); - poolDiscard(&temp2Pool); - if (!entity) { - if (dtd.complete) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_UNDEFINED_ENTITY; - } - } - else if (entity->open) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_RECURSIVE_ENTITY_REF; - } - else if (entity->notation) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_BINARY_ENTITY_REF; - } - else if (!entity->textPtr) { - if (enc == encoding) - eventPtr = ptr; - return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; - } - else { - enum XML_Error result; - const XML_Char *textEnd = entity->textPtr + entity->textLen; - entity->open = 1; - result = appendAttributeValue(parser, internalEnc, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); - entity->open = 0; - if (result) - return result; - } - } - break; - default: - abort(); - } - ptr = next; - } - /* not reached */ -} - -static -enum XML_Error storeEntityValue(XML_Parser parser, - const char *entityTextPtr, - const char *entityTextEnd) -{ - const ENCODING *internalEnc; - STRING_POOL *pool = &(dtd.pool); - entityTextPtr += encoding->minBytesPerChar; - entityTextEnd -= encoding->minBytesPerChar; - internalEnc = ns ? XmlGetInternalEncodingNS() : XmlGetInternalEncoding(); - for (;;) { - const char *next; - int tok = XmlEntityValueTok(encoding, entityTextPtr, entityTextEnd, &next); - switch (tok) { - case XML_TOK_PARAM_ENTITY_REF: - eventPtr = entityTextPtr; - return XML_ERROR_SYNTAX; - case XML_TOK_NONE: - if (declEntity) { - declEntity->textPtr = pool->start; - declEntity->textLen = pool->ptr - pool->start; - poolFinish(pool); - } - else - poolDiscard(pool); - return XML_ERROR_NONE; - case XML_TOK_ENTITY_REF: - case XML_TOK_DATA_CHARS: - if (!poolAppend(pool, encoding, entityTextPtr, next)) - return XML_ERROR_NO_MEMORY; - break; - case XML_TOK_TRAILING_CR: - next = entityTextPtr + encoding->minBytesPerChar; - /* fall through */ - case XML_TOK_DATA_NEWLINE: - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = 0xA; - break; - case XML_TOK_CHAR_REF: - { - XML_Char buf[XML_ENCODE_MAX]; - int i; - int n = XmlCharRefNumber(encoding, entityTextPtr); - if (n < 0) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - n = XmlEncode(n, (ICHAR *)buf); - if (!n) { - eventPtr = entityTextPtr; - return XML_ERROR_BAD_CHAR_REF; - } - for (i = 0; i < n; i++) { - if (pool->end == pool->ptr && !poolGrow(pool)) - return XML_ERROR_NO_MEMORY; - *(pool->ptr)++ = buf[i]; - } - } - break; - case XML_TOK_PARTIAL: - eventPtr = entityTextPtr; - return XML_ERROR_INVALID_TOKEN; - case XML_TOK_INVALID: - eventPtr = next; - return XML_ERROR_INVALID_TOKEN; - default: - abort(); - } - entityTextPtr = next; - } - /* not reached */ -} - -static void -normalizeLines(XML_Char *s) -{ - XML_Char *p; - for (;; s++) { - if (*s == XML_T('\0')) - return; - if (*s == 0xD) - break; - } - p = s; - do { - if (*s == 0xD) { - *p++ = 0xA; - if (*++s == 0xA) - s++; - } - else - *p++ = *s++; - } while (*s); - *p = XML_T('\0'); -} - -static int -reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - const XML_Char *target; - XML_Char *data; - const char *tem; - if (!processingInstructionHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - start += enc->minBytesPerChar * 2; - tem = start + XmlNameLength(enc, start); - target = poolStoreString(&tempPool, enc, start, tem); - if (!target) - return 0; - poolFinish(&tempPool); - data = poolStoreString(&tempPool, enc, - XmlSkipS(enc, tem), - end - enc->minBytesPerChar*2); - if (!data) - return 0; - normalizeLines(data); - processingInstructionHandler(handlerArg, target, data); - poolClear(&tempPool); - return 1; -} - -static int -reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - XML_Char *data; - if (!commentHandler) { - if (defaultHandler) - reportDefault(parser, enc, start, end); - return 1; - } - data = poolStoreString(&tempPool, - enc, - start + enc->minBytesPerChar * 4, - end - enc->minBytesPerChar * 3); - if (!data) - return 0; - normalizeLines(data); - commentHandler(handlerArg, data); - poolClear(&tempPool); - return 1; -} - -static void -reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) -{ - if (MUST_CONVERT(enc, s)) { - const char **eventPP; - const char **eventEndPP; - if (enc == encoding) { - eventPP = &eventPtr; - eventEndPP = &eventEndPtr; - } - else { - eventPP = &(openInternalEntities->internalEventPtr); - eventEndPP = &(openInternalEntities->internalEventEndPtr); - } - do { - ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); - *eventEndPP = s; - defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); - *eventPP = s; - } while (s != end); - } - else - defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); -} - - -static int -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, const XML_Char *value) -{ - DEFAULT_ATTRIBUTE *att; - if (type->nDefaultAtts == type->allocDefaultAtts) { - if (type->allocDefaultAtts == 0) { - type->allocDefaultAtts = 8; - type->defaultAtts = malloc(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - else { - type->allocDefaultAtts *= 2; - type->defaultAtts = realloc(type->defaultAtts, - type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); - } - if (!type->defaultAtts) - return 0; - } - att = type->defaultAtts + type->nDefaultAtts; - att->id = attId; - att->value = value; - att->isCdata = isCdata; - if (!isCdata) - attId->maybeTokenized = 1; - type->nDefaultAtts += 1; - return 1; -} - -static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) -{ - const XML_Char *name; - for (name = elementType->name; *name; name++) { - if (*name == XML_T(':')) { - PREFIX *prefix; - const XML_Char *s; - for (s = elementType->name; s != name; s++) { - if (!poolAppendChar(&dtd.pool, *s)) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (!prefix) - return 0; - if (prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - elementType->prefix = prefix; - - } - } - return 1; -} - -static ATTRIBUTE_ID * -getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) -{ - ATTRIBUTE_ID *id; - const XML_Char *name; - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - name = poolStoreString(&dtd.pool, enc, start, end); - if (!name) - return 0; - ++name; - id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); - if (!id) - return 0; - if (id->name != name) - poolDiscard(&dtd.pool); - else { - poolFinish(&dtd.pool); - if (!ns) - ; - else if (name[0] == 'x' - && name[1] == 'm' - && name[2] == 'l' - && name[3] == 'n' - && name[4] == 's' - && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { - if (name[5] == '\0') - id->prefix = &dtd.defaultPrefix; - else - id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); - id->xmlns = 1; - } - else { - int i; - for (i = 0; name[i]; i++) { - if (name[i] == XML_T(':')) { - int j; - for (j = 0; j < i; j++) { - if (!poolAppendChar(&dtd.pool, name[j])) - return 0; - } - if (!poolAppendChar(&dtd.pool, XML_T('\0'))) - return 0; - id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); - if (id->prefix->name == poolStart(&dtd.pool)) - poolFinish(&dtd.pool); - else - poolDiscard(&dtd.pool); - break; - } - } - } - } - return id; -} - -#define CONTEXT_SEP XML_T('\f') - -static -const XML_Char *getContext(XML_Parser parser) -{ - HASH_TABLE_ITER iter; - int needSep = 0; - - if (dtd.defaultPrefix.binding) { - int i; - int len; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = dtd.defaultPrefix.binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) - return 0; - needSep = 1; - } - - hashTableIterInit(&iter, &(dtd.prefixes)); - for (;;) { - int i; - int len; - const XML_Char *s; - PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); - if (!prefix) - break; - if (!prefix->binding) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = prefix->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - if (!poolAppendChar(&tempPool, XML_T('='))) - return 0; - len = prefix->binding->uriLen; - if (namespaceSeparator != XML_T('\0')) - len--; - for (i = 0; i < len; i++) - if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) - return 0; - needSep = 1; - } - - - hashTableIterInit(&iter, &(dtd.generalEntities)); - for (;;) { - const XML_Char *s; - ENTITY *e = (ENTITY *)hashTableIterNext(&iter); - if (!e) - break; - if (!e->open) - continue; - if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) - return 0; - for (s = e->name; *s; s++) - if (!poolAppendChar(&tempPool, *s)) - return 0; - needSep = 1; - } - - if (!poolAppendChar(&tempPool, XML_T('\0'))) - return 0; - return tempPool.start; -} - -static -void normalizePublicId(XML_Char *publicId) -{ - XML_Char *p = publicId; - XML_Char *s; - for (s = publicId; *s; s++) { - switch (*s) { - case 0x20: - case 0xD: - case 0xA: - if (p != publicId && p[-1] != 0x20) - *p++ = 0x20; - break; - default: - *p++ = *s; - } - } - if (p != publicId && p[-1] == 0x20) - --p; - *p = XML_T('\0'); -} - -static int dtdInit(DTD *p) -{ - poolInit(&(p->pool)); - hashTableInit(&(p->generalEntities)); - hashTableInit(&(p->elementTypes)); - hashTableInit(&(p->attributeIds)); - hashTableInit(&(p->prefixes)); - p->complete = 1; - p->standalone = 0; - p->base = 0; - p->defaultPrefix.name = 0; - p->defaultPrefix.binding = 0; - return 1; -} - -static void dtdDestroy(DTD *p) -{ - HASH_TABLE_ITER iter; - hashTableIterInit(&iter, &(p->elementTypes)); - for (;;) { - ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); - if (!e) - break; - if (e->allocDefaultAtts != 0) - g_free(e->defaultAtts); - } - hashTableDestroy(&(p->generalEntities)); - hashTableDestroy(&(p->elementTypes)); - hashTableDestroy(&(p->attributeIds)); - hashTableDestroy(&(p->prefixes)); - poolDestroy(&(p->pool)); -} - -static -void poolInit(STRING_POOL *pool) -{ - pool->blocks = 0; - pool->freeBlocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolClear(STRING_POOL *pool) -{ - if (!pool->freeBlocks) - pool->freeBlocks = pool->blocks; - else { - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - p->next = pool->freeBlocks; - pool->freeBlocks = p; - p = tem; - } - } - pool->blocks = 0; - pool->start = 0; - pool->ptr = 0; - pool->end = 0; -} - -static -void poolDestroy(STRING_POOL *pool) -{ - BLOCK *p = pool->blocks; - while (p) { - BLOCK *tem = p->next; - g_free(p); - p = tem; - } - pool->blocks = 0; - p = pool->freeBlocks; - while (p) { - BLOCK *tem = p->next; - g_free(p); - p = tem; - } - pool->freeBlocks = 0; - pool->ptr = 0; - pool->start = 0; - pool->end = 0; -} - -static -XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!pool->ptr && !poolGrow(pool)) - return 0; - for (;;) { - XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); - if (ptr == end) - break; - if (!poolGrow(pool)) - return 0; - } - return pool->start; -} - -static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) -{ - do { - if (!poolAppendChar(pool, *s)) - return 0; - } while (*s++); - s = pool->start; - poolFinish(pool); - return s; -} - -static -XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, - const char *ptr, const char *end) -{ - if (!poolAppend(pool, enc, ptr, end)) - return 0; - if (pool->ptr == pool->end && !poolGrow(pool)) - return 0; - *(pool->ptr)++ = 0; - return pool->start; -} - -static -int poolGrow(STRING_POOL *pool) -{ - if (pool->freeBlocks) { - if (pool->start == 0) { - pool->blocks = pool->freeBlocks; - pool->freeBlocks = pool->freeBlocks->next; - pool->blocks->next = 0; - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - pool->ptr = pool->start; - return 1; - } - if (pool->end - pool->start < pool->freeBlocks->size) { - BLOCK *tem = pool->freeBlocks->next; - pool->freeBlocks->next = pool->blocks; - pool->blocks = pool->freeBlocks; - pool->freeBlocks = tem; - memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + pool->blocks->size; - return 1; - } - } - if (pool->blocks && pool->start == pool->blocks->s) { - int blockSize = (pool->end - pool->start)*2; - pool->blocks = realloc(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!pool->blocks) - return 0; - pool->blocks->size = blockSize; - pool->ptr = pool->blocks->s + (pool->ptr - pool->start); - pool->start = pool->blocks->s; - pool->end = pool->start + blockSize; - } - else { - BLOCK *tem; - int blockSize = pool->end - pool->start; - if (blockSize < INIT_BLOCK_SIZE) - blockSize = INIT_BLOCK_SIZE; - else - blockSize *= 2; - tem = malloc(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); - if (!tem) - return 0; - tem->size = blockSize; - tem->next = pool->blocks; - pool->blocks = tem; - memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); - pool->ptr = tem->s + (pool->ptr - pool->start); - pool->start = tem->s; - pool->end = tem->s + blockSize; - } - return 1; -} diff --git a/protocols/jabber/xmlparse.h b/protocols/jabber/xmlparse.h deleted file mode 100644 index f39edb8c..00000000 --- a/protocols/jabber/xmlparse.h +++ /dev/null @@ -1,476 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlParse_INCLUDED -#define XmlParse_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLPARSEAPI -#define XMLPARSEAPI /* as nothing */ -#endif - -typedef void *XML_Parser; - -#ifdef XML_UNICODE_WCHAR_T - -/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t -uses Unicode. */ -/* Information is UTF-16 encoded as wchar_ts */ - -#ifndef XML_UNICODE -#define XML_UNICODE -#endif - -#include <stddef.h> -typedef wchar_t XML_Char; -typedef wchar_t XML_LChar; - -#else /* not XML_UNICODE_WCHAR_T */ - -#ifdef XML_UNICODE - -/* Information is UTF-16 encoded as unsigned shorts */ -typedef unsigned short XML_Char; -typedef char XML_LChar; - -#else /* not XML_UNICODE */ - -/* Information is UTF-8 encoded. */ -typedef char XML_Char; -typedef char XML_LChar; - -#endif /* not XML_UNICODE */ - -#endif /* not XML_UNICODE_WCHAR_T */ - - -/* Constructs a new parser; encoding is the encoding specified by the external -protocol or null if there is none specified. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreate(const XML_Char *encoding); - -/* Constructs a new parser and namespace processor. Element type names -and attribute names that belong to a namespace will be expanded; -unprefixed attribute names are never expanded; unprefixed element type -names are expanded only if there is a default namespace. The expanded -name is the concatenation of the namespace URI, the namespace separator character, -and the local part of the name. If the namespace separator is '\0' then -the namespace URI and the local part will be concatenated without any -separator. When a namespace is not declared, the name and prefix will be -passed through without expansion. */ - -XML_Parser XMLPARSEAPI -XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); - - -/* atts is array of name/value pairs, terminated by 0; - names and values are 0 terminated. */ - -typedef void (*XML_StartElementHandler)(void *userData, - const XML_Char *name, - const XML_Char **atts); - -typedef void (*XML_EndElementHandler)(void *userData, - const XML_Char *name); - -/* s is not 0 terminated. */ -typedef void (*XML_CharacterDataHandler)(void *userData, - const XML_Char *s, - int len); - -/* target and data are 0 terminated */ -typedef void (*XML_ProcessingInstructionHandler)(void *userData, - const XML_Char *target, - const XML_Char *data); - -/* data is 0 terminated */ -typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); - -typedef void (*XML_StartCdataSectionHandler)(void *userData); -typedef void (*XML_EndCdataSectionHandler)(void *userData); - -/* This is called for any characters in the XML document for -which there is no applicable handler. This includes both -characters that are part of markup which is of a kind that is -not reported (comments, markup declarations), or characters -that are part of a construct which could be reported but -for which no handler has been supplied. The characters are passed -exactly as they were in the XML document except that -they will be encoded in UTF-8. Line boundaries are not normalized. -Note that a byte order mark character is not passed to the default handler. -There are no guarantees about how characters are divided between calls -to the default handler: for example, a comment might be split between -multiple calls. */ - -typedef void (*XML_DefaultHandler)(void *userData, - const XML_Char *s, - int len); - -/* This is called for a declaration of an unparsed (NDATA) -entity. The base argument is whatever was set by XML_SetBase. -The entityName, systemId and notationName arguments will never be null. -The other arguments may be. */ - -typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName); - -/* This is called for a declaration of notation. -The base argument is whatever was set by XML_SetBase. -The notationName will never be null. The other arguments can be. */ - -typedef void (*XML_NotationDeclHandler)(void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* When namespace processing is enabled, these are called once for -each namespace declaration. The call to the start and end element -handlers occur between the calls to the start and end namespace -declaration handlers. For an xmlns attribute, prefix will be null. -For an xmlns="" attribute, uri will be null. */ - -typedef void (*XML_StartNamespaceDeclHandler)(void *userData, - const XML_Char *prefix, - const XML_Char *uri); - -typedef void (*XML_EndNamespaceDeclHandler)(void *userData, - const XML_Char *prefix); - -/* This is called if the document is not standalone (it has an -external subset or a reference to a parameter entity, but does not -have standalone="yes"). If this handler returns 0, then processing -will not continue, and the parser will return a -XML_ERROR_NOT_STANDALONE error. */ - -typedef int (*XML_NotStandaloneHandler)(void *userData); - -/* This is called for a reference to an external parsed general entity. -The referenced entity is not automatically parsed. -The application can parse it immediately or later using -XML_ExternalEntityParserCreate. -The parser argument is the parser parsing the entity containing the reference; -it can be passed as the parser argument to XML_ExternalEntityParserCreate. -The systemId argument is the system identifier as specified in the entity declaration; -it will not be null. -The base argument is the system identifier that should be used as the base for -resolving systemId if systemId was relative; this is set by XML_SetBase; -it may be null. -The publicId argument is the public identifier as specified in the entity declaration, -or null if none was specified; the whitespace in the public identifier -will have been normalized as required by the XML spec. -The context argument specifies the parsing context in the format -expected by the context argument to -XML_ExternalEntityParserCreate; context is valid only until the handler -returns, so if the referenced entity is to be parsed later, it must be copied. -The handler should return 0 if processing should not continue because of -a fatal error in the handling of the external entity. -In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING -error. -Note that unlike other handlers the first argument is the parser, not userData. */ - -typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId); - -/* This structure is filled in by the XML_UnknownEncodingHandler -to provide information to the parser about encodings that are unknown -to the parser. -The map[b] member gives information about byte sequences -whose first byte is b. -If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. -If map[b] is -1, then the byte sequence is malformed. -If map[b] is -n, where n >= 2, then b is the first byte of an n-byte -sequence that encodes a single Unicode scalar value. -The data member will be passed as the first argument to the convert function. -The convert function is used to convert multibyte sequences; -s will point to a n-byte sequence where map[(unsigned char)*s] == -n. -The convert function must return the Unicode scalar value -represented by this byte sequence or -1 if the byte sequence is malformed. -The convert function may be null if the encoding is a single-byte encoding, -that is if map[b] >= -1 for all bytes b. -When the parser is finished with the encoding, then if release is not null, -it will call release passing it the data member; -once release has been called, the convert function will not be called again. - -Expat places certain restrictions on the encodings that are supported -using this mechanism. - -1. Every ASCII character that can appear in a well-formed XML document, -other than the characters - - $@\^`{}~ - -must be represented by a single byte, and that byte must be the -same byte that represents that character in ASCII. - -2. No character may require more than 4 bytes to encode. - -3. All characters encoded must have Unicode scalar values <= 0xFFFF, -(ie characters that would be encoded by surrogates in UTF-16 -are not allowed). Note that this restriction doesn't apply to -the built-in support for UTF-8 and UTF-16. - -4. No Unicode character may be encoded by more than one distinct sequence -of bytes. */ - -typedef struct { - int map[256]; - void *data; - int (*convert)(void *data, const char *s); - void (*release)(void *data); -} XML_Encoding; - -/* This is called for an encoding that is unknown to the parser. -The encodingHandlerData argument is that which was passed as the -second argument to XML_SetUnknownEncodingHandler. -The name argument gives the name of the encoding as specified in -the encoding declaration. -If the callback can provide information about the encoding, -it must fill in the XML_Encoding structure, and return 1. -Otherwise it must return 0. -If info does not describe a suitable encoding, -then the parser will return an XML_UNKNOWN_ENCODING error. */ - -typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info); - -void XMLPARSEAPI -XML_SetElementHandler(XML_Parser parser, - XML_StartElementHandler start, - XML_EndElementHandler end); - -void XMLPARSEAPI -XML_SetCharacterDataHandler(XML_Parser parser, - XML_CharacterDataHandler handler); - -void XMLPARSEAPI -XML_SetProcessingInstructionHandler(XML_Parser parser, - XML_ProcessingInstructionHandler handler); -void XMLPARSEAPI -XML_SetCommentHandler(XML_Parser parser, - XML_CommentHandler handler); - -void XMLPARSEAPI -XML_SetCdataSectionHandler(XML_Parser parser, - XML_StartCdataSectionHandler start, - XML_EndCdataSectionHandler end); - -/* This sets the default handler and also inhibits expansion of internal entities. -The entity reference will be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandler(XML_Parser parser, - XML_DefaultHandler handler); - -/* This sets the default handler but does not inhibit expansion of internal entities. -The entity reference will not be passed to the default handler. */ - -void XMLPARSEAPI -XML_SetDefaultHandlerExpand(XML_Parser parser, - XML_DefaultHandler handler); - -void XMLPARSEAPI -XML_SetUnparsedEntityDeclHandler(XML_Parser parser, - XML_UnparsedEntityDeclHandler handler); - -void XMLPARSEAPI -XML_SetNotationDeclHandler(XML_Parser parser, - XML_NotationDeclHandler handler); - -void XMLPARSEAPI -XML_SetNamespaceDeclHandler(XML_Parser parser, - XML_StartNamespaceDeclHandler start, - XML_EndNamespaceDeclHandler end); - -void XMLPARSEAPI -XML_SetNotStandaloneHandler(XML_Parser parser, - XML_NotStandaloneHandler handler); - -void XMLPARSEAPI -XML_SetExternalEntityRefHandler(XML_Parser parser, - XML_ExternalEntityRefHandler handler); - -/* If a non-null value for arg is specified here, then it will be passed -as the first argument to the external entity ref handler instead -of the parser object. */ -void XMLPARSEAPI -XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); - -void XMLPARSEAPI -XML_SetUnknownEncodingHandler(XML_Parser parser, - XML_UnknownEncodingHandler handler, - void *encodingHandlerData); - -/* This can be called within a handler for a start element, end element, -processing instruction or character data. It causes the corresponding -markup to be passed to the default handler. */ -void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser); - -/* This value is passed as the userData argument to callbacks. */ -void XMLPARSEAPI -XML_SetUserData(XML_Parser parser, void *userData); - -/* Returns the last value set by XML_SetUserData or null. */ -#define XML_GetUserData(parser) (*(void **)(parser)) - -/* This is equivalent to supplying an encoding argument -to XML_CreateParser. It must not be called after XML_Parse -or XML_ParseBuffer. */ - -int XMLPARSEAPI -XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); - -/* If this function is called, then the parser will be passed -as the first argument to callbacks instead of userData. -The userData will still be accessible using XML_GetUserData. */ - -void XMLPARSEAPI -XML_UseParserAsHandlerArg(XML_Parser parser); - -/* Sets the base to be used for resolving relative URIs in system identifiers in -declarations. Resolving relative identifiers is left to the application: -this value will be passed through as the base argument to the -XML_ExternalEntityRefHandler, XML_NotationDeclHandler -and XML_UnparsedEntityDeclHandler. The base argument will be copied. -Returns zero if out of memory, non-zero otherwise. */ - -int XMLPARSEAPI -XML_SetBase(XML_Parser parser, const XML_Char *base); - -const XML_Char XMLPARSEAPI * -XML_GetBase(XML_Parser parser); - -/* Returns the number of the attributes passed in last call to the -XML_StartElementHandler that were specified in the start-tag rather -than defaulted. */ - -int XMLPARSEAPI XML_GetSpecifiedAttributeCount(XML_Parser parser); - -/* Parses some input. Returns 0 if a fatal error is detected. -The last call to XML_Parse must have isFinal true; -len may be zero for this call (or any other). */ -int XMLPARSEAPI -XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); - -/* Creates an XML_Parser object that can parse an external general entity; -context is a '\0'-terminated string specifying the parse context; -encoding is a '\0'-terminated string giving the name of the externally specified encoding, -or null if there is no externally specified encoding. -The context string consists of a sequence of tokens separated by formfeeds (\f); -a token consisting of a name specifies that the general entity of the name -is open; a token of the form prefix=uri specifies the namespace for a particular -prefix; a token of the form =uri specifies the default namespace. -This can be called at any point after the first call to an ExternalEntityRefHandler -so longer as the parser has not yet been freed. -The new parser is completely independent and may safely be used in a separate thread. -The handlers and userData are initialized from the parser argument. -Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */ -XML_Parser XMLPARSEAPI -XML_ExternalEntityParserCreate(XML_Parser parser, - const XML_Char *context, - const XML_Char *encoding); - -enum XML_Error { - XML_ERROR_NONE, - XML_ERROR_NO_MEMORY, - XML_ERROR_SYNTAX, - XML_ERROR_NO_ELEMENTS, - XML_ERROR_INVALID_TOKEN, - XML_ERROR_UNCLOSED_TOKEN, - XML_ERROR_PARTIAL_CHAR, - XML_ERROR_TAG_MISMATCH, - XML_ERROR_DUPLICATE_ATTRIBUTE, - XML_ERROR_JUNK_AFTER_DOC_ELEMENT, - XML_ERROR_PARAM_ENTITY_REF, - XML_ERROR_UNDEFINED_ENTITY, - XML_ERROR_RECURSIVE_ENTITY_REF, - XML_ERROR_ASYNC_ENTITY, - XML_ERROR_BAD_CHAR_REF, - XML_ERROR_BINARY_ENTITY_REF, - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, - XML_ERROR_MISPLACED_XML_PI, - XML_ERROR_UNKNOWN_ENCODING, - XML_ERROR_INCORRECT_ENCODING, - XML_ERROR_UNCLOSED_CDATA_SECTION, - XML_ERROR_EXTERNAL_ENTITY_HANDLING, - XML_ERROR_NOT_STANDALONE -}; - -/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode -returns information about the error. */ - -enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser); - -/* These functions return information about the current parse location. -They may be called when XML_Parse or XML_ParseBuffer return 0; -in this case the location is the location of the character at which -the error was detected. -They may also be called from any other callback called to report -some parse event; in this the location is the location of the first -of the sequence of characters that generated the event. */ - -int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser); -int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser); -long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser); - -/* Return the number of bytes in the current event. -Returns 0 if the event is in an internal entity. */ - -int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser); - -/* For backwards compatibility with previous versions. */ -#define XML_GetErrorLineNumber XML_GetCurrentLineNumber -#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber -#define XML_GetErrorByteIndex XML_GetCurrentByteIndex - -/* Frees memory used by the parser. */ -void XMLPARSEAPI -XML_ParserFree(XML_Parser parser); - -/* Returns a string describing the error. */ -const XML_LChar XMLPARSEAPI *XML_ErrorString(int code); - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlParse_INCLUDED */ diff --git a/protocols/jabber/xmlrole.c b/protocols/jabber/xmlrole.c deleted file mode 100644 index 320749e8..00000000 --- a/protocols/jabber/xmlrole.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmlrole.h" - -/* Doesn't check: - - that ,| are not mixed in a model group - content of literals - -*/ - -#ifndef MIN_BYTES_PER_CHAR -#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) -#endif - -typedef int PROLOG_HANDLER(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - -static PROLOG_HANDLER -prolog0, prolog1, prolog2, -doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, -internalSubset, -entity0, entity1, entity2, entity3, entity4, entity5, entity6, -entity7, entity8, entity9, -notation0, notation1, notation2, notation3, notation4, -attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, -attlist7, attlist8, attlist9, -element0, element1, element2, element3, element4, element5, element6, -element7, -declClose, -error; - -static -int syntaxError(PROLOG_STATE *); - -static -int prolog0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_XML_DECL: - state->handler = prolog1; - return XML_ROLE_XML_DECL; - case XML_TOK_PI: - state->handler = prolog1; - return XML_ROLE_NONE; - case XML_TOK_COMMENT: - state->handler = prolog1; - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - case XML_TOK_BOM: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (!XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "DOCTYPE")) - break; - state->handler = doctype0; - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int prolog2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_INSTANCE_START: - state->handler = error; - return XML_ROLE_INSTANCE_START; - } - return syntaxError(state); -} - -static -int doctype0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = doctype1; - return XML_ROLE_DOCTYPE_NAME; - } - return syntaxError(state); -} - -static -int doctype1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = doctype3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = doctype2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int doctype2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype3; - return XML_ROLE_DOCTYPE_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int doctype3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = doctype4; - return XML_ROLE_DOCTYPE_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int doctype4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_BRACKET: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int doctype5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = prolog2; - return XML_ROLE_DOCTYPE_CLOSE; - } - return syntaxError(state); -} - -static -int internalSubset(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_OPEN: - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ENTITY")) { - state->handler = entity0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ATTLIST")) { - state->handler = attlist0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "ELEMENT")) { - state->handler = element0; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, - ptr + 2 * MIN_BYTES_PER_CHAR(enc), - "NOTATION")) { - state->handler = notation0; - return XML_ROLE_NONE; - } - break; - case XML_TOK_PI: - case XML_TOK_COMMENT: - return XML_ROLE_NONE; - case XML_TOK_PARAM_ENTITY_REF: - return XML_ROLE_PARAM_ENTITY_REF; - case XML_TOK_CLOSE_BRACKET: - state->handler = doctype5; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int entity0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_PERCENT: - state->handler = entity1; - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity2; - return XML_ROLE_GENERAL_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = entity7; - return XML_ROLE_PARAM_ENTITY_NAME; - } - return syntaxError(state); -} - -static -int entity2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity4; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity3; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity4; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - - -static -int entity4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity5; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int entity5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "NDATA")) { - state->handler = entity6; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int entity6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = declClose; - return XML_ROLE_ENTITY_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int entity7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = entity9; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = entity8; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_VALUE; - } - return syntaxError(state); -} - -static -int entity8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = entity9; - return XML_ROLE_ENTITY_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int entity9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_ENTITY_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = notation1; - return XML_ROLE_NOTATION_NAME; - } - return syntaxError(state); -} - -static -int notation1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "SYSTEM")) { - state->handler = notation3; - return XML_ROLE_NONE; - } - if (XmlNameMatchesAscii(enc, ptr, "PUBLIC")) { - state->handler = notation2; - return XML_ROLE_NONE; - } - break; - } - return syntaxError(state); -} - -static -int notation2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = notation4; - return XML_ROLE_NOTATION_PUBLIC_ID; - } - return syntaxError(state); -} - -static -int notation3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int notation4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = declClose; - return XML_ROLE_NOTATION_SYSTEM_ID; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NOTATION_NO_SYSTEM_ID; - } - return syntaxError(state); -} - -static -int attlist0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist1; - return XML_ROLE_ATTLIST_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int attlist1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist2; - return XML_ROLE_ATTRIBUTE_NAME; - } - return syntaxError(state); -} - -static -int attlist2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - { - static const char *types[] = { - "CDATA", - "ID", - "IDREF", - "IDREFS", - "ENTITY", - "ENTITIES", - "NMTOKEN", - "NMTOKENS", - }; - int i; - for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) - if (XmlNameMatchesAscii(enc, ptr, types[i])) { - state->handler = attlist8; - return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; - } - } - if (XmlNameMatchesAscii(enc, ptr, "NOTATION")) { - state->handler = attlist5; - return XML_ROLE_NONE; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NMTOKEN: - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = attlist4; - return XML_ROLE_ATTRIBUTE_ENUM_VALUE; - } - return syntaxError(state); -} - -static -int attlist4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist3; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int attlist5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - - -static -int attlist6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - state->handler = attlist7; - return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; - } - return syntaxError(state); -} - -static -int attlist7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->handler = attlist8; - return XML_ROLE_NONE; - case XML_TOK_OR: - state->handler = attlist6; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -/* default value */ -static -int attlist8(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "IMPLIED")) { - state->handler = attlist1; - return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "REQUIRED")) { - state->handler = attlist1; - return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; - } - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "FIXED")) { - state->handler = attlist9; - return XML_ROLE_NONE; - } - break; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int attlist9(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_LITERAL: - state->handler = attlist1; - return XML_ROLE_FIXED_ATTRIBUTE_VALUE; - } - return syntaxError(state); -} - -static -int element0(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element1; - return XML_ROLE_ELEMENT_NAME; - } - return syntaxError(state); -} - -static -int element1(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - if (XmlNameMatchesAscii(enc, ptr, "EMPTY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_EMPTY; - } - if (XmlNameMatchesAscii(enc, ptr, "ANY")) { - state->handler = declClose; - return XML_ROLE_CONTENT_ANY; - } - break; - case XML_TOK_OPEN_PAREN: - state->handler = element2; - state->level = 1; - return XML_ROLE_GROUP_OPEN; - } - return syntaxError(state); -} - -static -int element2(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_POUND_NAME: - if (XmlNameMatchesAscii(enc, - ptr + MIN_BYTES_PER_CHAR(enc), - "PCDATA")) { - state->handler = element3; - return XML_ROLE_CONTENT_PCDATA; - } - break; - case XML_TOK_OPEN_PAREN: - state->level = 2; - state->handler = element6; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element3(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element4(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element5; - return XML_ROLE_CONTENT_ELEMENT; - } - return syntaxError(state); -} - -static -int element5(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_OR: - state->handler = element4; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -static -int element6(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_OPEN_PAREN: - state->level += 1; - return XML_ROLE_GROUP_OPEN; - case XML_TOK_NAME: - case XML_TOK_PREFIXED_NAME: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT; - case XML_TOK_NAME_QUESTION: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_OPT; - case XML_TOK_NAME_ASTERISK: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_REP; - case XML_TOK_NAME_PLUS: - state->handler = element7; - return XML_ROLE_CONTENT_ELEMENT_PLUS; - } - return syntaxError(state); -} - -static -int element7(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_CLOSE_PAREN: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE; - case XML_TOK_CLOSE_PAREN_ASTERISK: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_REP; - case XML_TOK_CLOSE_PAREN_QUESTION: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_OPT; - case XML_TOK_CLOSE_PAREN_PLUS: - state->level -= 1; - if (state->level == 0) - state->handler = declClose; - return XML_ROLE_GROUP_CLOSE_PLUS; - case XML_TOK_COMMA: - state->handler = element6; - return XML_ROLE_GROUP_SEQUENCE; - case XML_TOK_OR: - state->handler = element6; - return XML_ROLE_GROUP_CHOICE; - } - return syntaxError(state); -} - -static -int declClose(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_PROLOG_S: - return XML_ROLE_NONE; - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return XML_ROLE_NONE; - } - return syntaxError(state); -} - -#if 0 - -static -int ignore(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - switch (tok) { - case XML_TOK_DECL_CLOSE: - state->handler = internalSubset; - return 0; - default: - return XML_ROLE_NONE; - } - return syntaxError(state); -} -#endif - -static -int error(PROLOG_STATE *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc) -{ - return XML_ROLE_NONE; -} - -static -int syntaxError(PROLOG_STATE *state) -{ - state->handler = error; - return XML_ROLE_ERROR; -} - -void XmlPrologStateInit(PROLOG_STATE *state) -{ - state->handler = prolog0; -} diff --git a/protocols/jabber/xmlrole.h b/protocols/jabber/xmlrole.h deleted file mode 100644 index 877c40ba..00000000 --- a/protocols/jabber/xmlrole.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlRole_INCLUDED -#define XmlRole_INCLUDED 1 - -#include "xmltok.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - XML_ROLE_ERROR = -1, - XML_ROLE_NONE = 0, - XML_ROLE_XML_DECL, - XML_ROLE_INSTANCE_START, - XML_ROLE_DOCTYPE_NAME, - XML_ROLE_DOCTYPE_SYSTEM_ID, - XML_ROLE_DOCTYPE_PUBLIC_ID, - XML_ROLE_DOCTYPE_CLOSE, - XML_ROLE_GENERAL_ENTITY_NAME, - XML_ROLE_PARAM_ENTITY_NAME, - XML_ROLE_ENTITY_VALUE, - XML_ROLE_ENTITY_SYSTEM_ID, - XML_ROLE_ENTITY_PUBLIC_ID, - XML_ROLE_ENTITY_NOTATION_NAME, - XML_ROLE_NOTATION_NAME, - XML_ROLE_NOTATION_SYSTEM_ID, - XML_ROLE_NOTATION_NO_SYSTEM_ID, - XML_ROLE_NOTATION_PUBLIC_ID, - XML_ROLE_ATTRIBUTE_NAME, - XML_ROLE_ATTRIBUTE_TYPE_CDATA, - XML_ROLE_ATTRIBUTE_TYPE_ID, - XML_ROLE_ATTRIBUTE_TYPE_IDREF, - XML_ROLE_ATTRIBUTE_TYPE_IDREFS, - XML_ROLE_ATTRIBUTE_TYPE_ENTITY, - XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, - XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, - XML_ROLE_ATTRIBUTE_ENUM_VALUE, - XML_ROLE_ATTRIBUTE_NOTATION_VALUE, - XML_ROLE_ATTLIST_ELEMENT_NAME, - XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, - XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, - XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, - XML_ROLE_FIXED_ATTRIBUTE_VALUE, - XML_ROLE_ELEMENT_NAME, - XML_ROLE_CONTENT_ANY, - XML_ROLE_CONTENT_EMPTY, - XML_ROLE_CONTENT_PCDATA, - XML_ROLE_GROUP_OPEN, - XML_ROLE_GROUP_CLOSE, - XML_ROLE_GROUP_CLOSE_REP, - XML_ROLE_GROUP_CLOSE_OPT, - XML_ROLE_GROUP_CLOSE_PLUS, - XML_ROLE_GROUP_CHOICE, - XML_ROLE_GROUP_SEQUENCE, - XML_ROLE_CONTENT_ELEMENT, - XML_ROLE_CONTENT_ELEMENT_REP, - XML_ROLE_CONTENT_ELEMENT_OPT, - XML_ROLE_CONTENT_ELEMENT_PLUS, - XML_ROLE_PARAM_ENTITY_REF -}; - -typedef struct prolog_state { - int (*handler)(struct prolog_state *state, - int tok, - const char *ptr, - const char *end, - const ENCODING *enc); - unsigned level; -} PROLOG_STATE; - -void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *); - -#define XmlTokenRole(state, tok, ptr, end, enc) \ - (((state)->handler)(state, tok, ptr, end, enc)) - -#ifdef __cplusplus -} -#endif - -#endif /* not XmlRole_INCLUDED */ diff --git a/protocols/jabber/xmltok.c b/protocols/jabber/xmltok.c deleted file mode 100644 index 8b7ae15e..00000000 --- a/protocols/jabber/xmltok.c +++ /dev/null @@ -1,1518 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#include "xmldef.h" -#include "xmltok.h" -#include "nametab.h" - -#define VTABLE1 \ - { PREFIX(prologTok), PREFIX(contentTok), PREFIX(cdataSectionTok) }, \ - { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ - PREFIX(sameName), \ - PREFIX(nameMatchesAscii), \ - PREFIX(nameLength), \ - PREFIX(skipS), \ - PREFIX(getAtts), \ - PREFIX(charRefNumber), \ - PREFIX(predefinedEntityName), \ - PREFIX(updatePosition), \ - PREFIX(isPublicId) - -#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) - -#define UCS2_GET_NAMING(pages, hi, lo) \ - (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) - -/* A 2 byte UTF-8 representation splits the characters 11 bits -between the bottom 5 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING2(pages, byte) \ - (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ - + ((((byte)[0]) & 3) << 1) \ - + ((((byte)[1]) >> 5) & 1)] \ - & (1 << (((byte)[1]) & 0x1F))) - -/* A 3 byte UTF-8 representation splits the characters 16 bits -between the bottom 4, 6 and 6 bits of the bytes. -We need 8 bits to index into pages, 3 bits to add to that index and -5 bits to generate the mask. */ -#define UTF8_GET_NAMING3(pages, byte) \ - (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ - + ((((byte)[1]) >> 2) & 0xF)] \ - << 3) \ - + ((((byte)[1]) & 3) << 1) \ - + ((((byte)[2]) >> 5) & 1)] \ - & (1 << (((byte)[2]) & 0x1F))) - -#define UTF8_GET_NAMING(pages, p, n) \ - ((n) == 2 \ - ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ - : ((n) == 3 \ - ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ - : 0)) - -#define UTF8_INVALID3(p) \ - ((*p) == 0xED \ - ? (((p)[1] & 0x20) != 0) \ - : ((*p) == 0xEF \ - ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ - : 0)) - -#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) - -static -int isNever(const ENCODING *enc, const char *p) -{ - return 0; -} - -static -int utf8_isName2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); -} - -static -int utf8_isName3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); -} - -#define utf8_isName4 isNever - -static -int utf8_isNmstrt2(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); -} - -static -int utf8_isNmstrt3(const ENCODING *enc, const char *p) -{ - return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); -} - -#define utf8_isNmstrt4 isNever - -#define utf8_isInvalid2 isNever - -static -int utf8_isInvalid3(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID3((const unsigned char *)p); -} - -static -int utf8_isInvalid4(const ENCODING *enc, const char *p) -{ - return UTF8_INVALID4((const unsigned char *)p); -} - -struct normal_encoding { - ENCODING enc; - unsigned char type[256]; -#ifdef XML_MIN_SIZE - int (*byteType)(const ENCODING *, const char *); - int (*isNameMin)(const ENCODING *, const char *); - int (*isNmstrtMin)(const ENCODING *, const char *); - int (*byteToAscii)(const ENCODING *, const char *); - int (*charMatches)(const ENCODING *, const char *, int); -#endif /* XML_MIN_SIZE */ - int (*isName2)(const ENCODING *, const char *); - int (*isName3)(const ENCODING *, const char *); - int (*isName4)(const ENCODING *, const char *); - int (*isNmstrt2)(const ENCODING *, const char *); - int (*isNmstrt3)(const ENCODING *, const char *); - int (*isNmstrt4)(const ENCODING *, const char *); - int (*isInvalid2)(const ENCODING *, const char *); - int (*isInvalid3)(const ENCODING *, const char *); - int (*isInvalid4)(const ENCODING *, const char *); -}; - -#ifdef XML_MIN_SIZE - -#define STANDARD_VTABLE(E) \ - E ## byteType, \ - E ## isNameMin, \ - E ## isNmstrtMin, \ - E ## byteToAscii, \ - E ## charMatches, - -#else - -#define STANDARD_VTABLE(E) /* as nothing */ - -#endif - -#define NORMAL_VTABLE(E) \ - E ## isName2, \ - E ## isName3, \ - E ## isName4, \ - E ## isNmstrt2, \ - E ## isNmstrt3, \ - E ## isNmstrt4, \ - E ## isInvalid2, \ - E ## isInvalid3, \ - E ## isInvalid4 - -static int checkCharRefNumber(int); - -#include "xmltok_impl.h" - -#ifdef XML_MIN_SIZE -#define sb_isNameMin isNever -#define sb_isNmstrtMin isNever -#endif - -#ifdef XML_MIN_SIZE -#define MINBPC(enc) ((enc)->minBytesPerChar) -#else -/* minimum bytes per character */ -#define MINBPC(enc) 1 -#endif - -#define SB_BYTE_TYPE(enc, p) \ - (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) - -#ifdef XML_MIN_SIZE -static -int sb_byteType(const ENCODING *enc, const char *p) -{ - return SB_BYTE_TYPE(enc, p); -} -#define BYTE_TYPE(enc, p) \ - (((const struct normal_encoding *)(enc))->byteType(enc, p)) -#else -#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) -#endif - -#ifdef XML_MIN_SIZE -#define BYTE_TO_ASCII(enc, p) \ - (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) -static -int sb_byteToAscii(const ENCODING *enc, const char *p) -{ - return *p; -} -#else -#define BYTE_TO_ASCII(enc, p) (*p) -#endif - -#define IS_NAME_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) -#define IS_NMSTRT_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) -#define IS_INVALID_CHAR(enc, p, n) \ - (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) - -#ifdef XML_MIN_SIZE -#define IS_NAME_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ - (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) -#else -#define IS_NAME_CHAR_MINBPC(enc, p) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) -#endif - -#ifdef XML_MIN_SIZE -#define CHAR_MATCHES(enc, p, c) \ - (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) -static -int sb_charMatches(const ENCODING *enc, const char *p, int c) -{ - return *p == c; -} -#else -/* c is an ASCII character */ -#define CHAR_MATCHES(enc, p, c) (*(p) == c) -#endif - -#define PREFIX(ident) normal_ ## ident -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ - UTF8_cval1 = 0x00, - UTF8_cval2 = 0xc0, - UTF8_cval3 = 0xe0, - UTF8_cval4 = 0xf0 -}; - -static -void utf8_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char *to; - const char *from; - if (fromLim - *fromP > toLim - *toP) { - /* Avoid copying partial characters. */ - for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) - if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) - break; - } - for (to = *toP, from = *fromP; from != fromLim; from++, to++) - *to = *from; - *fromP = from; - *toP = to; -} - -static -void utf8_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - unsigned short *to = *toP; - const char *from = *fromP; - while (from != fromLim && to != toLim) { - switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { - case BT_LEAD2: - *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); - from += 2; - break; - case BT_LEAD3: - *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); - from += 3; - break; - case BT_LEAD4: - { - unsigned long n; - if (to + 1 == toLim) - break; - n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); - n -= 0x10000; - to[0] = (unsigned short)((n >> 10) | 0xD800); - to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); - to += 2; - from += 4; - } - break; - default: - *to++ = *from++; - break; - } - } - *fromP = from; - *toP = to; -} - -#ifdef XML_NS -static const struct normal_encoding utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; -#endif - -static const struct normal_encoding utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#ifdef XML_NS - -static const struct normal_encoding internal_utf8_encoding_ns = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#include "iasciitab.h" -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -#endif - -static const struct normal_encoding internal_utf8_encoding = { - { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "utf8tab.h" - }, - STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) - }; - -static -void latin1_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - for (;;) { - unsigned char c; - if (*fromP == fromLim) - break; - c = (unsigned char)**fromP; - if (c & 0x80) { - if (toLim - *toP < 2) - break; - *(*toP)++ = ((c >> 6) | UTF8_cval2); - *(*toP)++ = ((c & 0x3f) | 0x80); - (*fromP)++; - } - else { - if (*toP == toLim) - break; - *(*toP)++ = *(*fromP)++; - } - } -} - -static -void latin1_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = (unsigned char)*(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding latin1_encoding_ns = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding latin1_encoding = { - { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(sb_) - }; - -static -void ascii_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - while (*fromP != fromLim && *toP != toLim) - *(*toP)++ = *(*fromP)++; -} - -#ifdef XML_NS - -static const struct normal_encoding ascii_encoding_ns = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#include "asciitab.h" - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -#endif - -static const struct normal_encoding ascii_encoding = { - { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON - /* BT_NONXML == 0 */ - }, - STANDARD_VTABLE(sb_) - }; - -static int unicode_byte_type(char hi, char lo) -{ - switch ((unsigned char)hi) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: - return BT_LEAD4; -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return BT_TRAIL; - case 0xFF: - switch ((unsigned char)lo) { - case 0xFF: - case 0xFE: - return BT_NONXML; - } - break; - } - return BT_NONASCII; -} - -#define DEFINE_UTF16_TO_UTF8(E) \ -static \ -void E ## toUtf8(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - char **toP, const char *toLim) \ -{ \ - const char *from; \ - for (from = *fromP; from != fromLim; from += 2) { \ - int plane; \ - unsigned char lo2; \ - unsigned char lo = GET_LO(from); \ - unsigned char hi = GET_HI(from); \ - switch (hi) { \ - case 0: \ - if (lo < 0x80) { \ - if (*toP == toLim) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = lo; \ - break; \ - } \ - /* fall through */ \ - case 0x1: case 0x2: case 0x3: \ - case 0x4: case 0x5: case 0x6: case 0x7: \ - if (toLim - *toP < 2) { \ - *fromP = from; \ - return; \ - } \ - *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - default: \ - if (toLim - *toP < 3) { \ - *fromP = from; \ - return; \ - } \ - /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ - *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ - *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ - *(*toP)++ = ((lo & 0x3f) | 0x80); \ - break; \ - case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ - if (toLim - *toP < 4) { \ - *fromP = from; \ - return; \ - } \ - plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ - *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ - *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ - from += 2; \ - lo2 = GET_LO(from); \ - *(*toP)++ = (((lo & 0x3) << 4) \ - | ((GET_HI(from) & 0x3) << 2) \ - | (lo2 >> 6) \ - | 0x80); \ - *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ - break; \ - } \ - } \ - *fromP = from; \ -} - -#define DEFINE_UTF16_TO_UTF16(E) \ -static \ -void E ## toUtf16(const ENCODING *enc, \ - const char **fromP, const char *fromLim, \ - unsigned short **toP, const unsigned short *toLim) \ -{ \ - /* Avoid copying first half only of surrogate */ \ - if (fromLim - *fromP > ((toLim - *toP) << 1) \ - && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ - fromLim -= 2; \ - for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ - *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ -} - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) -#define GET_LO(ptr) ((unsigned char)(ptr)[0]) -#define GET_HI(ptr) ((unsigned char)(ptr)[1]) - -DEFINE_UTF16_TO_UTF8(little2_) -DEFINE_UTF16_TO_UTF16(little2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define SET2(ptr, ch) \ - (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) -#define GET_LO(ptr) ((unsigned char)(ptr)[1]) -#define GET_HI(ptr) ((unsigned char)(ptr)[0]) - -DEFINE_UTF16_TO_UTF8(big2_) -DEFINE_UTF16_TO_UTF16(big2_) - -#undef SET2 -#undef GET_LO -#undef GET_HI - -#define LITTLE2_BYTE_TYPE(enc, p) \ - ((p)[1] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ - : unicode_byte_type((p)[1], (p)[0])) -#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) -#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) -#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) -#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) - -#ifdef XML_MIN_SIZE - -static -int little2_byteType(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TYPE(enc, p); -} - -static -int little2_byteToAscii(const ENCODING *enc, const char *p) -{ - return LITTLE2_BYTE_TO_ASCII(enc, p); -} - -static -int little2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return LITTLE2_CHAR_MATCHES(enc, p, c); -} - -static -int little2_isNameMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int little2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) little2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding little2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding little2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 12 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#if XML_BYTE_ORDER != 21 - -#ifdef XML_NS - -static const struct normal_encoding internal_little2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - -static const struct normal_encoding internal_little2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(little2_) - }; - -#endif - - -#define BIG2_BYTE_TYPE(enc, p) \ - ((p)[0] == 0 \ - ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ - : unicode_byte_type((p)[0], (p)[1])) -#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) -#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) -#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) -#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ - UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) - -#ifdef XML_MIN_SIZE - -static -int big2_byteType(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TYPE(enc, p); -} - -static -int big2_byteToAscii(const ENCODING *enc, const char *p) -{ - return BIG2_BYTE_TO_ASCII(enc, p); -} - -static -int big2_charMatches(const ENCODING *enc, const char *p, int c) -{ - return BIG2_CHAR_MATCHES(enc, p, c); -} - -static -int big2_isNameMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NAME_CHAR_MINBPC(enc, p); -} - -static -int big2_isNmstrtMin(const ENCODING *enc, const char *p) -{ - return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); -} - -#undef VTABLE -#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 - -#else /* not XML_MIN_SIZE */ - -#undef PREFIX -#define PREFIX(ident) big2_ ## ident -#define MINBPC(enc) 2 -/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ -#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) -#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) -#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) -#define IS_NAME_CHAR(enc, p, n) 0 -#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) -#define IS_NMSTRT_CHAR(enc, p, n) (0) -#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) - -#include "xmltok_impl.c" - -#undef MINBPC -#undef BYTE_TYPE -#undef BYTE_TO_ASCII -#undef CHAR_MATCHES -#undef IS_NAME_CHAR -#undef IS_NAME_CHAR_MINBPC -#undef IS_NMSTRT_CHAR -#undef IS_NMSTRT_CHAR_MINBPC -#undef IS_INVALID_CHAR - -#endif /* not XML_MIN_SIZE */ - -#ifdef XML_NS - -static const struct normal_encoding big2_encoding_ns = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else -0 -#endif - }, - { -#include "asciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding big2_encoding = { - { VTABLE, 2, 0, -#if XML_BYTE_ORDER == 21 - 1 -#else - 0 -#endif - }, - { -#define BT_COLON BT_NMSTRT -#include "asciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#if XML_BYTE_ORDER != 12 - -#ifdef XML_NS - -static const struct normal_encoding internal_big2_encoding_ns = { - { VTABLE, 2, 0, 1 }, - { -#include "iasciitab.h" -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -static const struct normal_encoding internal_big2_encoding = { - { VTABLE, 2, 0, 1 }, - { -#define BT_COLON BT_NMSTRT -#include "iasciitab.h" -#undef BT_COLON -#include "latin1tab.h" - }, - STANDARD_VTABLE(big2_) - }; - -#endif - -#undef PREFIX - -static -int streqci(const char *s1, const char *s2) -{ - for (;;) { - char c1 = *s1++; - char c2 = *s2++; - if ('a' <= c1 && c1 <= 'z') - c1 += 'A' - 'a'; - if ('a' <= c2 && c2 <= 'z') - c2 += 'A' - 'a'; - if (c1 != c2) - return 0; - if (!c1) - break; - } - return 1; -} - -static -void initUpdatePosition(const ENCODING *enc, const char *ptr, - const char *end, POSITION *pos) -{ - normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); -} - -static -int toAscii(const ENCODING *enc, const char *ptr, const char *end) -{ - char buf[1]; - char *p = buf; - XmlUtf8Convert(enc, &ptr, end, &p, p + 1); - if (p == buf) - return -1; - else - return buf[0]; -} - -static -int isSpace(int c) -{ - switch (c) { - case 0x20: - case 0xD: - case 0xA: - case 0x9: - return 1; - } - return 0; -} - -/* Return 1 if there's just optional white space -or there's an S followed by name=val. */ -static -int parsePseudoAttribute(const ENCODING *enc, - const char *ptr, - const char *end, - const char **namePtr, - const char **valPtr, - const char **nextTokPtr) -{ - int c; - char open; - if (ptr == end) { - *namePtr = 0; - return 1; - } - if (!isSpace(toAscii(enc, ptr, end))) { - *nextTokPtr = ptr; - return 0; - } - do { - ptr += enc->minBytesPerChar; - } while (isSpace(toAscii(enc, ptr, end))); - if (ptr == end) { - *namePtr = 0; - return 1; - } - *namePtr = ptr; - for (;;) { - c = toAscii(enc, ptr, end); - if (c == -1) { - *nextTokPtr = ptr; - return 0; - } - if (c == '=') - break; - if (isSpace(c)) { - do { - ptr += enc->minBytesPerChar; - } while (isSpace(c = toAscii(enc, ptr, end))); - if (c != '=') { - *nextTokPtr = ptr; - return 0; - } - break; - } - ptr += enc->minBytesPerChar; - } - if (ptr == *namePtr) { - *nextTokPtr = ptr; - return 0; - } - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - while (isSpace(c)) { - ptr += enc->minBytesPerChar; - c = toAscii(enc, ptr, end); - } - if (c != '"' && c != '\'') { - *nextTokPtr = ptr; - return 0; - } - open = c; - ptr += enc->minBytesPerChar; - *valPtr = ptr; - for (;; ptr += enc->minBytesPerChar) { - c = toAscii(enc, ptr, end); - if (c == open) - break; - if (!('a' <= c && c <= 'z') - && !('A' <= c && c <= 'Z') - && !('0' <= c && c <= '9') - && c != '.' - && c != '-' - && c != '_') { - *nextTokPtr = ptr; - return 0; - } - } - *nextTokPtr = ptr + enc->minBytesPerChar; - return 1; -} - -static -int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, - const char *, - const char *), - int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - const char *val = 0; - const char *name = 0; - ptr += 5 * enc->minBytesPerChar; - end -= 2 * enc->minBytesPerChar; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr) || !name) { - *badPtr = ptr; - return 0; - } - if (!XmlNameMatchesAscii(enc, name, "version")) { - if (!isGeneralTextEntity) { - *badPtr = name; - return 0; - } - } - else { - if (versionPtr) - *versionPtr = val; - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) { - if (isGeneralTextEntity) { - /* a TextDecl must have an EncodingDecl */ - *badPtr = ptr; - return 0; - } - return 1; - } - } - if (XmlNameMatchesAscii(enc, name, "encoding")) { - int c = toAscii(enc, val, end); - if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) { - *badPtr = val; - return 0; - } - if (encodingName) - *encodingName = val; - if (encoding) - *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); - if (!parsePseudoAttribute(enc, ptr, end, &name, &val, &ptr)) { - *badPtr = ptr; - return 0; - } - if (!name) - return 1; - } - if (!XmlNameMatchesAscii(enc, name, "standalone") || isGeneralTextEntity) { - *badPtr = name; - return 0; - } - if (XmlNameMatchesAscii(enc, val, "yes")) { - if (standalone) - *standalone = 1; - } - else if (XmlNameMatchesAscii(enc, val, "no")) { - if (standalone) - *standalone = 0; - } - else { - *badPtr = val; - return 0; - } - while (isSpace(toAscii(enc, ptr, end))) - ptr += enc->minBytesPerChar; - if (ptr != end) { - *badPtr = ptr; - return 0; - } - return 1; -} - -static -int checkCharRefNumber(int result) -{ - switch (result >> 8) { -case 0xD8: case 0xD9: case 0xDA: case 0xDB: -case 0xDC: case 0xDD: case 0xDE: case 0xDF: - return -1; - case 0: - if (latin1_encoding.type[result] == BT_NONXML) - return -1; - break; - case 0xFF: - if (result == 0xFFFE || result == 0xFFFF) - return -1; - break; - } - return result; -} - -int XmlUtf8Encode(int c, char *buf) -{ - enum { - /* minN is minimum legal resulting value for N byte sequence */ - min2 = 0x80, - min3 = 0x800, - min4 = 0x10000 - }; - - if (c < 0) - return 0; - if (c < min2) { - buf[0] = (c | UTF8_cval1); - return 1; - } - if (c < min3) { - buf[0] = ((c >> 6) | UTF8_cval2); - buf[1] = ((c & 0x3f) | 0x80); - return 2; - } - if (c < min4) { - buf[0] = ((c >> 12) | UTF8_cval3); - buf[1] = (((c >> 6) & 0x3f) | 0x80); - buf[2] = ((c & 0x3f) | 0x80); - return 3; - } - if (c < 0x110000) { - buf[0] = ((c >> 18) | UTF8_cval4); - buf[1] = (((c >> 12) & 0x3f) | 0x80); - buf[2] = (((c >> 6) & 0x3f) | 0x80); - buf[3] = ((c & 0x3f) | 0x80); - return 4; - } - return 0; -} - -int XmlUtf16Encode(int charNum, unsigned short *buf) -{ - if (charNum < 0) - return 0; - if (charNum < 0x10000) { - buf[0] = charNum; - return 1; - } - if (charNum < 0x110000) { - charNum -= 0x10000; - buf[0] = (charNum >> 10) + 0xD800; - buf[1] = (charNum & 0x3FF) + 0xDC00; - return 2; - } - return 0; -} - -struct unknown_encoding { - struct normal_encoding normal; - int (*convert)(void *userData, const char *p); - void *userData; - unsigned short utf16[256]; - char utf8[256][4]; -}; - -int XmlSizeOfUnknownEncoding() -{ - return sizeof(struct unknown_encoding); -} - -static -int unknown_isName(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); -} - -static -int unknown_isNmstrt(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - if (c & ~0xFFFF) - return 0; - return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); -} - -static -int unknown_isInvalid(const ENCODING *enc, const char *p) -{ - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, p); - return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; -} - -static -void unknown_toUtf8(const ENCODING *enc, - const char **fromP, const char *fromLim, - char **toP, const char *toLim) -{ - char buf[XML_UTF8_ENCODE_MAX]; - for (;;) { - const char *utf8; - int n; - if (*fromP == fromLim) - break; - utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; - n = *utf8++; - if (n == 0) { - int c = ((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - n = XmlUtf8Encode(c, buf); - if (n > toLim - *toP) - break; - utf8 = buf; - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else { - if (n > toLim - *toP) - break; - (*fromP)++; - } - do { - *(*toP)++ = *utf8++; - } while (--n != 0); - } -} - -static -void unknown_toUtf16(const ENCODING *enc, - const char **fromP, const char *fromLim, - unsigned short **toP, const unsigned short *toLim) -{ - while (*fromP != fromLim && *toP != toLim) { - unsigned short c - = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; - if (c == 0) { - c = (unsigned short)((const struct unknown_encoding *)enc) - ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); - *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] - - (BT_LEAD2 - 2); - } - else - (*fromP)++; - *(*toP)++ = c; - } -} - -ENCODING * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - int i; - struct unknown_encoding *e = mem; - for (i = 0; i < sizeof(struct normal_encoding); i++) - ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; - for (i = 0; i < 128; i++) - if (latin1_encoding.type[i] != BT_OTHER - && latin1_encoding.type[i] != BT_NONXML - && table[i] != i) - return 0; - for (i = 0; i < 256; i++) { - int c = table[i]; - if (c == -1) { - e->normal.type[i] = BT_MALFORM; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else if (c < 0) { - if (c < -4) - return 0; - e->normal.type[i] = BT_LEAD2 - (c + 2); - e->utf8[i][0] = 0; - e->utf16[i] = 0; - } - else if (c < 0x80) { - if (latin1_encoding.type[c] != BT_OTHER - && latin1_encoding.type[c] != BT_NONXML - && c != i) - return 0; - e->normal.type[i] = latin1_encoding.type[c]; - e->utf8[i][0] = 1; - e->utf8[i][1] = (char)c; - e->utf16[i] = c == 0 ? 0xFFFF : c; - } - else if (checkCharRefNumber(c) < 0) { - e->normal.type[i] = BT_NONXML; - /* This shouldn't really get used. */ - e->utf16[i] = 0xFFFF; - e->utf8[i][0] = 1; - e->utf8[i][1] = 0; - } - else { - if (c > 0xFFFF) - return 0; - if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NMSTRT; - else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) - e->normal.type[i] = BT_NAME; - else - e->normal.type[i] = BT_OTHER; - e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); - e->utf16[i] = c; - } - } - e->userData = userData; - e->convert = convert; - if (convert) { - e->normal.isName2 = unknown_isName; - e->normal.isName3 = unknown_isName; - e->normal.isName4 = unknown_isName; - e->normal.isNmstrt2 = unknown_isNmstrt; - e->normal.isNmstrt3 = unknown_isNmstrt; - e->normal.isNmstrt4 = unknown_isNmstrt; - e->normal.isInvalid2 = unknown_isInvalid; - e->normal.isInvalid3 = unknown_isInvalid; - e->normal.isInvalid4 = unknown_isInvalid; - } - e->normal.enc.utf8Convert = unknown_toUtf8; - e->normal.enc.utf16Convert = unknown_toUtf16; - return &(e->normal.enc); -} - -/* If this enumeration is changed, getEncodingIndex and encodings -must also be changed. */ -enum { - UNKNOWN_ENC = -1, - ISO_8859_1_ENC = 0, - US_ASCII_ENC, - UTF_8_ENC, - UTF_16_ENC, - UTF_16BE_ENC, - UTF_16LE_ENC, - /* must match encodingNames up to here */ - NO_ENC -}; - -static -int getEncodingIndex(const char *name) -{ - static const char *encodingNames[] = { - "ISO-8859-1", - "US-ASCII", - "UTF-8", - "UTF-16", - "UTF-16BE" - "UTF-16LE", - }; - int i; - if (name == 0) - return NO_ENC; - for (i = 0; i < sizeof(encodingNames)/sizeof(encodingNames[0]); i++) - if (streqci(name, encodingNames[i])) - return i; - return UNKNOWN_ENC; -} - -/* For binary compatibility, we store the index of the encoding specified -at initialization in the isUtf16 member. */ - -#define INIT_ENC_INDEX(enc) ((enc)->initEnc.isUtf16) - -/* This is what detects the encoding. -encodingTable maps from encoding indices to encodings; -INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; -state is XML_CONTENT_STATE if we're parsing an external text entity, -and XML_PROLOG_STATE otherwise. -*/ - - -static -int initScan(const ENCODING **encodingTable, - const INIT_ENCODING *enc, - int state, - const char *ptr, - const char *end, - const char **nextTokPtr) -{ - const ENCODING **encPtr; - - if (ptr == end) - return XML_TOK_NONE; - encPtr = enc->encPtr; - if (ptr + 1 == end) { - /* only a single byte available for auto-detection */ - /* a well-formed document entity must have more than one byte */ - if (state != XML_CONTENT_STATE) - return XML_TOK_PARTIAL; - /* so we're parsing an external text entity... */ - /* if UTF-16 was externally specified, then we need at least 2 bytes */ - switch (INIT_ENC_INDEX(enc)) { - case UTF_16_ENC: - case UTF_16LE_ENC: - case UTF_16BE_ENC: - return XML_TOK_PARTIAL; - } - switch ((unsigned char)*ptr) { - case 0xFE: - case 0xFF: - case 0xEF: /* possibly first byte of UTF-8 BOM */ - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - /* fall through */ - case 0x00: - case 0x3C: - return XML_TOK_PARTIAL; - } - } - else { - switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { - case 0xFEFF: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XML_TOK_BOM; - /* 00 3C is handled in the default case */ - case 0x3C00: - if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC - || INIT_ENC_INDEX(enc) == UTF_16_ENC) - && state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - case 0xFFFE: - if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC - && state == XML_CONTENT_STATE) - break; - *nextTokPtr = ptr + 2; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XML_TOK_BOM; - case 0xEFBB: - /* Maybe a UTF-8 BOM (EF BB BF) */ - /* If there's an explicitly specified (external) encoding - of ISO-8859-1 or some flavour of UTF-16 - and this is an external text entity, - don't look for the BOM, - because it might be a legal data. */ - if (state == XML_CONTENT_STATE) { - int e = INIT_ENC_INDEX(enc); - if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) - break; - } - if (ptr + 2 == end) - return XML_TOK_PARTIAL; - if ((unsigned char)ptr[2] == 0xBF) { - *encPtr = encodingTable[UTF_8_ENC]; - return XML_TOK_BOM; - } - break; - default: - if (ptr[0] == '\0') { - /* 0 isn't a legal data character. Furthermore a document entity can only - start with ASCII characters. So the only way this can fail to be big-endian - UTF-16 if it it's an external parsed general entity that's labelled as - UTF-16LE. */ - if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) - break; - *encPtr = encodingTable[UTF_16BE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - else if (ptr[1] == '\0') { - /* We could recover here in the case: - - parsing an external entity - - second byte is 0 - - no externally specified encoding - - no encoding declaration - by assuming UTF-16LE. But we don't, because this would mean when - presented just with a single byte, we couldn't reliably determine - whether we needed further bytes. */ - if (state == XML_CONTENT_STATE) - break; - *encPtr = encodingTable[UTF_16LE_ENC]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); - } - break; - } - } - *encPtr = encodingTable[(int)INIT_ENC_INDEX(enc)]; - return XmlTok(*encPtr, state, ptr, end, nextTokPtr); -} - - -#define NS(x) x -#define ns(x) x -#include "xmltok_ns.c" -#undef NS -#undef ns - -#ifdef XML_NS - -#define NS(x) x ## NS -#define ns(x) x ## _ns - -#include "xmltok_ns.c" - -#undef NS -#undef ns - -ENCODING * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*convert)(void *userData, const char *p), - void *userData) -{ - ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); - if (enc) - ((struct normal_encoding *)enc)->type[':'] = BT_COLON; - return enc; -} - -#endif /* XML_NS */ diff --git a/protocols/jabber/xmltok.h b/protocols/jabber/xmltok.h deleted file mode 100644 index 06544d15..00000000 --- a/protocols/jabber/xmltok.h +++ /dev/null @@ -1,307 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -#ifndef XmlTok_INCLUDED -#define XmlTok_INCLUDED 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef XMLTOKAPI -#define XMLTOKAPI /* as nothing */ -#endif - -/* The following token may be returned by XmlContentTok */ -#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of - illegal ]]> sequence */ -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_NONE -4 /* The string to be scanned is empty */ -#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; - might be part of CRLF sequence */ -#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ -#define XML_TOK_PARTIAL -1 /* only part of a token */ -#define XML_TOK_INVALID 0 - -/* The following tokens are returned by XmlContentTok; some are also - returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ - -#define XML_TOK_START_TAG_WITH_ATTS 1 -#define XML_TOK_START_TAG_NO_ATTS 2 -#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ -#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 -#define XML_TOK_END_TAG 5 -#define XML_TOK_DATA_CHARS 6 -#define XML_TOK_DATA_NEWLINE 7 -#define XML_TOK_CDATA_SECT_OPEN 8 -#define XML_TOK_ENTITY_REF 9 -#define XML_TOK_CHAR_REF 10 /* numeric character reference */ - -/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ -#define XML_TOK_PI 11 /* processing instruction */ -#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ -#define XML_TOK_COMMENT 13 -#define XML_TOK_BOM 14 /* Byte order mark */ - -/* The following tokens are returned only by XmlPrologTok */ -#define XML_TOK_PROLOG_S 15 -#define XML_TOK_DECL_OPEN 16 /* <!foo */ -#define XML_TOK_DECL_CLOSE 17 /* > */ -#define XML_TOK_NAME 18 -#define XML_TOK_NMTOKEN 19 -#define XML_TOK_POUND_NAME 20 /* #name */ -#define XML_TOK_OR 21 /* | */ -#define XML_TOK_PERCENT 22 -#define XML_TOK_OPEN_PAREN 23 -#define XML_TOK_CLOSE_PAREN 24 -#define XML_TOK_OPEN_BRACKET 25 -#define XML_TOK_CLOSE_BRACKET 26 -#define XML_TOK_LITERAL 27 -#define XML_TOK_PARAM_ENTITY_REF 28 -#define XML_TOK_INSTANCE_START 29 - -/* The following occur only in element type declarations */ -#define XML_TOK_NAME_QUESTION 30 /* name? */ -#define XML_TOK_NAME_ASTERISK 31 /* name* */ -#define XML_TOK_NAME_PLUS 32 /* name+ */ -#define XML_TOK_COND_SECT_OPEN 33 /* <![ */ -#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */ -#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ -#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ -#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ -#define XML_TOK_COMMA 38 - -/* The following token is returned only by XmlAttributeValueTok */ -#define XML_TOK_ATTRIBUTE_VALUE_S 39 - -/* The following token is returned only by XmlCdataSectionTok */ -#define XML_TOK_CDATA_SECT_CLOSE 40 - -/* With namespace processing this is returned by XmlPrologTok - for a name with a colon. */ -#define XML_TOK_PREFIXED_NAME 41 - -#define XML_N_STATES 3 -#define XML_PROLOG_STATE 0 -#define XML_CONTENT_STATE 1 -#define XML_CDATA_SECTION_STATE 2 - -#define XML_N_LITERAL_TYPES 2 -#define XML_ATTRIBUTE_VALUE_LITERAL 0 -#define XML_ENTITY_VALUE_LITERAL 1 - -/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ -#define XML_UTF8_ENCODE_MAX 4 -/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ -#define XML_UTF16_ENCODE_MAX 2 - -typedef struct position { - /* first line and first column are 0 not 1 */ - unsigned long lineNumber; - unsigned long columnNumber; -} POSITION; - -typedef struct { - const char *name; - const char *valuePtr; - const char *valueEnd; - char normalized; -} ATTRIBUTE; - -struct encoding; -typedef struct encoding ENCODING; - -struct encoding { - int (*scanners[XML_N_STATES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, - const char *, - const char *, - const char **); - int (*sameName)(const ENCODING *, - const char *, const char *); - int (*nameMatchesAscii)(const ENCODING *, - const char *, const char *); - int (*nameLength)(const ENCODING *, const char *); - const char *(*skipS)(const ENCODING *, const char *); - int (*getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts); - int (*charRefNumber)(const ENCODING *enc, const char *ptr); - int (*predefinedEntityName)(const ENCODING *, const char *, const char *); - void (*updatePosition)(const ENCODING *, - const char *ptr, - const char *end, - POSITION *); - int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr); - void (*utf8Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - char **toP, - const char *toLim); - void (*utf16Convert)(const ENCODING *enc, - const char **fromP, - const char *fromLim, - unsigned short **toP, - const unsigned short *toLim); - int minBytesPerChar; - char isUtf8; - char isUtf16; -}; - -/* -Scan the string starting at ptr until the end of the next complete token, -but do not scan past eptr. Return an integer giving the type of token. - -Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. - -Return XML_TOK_PARTIAL when the string does not contain a complete token; -nextTokPtr will not be set. - -Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr -will be set to point to the character which made the token invalid. - -Otherwise the string starts with a valid token; nextTokPtr will be set to point -to the character following the end of that token. - -Each data character counts as a single token, but adjacent data characters -may be returned together. Similarly for characters in the prolog outside -literals, comments and processing instructions. -*/ - - -#define XmlTok(enc, state, ptr, end, nextTokPtr) \ - (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) - -#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) - -#define XmlContentTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) - -#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ - XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) - -/* This is used for performing a 2nd-level tokenization on -the content of a literal that has already been returned by XmlTok. */ - -#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ - (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) - -#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ - XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) - -#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) - -#define XmlNameMatchesAscii(enc, ptr1, ptr2) \ - (((enc)->nameMatchesAscii)(enc, ptr1, ptr2)) - -#define XmlNameLength(enc, ptr) \ - (((enc)->nameLength)(enc, ptr)) - -#define XmlSkipS(enc, ptr) \ - (((enc)->skipS)(enc, ptr)) - -#define XmlGetAttributes(enc, ptr, attsMax, atts) \ - (((enc)->getAtts)(enc, ptr, attsMax, atts)) - -#define XmlCharRefNumber(enc, ptr) \ - (((enc)->charRefNumber)(enc, ptr)) - -#define XmlPredefinedEntityName(enc, ptr, end) \ - (((enc)->predefinedEntityName)(enc, ptr, end)) - -#define XmlUpdatePosition(enc, ptr, end, pos) \ - (((enc)->updatePosition)(enc, ptr, end, pos)) - -#define XmlIsPublicId(enc, ptr, end, badPtr) \ - (((enc)->isPublicId)(enc, ptr, end, badPtr)) - -#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) - -#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ - (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) - -typedef struct { - ENCODING initEnc; - const ENCODING **encPtr; -} INIT_ENCODING; - -int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); - -int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(); -int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf); -int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf); - -int XMLTOKAPI XmlSizeOfUnknownEncoding(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncoding(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); - -int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingNamePtr, - const ENCODING **namedEncodingPtr, - int *standalonePtr); -int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); -const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(); -const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(); -ENCODING XMLTOKAPI * -XmlInitUnknownEncodingNS(void *mem, - int *table, - int (*conv)(void *userData, const char *p), - void *userData); -#ifdef __cplusplus -} -#endif - -#endif /* not XmlTok_INCLUDED */ diff --git a/protocols/jabber/xmltok_impl.c b/protocols/jabber/xmltok_impl.c deleted file mode 100644 index de11c2a8..00000000 --- a/protocols/jabber/xmltok_impl.c +++ /dev/null @@ -1,1737 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -#ifndef IS_INVALID_CHAR -#define IS_INVALID_CHAR(enc, ptr, n) (0) -#endif - -#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_INVALID_CHAR(enc, ptr, n)) { \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define INVALID_CASES(ptr, nextTokPtr) \ - INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ - INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ - case BT_NONXML: \ - case BT_MALFORM: \ - case BT_TRAIL: \ - *(nextTokPtr) = (ptr); \ - return XML_TOK_INVALID; - -#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NAME_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - case BT_DIGIT: \ - case BT_NAME: \ - case BT_MINUS: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) - -#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - ptr += n; \ - break; - -#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ - case BT_NONASCII: \ - if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; \ - } \ - case BT_NMSTRT: \ - case BT_HEX: \ - ptr += MINBPC(enc); \ - break; \ - CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ - CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) - -#ifndef PREFIX -#define PREFIX(ident) ident -#endif - -/* ptr points to character following "<!-" */ - -static -int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - if (!CHAR_MATCHES(enc, ptr, '-')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) - case BT_MINUS: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '-')) { - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMENT; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "<!" */ - -static -int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COND_SECT_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_PERCNT: - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - /* don't allow <!ENTITY% foo "whatever"> */ - switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { -case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* fall through */ -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DECL_OPEN; - case BT_NMSTRT: - case BT_HEX: - ptr += MINBPC(enc); - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) -{ - int upper = 0; - *tokPtr = XML_TOK_PI; - if (end - ptr != MINBPC(enc)*3) - return 1; - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'x': - break; - case 'X': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'm': - break; - case 'M': - upper = 1; - break; - default: - return 1; - } - ptr += MINBPC(enc); - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - break; - case 'L': - upper = 1; - break; - default: - return 1; - } - if (upper) - return 0; - *tokPtr = XML_TOK_XML_DECL; - return 1; -} - -/* ptr points to character following "<?" */ - -static -int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int tok; - const char *target = ptr; - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_CR: case BT_LF: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUEST: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - break; - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; - case BT_QUEST: - if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr + MINBPC(enc); - return tok; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - - -static -int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int i; - /* CDATA[ */ - if (end - ptr < 6 * MINBPC(enc)) - return XML_TOK_PARTIAL; - for (i = 0; i < 6; i++, ptr += MINBPC(enc)) { - if (!CHAR_MATCHES(enc, ptr, "CDATA["[i])) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - *nextTokPtr = ptr; - return XML_TOK_CDATA_SECT_OPEN; -} - -static -int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CDATA_SECT_CLOSE; - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - case BT_RSQB: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "</" */ - -static -int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_CR: case BT_LF: - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_CR: case BT_LF: - break; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -#ifdef XML_NS - case BT_COLON: - /* no need to check qname syntax here, since end-tag must match exactly */ - ptr += MINBPC(enc); - break; -#endif - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_END_TAG; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&#X" */ - -static -int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&#" */ - -static -int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr != end) { - if (CHAR_MATCHES(enc, ptr, 'x')) - return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - break; - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CHAR_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "&" */ - -static -int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_NUM: - return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following first character of attribute name */ - -static -int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ -#ifdef XML_NS - int hadColon = 0; -#endif - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -#ifdef XML_NS - case BT_COLON: - if (hadColon) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; -#endif -case BT_S: case BT_CR: case BT_LF: - for (;;) { - int t; - - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == BT_EQUALS) - break; - switch (t) { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_EQUALS: - { - int open; -#ifdef XML_NS - hadColon = 0; -#endif - for (;;) { - - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - open = BYTE_TYPE(enc, ptr); - if (open == BT_QUOT || open == BT_APOS) - break; - switch (open) { - case BT_S: - case BT_LF: - case BT_CR: - break; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - ptr += MINBPC(enc); - /* in attribute value */ - for (;;) { - int t; - if (ptr == end) - return XML_TOK_PARTIAL; - t = BYTE_TYPE(enc, ptr); - if (t == open) - break; - switch (t) { - INVALID_CASES(ptr, nextTokPtr) - case BT_AMP: - { - int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr); - if (tok <= 0) { - if (tok == XML_TOK_INVALID) - *nextTokPtr = ptr; - return tok; - } - break; - } - case BT_LT: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - default: - ptr += MINBPC(enc); - break; - } - } - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: - case BT_CR: - case BT_LF: - break; - case BT_SOL: - goto sol; - case BT_GT: - goto gt; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - /* ptr points to closing quote */ - for (;;) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_S: case BT_CR: case BT_LF: - continue; - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_WITH_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_WITH_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; - } - break; - } - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -/* ptr points to character following "<" */ - -static -int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ -#ifdef XML_NS - int hadColon; -#endif - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_EXCL: - if ((ptr += MINBPC(enc)) == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_MINUS: - return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LSQB: - return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr); - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_SOL: - return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr); - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } -#ifdef XML_NS - hadColon = 0; -#endif - /* we have a start-tag */ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -#ifdef XML_NS - case BT_COLON: - if (hadColon) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - hadColon = 1; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - break; -#endif -case BT_S: case BT_CR: case BT_LF: - { - ptr += MINBPC(enc); - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - case BT_GT: - goto gt; - case BT_SOL: - goto sol; - case BT_S: case BT_CR: case BT_LF: - ptr += MINBPC(enc); - continue; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr); - } - return XML_TOK_PARTIAL; - } - case BT_GT: -gt: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_START_TAG_NO_ATTS; - case BT_SOL: -sol: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (!CHAR_MATCHES(enc, ptr, '>')) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_EMPTY_ELEMENT_NO_ATTS; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_LT: - return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_AMP: - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_CR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - case BT_LF: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, ']')) - break; - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_RSQB; - if (!CHAR_MATCHES(enc, ptr, '>')) { - ptr -= MINBPC(enc); - break; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - INVALID_CASES(ptr, nextTokPtr) - default: - ptr += MINBPC(enc); - break; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ - *nextTokPtr = ptr; \ - return XML_TOK_DATA_CHARS; \ - } \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_RSQB: - if (ptr + MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ']')) { - ptr += MINBPC(enc); - break; - } - if (ptr + 2*MINBPC(enc) != end) { - if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), '>')) { - ptr += MINBPC(enc); - break; - } - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_INVALID; - } - } - /* fall through */ - case BT_AMP: - case BT_LT: - case BT_NONXML: - case BT_MALFORM: - case BT_TRAIL: - case BT_CR: - case BT_LF: - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -/* ptr points to character following "%" */ - -static -int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) -case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: - *nextTokPtr = ptr; - return XML_TOK_PERCENT; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - case BT_SEMI: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_PARAM_ENTITY_REF; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_CR: case BT_LF: case BT_S: -case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: - *nextTokPtr = ptr; - return XML_TOK_POUND_NAME; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(scanLit)(int open, const ENCODING *enc, - const char *ptr, const char *end, - const char **nextTokPtr) -{ - while (ptr != end) { - int t = BYTE_TYPE(enc, ptr); - switch (t) { - INVALID_CASES(ptr, nextTokPtr) - case BT_QUOT: - case BT_APOS: - ptr += MINBPC(enc); - if (t != open) - break; - if (ptr == end) - return XML_TOK_PARTIAL; - *nextTokPtr = ptr; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_CR: case BT_LF: - case BT_GT: case BT_PERCNT: case BT_LSQB: - return XML_TOK_LITERAL; - default: - return XML_TOK_INVALID; - } - default: - ptr += MINBPC(enc); - break; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - int tok; - if (ptr == end) - return XML_TOK_NONE; - if (MINBPC(enc) > 1) { - size_t n = end - ptr; - if (n & (MINBPC(enc) - 1)) { - n &= ~(MINBPC(enc) - 1); - if (n == 0) - return XML_TOK_PARTIAL; - end = ptr + n; - } - } - switch (BYTE_TYPE(enc, ptr)) { - case BT_QUOT: - return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_APOS: - return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_LT: - { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_EXCL: - return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_QUEST: - return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_NMSTRT: - case BT_HEX: - case BT_NONASCII: - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - *nextTokPtr = ptr - MINBPC(enc); - return XML_TOK_INSTANCE_START; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - case BT_CR: - if (ptr + MINBPC(enc) == end) - return XML_TOK_TRAILING_CR; - /* fall through */ -case BT_S: case BT_LF: - for (;;) { - ptr += MINBPC(enc); - if (ptr == end) - break; - switch (BYTE_TYPE(enc, ptr)) { - case BT_S: case BT_LF: - break; - case BT_CR: - /* don't split CR/LF pair */ - if (ptr + MINBPC(enc) != end) - break; - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - } - } - *nextTokPtr = ptr; - return XML_TOK_PROLOG_S; - case BT_PERCNT: - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - case BT_COMMA: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_COMMA; - case BT_LSQB: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_BRACKET; - case BT_RSQB: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr, ']')) { - if (ptr + MINBPC(enc) == end) - return XML_TOK_PARTIAL; - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), '>')) { - *nextTokPtr = ptr + 2*MINBPC(enc); - return XML_TOK_COND_SECT_CLOSE; - } - } - *nextTokPtr = ptr; - return XML_TOK_CLOSE_BRACKET; - case BT_LPAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OPEN_PAREN; - case BT_RPAR: - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_PARTIAL; - switch (BYTE_TYPE(enc, ptr)) { - case BT_AST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_ASTERISK; - case BT_QUEST: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_QUESTION; - case BT_PLUS: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_CLOSE_PAREN_PLUS; -case BT_CR: case BT_LF: case BT_S: -case BT_GT: case BT_COMMA: case BT_VERBAR: - case BT_RPAR: - *nextTokPtr = ptr; - return XML_TOK_CLOSE_PAREN; - } - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_VERBAR: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_OR; - case BT_GT: - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DECL_CLOSE; - case BT_NUM: - return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (end - ptr < n) \ - return XML_TOK_PARTIAL_CHAR; \ - if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NAME; \ - break; \ - } \ - if (IS_NAME_CHAR(enc, ptr, n)) { \ - ptr += n; \ - tok = XML_TOK_NMTOKEN; \ - break; \ - } \ - *nextTokPtr = ptr; \ - return XML_TOK_INVALID; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NMSTRT: - case BT_HEX: - tok = XML_TOK_NAME; - ptr += MINBPC(enc); - break; - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: -#ifdef XML_NS - case BT_COLON: -#endif - tok = XML_TOK_NMTOKEN; - ptr += MINBPC(enc); - break; - case BT_NONASCII: - if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NAME; - break; - } - if (IS_NAME_CHAR_MINBPC(enc, ptr)) { - ptr += MINBPC(enc); - tok = XML_TOK_NMTOKEN; - break; - } - /* fall through */ - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) -case BT_GT: case BT_RPAR: case BT_COMMA: -case BT_VERBAR: case BT_LSQB: case BT_PERCNT: -case BT_S: case BT_CR: case BT_LF: - *nextTokPtr = ptr; - return tok; -#ifdef XML_NS - case BT_COLON: - ptr += MINBPC(enc); - switch (tok) { - case XML_TOK_NAME: - if (ptr == end) - return XML_TOK_PARTIAL; - tok = XML_TOK_PREFIXED_NAME; - switch (BYTE_TYPE(enc, ptr)) { - CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) - default: - tok = XML_TOK_NMTOKEN; - break; - } - break; - case XML_TOK_PREFIXED_NAME: - tok = XML_TOK_NMTOKEN; - break; - } - break; -#endif - case BT_PLUS: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_PLUS; - case BT_AST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_ASTERISK; - case BT_QUEST: - if (tok == XML_TOK_NMTOKEN) { - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_NAME_QUESTION; - default: - *nextTokPtr = ptr; - return XML_TOK_INVALID; - } - } - return XML_TOK_PARTIAL; -} - -static -int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LT: - /* this is for inside entity references */ - *nextTokPtr = ptr; - return XML_TOK_INVALID; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_S: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_ATTRIBUTE_VALUE_S; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - const char *start; - if (ptr == end) - return XML_TOK_NONE; - start = ptr; - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_AMP: - if (ptr == start) - return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_PERCNT: - if (ptr == start) - return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_LF: - if (ptr == start) { - *nextTokPtr = ptr + MINBPC(enc); - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - case BT_CR: - if (ptr == start) { - ptr += MINBPC(enc); - if (ptr == end) - return XML_TOK_TRAILING_CR; - if (BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - *nextTokPtr = ptr; - return XML_TOK_DATA_NEWLINE; - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; - default: - ptr += MINBPC(enc); - break; - } - } - *nextTokPtr = ptr; - return XML_TOK_DATA_CHARS; -} - -static -int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, - const char **badPtr) -{ - ptr += MINBPC(enc); - end -= MINBPC(enc); - for (; ptr != end; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_DIGIT: - case BT_HEX: - case BT_MINUS: - case BT_APOS: - case BT_LPAR: - case BT_RPAR: - case BT_PLUS: - case BT_COMMA: - case BT_SOL: - case BT_EQUALS: - case BT_QUEST: - case BT_CR: - case BT_LF: - case BT_SEMI: - case BT_EXCL: - case BT_AST: - case BT_PERCNT: - case BT_NUM: -#ifdef XML_NS - case BT_COLON: -#endif - break; - case BT_S: - if (CHAR_MATCHES(enc, ptr, '\t')) { - *badPtr = ptr; - return 0; - } - break; - case BT_NAME: - case BT_NMSTRT: - if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) - break; - default: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 0x24: /* $ */ - case 0x40: /* @ */ - break; - default: - *badPtr = ptr; - return 0; - } - break; - } - } - return 1; -} - -/* This must only be called for a well-formed start-tag or empty element tag. -Returns the number of attributes. Pointers to the first attsMax attributes -are stored in atts. */ - -static -int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, - int attsMax, ATTRIBUTE *atts) -{ - enum { other, inName, inValue } state = inName; - int nAtts = 0; - int open = 0; - - for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { - switch (BYTE_TYPE(enc, ptr)) { -#define START_NAME \ - if (state == other) { \ - if (nAtts < attsMax) { \ - atts[nAtts].name = ptr; \ - atts[nAtts].normalized = 1; \ - } \ - state = inName; \ - } -#define LEAD_CASE(n) \ - case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: - case BT_HEX: - START_NAME - break; -#undef START_NAME - case BT_QUOT: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_QUOT; - } - else if (open == BT_QUOT) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_APOS: - if (state != inValue) { - if (nAtts < attsMax) - atts[nAtts].valuePtr = ptr + MINBPC(enc); - state = inValue; - open = BT_APOS; - } - else if (open == BT_APOS) { - state = other; - if (nAtts < attsMax) - atts[nAtts].valueEnd = ptr; - nAtts++; - } - break; - case BT_AMP: - if (nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_S: - if (state == inName) - state = other; - else if (state == inValue - && nAtts < attsMax - && atts[nAtts].normalized - && (ptr == atts[nAtts].valuePtr - || BYTE_TO_ASCII(enc, ptr) != ' ' - || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ' ' - || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) - atts[nAtts].normalized = 0; - break; - case BT_CR: case BT_LF: - /* This case ensures that the first attribute name is counted - Apart from that we could just change state on the quote. */ - if (state == inName) - state = other; - else if (state == inValue && nAtts < attsMax) - atts[nAtts].normalized = 0; - break; - case BT_GT: - case BT_SOL: - if (state != inValue) - return nAtts; - break; - default: - break; - } - } - /* not reached */ -} - -static -int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) -{ - int result = 0; - /* skip &# */ - ptr += 2*MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'x')) { - for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - switch (c) { -case '0': case '1': case '2': case '3': case '4': -case '5': case '6': case '7': case '8': case '9': - result <<= 4; - result |= (c - '0'); - break; -case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - result <<= 4; - result += 10 + (c - 'A'); - break; -case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - result <<= 4; - result += 10 + (c - 'a'); - break; - } - if (result >= 0x110000) - return -1; - } - } - else { - for (; !CHAR_MATCHES(enc, ptr, ';'); ptr += MINBPC(enc)) { - int c = BYTE_TO_ASCII(enc, ptr); - result *= 10; - result += (c - '0'); - if (result >= 0x110000) - return -1; - } - } - return checkCharRefNumber(result); -} - -static -int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) -{ - switch ((end - ptr)/MINBPC(enc)) { - case 2: - if (CHAR_MATCHES(enc, ptr + MINBPC(enc), 't')) { - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'l': - return '<'; - case 'g': - return '>'; - } - } - break; - case 3: - if (CHAR_MATCHES(enc, ptr, 'a')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'm')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) - return '&'; - } - } - break; - case 4: - switch (BYTE_TO_ASCII(enc, ptr)) { - case 'q': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'u')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 't')) - return '"'; - } - } - break; - case 'a': - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'p')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 'o')) { - ptr += MINBPC(enc); - if (CHAR_MATCHES(enc, ptr, 's')) - return '\''; - } - } - break; - } - } - return 0; -} - -static -int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr1)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - if (*ptr1++ != *ptr2++) \ - return 0; - LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) -#undef LEAD_CASE - /* fall through */ - if (*ptr1++ != *ptr2++) - return 0; - break; - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 1) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 2) { - if (*ptr2++ != *ptr1++) - return 0; - if (MINBPC(enc) > 3) { - if (*ptr2++ != *ptr1++) - return 0; - } - } - } - break; - default: - if (MINBPC(enc) == 1 && *ptr1 == *ptr2) - return 1; - switch (BYTE_TYPE(enc, ptr2)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } - } - } - /* not reached */ -} - -static -int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *ptr2) -{ - for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { - if (!CHAR_MATCHES(enc, ptr1, *ptr2)) - return 0; - } - switch (BYTE_TYPE(enc, ptr1)) { - case BT_LEAD2: - case BT_LEAD3: - case BT_LEAD4: - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - return 0; - default: - return 1; - } -} - -static -int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) -{ - const char *start = ptr; - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: ptr += n; break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_NONASCII: - case BT_NMSTRT: -#ifdef XML_NS - case BT_COLON: -#endif - case BT_HEX: - case BT_DIGIT: - case BT_NAME: - case BT_MINUS: - ptr += MINBPC(enc); - break; - default: - return ptr - start; - } - } -} - -static -const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) -{ - for (;;) { - switch (BYTE_TYPE(enc, ptr)) { - case BT_LF: - case BT_CR: - case BT_S: - ptr += MINBPC(enc); - break; - default: - return ptr; - } - } -} - -static -void PREFIX(updatePosition)(const ENCODING *enc, - const char *ptr, - const char *end, - POSITION *pos) -{ - while (ptr != end) { - switch (BYTE_TYPE(enc, ptr)) { -#define LEAD_CASE(n) \ - case BT_LEAD ## n: \ - ptr += n; \ - break; - LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) -#undef LEAD_CASE - case BT_LF: - pos->columnNumber = (unsigned)-1; - pos->lineNumber++; - ptr += MINBPC(enc); - break; - case BT_CR: - pos->lineNumber++; - ptr += MINBPC(enc); - if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) - ptr += MINBPC(enc); - pos->columnNumber = (unsigned)-1; - break; - default: - ptr += MINBPC(enc); - break; - } - pos->columnNumber++; - } -} - -#undef DO_LEAD_CASE -#undef MULTIBYTE_CASES -#undef INVALID_CASES -#undef CHECK_NAME_CASE -#undef CHECK_NAME_CASES -#undef CHECK_NMSTRT_CASE -#undef CHECK_NMSTRT_CASES diff --git a/protocols/jabber/xmltok_impl.h b/protocols/jabber/xmltok_impl.h deleted file mode 100644 index e72b225c..00000000 --- a/protocols/jabber/xmltok_impl.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -Alternatively, the contents of this file may be used under the terms -of the GNU General Public License (the "GPL"), in which case the -provisions of the GPL are applicable instead of those above. If you -wish to allow use of your version of this file only under the terms of -the GPL and not to allow others to use your version of this file under -the MPL, indicate your decision by deleting the provisions above and -replace them with the notice and other provisions required by the -GPL. If you do not delete the provisions above, a recipient may use -your version of this file under either the MPL or the GPL. -*/ - -enum { - BT_NONXML, - BT_MALFORM, - BT_LT, - BT_AMP, - BT_RSQB, - BT_LEAD2, - BT_LEAD3, - BT_LEAD4, - BT_TRAIL, - BT_CR, - BT_LF, - BT_GT, - BT_QUOT, - BT_APOS, - BT_EQUALS, - BT_QUEST, - BT_EXCL, - BT_SOL, - BT_SEMI, - BT_NUM, - BT_LSQB, - BT_S, - BT_NMSTRT, - BT_COLON, - BT_HEX, - BT_DIGIT, - BT_NAME, - BT_MINUS, - BT_OTHER, /* known not to be a name or name start character */ - BT_NONASCII, /* might be a name or name start character */ - BT_PERCNT, - BT_LPAR, - BT_RPAR, - BT_AST, - BT_PLUS, - BT_COMMA, - BT_VERBAR -}; - -#include <stddef.h> diff --git a/protocols/jabber/xmltok_ns.c b/protocols/jabber/xmltok_ns.c deleted file mode 100644 index ace3e5a4..00000000 --- a/protocols/jabber/xmltok_ns.c +++ /dev/null @@ -1,117 +0,0 @@ -/* -The contents of this file are subject to the Mozilla Public License -Version 1.1 (the "License"); you may not use this file except in -compliance with the License. You may obtain a copy of the License at -http://www.mozilla.org/MPL/ - -Software distributed under the License is distributed on an "AS IS" -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -License for the specific language governing rights and limitations -under the License. - -The Original Code is expat. - -The Initial Developer of the Original Code is James Clark. -Portions created by James Clark are Copyright (C) 1998, 1999 -James Clark. All Rights Reserved. - -Contributor(s): - -*/ - -const ENCODING *NS(XmlGetUtf8InternalEncoding)() -{ - return &ns(internal_utf8_encoding).enc; -} - -const ENCODING *NS(XmlGetUtf16InternalEncoding)() -{ -#if XML_BYTE_ORDER == 12 - return &ns(internal_little2_encoding).enc; -#elif XML_BYTE_ORDER == 21 -return &ns(internal_big2_encoding).enc; -#else -const short n = 1; - return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc; -#endif -} - -static -const ENCODING *NS(encodings)[] = { - &ns(latin1_encoding).enc, - &ns(ascii_encoding).enc, - &ns(utf8_encoding).enc, - &ns(big2_encoding).enc, - &ns(big2_encoding).enc, - &ns(little2_encoding).enc, - &ns(utf8_encoding).enc /* NO_ENC */ -}; - -static -int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); -} - -static -int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, - const char **nextTokPtr) -{ - return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); -} - -int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) -{ - int i = getEncodingIndex(name); - if (i == UNKNOWN_ENC) - return 0; - INIT_ENC_INDEX(p) = (char)i; - p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); - p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); - p->initEnc.updatePosition = initUpdatePosition; - p->encPtr = encPtr; - *encPtr = &(p->initEnc); - return 1; -} - -static -const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) -{ -#define ENCODING_MAX 128 - char buf[ENCODING_MAX]; - char *p = buf; - int i; - XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); - if (ptr != end) - return 0; - *p = 0; - if (streqci(buf, "UTF-16") && enc->minBytesPerChar == 2) - return enc; - i = getEncodingIndex(buf); - if (i == UNKNOWN_ENC) - return 0; - return NS(encodings)[i]; -} - -int NS(XmlParseXmlDecl)(int isGeneralTextEntity, - const ENCODING *enc, - const char *ptr, - const char *end, - const char **badPtr, - const char **versionPtr, - const char **encodingName, - const ENCODING **encoding, - int *standalone) -{ - return doParseXmlDecl(NS(findEncoding), - isGeneralTextEntity, - enc, - ptr, - end, - badPtr, - versionPtr, - encodingName, - encoding, - standalone); -} diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c new file mode 100644 index 00000000..68c9560d --- /dev/null +++ b/protocols/jabber/xmltree.c @@ -0,0 +1,481 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* 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, version * +* 2.1. * +* * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +#include <glib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <stdio.h> + +#include "xmltree.h" + +static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; + int i; + + node->parent = xt->cur; + node->name = g_strdup( element_name ); + + /* First count the number of attributes */ + for( i = 0; attr_names[i]; i ++ ); + + /* Then allocate a NULL-terminated array. */ + node->attr = g_new0( struct xt_attr, i + 1 ); + + /* And fill it, saving one variable by starting at the end. */ + for( i --; i >= 0; i -- ) + { + node->attr[i].key = g_strdup( attr_names[i] ); + node->attr[i].value = g_strdup( attr_values[i] ); + } + + /* Add it to the linked list of children nodes, if we have a current + node yet. */ + if( xt->cur ) + { + if( xt->cur->children ) + { + for( nt = xt->cur->children; nt->next; nt = nt->next ); + nt->next = node; + } + else + { + xt->cur->children = node; + } + } + else if( xt->root ) + { + /* ERROR situation: A second root-element??? */ + } + + /* Now this node will be the new current node. */ + xt->cur = node; + /* And maybe this is the root? */ + if( xt->root == NULL ) + xt->root = node; +} + +static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + struct xt_node *node = xt->cur; + + if( node == NULL ) + return; + + /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ + node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); + memcpy( node->text + node->text_len, text, text_len ); + node->text_len += text_len; + /* Zero termination is always nice to have. */ + node->text[node->text_len] = 0; +} + +static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + + xt->cur->flags |= XT_COMPLETE; + xt->cur = xt->cur->parent; +} + +GMarkupParser xt_parser_funcs = +{ + xt_start_element, + xt_end_element, + xt_text, + NULL, + NULL +}; + +struct xt_parser *xt_new( gpointer data ) +{ + struct xt_parser *xt = g_new0( struct xt_parser, 1 ); + + xt->data = data; + xt_reset( xt ); + + return xt; +} + +/* Reset the parser, flush everything we have so far. For example, we need + this for XMPP when doing TLS/SASL to restart the stream. */ +void xt_reset( struct xt_parser *xt ) +{ + if( xt->parser ) + g_markup_parse_context_free( xt->parser ); + + xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); + + if( xt->root ) + { + xt_free_node( xt->root ); + xt->root = NULL; + xt->cur = NULL; + } +} + +/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on + end-of-stream and 1 otherwise. */ +int xt_feed( struct xt_parser *xt, char *text, int text_len ) +{ + if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) + { + return -1; + } + + return !( xt->root && xt->root->flags & XT_COMPLETE ); +} + +/* Find completed nodes and see if a handler has to be called. Passing + a node isn't necessary if you want to start at the root, just pass + NULL. This second argument is needed for recursive calls. FIXME: Retval? */ +int xt_handle( struct xt_parser *xt, struct xt_node *node ) +{ + struct xt_node *c; + xt_status st; + int i; + + /* Let's just hope xt->root isn't NULL! */ + if( node == NULL ) + return xt_handle( xt, xt->root ); + + for( c = node->children; c; c = c->next ) + if( !xt_handle( xt, c ) ) + return 0; + + if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) + { + for( i = 0; xt->handlers[i].func; i ++ ) + { + /* This one is fun! \o/ */ + + /* If handler.name == NULL it means it should always match. */ + if( ( xt->handlers[i].name == NULL || + /* If it's not, compare. There should always be a name. */ + g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && + /* If handler.parent == NULL, it's a match. */ + ( xt->handlers[i].parent == NULL || + /* If there's a parent node, see if the name matches. */ + ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : + /* If there's no parent, the handler should mention <root> as a parent. */ + g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) + { + st = xt->handlers[i].func( node, xt->data ); + + if( st == XT_ABORT ) + return 0; + else if( st != XT_NEXT ) + break; + } + } + + node->flags |= XT_SEEN; + } + + return 1; +} + +/* Garbage collection: Cleans up all nodes that are handled. Useful for + streams because there's no reason to keep a complete packet history + in memory. */ +void xt_cleanup( struct xt_parser *xt, struct xt_node *node ) +{ + struct xt_node *c, *prev; + + /* Let's just hope xt->root isn't NULL! */ + if( node == NULL ) + return xt_cleanup( xt, xt->root ); + + if( node->flags & XT_SEEN && node == xt->root ) + { + xt_free_node( xt->root ); + xt->root = xt->cur = NULL; + /* xt->cur should be NULL already, BTW... */ + + return; + } + + /* c contains the current node, prev the previous node (or NULL). + I admit, this one's pretty horrible. */ + for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) + { + if( c->flags & XT_SEEN ) + { + /* Remove the node from the linked list. */ + if( prev ) + prev->next = c->next; + else + node->children = c->next; + + xt_free_node( c ); + + /* Since the for loop wants to get c->next, make sure + c points at something that exists (and that c->next + will actually be the next item we should check). c + can be NULL now, if we just removed the first item. + That explains the ? thing in for(). */ + c = prev; + } + else + { + /* This node can't be cleaned up yet, but maybe a + subnode can. */ + xt_cleanup( xt, c ); + } + } +} + +static void xt_to_string_real( struct xt_node *node, GString *str ) +{ + char *buf; + struct xt_node *c; + int i; + + g_string_append_printf( str, "<%s", node->name ); + + for( i = 0; node->attr[i].key; i ++ ) + { + buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); + g_string_append( str, buf ); + g_free( buf ); + } + + if( node->text == NULL && node->children == NULL ) + { + g_string_append( str, "/>" ); + return; + } + + g_string_append( str, ">" ); + if( node->text_len > 0 ) + { + buf = g_markup_escape_text( node->text, node->text_len ); + g_string_append( str, buf ); + g_free( buf ); + } + + for( c = node->children; c; c = c->next ) + xt_to_string_real( c, str ); + + g_string_append_printf( str, "</%s>", node->name ); +} + +char *xt_to_string( struct xt_node *node ) +{ + GString *ret; + char *real; + + ret = g_string_new( "" ); + xt_to_string_real( node, ret ); + + real = ret->str; + g_string_free( ret, FALSE ); + + return real; +} + +void xt_print( struct xt_node *node ) +{ + int i; + struct xt_node *c; + + printf( "%s\n", xt_to_string( node ) ); + return; + + /* Indentation */ + for( c = node; c->parent; c = c->parent ) + printf( "\t" ); + + /* Start the tag */ + printf( "<%s", node->name ); + + /* Print the attributes */ + for( i = 0; node->attr[i].key; i ++ ) + printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); + + /* /> in case there's really *nothing* inside this tag, otherwise + just >. */ + /* If this tag doesn't have any content at all... */ + if( node->text == NULL && node->children == NULL ) + { + printf( "/>\n" ); + return; + /* Then we're finished! */ + } + + /* Otherwise... */ + printf( ">" ); + + /* Only print the text if it contains more than whitespace (TEST). */ + if( node->text_len > 0 ) + { + for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); + if( node->text[i] ) + printf( "%s", g_markup_escape_text( node->text, -1 ) ); + } + + if( node->children ) + printf( "\n" ); + + for( c = node->children; c; c = c->next ) + xt_print( c ); + + if( node->children ) + for( c = node; c->parent; c = c->parent ) + printf( "\t" ); + + /* Non-empty tag is now finished. */ + printf( "</%s>\n", node->name ); +} + +/* Frees a node. This doesn't clean up references to itself from parents! */ +void xt_free_node( struct xt_node *node ) +{ + int i; + + g_free( node->name ); + g_free( node->text ); + + for( i = 0; node->attr[i].key; i ++ ) + { + g_free( node->attr[i].key ); + g_free( node->attr[i].value ); + } + g_free( node->attr ); + + while( node->children ) + { + struct xt_node *next = node->children->next; + + xt_free_node( node->children ); + node->children = next; + } + + g_free( node ); +} + +void xt_free( struct xt_parser *xt ) +{ + if( xt->root ) + xt_free_node( xt->root ); + + g_markup_parse_context_free( xt->parser ); + + g_free( xt ); +} + +/* To find a node's child with a specific name, pass the node's children + list, not the node itself! The reason you have to do this by hand: So + that you can also use this function as a find-next. */ +struct xt_node *xt_find_node( struct xt_node *node, char *name ) +{ + while( node ) + { + if( g_strcasecmp( node->name, name ) == 0 ) + break; + + node = node->next; + } + + return node; +} + +char *xt_find_attr( struct xt_node *node, char *key ) +{ + int i; + + for( i = 0; node->attr[i].key; i ++ ) + if( g_strcasecmp( node->attr[i].key, key ) == 0 ) + break; + + return node->attr[i].value; +} + +struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) +{ + struct xt_node *node, *c; + + node = g_new0( struct xt_node, 1 ); + node->name = g_strdup( name ); + node->children = children; + node->attr = g_new0( struct xt_attr, 1 ); + + if( text ) + { + node->text_len = strlen( text ); + node->text = g_memdup( text, node->text_len ); + } + + for( c = children; c; c = c->next ) + { + if( c->parent != NULL ) + { + /* ERROR CONDITION: They seem to have a parent already??? */ + } + + c->parent = node; + } + + return node; +} + +void xt_add_child( struct xt_node *parent, struct xt_node *child ) +{ + struct xt_node *node; + + /* This function can actually be used to add more than one child, so + do handle this properly. */ + for( node = child; node; node = node->next ) + { + if( node->parent != NULL ) + { + /* ERROR CONDITION: They seem to have a parent already??? */ + } + + node->parent = parent; + } + + if( parent->children == NULL ) + { + parent->children = child; + } + else + { + for( node = parent->children; node->next; node = node->next ); + node->next = child; + } +} + +void xt_add_attr( struct xt_node *node, char *key, char *value ) +{ + int i; + + for( i = 0; node->attr[i].key; i ++ ); + node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); + node->attr[i].key = g_strdup( key ); + node->attr[i].value = g_strdup( value ); + node->attr[i+1].key = NULL; +} diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h new file mode 100644 index 00000000..1a198ad5 --- /dev/null +++ b/protocols/jabber/xmltree.h @@ -0,0 +1,90 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* 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, version * +* 2.1. * +* * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +typedef enum +{ + XT_COMPLETE = 1, /* </tag> reached */ + XT_SEEN = 2, /* Handler called (or not defined) */ +} xt_flags; + +typedef enum +{ + XT_ABORT, /* Abort, don't handle the rest anymore */ + XT_HANDLED, /* Handled this tag properly, go to the next one */ + XT_NEXT /* Try if there's another matching handler */ +} xt_status; + +struct xt_attr +{ + char *key, *value; +}; + +struct xt_node +{ + struct xt_node *parent; + struct xt_node *children; + + char *name; + struct xt_attr *attr; + char *text; + int text_len; + + struct xt_node *next; + xt_flags flags; +}; + +typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); + +struct xt_handler_entry +{ + char *name, *parent; + xt_handler_func func; +}; + +struct xt_parser +{ + GMarkupParseContext *parser; + struct xt_node *root; + struct xt_node *cur; + + struct xt_handler_entry *handlers; + gpointer data; + + GError *gerr; +}; + +struct xt_parser *xt_new( gpointer data ); +void xt_reset( struct xt_parser *xt ); +int xt_feed( struct xt_parser *xt, char *text, int text_len ); +int xt_handle( struct xt_parser *xt, struct xt_node *node ); +void xt_cleanup( struct xt_parser *xt, struct xt_node *node ); +char *xt_to_string( struct xt_node *node ); +void xt_print( struct xt_node *node ); +void xt_free_node( struct xt_node *node ); +void xt_free( struct xt_parser *xt ); +struct xt_node *xt_find_node( struct xt_node *node, char *name ); +char *xt_find_attr( struct xt_node *node, char *key ); + +struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); +void xt_add_child( struct xt_node *parent, struct xt_node *child ); +void xt_add_attr( struct xt_node *node, char *key, char *value ); -- cgit v1.2.3 From f06894d8f55b50b632c1d81ad878f8581273ba66 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 20 Sep 2006 12:18:56 +0200 Subject: Added some pretty empty files. --- protocols/jabber/Makefile | 2 +- protocols/jabber/iq.c | 35 ++++++++++ protocols/jabber/jabber.c | 147 +++++++++++++++++++++++++++++++++++++++++ protocols/jabber/jabber.h | 39 +++++++++++ protocols/jabber/jabber_util.c | 48 ++++++++++++++ protocols/jabber/message.c | 36 ++++++++++ protocols/jabber/presence.c | 35 ++++++++++ protocols/jabber/xmltree.h | 5 ++ 8 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 protocols/jabber/iq.c create mode 100644 protocols/jabber/jabber.c create mode 100644 protocols/jabber/jabber.h create mode 100644 protocols/jabber/jabber_util.c create mode 100644 protocols/jabber/message.c create mode 100644 protocols/jabber/presence.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index ee34ec73..bf2424ba 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = jabber.o xmltree.o +objects = iq.o jabber.o jabber_util.o message.o presence.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c new file mode 100644 index 00000000..e3553637 --- /dev/null +++ b/protocols/jabber/iq.c @@ -0,0 +1,35 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - IQ packets * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) +{ + char *from = xt_find_attr( node, "from" ); + + printf( "Received IQ from %s:\n", from ); + xt_print( node ); + + return XT_HANDLED; +} + diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c new file mode 100644 index 00000000..0a091b06 --- /dev/null +++ b/protocols/jabber/jabber.c @@ -0,0 +1,147 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include <glib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <stdio.h> + +#include "xmltree.h" +#include "bitlbee.h" +#include "jabber.h" + +static void jabber_acc_init( account_t *acc ) +{ + set_t *s; + + s = set_add( &acc->set, "port", "5222", set_eval_int, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "priority", "0", set_eval_resprio, acc ); + + s = set_add( &acc->set, "resource", "BitlBee", set_eval_resprio, acc ); + + s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "tls", "try", set_eval_tls, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; +} + +static void jabber_login( account_t *acc ) +{ +} + +static void jabber_close( struct gaim_connection *gc ) +{ +} + +static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) +{ +} + +void jabber_init() +{ + struct prpl *ret = g_new0(struct prpl, 1); + + ret->name = "jabber"; + ret->login = jabber_login; + ret->acc_init = jabber_acc_init; + ret->close = jabber_close; + ret->send_im = jabber_send_im; +// ret->away_states = jabber_away_states; +// ret->get_status_string = jabber_get_status_string; +// ret->set_away = jabber_set_away; +// ret->set_info = jabber_set_info; +// ret->get_info = jabber_get_info; +// ret->add_buddy = jabber_add_buddy; +// ret->remove_buddy = jabber_remove_buddy; +// ret->chat_send = jabber_chat_send; +// ret->chat_invite = jabber_chat_invite; +// ret->chat_leave = jabber_chat_leave; +// ret->chat_open = jabber_chat_open; +// ret->keepalive = jabber_keepalive; +// ret->add_permit = jabber_add_permit; +// ret->rem_permit = jabber_rem_permit; +// ret->add_deny = jabber_add_deny; +// ret->rem_deny = jabber_rem_deny; +// ret->send_typing = jabber_send_typing; + ret->handle_cmp = g_strcasecmp; + + register_protocol(ret); +} + +static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) +{ + return XT_ABORT; +} + +static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) +{ + printf( "Received unknown packet:\n" ); + xt_print( node ); + + return XT_HANDLED; +} + +static const struct xt_handler_entry jabber_handlers[] = { + { "stream:stream", "<root>", jabber_end_of_stream }, + { "iq", "stream:stream", jabber_pkt_iq }, + { "message", "stream:stream", jabber_pkt_message }, + { "presence", "stream:stream", jabber_pkt_presence }, + { NULL, "stream:stream", jabber_pkt_misc }, + { NULL, NULL, NULL } +}; + +#if 0 +int main( int argc, char *argv[] ) +{ + struct xt_parser *xt = xt_new( NULL ); + struct xt_node *msg; + int i; + char buf[512]; + + msg = xt_new_node( "message", NULL, xt_new_node( "body", "blaataap-test", NULL ) ); + xt_add_child( msg, xt_new_node( "html", NULL, xt_new_node( "body", "<b>blaataap in html</b>", NULL ) ) ); + xt_add_attr( msg, "xmlns", "jabber:client" ); + xt_add_attr( xt_find_node( msg->children, "html" ), "xmlns", "html rotte zooi" ); + printf( "%s\n", xt_to_string( msg ) ); + + while( ( i = read( 0, buf, 512 ) ) > 0 ) + { + if( xt_feed( xt, buf, i ) < 1 ) + break; + } + xt->handlers = jabber_handlers; + xt_handle( xt, NULL ); + + xt_cleanup( xt, NULL ); + printf( "%d\n", xt->root ); + + xt_free( xt ); +} +#endif \ No newline at end of file diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h new file mode 100644 index 00000000..72fae75d --- /dev/null +++ b/protocols/jabber/jabber.h @@ -0,0 +1,39 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#ifndef _JABBER_H +#define _JABBER_H + +#include <glib.h> + +#include "xmltree.h" +#include "bitlbee.h" + +xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); +xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); +xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); + +char *set_eval_resprio( set_t *set, char *value ); +char *set_eval_tls( set_t *set, char *value ); + +#endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c new file mode 100644 index 00000000..ff79cb16 --- /dev/null +++ b/protocols/jabber/jabber_util.c @@ -0,0 +1,48 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +char *set_eval_resprio( set_t *set, char *value ) +{ + account_t *acc = set->data; + + /* Only run this stuff if the account is online ATM. */ + if( acc->gc ) + { + /* ... */ + } + + if( g_strcasecmp( set->key, "priority" ) == 0 ) + return set_eval_int( set, value ); + else + return value; +} + +char *set_eval_tls( set_t *set, char *value ) +{ + if( g_strcasecmp( value, "try" ) == 0 ) + return value; + else + return set_eval_bool( set, value ); +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c new file mode 100644 index 00000000..d4326063 --- /dev/null +++ b/protocols/jabber/message.c @@ -0,0 +1,36 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) +{ + char *from = xt_find_attr( node, "from" ); + struct xt_node *msg = xt_find_node( node->children, "body" ); + + printf( "Received MSG from %s: %s\n", from, msg ? msg->text : "<null>" ); + xt_print( node ); + + return XT_HANDLED; +} + diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c new file mode 100644 index 00000000..5383d7aa --- /dev/null +++ b/protocols/jabber/presence.c @@ -0,0 +1,35 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Main file * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) +{ + char *from = xt_find_attr( node, "from" ); + + printf( "Received PRES from %s:\n", from ); + xt_print( node ); + + return XT_HANDLED; +} + diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h index 1a198ad5..cfefadca 100644 --- a/protocols/jabber/xmltree.h +++ b/protocols/jabber/xmltree.h @@ -21,6 +21,9 @@ * * ****************************************************************************/ +#ifndef _XMLTREE_H +#define _XMLTREE_H + typedef enum { XT_COMPLETE = 1, /* </tag> reached */ @@ -88,3 +91,5 @@ char *xt_find_attr( struct xt_node *node, char *key ); struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); void xt_add_child( struct xt_node *parent, struct xt_node *child ); void xt_add_attr( struct xt_node *node, char *key, char *value ); + +#endif -- cgit v1.2.3 From 21167d2d14c333d67445546bb69dd52dd295287d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 20 Sep 2006 21:42:27 +0200 Subject: It can send a valid (pre-XMPP) login packet. Lots of work to do, still... --- protocols/jabber/Makefile | 2 +- protocols/jabber/io.c | 237 +++++++++++++++++++++++++++++++++++++++++ protocols/jabber/iq.c | 81 +++++++++++++- protocols/jabber/jabber.c | 69 ++++++++---- protocols/jabber/jabber.h | 33 ++++++ protocols/jabber/jabber_util.c | 22 +++- protocols/jabber/message.c | 2 +- protocols/jabber/presence.c | 2 +- protocols/jabber/xmltree.c | 13 ++- 9 files changed, 430 insertions(+), 31 deletions(-) create mode 100644 protocols/jabber/io.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index bf2424ba..d4dcc652 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = iq.o jabber.o jabber_util.o message.o presence.o xmltree.o +objects = io.o iq.o jabber.o jabber_util.o message.o presence.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c new file mode 100644 index 00000000..db869714 --- /dev/null +++ b/protocols/jabber/io.c @@ -0,0 +1,237 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - I/O stuff (plain, SSL), queues, etc * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ); + +int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ) +{ + char *buf; + int st; + + buf = xt_to_string( node ); + st = jabber_write( gc, buf, strlen( buf ) ); + g_free( buf ); + + return st; +} + +int jabber_write( struct gaim_connection *gc, char *buf, int len ) +{ + struct jabber_data *jd = gc->proto_data; + + if( jd->tx_len == 0 ) + { + /* If the queue is empty, allocate a new buffer. */ + jd->tx_len = len; + jd->txq = g_memdup( buf, len ); + + /* Try if we can write it immediately so we don't have to do + it via the event handler. If not, add the handler. (In + most cases it probably won't be necessary.) */ + if( jabber_write_callback( gc, jd->fd, GAIM_INPUT_WRITE ) ) + jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, gc ); + } + else + { + /* Just add it to the buffer if it's already filled. The + event handler is already set. */ + jd->txq = g_renew( char, jd->txq, jd->tx_len + len ); + memcpy( jd->txq + jd->tx_len, buf, len ); + jd->tx_len += len; + } + + /* FIXME: write_callback could've generated a real error! */ + return 1; +} + +static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + int st; + + st = write( jd->fd, jd->txq, jd->tx_len ); + + if( st == jd->tx_len ) + { + /* We wrote everything, clear the buffer. */ + g_free( jd->txq ); + jd->txq = NULL; + jd->tx_len = 0; + + return FALSE; + } + else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + { + hide_login_progress_error( gc, "Short write() to server" ); + signoff( gc ); + return FALSE; + } + else if( st > 0 ) + { + char *s; + + s = g_memdup( jd->txq + st, jd->tx_len - st ); + jd->tx_len -= st; + g_free( jd->txq ); + jd->txq = s; + + return FALSE; + } + else + { + /* Just in case we had EINPROGRESS/EAGAIN: */ + + return TRUE; + } +} + +static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + char buf[512]; + int st; + + st = read( fd, buf, sizeof( buf ) ); + + if( st > 0 ) + { + /* Parse. */ + if( !xt_feed( jd->xt, buf, st ) ) + { + hide_login_progress_error( gc, "XML stream error" ); + signoff( gc ); + return FALSE; + } + + /* Execute all handlers. */ + if( !xt_handle( jd->xt, NULL ) ) + { + /* Don't do anything, the handlers should have + aborted the connection already... Or not? FIXME */ + return FALSE; + } + + /* Garbage collection. */ + xt_cleanup( jd->xt, NULL ); + + /* This is a bit hackish, unfortunately. Although xmltree + has nifty event handler stuff, it only calls handlers + when nodes are complete. Since the server should only + send an opening <stream:stream> tag, we have to check + this by hand. :-( */ + if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root ) + { + if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 ) + { + jd->flags |= JFLAG_STREAM_STARTED; + return jabber_start_auth( gc ); + } + else + { + hide_login_progress_error( gc, "XML stream error" ); + signoff( gc ); + return FALSE; + } + } + } + else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + { + hide_login_progress_error( gc, "Error while reading from server" ); + signoff( gc ); + return FALSE; + } + + /* EAGAIN/etc or a successful read. */ + return TRUE; +} + +static gboolean jabber_start_stream( struct gaim_connection *gc ); + +gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) +{ + struct gaim_connection *gc = data; + + if( source == -1 ) + { + hide_login_progress( gc, "Could not connect to server" ); + signoff( gc ); + return FALSE; + } + + set_login_progress( gc, 1, "Connected to server, logging in" ); + + return jabber_start_stream( gc ); +} + +static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) +{ + return XT_ABORT; +} + +static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) +{ + printf( "Received unknown packet:\n" ); + xt_print( node ); + + return XT_HANDLED; +} + +static const struct xt_handler_entry jabber_handlers[] = { + { "stream:stream", "<root>", jabber_end_of_stream }, + { "iq", "stream:stream", jabber_pkt_iq }, + { "message", "stream:stream", jabber_pkt_message }, + { "presence", "stream:stream", jabber_pkt_presence }, + { NULL, "stream:stream", jabber_pkt_misc }, + { NULL, NULL, NULL } +}; + +static gboolean jabber_start_stream( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + int st; + char *greet; + + /* We'll start our stream now, so prepare everything to receive one + from the server too. */ + xt_free( jd->xt ); /* In case we're RE-starting. */ + jd->xt = xt_new( gc ); + jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; + + jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc ); + + greet = g_strdup_printf( "<?xml version='1.0' ?>" + "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " + "xmlns:stream=\"http://etherx.jabber.org/streams\">", jd->server ); + /* Add this when TLS and SASL are supported? */ + // version=\"1.0\">" + + st = jabber_write( gc, greet, strlen( greet ) ); + + g_free( greet ); + + return st; +} diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e3553637..58e3f33c 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -23,13 +23,88 @@ #include "jabber.h" +/* +<iq xmlns="jabber:client" id="BeeX00000001" type="result"><query +xmlns="jabber:iq:auth"><username>wilmer</username><resource/><password/><digest/> +<sequence>499</sequence><token>450D1FFD</token></query></iq> +*/ + xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { - char *from = xt_find_attr( node, "from" ); + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + struct xt_node *query, *reply = NULL; + char *s; + int st; + + query = xt_find_node( node->children, "query" ); - printf( "Received IQ from %s:\n", from ); - xt_print( node ); + if( !query ) + return XT_HANDLED; /* Ignore it for now, don't know what's best... */ + + if( ( s = xt_find_attr( query, "xmlns" ) ) && strcmp( s, "jabber:iq:auth" ) == 0 ) + { + /* Time to authenticate ourselves! */ + reply = xt_new_node( "query", NULL, NULL ); + xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); + xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); + xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + + if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) + { + /* We can do digest authentication, it seems, and of + course we prefer that. */ + SHA_CTX sha; + char hash_hex[40]; + unsigned char hash[20]; + int i; + + shaInit( &sha ); + shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); + shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); + shaFinal( &sha, hash ); + + for( i = 0; i < 20; i ++ ) + sprintf( hash_hex + i * 2, "%02x", hash[i] ); + + xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); + } + else if( xt_find_node( query->children, "password" ) ) + { + /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ + xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); + } + else + { + xt_free_node( reply ); + + hide_login_progress_error( gc, "Can't find suitable authentication method" ); + signoff( gc ); + return XT_ABORT; + } + + reply = jabber_make_packet( "iq", "set", NULL, reply ); + st = jabber_write_packet( gc, reply ); + xt_free_node( reply ); + + return st ? XT_HANDLED : XT_ABORT; + } return XT_HANDLED; } +int jabber_start_auth( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *node; + int st; + + node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) ); + xt_add_attr( node, "xmlns", "jabber:iq:auth" ); + node = jabber_make_packet( "iq", "get", NULL, node ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 0a091b06..9732d6eb 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -27,6 +27,7 @@ #include <ctype.h> #include <stdio.h> +#include "ssl_client.h" #include "xmltree.h" #include "bitlbee.h" #include "jabber.h" @@ -54,14 +55,58 @@ static void jabber_acc_init( account_t *acc ) static void jabber_login( account_t *acc ) { + struct gaim_connection *gc = new_gaim_conn( acc ); + struct jabber_data *jd = g_new0( struct jabber_data, 1 ); + + jd->gc = gc; + gc->proto_data = jd; + + jd->username = g_strdup( acc->user ); + jd->server = strchr( jd->username, '@' ); + + if( jd->server == NULL ) + { + hide_login_progress( gc, "Incomplete account name (format it like <username@jabberserver.name>)" ); + signoff( gc ); + return; + } + + /* So don't think of free()ing jd->server.. :-) */ + *jd->server = 0; + jd->server ++; + + if( set_getbool( &acc->set, "ssl" ) ) + { + signoff( gc ); + /* TODO! */ + } + else + { + jd->fd = proxy_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); + } } static void jabber_close( struct gaim_connection *gc ) { + struct jabber_data *jd = gc->proto_data; + + if( jd->r_inpa >= 0 ) + b_event_remove( jd->r_inpa ); + if( jd->w_inpa >= 0 ) + b_event_remove( jd->w_inpa ); + + if( jd->ssl ) + ssl_disconnect( jd->ssl ); + if( jd->fd >= 0 ) + closesocket( jd->fd ); + + g_free( jd->username ); + g_free( jd ); } static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) { + return 0; } void jabber_init() @@ -95,28 +140,6 @@ void jabber_init() register_protocol(ret); } -static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) -{ - return XT_ABORT; -} - -static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) -{ - printf( "Received unknown packet:\n" ); - xt_print( node ); - - return XT_HANDLED; -} - -static const struct xt_handler_entry jabber_handlers[] = { - { "stream:stream", "<root>", jabber_end_of_stream }, - { "iq", "stream:stream", jabber_pkt_iq }, - { "message", "stream:stream", jabber_pkt_message }, - { "presence", "stream:stream", jabber_pkt_presence }, - { NULL, "stream:stream", jabber_pkt_misc }, - { NULL, NULL, NULL } -}; - #if 0 int main( int argc, char *argv[] ) { @@ -144,4 +167,4 @@ int main( int argc, char *argv[] ) xt_free( xt ); } -#endif \ No newline at end of file +#endif diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 72fae75d..d812ec54 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -29,11 +29,44 @@ #include "xmltree.h" #include "bitlbee.h" +typedef enum +{ + JFLAG_STREAM_STARTED = 1, + JFLAG_AUTHENTICATED = 2, +} jabber_flags_t; + +/* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); +int jabber_start_auth( struct gaim_connection *gc ); + xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); +/* jabber_util.c */ char *set_eval_resprio( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); +struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); + +/* io.c */ +int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); +int jabber_write( struct gaim_connection *gc, char *buf, int len ); +gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); + +struct jabber_data +{ + struct gaim_connection *gc; + + int fd; + void *ssl; + char *txq; + int tx_len; + int r_inpa, w_inpa; + + struct xt_parser *xt; + jabber_flags_t flags; + + char *username; /* USERNAME@server */ + char *server; /* username@SERVER -=> server/domain, not hostname */ +}; #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index ff79cb16..46811d05 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -1,7 +1,7 @@ /***************************************************************************\ * * * BitlBee - An IRC to IM gateway * -* Jabber module - Main file * +* Jabber module - Misc. stuff * * * * Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * * * @@ -23,6 +23,8 @@ #include "jabber.h" +static int next_id = 1; + char *set_eval_resprio( set_t *set, char *value ) { account_t *acc = set->data; @@ -46,3 +48,21 @@ char *set_eval_tls( set_t *set, char *value ) else return set_eval_bool( set, value ); } + +struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ) +{ + char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + struct xt_node *node; + + node = xt_new_node( name, NULL, children ); + + xt_add_attr( node, "id", id ); + if( type ) + xt_add_attr( node, "type", type ); + if( to ) + xt_add_attr( node, "to", to ); + + g_free( id ); + + return node; +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index d4326063..e5f75464 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -1,7 +1,7 @@ /***************************************************************************\ * * * BitlBee - An IRC to IM gateway * -* Jabber module - Main file * +* Jabber module - Handling of message(s) (tags), etc * * * * Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * * * diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 5383d7aa..83b69013 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -1,7 +1,7 @@ /***************************************************************************\ * * * BitlBee - An IRC to IM gateway * -* Jabber module - Main file * +* Jabber module - Handling of presence (tags), etc * * * * Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * * * diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 68c9560d..3d0a2919 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -205,7 +205,9 @@ void xt_cleanup( struct xt_parser *xt, struct xt_node *node ) { struct xt_node *c, *prev; - /* Let's just hope xt->root isn't NULL! */ + if( !xt || !xt->root ) + return; + if( node == NULL ) return xt_cleanup( xt, xt->root ); @@ -356,6 +358,9 @@ void xt_free_node( struct xt_node *node ) { int i; + if( !node ) + return; + g_free( node->name ); g_free( node->text ); @@ -379,6 +384,9 @@ void xt_free_node( struct xt_node *node ) void xt_free( struct xt_parser *xt ) { + if( !xt ) + return; + if( xt->root ) xt_free_node( xt->root ); @@ -407,6 +415,9 @@ char *xt_find_attr( struct xt_node *node, char *key ) { int i; + if( !node ) + return NULL; + for( i = 0; node->attr[i].key; i ++ ) if( g_strcasecmp( node->attr[i].key, key ) == 0 ) break; -- cgit v1.2.3 From 70f6aab8f4b6a1bbd9991e800dde91a02cc363f0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 20 Sep 2006 22:09:19 +0200 Subject: It now requests a roster when logged in, no parsing for it yet. --- protocols/jabber/iq.c | 54 ++++++++++++++++++++++++++++++++++++++--------- protocols/jabber/jabber.c | 2 ++ protocols/jabber/jabber.h | 1 + 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 58e3f33c..0f1b1036 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -23,26 +23,23 @@ #include "jabber.h" -/* -<iq xmlns="jabber:client" id="BeeX00000001" type="result"><query -xmlns="jabber:iq:auth"><username>wilmer</username><resource/><password/><digest/> -<sequence>499</sequence><token>450D1FFD</token></query></iq> -*/ - xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; struct xt_node *query, *reply = NULL; - char *s; + char *s, *type, *xmlns; int st; query = xt_find_node( node->children, "query" ); + type = xt_find_attr( node, "type" ); - if( !query ) + if( !type ) return XT_HANDLED; /* Ignore it for now, don't know what's best... */ - if( ( s = xt_find_attr( query, "xmlns" ) ) && strcmp( s, "jabber:iq:auth" ) == 0 ) + xmlns = xt_find_attr( query, "xmlns" ); + + if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 ) { /* Time to authenticate ourselves! */ reply = xt_new_node( "query", NULL, NULL ); @@ -78,7 +75,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { xt_free_node( reply ); - hide_login_progress_error( gc, "Can't find suitable authentication method" ); + hide_login_progress( gc, "Can't find suitable authentication method" ); signoff( gc ); return XT_ABORT; } @@ -89,6 +86,26 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return st ? XT_HANDLED : XT_ABORT; } + else if( strcmp( type, "result" ) == 0 ) + { + /* If we weren't authenticated yet, let's assume we are now. + There are cleaner ways to do this, probably, but well.. */ + if( !( jd->flags & JFLAG_AUTHENTICATED ) ) + { + jd->flags |= JFLAG_AUTHENTICATED; + if( !jabber_get_roster( gc ) ) + return XT_ABORT; + } + } + else if( strcmp( type, "error" ) == 0 ) + { + if( !( jd->flags & JFLAG_AUTHENTICATED ) ) + { + hide_login_progress( gc, "Authentication failure" ); + signoff( gc ); + return XT_ABORT; + } + } return XT_HANDLED; } @@ -108,3 +125,20 @@ int jabber_start_auth( struct gaim_connection *gc ) xt_free_node( node ); return st; } + +int jabber_get_roster( struct gaim_connection *gc ) +{ + struct xt_node *node; + int st; + + set_login_progress( gc, 1, "Authenticated, requesting buddy list" ); + + node = xt_new_node( "query", NULL, NULL ); + xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + node = jabber_make_packet( "iq", "get", NULL, node ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 9732d6eb..cc7bac3d 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -100,6 +100,8 @@ static void jabber_close( struct gaim_connection *gc ) if( jd->fd >= 0 ) closesocket( jd->fd ); + xt_free( jd->xt ); + g_free( jd->username ); g_free( jd ); } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index d812ec54..fcf8bbd3 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -38,6 +38,7 @@ typedef enum /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_auth( struct gaim_connection *gc ); +int jabber_get_roster( struct gaim_connection *gc ); xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); -- cgit v1.2.3 From 0b4a0db448d033b8f35f32060bf261374fd81bd8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 20 Sep 2006 22:26:47 +0200 Subject: Now parsing roster properly. (Hopefully...) --- protocols/jabber/iq.c | 19 +++++++++++++++++++ protocols/jabber/jabber.h | 3 +++ protocols/jabber/presence.c | 15 +++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 0f1b1036..119176f9 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -86,6 +86,25 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return st ? XT_HANDLED : XT_ABORT; } + if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 ) + { + struct xt_node *node; + + node = query->children; + while( ( node = xt_find_node( node, "item" ) ) ) + { + char *jid = xt_find_attr( node, "jid" ); + char *name = xt_find_attr( node, "name" ); + char *sub = xt_find_attr( node, "subscription" ); + + if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) + add_buddy( gc, NULL, jid, name ); + + node = node->next; + } + + presence_announce( gc ); + } else if( strcmp( type, "result" ) == 0 ) { /* If we weren't authenticated yet, let's assume we are now. diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index fcf8bbd3..85765628 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -41,7 +41,10 @@ int jabber_start_auth( struct gaim_connection *gc ); int jabber_get_roster( struct gaim_connection *gc ); xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); + +/* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); +int presence_announce( struct gaim_connection *gc ); /* jabber_util.c */ char *set_eval_resprio( set_t *set, char *value ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 83b69013..46e2b3b2 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -33,3 +33,18 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) return XT_HANDLED; } +int presence_announce( struct gaim_connection *gc ) +{ + struct xt_node *node; + int st; + + node = jabber_make_packet( "presence", NULL, NULL, NULL ); + + st = jabber_write_packet( gc, node ); + + if( st ) + account_online( gc ); + + xt_free_node( node ); + return st; +} -- cgit v1.2.3 From dd788bb0b18684be993cc7edf1f0da6f8e36449d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 21 Sep 2006 09:32:39 +0200 Subject: Added enough to not make it crash on login, and it can properly receive messages now. Just try to figure out why it doesn't get typing notifications... --- protocols/jabber/jabber.c | 20 ++++++++++++++++++-- protocols/jabber/message.c | 25 +++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index cc7bac3d..84d7e366 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -111,6 +111,22 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, return 0; } +static GList *jabber_away_states( struct gaim_connection *gc ) +{ + GList *l = NULL; + + l = g_list_append( l, (void*) "Online" ); + l = g_list_append( l, (void*) "Away" ); + l = g_list_append( l, (void*) "Extended Away" ); + l = g_list_append( l, (void*) "Do Not Disturb" ); + + return( l ); +} + +static void jabber_set_away( struct gaim_connection *gc, char *state, char *message ) +{ +} + void jabber_init() { struct prpl *ret = g_new0(struct prpl, 1); @@ -120,9 +136,9 @@ void jabber_init() ret->acc_init = jabber_acc_init; ret->close = jabber_close; ret->send_im = jabber_send_im; -// ret->away_states = jabber_away_states; + ret->away_states = jabber_away_states; // ret->get_status_string = jabber_get_status_string; -// ret->set_away = jabber_set_away; + ret->set_away = jabber_set_away; // ret->set_info = jabber_set_info; // ret->get_info = jabber_get_info; // ret->add_buddy = jabber_add_buddy; diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index e5f75464..b41522fd 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -25,11 +25,32 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) { + struct gaim_connection *gc = data; char *from = xt_find_attr( node, "from" ); + char *type = xt_find_attr( node, "type" ); struct xt_node *msg = xt_find_node( node->children, "body" ); - printf( "Received MSG from %s: %s\n", from, msg ? msg->text : "<null>" ); - xt_print( node ); + if( !type || !msg ) + return XT_HANDLED; /* Grmbl... FIXME */ + + if( strcmp( type, "chat" ) == 0 ) + { + char *s; + + s = strchr( from, '/' ); + if( s ) + *s = 0; + + serv_got_im( gc, from, msg->text, 0, 0, 0 ); + + if( s ) + *s = '/'; + } + else + { + printf( "Received MSG from %s: %s\n", from, msg ? msg->text : "<null>" ); + xt_print( node ); + } return XT_HANDLED; } -- cgit v1.2.3 From 4a0614e65b45364d4d1f631aeaae047a92c752c5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 21 Sep 2006 11:37:03 +0200 Subject: Added simple parsing of incoming <presence> tags, a nice </stream:stream> at the end of sessions, support for sending messages, and restored the old (and leaking) xt_print(), which I'll only use for debugging. --- protocols/jabber/io.c | 17 ++++++++++++++--- protocols/jabber/jabber.c | 12 +++++++++++- protocols/jabber/jabber.h | 2 ++ protocols/jabber/presence.c | 24 ++++++++++++++++++++++-- protocols/jabber/xmltree.c | 3 --- 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index db869714..8c0b239e 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -169,8 +169,6 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition return TRUE; } -static gboolean jabber_start_stream( struct gaim_connection *gc ); - gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) { struct gaim_connection *gc = data; @@ -209,7 +207,7 @@ static const struct xt_handler_entry jabber_handlers[] = { { NULL, NULL, NULL } }; -static gboolean jabber_start_stream( struct gaim_connection *gc ) +gboolean jabber_start_stream( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; int st; @@ -235,3 +233,16 @@ static gboolean jabber_start_stream( struct gaim_connection *gc ) return st; } + +gboolean jabber_end_stream( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + char eos[] = "</stream:stream>"; + + /* Let's only do this if the queue is currently empty, otherwise it'd + take too long anyway. */ + if( jd->tx_len > 0 ) + return TRUE; + else + return jabber_write( gc, eos, strlen( eos ) ); +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 84d7e366..132a355c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -90,6 +90,8 @@ static void jabber_close( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; + jabber_end_stream( gc ); + if( jd->r_inpa >= 0 ) b_event_remove( jd->r_inpa ); if( jd->w_inpa >= 0 ) @@ -108,7 +110,15 @@ static void jabber_close( struct gaim_connection *gc ) static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) { - return 0; + struct xt_node *node; + int st; + + node = xt_new_node( "body", message, NULL ); + node = jabber_make_packet( "message", "chat", who, node ); + st = jabber_write_packet( gc, node ); + xt_free_node( node ); + + return st; } static GList *jabber_away_states( struct gaim_connection *gc ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 85765628..93e2baab 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -55,6 +55,8 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); int jabber_write( struct gaim_connection *gc, char *buf, int len ); gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); +gboolean jabber_start_stream( struct gaim_connection *gc ); +gboolean jabber_end_stream( struct gaim_connection *gc ); struct jabber_data { diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 46e2b3b2..8004ed40 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -25,10 +25,30 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { + struct gaim_connection *gc = data; char *from = xt_find_attr( node, "from" ); + char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ + char *s; - printf( "Received PRES from %s:\n", from ); - xt_print( node ); + if( !from ) + return XT_HANDLED; + + s = strchr( from, '/' ); + if( s ) + *s = 0; + + if( type == NULL ) + serv_got_update( gc, from, 1, 0, 0, 0, 0, 0 ); + else if( strcmp( type, "unavailable" ) == 0 ) + serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + else + { + printf( "Received PRES from %s:\n", from ); + xt_print( node ); + } + + if( s ) + *s = '/'; return XT_HANDLED; } diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 3d0a2919..049eb5ef 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -304,9 +304,6 @@ void xt_print( struct xt_node *node ) int i; struct xt_node *c; - printf( "%s\n", xt_to_string( node ) ); - return; - /* Indentation */ for( c = node; c->parent; c = c->parent ) printf( "\t" ); -- cgit v1.2.3 From 5bcf70a662244dc77af09d2fffbe913ec6f19393 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 21 Sep 2006 20:44:34 +0200 Subject: Now also sending <presence type="unavailable"/> tag on disconnect, as recommended by rfc3921/5.1.5. --- protocols/jabber/io.c | 20 ++++++++++++++------ protocols/jabber/jabber.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 8c0b239e..b11ef17d 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -234,15 +234,23 @@ gboolean jabber_start_stream( struct gaim_connection *gc ) return st; } -gboolean jabber_end_stream( struct gaim_connection *gc ) +void jabber_end_stream( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; - char eos[] = "</stream:stream>"; /* Let's only do this if the queue is currently empty, otherwise it'd take too long anyway. */ - if( jd->tx_len > 0 ) - return TRUE; - else - return jabber_write( gc, eos, strlen( eos ) ); + if( jd->tx_len == 0 ) + { + char eos[] = "</stream:stream>"; + struct xt_node *node; + int st; + + node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); + st = jabber_write_packet( gc, node ); + xt_free_node( node ); + + if( st ) + jabber_write( gc, eos, strlen( eos ) ); + } } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 93e2baab..45747fcb 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -56,7 +56,7 @@ int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); int jabber_write( struct gaim_connection *gc, char *buf, int len ); gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); gboolean jabber_start_stream( struct gaim_connection *gc ); -gboolean jabber_end_stream( struct gaim_connection *gc ); +void jabber_end_stream( struct gaim_connection *gc ); struct jabber_data { -- cgit v1.2.3 From deff0406d501264e1d91203ea8f91411a150e35f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 21 Sep 2006 21:48:17 +0200 Subject: Implemented set_away() (VERY simple version, have to add an away state table like in the MSN module), added sending of keepalive "packets" and removed old main() code (for testing only) from jabber.c. --- protocols/jabber/jabber.c | 44 ++++++++++++-------------------------------- protocols/jabber/jabber.h | 1 + protocols/jabber/presence.c | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 132a355c..13eac23e 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -121,6 +121,7 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, return st; } +/* TODO: For away state handling, implement some list like the one for MSN. */ static GList *jabber_away_states( struct gaim_connection *gc ) { GList *l = NULL; @@ -135,11 +136,19 @@ static GList *jabber_away_states( struct gaim_connection *gc ) static void jabber_set_away( struct gaim_connection *gc, char *state, char *message ) { + /* For now let's just always set state to "away" and send the message, if available. */ + presence_send( gc, NULL, g_strcasecmp( state, "Online" ) == 0 ? NULL : "away", message ); +} + +static void jabber_keepalive( struct gaim_connection *gc ) +{ + /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ + jabber_write( gc, "\n", 1 ); } void jabber_init() { - struct prpl *ret = g_new0(struct prpl, 1); + struct prpl *ret = g_new0( struct prpl, 1 ); ret->name = "jabber"; ret->login = jabber_login; @@ -157,7 +166,7 @@ void jabber_init() // ret->chat_invite = jabber_chat_invite; // ret->chat_leave = jabber_chat_leave; // ret->chat_open = jabber_chat_open; -// ret->keepalive = jabber_keepalive; + ret->keepalive = jabber_keepalive; // ret->add_permit = jabber_add_permit; // ret->rem_permit = jabber_rem_permit; // ret->add_deny = jabber_add_deny; @@ -165,34 +174,5 @@ void jabber_init() // ret->send_typing = jabber_send_typing; ret->handle_cmp = g_strcasecmp; - register_protocol(ret); -} - -#if 0 -int main( int argc, char *argv[] ) -{ - struct xt_parser *xt = xt_new( NULL ); - struct xt_node *msg; - int i; - char buf[512]; - - msg = xt_new_node( "message", NULL, xt_new_node( "body", "blaataap-test", NULL ) ); - xt_add_child( msg, xt_new_node( "html", NULL, xt_new_node( "body", "<b>blaataap in html</b>", NULL ) ) ); - xt_add_attr( msg, "xmlns", "jabber:client" ); - xt_add_attr( xt_find_node( msg->children, "html" ), "xmlns", "html rotte zooi" ); - printf( "%s\n", xt_to_string( msg ) ); - - while( ( i = read( 0, buf, 512 ) ) > 0 ) - { - if( xt_feed( xt, buf, i ) < 1 ) - break; - } - xt->handlers = jabber_handlers; - xt_handle( xt, NULL ); - - xt_cleanup( xt, NULL ); - printf( "%d\n", xt->root ); - - xt_free( xt ); + register_protocol( ret ); } -#endif diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 45747fcb..775cd787 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -45,6 +45,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); /* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); int presence_announce( struct gaim_connection *gc ); +int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ); /* jabber_util.c */ char *set_eval_resprio( set_t *set, char *value ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 8004ed40..75e8786c 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -53,6 +53,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) return XT_HANDLED; } +/* Send the <presence/> tag that finalizes the whole login process, from here + we'll actually show up as online to our buddies. */ int presence_announce( struct gaim_connection *gc ) { struct xt_node *node; @@ -68,3 +70,20 @@ int presence_announce( struct gaim_connection *gc ) xt_free_node( node ); return st; } + +int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ) +{ + struct xt_node *node; + int st; + + node = jabber_make_packet( "presence", NULL, to, NULL ); + if( show ) + xt_add_child( node, xt_new_node( "show", show, NULL ) ); + if( status ) + xt_add_child( node, xt_new_node( "status", status, NULL ) ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} -- cgit v1.2.3 From 59974884ba72d6e8fa008d07ee93bd228d30a99c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 22 Sep 2006 14:04:35 +0200 Subject: Basic SASL (PLAIN only ATM) authentication code. Doesn't log in completely yet. --- protocols/jabber/Makefile | 2 +- protocols/jabber/io.c | 15 ++++-- protocols/jabber/jabber.h | 11 +++- protocols/jabber/sasl.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 protocols/jabber/sasl.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index d4dcc652..c084b1f4 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = io.o iq.o jabber.o jabber_util.o message.o presence.o xmltree.o +objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index b11ef17d..c7c1d8d9 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -135,6 +135,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition return FALSE; } + if( jd->flags & JFLAG_STREAM_RESTART ) + { + jd->flags &= ~JFLAG_STREAM_RESTART; + xt_reset( jd->xt ); + jabber_start_stream( gc ); + } + /* Garbage collection. */ xt_cleanup( jd->xt, NULL ); @@ -203,6 +210,10 @@ static const struct xt_handler_entry jabber_handlers[] = { { "iq", "stream:stream", jabber_pkt_iq }, { "message", "stream:stream", jabber_pkt_message }, { "presence", "stream:stream", jabber_pkt_presence }, + { "mechanisms", "stream:features", sasl_pkt_mechanisms }, + { "challenge", "stream:stream", sasl_pkt_challenge }, + { "success", "stream:stream", sasl_pkt_result }, + { "failure", "stream:stream", sasl_pkt_result }, { NULL, "stream:stream", jabber_pkt_misc }, { NULL, NULL, NULL } }; @@ -223,9 +234,7 @@ gboolean jabber_start_stream( struct gaim_connection *gc ) greet = g_strdup_printf( "<?xml version='1.0' ?>" "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " - "xmlns:stream=\"http://etherx.jabber.org/streams\">", jd->server ); - /* Add this when TLS and SASL are supported? */ - // version=\"1.0\">" + "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server ); st = jabber_write( gc, greet, strlen( greet ) ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 775cd787..03fe57a7 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -31,8 +31,10 @@ typedef enum { - JFLAG_STREAM_STARTED = 1, - JFLAG_AUTHENTICATED = 2, + JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ + JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ + JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ + JFLAG_SUPPORTS_TLS = 8, /* Set when there's <starttls/> in <stream:features>. */ } jabber_flags_t; /* iq.c */ @@ -59,6 +61,11 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c gboolean jabber_start_stream( struct gaim_connection *gc ); void jabber_end_stream( struct gaim_connection *gc ); +/* sasl.c */ +xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ); +xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); +xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); + struct jabber_data { struct gaim_connection *gc; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c new file mode 100644 index 00000000..da577877 --- /dev/null +++ b/protocols/jabber/sasl.c @@ -0,0 +1,124 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - SASL authentication * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" +#include "base64.h" + +#define SASL_NS "urn:ietf:params:xml:ns:xmpp-sasl" + +xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + struct xt_node *c, *reply; + char *s; + int sup_plain = 0, sup_digest = 0; + + s = xt_find_attr( node, "xmlns" ); + if( !s || strcmp( s, SASL_NS ) != 0 ) + { + signoff( gc ); + return XT_ABORT; + } + + c = node->children; + while( ( c = xt_find_node( c, "mechanism" ) ) ) + { + if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) + sup_plain = 1; + if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) + sup_digest = 1; + + c = c->next; + } + + if( !sup_plain && !sup_digest ) + { + signoff( gc ); + return XT_ABORT; + } + + reply = xt_new_node( "auth", NULL, NULL ); + xt_add_attr( reply, "xmlns", SASL_NS ); + + if( sup_plain ) + { + int len; + + xt_add_attr( reply, "mechanism", "PLAIN" ); + + /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ + len = strlen( jd->username ) + strlen( gc->acc->pass ) + 2; + s = g_malloc( len + 1 ); + s[0] = 0; + strcpy( s + 1, jd->username ); + strcpy( s + 2 + strlen( jd->username ), gc->acc->pass ); + reply->text = base64_encode( s, len ); + reply->text_len = strlen( reply->text ); + g_free( s ); + } + + if( !jabber_write_packet( gc, reply ) ) + { + xt_free_node( reply ); + return XT_ABORT; + } + xt_free_node( reply ); + + /* To prevent classic authentication from happening. */ + jd->flags |= JFLAG_STREAM_STARTED; + + return XT_HANDLED; +} + +xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) +{ +} + +xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + char *s; + + s = xt_find_attr( node, "xmlns" ); + if( !s || strcmp( s, SASL_NS ) != 0 ) + { + signoff( gc ); + return XT_ABORT; + } + + if( strcmp( node->name, "success" ) == 0 ) + { + set_login_progress( gc, 1, "Authentication finished" ); + jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; + } + else if( strcmp( node->name, "failure" ) == 0 ) + { + hide_login_progress( gc, "Authentication failure" ); + signoff( gc ); + return XT_ABORT; + } + + return XT_HANDLED; +} -- cgit v1.2.3 From 8d7429102adf8dce6844f2f3da2723d1f87c6442 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 22 Sep 2006 18:56:58 +0200 Subject: Fixed return value on incomplete write()s in write handler, protection against write()ing to sockets that are closed already, hopefully sane detection for SASL support, and only sending type=unavailable presence tag to logged in sessions. --- protocols/jabber/io.c | 67 ++++++++++++++++++++++++++++++++++++++++------- protocols/jabber/iq.c | 2 +- protocols/jabber/jabber.h | 4 +-- protocols/jabber/sasl.c | 20 ++++++++++++++ protocols/nogaim.c | 5 ++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index c7c1d8d9..8f2ce0f1 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -72,6 +72,9 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition struct jabber_data *jd = gc->proto_data; int st; + if( jd->fd == -1 ) + return FALSE; + st = write( jd->fd, jd->txq, jd->tx_len ); if( st == jd->tx_len ) @@ -85,6 +88,10 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition } else if( st == 0 || ( st < 0 && !sockerr_again() ) ) { + /* Set fd to -1 to make sure we won't write to it anymore. */ + closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ + jd->fd = -1; + hide_login_progress_error( gc, "Short write() to server" ); signoff( gc ); return FALSE; @@ -98,7 +105,7 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition g_free( jd->txq ); jd->txq = s; - return FALSE; + return TRUE; } else { @@ -115,6 +122,9 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition char buf[512]; int st; + if( jd->fd == -1 ) + return FALSE; + st = read( fd, buf, sizeof( buf ) ); if( st > 0 ) @@ -138,7 +148,6 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( jd->flags & JFLAG_STREAM_RESTART ) { jd->flags &= ~JFLAG_STREAM_RESTART; - xt_reset( jd->xt ); jabber_start_stream( gc ); } @@ -155,7 +164,12 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 ) { jd->flags |= JFLAG_STREAM_STARTED; - return jabber_start_auth( gc ); + + /* If there's no version attribute, assume + this is an old server that can't do SASL + authentication. */ + if( !sasl_supported( gc ) ) + return jabber_start_iq_auth( gc ); } else { @@ -167,6 +181,9 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } else if( st == 0 || ( st < 0 && !sockerr_again() ) ) { + closesocket( jd->fd ); + jd->fd = -1; + hide_login_progress_error( gc, "Error while reading from server" ); signoff( gc ); return FALSE; @@ -197,6 +214,33 @@ static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) return XT_ABORT; } +static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + struct xt_node *c; + + c = xt_find_node( node->children, "starttls" ); + if( c ) + { + /* + jd->flags |= JFLAG_SUPPORTS_TLS; + if( xt_find_node( c->children, "required" ) ) + jd->flags |= JFLAG_REQUIRES_TLS; + */ + } + + /* This flag is already set if we authenticated via SASL, so now + we can resume the session in the new stream. */ + if( jd->flags & JFLAG_AUTHENTICATED ) + { + if( !jabber_get_roster( gc ) ) + return XT_ABORT; + } + + return XT_HANDLED; +} + static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) { printf( "Received unknown packet:\n" ); @@ -207,9 +251,10 @@ static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) static const struct xt_handler_entry jabber_handlers[] = { { "stream:stream", "<root>", jabber_end_of_stream }, - { "iq", "stream:stream", jabber_pkt_iq }, { "message", "stream:stream", jabber_pkt_message }, { "presence", "stream:stream", jabber_pkt_presence }, + { "iq", "stream:stream", jabber_pkt_iq }, + { "stream:features", "stream:stream", jabber_pkt_features }, { "mechanisms", "stream:features", sasl_pkt_mechanisms }, { "challenge", "stream:stream", sasl_pkt_challenge }, { "success", "stream:stream", sasl_pkt_result }, @@ -230,7 +275,8 @@ gboolean jabber_start_stream( struct gaim_connection *gc ) jd->xt = xt_new( gc ); jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; - jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc ); + if( jd->r_inpa <= 0 ) + jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc ); greet = g_strdup_printf( "<?xml version='1.0' ?>" "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " @@ -253,11 +299,14 @@ void jabber_end_stream( struct gaim_connection *gc ) { char eos[] = "</stream:stream>"; struct xt_node *node; - int st; + int st = 1; - node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); - st = jabber_write_packet( gc, node ); - xt_free_node( node ); + if( gc->flags & OPT_LOGGED_IN ) + { + node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); + st = jabber_write_packet( gc, node ); + xt_free_node( node ); + } if( st ) jabber_write( gc, eos, strlen( eos ) ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 119176f9..bcce5289 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -129,7 +129,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return XT_HANDLED; } -int jabber_start_auth( struct gaim_connection *gc ) +int jabber_start_iq_auth( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; struct xt_node *node; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 03fe57a7..f8b604b0 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -34,12 +34,11 @@ typedef enum JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ - JFLAG_SUPPORTS_TLS = 8, /* Set when there's <starttls/> in <stream:features>. */ } jabber_flags_t; /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); -int jabber_start_auth( struct gaim_connection *gc ); +int jabber_start_iq_auth( struct gaim_connection *gc ); int jabber_get_roster( struct gaim_connection *gc ); xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); @@ -65,6 +64,7 @@ void jabber_end_stream( struct gaim_connection *gc ); xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ); xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); +gboolean sasl_supported( struct gaim_connection *gc ); struct jabber_data { diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index da577877..2f75e733 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -34,6 +34,15 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) char *s; int sup_plain = 0, sup_digest = 0; + if( !sasl_supported( gc ) ) + { + /* Should abort this now, since we should already be doing + IQ authentication. Strange things happen when you try + to do both... */ + serv_got_crap( gc, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); + return XT_HANDLED; + } + s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, SASL_NS ) != 0 ) { @@ -93,6 +102,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) { + return XT_HANDLED; } xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) @@ -122,3 +132,13 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) return XT_HANDLED; } + +/* This one is needed to judge if we'll do authentication using IQ or SASL. + It's done by checking if the <stream:stream> from the server has a + version attribute. I don't know if this is the right way though... */ +gboolean sasl_supported( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + + return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != NULL; +} diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 47e2bda6..ec87ccd5 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -279,6 +279,11 @@ void signoff( struct gaim_connection *gc ) user_t *t, *u = irc->users; account_t *a; + /* Nested calls might happen sometimes, this is probably the best + place to catch them. */ + if( gc->flags & OPT_LOGGING_OUT ) + return; + serv_got_crap( gc, "Signing off.." ); b_event_remove( gc->keepalive ); -- cgit v1.2.3 From fe7a55434385fd858453dffdbb425a21f41e3859 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 22 Sep 2006 20:39:31 +0200 Subject: Better detection of successful IQ authentication (using packet caching), properly working SASL authentication (although only PLAIN so far). --- protocols/jabber/io.c | 33 ++++++++++++++++++++++++++++++--- protocols/jabber/iq.c | 34 ++++++++++++++++++++++++++++------ protocols/jabber/jabber.c | 6 ++++++ protocols/jabber/jabber.h | 6 ++++++ protocols/jabber/jabber_util.c | 29 +++++++++++++++++++++++++++-- protocols/jabber/sasl.c | 10 ++++++++-- 6 files changed, 105 insertions(+), 13 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 8f2ce0f1..333e3123 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -218,7 +218,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; - struct xt_node *c; + struct xt_node *c, *reply; c = xt_find_node( node->children, "starttls" ); if( c ) @@ -230,9 +230,36 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) */ } + if( ( c = xt_find_node( node->children, "bind" ) ) ) + { + reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); + reply = jabber_make_packet( "iq", "set", NULL, reply ); + jabber_cache_packet( gc, reply ); + + if( !jabber_write_packet( gc, reply ) ) + return XT_ABORT; + + jd->flags |= JFLAG_WAIT_BIND; + } + + if( ( c = xt_find_node( node->children, "session" ) ) ) + { + reply = xt_new_node( "session", NULL, NULL ); + xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); + reply = jabber_make_packet( "iq", "set", NULL, reply ); + jabber_cache_packet( gc, reply ); + + if( !jabber_write_packet( gc, reply ) ) + return XT_ABORT; + + jd->flags |= JFLAG_WAIT_SESSION; + } + /* This flag is already set if we authenticated via SASL, so now - we can resume the session in the new stream. */ - if( jd->flags & JFLAG_AUTHENTICATED ) + we can resume the session in the new stream, if we don't have + to bind/initialize the session. */ + if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { if( !jabber_get_roster( gc ) ) return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index bcce5289..fbb4a38b 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,7 +27,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; - struct xt_node *query, *reply = NULL; + struct xt_node *query, *reply = NULL, *orig = NULL; char *s, *type, *xmlns; int st; @@ -39,6 +39,9 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xmlns = xt_find_attr( query, "xmlns" ); + if( ( s = xt_find_attr( node, "id" ) ) ) + orig = jabber_packet_from_cache( gc, s ); + if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 ) { /* Time to authenticate ourselves! */ @@ -81,8 +84,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } reply = jabber_make_packet( "iq", "set", NULL, reply ); + jabber_cache_packet( gc, reply ); st = jabber_write_packet( gc, reply ); - xt_free_node( reply ); return st ? XT_HANDLED : XT_ABORT; } @@ -105,16 +108,35 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) presence_announce( gc ); } - else if( strcmp( type, "result" ) == 0 ) + else if( strcmp( type, "result" ) == 0 && orig ) { - /* If we weren't authenticated yet, let's assume we are now. - There are cleaner ways to do this, probably, but well.. */ - if( !( jd->flags & JFLAG_AUTHENTICATED ) ) + struct xt_node *node; + + if( !( jd->flags & JFLAG_AUTHENTICATED ) && + ( node = xt_find_node( orig->children, "query" ) ) && + ( node = xt_find_node( node->children, "username" ) ) && + node->text_len ) { + /* This happens when we just successfully authenticated + the old (non-SASL) way. */ jd->flags |= JFLAG_AUTHENTICATED; if( !jabber_get_roster( gc ) ) return XT_ABORT; } + else if( ( node = xt_find_node( orig->children, "bind" ) ) || + ( node = xt_find_node( orig->children, "session" ) ) ) + { + if( strcmp( node->name, "bind" ) == 0 ) + jd->flags &= ~JFLAG_WAIT_BIND; + else if( strcmp( node->name, "session" ) == 0 ) + jd->flags &= ~JFLAG_WAIT_SESSION; + + if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) + { + if( !jabber_get_roster( gc ) ) + return XT_ABORT; + } + } } else if( strcmp( type, "error" ) == 0 ) { diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 13eac23e..c8525db5 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -75,6 +75,8 @@ static void jabber_login( account_t *acc ) *jd->server = 0; jd->server ++; + jd->node_cache = xt_new_node( "cache", NULL, NULL ); + if( set_getbool( &acc->set, "ssl" ) ) { signoff( gc ); @@ -102,6 +104,10 @@ static void jabber_close( struct gaim_connection *gc ) if( jd->fd >= 0 ) closesocket( jd->fd ); + if( jd->tx_len ) + g_free( jd->txq ); + + xt_free_node( jd->node_cache ); xt_free( jd->xt ); g_free( jd->username ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index f8b604b0..c2d3867e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -34,6 +34,8 @@ typedef enum JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ + JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply before we continue. */ + JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ } jabber_flags_t; /* iq.c */ @@ -52,6 +54,8 @@ int presence_send( struct gaim_connection *gc, char *to, char *show, char *statu char *set_eval_resprio( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); +void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); +struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ); /* io.c */ int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); @@ -81,6 +85,8 @@ struct jabber_data char *username; /* USERNAME@server */ char *server; /* username@SERVER -=> server/domain, not hostname */ + + struct xt_node *node_cache; }; #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 46811d05..88b9e55d 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -51,18 +51,43 @@ char *set_eval_tls( set_t *set, char *value ) struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ) { - char *id = g_strdup_printf( "BeeX%04x", next_id++ ); struct xt_node *node; node = xt_new_node( name, NULL, children ); - xt_add_attr( node, "id", id ); if( type ) xt_add_attr( node, "type", type ); if( to ) xt_add_attr( node, "to", to ); + return node; +} + +/* Cache a node/packet for later use. Mainly useful for IQ packets if you need + them when you receive the response. Use this BEFORE sending the packet so + it'll get an id= tag, and do NOT free() the packet after writing it! */ +void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +{ + struct jabber_data *jd = gc->proto_data; + char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + + /* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ + + xt_add_attr( node, "id", id ); + xt_add_child( jd->node_cache, node ); g_free( id ); +} + +/* Emptying this cache is a BIG TODO! */ +struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *node; + char *s; + + for( node = jd->node_cache->children; node; node = node->next ) + if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) + break; return node; } diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 2f75e733..13ff9d26 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -70,7 +70,13 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) reply = xt_new_node( "auth", NULL, NULL ); xt_add_attr( reply, "xmlns", SASL_NS ); - if( sup_plain ) + if( sup_digest && 0 ) + { + xt_add_attr( reply, "mechanism", "DIGEST-MD5" ); + + /* The rest will be done later, when we receive a <challenge/>. */ + } + else if( sup_plain ) { int len; @@ -140,5 +146,5 @@ gboolean sasl_supported( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; - return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != NULL; + return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL; } -- cgit v1.2.3 From d8e04849607d4a5ca590752dce37954f12179580 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 23 Sep 2006 00:49:40 +0200 Subject: Implemented support for SASL DIGEST-MD5 authentication. --- protocols/jabber/sasl.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 13ff9d26..7a3ca112 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -70,7 +70,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) reply = xt_new_node( "auth", NULL, NULL ); xt_add_attr( reply, "xmlns", SASL_NS ); - if( sup_digest && 0 ) + if( sup_digest ) { xt_add_attr( reply, "mechanism", "DIGEST-MD5" ); @@ -106,9 +106,186 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) return XT_HANDLED; } +static char *sasl_get_part( char *data, char *field ) +{ + int i, len; + + len = strlen( field ); + + if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' ) + { + i = strlen( field ) + 1; + } + else + { + for( i = 0; data[i]; i ++ ) + { + /* If we have a ", skip until it's closed again. */ + if( data[i] == '"' ) + { + i ++; + while( data[i] != '"' || data[i-1] == '\\' ) + i ++; + } + + /* If we got a comma, we got a new field. Check it. */ + if( data[i] == ',' && + g_strncasecmp( data + i + 1, field, len ) == 0 && + data[i+len+1] == '=' ) + { + i += len + 2; + break; + } + } + } + + if( data[i] == '"' ) + { + int j; + char *ret; + + i ++; + len = 0; + while( data[i+len] != '"' || data[i+len-1] == '\\' ) + len ++; + + ret = g_strndup( data + i, len ); + for( i = j = 0; ret[i]; i ++ ) + { + if( ret[i] == '\\' ) + { + ret[j++] = ret[++i]; + } + else + { + ret[j++] = ret[i]; + } + } + ret[j] = 0; + + return ret; + } + else if( data[i] ) + { + len = 0; + while( data[i+len] && data[i+len] != ',' ) + len ++; + + return g_strndup( data + i, len ); + } + else + { + return NULL; + } +} + xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) { - return XT_HANDLED; + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + struct xt_node *reply = NULL; + char *nonce = NULL, *realm = NULL, *cnonce = NULL, cnonce_bin[30]; + char *digest_uri = NULL; + char *dec = NULL; + char *s = NULL; + xt_status ret = XT_ABORT; + + if( node->text_len == 0 ) + goto error; + + dec = frombase64( node->text ); + + if( !( s = sasl_get_part( dec, "rspauth" ) ) ) + { + /* See RFC 2831 for for information. */ + md5_state_t A1, A2, H; + md5_byte_t A1r[16], A2r[16], Hr[16]; + char A1h[33], A2h[33], Hh[33]; + int i; + + nonce = sasl_get_part( dec, "nonce" ); + realm = sasl_get_part( dec, "realm" ); + + if( !nonce || !realm ) + goto error; + + random_bytes( (unsigned char *) cnonce_bin, sizeof( cnonce_bin ) ); + cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) ); + digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server ); + + /* Generate the MD5 hash of username:realm:password, + I decided to call it H. */ + md5_init( &H ); + s = g_strdup_printf( "%s:%s:%s", jd->username, realm, gc->acc->pass ); + md5_append( &H, (unsigned char *) s, strlen( s ) ); + g_free( s ); + md5_finish( &H, Hr ); + + /* Now generate the hex. MD5 hash of H:nonce:cnonce, called A1. */ + md5_init( &A1 ); + s = g_strdup_printf( ":%s:%s", nonce, cnonce ); + md5_append( &A1, Hr, 16 ); + md5_append( &A1, (unsigned char *) s, strlen( s ) ); + g_free( s ); + md5_finish( &A1, A1r ); + for( i = 0; i < 16; i ++ ) + sprintf( A1h + i * 2, "%02x", A1r[i] ); + + /* A2... */ + md5_init( &A2 ); + s = g_strdup_printf( "%s:%s", "AUTHENTICATE", digest_uri ); + md5_append( &A2, (unsigned char *) s, strlen( s ) ); + g_free( s ); + md5_finish( &A2, A2r ); + for( i = 0; i < 16; i ++ ) + sprintf( A2h + i * 2, "%02x", A2r[i] ); + + /* Final result: A1:nonce:00000001:cnonce:auth:A2. Let's reuse H for it. */ + md5_init( &H ); + s = g_strdup_printf( "%s:%s:%s:%s:%s:%s", A1h, nonce, "00000001", cnonce, "auth", A2h ); + md5_append( &H, (unsigned char *) s, strlen( s ) ); + g_free( s ); + md5_finish( &H, Hr ); + for( i = 0; i < 16; i ++ ) + sprintf( Hh + i * 2, "%02x", Hr[i] ); + + /* Now build the SASL response string: */ + g_free( dec ); + dec = g_strdup_printf( "username=\"%s\",realm=\"%s\",nonce=\"%s\",cnonce=\"%s\"," + "nc=%08x,qop=auth,digest-uri=\"%s\",response=%s,charset=%s", + jd->username, realm, nonce, cnonce, 1, digest_uri, Hh, "utf-8" ); + s = tobase64( dec ); + } + else + { + /* We found rspauth, but don't really care... */ + g_free( s ); + s = NULL; + } + + reply = xt_new_node( "response", s, NULL ); + xt_add_attr( reply, "xmlns", SASL_NS ); + + if( !jabber_write_packet( gc, reply ) ) + goto silent_error; + + ret = XT_HANDLED; + goto silent_error; + +error: + hide_login_progress( gc, "Incorrect SASL challenge received" ); + signoff( gc ); + +silent_error: + g_free( digest_uri ); + g_free( cnonce ); + g_free( nonce ); + g_free( realm ); + g_free( dec ); + g_free( s ); + xt_free_node( reply ); + + return ret; } xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) -- cgit v1.2.3 From 5e202b09f2cd9faff5f316ae6804facb5342eace Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 23 Sep 2006 18:18:24 +0200 Subject: Implemented a list of away states, using this for a better set_away(), and got rid of the double <presence> tag sent because of presence_announce(). --- protocols/jabber/iq.c | 2 +- protocols/jabber/jabber.c | 28 ++++++++++++++--------- protocols/jabber/jabber.h | 51 +++++++++++++++++++++++++----------------- protocols/jabber/jabber_util.c | 32 ++++++++++++++++++++++++++ protocols/jabber/presence.c | 20 +---------------- protocols/msn/msn.c | 9 ++++---- protocols/nogaim.c | 2 -- 7 files changed, 88 insertions(+), 56 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index fbb4a38b..5c108379 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -106,7 +106,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) node = node->next; } - presence_announce( gc ); + account_online( gc ); } else if( strcmp( type, "result" ) == 0 && orig ) { diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index c8525db5..b3199cde 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -110,6 +110,7 @@ static void jabber_close( struct gaim_connection *gc ) xt_free_node( jd->node_cache ); xt_free( jd->xt ); + g_free( jd->away_message ); g_free( jd->username ); g_free( jd ); } @@ -127,23 +128,30 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, return st; } -/* TODO: For away state handling, implement some list like the one for MSN. */ static GList *jabber_away_states( struct gaim_connection *gc ) { - GList *l = NULL; + static GList *l = NULL; + int i; - l = g_list_append( l, (void*) "Online" ); - l = g_list_append( l, (void*) "Away" ); - l = g_list_append( l, (void*) "Extended Away" ); - l = g_list_append( l, (void*) "Do Not Disturb" ); + if( l == NULL ) + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) + l = g_list_append( l, (void*) jabber_away_state_list[i].full_name ); - return( l ); + return l; } -static void jabber_set_away( struct gaim_connection *gc, char *state, char *message ) +static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) { - /* For now let's just always set state to "away" and send the message, if available. */ - presence_send( gc, NULL, g_strcasecmp( state, "Online" ) == 0 ? NULL : "away", message ); + struct jabber_data *jd = gc->proto_data; + struct jabber_away_state *state; + + /* Save all this info. We need it, for example, when changing the priority setting. */ + state = (void *) jabber_away_state_by_name( state_txt ); + jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */ + g_free( jd->away_message ); + jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; + + presence_send( gc, NULL, jd->away_state->code, jd->away_message ); } static void jabber_keepalive( struct gaim_connection *gc ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index c2d3867e..29cf6a84 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -38,6 +38,33 @@ typedef enum JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ } jabber_flags_t; +struct jabber_data +{ + struct gaim_connection *gc; + + int fd; + void *ssl; + char *txq; + int tx_len; + int r_inpa, w_inpa; + + struct xt_parser *xt; + jabber_flags_t flags; + + char *username; /* USERNAME@server */ + char *server; /* username@SERVER -=> server/domain, not hostname */ + struct jabber_away_state *away_state; + char *away_message; + + struct xt_node *node_cache; +}; + +struct jabber_away_state +{ + char code[5]; + char *full_name; +}; + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_iq_auth( struct gaim_connection *gc ); @@ -47,7 +74,6 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); /* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); -int presence_announce( struct gaim_connection *gc ); int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ); /* jabber_util.c */ @@ -56,6 +82,10 @@ char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ); +const struct jabber_away_state *jabber_away_state_by_code( char *code ); +const struct jabber_away_state *jabber_away_state_by_name( char *name ); + +extern const struct jabber_away_state jabber_away_state_list[]; /* io.c */ int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); @@ -70,23 +100,4 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); gboolean sasl_supported( struct gaim_connection *gc ); -struct jabber_data -{ - struct gaim_connection *gc; - - int fd; - void *ssl; - char *txq; - int tx_len; - int r_inpa, w_inpa; - - struct xt_parser *xt; - jabber_flags_t flags; - - char *username; /* USERNAME@server */ - char *server; /* username@SERVER -=> server/domain, not hostname */ - - struct xt_node *node_cache; -}; - #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 88b9e55d..21df5126 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -91,3 +91,35 @@ struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) return node; } + +const struct jabber_away_state jabber_away_state_list[] = +{ + { "away", "Away" }, + { "chat", "Free for Chat" }, + { "dnd", "Do not Disturb" }, + { "xa", "Extended Away" }, + { "", "Online" }, + { "", NULL } +}; + +const struct jabber_away_state *jabber_away_state_by_code( char *code ) +{ + int i; + + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) + if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 ) + return jabber_away_state_list + i; + + return NULL; +} + +const struct jabber_away_state *jabber_away_state_by_name( char *name ) +{ + int i; + + for( i = 0; jabber_away_state_list[i].full_name; i ++ ) + if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 ) + return jabber_away_state_list + i; + + return NULL; +} diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 75e8786c..18ce969b 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -53,31 +53,13 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) return XT_HANDLED; } -/* Send the <presence/> tag that finalizes the whole login process, from here - we'll actually show up as online to our buddies. */ -int presence_announce( struct gaim_connection *gc ) -{ - struct xt_node *node; - int st; - - node = jabber_make_packet( "presence", NULL, NULL, NULL ); - - st = jabber_write_packet( gc, node ); - - if( st ) - account_online( gc ); - - xt_free_node( node ); - return st; -} - int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ) { struct xt_node *node; int st; node = jabber_make_packet( "presence", NULL, to, NULL ); - if( show ) + if( show && *show ) xt_add_child( node, xt_new_node( "show", show, NULL ) ); if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 01b011c7..d36d861f 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -182,13 +182,14 @@ static int msn_send_im( struct gaim_connection *gc, char *who, char *message, in static GList *msn_away_states( struct gaim_connection *gc ) { - GList *l = NULL; + static GList *l = NULL; int i; - for( i = 0; msn_away_state_list[i].number > -1; i ++ ) - l = g_list_append( l, (void*) msn_away_state_list[i].name ); + if( l == NULL ) + for( i = 0; msn_away_state_list[i].number > -1; i ++ ) + l = g_list_append( l, (void*) msn_away_state_list[i].name ); - return( l ); + return l; } static char *msn_get_status_string( struct gaim_connection *gc, int number ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index ec87ccd5..36461b32 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1018,8 +1018,6 @@ int bim_set_away( struct gaim_connection *gc, char *away ) gc->acc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away ); } - g_list_free( ms ); - return( 1 ); } -- cgit v1.2.3 From 172a73f1a4b37fa20d1d50496a3faccb8fe6c769 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 12:25:41 +0200 Subject: Updated <presence> stuff to handle changing the priority setting. --- protocols/jabber/jabber.c | 2 +- protocols/jabber/jabber.h | 5 ++++- protocols/jabber/jabber_util.c | 39 ++++++++++++++++++++++++++++++++------- protocols/jabber/presence.c | 12 ++++++++++-- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b3199cde..ee26a007 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -151,7 +151,7 @@ static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char * g_free( jd->away_message ); jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; - presence_send( gc, NULL, jd->away_state->code, jd->away_message ); + presence_send_update( gc ); } static void jabber_keepalive( struct gaim_connection *gc ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 29cf6a84..4a8292ea 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -53,6 +53,9 @@ struct jabber_data char *username; /* USERNAME@server */ char *server; /* username@SERVER -=> server/domain, not hostname */ + + /* After changing one of these two (or the priority setting), call + presence_send_update() to inform the server about the changes. */ struct jabber_away_state *away_state; char *away_message; @@ -74,7 +77,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); /* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); -int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ); +int presence_send_update( struct gaim_connection *gc ); /* jabber_util.c */ char *set_eval_resprio( set_t *set, char *value ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 21df5126..e7a161cc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -28,17 +28,42 @@ static int next_id = 1; char *set_eval_resprio( set_t *set, char *value ) { account_t *acc = set->data; + char *ret; - /* Only run this stuff if the account is online ATM. */ - if( acc->gc ) + if( strcmp( set->key, "priority" ) == 0 ) + ret = set_eval_int( set, value ); + else + ret = value; + + /* Only run this stuff if the account is online ATM, + and if the setting seems to be acceptable. */ + if( acc->gc && ret ) { - /* ... */ + if( strcmp( set->key, "priority" ) == 0 ) + { + /* Although set_eval functions usually are very nice + and convenient, they have one disadvantage: If I + would just call p_s_u() now to send the new prio + setting, it would send the old setting because the + set->value gets changed when the eval returns a + non-NULL value. + + So now I can choose between implementing post-set + functions next to evals, or just do this little + hack: */ + g_free( set->value ); + set->value = g_strdup( ret ); + + /* (Yes, sorry, I prefer the hack. :-P) */ + + presence_send_update( acc->gc ); + } + else + { + } } - if( g_strcasecmp( set->key, "priority" ) == 0 ) - return set_eval_int( set, value ); - else - return value; + return ret; } char *set_eval_tls( set_t *set, char *value ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 18ce969b..d9053c5f 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -53,16 +53,24 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) return XT_HANDLED; } -int presence_send( struct gaim_connection *gc, char *to, char *show, char *status ) +/* Whenever presence information is updated, call this function to inform the + server. */ +int presence_send_update( struct gaim_connection *gc ) { + struct jabber_data *jd = gc->proto_data; struct xt_node *node; + char *show = jd->away_state->code; + char *status = jd->away_message; int st; - node = jabber_make_packet( "presence", NULL, to, NULL ); + node = jabber_make_packet( "presence", NULL, NULL, NULL ); if( show && *show ) xt_add_child( node, xt_new_node( "show", show, NULL ) ); if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); + /* if( set_getint( &gc->acc->set, "priority" ) != 0 ) */ + /* Let's just send this every time... */ + xt_add_child( node, xt_new_node( "priority", set_getstr( &gc->acc->set, "priority" ), NULL ) ); st = jabber_write_packet( gc, node ); -- cgit v1.2.3 From 42127dcd26be4f6746004237eac5333ffbb94f8e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 13:57:45 +0200 Subject: Added support for SSL- and TLS-connections. Checking of the "tls" user setting has to be finished, plus an ssl_starttls() function for the other SSL libraries (this code will only compile with GnuTLS for now). --- lib/ssl_client.h | 4 ++ lib/ssl_gnutls.c | 45 ++++++++++++------- protocols/jabber/io.c | 107 ++++++++++++++++++++++++++++++++++++++++++---- protocols/jabber/jabber.c | 4 +- protocols/jabber/jabber.h | 1 + 5 files changed, 135 insertions(+), 26 deletions(-) diff --git a/lib/ssl_client.h b/lib/ssl_client.h index 964caee4..dcbf9a01 100644 --- a/lib/ssl_client.h +++ b/lib/ssl_client.h @@ -51,6 +51,10 @@ typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition); blocking I/O! (Except for the DNS lookups, for now...) */ G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ); +/* Start an SSL session on an existing fd. Useful for STARTTLS functionality, + for example in Jabber. */ +G_MODULE_EXPORT void *ssl_starttls( int fd, ssl_input_function func, gpointer data ); + /* Obviously you need special read/write functions to read data. */ G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 3ebe1756..fc848bb1 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -62,22 +62,28 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data if( conn->fd < 0 ) { g_free( conn ); - return( NULL ); + return NULL; } - if( !initialized ) - { - gnutls_global_init(); - initialized = TRUE; - atexit( gnutls_global_deinit ); - } + return conn; +} + +/* FIXME: It can happen that the handshake fails even before ssl_connected() + returns already. This function will then return an invalid pointer because + these failures can't be detected properly yet. Maybe ssl_connected() + shouldn't be called directly, but via a short timeout? */ +void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) +{ + struct scd *conn = g_new0( struct scd, 1 ); - gnutls_certificate_allocate_credentials( &conn->xcred ); - gnutls_init( &conn->session, GNUTLS_CLIENT ); - gnutls_set_default_priority( conn->session ); - gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred ); + conn->fd = fd; + conn->func = func; + conn->data = data; + conn->inpa = -1; + + ssl_connected( conn, fd, GAIM_INPUT_WRITE ); - return( conn ); + return conn; } static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); @@ -90,14 +96,23 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con { conn->func( conn->data, NULL, cond ); - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); - g_free( conn ); return FALSE; } + if( !initialized ) + { + gnutls_global_init(); + initialized = TRUE; + atexit( gnutls_global_deinit ); + } + + gnutls_certificate_allocate_credentials( &conn->xcred ); + gnutls_init( &conn->session, GNUTLS_CLIENT ); + gnutls_set_default_priority( conn->session ); + gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred ); + sock_make_nonblocking( conn->fd ); gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 333e3123..f1f62a48 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -22,6 +22,7 @@ \***************************************************************************/ #include "jabber.h" +#include "ssl_client.h" static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ); @@ -75,7 +76,12 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition if( jd->fd == -1 ) return FALSE; - st = write( jd->fd, jd->txq, jd->tx_len ); + if( jd->ssl ) + st = ssl_write( jd->ssl, jd->txq, jd->tx_len ); + else + st = write( jd->fd, jd->txq, jd->tx_len ); + +// if( st > 0 ) write( 1, jd->txq, st ); if( st == jd->tx_len ) { @@ -125,7 +131,12 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( jd->fd == -1 ) return FALSE; - st = read( fd, buf, sizeof( buf ) ); + if( jd->ssl ) + st = ssl_read( jd->ssl, buf, sizeof( buf ) ); + else + st = read( jd->fd, buf, sizeof( buf ) ); + +// if( st > 0 ) write( 1, buf, st ); if( st > 0 ) { @@ -209,6 +220,22 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c return jabber_start_stream( gc ); } +gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ) +{ + struct gaim_connection *gc = data; + + if( source == NULL ) + { + hide_login_progress( gc, "Could not connect to server" ); + signoff( gc ); + return FALSE; + } + + set_login_progress( gc, 1, "Connected to server, logging in" ); + + return jabber_start_stream( gc ); +} + static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) { return XT_ABORT; @@ -221,15 +248,43 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) struct xt_node *c, *reply; c = xt_find_node( node->children, "starttls" ); - if( c ) + if( c && !jd->ssl ) { - /* - jd->flags |= JFLAG_SUPPORTS_TLS; - if( xt_find_node( c->children, "required" ) ) - jd->flags |= JFLAG_REQUIRES_TLS; - */ + /* If the server advertises the STARTTLS feature and if we're + not in a secure connection already: */ + + int try; + + try = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0; + c = xt_find_node( c->children, "required" ); + + /* Only run this if the tls setting is set to true or try: */ + if( ( try | set_getbool( &gc->acc->set, "tls" ) ) ) + { + reply = xt_new_node( "starttls", NULL, NULL ); + xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-tls" ); + if( !jabber_write_packet( gc, reply ) ) + { + xt_free_node( reply ); + return XT_ABORT; + } + xt_free_node( reply ); + + return XT_HANDLED; + } + } + else + { + /* TODO: Abort if TLS is required by the user. */ } + /* This one used to be in jabber_handlers[], but it has to be done + from here to make sure the TLS session will be initialized + properly before we attempt SASL authentication. */ + if( ( c = xt_find_node( node->children, "mechanisms" ) ) ) + if( sasl_pkt_mechanisms( c, data ) == XT_ABORT ) + return XT_ABORT; + if( ( c = xt_find_node( node->children, "bind" ) ) ) { reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); @@ -268,6 +323,40 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) return XT_HANDLED; } +static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) +{ + struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; + char *xmlns; + + xmlns = xt_find_attr( node, "xmlns" ); + + /* Just ignore it when it doesn't seem to be TLS-related (is that at + all possible??). */ + if( !xmlns || strcmp( xmlns, "urn:ietf:params:xml:ns:xmpp-tls" ) != 0 ) + return XT_HANDLED; + + /* We don't want event handlers to touch our TLS session while it's + still initializing! */ + b_event_remove( jd->r_inpa ); + if( jd->tx_len > 0 ) + { + /* Actually the write queue should be empty here, but just + to be sure... */ + b_event_remove( jd->w_inpa ); + g_free( jd->txq ); + jd->txq = NULL; + jd->tx_len = 0; + } + jd->w_inpa = jd->r_inpa = 0; + + set_login_progress( gc, 1, "Converting stream to TLS" ); + + jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, gc ); + + return XT_HANDLED; +} + static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) { printf( "Received unknown packet:\n" ); @@ -282,7 +371,7 @@ static const struct xt_handler_entry jabber_handlers[] = { { "presence", "stream:stream", jabber_pkt_presence }, { "iq", "stream:stream", jabber_pkt_iq }, { "stream:features", "stream:stream", jabber_pkt_features }, - { "mechanisms", "stream:features", sasl_pkt_mechanisms }, + { "proceed", "stream:stream", jabber_pkt_proceed_tls }, { "challenge", "stream:stream", sasl_pkt_challenge }, { "success", "stream:stream", sasl_pkt_result }, { "failure", "stream:stream", sasl_pkt_result }, diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index ee26a007..a337dd68 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -79,8 +79,8 @@ static void jabber_login( account_t *acc ) if( set_getbool( &acc->set, "ssl" ) ) { - signoff( gc ); - /* TODO! */ + jd->ssl = ssl_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); + jd->fd = ssl_getfd( jd->ssl ); } else { diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 4a8292ea..cf84a6e8 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -94,6 +94,7 @@ extern const struct jabber_away_state jabber_away_state_list[]; int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); int jabber_write( struct gaim_connection *gc, char *buf, int len ); gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); +gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ); gboolean jabber_start_stream( struct gaim_connection *gc ); void jabber_end_stream( struct gaim_connection *gc ); -- cgit v1.2.3 From e101506a3e660d3165a89aab0898293b367e2b5b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 19:22:08 +0200 Subject: Better handling of user tls setting. --- protocols/jabber/io.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index f1f62a48..3bc967e0 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -246,20 +246,27 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; struct xt_node *c, *reply; + int trytls; + trytls = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0; c = xt_find_node( node->children, "starttls" ); if( c && !jd->ssl ) { /* If the server advertises the STARTTLS feature and if we're not in a secure connection already: */ - int try; - - try = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0; c = xt_find_node( c->children, "required" ); + if( c && ( !trytls && !set_getbool( &gc->acc->set, "tls" ) ) ) + { + hide_login_progress( gc, "Server requires TLS connections, but TLS is turned off for this account" ); + signoff( gc ); + + return XT_ABORT; + } + /* Only run this if the tls setting is set to true or try: */ - if( ( try | set_getbool( &gc->acc->set, "tls" ) ) ) + if( ( trytls || set_getbool( &gc->acc->set, "tls" ) ) ) { reply = xt_new_node( "starttls", NULL, NULL ); xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-tls" ); @@ -273,9 +280,20 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) return XT_HANDLED; } } - else + else if( !c && !jd->ssl ) { - /* TODO: Abort if TLS is required by the user. */ + /* If the server does not advertise the STARTTLS feature and + we're not in a secure connection already: (Servers have a + habit of not advertising <starttls/> anymore when already + using SSL/TLS. */ + + if( !trytls && set_getbool( &gc->acc->set, "tls" ) ) + { + hide_login_progress( gc, "TLS is turned on for this account, but is not supported by this server" ); + signoff( gc ); + + return XT_ABORT; + } } /* This one used to be in jabber_handlers[], but it has to be done -- cgit v1.2.3 From cfbb3a6e5e11a8d2d162d80958d6ce997104e9d3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 20:08:07 +0200 Subject: Added add_buddy/remove_buddy functions. Removing a contact doesn't seem to work perfectly though. --- protocols/jabber/iq.c | 43 +++++++++++++++++++++++++++++++++++++++++++ protocols/jabber/jabber.c | 16 ++++++++++++++-- protocols/jabber/jabber.h | 4 ++++ protocols/jabber/presence.c | 16 ++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 5c108379..ac5e0932 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -183,3 +183,46 @@ int jabber_get_roster( struct gaim_connection *gc ) xt_free_node( node ); return st; } + +int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) +{ + struct xt_node *node; + int st; + + /* Build the item entry */ + node = xt_new_node( "item", NULL, NULL ); + xt_add_attr( node, "jid", handle ); + if( name ) + xt_add_attr( node, "name", name ); + + /* And pack it into a roster-add packet */ + node = xt_new_node( "query", NULL, node ); + xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + node = jabber_make_packet( "iq", "set", NULL, node ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} + +int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) +{ + struct xt_node *node; + int st; + + /* Build the item entry */ + node = xt_new_node( "item", NULL, NULL ); + xt_add_attr( node, "jid", handle ); + xt_add_attr( node, "subscription", "remove" ); + + /* And pack it into a roster-add packet */ + node = xt_new_node( "query", NULL, node ); + xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + node = jabber_make_packet( "iq", "set", NULL, node ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index a337dd68..21633973 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -154,6 +154,18 @@ static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char * presence_send_update( gc ); } +static void jabber_add_buddy( struct gaim_connection *gc, char *who ) +{ + if( jabber_add_to_roster( gc, who, NULL ) ) + presence_send_request( gc, who, "subscribe" ); +} + +static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group ) +{ + if( jabber_remove_from_roster( gc, who ) ) + presence_send_request( gc, who, "unsubscribe" ); +} + static void jabber_keepalive( struct gaim_connection *gc ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ @@ -174,8 +186,8 @@ void jabber_init() ret->set_away = jabber_set_away; // ret->set_info = jabber_set_info; // ret->get_info = jabber_get_info; -// ret->add_buddy = jabber_add_buddy; -// ret->remove_buddy = jabber_remove_buddy; + ret->add_buddy = jabber_add_buddy; + ret->remove_buddy = jabber_remove_buddy; // ret->chat_send = jabber_chat_send; // ret->chat_invite = jabber_chat_invite; // ret->chat_leave = jabber_chat_leave; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index cf84a6e8..7a2c7783 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -72,12 +72,16 @@ struct jabber_away_state xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_iq_auth( struct gaim_connection *gc ); int jabber_get_roster( struct gaim_connection *gc ); +int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); +int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); +/* message.c */ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); /* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); int presence_send_update( struct gaim_connection *gc ); +int presence_send_request( struct gaim_connection *gc, char *handle, char *request ); /* jabber_util.c */ char *set_eval_resprio( set_t *set, char *value ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index d9053c5f..fa9c1248 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -77,3 +77,19 @@ int presence_send_update( struct gaim_connection *gc ) xt_free_node( node ); return st; } + +/* Send a subscribe/unsubscribe request to a buddy. */ +int presence_send_request( struct gaim_connection *gc, char *handle, char *request ) +{ + struct xt_node *node; + int st; + + node = jabber_make_packet( "presence", NULL, NULL, NULL ); + xt_add_attr( node, "to", handle ); + xt_add_attr( node, "type", request ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} -- cgit v1.2.3 From 8e5e2e9a0ef549c94afc8041dc7d99358f51c9bd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 21:25:06 +0200 Subject: Handling of incoming authorization requests, manual block/allow. (Doesn't seem to be completely like how it works on other IM networks.) --- protocols/jabber/jabber.c | 26 ++++++++++++++++++++++---- protocols/jabber/jabber.h | 1 + protocols/jabber/jabber_util.c | 38 ++++++++++++++++++++++++++++++++++++++ protocols/jabber/presence.c | 15 +++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 21633973..05ff8047 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -172,6 +172,24 @@ static void jabber_keepalive( struct gaim_connection *gc ) jabber_write( gc, "\n", 1 ); } +static void jabber_add_permit( struct gaim_connection *gc, char *who ) +{ + presence_send_request( gc, who, "subscribed" ); +} + +static void jabber_rem_permit( struct gaim_connection *gc, char *who ) +{ + presence_send_request( gc, who, "unsubscribed" ); +} + +static void jabber_add_deny( struct gaim_connection *gc, char *who ) +{ +} + +static void jabber_rem_deny( struct gaim_connection *gc, char *who ) +{ +} + void jabber_init() { struct prpl *ret = g_new0( struct prpl, 1 ); @@ -193,10 +211,10 @@ void jabber_init() // ret->chat_leave = jabber_chat_leave; // ret->chat_open = jabber_chat_open; ret->keepalive = jabber_keepalive; -// ret->add_permit = jabber_add_permit; -// ret->rem_permit = jabber_rem_permit; -// ret->add_deny = jabber_add_deny; -// ret->rem_deny = jabber_rem_deny; + ret->add_permit = jabber_add_permit; + ret->rem_permit = jabber_rem_permit; + ret->add_deny = jabber_add_deny; + ret->rem_deny = jabber_rem_deny; // ret->send_typing = jabber_send_typing; ret->handle_cmp = g_strcasecmp; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 7a2c7783..f05c1c55 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -91,6 +91,7 @@ void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); +void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index e7a161cc..3a0d2004 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -148,3 +148,41 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name ) return NULL; } + +struct jabber_buddy_ask_data +{ + struct gaim_connection *gc; + char *handle; + char *realname; +}; + +static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) +{ + presence_send_request( bla->gc, bla->handle, "subscribed" ); + + if( find_buddy( bla->gc, bla->handle ) == NULL ) + show_got_added( bla->gc, bla->handle, NULL ); + + g_free( bla->handle ); + g_free( bla ); +} + +static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) +{ + presence_send_request( bla->gc, bla->handle, "subscribed" ); + + g_free( bla->handle ); + g_free( bla ); +} + +void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) +{ + struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 ); + char *buf; + + bla->gc = gc; + bla->handle = g_strdup( handle ); + + buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); + do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); +} diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index fa9c1248..1b8008b8 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -41,6 +41,21 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) serv_got_update( gc, from, 1, 0, 0, 0, 0, 0 ); else if( strcmp( type, "unavailable" ) == 0 ) serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + else if( strcmp( type, "subscribe" ) == 0 ) + jabber_buddy_ask( gc, from ); + else if( strcmp( type, "subscribed" ) == 0 ) + serv_got_crap( gc, "%s just accepted your authorization request", from ); + else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) + { + /* Do nothing here. Plenty of control freaks or over-curious + souls get excited when they can see who still has them in + their buddy list and who finally removed them. Somehow I + got the impression that those are the people who get + removed from many buddy lists for "some" reason... + + If you're one of those people, this is your chance to write + your first line of code in C... */ + } else { printf( "Received PRES from %s:\n", from ); -- cgit v1.2.3 From 4ecdc69c19546fd7256e138d7be3cf49d299b36b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 21:56:44 +0200 Subject: Fixed an off-by-one memory allocation bug in xt_new_node(). --- protocols/jabber/xmltree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 049eb5ef..81e0dab5 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -434,7 +434,7 @@ struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) if( text ) { node->text_len = strlen( text ); - node->text = g_memdup( text, node->text_len ); + node->text = g_memdup( text, node->text_len + 1 ); } for( c = children; c; c = c->next ) -- cgit v1.2.3 From a214954bda17730b6251e5c5c26f6d4d23eb1ed9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 24 Sep 2006 22:00:09 +0200 Subject: Added some experimental stuff with typing notifications that seems to show that Gaim doesn't support the official JEP-0085 standard (yet?)... And added simple garbage collection for the node_cache. Will improve it later. --- protocols/jabber/jabber.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 05ff8047..32bc7563 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -117,11 +117,20 @@ static void jabber_close( struct gaim_connection *gc ) static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) { - struct xt_node *node; + struct xt_node *node, *event; int st; + /* + event = xt_new_node( "active", NULL, NULL ); + xt_add_attr( event, "xlmns", "http://jabber.org/protocol/chatstates" ); + + event = xt_new_node( "x", NULL, xt_new_node( "composing", NULL, NULL ) ); + xt_add_attr( event, "xmlns", "jabber:x:event" ); + */ + node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "chat", who, node ); + xt_add_child( node, event ); st = jabber_write_packet( gc, node ); xt_free_node( node ); @@ -168,8 +177,39 @@ static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *gr static void jabber_keepalive( struct gaim_connection *gc ) { + struct jabber_data *jd = gc->proto_data; + struct xt_node *c, *prev; + /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ jabber_write( gc, "\n", 1 ); + + /* Let's abuse this keepalive for garbage collection of the node cache too. + It runs every minute, so let's mark every node with a special flag the + first time we see it, and clean it up the second time (clean up all + packets with the flag set). + + node->flags is normally only used by xmltree itself for parsing/handling, + so it should be safe to use the variable for gc. */ + + /* This horrible loop is explained in xmltree.c. Makes me wonder if maybe I + didn't choose the perfect data structure... */ + for( prev = NULL, c = jd->node_cache->children; c; prev = c, c = c ? c->next : jd->node_cache->children ) + { + if( c->flags == 0 ) + { + c->flags ++; + } + else + { + if( prev ) + prev->next = c->next; + else + jd->node_cache->children = c->next; + + xt_free_node( c ); + c = prev; + } + } } static void jabber_add_permit( struct gaim_connection *gc, char *who ) -- cgit v1.2.3 From eab2ac45071373751a3041c85b0ab69460109032 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 25 Sep 2006 09:42:39 +0200 Subject: Saner garbage collection for node cache. --- protocols/jabber/jabber.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 32bc7563..39a61bf3 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -178,7 +178,7 @@ static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *gr static void jabber_keepalive( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; - struct xt_node *c, *prev; + struct xt_node *c, *tmp; /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ jabber_write( gc, "\n", 1 ); @@ -193,22 +193,33 @@ static void jabber_keepalive( struct gaim_connection *gc ) /* This horrible loop is explained in xmltree.c. Makes me wonder if maybe I didn't choose the perfect data structure... */ - for( prev = NULL, c = jd->node_cache->children; c; prev = c, c = c ? c->next : jd->node_cache->children ) + for( c = jd->node_cache->children; c; c = c->next ) + if( !( c->flags & XT_SEEN ) ) + break; + + /* Now c points at the first unflagged node (or at NULL). Clean up + everything until that point. */ + while( jd->node_cache->children != c ) + { + /* + printf( "Cleaning up:\n" ); + xt_print( jd->node_cache->children ); + */ + + tmp = jd->node_cache->children->next; + xt_free_node( jd->node_cache->children ); + jd->node_cache->children = tmp; + } + + /* Now flag the ones that were still unflagged. */ + for( c = jd->node_cache->children; c; c = c->next ) { - if( c->flags == 0 ) - { - c->flags ++; - } - else - { - if( prev ) - prev->next = c->next; - else - jd->node_cache->children = c->next; - - xt_free_node( c ); - c = prev; - } + /* + printf( "Flagged:\n" ); + xt_print( c ); + */ + + c->flags |= XT_SEEN; } } -- cgit v1.2.3 From ebe7b36af555d644357efbc0e63393927162bf06 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 25 Sep 2006 12:10:14 +0200 Subject: Changing the resource string while online probably doesn't work. --- protocols/jabber/jabber.c | 7 +++++-- protocols/jabber/jabber.h | 2 +- protocols/jabber/jabber_util.c | 44 ++++++++++++++++-------------------------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 39a61bf3..7f679559 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -39,9 +39,10 @@ static void jabber_acc_init( account_t *acc ) s = set_add( &acc->set, "port", "5222", set_eval_int, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; - s = set_add( &acc->set, "priority", "0", set_eval_resprio, acc ); + s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); - s = set_add( &acc->set, "resource", "BitlBee", set_eval_resprio, acc ); + s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; @@ -233,6 +234,8 @@ static void jabber_rem_permit( struct gaim_connection *gc, char *who ) presence_send_request( gc, who, "unsubscribed" ); } +/* XMPP doesn't have both a block- and and allow-list, so these two functions + will be no-ops: */ static void jabber_add_deny( struct gaim_connection *gc, char *who ) { } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index f05c1c55..8ca7d545 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -84,7 +84,7 @@ int presence_send_update( struct gaim_connection *gc ); int presence_send_request( struct gaim_connection *gc, char *handle, char *request ); /* jabber_util.c */ -char *set_eval_resprio( set_t *set, char *value ); +char *set_eval_priority( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3a0d2004..6764e7b3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -25,42 +25,32 @@ static int next_id = 1; -char *set_eval_resprio( set_t *set, char *value ) +char *set_eval_priority( set_t *set, char *value ) { account_t *acc = set->data; char *ret; - if( strcmp( set->key, "priority" ) == 0 ) - ret = set_eval_int( set, value ); - else - ret = value; + ret = set_eval_int( set, value ); /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ if( acc->gc && ret ) { - if( strcmp( set->key, "priority" ) == 0 ) - { - /* Although set_eval functions usually are very nice - and convenient, they have one disadvantage: If I - would just call p_s_u() now to send the new prio - setting, it would send the old setting because the - set->value gets changed when the eval returns a - non-NULL value. - - So now I can choose between implementing post-set - functions next to evals, or just do this little - hack: */ - g_free( set->value ); - set->value = g_strdup( ret ); - - /* (Yes, sorry, I prefer the hack. :-P) */ - - presence_send_update( acc->gc ); - } - else - { - } + /* Although set_eval functions usually are very nice and + convenient, they have one disadvantage: If I would just + call p_s_u() now to send the new prio setting, it would + send the old setting because the set->value gets changed + when the eval returns a non-NULL value. + + So now I can choose between implementing post-set + functions next to evals, or just do this little hack: */ + + g_free( set->value ); + set->value = g_strdup( ret ); + + /* (Yes, sorry, I prefer the hack. :-P) */ + + presence_send_update( acc->gc ); } return ret; -- cgit v1.2.3 From 281859e83eb7c953b64a970d3156279b323617d0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 25 Sep 2006 19:04:50 +0200 Subject: Forgot to comment out one line... --- protocols/jabber/jabber.c | 1 - 1 file changed, 1 deletion(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 7f679559..df518956 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -131,7 +131,6 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "chat", who, node ); - xt_add_child( node, event ); st = jabber_write_packet( gc, node ); xt_free_node( node ); -- cgit v1.2.3 From 8e6c7326667f7302bf622555d7c4164d24b89be0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 26 Sep 2006 15:12:11 +0200 Subject: Proper detection of resource changed strings from the server. --- protocols/jabber/iq.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index ac5e0932..a7783fcb 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -110,12 +110,12 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( type, "result" ) == 0 && orig ) { - struct xt_node *node; + struct xt_node *c; if( !( jd->flags & JFLAG_AUTHENTICATED ) && - ( node = xt_find_node( orig->children, "query" ) ) && - ( node = xt_find_node( node->children, "username" ) ) && - node->text_len ) + ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "username" ) ) && + c->text_len ) { /* This happens when we just successfully authenticated the old (non-SASL) way. */ @@ -123,12 +123,23 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !jabber_get_roster( gc ) ) return XT_ABORT; } - else if( ( node = xt_find_node( orig->children, "bind" ) ) || - ( node = xt_find_node( orig->children, "session" ) ) ) + /* Tricky: Look for <bind> in the reply, because the server + should confirm the chosen resource string there. For + <session>, however, look in the cache, because the server + will probably not include it in its reply. */ + else if( ( c = xt_find_node( node->children, "bind" ) ) || + ( c = xt_find_node( orig->children, "session" ) ) ) { - if( strcmp( node->name, "bind" ) == 0 ) + if( strcmp( c->name, "bind" ) == 0 ) + { + c = xt_find_node( c->children, "jid" ); + if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && + strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) + serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); + jd->flags &= ~JFLAG_WAIT_BIND; - else if( strcmp( node->name, "session" ) == 0 ) + } + else if( strcmp( c->name, "session" ) == 0 ) jd->flags &= ~JFLAG_WAIT_SESSION; if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) -- cgit v1.2.3 From 022df46b52683f49a1a48e15a440d1f6b81adfdd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 26 Sep 2006 15:30:54 +0200 Subject: Added xt_dup(). --- protocols/jabber/xmltree.c | 41 +++++++++++++++++++++++++++++++++++++++++ protocols/jabber/xmltree.h | 1 + 2 files changed, 42 insertions(+) diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 81e0dab5..da316f99 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -350,6 +350,47 @@ void xt_print( struct xt_node *node ) printf( "</%s>\n", node->name ); } +struct xt_node *xt_dup( struct xt_node *node ) +{ + struct xt_node *dup = g_new0( struct xt_node, 1 ); + struct xt_node *c, *dc = NULL; + int i; + + /* Let's NOT copy the parent element here BTW! Only do it for children. */ + + dup->name = g_strdup( node->name ); + dup->flags = node->flags; + if( node->text ) + { + dup->text = g_memdup( node->text, node->text_len + 1 ); + dup->text_len = node->text_len; + } + + /* Count the number of attributes and allocate the new array. */ + for( i = 0; node->attr[i].key; i ++ ); + dup->attr = g_new0( struct xt_attr, i + 1 ); + + /* Copy them all! */ + for( i --; i >= 0; i -- ) + { + dup->attr[i].key = g_strdup( node->attr[i].key ); + dup->attr[i].value = g_strdup( node->attr[i].value ); + } + + /* This nice mysterious loop takes care of the children. */ + for( c = node->children; c; c = c->next ) + { + if( dc == NULL ) + dc = dup->children = xt_dup( c ); + else + dc = ( dc->next = xt_dup( c ) ); + + dc->parent = dup; + } + + return dup; +} + /* Frees a node. This doesn't clean up references to itself from parents! */ void xt_free_node( struct xt_node *node ) { diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h index cfefadca..55030d83 100644 --- a/protocols/jabber/xmltree.h +++ b/protocols/jabber/xmltree.h @@ -83,6 +83,7 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node ); void xt_cleanup( struct xt_parser *xt, struct xt_node *node ); char *xt_to_string( struct xt_node *node ); void xt_print( struct xt_node *node ); +struct xt_node *xt_dup( struct xt_node *node ); void xt_free_node( struct xt_node *node ); void xt_free( struct xt_parser *xt ); struct xt_node *xt_find_node( struct xt_node *node, char *name ); -- cgit v1.2.3 From 6baca2a2910d0b6663b54ef302820d9ffbbf5eee Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Oct 2006 11:31:41 +0200 Subject: Some initial hooks/stuff for privacy lists, and fixed a crash bug on connecting to Google Talk. --- protocols/jabber/io.c | 2 +- protocols/jabber/iq.c | 119 ++++++++++++++++++++++++++++++++++++++++++++-- protocols/jabber/jabber.c | 10 +++- protocols/jabber/jabber.h | 8 ++++ 4 files changed, 131 insertions(+), 8 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 3bc967e0..f62e059a 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -334,7 +334,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) to bind/initialize the session. */ if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) return XT_ABORT; } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index a7783fcb..0411d4ad 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,7 +27,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; - struct xt_node *query, *reply = NULL, *orig = NULL; + struct xt_node *query, *reply = NULL, *orig = NULL, *c; char *s, *type, *xmlns; int st; @@ -108,10 +108,45 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) account_online( gc ); } + if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 ) + { + struct xt_node *node; + + /* When receiving a list of lists: */ + if( ( node = xt_find_node( query->children, "active" ) ) ) + { + if( ( s = xt_find_attr( node, "name" ) ) ) + { + set_t *set; + + g_free( jd->privacy_active ); + jd->privacy_active = g_strdup( s ); + + /* Save it so the user can see it. */ + if( ( set = set_find( &gc->acc->set, "privacy_list" ) ) ) + { + g_free( set->value ); + set->value = g_strdup( s ); + } + + if( !jabber_get_privacy( gc ) ) + return XT_ABORT; + } + } + /* When receiving an actual list: */ + else if( ( node = xt_find_node( query->children, "list" ) ) ) + { + xt_free_node( jd->privacy_list ); + jd->privacy_list = xt_dup( node ); + } + else if( query->children == NULL ) + { + /* What to do here if there is no privacy list defined yet... */ + } + } else if( strcmp( type, "result" ) == 0 && orig ) { struct xt_node *c; - if( !( jd->flags & JFLAG_AUTHENTICATED ) && ( c = xt_find_node( orig->children, "query" ) ) && ( c = xt_find_node( c->children, "username" ) ) && @@ -120,7 +155,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) /* This happens when we just successfully authenticated the old (non-SASL) way. */ jd->flags |= JFLAG_AUTHENTICATED; - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) return XT_ABORT; } /* Tricky: Look for <bind> in the reply, because the server @@ -144,19 +179,39 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) return XT_ABORT; } } + else if( ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "active" ) ) ) + { + /* We just successfully activated a (different) + privacy list. Fetch it now. */ + g_free( jd->privacy_active ); + jd->privacy_active = g_strdup( xt_find_attr( c, "name" ) ); + + if( !jabber_get_privacy( gc ) ) + return XT_ABORT; + } } else if( strcmp( type, "error" ) == 0 ) { - if( !( jd->flags & JFLAG_AUTHENTICATED ) ) + if( !( jd->flags & JFLAG_AUTHENTICATED ) && + ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "username" ) ) && + c->text_len ) { hide_login_progress( gc, "Authentication failure" ); signoff( gc ); return XT_ABORT; } + else if( orig && + ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "active" ) ) ) + { + serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" ); + } } return XT_HANDLED; @@ -237,3 +292,57 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) xt_free_node( node ); return st; } + +/* Request the privacy list from the server. We need this, because every + time we remove/add something we have to send the whole new list to the + server again... If no privacy list is specified yet, this function will + first ask for the list of lists (XMPP supports multiple "privacy lists", + don't ask me why), later we can then fetch the list we want to use. */ +int jabber_get_privacy( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *node = NULL; + char *name; + int st; + + if( jd->privacy_active ) + { + /* If we know what is the active list right now, fetch it. */ + node = xt_new_node( "list", NULL, NULL ); + xt_add_attr( node, "name", jd->privacy_active ); + } + /* Okay, we don't know yet. If the user set a specific list, we'll + activate that one. Otherwise, we should figure out which list is + currently active. */ + else if( ( name = set_getstr( &gc->acc->set, "privacy_list" ) ) ) + { + return jabber_set_privacy( gc, name ); + } + /* else: sending this packet without a <list/> element will give + a list of available lists and information about the currently + active list. */ + + node = xt_new_node( "query", NULL, node ); + xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); + node = jabber_make_packet( "iq", "get", NULL, node ); + + st = jabber_write_packet( gc, node ); + + xt_free_node( node ); + return st; +} + +int jabber_set_privacy( struct gaim_connection *gc, char *name ) +{ + struct xt_node *node; + + node = xt_new_node( "active", NULL, NULL ); + xt_add_attr( node, "name", name ); + node = xt_new_node( "query", NULL, node ); + xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); + + node = jabber_make_packet( "iq", "set", NULL, node ); + jabber_cache_packet( gc, node ); + + return jabber_write_packet( gc, node ); +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index df518956..8ec6b70c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -41,6 +41,9 @@ static void jabber_acc_init( account_t *acc ) s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); + s = set_add( &acc->set, "privacy_list", NULL, NULL, acc ); + /* TODO: Add evaluator. */ + s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; @@ -80,12 +83,12 @@ static void jabber_login( account_t *acc ) if( set_getbool( &acc->set, "ssl" ) ) { - jd->ssl = ssl_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); + jd->ssl = ssl_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); jd->fd = ssl_getfd( jd->ssl ); } else { - jd->fd = proxy_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); + jd->fd = proxy_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); } } @@ -108,6 +111,9 @@ static void jabber_close( struct gaim_connection *gc ) if( jd->tx_len ) g_free( jd->txq ); + xt_free_node( jd->privacy_list ); + g_free( jd->privacy_active ); + xt_free_node( jd->node_cache ); xt_free( jd->xt ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 8ca7d545..1ee02d3e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -59,6 +59,10 @@ struct jabber_data struct jabber_away_state *away_state; char *away_message; + /* Updates to this one should be synchronized using jabber_privacy_update(). */ + struct xt_node *privacy_list; + char *privacy_active; + struct xt_node *node_cache; }; @@ -68,12 +72,16 @@ struct jabber_away_state char *full_name; }; +#define DEFAULT_PRIVACY_LIST "simple_blocklist" + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_iq_auth( struct gaim_connection *gc ); int jabber_get_roster( struct gaim_connection *gc ); int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); +int jabber_get_privacy( struct gaim_connection *gc ); +int jabber_set_privacy( struct gaim_connection *gc, char *name ); /* message.c */ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); -- cgit v1.2.3 From 0e2d97f6b3bcffd5637eafa9a687e42a7c134f57 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Oct 2006 11:40:55 +0200 Subject: Can now log in to the jabber.com server (which pretends to support XMPP 1.0 but does NOT (seem to) support SASL authentication). --- protocols/jabber/io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index f62e059a..3dbc6faa 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -300,8 +300,20 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) from here to make sure the TLS session will be initialized properly before we attempt SASL authentication. */ if( ( c = xt_find_node( node->children, "mechanisms" ) ) ) + { if( sasl_pkt_mechanisms( c, data ) == XT_ABORT ) return XT_ABORT; + } + else + { + /* If the server *SEEMS* to support SASL authentication but + doesn't support it after all, we should try to do + authentication the other way. jabber.com doesn't seem to + do SASL while it pretends to be XMPP 1.0 compliant! */ + if( sasl_supported( gc ) ) + if( !jabber_start_iq_auth( gc ) ) + return XT_ABORT; + } if( ( c = xt_find_node( node->children, "bind" ) ) ) { -- cgit v1.2.3 From 88591fd3b95ab21ca016204b49fb80d6d6cdd541 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Oct 2006 18:15:46 +0200 Subject: Better fix for servers that report to comply with XMPP 1.0 but don't offer SASL authentication options. Previous fix tried to do IQ authentication even after successful SASL authentications. --- protocols/jabber/io.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 3dbc6faa..189320d9 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -304,15 +304,14 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( sasl_pkt_mechanisms( c, data ) == XT_ABORT ) return XT_ABORT; } - else + /* If the server *SEEMS* to support SASL authentication but doesn't + support it after all, we should try to do authentication the + other way. jabber.com doesn't seem to do SASL while it pretends + to be XMPP 1.0 compliant! */ + else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) ) { - /* If the server *SEEMS* to support SASL authentication but - doesn't support it after all, we should try to do - authentication the other way. jabber.com doesn't seem to - do SASL while it pretends to be XMPP 1.0 compliant! */ - if( sasl_supported( gc ) ) - if( !jabber_start_iq_auth( gc ) ) - return XT_ABORT; + if( !jabber_start_iq_auth( gc ) ) + return XT_ABORT; } if( ( c = xt_find_node( node->children, "bind" ) ) ) -- cgit v1.2.3 From c1ed6527576ac4c6ee1241f662e7db8e59327fd8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Oct 2006 15:19:13 +0200 Subject: No more double free()/crashes when trying to set up an SSL connection to a non-SSL server, and better handling of TLS connection setup by initializing the TLS session from a callback function (which guarantees a valid return value from ssl_starttls() before any error callback could be called). --- lib/ssl_gnutls.c | 24 ++++++++++++++++++------ protocols/jabber/io.c | 5 +++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index fc848bb1..7481127a 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -48,6 +48,8 @@ struct scd }; static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) @@ -68,10 +70,6 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data return conn; } -/* FIXME: It can happen that the handshake fails even before ssl_connected() - returns already. This function will then return an invalid pointer because - these failures can't be detected properly yet. Maybe ssl_connected() - shouldn't be called directly, but via a short timeout? */ void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); @@ -81,12 +79,26 @@ void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) conn->data = data; conn->inpa = -1; - ssl_connected( conn, fd, GAIM_INPUT_WRITE ); + /* This function should be called via a (short) timeout instead of + directly from here, because these SSL calls are *supposed* to be + *completely* asynchronous and not ready yet when this function + (or *_connect, for examle) returns. Also, errors are reported via + the callback function, not via this function's return value. + + In short, doing things like this makes the rest of the code a lot + simpler. */ + + b_timeout_add( 1, ssl_starttls_real, conn ); return conn; } -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + + return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE ); +} static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) { diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 189320d9..8834c906 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -223,9 +223,14 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ) { struct gaim_connection *gc = data; + struct jabber_data *jd = gc->proto_data; if( source == NULL ) { + /* The SSL connection will be cleaned up by the SSL lib + already, set it to NULL here to prevent a double cleanup: */ + jd->ssl = NULL; + hide_login_progress( gc, "Could not connect to server" ); signoff( gc ); return FALSE; -- cgit v1.2.3 From d9282b4b3a7a1264bf7952e5de4dbd10b6aa5e4e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Oct 2006 15:46:33 +0200 Subject: The SASL DIGEST-MD5 handler now doesn't barf on challenges without a realm (jabber.org likes to do this). --- protocols/jabber/sasl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 7a3ca112..39d45c9b 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -206,9 +206,15 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) nonce = sasl_get_part( dec, "nonce" ); realm = sasl_get_part( dec, "realm" ); - if( !nonce || !realm ) + if( !nonce ) goto error; + /* Jabber.Org considers the realm part optional and doesn't + specify one. Oh well, actually they're right, but still, + don't know if this is right... */ + if( !realm ) + realm = g_strdup( jd->server ); + random_bytes( (unsigned char *) cnonce_bin, sizeof( cnonce_bin ) ); cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) ); digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server ); -- cgit v1.2.3 From 501b4e06244dbd333ee207ceade37592482e0fe7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Oct 2006 18:42:32 +0200 Subject: Added a useful error message for SASL negotiation failures and turned off the little hack in jabber_write() for now because it breaks error handling. --- protocols/jabber/io.c | 8 +++++++- protocols/jabber/sasl.c | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 8834c906..634e5b99 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -51,7 +51,10 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) /* Try if we can write it immediately so we don't have to do it via the event handler. If not, add the handler. (In most cases it probably won't be necessary.) */ + /* Disabling this trick for now because there's really not + a good way to catch errors yet. :-( if( jabber_write_callback( gc, jd->fd, GAIM_INPUT_WRITE ) ) + */ jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, gc ); } else @@ -63,7 +66,10 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) jd->tx_len += len; } - /* FIXME: write_callback could've generated a real error! */ + /* FIXME: write_callback could've generated a real error! Have to + find a way to find out if we have to return 0 here. Looking for + ourselves in the linked list of connections is a possibility, + but it'd be too time-consuming... */ return 1; } diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 39d45c9b..a9676338 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -63,6 +63,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) if( !sup_plain && !sup_digest ) { + hide_login_progress( gc, "No known SASL authentication schemes supported" ); signoff( gc ); return XT_ABORT; } -- cgit v1.2.3 From 995913b4be70be6e07b8aa7661ac639e5fc0d6e7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Oct 2006 19:46:57 +0200 Subject: Added some error handling for the (not very complete yet) privacy list code. --- protocols/jabber/iq.c | 53 ++++++++++++++++++++++++++++++++++++++++++----- protocols/jabber/jabber.c | 19 +++++++++++++---- protocols/jabber/jabber.h | 2 ++ 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 0411d4ad..b77ee9ff 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -147,6 +147,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) else if( strcmp( type, "result" ) == 0 && orig ) { struct xt_node *c; + if( !( jd->flags & JFLAG_AUTHENTICATED ) && ( c = xt_find_node( orig->children, "query" ) ) && ( c = xt_find_node( c->children, "username" ) ) && @@ -198,6 +199,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) else if( strcmp( type, "error" ) == 0 ) { if( !( jd->flags & JFLAG_AUTHENTICATED ) && + orig && ( c = xt_find_node( orig->children, "query" ) ) && ( c = xt_find_node( c->children, "username" ) ) && c->text_len ) @@ -206,11 +208,32 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) signoff( gc ); return XT_ABORT; } - else if( orig && - ( c = xt_find_node( orig->children, "query" ) ) && - ( c = xt_find_node( c->children, "active" ) ) ) + else if( ( xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 ) || + ( orig && + ( c = xt_find_node( orig->children, "query" ) ) && + ( s = xt_find_attr( c, "xmlns" ) ) && + strcmp( s, "jabber:iq:privacy" ) == 0 ) ) { - serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" ); + /* All errors related to privacy lists. */ + if( ( c = xt_find_node( node->children, "error" ) ) == NULL ) + { + hide_login_progress_error( gc, "Received malformed error packet" ); + signoff( gc ); + return XT_ABORT; + } + + if( xt_find_node( c->children, "item-not-found" ) ) + { + serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" ); + /* Should I do anything else here? */ + } + else if( xt_find_node( c->children, "feature-not-implemented" ) ) + { + jd->flags |= JFLAG_PRIVACY_BROKEN; + /* Probably there's no need to inform the user. + We can do that if the user ever tries to use + the block/allow commands. */ + } } } @@ -326,9 +349,9 @@ int jabber_get_privacy( struct gaim_connection *gc ) xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); node = jabber_make_packet( "iq", "get", NULL, node ); + jabber_cache_packet( gc, node ); st = jabber_write_packet( gc, node ); - xt_free_node( node ); return st; } @@ -346,3 +369,23 @@ int jabber_set_privacy( struct gaim_connection *gc, char *name ) return jabber_write_packet( gc, node ); } + +char *set_eval_privacy_list( set_t *set, char *value ) +{ + account_t *acc = set->data; + struct jabber_data *jd = acc->gc->proto_data; + + if( jd->flags & JFLAG_PRIVACY_BROKEN ) + { + serv_got_crap( acc->gc, "Privacy lists not supported by this server" ); + return NULL; + } + + /* If we're on-line, return NULL and let the server decide if the + chosen list is valid. If we're off-line, just accept it and we'll + see later (when we connect). */ + if( acc->gc ) + jabber_set_privacy( acc->gc, value ); + + return acc->gc ? NULL : value; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 8ec6b70c..39d93d16 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -41,8 +41,7 @@ static void jabber_acc_init( account_t *acc ) s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); - s = set_add( &acc->set, "privacy_list", NULL, NULL, acc ); - /* TODO: Add evaluator. */ + s = set_add( &acc->set, "privacy_list", NULL, set_eval_privacy_list, acc ); s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; @@ -231,12 +230,24 @@ static void jabber_keepalive( struct gaim_connection *gc ) static void jabber_add_permit( struct gaim_connection *gc, char *who ) { - presence_send_request( gc, who, "subscribed" ); + struct jabber_data *jd = gc->proto_data; + + if( jd->flags & JFLAG_PRIVACY_BROKEN ) + { + serv_got_crap( gc, "Privacy lists not supported by this server" ); + return; + } } static void jabber_rem_permit( struct gaim_connection *gc, char *who ) { - presence_send_request( gc, who, "unsubscribed" ); + struct jabber_data *jd = gc->proto_data; + + if( jd->flags & JFLAG_PRIVACY_BROKEN ) + { + serv_got_crap( gc, "Privacy lists not supported by this server" ); + return; + } } /* XMPP doesn't have both a block- and and allow-list, so these two functions diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 1ee02d3e..2c7cadd1 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -36,6 +36,7 @@ typedef enum JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply before we continue. */ JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ + JFLAG_PRIVACY_BROKEN = 32, /* Or just not supported, actually. */ } jabber_flags_t; struct jabber_data @@ -82,6 +83,7 @@ int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); int jabber_get_privacy( struct gaim_connection *gc ); int jabber_set_privacy( struct gaim_connection *gc, char *name ); +char *set_eval_privacy_list( set_t *set, char *value ); /* message.c */ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); -- cgit v1.2.3 From 6266fcab664c9a907b1d32a1c94ef7fd3cfb9fba Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Oct 2006 20:32:21 +0200 Subject: Fixed memory leak in jabber_buddy_ask() and added "handling" of type="error" <presence/> tags. --- protocols/jabber/jabber_util.c | 1 + protocols/jabber/presence.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 6764e7b3..845c2d8c 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -175,4 +175,5 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + g_free( buf ); } diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 1b8008b8..57301270 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -56,6 +56,10 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) If you're one of those people, this is your chance to write your first line of code in C... */ } + else if( strcmp( type, "error" ) == 0 ) + { + /* What to do with it? */ + } else { printf( "Received PRES from %s:\n", from ); -- cgit v1.2.3 From cc2cb2da3f1c0e2ad65708f4110e74e945ea9b66 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 4 Oct 2006 20:14:41 +0200 Subject: Lack of TLS support is also detected now if the server doesn't support XMPP 1.0 (properly), and restored immediate writes by splitting up the jabber_write_callback() function. --- protocols/jabber/io.c | 61 ++++++++++++++++++++++++++++++++++------------- protocols/jabber/jabber.c | 2 +- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 634e5b99..88ebf5d9 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -25,6 +25,7 @@ #include "ssl_client.h" static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ); +static gboolean jabber_write_queue( struct gaim_connection *gc ); int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ) { @@ -41,6 +42,7 @@ int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ) int jabber_write( struct gaim_connection *gc, char *buf, int len ) { struct jabber_data *jd = gc->proto_data; + gboolean ret; if( jd->tx_len == 0 ) { @@ -51,10 +53,7 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) /* Try if we can write it immediately so we don't have to do it via the event handler. If not, add the handler. (In most cases it probably won't be necessary.) */ - /* Disabling this trick for now because there's really not - a good way to catch errors yet. :-( - if( jabber_write_callback( gc, jd->fd, GAIM_INPUT_WRITE ) ) - */ + if( ( ret = jabber_write_queue( gc ) ) && jd->tx_len > 0 ) jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, gc ); } else @@ -64,24 +63,39 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) jd->txq = g_renew( char, jd->txq, jd->tx_len + len ); memcpy( jd->txq + jd->tx_len, buf, len ); jd->tx_len += len; + + /* The return value for write() doesn't necessarily mean + that everything got sent, it mainly means that the + connection (officially) still exists and can still + be accessed without hitting SIGSEGV. IOW: */ + ret = TRUE; } - /* FIXME: write_callback could've generated a real error! Have to - find a way to find out if we have to return 0 here. Looking for - ourselves in the linked list of connections is a possibility, - but it'd be too time-consuming... */ - return 1; + return ret; } +/* Splitting up in two separate functions: One to use as a callback and one + to use in the function above to escape from having to wait for the event + handler to call us, if possible. + + Two different functions are necessary because of the return values: The + callback should only return TRUE if the write was successful AND if the + buffer is not empty yet (ie. if the handler has to be called again when + the socket is ready for more data). */ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ) { - struct gaim_connection *gc = data; + struct jabber_data *jd = ((struct gaim_connection *)data)->proto_data; + + return jd->fd != -1 && + jabber_write_queue( data ) && + jd->tx_len > 0; +} + +static gboolean jabber_write_queue( struct gaim_connection *gc ) +{ struct jabber_data *jd = gc->proto_data; int st; - if( jd->fd == -1 ) - return FALSE; - if( jd->ssl ) st = ssl_write( jd->ssl, jd->txq, jd->tx_len ); else @@ -96,7 +110,7 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition jd->txq = NULL; jd->tx_len = 0; - return FALSE; + return TRUE; } else if( st == 0 || ( st < 0 && !sockerr_again() ) ) { @@ -186,11 +200,26 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition this is an old server that can't do SASL authentication. */ if( !sasl_supported( gc ) ) - return jabber_start_iq_auth( gc ); + { + /* If there's no version= tag, we suppose + this server does NOT implement: XMPP 1.0, + SASL and TLS. */ + if( set_getbool( &gc->acc->set, "tls" ) ) + { + hide_login_progress( gc, "TLS is turned on for this " + "account, but is not supported by this server" ); + signoff( gc ); + return FALSE; + } + else + { + return jabber_start_iq_auth( gc ); + } + } } else { - hide_login_progress_error( gc, "XML stream error" ); + hide_login_progress( gc, "XML stream error" ); signoff( gc ); return FALSE; } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 39d93d16..fc415ca7 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -123,7 +123,7 @@ static void jabber_close( struct gaim_connection *gc ) static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) { - struct xt_node *node, *event; + struct xt_node *node; int st; /* -- cgit v1.2.3 From 101d84fe3018ba138a9cb5f0f030997e8ff7bdbe Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 6 Oct 2006 00:55:54 +0200 Subject: Added max. recursion depth arguments to xt_handle()/_cleanup() to make sure commands that still have to be handled don't get (partially) cleaned up already. --- protocols/jabber/io.c | 4 ++-- protocols/jabber/xmltree.c | 25 +++++++++++++++---------- protocols/jabber/xmltree.h | 4 ++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 88ebf5d9..04b98626 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -169,7 +169,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } /* Execute all handlers. */ - if( !xt_handle( jd->xt, NULL ) ) + if( !xt_handle( jd->xt, NULL, 1 ) ) { /* Don't do anything, the handlers should have aborted the connection already... Or not? FIXME */ @@ -183,7 +183,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } /* Garbage collection. */ - xt_cleanup( jd->xt, NULL ); + xt_cleanup( jd->xt, NULL, 1 ); /* This is a bit hackish, unfortunately. Although xmltree has nifty event handler stuff, it only calls handlers diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index da316f99..d4063476 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -151,20 +151,24 @@ int xt_feed( struct xt_parser *xt, char *text, int text_len ) /* Find completed nodes and see if a handler has to be called. Passing a node isn't necessary if you want to start at the root, just pass - NULL. This second argument is needed for recursive calls. FIXME: Retval? */ -int xt_handle( struct xt_parser *xt, struct xt_node *node ) + NULL. This second argument is needed for recursive calls. */ +int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) { struct xt_node *c; xt_status st; int i; - /* Let's just hope xt->root isn't NULL! */ + /* Just in case someone likes infinite loops... */ + if( xt->root == NULL ) + return 0; + if( node == NULL ) - return xt_handle( xt, xt->root ); + return xt_handle( xt, xt->root, depth ); - for( c = node->children; c; c = c->next ) - if( !xt_handle( xt, c ) ) - return 0; + if( depth != 0 ) + for( c = node->children; c; c = c->next ) + if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) + return 0; if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) { @@ -201,7 +205,7 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node ) /* Garbage collection: Cleans up all nodes that are handled. Useful for streams because there's no reason to keep a complete packet history in memory. */ -void xt_cleanup( struct xt_parser *xt, struct xt_node *node ) +void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) { struct xt_node *c, *prev; @@ -209,7 +213,7 @@ void xt_cleanup( struct xt_parser *xt, struct xt_node *node ) return; if( node == NULL ) - return xt_cleanup( xt, xt->root ); + return xt_cleanup( xt, xt->root, depth ); if( node->flags & XT_SEEN && node == xt->root ) { @@ -245,7 +249,8 @@ void xt_cleanup( struct xt_parser *xt, struct xt_node *node ) { /* This node can't be cleaned up yet, but maybe a subnode can. */ - xt_cleanup( xt, c ); + if( depth != 0 ) + xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); } } } diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h index 55030d83..4abb094f 100644 --- a/protocols/jabber/xmltree.h +++ b/protocols/jabber/xmltree.h @@ -79,8 +79,8 @@ struct xt_parser struct xt_parser *xt_new( gpointer data ); void xt_reset( struct xt_parser *xt ); int xt_feed( struct xt_parser *xt, char *text, int text_len ); -int xt_handle( struct xt_parser *xt, struct xt_node *node ); -void xt_cleanup( struct xt_parser *xt, struct xt_node *node ); +int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); +void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); char *xt_to_string( struct xt_node *node ); void xt_print( struct xt_node *node ); struct xt_node *xt_dup( struct xt_node *node ); -- cgit v1.2.3 From 090f1cbe72373b31e753af4a1442ddd53b02791b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 7 Oct 2006 15:01:02 +0200 Subject: Never mind about those privacy lists, they're horrible and not supported by any client I know of. Also, they're already working on a (probably completely incompatible) standard: JEP-191. Maybe BitlBee will implement it too some day... --- protocols/jabber/io.c | 2 +- protocols/jabber/iq.c | 152 +-------------------------------------------- protocols/jabber/jabber.c | 41 ------------ protocols/jabber/jabber.h | 10 --- protocols/jabber/xmltree.c | 24 +++++-- 5 files changed, 23 insertions(+), 206 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 04b98626..73173dbc 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -385,7 +385,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) to bind/initialize the session. */ if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) + if( !jabber_get_roster( gc ) ) return XT_ABORT; } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index b77ee9ff..4739d6ab 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -108,42 +108,6 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) account_online( gc ); } - if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 ) - { - struct xt_node *node; - - /* When receiving a list of lists: */ - if( ( node = xt_find_node( query->children, "active" ) ) ) - { - if( ( s = xt_find_attr( node, "name" ) ) ) - { - set_t *set; - - g_free( jd->privacy_active ); - jd->privacy_active = g_strdup( s ); - - /* Save it so the user can see it. */ - if( ( set = set_find( &gc->acc->set, "privacy_list" ) ) ) - { - g_free( set->value ); - set->value = g_strdup( s ); - } - - if( !jabber_get_privacy( gc ) ) - return XT_ABORT; - } - } - /* When receiving an actual list: */ - else if( ( node = xt_find_node( query->children, "list" ) ) ) - { - xt_free_node( jd->privacy_list ); - jd->privacy_list = xt_dup( node ); - } - else if( query->children == NULL ) - { - /* What to do here if there is no privacy list defined yet... */ - } - } else if( strcmp( type, "result" ) == 0 && orig ) { struct xt_node *c; @@ -156,7 +120,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) /* This happens when we just successfully authenticated the old (non-SASL) way. */ jd->flags |= JFLAG_AUTHENTICATED; - if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) + if( !jabber_get_roster( gc ) ) return XT_ABORT; } /* Tricky: Look for <bind> in the reply, because the server @@ -180,21 +144,10 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) ) + if( !jabber_get_roster( gc ) ) return XT_ABORT; } } - else if( ( c = xt_find_node( orig->children, "query" ) ) && - ( c = xt_find_node( c->children, "active" ) ) ) - { - /* We just successfully activated a (different) - privacy list. Fetch it now. */ - g_free( jd->privacy_active ); - jd->privacy_active = g_strdup( xt_find_attr( c, "name" ) ); - - if( !jabber_get_privacy( gc ) ) - return XT_ABORT; - } } else if( strcmp( type, "error" ) == 0 ) { @@ -208,33 +161,6 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) signoff( gc ); return XT_ABORT; } - else if( ( xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 ) || - ( orig && - ( c = xt_find_node( orig->children, "query" ) ) && - ( s = xt_find_attr( c, "xmlns" ) ) && - strcmp( s, "jabber:iq:privacy" ) == 0 ) ) - { - /* All errors related to privacy lists. */ - if( ( c = xt_find_node( node->children, "error" ) ) == NULL ) - { - hide_login_progress_error( gc, "Received malformed error packet" ); - signoff( gc ); - return XT_ABORT; - } - - if( xt_find_node( c->children, "item-not-found" ) ) - { - serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" ); - /* Should I do anything else here? */ - } - else if( xt_find_node( c->children, "feature-not-implemented" ) ) - { - jd->flags |= JFLAG_PRIVACY_BROKEN; - /* Probably there's no need to inform the user. - We can do that if the user ever tries to use - the block/allow commands. */ - } - } } return XT_HANDLED; @@ -315,77 +241,3 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) xt_free_node( node ); return st; } - -/* Request the privacy list from the server. We need this, because every - time we remove/add something we have to send the whole new list to the - server again... If no privacy list is specified yet, this function will - first ask for the list of lists (XMPP supports multiple "privacy lists", - don't ask me why), later we can then fetch the list we want to use. */ -int jabber_get_privacy( struct gaim_connection *gc ) -{ - struct jabber_data *jd = gc->proto_data; - struct xt_node *node = NULL; - char *name; - int st; - - if( jd->privacy_active ) - { - /* If we know what is the active list right now, fetch it. */ - node = xt_new_node( "list", NULL, NULL ); - xt_add_attr( node, "name", jd->privacy_active ); - } - /* Okay, we don't know yet. If the user set a specific list, we'll - activate that one. Otherwise, we should figure out which list is - currently active. */ - else if( ( name = set_getstr( &gc->acc->set, "privacy_list" ) ) ) - { - return jabber_set_privacy( gc, name ); - } - /* else: sending this packet without a <list/> element will give - a list of available lists and information about the currently - active list. */ - - node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); - node = jabber_make_packet( "iq", "get", NULL, node ); - - jabber_cache_packet( gc, node ); - st = jabber_write_packet( gc, node ); - - return st; -} - -int jabber_set_privacy( struct gaim_connection *gc, char *name ) -{ - struct xt_node *node; - - node = xt_new_node( "active", NULL, NULL ); - xt_add_attr( node, "name", name ); - node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); - - node = jabber_make_packet( "iq", "set", NULL, node ); - jabber_cache_packet( gc, node ); - - return jabber_write_packet( gc, node ); -} - -char *set_eval_privacy_list( set_t *set, char *value ) -{ - account_t *acc = set->data; - struct jabber_data *jd = acc->gc->proto_data; - - if( jd->flags & JFLAG_PRIVACY_BROKEN ) - { - serv_got_crap( acc->gc, "Privacy lists not supported by this server" ); - return NULL; - } - - /* If we're on-line, return NULL and let the server decide if the - chosen list is valid. If we're off-line, just accept it and we'll - see later (when we connect). */ - if( acc->gc ) - jabber_set_privacy( acc->gc, value ); - - return acc->gc ? NULL : value; -} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index fc415ca7..706d31c3 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -41,8 +41,6 @@ static void jabber_acc_init( account_t *acc ) s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); - s = set_add( &acc->set, "privacy_list", NULL, set_eval_privacy_list, acc ); - s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; @@ -110,9 +108,6 @@ static void jabber_close( struct gaim_connection *gc ) if( jd->tx_len ) g_free( jd->txq ); - xt_free_node( jd->privacy_list ); - g_free( jd->privacy_active ); - xt_free_node( jd->node_cache ); xt_free( jd->xt ); @@ -228,38 +223,6 @@ static void jabber_keepalive( struct gaim_connection *gc ) } } -static void jabber_add_permit( struct gaim_connection *gc, char *who ) -{ - struct jabber_data *jd = gc->proto_data; - - if( jd->flags & JFLAG_PRIVACY_BROKEN ) - { - serv_got_crap( gc, "Privacy lists not supported by this server" ); - return; - } -} - -static void jabber_rem_permit( struct gaim_connection *gc, char *who ) -{ - struct jabber_data *jd = gc->proto_data; - - if( jd->flags & JFLAG_PRIVACY_BROKEN ) - { - serv_got_crap( gc, "Privacy lists not supported by this server" ); - return; - } -} - -/* XMPP doesn't have both a block- and and allow-list, so these two functions - will be no-ops: */ -static void jabber_add_deny( struct gaim_connection *gc, char *who ) -{ -} - -static void jabber_rem_deny( struct gaim_connection *gc, char *who ) -{ -} - void jabber_init() { struct prpl *ret = g_new0( struct prpl, 1 ); @@ -281,10 +244,6 @@ void jabber_init() // ret->chat_leave = jabber_chat_leave; // ret->chat_open = jabber_chat_open; ret->keepalive = jabber_keepalive; - ret->add_permit = jabber_add_permit; - ret->rem_permit = jabber_rem_permit; - ret->add_deny = jabber_add_deny; - ret->rem_deny = jabber_rem_deny; // ret->send_typing = jabber_send_typing; ret->handle_cmp = g_strcasecmp; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 2c7cadd1..8ca7d545 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -36,7 +36,6 @@ typedef enum JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply before we continue. */ JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ - JFLAG_PRIVACY_BROKEN = 32, /* Or just not supported, actually. */ } jabber_flags_t; struct jabber_data @@ -60,10 +59,6 @@ struct jabber_data struct jabber_away_state *away_state; char *away_message; - /* Updates to this one should be synchronized using jabber_privacy_update(). */ - struct xt_node *privacy_list; - char *privacy_active; - struct xt_node *node_cache; }; @@ -73,17 +68,12 @@ struct jabber_away_state char *full_name; }; -#define DEFAULT_PRIVACY_LIST "simple_blocklist" - /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_iq_auth( struct gaim_connection *gc ); int jabber_get_roster( struct gaim_connection *gc ); int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); -int jabber_get_privacy( struct gaim_connection *gc ); -int jabber_set_privacy( struct gaim_connection *gc, char *name ); -char *set_eval_privacy_list( set_t *set, char *value ); /* message.c */ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index d4063476..af0c5832 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -527,9 +527,25 @@ void xt_add_attr( struct xt_node *node, char *key, char *value ) { int i; - for( i = 0; node->attr[i].key; i ++ ); - node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); - node->attr[i].key = g_strdup( key ); + /* Now actually it'd be nice if we can also change existing attributes + (which actually means this function doesn't have the right name). + So let's find out if we have this attribute already... */ + for( i = 0; node->attr[i].key; i ++ ) + if( strcmp( node->attr[i].key, key ) == 0 ) + break; + + if( node->attr[i].key == NULL ) + { + /* If not, allocate space for a new attribute. */ + node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); + node->attr[i].key = g_strdup( key ); + node->attr[i+1].key = NULL; + } + else + { + /* Otherwise, free the old value before setting the new one. */ + g_free( node->attr[i].value ); + } + node->attr[i].value = g_strdup( value ); - node->attr[i+1].key = NULL; } -- cgit v1.2.3 From 36e9f62a6e6fdb1217b3b819320ac5a94025c448 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 7 Oct 2006 19:46:28 +0200 Subject: Added SRV lookups to automatically find out the correct server for a domain. --- configure | 8 +++++++ lib/misc.c | 57 +++++++++++++++++++++++++++++++++++++++++++++ lib/misc.h | 10 ++++++++ protocols/jabber/jabber.c | 20 ++++++++++++++-- protocols/jabber/presence.c | 7 +++--- 5 files changed, 97 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 7cc99b41..78ba44e1 100755 --- a/configure +++ b/configure @@ -318,6 +318,14 @@ fi; echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings +for i in /lib /usr/lib /usr/local/lib; do + if [ -e $i/libresolv.a ]; then + echo '#define HAVE_RESOLV_A' >> config.h + echo 'EFLAGS+='$i'/libresolv.a' >> Makefile.settings + break + fi +done + STORAGES="text xml" if [ "$ldap" = "auto" ]; then diff --git a/lib/misc.c b/lib/misc.c index 64666492..9061af39 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -39,6 +39,11 @@ #include <glib.h> #include <time.h> +#ifdef HAVE_RESOLV_A +#include <arpa/nameser.h> +#include <resolv.h> +#endif + void strip_linefeed(gchar *text) { int i, j; @@ -487,3 +492,55 @@ int bool2int( char *value ) return 0; } + +struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) +{ + struct ns_srv_reply *reply = NULL; +#ifdef HAVE_RESOLV_A + char name[1024]; + unsigned char querybuf[1024]; + const unsigned char *buf; + ns_msg nsh; + ns_rr rr; + int i, len, size; + + g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain ); + + if( ( size = res_query( name, ns_c_in, ns_t_srv, querybuf, sizeof( querybuf ) ) ) <= 0 ) + return NULL; + + if( ns_initparse( querybuf, size, &nsh ) != 0 ) + return NULL; + + if( ns_parserr( &nsh, ns_s_an, 0, &rr ) != 0 ) + return NULL; + + size = ns_rr_rdlen( rr ); + buf = ns_rr_rdata( rr ); + + len = 0; + for( i = 6; i < size && buf[i]; i += buf[i] + 1 ) + len += buf[i] + 1; + + if( i > size ) + return NULL; + + reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); + memcpy( reply->name, buf + 7, len ); + + for( i = buf[6]; i < len && buf[7+i]; i += buf[7+i] + 1 ) + reply->name[i] = '.'; + + if( i > len ) + { + g_free( reply ); + return NULL; + } + + reply->prio = ( buf[0] << 8 ) | buf[1]; + reply->weight = ( buf[2] << 8 ) | buf[3]; + reply->port = ( buf[4] << 8 ) | buf[5]; +#endif + + return reply; +} diff --git a/lib/misc.h b/lib/misc.h index b021e642..55dabfc4 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -29,6 +29,14 @@ #include <gmodule.h> #include <time.h> +struct ns_srv_reply +{ + int prio; + int weight; + int port; + char name[]; +}; + G_MODULE_EXPORT void strip_linefeed( gchar *text ); G_MODULE_EXPORT char *add_cr( char *text ); G_MODULE_EXPORT char *strip_newlines(char *source); @@ -53,4 +61,6 @@ G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); G_MODULE_EXPORT int is_bool( char *value ); G_MODULE_EXPORT int bool2int( char *value ); +G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ); + #endif diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 706d31c3..2c0f7945 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -58,6 +58,8 @@ static void jabber_login( account_t *acc ) { struct gaim_connection *gc = new_gaim_conn( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); + struct ns_srv_reply *srv = NULL; + char *connect_to; jd->gc = gc; gc->proto_data = jd; @@ -78,15 +80,29 @@ static void jabber_login( account_t *acc ) jd->node_cache = xt_new_node( "cache", NULL, NULL ); + /* Figure out the hostname to connect to. */ + if( acc->server ) + connect_to = acc->server; + else if( ( srv = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || + ( srv = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) + connect_to = srv->name; + else + connect_to = jd->server; + + /* For non-SSL connections we can try to use the port # from the SRV + reply, but let's not do that when using SSL, SSL usually runs on + non-standard ports... */ if( set_getbool( &acc->set, "ssl" ) ) { - jd->ssl = ssl_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); + jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); jd->fd = ssl_getfd( jd->ssl ); } else { - jd->fd = proxy_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); + jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); } + + g_free( srv ); } static void jabber_close( struct gaim_connection *gc ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 57301270..5bef498d 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -37,6 +37,9 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( s ) *s = 0; + /* Will implement better parsing of away states/msgs when we + finally do those API changes. Which will probably be after + merging this module into the main tree. */ if( type == NULL ) serv_got_update( gc, from, 1, 0, 0, 0, 0, 0 ); else if( strcmp( type, "unavailable" ) == 0 ) @@ -83,13 +86,11 @@ int presence_send_update( struct gaim_connection *gc ) int st; node = jabber_make_packet( "presence", NULL, NULL, NULL ); + xt_add_child( node, xt_new_node( "priority", set_getstr( &gc->acc->set, "priority" ), NULL ) ); if( show && *show ) xt_add_child( node, xt_new_node( "show", show, NULL ) ); if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); - /* if( set_getint( &gc->acc->set, "priority" ) != 0 ) */ - /* Let's just send this every time... */ - xt_add_child( node, xt_new_node( "priority", set_getstr( &gc->acc->set, "priority" ), NULL ) ); st = jabber_write_packet( gc, node ); -- cgit v1.2.3 From 038d17f834219505cbbdae469b2b150117467dd0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 8 Oct 2006 18:11:16 +0200 Subject: Implemented a better node cache using a GLib hash, and preparing to add event handlers that can be set when sending a packet to handle the reply to this specific packet. This should allow me to make the iq handler a lot cleaner. --- protocols/jabber/io.c | 4 +-- protocols/jabber/iq.c | 4 +-- protocols/jabber/jabber.c | 63 +++++++++++++----------------------------- protocols/jabber/jabber.h | 16 +++++++++-- protocols/jabber/jabber_util.c | 50 +++++++++++++++++++++++++-------- 5 files changed, 74 insertions(+), 63 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 73173dbc..c6ad68e0 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -359,7 +359,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_packet( gc, reply ); + jabber_cache_add( gc, reply ); if( !jabber_write_packet( gc, reply ) ) return XT_ABORT; @@ -372,7 +372,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) reply = xt_new_node( "session", NULL, NULL ); xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_packet( gc, reply ); + jabber_cache_add( gc, reply ); if( !jabber_write_packet( gc, reply ) ) return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 4739d6ab..ae4ed099 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -40,7 +40,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xmlns = xt_find_attr( query, "xmlns" ); if( ( s = xt_find_attr( node, "id" ) ) ) - orig = jabber_packet_from_cache( gc, s ); + orig = jabber_cache_get( gc, s ); if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 ) { @@ -84,7 +84,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_packet( gc, reply ); + jabber_cache_add( gc, reply ); st = jabber_write_packet( gc, reply ); return st ? XT_HANDLED : XT_ABORT; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 2c0f7945..32d1d99d 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -78,7 +78,7 @@ static void jabber_login( account_t *acc ) *jd->server = 0; jd->server ++; - jd->node_cache = xt_new_node( "cache", NULL, NULL ); + jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free ); /* Figure out the hostname to connect to. */ if( acc->server ) @@ -124,7 +124,8 @@ static void jabber_close( struct gaim_connection *gc ) if( jd->tx_len ) g_free( jd->txq ); - xt_free_node( jd->node_cache ); + g_hash_table_destroy( jd->node_cache ); + xt_free( jd->xt ); g_free( jd->away_message ); @@ -165,6 +166,18 @@ static GList *jabber_away_states( struct gaim_connection *gc ) return l; } +static void jabber_get_info( struct gaim_connection *gc, char *who ) +{ + struct xt_node *node; + + node = xt_new_node( "query", NULL, NULL ); + xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" ); + node = jabber_make_packet( "iq", "get", who, node ); + jabber_cache_add( gc, node ); + + jabber_write_packet( gc, node ); +} + static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) { struct jabber_data *jd = gc->proto_data; @@ -193,50 +206,12 @@ static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *gr static void jabber_keepalive( struct gaim_connection *gc ) { - struct jabber_data *jd = gc->proto_data; - struct xt_node *c, *tmp; - /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ jabber_write( gc, "\n", 1 ); - /* Let's abuse this keepalive for garbage collection of the node cache too. - It runs every minute, so let's mark every node with a special flag the - first time we see it, and clean it up the second time (clean up all - packets with the flag set). - - node->flags is normally only used by xmltree itself for parsing/handling, - so it should be safe to use the variable for gc. */ - - /* This horrible loop is explained in xmltree.c. Makes me wonder if maybe I - didn't choose the perfect data structure... */ - for( c = jd->node_cache->children; c; c = c->next ) - if( !( c->flags & XT_SEEN ) ) - break; - - /* Now c points at the first unflagged node (or at NULL). Clean up - everything until that point. */ - while( jd->node_cache->children != c ) - { - /* - printf( "Cleaning up:\n" ); - xt_print( jd->node_cache->children ); - */ - - tmp = jd->node_cache->children->next; - xt_free_node( jd->node_cache->children ); - jd->node_cache->children = tmp; - } - - /* Now flag the ones that were still unflagged. */ - for( c = jd->node_cache->children; c; c = c->next ) - { - /* - printf( "Flagged:\n" ); - xt_print( c ); - */ - - c->flags |= XT_SEEN; - } + /* This runs the garbage collection every minute, which means every packet + is in the cache for about a minute (which should be enough AFAIK). */ + jabber_cache_clean( gc ); } void jabber_init() @@ -252,7 +227,7 @@ void jabber_init() // ret->get_status_string = jabber_get_status_string; ret->set_away = jabber_set_away; // ret->set_info = jabber_set_info; -// ret->get_info = jabber_get_info; + ret->get_info = jabber_get_info; ret->add_buddy = jabber_add_buddy; ret->remove_buddy = jabber_remove_buddy; // ret->chat_send = jabber_chat_send; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 8ca7d545..58a81810 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -59,7 +59,7 @@ struct jabber_data struct jabber_away_state *away_state; char *away_message; - struct xt_node *node_cache; + GHashTable *node_cache; }; struct jabber_away_state @@ -68,6 +68,14 @@ struct jabber_away_state char *full_name; }; +typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *packet ); + +struct jabber_cache_entry +{ + struct xt_node *node; + jabber_cache_event func; +}; + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_start_iq_auth( struct gaim_connection *gc ); @@ -87,8 +95,10 @@ int presence_send_request( struct gaim_connection *gc, char *handle, char *reque char *set_eval_priority( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); -void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); -struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ); +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ); +struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); +void jabber_cache_entry_free( gpointer entry ); +void jabber_cache_clean( struct gaim_connection *gc ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 845c2d8c..11156258 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -81,30 +81,56 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) { struct jabber_data *jd = gc->proto_data; char *id = g_strdup_printf( "BeeX%04x", next_id++ ); - - /* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ + struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); xt_add_attr( node, "id", id ); - xt_add_child( jd->node_cache, node ); g_free( id ); + + entry->node = node; + g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } -/* Emptying this cache is a BIG TODO! */ -struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ) { struct jabber_data *jd = gc->proto_data; - struct xt_node *node; - char *s; + struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id ); - for( node = jd->node_cache->children; node; node = node->next ) - if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) - break; + return entry ? entry->node : NULL; +} + +void jabber_cache_entry_free( gpointer data ) +{ + struct jabber_cache_entry *entry = data; - return node; + xt_free_node( entry->node ); + g_free( entry ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); + +void jabber_cache_clean( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + + g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); +} + +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer ) +{ + struct jabber_cache_entry *entry = entry_; + struct xt_node *node = entry->node; + + if( node->flags & XT_SEEN ) + return TRUE; + else + { + node->flags |= XT_SEEN; + return FALSE; + } } const struct jabber_away_state jabber_away_state_list[] = -- cgit v1.2.3 From 861c199fb60fecf5dab96e0ed9d4b0cf0c57822f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 8 Oct 2006 20:41:11 +0200 Subject: Moved handling of all IQ packets to event handlers. Cleaned up a LOT of mess in iq.c! --- protocols/jabber/io.c | 8 +- protocols/jabber/iq.c | 274 ++++++++++++++++++++++------------------- protocols/jabber/jabber.c | 2 +- protocols/jabber/jabber.h | 7 +- protocols/jabber/jabber_util.c | 16 ++- 5 files changed, 165 insertions(+), 142 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index c6ad68e0..783d6d2c 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -213,7 +213,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } else { - return jabber_start_iq_auth( gc ); + return jabber_init_iq_auth( gc ); } } } @@ -350,7 +350,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) to be XMPP 1.0 compliant! */ else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) ) { - if( !jabber_start_iq_auth( gc ) ) + if( !jabber_init_iq_auth( gc ) ) return XT_ABORT; } @@ -359,7 +359,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply ); + jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); if( !jabber_write_packet( gc, reply ) ) return XT_ABORT; @@ -372,7 +372,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) reply = xt_new_node( "session", NULL, NULL ); xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply ); + jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); if( !jabber_write_packet( gc, reply ) ) return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index ae4ed099..1b968739 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,161 +27,161 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; - struct xt_node *query, *reply = NULL, *orig = NULL, *c; - char *s, *type, *xmlns; - int st; + char *type, *s; - query = xt_find_node( node->children, "query" ); type = xt_find_attr( node, "type" ); if( !type ) - return XT_HANDLED; /* Ignore it for now, don't know what's best... */ + { + hide_login_progress_error( gc, "Received IQ packet without type!" ); + signoff( gc ); + return XT_ABORT; + } + + if( ( s = xt_find_attr( node, "id" ) ) && + ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) ) + { + struct jabber_cache_entry *entry; + + entry = g_hash_table_lookup( jd->node_cache, s ); + + if( entry == NULL ) + serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s ); + else if( entry->func ) + return entry->func( gc, node, entry->node ); + } + + return XT_HANDLED; +} + +static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); + +int jabber_init_iq_auth( struct gaim_connection *gc ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *node; + int st; + + node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) ); + xt_add_attr( node, "xmlns", "jabber:iq:auth" ); + node = jabber_make_packet( "iq", "get", NULL, node ); - xmlns = xt_find_attr( query, "xmlns" ); + jabber_cache_add( gc, node, jabber_do_iq_auth ); + st = jabber_write_packet( gc, node ); - if( ( s = xt_find_attr( node, "id" ) ) ) - orig = jabber_cache_get( gc, s ); + return st; +} + +static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +{ + struct jabber_data *jd = gc->proto_data; + struct xt_node *reply, *query; + xt_status st; + char *s; - if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 ) + query = xt_find_node( node->children, "query" ); + + /* Time to authenticate ourselves! */ + reply = xt_new_node( "query", NULL, NULL ); + xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); + xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); + xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + + if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) { - /* Time to authenticate ourselves! */ - reply = xt_new_node( "query", NULL, NULL ); - xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); - xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); - xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + /* We can do digest authentication, it seems, and of + course we prefer that. */ + SHA_CTX sha; + char hash_hex[40]; + unsigned char hash[20]; + int i; - if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) - { - /* We can do digest authentication, it seems, and of - course we prefer that. */ - SHA_CTX sha; - char hash_hex[40]; - unsigned char hash[20]; - int i; - - shaInit( &sha ); - shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); - shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); - shaFinal( &sha, hash ); - - for( i = 0; i < 20; i ++ ) - sprintf( hash_hex + i * 2, "%02x", hash[i] ); - - xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); - } - else if( xt_find_node( query->children, "password" ) ) - { - /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ - xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); - } - else - { - xt_free_node( reply ); - - hide_login_progress( gc, "Can't find suitable authentication method" ); - signoff( gc ); - return XT_ABORT; - } + shaInit( &sha ); + shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); + shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); + shaFinal( &sha, hash ); - reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply ); - st = jabber_write_packet( gc, reply ); + for( i = 0; i < 20; i ++ ) + sprintf( hash_hex + i * 2, "%02x", hash[i] ); - return st ? XT_HANDLED : XT_ABORT; + xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); } - if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 ) + else if( xt_find_node( query->children, "password" ) ) { - struct xt_node *node; - - node = query->children; - while( ( node = xt_find_node( node, "item" ) ) ) - { - char *jid = xt_find_attr( node, "jid" ); - char *name = xt_find_attr( node, "name" ); - char *sub = xt_find_attr( node, "subscription" ); - - if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) - add_buddy( gc, NULL, jid, name ); - - node = node->next; - } - - account_online( gc ); + /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ + xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); } - else if( strcmp( type, "result" ) == 0 && orig ) + else { - struct xt_node *c; + xt_free_node( reply ); - if( !( jd->flags & JFLAG_AUTHENTICATED ) && - ( c = xt_find_node( orig->children, "query" ) ) && - ( c = xt_find_node( c->children, "username" ) ) && - c->text_len ) - { - /* This happens when we just successfully authenticated - the old (non-SASL) way. */ - jd->flags |= JFLAG_AUTHENTICATED; - if( !jabber_get_roster( gc ) ) - return XT_ABORT; - } - /* Tricky: Look for <bind> in the reply, because the server - should confirm the chosen resource string there. For - <session>, however, look in the cache, because the server - will probably not include it in its reply. */ - else if( ( c = xt_find_node( node->children, "bind" ) ) || - ( c = xt_find_node( orig->children, "session" ) ) ) - { - if( strcmp( c->name, "bind" ) == 0 ) - { - c = xt_find_node( c->children, "jid" ); - if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && - strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) - serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); - - jd->flags &= ~JFLAG_WAIT_BIND; - } - else if( strcmp( c->name, "session" ) == 0 ) - jd->flags &= ~JFLAG_WAIT_SESSION; - - if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) - { - if( !jabber_get_roster( gc ) ) - return XT_ABORT; - } - } + hide_login_progress( gc, "Can't find suitable authentication method" ); + signoff( gc ); + return XT_ABORT; } - else if( strcmp( type, "error" ) == 0 ) + + reply = jabber_make_packet( "iq", "set", NULL, reply ); + jabber_cache_add( gc, reply, jabber_finish_iq_auth ); + st = jabber_write_packet( gc, reply ); + + return st ? XT_HANDLED : XT_ABORT; +} + +static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +{ + char *type = xt_find_attr( node, "type" ); + struct jabber_data *jd = gc->proto_data; + + if( strcmp( type, "error" ) == 0 ) + { + hide_login_progress( gc, "Authentication failure" ); + signoff( gc ); + return XT_ABORT; + } + else if( strcmp( type, "result" ) == 0 ) { - if( !( jd->flags & JFLAG_AUTHENTICATED ) && - orig && - ( c = xt_find_node( orig->children, "query" ) ) && - ( c = xt_find_node( c->children, "username" ) ) && - c->text_len ) - { - hide_login_progress( gc, "Authentication failure" ); - signoff( gc ); + /* This happens when we just successfully authenticated the + old (non-SASL) way. */ + jd->flags |= JFLAG_AUTHENTICATED; + if( !jabber_get_roster( gc ) ) return XT_ABORT; - } } return XT_HANDLED; } -int jabber_start_iq_auth( struct gaim_connection *gc ) +xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) { struct jabber_data *jd = gc->proto_data; - struct xt_node *node; - int st; + struct xt_node *c; + char *s; - node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) ); - xt_add_attr( node, "xmlns", "jabber:iq:auth" ); - node = jabber_make_packet( "iq", "get", NULL, node ); + if( ( c = xt_find_node( node->children, "bind" ) ) ) + { + c = xt_find_node( c->children, "jid" ); + if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && + strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) + serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); + + jd->flags &= ~JFLAG_WAIT_BIND; + } + else + { + jd->flags &= ~JFLAG_WAIT_SESSION; + } - st = jabber_write_packet( gc, node ); + if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) + { + if( !jabber_get_roster( gc ) ) + return XT_ABORT; + } - xt_free_node( node ); - return st; + return XT_HANDLED; } +static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); + int jabber_get_roster( struct gaim_connection *gc ) { struct xt_node *node; @@ -193,12 +193,36 @@ int jabber_get_roster( struct gaim_connection *gc ) xt_add_attr( node, "xmlns", "jabber:iq:roster" ); node = jabber_make_packet( "iq", "get", NULL, node ); + jabber_cache_add( gc, node, jabber_parse_roster ); st = jabber_write_packet( gc, node ); - xt_free_node( node ); return st; } +static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +{ + struct xt_node *query, *c; + + query = xt_find_node( node->children, "query" ); + + c = query->children; + while( ( c = xt_find_node( c, "item" ) ) ) + { + char *jid = xt_find_attr( c, "jid" ); + char *name = xt_find_attr( c, "name" ); + char *sub = xt_find_attr( c, "subscription" ); + + if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) + add_buddy( gc, NULL, jid, name ); + + c = c->next; + } + + account_online( gc ); + + return XT_HANDLED; +} + int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) { struct xt_node *node; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 32d1d99d..b508cb45 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -173,7 +173,7 @@ static void jabber_get_info( struct gaim_connection *gc, char *who ) node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" ); node = jabber_make_packet( "iq", "get", who, node ); - jabber_cache_add( gc, node ); + // jabber_cache_add( gc, node, ); jabber_write_packet( gc, node ); } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 58a81810..6791a0f5 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -68,7 +68,7 @@ struct jabber_away_state char *full_name; }; -typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *packet ); +typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); struct jabber_cache_entry { @@ -78,7 +78,8 @@ struct jabber_cache_entry /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); -int jabber_start_iq_auth( struct gaim_connection *gc ); +int jabber_init_iq_auth( struct gaim_connection *gc ); +xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); int jabber_get_roster( struct gaim_connection *gc ); int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); @@ -95,7 +96,7 @@ int presence_send_request( struct gaim_connection *gc, char *handle, char *reque char *set_eval_priority( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ); +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ); struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); void jabber_cache_entry_free( gpointer entry ); void jabber_cache_clean( struct gaim_connection *gc ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 11156258..f26b9617 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -81,7 +81,7 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) +void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = gc->proto_data; char *id = g_strdup_printf( "BeeX%04x", next_id++ ); @@ -91,17 +91,10 @@ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node ) g_free( id ); entry->node = node; + entry->func = func; g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } -struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ) -{ - struct jabber_data *jd = gc->proto_data; - struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id ); - - return entry ? entry->node : NULL; -} - void jabber_cache_entry_free( gpointer data ) { struct jabber_cache_entry *entry = data; @@ -112,6 +105,11 @@ void jabber_cache_entry_free( gpointer data ) gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); +/* This one should be called from time to time (from keepalive, in this case) + to make sure things don't stay in the node cache forever. By marking nodes + during the first run and deleting marked nodes during a next run, every + node should be available in the cache for at least a minute (assuming the + function is indeed called every minute). */ void jabber_cache_clean( struct gaim_connection *gc ) { struct jabber_data *jd = gc->proto_data; -- cgit v1.2.3 From 6a1128d1333cf79f1ef9fb1f55b1b8fec67caf2a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 9 Oct 2006 20:19:05 +0200 Subject: The module now keeps track of all resources available for a buddy. This means the buddy won't show up offline when one resource goes down (while there are still others available). It also remembers away state information for every separate resource. Later this system will be used to keep track of client capability information (Typing notices, yay...) and who knows what else. --- protocols/jabber/jabber.c | 16 ++++- protocols/jabber/jabber.h | 19 ++++++ protocols/jabber/jabber_util.c | 132 +++++++++++++++++++++++++++++++++++++++++ protocols/jabber/presence.c | 59 ++++++++++++++---- 4 files changed, 212 insertions(+), 14 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b508cb45..266022ba 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -79,6 +79,7 @@ static void jabber_login( account_t *acc ) jd->server ++; jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free ); + jd->buddies = g_hash_table_new( g_str_hash, g_str_equal ); /* Figure out the hostname to connect to. */ if( acc->server ) @@ -168,10 +169,23 @@ static GList *jabber_away_states( struct gaim_connection *gc ) static void jabber_get_info( struct gaim_connection *gc, char *who ) { + struct jabber_buddy *bud; struct xt_node *node; + bud = jabber_buddy_by_jid( gc, who ); + while( bud ) + { + serv_got_crap( gc, "Buddy %s/%s (%d) information:\nAway state: %s\nAway message: %s", + bud->handle, bud->resource, bud->priority, + bud->away_state ? bud->away_state->full_name : "(none)", + bud->away_message ? : "(none)" ); + bud = bud->next; + } + +// node = xt_new_node( "vCard", NULL, NULL ); +// xt_add_attr( node, "xmlns", "vcard-temp" ); node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" ); + xt_add_attr( node, "xmlns", "jabber:iq:version" ); node = jabber_make_packet( "iq", "get", who, node ); // jabber_cache_add( gc, node, ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 6791a0f5..450c8be7 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -60,6 +60,7 @@ struct jabber_data char *away_message; GHashTable *node_cache; + GHashTable *buddies; }; struct jabber_away_state @@ -76,6 +77,21 @@ struct jabber_cache_entry jabber_cache_event func; }; +struct jabber_buddy +{ + char *handle; + char *resource; + + int priority; + struct jabber_away_state *away_state; + char *away_message; + + time_t last_act; + int flags; + + struct jabber_buddy *next; +}; + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_init_iq_auth( struct gaim_connection *gc ); @@ -103,6 +119,9 @@ void jabber_cache_clean( struct gaim_connection *gc ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); +struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ); +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ); +int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ); extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index f26b9617..f4cd40d4 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -201,3 +201,135 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } + +/* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a + FULL jid or if we already have this buddy/resource. */ +struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *new, *bi; + char *s; + + if( !( s = strchr( full_jid, '/' ) ) ) + return NULL; + + new = g_new0( struct jabber_buddy, 1 ); + + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) + { + new->handle = bud->handle; + + /* We already have another resource for this buddy, add the + new one to the list. */ + for( bi = bud; bi; bi = bi->next ) + { + /* Check for dupes. Resource seem to be case sensitive. */ + if( strcmp( bi->resource, s + 1 ) == 0 ) + { + *s = '/'; + g_free( new ); + return NULL; + } + /* Append the new item to the list. */ + else if( bi->next == NULL ) + { + bi->next = new; + break; + } + } + } + else + { + new->handle = g_strdup( full_jid ); + g_hash_table_insert( jd->buddies, new->handle, new ); + } + + *s = '/'; + new->resource = g_strdup( s + 1 ); + + return new; +} + +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud; + char *s; + + if( ( s = strchr( jid, '/' ) ) ) + { + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) + for( ; bud; bud = bud->next ) + if( strcmp( bud->resource, s + 1 ) == 0 ) + break; + } + else + { + /* TODO: Add selection. */ + return g_hash_table_lookup( jd->buddies, jid ); + } + + *s = '/'; + return bud; +} + +int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *prev, *bi; + char *s; + + if( !( s = strchr( full_jid, '/' ) ) ) + return 0; + + *s = 0; + if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) + { + /* If there's only one item in the list (and if the resource + matches), removing it is simple. (And the hash reference + should be removed too!) */ + if( bud->next == NULL && strcmp( bud->resource, s + 1 ) == 0 ) + { + g_hash_table_remove( jd->buddies, bud->handle ); + g_free( bud->handle ); + g_free( bud->resource ); + g_free( bud->away_message ); + g_free( bud ); + } + else + { + for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) + if( strcmp( bi->resource, s + 1 ) == 0 ) + break; + + if( bi ) + { + if( prev ) + prev->next = bi->next; + else + /* The hash table should point at the second + item, because we're removing the first. */ + g_hash_table_replace( jd->buddies, bi->handle, bi->next ); + + g_free( bi->resource ); + g_free( bi->away_message ); + g_free( bi ); + } + else + { + *s = '/'; + return 0; + } + } + + *s = '/'; + return 1; + } + else + { + *s = '/'; + return 0; + } +} diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 5bef498d..86bdcb1d 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -28,26 +28,62 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) struct gaim_connection *gc = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ - char *s; + struct xt_node *c; if( !from ) return XT_HANDLED; - s = strchr( from, '/' ); - if( s ) - *s = 0; - - /* Will implement better parsing of away states/msgs when we - finally do those API changes. Which will probably be after - merging this module into the main tree. */ if( type == NULL ) - serv_got_update( gc, from, 1, 0, 0, 0, 0, 0 ); + { + struct jabber_buddy *bud; + + if( !( bud = jabber_buddy_by_jid( gc, from ) ) ) + { + bud = jabber_buddy_add( gc, from ); + } + + g_free( bud->away_message ); + if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 ) + bud->away_message = g_strdup( c->text ); + else + bud->away_message = NULL; + + if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) + bud->away_state = (void*) jabber_away_state_by_code( c->text ); + else + bud->away_state = NULL; + + if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 ) + bud->priority = atoi( c->text ); + else + bud->priority = 0; + + serv_got_update( gc, bud->handle, 1, 0, 0, 0, 0, 0 ); + } else if( strcmp( type, "unavailable" ) == 0 ) - serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + { + char *s; + + jabber_buddy_remove( gc, from ); + + if( ( s = strchr( from, '/' ) ) ) + *s = 0; + + /* Only count this as offline if there's no other resource + available anymore. */ + if( jabber_buddy_by_jid( gc, from ) == NULL ) + serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + + *s = '/'; + } else if( strcmp( type, "subscribe" ) == 0 ) + { jabber_buddy_ask( gc, from ); + } else if( strcmp( type, "subscribed" ) == 0 ) + { serv_got_crap( gc, "%s just accepted your authorization request", from ); + } else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) { /* Do nothing here. Plenty of control freaks or over-curious @@ -69,9 +105,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) xt_print( node ); } - if( s ) - *s = '/'; - return XT_HANDLED; } -- cgit v1.2.3 From a21a8ac4fbd5a234bc8d31d9d487c74a81383c8a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 10 Oct 2006 14:05:42 +0200 Subject: Added resource selection (based on priority or time of last message) to budd_by_jid(), added a full_jid property to easily address that resource without having to rebuild the full JID every time and implemented typing notification shite. --- protocols/jabber/jabber.c | 72 ++++++++++++++++++++++++++++++++++++------ protocols/jabber/jabber.h | 20 ++++++++++-- protocols/jabber/jabber_util.c | 27 +++++++++++++--- protocols/jabber/message.c | 35 ++++++++++++++------ protocols/jabber/presence.c | 27 +++++++++++++--- 5 files changed, 149 insertions(+), 32 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 266022ba..91f88350 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -44,6 +44,8 @@ static void jabber_acc_init( account_t *acc ) s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; + s = set_add( &acc->set, "resource_select", "priority", NULL, acc ); + s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; @@ -136,19 +138,33 @@ static void jabber_close( struct gaim_connection *gc ) static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) { + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud; struct xt_node *node; int st; - /* - event = xt_new_node( "active", NULL, NULL ); - xt_add_attr( event, "xlmns", "http://jabber.org/protocol/chatstates" ); - - event = xt_new_node( "x", NULL, xt_new_node( "composing", NULL, NULL ) ); - xt_add_attr( event, "xmlns", "jabber:x:event" ); - */ + bud = jabber_buddy_by_jid( gc, who ); node = xt_new_node( "body", message, NULL ); - node = jabber_make_packet( "message", "chat", who, node ); + node = jabber_make_packet( "message", "chat", bud->full_jid, node ); + + if( ( jd->flags & JFLAG_WANT_TYPING ) && + ( ( bud->flags & JBFLAG_DOES_JEP85 ) || + !( bud->flags & JBFLAG_PROBED_JEP85 ) ) ) + { + struct xt_node *act; + + /* If the user likes typing notification and if we don't know + (and didn't probe before) if this resource supports JEP85, + include a probe in this packet now. */ + act = xt_new_node( "active", NULL, NULL ); + xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" ); + xt_add_child( node, act ); + + /* Just make sure we do this only once. */ + bud->flags |= JBFLAG_PROBED_JEP85; + } + st = jabber_write_packet( gc, node ); xt_free_node( node ); @@ -228,6 +244,44 @@ static void jabber_keepalive( struct gaim_connection *gc ) jabber_cache_clean( gc ); } +static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud; + + /* Enable typing notification related code from now. */ + jd->flags |= JFLAG_WANT_TYPING; + + bud = jabber_buddy_by_jid( gc, who ); + if( bud->flags & JBFLAG_DOES_JEP85 ) + { + /* We're only allowed to send this stuff if we know the other + side supports it. */ + + struct xt_node *node; + char *type; + int st; + + if( typing == 0 ) + type = "active"; + else if( typing == 2 ) + type = "paused"; + else /* if( typing == 1 ) */ + type = "composing"; + + node = xt_new_node( type, NULL, NULL ); + xt_add_attr( node, "xmlns", "http://jabber.org/protocol/chatstates" ); + node = jabber_make_packet( "message", "chat", bud->full_jid, node ); + + st = jabber_write_packet( gc, node ); + xt_free_node( node ); + + return st; + } + + return 1; +} + void jabber_init() { struct prpl *ret = g_new0( struct prpl, 1 ); @@ -249,7 +303,7 @@ void jabber_init() // ret->chat_leave = jabber_chat_leave; // ret->chat_open = jabber_chat_open; ret->keepalive = jabber_keepalive; -// ret->send_typing = jabber_send_typing; + ret->send_typing = jabber_send_typing; ret->handle_cmp = g_strcasecmp; register_protocol( ret ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 450c8be7..3535ecc5 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -31,13 +31,26 @@ typedef enum { - JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ + JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream + and want to do auth. */ JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ - JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ - JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply before we continue. */ + JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after + SASL or TLS). */ + JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply + before we continue. */ JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ + JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this + activates all JEP-85 related code. */ } jabber_flags_t; +typedef enum +{ + JBFLAG_PROBED_JEP85 = 1, /* Set this when we sent our probe packet to make + sure it gets sent only once. */ + JBFLAG_DOES_JEP85 = 2, /* Set this when the resource seems to support + JEP85 (typing notification shite). */ +} jabber_buddy_flag_t; + struct jabber_data { struct gaim_connection *gc; @@ -80,6 +93,7 @@ struct jabber_cache_entry struct jabber_buddy { char *handle; + char *full_jid; char *resource; int priority; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index f4cd40d4..357743d3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -246,7 +246,8 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji } *s = '/'; - new->resource = g_strdup( s + 1 ); + new->full_jid = g_strdup( full_jid ); + new->resource = strchr( new->full_jid, '/' ) + 1; return new; } @@ -267,8 +268,24 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid } else { - /* TODO: Add selection. */ - return g_hash_table_lookup( jd->buddies, jid ); + struct jabber_buddy *best_prio, *best_time; + char *set; + + best_prio = best_time = bud = g_hash_table_lookup( jd->buddies, jid ); + for( ; bud; bud = bud->next ) + { + if( bud->priority > best_prio->priority ) + best_prio = bud; + if( bud->last_act > best_time->last_act ) + best_time = bud; + } + + if( ( set = set_getstr( &gc->acc->set, "resource_select" ) ) == NULL ) + return NULL; + else if( strcmp( set, "activity" ) == 0 ) + return best_time; + else /* if( strcmp( set, "priority" ) == 0 ) */ + return best_prio; } *s = '/'; @@ -294,7 +311,7 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) { g_hash_table_remove( jd->buddies, bud->handle ); g_free( bud->handle ); - g_free( bud->resource ); + g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); } @@ -313,7 +330,7 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) item, because we're removing the first. */ g_hash_table_replace( jd->buddies, bi->handle, bi->next ); - g_free( bi->resource ); + g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); } diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index b41522fd..fea728e3 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -28,27 +28,42 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) struct gaim_connection *gc = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); - struct xt_node *msg = xt_find_node( node->children, "body" ); + struct xt_node *body = xt_find_node( node->children, "body" ); - if( !type || !msg ) + if( !type ) return XT_HANDLED; /* Grmbl... FIXME */ if( strcmp( type, "chat" ) == 0 ) { - char *s; + struct jabber_buddy *bud = NULL; - s = strchr( from, '/' ); - if( s ) - *s = 0; + if( strchr( from, '/' ) == NULL ) + { + /* It just shouldn't happen. */ + hide_login_progress( gc, "Received message packet from bare JID" ); + signoff( gc ); + return XT_ABORT; + } - serv_got_im( gc, from, msg->text, 0, 0, 0 ); + bud = jabber_buddy_by_jid( gc, from ); + bud->last_act = time( NULL ); - if( s ) - *s = '/'; + if( body ) /* Could be just a typing notification. */ + serv_got_im( gc, bud->handle, body->text, 0, 0, 0 ); + + if( xt_find_node( node->children, "composing" ) ) + { + bud->flags |= JBFLAG_DOES_JEP85; + serv_got_typing( gc, bud->handle, 0, 1 ); + } + else if( xt_find_node( node->children, "active" ) ) + { + bud->flags |= JBFLAG_DOES_JEP85; + } } else { - printf( "Received MSG from %s: %s\n", from, msg ? msg->text : "<null>" ); + printf( "Received MSG from %s:\n", from ); xt_print( node ); } diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 86bdcb1d..3a682e52 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -29,13 +29,19 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; + struct jabber_buddy *bud; if( !from ) return XT_HANDLED; if( type == NULL ) { - struct jabber_buddy *bud; + if( strchr( from, '/' ) == NULL ) + { + char *s = xt_to_string( node ); + serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); + g_free( s ); + } if( !( bud = jabber_buddy_by_jid( gc, from ) ) ) { @@ -51,23 +57,34 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) bud->away_state = (void*) jabber_away_state_by_code( c->text ); else + { bud->away_state = NULL; + /* Let's only set last_act if there's *no* away state, + since it could be some auto-away thingy. */ + bud->last_act = time( NULL ); + } if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 ) bud->priority = atoi( c->text ); else bud->priority = 0; - serv_got_update( gc, bud->handle, 1, 0, 0, 0, 0, 0 ); + serv_got_update( gc, bud->handle, 1, 0, 0, 0, + bud->away_state ? UC_UNAVAILABLE : 0, 0 ); } else if( strcmp( type, "unavailable" ) == 0 ) { char *s; - jabber_buddy_remove( gc, from ); + if( ( s = strchr( from, '/' ) ) == NULL ) + { + char *s = xt_to_string( node ); + serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); + g_free( s ); + } - if( ( s = strchr( from, '/' ) ) ) - *s = 0; + jabber_buddy_remove( gc, from ); + *s = 0; /* Only count this as offline if there's no other resource available anymore. */ -- cgit v1.2.3 From 8eb10c9dbdf1497a5e154e3d32734f79f42e8213 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 10 Oct 2006 14:10:20 +0200 Subject: Oops... When I say ignore, I really mean ignore! --- protocols/jabber/presence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 3a682e52..b10ce634 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -41,6 +41,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *s = xt_to_string( node ); serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); g_free( s ); + return XT_HANDLED; } if( !( bud = jabber_buddy_by_jid( gc, from ) ) ) @@ -81,6 +82,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *s = xt_to_string( node ); serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); g_free( s ); + return XT_HANDLED; } jabber_buddy_remove( gc, from ); -- cgit v1.2.3 From 58b5f622cd003433dc78b4f510c667baf537424a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 11 Oct 2006 10:45:45 +0200 Subject: Handling of some basic IQ-get packets. --- protocols/jabber/iq.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 1b968739..e39f3064 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,22 +27,31 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; struct jabber_data *jd = gc->proto_data; + struct xt_node *c, *reply = NULL; char *type, *s; + int st; type = xt_find_attr( node, "type" ); if( !type ) { - hide_login_progress_error( gc, "Received IQ packet without type!" ); + hide_login_progress_error( gc, "Received IQ packet without type." ); signoff( gc ); return XT_ABORT; } - if( ( s = xt_find_attr( node, "id" ) ) && - ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) ) + if( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) { struct jabber_cache_entry *entry; + if( ( s = xt_find_attr( node, "id" ) ) == NULL ) + { + /* Silently ignore it, without an ID we don't know + how to handle the packet, but it doesn't have + to be a serious problem. */ + return XT_HANDLED; + } + entry = g_hash_table_lookup( jd->node_cache, s ); if( entry == NULL ) @@ -50,6 +59,64 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) else if( entry->func ) return entry->func( gc, node, entry->node ); } + else if( strcmp( type, "get" ) == 0 ) + { + if( !( c = xt_find_node( node->children, "query" ) ) || + !( s = xt_find_attr( c, "xmlns" ) ) ) + { + serv_got_crap( gc, "WARNING: Received incomplete IQ-get packet" ); + return XT_HANDLED; + } + + reply = xt_new_node( "query", NULL, NULL ); + xt_add_attr( reply, "xmlns", s ); + + /* Of course this is a very essential query to support. ;-) */ + if( strcmp( s, "jabber:iq:version" ) == 0 ) + { + xt_add_child( reply, xt_new_node( "name", "BitlBee", NULL ) ); + xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) ); + xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) ); + } + else if( strcmp( s, "http://jabber.org/protocol/disco#info" ) == 0 ) + { + c = xt_new_node( "identity", NULL, NULL ); + xt_add_attr( c, "category", "client" ); + xt_add_attr( c, "type", "pc" ); + xt_add_attr( c, "name", "BitlBee" ); + xt_add_child( reply, c ); + + c = xt_new_node( "feature", NULL, NULL ); + xt_add_attr( c, "var", "jabber:iq:version" ); + xt_add_child( reply, c ); + + c = xt_new_node( "feature", NULL, NULL ); + xt_add_attr( c, "var", "http://jabber.org/protocol/chatstates" ); + xt_add_child( reply, c ); + + /* Later this can be useful to announce things like + MUC support. */ + } + else + { + xt_free_node( reply ); + reply = NULL; + } + + /* If we recognized the xmlns and managed to generate a reply, + finish and send it. */ + if( reply ) + { + reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), reply ); + if( ( s = xt_find_attr( node, "id" ) ) ) + xt_add_attr( reply, "id", s ); + + st = jabber_write_packet( gc, reply ); + xt_free_node( reply ); + if( !st ) + return XT_ABORT; + } + } return XT_HANDLED; } -- cgit v1.2.3 From b56b220e4280a75577f79b9dbcaf6eb2d7336873 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 11 Oct 2006 20:29:56 +0200 Subject: Fixed issues in end-of-connection detection and added basic "handling" of stream errors. (They can't really be handled, but at least the user can be informed.) --- protocols/jabber/io.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 783d6d2c..aa43d04e 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -161,7 +161,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( st > 0 ) { /* Parse. */ - if( !xt_feed( jd->xt, buf, st ) ) + if( xt_feed( jd->xt, buf, st ) < 0 ) { hide_login_progress_error( gc, "XML stream error" ); signoff( gc ); @@ -278,6 +278,7 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) { + signoff( data ); return XT_ABORT; } @@ -426,6 +427,53 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) return XT_HANDLED; } +static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) +{ + struct gaim_connection *gc = data; + struct xt_node *c; + char *s, *type = NULL, *text = NULL; + + for( c = node->children; c; c = c->next ) + { + if( !( s = xt_find_attr( c, "xmlns" ) ) || + strcmp( s, "urn:ietf:params:xml:ns:xmpp-streams" ) != 0 ) + continue; + + if( strcmp( c->name, "text" ) != 0 ) + { + type = c->name; + } + /* Only use the text if it doesn't have an xml:lang attribute, + if it's empty or if it's set to something English. */ + else if( !( s = xt_find_attr( c, "xml:lang" ) ) || + !*s || strncmp( s, "en", 2 ) == 0 ) + { + text = c->text; + } + } + + /* Tssk... */ + if( type == NULL ) + { + hide_login_progress_error( gc, "Unknown stream error reported by server" ); + signoff( gc ); + return XT_ABORT; + } + + /* We know that this is a fatal error. If it's a "conflict" error, we + should turn off auto-reconnect to make sure we won't get some nasty + infinite loop! */ + if( strcmp( type, "conflict" ) == 0 ) + gc->wants_to_die = TRUE; + + s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); + hide_login_progress_error( gc, s ); + g_free( s ); + signoff( gc ); + + return XT_ABORT; +} + static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) { printf( "Received unknown packet:\n" ); @@ -440,6 +488,7 @@ static const struct xt_handler_entry jabber_handlers[] = { { "presence", "stream:stream", jabber_pkt_presence }, { "iq", "stream:stream", jabber_pkt_iq }, { "stream:features", "stream:stream", jabber_pkt_features }, + { "stream:error", "stream:stream", jabber_pkt_stream_error }, { "proceed", "stream:stream", jabber_pkt_proceed_tls }, { "challenge", "stream:stream", sasl_pkt_challenge }, { "success", "stream:stream", sasl_pkt_result }, -- cgit v1.2.3 From 259edd40f5e332791a44f7547346bf799f1f7327 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 12 Oct 2006 19:48:58 +0200 Subject: Special message when the XMPP session is ended because of a concurrent login, and now sending proper error responses to IQ packets we can't handle. --- protocols/jabber/io.c | 12 +++++++++--- protocols/jabber/iq.c | 34 +++++++++++++++++++++++----------- protocols/jabber/jabber.h | 1 + protocols/jabber/jabber_util.c | 32 +++++++++++++++++++++++++++++++- protocols/jabber/xmltree.c | 36 ++++++++++++++++++++++++++++++++++++ protocols/jabber/xmltree.h | 1 + 6 files changed, 101 insertions(+), 15 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index aa43d04e..665f5322 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -464,11 +464,17 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) should turn off auto-reconnect to make sure we won't get some nasty infinite loop! */ if( strcmp( type, "conflict" ) == 0 ) + { + hide_login_progress( gc, "Account and resource used from a different location" ); gc->wants_to_die = TRUE; + } + else + { + s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); + hide_login_progress_error( gc, s ); + g_free( s ); + } - s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); - hide_login_progress_error( gc, s ); - g_free( s ); signoff( gc ); return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e39f3064..265fae53 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -29,7 +29,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) struct jabber_data *jd = gc->proto_data; struct xt_node *c, *reply = NULL; char *type, *s; - int st; + int st, pack = 1; type = xt_find_attr( node, "type" ); @@ -100,22 +100,34 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) else { xt_free_node( reply ); - reply = NULL; + reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); + pack = 0; } - - /* If we recognized the xmlns and managed to generate a reply, - finish and send it. */ - if( reply ) + } + else if( strcmp( type, "set" ) == 0 ) + { + xt_free_node( reply ); + reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); + pack = 0; + } + + /* If we recognized the xmlns and managed to generate a reply, + finish and send it. */ + if( reply ) + { + /* Normally we still have to pack it into an iq-result + packet, but for errors, for example, we don't. */ + if( pack ) { reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), reply ); if( ( s = xt_find_attr( node, "id" ) ) ) xt_add_attr( reply, "id", s ); - - st = jabber_write_packet( gc, reply ); - xt_free_node( reply ); - if( !st ) - return XT_ABORT; } + + st = jabber_write_packet( gc, reply ); + xt_free_node( reply ); + if( !st ) + return XT_ABORT; } return XT_HANDLED; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 3535ecc5..e5b85f39 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -126,6 +126,7 @@ int presence_send_request( struct gaim_connection *gc, char *handle, char *reque char *set_eval_priority( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); +struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ); void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ); struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); void jabber_cache_entry_free( gpointer entry ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 357743d3..d9a89951 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -78,7 +78,37 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ return node; } -/* Cache a node/packet for later use. Mainly useful for IQ packets if you need +struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ) +{ + struct xt_node *node, *c; + char *to; + + /* Create the "defined-condition" tag. */ + c = xt_new_node( err_cond, NULL, NULL ); + xt_add_attr( c, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); + + /* Put it in an <error> tag. */ + c = xt_new_node( "error", NULL, c ); + xt_add_attr( c, "type", err_type ); + + /* To make the actual error packet, we copy the original packet and + add our <error>/type="error" tag. Including the original packet + is recommended, so let's just do it. */ + node = xt_dup( orig ); + xt_add_child( node, c ); + xt_add_attr( node, "type", "error" ); + + /* Return to sender. */ + if( ( to = xt_find_attr( node, "from" ) ) ) + { + xt_add_attr( node, "to", to ); + xt_remove_attr( node, "from" ); + } + + return node; +} + +/* Cache a node/epacket for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get an id= tag, and do NOT free() the packet after writing it! */ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index af0c5832..7a165a1e 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -549,3 +549,39 @@ void xt_add_attr( struct xt_node *node, char *key, char *value ) node->attr[i].value = g_strdup( value ); } + +int xt_remove_attr( struct xt_node *node, char *key ) +{ + int i, last; + + for( i = 0; node->attr[i].key; i ++ ) + if( strcmp( node->attr[i].key, key ) == 0 ) + break; + + /* If we didn't find the attribute... */ + if( node->attr[i].key == NULL ) + return 0; + + g_free( node->attr[i].key ); + g_free( node->attr[i].value ); + + /* If it's the last, this is easy: */ + if( node->attr[i+1].key == NULL ) + { + node->attr[i].key = node->attr[i].value = NULL; + } + else /* It's also pretty easy, actually. */ + { + /* Find the last item. */ + for( last = i + 1; node->attr[last+1].key; last ++ ); + + node->attr[i] = node->attr[last]; + node->attr[last].key = NULL; + node->attr[last].value = NULL; + } + + /* Let's not bother with reallocating memory here. It takes time and + most packets don't stay in memory for long anyway. */ + + return 1; +} diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h index 4abb094f..70850c1d 100644 --- a/protocols/jabber/xmltree.h +++ b/protocols/jabber/xmltree.h @@ -92,5 +92,6 @@ char *xt_find_attr( struct xt_node *node, char *key ); struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); void xt_add_child( struct xt_node *parent, struct xt_node *child ); void xt_add_attr( struct xt_node *node, char *key, char *value ); +int xt_remove_attr( struct xt_node *node, char *key ); #endif -- cgit v1.2.3 From a4effbf8f749459340cb353a29053e6f69850f63 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 12 Oct 2006 23:01:51 +0200 Subject: Replies to jabber:iq:time packets. --- protocols/jabber/iq.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 265fae53..8a7b3192 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -78,6 +78,20 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) ); xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) ); } + else if( strcmp( s, "jabber:iq:time" ) == 0 ) + { + time_t time_ep; + char buf[1024]; + + buf[sizeof(buf)-1] = 0; + time_ep = time( NULL ); + + strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%S", gmtime( &time_ep ) ); + xt_add_child( reply, xt_new_node( "utc", buf, NULL ) ); + + strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); + xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); + } else if( strcmp( s, "http://jabber.org/protocol/disco#info" ) == 0 ) { c = xt_new_node( "identity", NULL, NULL ); @@ -90,6 +104,10 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xt_add_attr( c, "var", "jabber:iq:version" ); xt_add_child( reply, c ); + c = xt_new_node( "feature", NULL, NULL ); + xt_add_attr( c, "var", "jabber:iq:time" ); + xt_add_child( reply, c ); + c = xt_new_node( "feature", NULL, NULL ); xt_add_attr( c, "var", "http://jabber.org/protocol/chatstates" ); xt_add_child( reply, c ); -- cgit v1.2.3 From 7e83adca0e875710627588bf28ddb60fb61bd43b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 13 Oct 2006 00:14:00 +0200 Subject: Fixed get_info(), now that buddy_by_jid() doesn't just return the first resource in the list anymore. --- protocols/jabber/jabber.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 91f88350..26d7bbab 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -185,10 +185,14 @@ static GList *jabber_away_states( struct gaim_connection *gc ) static void jabber_get_info( struct gaim_connection *gc, char *who ) { + struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud; - struct xt_node *node; - bud = jabber_buddy_by_jid( gc, who ); + if( strchr( who, '/' ) ) + bud = jabber_buddy_by_jid( gc, who ); + else + bud = g_hash_table_lookup( jd->buddies, who ); + while( bud ) { serv_got_crap( gc, "Buddy %s/%s (%d) information:\nAway state: %s\nAway message: %s", @@ -197,15 +201,6 @@ static void jabber_get_info( struct gaim_connection *gc, char *who ) bud->away_message ? : "(none)" ); bud = bud->next; } - -// node = xt_new_node( "vCard", NULL, NULL ); -// xt_add_attr( node, "xmlns", "vcard-temp" ); - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", "jabber:iq:version" ); - node = jabber_make_packet( "iq", "get", who, node ); - // jabber_cache_add( gc, node, ); - - jabber_write_packet( gc, node ); } static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) -- cgit v1.2.3 From 695e39232324711816f1db8e25fdba59a0c6456f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 13 Oct 2006 23:44:54 +0200 Subject: Fixed some memory leaking in the MSN Passport code. --- protocols/msn/passport.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index dd1d9b6f..42b6ea73 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -58,6 +58,7 @@ static int passport_get_id_real( gpointer func, gpointer data, char *header ) rep = g_new0( struct passport_reply, 1 ); rep->data = data; rep->func = func; + rep->header = header; server = g_strdup( prd_cached ); dummy = strchr( server, '/' ); @@ -124,10 +125,14 @@ static void passport_get_id_ready( struct http_request *req ) static char *passport_create_header( char *cookie, char *email, char *pwd ) { - char *buffer = g_new0( char, 2048 ); + char *buffer; char *currenttoken; char *email_enc, *pwd_enc; + currenttoken = strstr( cookie, "lc=" ); + if( currenttoken == NULL ) + return NULL; + email_enc = g_new0( char, strlen( email ) * 3 + 1 ); strcpy( email_enc, email ); http_encode( email_enc ); @@ -136,20 +141,15 @@ static char *passport_create_header( char *cookie, char *email, char *pwd ) strcpy( pwd_enc, pwd ); http_encode( pwd_enc ); - currenttoken = strstr( cookie, "lc=" ); - if( currenttoken == NULL ) - return( NULL ); - - g_snprintf( buffer, 2048, - "Authorization: Passport1.4 OrgVerb=GET," - "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," - "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, - currenttoken ); + buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET," + "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," + "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, + currenttoken ); g_free( email_enc ); g_free( pwd_enc ); - return( buffer ); + return buffer; } static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) -- cgit v1.2.3 From 3ef6410bab141e5c6ea465730a37289991c38f9f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 11:26:06 +0200 Subject: Removed a reference to an already free()d variable from cmd_remove(). --- root_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/root_commands.c b/root_commands.c index 3097dc81..64dc71b9 100644 --- a/root_commands.c +++ b/root_commands.c @@ -572,7 +572,7 @@ static void cmd_remove( irc_t *irc, char **cmd ) u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); user_del( irc, cmd[1] ); - nick_del( u->gc->acc, u->handle ); + nick_del( u->gc->acc, s ); irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); g_free( s ); -- cgit v1.2.3 From 2529faf12adfc414048dc41e949065855d0da945 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 16:02:27 +0200 Subject: Small documentation fix (closes #208). --- doc/user-guide/commands.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 790e89f6..a920cfae 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -432,9 +432,11 @@ <bitlbee-setting name="display_namechanges" type="boolean" scope="global"> <default>false</default> - <para> - With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name". - </para> + <description> + <para> + With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name". + </para> + </description> </bitlbee-setting> <bitlbee-setting name="handle_unknown" type="string" scope="global"> -- cgit v1.2.3 From ee5c3558c7db32750e1029a1b4983672dc519bca Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 17:01:13 +0200 Subject: Documentation updates. --- doc/user-guide/commands.xml | 54 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 790e89f6..09d4b7b6 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -29,20 +29,13 @@ <description> <para> - Note that the servertag argument is optional. You only have to use it if the part after the @ in your handle isn't the hostname of your Jabber server, or if you want to use SSL/connect to a non-standard port number. The format is simple: [<servername>[:<portnumber>][:ssl]]. + The handle should be a full handle, including the domain name. You can specify a servername if necessary. Normally BitlBee doesn't need this though, since it's able to find out the server by doing DNS SRV lookups. </para> - </description> - <description> <para> - Google Talk uses the Jabber protocol. Please note that Google talk is SSL-only, but officially reachable over both port 5222 and 5223. Usually BitlBee users have to connect via port 5223, for example like this: + In previous versions it was also possible to specify port numbers and/or SSL in the server tag. This is deprecated and should now be done using the <emphasis>account set</emphasis> command. This also applies to specifying a resource in the handle (like <emphasis>wilmer@bitlbee.org/work</emphasis>). </para> </description> - - <ircexample> - <ircline nick="wilmer">account add jabber example@gmail.com hobbelmeeuw talk.google.com:5223:ssl</ircline> - <ircline nick="root">Account successfully added</ircline> - </ircexample> </bitlbee-command> <bitlbee-command name="msn"> @@ -514,6 +507,20 @@ </description> </bitlbee-setting> + <bitlbee-setting name="priority" type="integer" scope="account"> + <default>0</default> + + <description> + <para> + Can be set for Jabber connections. When connecting to one account from multiple places, this priority value will help the server to determine where to deliver incoming messages (that aren't addressed to a specific resource already). + </para> + + <para> + According to RFC 3921 servers will always deliver messages to the server with the highest priority value. Mmessages will not be delivered to resources with a negative priority setting (and should be saved as an off-line message if all available resources have a negative priority value). + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="private" type="boolean" scope="global"> <default>true</default> @@ -553,6 +560,21 @@ </description> </bitlbee-setting> + <bitlbee-setting name="resource_select" type="string" scope="account"> + <default>priority</default> + <possible-values>priority, time</possible-values> + + <description> + <para> + Because the IRC interface makes it pretty hard to specify the resource to talk to (when a buddy is online through different resources), this setting was added. + </para> + + <para> + Normally it's set to <emphasis>priority</emphasis> which means messages will always be delivered to the buddy's resource with the highest priority. If the setting is set to <emphasis>time</emphasis>, messages will be delivered to the resource that was last used to send you a message (or the resource that most recently connected). + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="save_on_quit" type="boolean" scope="global"> <default>true</default> @@ -594,6 +616,20 @@ </description> </bitlbee-setting> + <bitlbee-setting name="tls" type="boolean" scope="account"> + <default>try</default> + + <description> + <para> + Newer Jabber servers allow clients to convert a plain-text session to a TLS/SSL-encrypted session. Normally (with this setting set to <emphasis>try</emphasis>) BitlBee will do this, if possible. + </para> + + <para> + If you want to force BitlBee to use TLS sessions only (and to give up if that doesn't seem to be possible) you can set this setting to <emphasis>true</emphasis>. Set it to <emphasis>false</emphasis> if you want the session to remain plain-text. + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="to_char" type="string" scope="global"> <default>": "</default> -- cgit v1.2.3 From 3dc9d46cc20d287c266fed97f92d298ed721f7b3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 17:32:46 +0200 Subject: Fixed a very interesting memory leak in the OSCAR module. --- protocols/msn/msn.c | 1 - protocols/oscar/info.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 46049108..f7e57707 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -366,7 +366,6 @@ static char *msn_set_display_name( set_t *set, char *value ) struct gaim_connection *gc = acc->gc; struct msn_data *md; char buf[1024], *fn; - int i; /* Double-check. */ if( gc == NULL ) diff --git a/protocols/oscar/info.c b/protocols/oscar/info.c index ffe29d1f..0f1bcfd2 100644 --- a/protocols/oscar/info.c +++ b/protocols/oscar/info.c @@ -260,6 +260,7 @@ guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len) if (!identified) { /*FIXME*/ + /*REMOVEME :-) g_strdup_printf("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], @@ -267,7 +268,7 @@ guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len) cap[8], cap[9], cap[10], cap[11], cap[12], cap[13], cap[14], cap[15]); - + */ } g_free(cap); -- cgit v1.2.3 From a3265629451475df75a3cd1fbe1805bbb71b2365 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 20:44:47 +0200 Subject: Fixing early free(). Memory management in the passport code is getting too messy, really... :-( --- protocols/msn/passport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 42b6ea73..9fe6a174 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -211,6 +211,7 @@ static void passport_retrieve_dalogin_ready( struct http_request *req ) if( passport_get_id_real( rep->func, rep->data, rep->header ) ) { + rep->header = NULL; destroy_reply( rep ); return; } -- cgit v1.2.3 From 5eec897b4d962e643e26574d1bffc22ffcaddac6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 21:53:42 +0200 Subject: set_eval_int() now allows negative integers. --- set.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/set.c b/set.c index 6a45fd14..d172a79f 100644 --- a/set.c +++ b/set.c @@ -174,6 +174,10 @@ char *set_eval_int( set_t *set, char *value ) { char *s; + /* Allow a minus at the first position. */ + if( *s == '-' ) + s ++; + for( s = value; *s; s ++ ) if( !isdigit( *s ) ) return NULL; -- cgit v1.2.3 From 788a1afa9628aeaf9d69fc53f49131a4330253cf Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 22:24:01 +0200 Subject: Proper cleanup of jabber buddy structures when removing a buddy from the list, proper checking (and handling) of events related to buddies that aren't "hashed" yet, limit checks on priorityto setting, renamed JEP85 to XEP85, support for more XEP85 states. --- protocols/jabber/jabber.c | 25 ++++++++++++------ protocols/jabber/jabber.h | 9 ++++--- protocols/jabber/jabber_util.c | 57 ++++++++++++++++++++++++++++++++++++++---- protocols/jabber/message.c | 31 ++++++++++++++++------- protocols/jabber/presence.c | 28 +++++++++++++++++++-- 5 files changed, 122 insertions(+), 28 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 26d7bbab..abc3837b 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -146,23 +146,23 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, bud = jabber_buddy_by_jid( gc, who ); node = xt_new_node( "body", message, NULL ); - node = jabber_make_packet( "message", "chat", bud->full_jid, node ); + node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); - if( ( jd->flags & JFLAG_WANT_TYPING ) && - ( ( bud->flags & JBFLAG_DOES_JEP85 ) || - !( bud->flags & JBFLAG_PROBED_JEP85 ) ) ) + if( ( jd->flags & JFLAG_WANT_TYPING ) && bud && + ( ( bud->flags & JBFLAG_DOES_XEP85 ) || + !( bud->flags & JBFLAG_PROBED_XEP85 ) ) ) { struct xt_node *act; /* If the user likes typing notification and if we don't know - (and didn't probe before) if this resource supports JEP85, + (and didn't probe before) if this resource supports XEP85, include a probe in this packet now. */ act = xt_new_node( "active", NULL, NULL ); xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" ); xt_add_child( node, act ); /* Just make sure we do this only once. */ - bud->flags |= JBFLAG_PROBED_JEP85; + bud->flags |= JBFLAG_PROBED_XEP85; } st = jabber_write_packet( gc, node ); @@ -225,6 +225,9 @@ static void jabber_add_buddy( struct gaim_connection *gc, char *who ) static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group ) { + /* We should always do this part. Clean up our administration a little bit. */ + jabber_buddy_remove_bare( gc, who ); + if( jabber_remove_from_roster( gc, who ) ) presence_send_request( gc, who, "unsubscribe" ); } @@ -247,8 +250,14 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing /* Enable typing notification related code from now. */ jd->flags |= JFLAG_WANT_TYPING; - bud = jabber_buddy_by_jid( gc, who ); - if( bud->flags & JBFLAG_DOES_JEP85 ) + if( ( bud = jabber_buddy_by_jid( gc, who ) ) == NULL ) + { + /* Sending typing notifications to unknown buddies is + unsupported for now. Shouldn't be a problem, I think. */ + return 0; + } + + if( bud->flags & JBFLAG_DOES_XEP85 ) { /* We're only allowed to send this stuff if we know the other side supports it. */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index e5b85f39..d1d452b4 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -40,15 +40,15 @@ typedef enum before we continue. */ JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this - activates all JEP-85 related code. */ + activates all XEP-85 related code. */ } jabber_flags_t; typedef enum { - JBFLAG_PROBED_JEP85 = 1, /* Set this when we sent our probe packet to make + JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make sure it gets sent only once. */ - JBFLAG_DOES_JEP85 = 2, /* Set this when the resource seems to support - JEP85 (typing notification shite). */ + JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support + XEP85 (typing notification shite). */ } jabber_buddy_flag_t; struct jabber_data @@ -137,6 +137,7 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ); struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ); int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ); +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ); extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index d9a89951..d5d038cf 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -28,13 +28,20 @@ static int next_id = 1; char *set_eval_priority( set_t *set, char *value ) { account_t *acc = set->data; - char *ret; + int i; - ret = set_eval_int( set, value ); + if( sscanf( value, "%d", &i ) == 1 ) + { + /* Priority is a signed 8-bit integer, according to RFC 3921. */ + if( i < -128 || i > 127 ) + return NULL; + } + else + return NULL; /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ - if( acc->gc && ret ) + if( acc->gc ) { /* Although set_eval functions usually are very nice and convenient, they have one disadvantage: If I would just @@ -46,14 +53,14 @@ char *set_eval_priority( set_t *set, char *value ) functions next to evals, or just do this little hack: */ g_free( set->value ); - set->value = g_strdup( ret ); + set->value = g_strdup( value ); /* (Yes, sorry, I prefer the hack. :-P) */ presence_send_update( acc->gc ); } - return ret; + return value; } char *set_eval_tls( set_t *set, char *value ) @@ -282,6 +289,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji return new; } +/* Finds a buddy from our structures. Can find both full- and bare JIDs. When + asked for a bare JID, it uses the "resource_select" setting to see which + resource to pick. */ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) { struct jabber_data *jd = gc->proto_data; @@ -322,6 +332,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid return bud; } +/* Remove one specific full JID from our list. Use this when a buddy goes + off-line (because (s)he can still be online from a different location. */ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) { struct jabber_data *jd = gc->proto_data; @@ -380,3 +392,38 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) return 0; } } + +/* Remove a buddy completely; removes all resources that belong to the + specified bare JID. Use this when removing someone from the contact + list, for example. */ +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) +{ + struct jabber_data *jd = gc->proto_data; + struct jabber_buddy *bud, *next; + + if( strchr( bare_jid, '/' ) ) + return 0; + + if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) + { + /* Most important: Remove the hash reference. We don't know + this buddy anymore. */ + g_hash_table_remove( jd->buddies, bud->handle ); + + /* Deallocate the linked list of resources. */ + while( bud ) + { + next = bud->next; + g_free( bud->full_jid ); + g_free( bud->away_message ); + g_free( bud ); + bud = next; + } + + return 1; + } + else + { + return 0; + } +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index fea728e3..3ff1da1c 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -29,6 +29,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); struct xt_node *body = xt_find_node( node->children, "body" ); + char *s; if( !type ) return XT_HANDLED; /* Grmbl... FIXME */ @@ -37,7 +38,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) { struct jabber_buddy *bud = NULL; - if( strchr( from, '/' ) == NULL ) + if( ( s = strchr( from, '/' ) ) == NULL ) { /* It just shouldn't happen. */ hide_login_progress( gc, "Received message packet from bare JID" ); @@ -45,21 +46,34 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) return XT_ABORT; } - bud = jabber_buddy_by_jid( gc, from ); - bud->last_act = time( NULL ); + if( ( bud = jabber_buddy_by_jid( gc, from ) ) ) + bud->last_act = time( NULL ); + else + *s = 0; /* We need to generate a bare JID now. */ if( body ) /* Could be just a typing notification. */ - serv_got_im( gc, bud->handle, body->text, 0, 0, 0 ); + serv_got_im( gc, bud ? bud->handle : from, body->text, 0, 0, 0 ); + /* Handling of incoming typing notifications. */ if( xt_find_node( node->children, "composing" ) ) { - bud->flags |= JBFLAG_DOES_JEP85; - serv_got_typing( gc, bud->handle, 0, 1 ); + bud->flags |= JBFLAG_DOES_XEP85; + serv_got_typing( gc, bud ? bud->handle : from, 0, 1 ); } - else if( xt_find_node( node->children, "active" ) ) + /* No need to send a "stopped typing" signal when there's a message. */ + else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) { - bud->flags |= JBFLAG_DOES_JEP85; + bud->flags |= JBFLAG_DOES_XEP85; + serv_got_typing( gc, bud ? bud->handle : from, 0, 0 ); } + else if( xt_find_node( node->children, "paused" ) ) + { + bud->flags |= JBFLAG_DOES_XEP85; + serv_got_typing( gc, bud ? bud->handle : from, 0, 2 ); + } + + if( s ) + *s = '/'; /* And convert it back to a full JID. */ } else { @@ -69,4 +83,3 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) return XT_HANDLED; } - diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index b10ce634..ccd22f60 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -30,22 +30,40 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; struct jabber_buddy *bud; + char *s; if( !from ) return XT_HANDLED; if( type == NULL ) { - if( strchr( from, '/' ) == NULL ) + if( ( s = strchr( from, '/' ) ) == NULL ) { char *s = xt_to_string( node ); - serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); + serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s", s ); g_free( s ); return XT_HANDLED; } if( !( bud = jabber_buddy_by_jid( gc, from ) ) ) { + /* FOR NOW, s still contains the location of the /. + Keep this in mind when changing things here. :-) */ + + /* We check if the buddy is in the contact list, + because Jabber servers seem to like to send + presence information of buddies we removed + from our list sometimes, for example... */ + + *s = 0; + if( find_buddy( gc, from ) == NULL ) + { + *s = '/'; + serv_got_crap( gc, "WARNING: Ignoring presence information from unknown JID: %s", from ); + return XT_HANDLED; + } + *s = '/'; + bud = jabber_buddy_add( gc, from ); } @@ -85,6 +103,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) return XT_HANDLED; } + if( jabber_buddy_by_jid( gc, from ) == NULL ) + { + serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); + return XT_HANDLED; + } + jabber_buddy_remove( gc, from ); *s = 0; -- cgit v1.2.3 From aaaed5ea8950bbecee2f4b2d5ead108308c7a45f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Oct 2006 23:42:28 +0200 Subject: A *working* fix for a memory access violation in cmd_remove(). --- root_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/root_commands.c b/root_commands.c index e0cd15b9..116f1d06 100644 --- a/root_commands.c +++ b/root_commands.c @@ -571,8 +571,8 @@ static void cmd_remove( irc_t *irc, char **cmd ) s = g_strdup( u->handle ); u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); + nick_del( u->gc->acc, u->handle ); user_del( irc, cmd[1] ); - nick_del( u->gc->acc, s ); irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); g_free( s ); -- cgit v1.2.3 From a5ac9f94c2dad85cb0f504172635982368db4d65 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 16 Oct 2006 00:25:59 +0200 Subject: Filled in the user changelog a bit more. --- doc/CHANGES | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/CHANGES b/doc/CHANGES index cd100741..05ae81f6 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,23 @@ Version x.x: +- Added ForkDaemon mode next to the existing Daemon- and inetd modes. With + ForkDaemon you can run BitlBee as a stand-alone daemon and every connection + will run in its own process. No more need to configure inetd, and still you + don't get the stability problems BitlBee unfortunately still has in ordinary + (one-process) daemon mode. +- Added inter-process/connection communication. This made it possible to + implement some IRC operator features like WALLOPs, KILL, DIE, REHASH and + more. +- Added hooks for using libevent instead of GLib for event handling. This + should improve scalability, although this won't really be useful yet because + the one-process daemon mode is not reliable enough. +- BitlBee now makes the buddy quits when doing "account off" look like a + netsplit. Modern IRC clients show this in a different, more compact way. +- GLib 1.x compatibility was dropped. BitlBee now requires GLib 2.6 (FIXME) + or newer. This allows us to use more GLib features. By now GLib 1.x is so + old that supporting it isn't really necessary anymore. +- Many, many, MANY little changes, improvements, fixes. Using non-blocking + I/O as much as possible, fixed lots of little bugs (including bugs that + affected daemon mode stability). See the bzr logs for more information. - Most important change: New file format for user data (accounts, nicks and settings). Migration to the new format should happen transparently, BitlBee will read the old files and once you quit/save it will save in the -- cgit v1.2.3 From e7276082fede405633f63d38fe18e010e897a972 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 16 Oct 2006 10:21:03 +0200 Subject: hash_hex buffer for IQ digest authentication missed one byte... --- protocols/jabber/iq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 8a7b3192..ccf9d30c 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -190,7 +190,7 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * /* We can do digest authentication, it seems, and of course we prefer that. */ SHA_CTX sha; - char hash_hex[40]; + char hash_hex[41]; unsigned char hash[20]; int i; -- cgit v1.2.3 From 1991be623c6c53d2f61f0b15405d41d144c21c8f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 18 Oct 2006 19:47:08 +0200 Subject: get_info() now displays vCard information too. --- protocols/jabber/iq.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++ protocols/jabber/jabber.c | 2 + protocols/jabber/jabber.h | 1 + 3 files changed, 145 insertions(+) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index ccf9d30c..8864e3fd 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -320,6 +320,148 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node return XT_HANDLED; } +static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); + +int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ) +{ + struct xt_node *node; + + if( strchr( bare_jid, '/' ) ) + return 1; /* This was an error, but return 0 should only be done if the connection died... */ + + node = xt_new_node( "vCard", NULL, NULL ); + xt_add_attr( node, "xmlns", "vcard-temp" ); + node = jabber_make_packet( "iq", "get", bare_jid, node ); + + jabber_cache_add( gc, node, jabber_iq_display_vcard ); + return jabber_write_packet( gc, node ); +} + +static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +{ + struct xt_node *vc, *c, *sc; /* subchild, gc is already in use ;-) */ + GString *reply; + char *s; + + if( ( s = xt_find_attr( node, "type" ) ) == NULL || + strcmp( s, "result" ) != 0 || + ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) + { + s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ + serv_got_crap( gc, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); + return XT_HANDLED; + } + + s = xt_find_attr( orig, "to" ); + reply = g_string_new( "vCard information for " ); + reply = g_string_append( reply, s ? s : "(NULL)" ); + reply = g_string_append( reply, ":\n" ); + + /* I hate this format, I really do... */ + + if( ( c = xt_find_node( vc->children, "FN" ) ) && c->text_len ) + g_string_append_printf( reply, "Name: %s\n", c->text ); + + if( ( c = xt_find_node( vc->children, "N" ) ) && c->children ) + { + reply = g_string_append( reply, "Full name:" ); + + if( ( sc = xt_find_node( c->children, "PREFIX" ) ) && sc->text_len ) + g_string_append_printf( reply, " %s", sc->text ); + if( ( sc = xt_find_node( c->children, "GIVEN" ) ) && sc->text_len ) + g_string_append_printf( reply, " %s", sc->text ); + if( ( sc = xt_find_node( c->children, "MIDDLE" ) ) && sc->text_len ) + g_string_append_printf( reply, " %s", sc->text ); + if( ( sc = xt_find_node( c->children, "FAMILY" ) ) && sc->text_len ) + g_string_append_printf( reply, " %s", sc->text ); + if( ( sc = xt_find_node( c->children, "SUFFIX" ) ) && sc->text_len ) + g_string_append_printf( reply, " %s", sc->text ); + + reply = g_string_append_c( reply, '\n' ); + } + + if( ( c = xt_find_node( vc->children, "NICKNAME" ) ) && c->text_len ) + g_string_append_printf( reply, "Nickname: %s\n", c->text ); + + if( ( c = xt_find_node( vc->children, "BDAY" ) ) && c->text_len ) + g_string_append_printf( reply, "Date of birth: %s\n", c->text ); + + /* Slightly alternative use of for... ;-) */ + for( c = vc->children; ( c = xt_find_node( c, "EMAIL" ) ); c = c->next ) + { + if( ( sc = xt_find_node( c->children, "USERID" ) ) == NULL || sc->text_len == 0 ) + continue; + + if( xt_find_node( c->children, "HOME" ) ) + s = "Home"; + else if( xt_find_node( c->children, "WORK" ) ) + s = "Work"; + else + s = "Misc."; + + g_string_append_printf( reply, "%s e-mail address: %s\n", s, sc->text ); + } + + if( ( c = xt_find_node( vc->children, "URL" ) ) && c->text_len ) + g_string_append_printf( reply, "Homepage: %s\n", c->text ); + + /* Slightly alternative use of for... ;-) */ + for( c = vc->children; ( c = xt_find_node( c, "ADR" ) ); c = c->next ) + { + if( xt_find_node( c->children, "HOME" ) ) + s = "Home"; + else if( xt_find_node( c->children, "WORK" ) ) + s = "Work"; + else + s = "Misc."; + + g_string_append_printf( reply, "%s address: ", s ); + + if( ( sc = xt_find_node( c->children, "STREET" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s ", sc->text ); + if( ( sc = xt_find_node( c->children, "EXTADR" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s, ", sc->text ); + if( ( sc = xt_find_node( c->children, "PCODE" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s, ", sc->text ); + if( ( sc = xt_find_node( c->children, "LOCALITY" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s, ", sc->text ); + if( ( sc = xt_find_node( c->children, "REGION" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s, ", sc->text ); + if( ( sc = xt_find_node( c->children, "CTRY" ) ) && sc->text_len ) + g_string_append_printf( reply, "%s", sc->text ); + + if( reply->str[reply->len-2] == ',' ) + reply = g_string_truncate( reply, reply->len-2 ); + + reply = g_string_append_c( reply, '\n' ); + } + + for( c = vc->children; ( c = xt_find_node( c, "TEL" ) ); c = c->next ) + { + if( ( sc = xt_find_node( c->children, "NUMBER" ) ) == NULL || sc->text_len == 0 ) + continue; + + if( xt_find_node( c->children, "HOME" ) ) + s = "Home"; + else if( xt_find_node( c->children, "WORK" ) ) + s = "Work"; + else + s = "Misc."; + + g_string_append_printf( reply, "%s phone number: %s\n", s, sc->text ); + } + + if( ( c = xt_find_node( vc->children, "DESC" ) ) && c->text_len ) + g_string_append_printf( reply, "Other information:\n%s", c->text ); + + /* *sigh* */ + + serv_got_crap( gc, reply->str ); + g_string_free( reply, TRUE ); + + return XT_HANDLED; +} + int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) { struct xt_node *node; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index abc3837b..f460aff2 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -201,6 +201,8 @@ static void jabber_get_info( struct gaim_connection *gc, char *who ) bud->away_message ? : "(none)" ); bud = bud->next; } + + jabber_get_vcard( gc, bud ? bud->handle : who ); } static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index d1d452b4..cd65d374 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -111,6 +111,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_init_iq_auth( struct gaim_connection *gc ); xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); int jabber_get_roster( struct gaim_connection *gc ); +int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ); int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); -- cgit v1.2.3 From f920d9eb003541245e0fc32a381447cbba8fbea5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 19 Oct 2006 09:51:35 +0200 Subject: Added starttls code to ssl_openssl.c so GnuTLS isn't the only supported SSL module in this branch anymore. --- lib/ssl_gnutls.c | 2 - lib/ssl_openssl.c | 117 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 7481127a..fbd1d0c0 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -107,9 +107,7 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con if( source == -1 ) { conn->func( conn->data, NULL, cond ); - g_free( conn ); - return FALSE; } diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c index b6f6c520..b1ba1db9 100644 --- a/lib/ssl_openssl.c +++ b/lib/ssl_openssl.c @@ -52,23 +52,66 @@ struct scd }; static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data ) { struct scd *conn = g_new0( struct scd, 1 ); - SSL_METHOD *meth; conn->fd = proxy_connect( host, port, ssl_connected, conn ); conn->func = func; conn->data = data; + conn->inpa = -1; if( conn->fd < 0 ) { g_free( conn ); - return( NULL ); + return NULL; } + return conn; +} + +void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) +{ + struct scd *conn = g_new0( struct scd, 1 ); + + conn->fd = fd; + conn->func = func; + conn->data = data; + conn->inpa = -1; + + /* This function should be called via a (short) timeout instead of + directly from here, because these SSL calls are *supposed* to be + *completely* asynchronous and not ready yet when this function + (or *_connect, for examle) returns. Also, errors are reported via + the callback function, not via this function's return value. + + In short, doing things like this makes the rest of the code a lot + simpler. */ + + b_timeout_add( 1, ssl_starttls_real, conn ); + + return conn; +} + +static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + + return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE ); +} + +static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +{ + struct scd *conn = data; + SSL_METHOD *meth; + + if( source == -1 ) + goto ssl_connected_failure; + if( !initialized ) { initialized = TRUE; @@ -78,35 +121,35 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data meth = TLSv1_client_method(); conn->ssl_ctx = SSL_CTX_new( meth ); if( conn->ssl_ctx == NULL ) - { - conn->fd = -1; - return( NULL ); - } + goto ssl_connected_failure; conn->ssl = SSL_new( conn->ssl_ctx ); if( conn->ssl == NULL ) - { - conn->fd = -1; - return( NULL ); - } - - return( conn ); -} - -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); - -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) -{ - struct scd *conn = data; - - if( source == -1 ) - return ssl_handshake( data, -1, cond ); + goto ssl_connected_failure; /* We can do at least the handshake with non-blocking I/O */ sock_make_nonblocking( conn->fd ); SSL_set_fd( conn->ssl, conn->fd ); return ssl_handshake( data, source, cond ); + +ssl_connected_failure: + conn->func( conn->data, NULL, cond ); + + if( conn->ssl ) + { + SSL_shutdown( conn->ssl ); + SSL_free( conn->ssl ); + } + if( conn->ssl_ctx ) + { + SSL_CTX_free( conn->ssl_ctx ); + } + if( source >= 0 ) closesocket( source ); + g_free( conn ); + + return FALSE; + } static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) @@ -118,7 +161,18 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con { conn->lasterr = SSL_get_error( conn->ssl, st ); if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) - goto ssl_connected_failure; + { + conn->func( conn->data, NULL, cond ); + + SSL_shutdown( conn->ssl ); + SSL_free( conn->ssl ); + SSL_CTX_free( conn->ssl_ctx ); + + if( source >= 0 ) closesocket( source ); + g_free( conn ); + + return FALSE; + } conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); return FALSE; @@ -128,23 +182,6 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con sock_make_blocking( conn->fd ); /* For now... */ conn->func( conn->data, conn, cond ); return FALSE; - -ssl_connected_failure: - conn->func( conn->data, NULL, cond ); - - if( conn->ssl ) - { - SSL_shutdown( conn->ssl ); - SSL_free( conn->ssl ); - } - if( conn->ssl_ctx ) - { - SSL_CTX_free( conn->ssl_ctx ); - } - if( source >= 0 ) closesocket( source ); - g_free( conn ); - - return FALSE; } int ssl_read( void *conn, char *buf, int len ) -- cgit v1.2.3 From dfa41a405f0c80549f6dd5c0c111e3b62ce83b07 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Oct 2006 21:12:14 +0200 Subject: Now all IQ packets get an ID and cached packets get a "special" ID. This makes it easier to find out if an event handler has to be called for a reply packet. --- protocols/jabber/iq.c | 34 ++++++++++++++++++++++++++-------- protocols/jabber/jabber.h | 9 ++++++++- protocols/jabber/jabber_util.c | 19 +++++++++++++++---- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 8864e3fd..446a25bb 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -44,11 +44,12 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct jabber_cache_entry *entry; - if( ( s = xt_find_attr( node, "id" ) ) == NULL ) + if( ( s = xt_find_attr( node, "id" ) ) == NULL || + strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 ) { - /* Silently ignore it, without an ID we don't know - how to handle the packet, but it doesn't have - to be a serious problem. */ + /* Silently ignore it, without an ID (or an non-cache + ID) we don't know how to handle the packet and we + probably don't have to. */ return XT_HANDLED; } @@ -64,7 +65,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - serv_got_crap( gc, "WARNING: Received incomplete IQ-get packet" ); + serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -124,9 +125,26 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( type, "set" ) == 0 ) { - xt_free_node( reply ); - reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); - pack = 0; + if( !( c = xt_find_node( node->children, "query" ) ) || + !( s = xt_find_attr( c, "xmlns" ) ) ) + { + serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type ); + return XT_HANDLED; + } + + if( strcmp( s, "jabber:iq:roster" ) == 0 ) + { + /* This is a roster push packet, probably. Here we + should check if the packet is legitimate by + checking if it really comes from the user's JID + and, if so, process it. */ + } + else + { + xt_free_node( reply ); + reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" ); + pack = 0; + } } /* If we recognized the xmlns and managed to generate a reply, diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index cd65d374..4bccd5ed 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -101,11 +101,18 @@ struct jabber_buddy char *away_message; time_t last_act; - int flags; + jabber_buddy_flag_t flags; struct jabber_buddy *next; }; +/* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the + first one should be used, but when storing a packet in the cache, a + "special" kind of ID is assigned to make it easier later to figure out + if we have to do call an event handler for the response packet. */ +#define JABBER_PACKET_ID "BeeP" +#define JABBER_CACHED_ID "BeeC" + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_init_iq_auth( struct gaim_connection *gc ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index d5d038cf..3f189300 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -23,7 +23,7 @@ #include "jabber.h" -static int next_id = 1; +static unsigned int next_id = 1; char *set_eval_priority( set_t *set, char *value ) { @@ -82,6 +82,17 @@ struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_ if( to ) xt_add_attr( node, "to", to ); + /* IQ packets should always have an ID, so let's generate one. It + might get overwritten by jabber_cache_add() if this packet has + to be saved until we receive a response. Cached packets get + slightly different IDs so we can recognize them. */ + if( strcmp( name, "iq" ) == 0 ) + { + char *id = g_strdup_printf( "%s%05x", JABBER_PACKET_ID, ( next_id++ ) & 0xfffff ); + xt_add_attr( node, "id", id ); + g_free( id ); + } + return node; } @@ -115,13 +126,13 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, return node; } -/* Cache a node/epacket for later use. Mainly useful for IQ packets if you need +/* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so - it'll get an id= tag, and do NOT free() the packet after writing it! */ + it'll get a new id= tag, and do NOT free() the packet after writing it! */ void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = gc->proto_data; - char *id = g_strdup_printf( "BeeX%04x", next_id++ ); + char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); xt_add_attr( node, "id", id ); -- cgit v1.2.3 From 3b3cd693845539938baf5e26c80234f03ebf870c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Oct 2006 21:58:09 +0200 Subject: Added backwards compatibility with the old "account add" syntax for Jabber accounts. Very ugly code, so it won't stay long. ;-) Plus checking of the ssl_connect() return value, because of course it can return NULL too... Have to add general *_connect() error checking to jabber_login() soon! --- protocols/jabber/jabber.c | 72 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index f460aff2..3a2cb246 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -61,7 +61,7 @@ static void jabber_login( account_t *acc ) struct gaim_connection *gc = new_gaim_conn( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); struct ns_srv_reply *srv = NULL; - char *connect_to; + char *connect_to, *s; jd->gc = gc; gc->proto_data = jd; @@ -80,11 +80,77 @@ static void jabber_login( account_t *acc ) *jd->server = 0; jd->server ++; + if( ( s = strchr( jd->server, '/' ) ) ) + { + *s = 0; + set_setstr( &acc->set, "resource", s + 1 ); + + /* Also remove the /resource from the original variable so we + won't have to do this again every time. */ + s = strchr( acc->user, '/' ); + *s = 0; + } + + /* This code isn't really pretty. Backwards compatibility never is... */ + s = acc->server; + while( s ) + { + static int had_port = 0; + + if( strncmp( s, "ssl", 3 ) == 0 ) + { + set_setstr( &acc->set, "ssl", "true" ); + + /* Flush this part so that (if this was the first + part of the server string) acc->server gets + flushed. We don't want to have to do this another + time. :-) */ + *s = 0; + s ++; + + /* Only set this if the user didn't specify a custom + port number already... */ + if( !had_port ) + set_setint( &acc->set, "port", 5223 ); + } + else if( isdigit( *s ) ) + { + int i; + + /* The first character is a digit. It could be an + IP address though. Only accept this as a port# + if there are only digits. */ + for( i = 0; isdigit( s[i] ); i ++ ); + + /* If the first non-digit character is a colon or + the end of the string, save the port number + where it should be. */ + if( s[i] == ':' || s[i] == 0 ) + { + sscanf( s, "%d", &i ); + set_setint( &acc->set, "port", i ); + + /* See above. */ + *s = 0; + s ++; + } + + had_port = 1; + } + + s = strchr( s, ':' ); + if( s ) + { + *s = 0; + s ++; + } + } + jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free ); jd->buddies = g_hash_table_new( g_str_hash, g_str_equal ); /* Figure out the hostname to connect to. */ - if( acc->server ) + if( acc->server && *acc->server ) connect_to = acc->server; else if( ( srv = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || ( srv = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) @@ -98,7 +164,7 @@ static void jabber_login( account_t *acc ) if( set_getbool( &acc->set, "ssl" ) ) { jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); - jd->fd = ssl_getfd( jd->ssl ); + jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1; } else { -- cgit v1.2.3 From 2a29eac1dd6c9d5d2ed5083efc1c185cfd750fd7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Oct 2006 21:49:57 +0200 Subject: "Restructured" msn_login() a little bit. --- protocols/msn/msn.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index f7e57707..f8686835 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -41,8 +41,6 @@ static void msn_login( account_t *acc ) struct gaim_connection *gc = new_gaim_conn( acc ); struct msn_data *md = g_new0( struct msn_data, 1 ); - set_login_progress( gc, 1, "Connecting" ); - gc->proto_data = md; md->fd = -1; @@ -53,19 +51,20 @@ static void msn_login( account_t *acc ) return; } + set_login_progress( gc, 1, "Connecting" ); + md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, gc ); if( md->fd < 0 ) { hide_login_progress( gc, "Could not connect to server" ); signoff( gc ); + return; } - else - { - md->gc = gc; - md->away_state = msn_away_state_list; - - msn_connections = g_slist_append( msn_connections, gc ); - } + + md->gc = gc; + md->away_state = msn_away_state_list; + + msn_connections = g_slist_append( msn_connections, gc ); } static void msn_close( struct gaim_connection *gc ) -- cgit v1.2.3 From 35f6677c07770f0323872e4edddefb7b752e50bd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Oct 2006 22:48:44 +0200 Subject: Proper detections of errors from *_connect() and added a "Connecting" message in jabber_login(). --- protocols/jabber/io.c | 4 ---- protocols/jabber/jabber.c | 9 ++++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 665f5322..bc08a977 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -101,8 +101,6 @@ static gboolean jabber_write_queue( struct gaim_connection *gc ) else st = write( jd->fd, jd->txq, jd->tx_len ); -// if( st > 0 ) write( 1, jd->txq, st ); - if( st == jd->tx_len ) { /* We wrote everything, clear the buffer. */ @@ -156,8 +154,6 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition else st = read( jd->fd, buf, sizeof( buf ) ); -// if( st > 0 ) write( 1, buf, st ); - if( st > 0 ) { /* Parse. */ diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 3a2cb246..fd8b6128 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -158,6 +158,8 @@ static void jabber_login( account_t *acc ) else connect_to = jd->server; + set_login_progress( gc, "Connecting" ); + /* For non-SSL connections we can try to use the port # from the SRV reply, but let's not do that when using SSL, SSL usually runs on non-standard ports... */ @@ -170,8 +172,13 @@ static void jabber_login( account_t *acc ) { jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); } - g_free( srv ); + + if( jd->fd == -1 ) + { + hide_login_progress( gc, "Could not connect to server" ); + signoff( gc ); + } } static void jabber_close( struct gaim_connection *gc ) -- cgit v1.2.3 From 91bd910ec5ecf95953518246e3fd0adf1f43c1f7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Oct 2006 22:56:21 +0200 Subject: Fixed #139. (Wrong Gender description) --- protocols/oscar/oscar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index b8cf521b..72078b3c 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2296,7 +2296,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) } } info_string_append(str, "\n", _("Mobile Phone"), info->mobile); - info_string_append(str, "\n", _("Gender"), info->gender==1 ? _("Female") : _("Male")); + info_string_append(str, "\n", _("Gender"), info->gender==1 ? _("Female") : info->gender==2 ? _("Male") : _("Unknown")); if (info->birthyear || info->birthmonth || info->birthday) { char date[30]; struct tm tm; -- cgit v1.2.3 From 4b0d8055fe3fc08cdaa7696f1c4af1e0e471a67e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Oct 2006 23:12:30 +0200 Subject: Can't hurt to at least try one compile before running bzr commit... --- protocols/jabber/jabber.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index fd8b6128..e4bdc463 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -158,7 +158,7 @@ static void jabber_login( account_t *acc ) else connect_to = jd->server; - set_login_progress( gc, "Connecting" ); + set_login_progress( gc, 0, "Connecting" ); /* For non-SSL connections we can try to use the port # from the SRV reply, but let's not do that when using SSL, SSL usually runs on -- cgit v1.2.3 From 66f783fa6365fefe7ba449e6409b4dc1359b155b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Oct 2006 23:40:06 +0200 Subject: Complete fix (or mostly a work-around) for nested calls to signoff(). (Can happen when the IRC connection to the user is broken, a write() to it eventually fails, which triggers an irc_kill() which, in turn, will call signoff() for all accounts.) --- protocols/nogaim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 36461b32..3e9d7c07 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -283,12 +283,12 @@ void signoff( struct gaim_connection *gc ) place to catch them. */ if( gc->flags & OPT_LOGGING_OUT ) return; + else + gc->flags |= OPT_LOGGING_OUT; serv_got_crap( gc, "Signing off.." ); b_event_remove( gc->keepalive ); - gc->flags |= OPT_LOGGING_OUT; - gc->keepalive = 0; gc->acc->prpl->close( gc ); b_event_remove( gc->inpa ); -- cgit v1.2.3 From 208715962fcd1b806d42ef7edb47503eb296895b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Oct 2006 11:24:55 +0200 Subject: Away devoices are done by the server instead of by root now. This makes more sense with the "netsplit feature". (Because of less noisy joins.) --- protocols/nogaim.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 47e2bda6..0270d5a0 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -572,7 +572,7 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ { - irc_write( gc->irc, ":%s!%s@%s MODE %s %cv %s", gc->irc->mynick, gc->irc->mynick, gc->irc->myhost, + irc_write( gc->irc, ":%s MODE %s %cv %s", gc->irc->myhost, gc->irc->channel, u->away?'-':'+', u->nick ); } } @@ -906,8 +906,8 @@ char *set_eval_away_devoice( set_t *set, char *value ) if( ( strlen( list ) + strlen( u->nick ) ) >= 79 ) { for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0; - irc_write( irc, ":%s!%s@%s MODE %s %c%s%s", - irc->mynick, irc->mynick, irc->myhost, + irc_write( irc, ":%s MODE %s %c%s%s", + irc->myhost, irc->channel, pm, v, list ); *list = 0; @@ -922,7 +922,7 @@ char *set_eval_away_devoice( set_t *set, char *value ) /* $v = 'v' x $i */ for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0; - irc_write( irc, ":%s!%s@%s MODE %s %c%s%s", irc->mynick, irc->mynick, irc->myhost, + irc_write( irc, ":%s MODE %s %c%s%s", irc->myhost, irc->channel, pm, v, list ); } -- cgit v1.2.3 From 670204fe6b883397208758d1e8e0c3ada699379c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Oct 2006 14:43:40 +0200 Subject: Copied 1.0.x changelogs, disabled LDAP support in configure (because the code just doesn't work yet) and added GLib version detection. (GLib 2.4 and up *should* work.) --- configure | 17 +++++++++++++---- doc/CHANGES | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 7cc99b41..23bdd383 100755 --- a/configure +++ b/configure @@ -30,12 +30,14 @@ strip=1 ipv6=1 events=glib -ldap=auto +ldap=0 ssl=auto arch=`uname -s` cpu=`uname -m` +GLIB_MIN_VERSION=2.4 + echo BitlBee configure while [ -n "$1" ]; do @@ -174,13 +176,20 @@ if [ -z "$PKG_CONFIG" ]; then fi if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG glib-2.0; then - cat<<EOF>>Makefile.settings + if $PKG_CONFIG glib-2.0 --atleast-version=$GLIB_MIN_VERSION; then + cat<<EOF>>Makefile.settings EFLAGS+=`$PKG_CONFIG --libs glib-2.0 gmodule-2.0` CFLAGS+=`$PKG_CONFIG --cflags glib-2.0 gmodule-2.0` EOF + else + echo + echo 'Found glib2 '`$PKG_CONFIG glib-2.0 --modversion`', but version '$GLIB_MIN_VERSION' or newer is required.' + exit 1 + fi else + echo echo 'Cannot find glib2 development libraries, aborting. (Install libglib2-dev?)' - exit 1; + exit 1 fi if [ "$events" = "libevent" ]; then @@ -289,7 +298,7 @@ elif [ "$ssl" = "openssl" ]; then ret=1 elif [ "$ssl" = "bogus" ]; then echo - echo 'Using bogus SSL code. This means some features have to be disabled.' + echo 'Using bogus SSL code. This means some features will not work properly.' ## Yes, you, at the console! How can you authenticate if you don't have any SSL!? if [ "$msn" = "1" ]; then diff --git a/doc/CHANGES b/doc/CHANGES index 05ae81f6..e9435216 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -12,9 +12,9 @@ Version x.x: the one-process daemon mode is not reliable enough. - BitlBee now makes the buddy quits when doing "account off" look like a netsplit. Modern IRC clients show this in a different, more compact way. -- GLib 1.x compatibility was dropped. BitlBee now requires GLib 2.6 (FIXME) - or newer. This allows us to use more GLib features. By now GLib 1.x is so - old that supporting it isn't really necessary anymore. +- GLib 1.x compatibility was dropped. BitlBee now requires GLib 2.4 or newer. + This allows us to use more GLib features (like the XML parser). By now GLib + 1.x is so old that supporting it really isn't necessary anymore. - Many, many, MANY little changes, improvements, fixes. Using non-blocking I/O as much as possible, fixed lots of little bugs (including bugs that affected daemon mode stability). See the bzr logs for more information. @@ -41,6 +41,61 @@ Version x.x: and password for the existing connection. * Per-account settings (see the new "account set" command). +Version 1.0.3: +- Fixed ugliness in block/allow list commands (still not perfect though, the + list is empty or not up-to-date for most protocols). +- OSCAR module doesn't send the ICQ web-aware flag anymore, which seems to + get rid of a lot of ICQ spam. +- added show_got_added(), BitlBee asks you, after authorizing someone, if you + want to add him/her to your list too. +- add -tmp, mainly convenient if you want to talk to people who are not in + your list. +- Fixed ISON command, should work better with irssi now. +- Fixed compilation with tcc. +- Fixed xinetd-file. +- Misc. (crash)bug fixes, including one in the root command parsing that + caused mysterious error messages sometimes. + +Finished 24 Jun 2006 (Happy 4th birthday, BitlBee!) + +Version 1.0.2: +- Pieces of code cleanup, fixes for possible problems in error checking. +- Fixed an auto-reconnect cleanup problem that caused crashes in daemon mode. +- /AWAY in daemon mode now doesn't set the away state for every connection + anymore. +- Fixed a crash-bug on empty help subjects. +- Jabber now correctly sets the current away state when connecting. +- Added Invisible and Hidden to the away state alias list, invisible mode + should be pretty usable now. +- Fixed handling of iconv(): It's now done for everything that goes between + BitlBee and the IRC client, instead of doing it (almost) every time + something goes to or come from the IM-modules. Should've thought about + that before. :-) +- When cleaning up MSN switchboards with unsent msgs, it now also says which + contact those messages were meant for. +- You can now use the block and allow commands to see your current block/ + allow list. + +Finished 1 Apr 2006 + +Version 1.0.1: +- Support for AIM groupchats. +- Improved typing notification support for at least AIM. +- BitlBee sends a 005 reply when logging in, this informs modern IRC clients + of some of BitlBee's capabilities. This might also solve problems some + people were having with the new control channel name. +- MSN switchboards are now properly reset when talking to a person who is + offline. This fixes problems with messages to MSN people that sometimes + didn't arrive. +- Fixed one of the problems that made BitlBee show online Jabber people as + offline. +- Fixed problems with commas in MSN passwords. +- Added some consts for read-only data, which should make the BitlBee per- + process memory footprint a bit smaller. +- Other bits of code cleanup. + +Finished 14 Jan 2006 + Version 1.0: - Removed some crashy debugging code. - QUIT command now works before logging in. (Mainly an RFC-compliancy fix.) -- cgit v1.2.3 From 28eda862ffd1f59ac3cd214295c366ab939afd46 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Oct 2006 15:53:55 +0200 Subject: Fixed #181. (Using wrong (static) variable in error messages.) --- storage_text.c | 2 +- storage_xml.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage_text.c b/storage_text.c index acc9eefe..3a11facf 100644 --- a/storage_text.c +++ b/storage_text.c @@ -30,7 +30,7 @@ static void text_init (void) { if( access( global.conf->configdir, F_OK ) != 0 ) - log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG ); + log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir ); else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 ) log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); } diff --git a/storage_xml.c b/storage_xml.c index 52240a36..ba311120 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -262,7 +262,7 @@ GMarkupParser xml_parser = static void xml_init( void ) { if( access( global.conf->configdir, F_OK ) != 0 ) - log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG ); + log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir ); else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 ) log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); } -- cgit v1.2.3 From 6237ded20b3f3058f1ada9b6afeaa07fcba535eb Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Oct 2006 15:58:32 +0200 Subject: set_eval_int() was pretty broken... --- set.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/set.c b/set.c index d172a79f..8d872503 100644 --- a/set.c +++ b/set.c @@ -172,13 +172,13 @@ void set_del( set_t **head, char *key ) char *set_eval_int( set_t *set, char *value ) { - char *s; + char *s = value; /* Allow a minus at the first position. */ if( *s == '-' ) s ++; - for( s = value; *s; s ++ ) + for( ; *s; s ++ ) if( !isdigit( *s ) ) return NULL; -- cgit v1.2.3 From f0071b791cc1be18a3236bdc6e363c837210e5cd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 23 Oct 2006 22:01:19 +0200 Subject: Better handling of <message/> packets. (Headlines, JIDs without /resource part, non-chat messages.) --- protocols/jabber/message.c | 62 ++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 3ff1da1c..81de177a 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -28,31 +28,56 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) struct gaim_connection *gc = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); - struct xt_node *body = xt_find_node( node->children, "body" ); + struct xt_node *body = xt_find_node( node->children, "body" ), *c; char *s; - if( !type ) - return XT_HANDLED; /* Grmbl... FIXME */ - - if( strcmp( type, "chat" ) == 0 ) + if( type && strcmp( type, "error" ) == 0 ) + { + /* Handle type=error packet. */ + } + else if( type && strcmp( type, "groupchat" ) == 0 ) + { + /* TODO! */ + } + else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */ { struct jabber_buddy *bud = NULL; + GString *fullmsg = g_string_new( "" ); - if( ( s = strchr( from, '/' ) ) == NULL ) + if( ( s = strchr( from, '/' ) ) ) { - /* It just shouldn't happen. */ - hide_login_progress( gc, "Received message packet from bare JID" ); - signoff( gc ); - return XT_ABORT; + if( ( bud = jabber_buddy_by_jid( gc, from ) ) ) + bud->last_act = time( NULL ); + else + *s = 0; /* We need to generate a bare JID now. */ } - if( ( bud = jabber_buddy_by_jid( gc, from ) ) ) - bud->last_act = time( NULL ); - else - *s = 0; /* We need to generate a bare JID now. */ + if( strcmp( type, "headline" ) == 0 ) + { + c = xt_find_node( node->children, "subject" ); + g_string_append_printf( fullmsg, "Headline: %s\n", c && c->text_len > 0 ? c->text : "" ); + + /* <x xmlns="jabber:x:oob"><url>http://....</url></x> can contain a URL, it seems. */ + for( c = node->children; c; c = c->next ) + { + struct xt_node *url; + + if( ( url = xt_find_node( c->children, "url" ) ) && url->text_len > 0 ) + g_string_append_printf( fullmsg, "URL: %s\n", url->text ); + } + } + else if( ( c = xt_find_node( node->children, "subject" ) ) && c->text_len > 0 ) + { + g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Message with subject: %s >>\n", c->text ); + } + + if( body && body->text_len > 0 ) /* Could be just a typing notification. */ + fullmsg = g_string_append( fullmsg, body->text ); - if( body ) /* Could be just a typing notification. */ - serv_got_im( gc, bud ? bud->handle : from, body->text, 0, 0, 0 ); + if( fullmsg->len > 0 ) + serv_got_im( gc, bud ? bud->handle : from, fullmsg->str, 0, 0, fullmsg->len ); + + g_string_free( fullmsg, TRUE ); /* Handling of incoming typing notifications. */ if( xt_find_node( node->children, "composing" ) ) @@ -75,11 +100,6 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( s ) *s = '/'; /* And convert it back to a full JID. */ } - else - { - printf( "Received MSG from %s:\n", from ); - xt_print( node ); - } return XT_HANDLED; } -- cgit v1.2.3 From bd28e6a2eec0333a866ef2e380d32b1e6ad0c80b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 24 Oct 2006 12:40:28 +0200 Subject: MSN message packets are now sent at once instead of separately. Probably the MSN servers don't care, but it looks a bit prettier in wireshark. ;-) --- protocols/msn/sb.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 63744cd0..7ec340bd 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -121,9 +121,10 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) { if( sb->ready ) { - char cmd[1024], *buf; + char *packet, *buf; int i, j; + /* Build the message. Convert LF to CR-LF for normal messages. */ if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 ) { buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 ); @@ -141,19 +142,21 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) else { i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->gc->username ); - buf = g_new0( char, strlen( MSN_TYPING_HEADERS ) + strlen( sb->gc->username ) ); + buf = g_new0( char, i ); i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->gc->username ); } - g_snprintf( cmd, sizeof( cmd ), "MSG %d N %d\r\n", ++sb->trId, i ); - if( msn_sb_write( sb, cmd, strlen( cmd ) ) && msn_sb_write( sb, buf, i ) ) + /* Build the final packet (MSG command + the message). */ + packet = g_strdup_printf( "MSG %d N %d\r\n%s", ++sb->trId, i, buf ); + g_free( buf ); + if( msn_sb_write( sb, packet, strlen( packet ) ) ) { - g_free( buf ); + g_free( packet ); return( 1 ); } else { - g_free( buf ); + g_free( packet ); return( 0 ); } } -- cgit v1.2.3 From 62d0c141f1118d245fe192151e57b2beb739aa5c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 24 Oct 2006 21:04:52 +0200 Subject: Forgot about one possible NULL pointer dereference in jabber_pkt_message(). --- protocols/jabber/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 81de177a..ad19a1dc 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -52,7 +52,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) *s = 0; /* We need to generate a bare JID now. */ } - if( strcmp( type, "headline" ) == 0 ) + if( type && strcmp( type, "headline" ) == 0 ) { c = xt_find_node( node->children, "subject" ); g_string_append_printf( fullmsg, "Headline: %s\n", c && c->text_len > 0 ? c->text : "" ); -- cgit v1.2.3 From abbd8ede1eb5eeb9b82e09357e0b38949bc95b8d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 28 Oct 2006 22:54:40 +0200 Subject: Added handling of roster pushes. This means your local buddy list will stay synchronized with other clients logged into your account at the same time. --- protocols/jabber/iq.c | 64 +++++++++++++++++++++++++++++++++++++++-------- protocols/jabber/jabber.c | 5 +++- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 446a25bb..c5263572 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -23,6 +23,9 @@ #include "jabber.h" +static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); + xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; @@ -134,10 +137,25 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( strcmp( s, "jabber:iq:roster" ) == 0 ) { - /* This is a roster push packet, probably. Here we - should check if the packet is legitimate by - checking if it really comes from the user's JID - and, if so, process it. */ + int bare_len = strlen( gc->acc->user ); + + if( ( s = xt_find_attr( node, "from" ) ) == NULL || + ( strncmp( s, gc->acc->user, bare_len ) == 0 && + ( s[bare_len] == 0 || s[bare_len] == '/' ) ) ) + { + jabber_parse_roster( gc, node, NULL ); + + /* Should we generate a reply here? Don't think it's + very important... */ + } + else + { + serv_got_crap( gc, "WARNING: %s tried to fake a roster push!", s ); + + xt_free_node( reply ); + reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); + pack = 0; + } } else { @@ -295,8 +313,6 @@ xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node return XT_HANDLED; } -static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); - int jabber_get_roster( struct gaim_connection *gc ) { struct xt_node *node; @@ -317,6 +333,7 @@ int jabber_get_roster( struct gaim_connection *gc ) static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) { struct xt_node *query, *c; + int initial = ( orig != NULL ); query = xt_find_node( node->children, "query" ); @@ -327,19 +344,44 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node char *name = xt_find_attr( c, "name" ); char *sub = xt_find_attr( c, "subscription" ); - if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) - add_buddy( gc, NULL, jid, name ); + if( !jid || !sub ) + { + /* Maybe warn. But how likely is this to happen in the first place? */ + } + else if( initial ) + { + if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) + add_buddy( gc, NULL, jid, name ); + } + else + { + /* This is a roster push item. Find out what changed exactly. */ + if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) + { + if( find_buddy( gc, jid ) == NULL ) + add_buddy( gc, NULL, jid, name ); + else + serv_buddy_rename( gc, jid, name ); + } + else if( strcmp( sub, "remove" ) == 0 ) + { + /* Don't have any API call for this yet! So let's + just try to handle this as well as we can. */ + jabber_buddy_remove_bare( gc, jid ); + serv_got_update( gc, jid, 0, 0, 0, 0, 0, 0 ); + /* FIXME! */ + } + } c = c->next; } - account_online( gc ); + if( initial ) + account_online( gc ); return XT_HANDLED; } -static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); - int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ) { struct xt_node *node; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e4bdc463..855a6a3b 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -229,7 +229,10 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, /* If the user likes typing notification and if we don't know (and didn't probe before) if this resource supports XEP85, - include a probe in this packet now. */ + include a probe in this packet now. Also, if we know this + buddy does support XEP85, we have to send this <active/> + tag to tell that the user stopped typing (well, that's what + we guess when s/he pressed Enter...). */ act = xt_new_node( "active", NULL, NULL ); xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" ); xt_add_child( node, act ); -- cgit v1.2.3 From 47d3ac46306965e9db66096eef8c60c8e7985950 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 31 Oct 2006 09:25:41 +0100 Subject: Added #defines for XML namespaces. --- protocols/jabber/io.c | 10 +++++----- protocols/jabber/iq.c | 26 +++++++++++++------------- protocols/jabber/jabber.c | 4 ++-- protocols/jabber/jabber.h | 17 +++++++++++++++++ protocols/jabber/jabber_util.c | 2 +- protocols/jabber/sasl.c | 10 ++++------ 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index bc08a977..1039bb87 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -306,7 +306,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( ( trytls || set_getbool( &gc->acc->set, "tls" ) ) ) { reply = xt_new_node( "starttls", NULL, NULL ); - xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-tls" ); + xt_add_attr( reply, "xmlns", XMLNS_TLS ); if( !jabber_write_packet( gc, reply ) ) { xt_free_node( reply ); @@ -354,7 +354,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( ( c = xt_find_node( node->children, "bind" ) ) ) { reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); - xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); + xt_add_attr( reply, "xmlns", XMLNS_BIND ); reply = jabber_make_packet( "iq", "set", NULL, reply ); jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); @@ -367,7 +367,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( ( c = xt_find_node( node->children, "session" ) ) ) { reply = xt_new_node( "session", NULL, NULL ); - xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); + xt_add_attr( reply, "xmlns", XMLNS_SESSION ); reply = jabber_make_packet( "iq", "set", NULL, reply ); jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); @@ -399,7 +399,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) /* Just ignore it when it doesn't seem to be TLS-related (is that at all possible??). */ - if( !xmlns || strcmp( xmlns, "urn:ietf:params:xml:ns:xmpp-tls" ) != 0 ) + if( !xmlns || strcmp( xmlns, XMLNS_TLS ) != 0 ) return XT_HANDLED; /* We don't want event handlers to touch our TLS session while it's @@ -432,7 +432,7 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) for( c = node->children; c; c = c->next ) { if( !( s = xt_find_attr( c, "xmlns" ) ) || - strcmp( s, "urn:ietf:params:xml:ns:xmpp-streams" ) != 0 ) + strcmp( s, XMLNS_STREAM_ERROR ) != 0 ) continue; if( strcmp( c->name, "text" ) != 0 ) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index c5263572..c46a7c52 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -76,13 +76,13 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xt_add_attr( reply, "xmlns", s ); /* Of course this is a very essential query to support. ;-) */ - if( strcmp( s, "jabber:iq:version" ) == 0 ) + if( strcmp( s, XMLNS_VERSION ) == 0 ) { xt_add_child( reply, xt_new_node( "name", "BitlBee", NULL ) ); xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) ); xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) ); } - else if( strcmp( s, "jabber:iq:time" ) == 0 ) + else if( strcmp( s, XMLNS_TIME ) == 0 ) { time_t time_ep; char buf[1024]; @@ -96,7 +96,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); } - else if( strcmp( s, "http://jabber.org/protocol/disco#info" ) == 0 ) + else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { c = xt_new_node( "identity", NULL, NULL ); xt_add_attr( c, "category", "client" ); @@ -105,15 +105,15 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xt_add_child( reply, c ); c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", "jabber:iq:version" ); + xt_add_attr( c, "var", XMLNS_VERSION ); xt_add_child( reply, c ); c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", "jabber:iq:time" ); + xt_add_attr( c, "var", XMLNS_TIME ); xt_add_child( reply, c ); c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", "http://jabber.org/protocol/chatstates" ); + xt_add_attr( c, "var", XMLNS_CHATSTATES ); xt_add_child( reply, c ); /* Later this can be useful to announce things like @@ -135,7 +135,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return XT_HANDLED; } - if( strcmp( s, "jabber:iq:roster" ) == 0 ) + if( strcmp( s, XMLNS_ROSTER ) == 0 ) { int bare_len = strlen( gc->acc->user ); @@ -197,7 +197,7 @@ int jabber_init_iq_auth( struct gaim_connection *gc ) int st; node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) ); - xt_add_attr( node, "xmlns", "jabber:iq:auth" ); + xt_add_attr( node, "xmlns", XMLNS_AUTH ); node = jabber_make_packet( "iq", "get", NULL, node ); jabber_cache_add( gc, node, jabber_do_iq_auth ); @@ -217,7 +217,7 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * /* Time to authenticate ourselves! */ reply = xt_new_node( "query", NULL, NULL ); - xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); + xt_add_attr( reply, "xmlns", XMLNS_AUTH ); xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); @@ -321,7 +321,7 @@ int jabber_get_roster( struct gaim_connection *gc ) set_login_progress( gc, 1, "Authenticated, requesting buddy list" ); node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "get", NULL, node ); jabber_cache_add( gc, node, jabber_parse_roster ); @@ -390,7 +390,7 @@ int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ) return 1; /* This was an error, but return 0 should only be done if the connection died... */ node = xt_new_node( "vCard", NULL, NULL ); - xt_add_attr( node, "xmlns", "vcard-temp" ); + xt_add_attr( node, "xmlns", XMLNS_VCARD ); node = jabber_make_packet( "iq", "get", bare_jid, node ); jabber_cache_add( gc, node, jabber_iq_display_vcard ); @@ -535,7 +535,7 @@ int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) /* And pack it into a roster-add packet */ node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); st = jabber_write_packet( gc, node ); @@ -556,7 +556,7 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) /* And pack it into a roster-add packet */ node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", "jabber:iq:roster" ); + xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); st = jabber_write_packet( gc, node ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 855a6a3b..2ef76444 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -234,7 +234,7 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, tag to tell that the user stopped typing (well, that's what we guess when s/he pressed Enter...). */ act = xt_new_node( "active", NULL, NULL ); - xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" ); + xt_add_attr( act, "xmlns", XMLNS_CHATSTATES ); xt_add_child( node, act ); /* Just make sure we do this only once. */ @@ -352,7 +352,7 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing type = "composing"; node = xt_new_node( type, NULL, NULL ); - xt_add_attr( node, "xmlns", "http://jabber.org/protocol/chatstates" ); + xt_add_attr( node, "xmlns", XMLNS_CHATSTATES ); node = jabber_make_packet( "message", "chat", bud->full_jid, node ); st = jabber_write_packet( gc, node ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 4bccd5ed..da9bfd52 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -113,6 +113,23 @@ struct jabber_buddy #define JABBER_PACKET_ID "BeeP" #define JABBER_CACHED_ID "BeeC" +/* RFC 392[01] stuff */ +#define XMLNS_TLS "urn:ietf:params:xml:ns:xmpp-tls" +#define XMLNS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" +#define XMLNS_BIND "urn:ietf:params:xml:ns:xmpp-bind" +#define XMLNS_SESSION "urn:ietf:params:xml:ns:xmpp-session" +#define XMLNS_STANZA_ERROR "urn:ietf:params:xml:ns:xmpp-stanzas" +#define XMLNS_STREAM_ERROR "urn:ietf:params:xml:ns:xmpp-streams" +#define XMLNS_ROSTER "jabber:iq:roster" + +/* Some supported extensions/legacy stuff */ +#define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ +#define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ +#define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ +#define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ +#define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ +#define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ + /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); int jabber_init_iq_auth( struct gaim_connection *gc ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3f189300..07d7a2fd 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -103,7 +103,7 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Create the "defined-condition" tag. */ c = xt_new_node( err_cond, NULL, NULL ); - xt_add_attr( c, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" ); + xt_add_attr( c, "xmlns", XMLNS_STANZA_ERROR ); /* Put it in an <error> tag. */ c = xt_new_node( "error", NULL, c ); diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index a9676338..68953ced 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -24,8 +24,6 @@ #include "jabber.h" #include "base64.h" -#define SASL_NS "urn:ietf:params:xml:ns:xmpp-sasl" - xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) { struct gaim_connection *gc = data; @@ -44,7 +42,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) } s = xt_find_attr( node, "xmlns" ); - if( !s || strcmp( s, SASL_NS ) != 0 ) + if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { signoff( gc ); return XT_ABORT; @@ -69,7 +67,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) } reply = xt_new_node( "auth", NULL, NULL ); - xt_add_attr( reply, "xmlns", SASL_NS ); + xt_add_attr( reply, "xmlns", XMLNS_SASL ); if( sup_digest ) { @@ -271,7 +269,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) } reply = xt_new_node( "response", s, NULL ); - xt_add_attr( reply, "xmlns", SASL_NS ); + xt_add_attr( reply, "xmlns", XMLNS_SASL ); if( !jabber_write_packet( gc, reply ) ) goto silent_error; @@ -302,7 +300,7 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) char *s; s = xt_find_attr( node, "xmlns" ); - if( !s || strcmp( s, SASL_NS ) != 0 ) + if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { signoff( gc ); return XT_ABORT; -- cgit v1.2.3 From bbb6ffb4d2f4e02d3f856f731a83cb6b911bf659 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 31 Oct 2006 09:35:36 +0100 Subject: Disabling little optimization in irc.c because it can't be done safely in this part of the code for now. --- irc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/irc.c b/irc.c index 8f79b535..f9654034 100644 --- a/irc.c +++ b/irc.c @@ -584,8 +584,11 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) immediately. If it returns TRUE, it should be called again, so add the event to the queue. If it's FALSE, we emptied the buffer and saved ourselves some work in the event queue. */ - if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) - irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); + /* Really can't be done as long as the code doesn't do error checking very well: + if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) */ + + /* So just always do it via the event handler. */ + irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc ); } return; -- cgit v1.2.3 From 0d3f30f5449cf1730c006314f3dd60843e911ad1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 13 Nov 2006 00:06:08 +0100 Subject: Improved handling of JIDs: Bare JIDs are allowed (*sigh*) and case insensitivity. Probably not complete yet... --- protocols/jabber/jabber.c | 20 +++-- protocols/jabber/jabber.h | 16 +++- protocols/jabber/jabber_util.c | 168 ++++++++++++++++++++++++++++++----------- protocols/jabber/message.c | 10 +-- protocols/jabber/presence.c | 63 +++++----------- 5 files changed, 174 insertions(+), 103 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 2ef76444..a60cd4aa 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -216,12 +216,12 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, struct xt_node *node; int st; - bud = jabber_buddy_by_jid( gc, who ); + bud = jabber_buddy_by_jid( gc, who, 0 ); node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); - if( ( jd->flags & JFLAG_WANT_TYPING ) && bud && + if( bud && ( jd->flags & JFLAG_WANT_TYPING ) && ( ( bud->flags & JBFLAG_DOES_XEP85 ) || !( bud->flags & JBFLAG_PROBED_XEP85 ) ) ) { @@ -265,20 +265,24 @@ static void jabber_get_info( struct gaim_connection *gc, char *who ) struct jabber_buddy *bud; if( strchr( who, '/' ) ) - bud = jabber_buddy_by_jid( gc, who ); + bud = jabber_buddy_by_jid( gc, who, 0 ); else - bud = g_hash_table_lookup( jd->buddies, who ); + { + char *s = jabber_normalize( who ); + bud = g_hash_table_lookup( jd->buddies, s ); + g_free( s ); + } while( bud ) { - serv_got_crap( gc, "Buddy %s/%s (%d) information:\nAway state: %s\nAway message: %s", - bud->handle, bud->resource, bud->priority, + serv_got_crap( gc, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", + bud->full_jid, bud->priority, bud->away_state ? bud->away_state->full_name : "(none)", bud->away_message ? : "(none)" ); bud = bud->next; } - jabber_get_vcard( gc, bud ? bud->handle : who ); + jabber_get_vcard( gc, bud ? bud->full_jid : who ); } static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) @@ -328,7 +332,7 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing /* Enable typing notification related code from now. */ jd->flags |= JFLAG_WANT_TYPING; - if( ( bud = jabber_buddy_by_jid( gc, who ) ) == NULL ) + if( ( bud = jabber_buddy_by_jid( gc, who, 0 ) ) == NULL ) { /* Sending typing notifications to unknown buddies is unsupported for now. Shouldn't be a problem, I think. */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index da9bfd52..628cb03a 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -49,7 +49,7 @@ typedef enum sure it gets sent only once. */ JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support XEP85 (typing notification shite). */ -} jabber_buddy_flag_t; +} jabber_buddy_flags_t; struct jabber_data { @@ -92,7 +92,7 @@ struct jabber_cache_entry struct jabber_buddy { - char *handle; + char *bare_jid; char *full_jid; char *resource; @@ -101,7 +101,7 @@ struct jabber_buddy char *away_message; time_t last_act; - jabber_buddy_flag_t flags; + jabber_buddy_flags_t flags; struct jabber_buddy *next; }; @@ -159,8 +159,16 @@ void jabber_cache_clean( struct gaim_connection *gc ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); +char *jabber_normalize( char *orig ); + +typedef enum +{ + GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */ + GET_BUDDY_EXACT = 2, /* Get an exact message (only makes sense with bare JIDs). */ +} get_buddy_flags_t; + struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ); -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ); +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid, get_buddy_flags_t flags ); int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ); int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 07d7a2fd..7b1961e0 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -250,33 +250,63 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) g_free( buf ); } +/* Returns a new string. Don't leak it! */ +char *jabber_normalize( char *orig ) +{ + int len, i; + char *new; + + len = strlen( orig ); + new = g_new( char, len + 1 ); + for( i = 0; i < len; i ++ ) + new[i] = tolower( orig[i] ); + + new[i] = 0; + return new; +} + /* Adds a buddy/resource to our list. Returns NULL if full_jid is not really a - FULL jid or if we already have this buddy/resource. */ -struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ) + FULL jid or if we already have this buddy/resource. XXX: No, great, actually + buddies from transports don't (usually) have resources. So we'll really have + to deal with that properly. Set their ->resource property to NULL. Do *NOT* + allow to mix this stuff, though... */ +struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *new, *bi; - char *s; + char *s, *full_jid; - if( !( s = strchr( full_jid, '/' ) ) ) - return NULL; + full_jid = jabber_normalize( full_jid_ ); + + if( ( s = strchr( full_jid, '/' ) ) ) + *s = 0; new = g_new0( struct jabber_buddy, 1 ); - *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { - new->handle = bud->handle; + /* If this is a transport buddy or whatever, it can't have more + than one instance, so this is always wrong: */ + if( s == NULL || bud->resource == NULL ) + { + if( s ) *s = '/'; + g_free( new ); + g_free( full_jid ); + return NULL; + } + + new->bare_jid = bud->bare_jid; /* We already have another resource for this buddy, add the new one to the list. */ for( bi = bud; bi; bi = bi->next ) { - /* Check for dupes. Resource seem to be case sensitive. */ - if( strcmp( bi->resource, s + 1 ) == 0 ) + /* Check for dupes. */ + if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) { *s = '/'; g_free( new ); + g_free( full_jid ); return NULL; } /* Append the new item to the list. */ @@ -289,13 +319,22 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji } else { - new->handle = g_strdup( full_jid ); - g_hash_table_insert( jd->buddies, new->handle, new ); + new->bare_jid = g_strdup( full_jid ); + g_hash_table_insert( jd->buddies, new->bare_jid, new ); } - *s = '/'; - new->full_jid = g_strdup( full_jid ); - new->resource = strchr( new->full_jid, '/' ) + 1; + if( s ) + { + *s = '/'; + new->full_jid = full_jid; + new->resource = strchr( new->full_jid, '/' ) + 1; + } + else + { + /* Let's waste some more bytes of RAM instead of to make + memory management a total disaster here.. */ + new->full_jid = full_jid; + } return new; } @@ -303,26 +342,56 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji /* Finds a buddy from our structures. Can find both full- and bare JIDs. When asked for a bare JID, it uses the "resource_select" setting to see which resource to pick. */ -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid ) +struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud; - char *s; + char *s, *jid; + + jid = jabber_normalize( jid_ ); if( ( s = strchr( jid, '/' ) ) ) { *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) - for( ; bud; bud = bud->next ) - if( strcmp( bud->resource, s + 1 ) == 0 ) - break; + { + /* Is this one of those no-resource buddies? */ + if( bud->resource == NULL ) + { + bud = NULL; + } + else + { + /* See if there's an exact match. */ + for( ; bud; bud = bud->next ) + if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) + break; + } + } + + *s = '/'; + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) ) + bud = jabber_buddy_add( gc, jid ); + + g_free( jid ); + return bud; } else { struct jabber_buddy *best_prio, *best_time; char *set; - best_prio = best_time = bud = g_hash_table_lookup( jd->buddies, jid ); + bud = g_hash_table_lookup( jd->buddies, jid ); + + g_free( jid ); + + /* An exact match, or only one option. */ + if( bud == NULL ) + return ( flags & GET_BUDDY_CREAT ) ? jabber_buddy_add( gc, jid ) : NULL; + else if( ( bud->resource == NULL || bud->next == NULL ) ) + return bud; + + best_prio = best_time = bud; for( ; bud; bud = bud->next ) { if( bud->priority > best_prio->priority ) @@ -338,42 +407,54 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid else /* if( strcmp( set, "priority" ) == 0 ) */ return best_prio; } - - *s = '/'; - return bud; } /* Remove one specific full JID from our list. Use this when a buddy goes - off-line (because (s)he can still be online from a different location. */ -int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) + off-line (because (s)he can still be online from a different location. + XXX: See above, we should accept bare JIDs too... */ +int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *prev, *bi; - char *s; + char *s, *full_jid; - if( !( s = strchr( full_jid, '/' ) ) ) - return 0; + full_jid = jabber_normalize( full_jid_ ); + + if( ( s = strchr( full_jid, '/' ) ) ) + *s = 0; - *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) { /* If there's only one item in the list (and if the resource matches), removing it is simple. (And the hash reference should be removed too!) */ - if( bud->next == NULL && strcmp( bud->resource, s + 1 ) == 0 ) + if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) ) { - g_hash_table_remove( jd->buddies, bud->handle ); - g_free( bud->handle ); + g_hash_table_remove( jd->buddies, bud->bare_jid ); + g_free( bud->bare_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); + + g_free( full_jid ); + + return 1; + } + else if( s == NULL || bud->resource == NULL ) + { + /* Tried to remove a bare JID while this JID does seem + to have resources... (Or the opposite.) *sigh* */ + g_free( full_jid ); + return 0; } else { for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next ) - if( strcmp( bi->resource, s + 1 ) == 0 ) + if( g_strcasecmp( bi->resource, s + 1 ) == 0 ) break; + g_free( full_jid ); + if( bi ) { if( prev ) @@ -381,25 +462,23 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) else /* The hash table should point at the second item, because we're removing the first. */ - g_hash_table_replace( jd->buddies, bi->handle, bi->next ); + g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); + + return 1; } else { - *s = '/'; return 0; } } - - *s = '/'; - return 1; } else { - *s = '/'; + g_free( full_jid ); return 0; } } @@ -407,19 +486,22 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ ) { struct jabber_data *jd = gc->proto_data; struct jabber_buddy *bud, *next; + char *bare_jid; - if( strchr( bare_jid, '/' ) ) + if( strchr( bare_jid_, '/' ) ) return 0; + bare_jid = jabber_normalize( bare_jid_ ); + if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) { /* Most important: Remove the hash reference. We don't know this buddy anymore. */ - g_hash_table_remove( jd->buddies, bud->handle ); + g_hash_table_remove( jd->buddies, bud->bare_jid ); /* Deallocate the linked list of resources. */ while( bud ) @@ -431,10 +513,12 @@ int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) bud = next; } + g_free( bare_jid ); return 1; } else { + g_free( bare_jid ); return 0; } } diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index ad19a1dc..ac72f661 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -46,7 +46,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( ( s = strchr( from, '/' ) ) ) { - if( ( bud = jabber_buddy_by_jid( gc, from ) ) ) + if( ( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) ) ) bud->last_act = time( NULL ); else *s = 0; /* We need to generate a bare JID now. */ @@ -75,7 +75,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) fullmsg = g_string_append( fullmsg, body->text ); if( fullmsg->len > 0 ) - serv_got_im( gc, bud ? bud->handle : from, fullmsg->str, 0, 0, fullmsg->len ); + serv_got_im( gc, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len ); g_string_free( fullmsg, TRUE ); @@ -83,18 +83,18 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( xt_find_node( node->children, "composing" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->handle : from, 0, 1 ); + serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 1 ); } /* No need to send a "stopped typing" signal when there's a message. */ else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->handle : from, 0, 0 ); + serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 0 ); } else if( xt_find_node( node->children, "paused" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->handle : from, 0, 2 ); + serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 2 ); } if( s ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index ccd22f60..b56acb51 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -37,36 +37,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( type == NULL ) { - if( ( s = strchr( from, '/' ) ) == NULL ) + if( !( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { - char *s = xt_to_string( node ); - serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s", s ); - g_free( s ); + serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } - if( !( bud = jabber_buddy_by_jid( gc, from ) ) ) - { - /* FOR NOW, s still contains the location of the /. - Keep this in mind when changing things here. :-) */ - - /* We check if the buddy is in the contact list, - because Jabber servers seem to like to send - presence information of buddies we removed - from our list sometimes, for example... */ - - *s = 0; - if( find_buddy( gc, from ) == NULL ) - { - *s = '/'; - serv_got_crap( gc, "WARNING: Ignoring presence information from unknown JID: %s", from ); - return XT_HANDLED; - } - *s = '/'; - - bud = jabber_buddy_add( gc, from ); - } - g_free( bud->away_message ); if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 ) bud->away_message = g_strdup( c->text ); @@ -88,36 +64,34 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; - serv_got_update( gc, bud->handle, 1, 0, 0, 0, + serv_got_update( gc, bud->bare_jid, 1, 0, 0, 0, bud->away_state ? UC_UNAVAILABLE : 0, 0 ); } else if( strcmp( type, "unavailable" ) == 0 ) { - char *s; - - if( ( s = strchr( from, '/' ) ) == NULL ) - { - char *s = xt_to_string( node ); - serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); - g_free( s ); - return XT_HANDLED; - } - - if( jabber_buddy_by_jid( gc, from ) == NULL ) + if( jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) == NULL ) { serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } jabber_buddy_remove( gc, from ); - *s = 0; - /* Only count this as offline if there's no other resource - available anymore. */ - if( jabber_buddy_by_jid( gc, from ) == NULL ) - serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + if( ( s = strchr( from, '/' ) ) ) + { + *s = 0; - *s = '/'; + /* Only count this as offline if there's no other resource + available anymore. */ + if( jabber_buddy_by_jid( gc, from, 0 ) == NULL ) + serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + + *s = '/'; + } + else + { + serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + } } else if( strcmp( type, "subscribe" ) == 0 ) { @@ -125,6 +99,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) } else if( strcmp( type, "subscribed" ) == 0 ) { + /* Not sure about this one, actually... */ serv_got_crap( gc, "%s just accepted your authorization request", from ); } else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) -- cgit v1.2.3 From 16b5f86a2cf909628d5b90aa5d36aaac8f869a78 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 13 Nov 2006 11:38:23 +0100 Subject: Added handling of GET_BUDDY_* flags. --- protocols/jabber/jabber_util.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 7b1961e0..5184a37e 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -358,7 +358,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ /* Is this one of those no-resource buddies? */ if( bud->resource == NULL ) { - bud = NULL; + g_free( jid ); + return NULL; } else { @@ -369,9 +370,11 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ } } - *s = '/'; - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) + { + *s = '/'; bud = jabber_buddy_add( gc, jid ); + } g_free( jid ); return bud; @@ -385,10 +388,15 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ g_free( jid ); - /* An exact match, or only one option. */ if( bud == NULL ) - return ( flags & GET_BUDDY_CREAT ) ? jabber_buddy_add( gc, jid ) : NULL; + /* No match. Create it now? */ + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) ? + jabber_buddy_add( gc, jid ) : NULL; + else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) + /* We want an exact match, so in thise case there shouldn't be a /resource. */ + return NULL; else if( ( bud->resource == NULL || bud->next == NULL ) ) + /* No need for selection if there's only one option. */ return bud; best_prio = best_time = bud; -- cgit v1.2.3 From 9bcbe48c6e8a3ab80e498b78b486c0e7cb3466fd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 23 Nov 2006 10:34:18 +0100 Subject: Fixed some (possible) NULL-pointer dereferences. THANKS FOR NOTHING to GLib for giving this very useful "s2 != NULL assertion failed" message instead of just dereferencing the damn pointer so I can find a backtrace, this sure makes debugging very easy, guys! Wasn't GLib supposed to SAVE time? --- protocols/jabber/iq.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index c46a7c52..914dd02b 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -50,7 +50,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( ( s = xt_find_attr( node, "id" ) ) == NULL || strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 ) { - /* Silently ignore it, without an ID (or an non-cache + /* Silently ignore it, without an ID (or a non-cache ID) we don't know how to handle the packet and we probably don't have to. */ return XT_HANDLED; @@ -59,7 +59,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) entry = g_hash_table_lookup( jd->node_cache, s ); if( entry == NULL ) - serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s ); + serv_got_crap( gc, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); else if( entry->func ) return entry->func( gc, node, entry->node ); } @@ -135,6 +135,9 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return XT_HANDLED; } + /* This is a roster push. XMPP servers send this when someone + was added to (or removed from) the buddy list. AFAIK they're + sent even if we added this buddy in our own session. */ if( strcmp( s, XMLNS_ROSTER ) == 0 ) { int bare_len = strlen( gc->acc->user ); @@ -150,7 +153,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else { - serv_got_crap( gc, "WARNING: %s tried to fake a roster push!", s ); + serv_got_crap( gc, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -213,7 +216,12 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * xt_status st; char *s; - query = xt_find_node( node->children, "query" ); + if( !( query = xt_find_node( node->children, "query" ) ) ) + { + serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" ); + signoff( gc ); + return XT_HANDLED; + } /* Time to authenticate ourselves! */ reply = xt_new_node( "query", NULL, NULL ); @@ -263,8 +271,15 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) { - char *type = xt_find_attr( node, "type" ); struct jabber_data *jd = gc->proto_data; + char *type; + + if( !( type = xt_find_attr( node, "type" ) ) ) + { + serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" ); + signoff( gc ); + return XT_HANDLED; + } if( strcmp( type, "error" ) == 0 ) { @@ -335,7 +350,11 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node struct xt_node *query, *c; int initial = ( orig != NULL ); - query = xt_find_node( node->children, "query" ); + if( !( query = xt_find_node( node->children, "query" ) ) ) + { + serv_got_crap( gc, "WARNING: Received NULL roster packet" ); + return XT_HANDLED; + } c = query->children; while( ( c = xt_find_node( c, "item" ) ) ) @@ -360,7 +379,7 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node { if( find_buddy( gc, jid ) == NULL ) add_buddy( gc, NULL, jid, name ); - else + else if( name ) serv_buddy_rename( gc, jid, name ); } else if( strcmp( sub, "remove" ) == 0 ) -- cgit v1.2.3 From 25984f203b18ce36aabae431797266e44e9a3ba0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 23 Nov 2006 19:46:09 +0100 Subject: Fixed me. ;-) This seems to be correct already. --- protocols/jabber/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 1039bb87..f05cc93d 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -168,7 +168,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( !xt_handle( jd->xt, NULL, 1 ) ) { /* Don't do anything, the handlers should have - aborted the connection already... Or not? FIXME */ + aborted the connection already. */ return FALSE; } -- cgit v1.2.3 From dfc8a468020935a444397129eb5b2579e1001cf2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 24 Nov 2006 20:39:59 +0100 Subject: Bye bye lilo. I've never been a fan of yours, but let's not make fun of the dead... --- ipc.c | 6 +++--- irc_commands.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ipc.c b/ipc.c index 28aa07cb..d0d2dff3 100644 --- a/ipc.c +++ b/ipc.c @@ -98,7 +98,7 @@ static const command_t ipc_master_commands[] = { { "hello", 0, ipc_master_cmd_client, 0 }, { "die", 0, ipc_master_cmd_die, 0 }, { "wallops", 1, NULL, IPC_CMD_TO_CHILDREN }, - { "lilo", 1, NULL, IPC_CMD_TO_CHILDREN }, + { "wall", 1, NULL, IPC_CMD_TO_CHILDREN }, { "opermsg", 1, NULL, IPC_CMD_TO_CHILDREN }, { "rehash", 0, ipc_master_cmd_rehash, 0 }, { "kill", 2, NULL, IPC_CMD_TO_CHILDREN }, @@ -121,7 +121,7 @@ static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] ); } -static void ipc_child_cmd_lilo( irc_t *irc, char **cmd ) +static void ipc_child_cmd_wall( irc_t *irc, char **cmd ) { if( !( irc->status & USTATUS_LOGGED_IN ) ) return; @@ -174,7 +174,7 @@ static void ipc_child_cmd_hello( irc_t *irc, char **cmd ) static const command_t ipc_child_commands[] = { { "die", 0, ipc_child_cmd_die, 0 }, { "wallops", 1, ipc_child_cmd_wallops, 0 }, - { "lilo", 1, ipc_child_cmd_lilo, 0 }, + { "wall", 1, ipc_child_cmd_wall, 0 }, { "opermsg", 1, ipc_child_cmd_opermsg, 0 }, { "rehash", 0, ipc_child_cmd_rehash, 0 }, { "kill", 2, ipc_child_cmd_kill, 0 }, diff --git a/irc_commands.c b/irc_commands.c index 47d9e8cb..b1045c93 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -592,7 +592,7 @@ static const command_t irc_commands[] = { { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN }, { "die", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, { "wallops", 1, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, - { "lilo", 1, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, + { "wall", 1, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, { "rehash", 0, irc_cmd_rehash, IRC_CMD_OPER_ONLY }, { "restart", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, { "kill", 2, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, -- cgit v1.2.3 From 55078f59c8e9f52f1d10bed55511e5e58ec3e53b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 25 Nov 2006 10:20:29 +0100 Subject: Forgot to pass O_CREAT to open() which can cause problems if there's a stale .xml~ file. --- storage_xml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_xml.c b/storage_xml.c index ba311120..00fca425 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -394,7 +394,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) return STORAGE_ALREADY_EXISTS; strcat( path, "~" ); - if( ( fd = open( path, O_WRONLY | O_CREAT, 0600 ) ) < 0 ) + if( ( fd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0600 ) ) < 0 ) { irc_usermsg( irc, "Error while opening configuration file." ); return STORAGE_OTHER_ERROR; -- cgit v1.2.3 From cb6a6f437f4fb1be3f35b61f2c26e78ecacaedde Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Dec 2006 18:57:17 +0100 Subject: Fixed use of already free()d variable. --- protocols/jabber/jabber_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 5184a37e..4ca0c1fc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -390,8 +390,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) ? - jabber_buddy_add( gc, jid ) : NULL; + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid_ ) ) ? + jabber_buddy_add( gc, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ return NULL; -- cgit v1.2.3 From c7d0f415e0bed09decce7a0503dce2274c9d94d9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Dec 2006 18:57:31 +0100 Subject: Added Jabber info to CHANGES. --- doc/CHANGES | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/CHANGES b/doc/CHANGES index e9435216..567a8ae6 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -40,6 +40,26 @@ Version x.x: lose the nicknames, you can now use "account set" to change the username and password for the existing connection. * Per-account settings (see the new "account set" command). +- A brand new Jabber module. Besides the major code cleanup, it also has + has these new features: + * Pretty complete XMPP support: RFC3920, RFC3921 plus a number of XEPs + including XEP73 and XEP85. (See http://www.xmpp.org/ for what all these + things mean exactly.) Privacy lists are not supported for obvious + reasons. + * This complete support also includes TLS and SASL support and SRV record + lookup. This means that specifying a server tag for connections should + (almost) never be necessary anymore, BitlBee can find the server and can + automatically convert plaintext connections to TLS-encrypted ones. + * XEP85 means typing notifications. The older XEP22 (still used by some + clients including Gaim <2.0) is not supported. + * Better handling of buddies who have more than one resource on-line. As + long as one resource is on-line (and visible), BitlBee will show this. + (The previous module didn't keep track of resources and sent an offline + event as soon as any resource disappears.) + * You can now set your resource priority. + * The info command now gives away state/message information for all + resources available for that buddy. (Of course this only works if the + buddy is in your contact list.) Version 1.0.3: - Fixed ugliness in block/allow list commands (still not perfect though, the -- cgit v1.2.3 From 7740c4caae24fe8186947d0f1f6a114098daa171 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Tue, 5 Dec 2006 23:57:02 +0100 Subject: Fix xslt with newer (more pedantic) XSLT processors. --- doc/user-guide/docbook.xsl | 1 + doc/user-guide/help.xsl | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/user-guide/docbook.xsl b/doc/user-guide/docbook.xsl index 9adff305..21d6b08e 100644 --- a/doc/user-guide/docbook.xsl +++ b/doc/user-guide/docbook.xsl @@ -82,6 +82,7 @@ </xsl:template> <xsl:template name="cmd"> + <xsl:param name="prefix"/> <xsl:variable name="thiscmd"><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></xsl:variable> <xsl:attribute name="id"> <xsl:text>cmd_</xsl:text> diff --git a/doc/user-guide/help.xsl b/doc/user-guide/help.xsl index dec6a671..b7e3c371 100644 --- a/doc/user-guide/help.xsl +++ b/doc/user-guide/help.xsl @@ -30,6 +30,7 @@ </xsl:template> <xsl:template name="subject"> + <xsl:param name="id"/> <xsl:message><xsl:text>Processing: </xsl:text><xsl:value-of select="$id"/></xsl:message> <xsl:text>?</xsl:text><xsl:value-of select="$id"/><xsl:text> </xsl:text> @@ -121,6 +122,7 @@ </xsl:template> <xsl:template name="cmd"> + <xsl:param name="prefix"/> <xsl:variable name="thiscmd"><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></xsl:variable> <xsl:message><xsl:text>Processing command '</xsl:text><xsl:value-of select="$thiscmd"/><xsl:text>'</xsl:text></xsl:message> <xsl:text>?</xsl:text><xsl:value-of select="$thiscmd"/><xsl:text> </xsl:text> -- cgit v1.2.3 From 2c7df621d2337437a46b0ccee6a7801bc04db8f4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Wed, 6 Dec 2006 13:15:09 +0100 Subject: Fix testsuite. --- lib/Makefile | 2 ++ tests/Makefile | 4 ++-- tests/check_nick.c | 2 +- tests/check_util.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 6408c5ba..b1bddb3e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,6 +17,8 @@ LFLAGS += -r # [SH] Phony targets all: lib.o +check: + .PHONY: all clean distclean clean: $(subdirs) diff --git a/tests/Makefile b/tests/Makefile index 206331f4..f0456063 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,11 +8,11 @@ all: check clean: rm -f check *.o -main_objs = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o url.o user.o util.o +main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o test_objs = check.o check_util.o check_nick.o -check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o +check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ @$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(EFLAGS) diff --git a/tests/check_nick.c b/tests/check_nick.c index b235d260..714c4fdc 100644 --- a/tests/check_nick.c +++ b/tests/check_nick.c @@ -5,7 +5,7 @@ #include <string.h> #include "irc.h" #include "set.h" -#include "util.h" +#include "misc.h" START_TEST(test_nick_strip) { diff --git a/tests/check_util.c b/tests/check_util.c index e771238f..ee365735 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -5,7 +5,7 @@ #include <string.h> #include "irc.h" #include "set.h" -#include "util.h" +#include "misc.h" START_TEST(test_strip_linefeed) { -- cgit v1.2.3 From 6a909671115ba5fac94c212c249264bf25ec8840 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Wed, 6 Dec 2006 14:26:22 +0100 Subject: Add tests for md5. --- tests/Makefile | 2 +- tests/check.c | 18 ++++++++++++++++++ tests/check_md5.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.h | 6 ++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tests/check_md5.c create mode 100644 tests/testsuite.h diff --git a/tests/Makefile b/tests/Makefile index f0456063..6a97e8ac 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ clean: main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o +test_objs = check.o check_util.o check_nick.o check_md5.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 5cfb7dfd..294580b7 100644 --- a/tests/check.c +++ b/tests/check.c @@ -3,9 +3,23 @@ #include <gmodule.h> #include <check.h> #include "bitlbee.h" +#include "testsuite.h" global_t global; /* Against global namespace pollution */ +gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2) +{ + int sock[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, sock) < 0) { + perror("socketpair"); + return FALSE; + } + + *ch1 = g_io_channel_unix_new(sock[0]); + *ch2 = g_io_channel_unix_new(sock[1]); + return TRUE; +} + double gettime() { struct timeval time[1]; @@ -20,11 +34,15 @@ Suite *util_suite(void); /* From check_nick.c */ Suite *nick_suite(void); +/* From check_md5.c */ +Suite *md5_suite(void); + int main (void) { int nf; SRunner *sr = srunner_create(util_suite()); srunner_add_suite(sr, nick_suite()); + srunner_add_suite(sr, md5_suite()); srunner_run_all (sr, CK_NORMAL); nf = srunner_ntests_failed(sr); srunner_free(sr); diff --git a/tests/check_md5.c b/tests/check_md5.c new file mode 100644 index 00000000..4b99d300 --- /dev/null +++ b/tests/check_md5.c @@ -0,0 +1,56 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "md5.h" + +/* From RFC 1321 */ +struct md5_test { + const char *str; + md5_byte_t expected[16]; +} tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + + { NULL }, +}; + +static void check_sums(int l) +{ + int i; + for (i = 0; tests[i].str; i++) { + md5_byte_t sum[16]; + tcase_fn_start (tests[i].str, __FILE__, __LINE__); + md5_state_t state; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)tests[i].str, strlen(tests[i].str)); + md5_finish(&state, sum); + + fail_if(memcmp(tests[i].expected, sum, 16) != 0, "%s failed", tests[i].str); + } +} + +Suite *md5_suite (void) +{ + Suite *s = suite_create("MD5"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, check_sums); + return s; +} diff --git a/tests/testsuite.h b/tests/testsuite.h new file mode 100644 index 00000000..dacaf8a3 --- /dev/null +++ b/tests/testsuite.h @@ -0,0 +1,6 @@ +#ifndef __BITLBEE_CHECK_H__ +#define __BITLBEE_CHECK_H__ + +gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2); + +#endif /* __BITLBEE_CHECK_H__ */ -- cgit v1.2.3 From 3b4cc8f0af7a4d9e1fae69e12a438b15f9206003 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Wed, 6 Dec 2006 14:34:15 +0100 Subject: Support arguments passed to tests/check to enable verbose logging or to disable forking (for debugging purposes). --- tests/check.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/check.c b/tests/check.c index 294580b7..6cba4302 100644 --- a/tests/check.c +++ b/tests/check.c @@ -37,13 +37,35 @@ Suite *nick_suite(void); /* From check_md5.c */ Suite *md5_suite(void); -int main (void) +int main (int argc, char **argv) { int nf; - SRunner *sr = srunner_create(util_suite()); + SRunner *sr; + GOptionContext *pc; + gboolean no_fork = FALSE; + gboolean verbose = FALSE; + GOptionEntry options[] = { + {"no-fork", 'n', 0, G_OPTION_ARG_NONE, &no_fork, "Don't fork" }, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, + { NULL } + }; + int i; + + pc = g_option_context_new(""); + g_option_context_add_main_entries(pc, options, NULL); + + if(!g_option_context_parse(pc, &argc, &argv, NULL)) + return 1; + + g_option_context_free(pc); + + + sr = srunner_create(util_suite()); srunner_add_suite(sr, nick_suite()); srunner_add_suite(sr, md5_suite()); - srunner_run_all (sr, CK_NORMAL); + if (no_fork) + srunner_set_fork_status(sr, CK_NOFORK); + srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); nf = srunner_ntests_failed(sr); srunner_free(sr); return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -- cgit v1.2.3 From 7bcdde3d31f0e5b53601b90aa33ebd820c770172 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Wed, 6 Dec 2006 14:57:25 +0100 Subject: Some simple tests for irc_*() --- tests/Makefile | 4 ++-- tests/check.c | 15 +++++++++++++ tests/check_irc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 tests/check_irc.c diff --git a/tests/Makefile b/tests/Makefile index 6a97e8ac..9dd3df7c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,14 +3,14 @@ include ../Makefile.settings LFLAGS +=-lcheck all: check - ./check + ./check $(CHECKFLAGS) clean: rm -f check *.o main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 6cba4302..42ff067f 100644 --- a/tests/check.c +++ b/tests/check.c @@ -37,6 +37,9 @@ Suite *nick_suite(void); /* From check_md5.c */ Suite *md5_suite(void); +/* From check_irc.c */ +Suite *irc_suite(void); + int main (int argc, char **argv) { int nf; @@ -59,10 +62,22 @@ int main (int argc, char **argv) g_option_context_free(pc); + log_init(); + + if (verbose) { + log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); + log_link( LOGLVL_DEBUG, LOGOUTPUT_CONSOLE ); + log_link( LOGLVL_INFO, LOGOUTPUT_CONSOLE ); + log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); + } + + global.conf = conf_load( 0, NULL); + global.conf->runmode = RUNMODE_DAEMON; sr = srunner_create(util_suite()); srunner_add_suite(sr, nick_suite()); srunner_add_suite(sr, md5_suite()); + srunner_add_suite(sr, irc_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_irc.c b/tests/check_irc.c new file mode 100644 index 00000000..c1cf05a5 --- /dev/null +++ b/tests/check_irc.c @@ -0,0 +1,65 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "irc.h" +#include "testsuite.h" + +START_TEST(test_connect) + GIOChannel *ch1, *ch2; + irc_t *irc; + char *raw; + fail_unless(g_io_channel_pair(&ch1, &ch2)); + + irc = irc_new(g_io_channel_unix_get_fd(ch1)); + + irc_free(irc); + + fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); + + fail_if(strcmp(raw, "") != 0); + + g_free(raw); +END_TEST + +START_TEST(test_login) + GIOChannel *ch1, *ch2; + irc_t *irc; + GError *error = NULL; + char *raw; + fail_unless(g_io_channel_pair(&ch1, &ch2)); + + g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL); + + irc = irc_new(g_io_channel_unix_get_fd(ch1)); + + fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\n" + "USER a a a a\r\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL); + fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL); + + g_main_iteration(FALSE); + irc_free(irc); + + fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); + + fail_unless(strstr(raw, "001") != NULL); + fail_unless(strstr(raw, "002") != NULL); + fail_unless(strstr(raw, "003") != NULL); + fail_unless(strstr(raw, "004") != NULL); + fail_unless(strstr(raw, "005") != NULL); + + g_free(raw); +END_TEST + +Suite *irc_suite (void) +{ + Suite *s = suite_create("IRC"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_connect); + tcase_add_test (tc_core, test_login); + return s; +} -- cgit v1.2.3 From a51be6448b7a6aa100f27873ce40b835068a66a7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Wed, 6 Dec 2006 15:16:56 +0100 Subject: Fix gcov. --- lib/Makefile | 5 +++-- protocols/jabber/Makefile | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index b1bddb3e..33073c27 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -16,8 +16,9 @@ LFLAGS += -r # [SH] Phony targets all: lib.o - -check: +check: all +gcov: + gcov *.c .PHONY: all clean distclean diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index abfc7478..27a29be4 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -17,6 +17,8 @@ LFLAGS += -r # [SH] Phony targets all: jabber_mod.o check: all +gcov: + gcov *.c .PHONY: all clean distclean -- cgit v1.2.3 From 9225e08f377026e653e31468d53df9d328dd7951 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 24 Dec 2006 02:47:20 +0100 Subject: Fix check for non-debug builds. --- tests/check.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/check.c b/tests/check.c index 42ff067f..f70ccae7 100644 --- a/tests/check.c +++ b/tests/check.c @@ -66,7 +66,9 @@ int main (int argc, char **argv) if (verbose) { log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); +#ifdef DEBUG log_link( LOGLVL_DEBUG, LOGOUTPUT_CONSOLE ); +#endif log_link( LOGLVL_INFO, LOGOUTPUT_CONSOLE ); log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); } -- cgit v1.2.3 From c227706bc921c3bb426eb315c0d097df30aa9d16 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 24 Dec 2006 20:35:13 +0100 Subject: Refactor the help code to take a filename rather than using the global struct. --- help.c | 13 ++++++------- help.h | 2 +- tests/Makefile | 2 +- tests/check.c | 4 ++++ tests/check_help.c | 30 ++++++++++++++++++++++++++++++ unix.c | 2 +- 6 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 tests/check_help.c diff --git a/help.c b/help.c index 7c6d2dda..756eb12a 100644 --- a/help.c +++ b/help.c @@ -30,7 +30,7 @@ #define BUFSIZE 1100 -help_t *help_init( help_t **help ) +help_t *help_init( help_t **help, const char *helpfile ) { int i, buflen = 0; help_t *h; @@ -40,7 +40,7 @@ help_t *help_init( help_t **help ) *help = h = g_new0 ( help_t, 1 ); - h->fd = open( global.helpfile, O_RDONLY + h->fd = open( helpfile, O_RDONLY #ifdef _WIN32 | O_BINARY #endif @@ -108,12 +108,11 @@ char *help_get( help_t **help, char *string ) struct stat stat[1]; help_t *h; - h=*help; - - while( h ) + for( h = *help; h; h = h->next ) { - if( g_strcasecmp( h->string, string ) == 0 ) break; - h = h->next; + if( h->string != NULL && + g_strcasecmp( h->string, string ) == 0 ) + break; } if( h && h->length > 0 ) { diff --git a/help.h b/help.h index 7b8da39a..07182e9c 100644 --- a/help.h +++ b/help.h @@ -42,7 +42,7 @@ typedef struct help struct help *next; } help_t; -help_t *help_init( help_t **help ); +help_t *help_init( help_t **help, const char *helpfile ); char *help_get( help_t **help, char *string ); #endif diff --git a/tests/Makefile b/tests/Makefile index 9dd3df7c..3ddd1570 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ clean: main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index f70ccae7..069b3c57 100644 --- a/tests/check.c +++ b/tests/check.c @@ -40,6 +40,9 @@ Suite *md5_suite(void); /* From check_irc.c */ Suite *irc_suite(void); +/* From check_help.c */ +Suite *help_suite(void); + int main (int argc, char **argv) { int nf; @@ -80,6 +83,7 @@ int main (int argc, char **argv) srunner_add_suite(sr, nick_suite()); srunner_add_suite(sr, md5_suite()); srunner_add_suite(sr, irc_suite()); + srunner_add_suite(sr, help_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_help.c b/tests/check_help.c new file mode 100644 index 00000000..7e5283e3 --- /dev/null +++ b/tests/check_help.c @@ -0,0 +1,30 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "help.h" + +START_TEST(test_help_none) + help_t *h, *r; + r = help_init(&h, "/dev/null"); + fail_if(r == NULL); + fail_if(r != h); +END_TEST + +START_TEST(test_help_nonexistent) + help_t *h, *r; + r = help_init(&h, "/dev/null"); + fail_unless(help_get(&h, "nonexistent") == NULL); +END_TEST + +Suite *help_suite (void) +{ + Suite *s = suite_create("Help"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_help_none); + tcase_add_test (tc_core, test_help_nonexistent); + return s; +} diff --git a/unix.c b/unix.c index 23ae1b91..2be16b2b 100644 --- a/unix.c +++ b/unix.c @@ -111,7 +111,7 @@ int main( int argc, char *argv[], char **envp ) if( !getuid() || !geteuid() ) log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" ); - if( help_init( &(global.help) ) == NULL ) + if( help_init( &(global.help), global.helpfile ) == NULL ) log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE ); b_main_run(); -- cgit v1.2.3 From 7bee5af91e56f1e58232b895fd40c367aec67e8a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 24 Dec 2006 22:47:18 +0100 Subject: Add tests for set_url(). Fixed a bug where the default port wasn't set when socks5 was used. --- lib/url.c | 2 +- set.h | 5 +++++ tests/check_util.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/lib/url.c b/lib/url.c index e4deac78..c6fdc4c8 100644 --- a/lib/url.c +++ b/lib/url.c @@ -99,7 +99,7 @@ int url_set( url_t *url, char *set_url ) url->port = 80; else if( url->proto == PROTO_HTTPS ) url->port = 443; - else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 ) + else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS5 ) url->port = 1080; } diff --git a/set.h b/set.h index 37d2430f..32f7a0e6 100644 --- a/set.h +++ b/set.h @@ -23,6 +23,9 @@ Suite 330, Boston, MA 02111-1307 USA */ +#ifndef __SET_H__ +#define __SET_H__ + /* This used to be specific to irc_t structures, but it's more generic now (so it can also be used for account_t structs). It's pretty simple, but so far pretty useful. @@ -87,3 +90,5 @@ char *set_eval_bool( set_t *set, char *value ); char *set_eval_to_char( set_t *set, char *value ); char *set_eval_ops( set_t *set, char *value ); char *set_eval_charset( set_t *set, char *value ); + +#endif /* __SET_H__ */ diff --git a/tests/check_util.c b/tests/check_util.c index ee365735..284ddba3 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -6,6 +6,7 @@ #include "irc.h" #include "set.h" #include "misc.h" +#include "url.h" START_TEST(test_strip_linefeed) { @@ -42,6 +43,66 @@ START_TEST(test_strip_newlines) } END_TEST +START_TEST(test_set_url_http) + url_t url; + + fail_if (0 == url_set(&url, "http://host/")); + fail_unless (!strcmp(url.host, "host")); + fail_unless (!strcmp(url.file, "/")); + fail_unless (!strcmp(url.user, "")); + fail_unless (!strcmp(url.pass, "")); + fail_unless (url.proto == PROTO_HTTP); + fail_unless (url.port == 80); +END_TEST + +START_TEST(test_set_url_https) + url_t url; + + fail_if (0 == url_set(&url, "https://ahost/AimeeMann")); + fail_unless (!strcmp(url.host, "ahost")); + fail_unless (!strcmp(url.file, "/AimeeMann")); + fail_unless (!strcmp(url.user, "")); + fail_unless (!strcmp(url.pass, "")); + fail_unless (url.proto == PROTO_HTTPS); + fail_unless (url.port == 443); +END_TEST + +START_TEST(test_set_url_port) + url_t url; + + fail_if (0 == url_set(&url, "https://ahost:200/Lost/In/Space")); + fail_unless (!strcmp(url.host, "ahost")); + fail_unless (!strcmp(url.file, "/Lost/In/Space")); + fail_unless (!strcmp(url.user, "")); + fail_unless (!strcmp(url.pass, "")); + fail_unless (url.proto == PROTO_HTTPS); + fail_unless (url.port == 200); +END_TEST + +START_TEST(test_set_url_username) + url_t url; + + fail_if (0 == url_set(&url, "socks4://user@ahost/Space")); + fail_unless (!strcmp(url.host, "ahost")); + fail_unless (!strcmp(url.file, "/Space")); + fail_unless (!strcmp(url.user, "user")); + fail_unless (!strcmp(url.pass, "")); + fail_unless (url.proto == PROTO_SOCKS4); + fail_unless (url.port == 1080); +END_TEST + +START_TEST(test_set_url_username_pwd) + url_t url; + + fail_if (0 == url_set(&url, "socks5://user:pass@ahost/")); + fail_unless (!strcmp(url.host, "ahost")); + fail_unless (!strcmp(url.file, "/")); + fail_unless (!strcmp(url.user, "user")); + fail_unless (!strcmp(url.pass, "pass")); + fail_unless (url.proto == PROTO_SOCKS5); + fail_unless (url.port == 1080); +END_TEST + Suite *util_suite (void) { Suite *s = suite_create("Util"); @@ -49,5 +110,10 @@ Suite *util_suite (void) suite_add_tcase (s, tc_core); tcase_add_test (tc_core, test_strip_linefeed); tcase_add_test (tc_core, test_strip_newlines); + tcase_add_test (tc_core, test_set_url_http); + tcase_add_test (tc_core, test_set_url_https); + tcase_add_test (tc_core, test_set_url_port); + tcase_add_test (tc_core, test_set_url_username); + tcase_add_test (tc_core, test_set_url_username_pwd); return s; } -- cgit v1.2.3 From ed5df815732d311b228993627f5d8b8c8e3eb4e0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 21 Jan 2007 22:17:11 +0100 Subject: Add unit testing for user code --- tests/Makefile | 2 +- tests/check.c | 14 ++++++++++ tests/check_user.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.h | 1 + user.h | 4 +++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/check_user.c diff --git a/tests/Makefile b/tests/Makefile index 3ddd1570..b9da83c9 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ clean: main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 069b3c57..9fee07e3 100644 --- a/tests/check.c +++ b/tests/check.c @@ -20,6 +20,16 @@ gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2) return TRUE; } +irc_t *torture_irc(void) +{ + irc_t *irc; + GIOChannel *ch1, *ch2; + if (!g_io_channel_pair(&ch1, &ch2)) + return NULL; + irc = irc_new(g_io_channel_unix_get_fd(ch1)); + return irc; +} + double gettime() { struct timeval time[1]; @@ -43,6 +53,9 @@ Suite *irc_suite(void); /* From check_help.c */ Suite *help_suite(void); +/* From check_user.c */ +Suite *user_suite(void); + int main (int argc, char **argv) { int nf; @@ -84,6 +97,7 @@ int main (int argc, char **argv) srunner_add_suite(sr, md5_suite()); srunner_add_suite(sr, irc_suite()); srunner_add_suite(sr, help_suite()); + srunner_add_suite(sr, user_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_user.c b/tests/check_user.c new file mode 100644 index 00000000..79248049 --- /dev/null +++ b/tests/check_user.c @@ -0,0 +1,75 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include "bitlbee.h" +#include "user.h" +#include "testsuite.h" + +START_TEST(test_user_add) + irc_t *irc = torture_irc(); + user_t *user; + user = user_add(irc, "foo"); + fail_if(user == NULL); + fail_if(strcmp(user->nick, "foo") != 0); + fail_unless(user_find(irc, "foo") == user); +END_TEST + +START_TEST(test_user_add_exists) + irc_t *irc = torture_irc(); + user_t *user; + user = user_add(irc, "foo"); + fail_if(user == NULL); + user = user_add(irc, "foo"); + fail_unless(user == NULL); +END_TEST + +START_TEST(test_user_add_invalid) + irc_t *irc = torture_irc(); + user_t *user; + user = user_add(irc, ":foo"); + fail_unless(user == NULL); +END_TEST + +START_TEST(test_user_del_invalid) + irc_t *irc = torture_irc(); + fail_unless(user_del(irc, ":foo") == 0); +END_TEST + +START_TEST(test_user_del) + irc_t *irc = torture_irc(); + user_t *user; + user = user_add(irc, "foo"); + fail_unless(user_del(irc, "foo") == 1); + fail_unless(user_find(irc, "foo") == NULL); +END_TEST + +START_TEST(test_user_del_nonexistant) + irc_t *irc = torture_irc(); + fail_unless(user_del(irc, "foo") == 0); +END_TEST + +START_TEST(test_user_rename) + irc_t *irc = torture_irc(); + user_t *user; + user = user_add(irc, "foo"); + user_rename(irc, "foo", "bar"); + fail_unless(user_find(irc, "foo") == NULL); + fail_if(user_find(irc, "bar") == NULL); +END_TEST + +Suite *user_suite (void) +{ + Suite *s = suite_create("User"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_user_add); + tcase_add_test (tc_core, test_user_add_invalid); + tcase_add_test (tc_core, test_user_add_exists); + tcase_add_test (tc_core, test_user_del_invalid); + tcase_add_test (tc_core, test_user_del_nonexistant); + tcase_add_test (tc_core, test_user_del); + tcase_add_test (tc_core, test_user_rename); + return s; +} diff --git a/tests/testsuite.h b/tests/testsuite.h index dacaf8a3..79227041 100644 --- a/tests/testsuite.h +++ b/tests/testsuite.h @@ -1,6 +1,7 @@ #ifndef __BITLBEE_CHECK_H__ #define __BITLBEE_CHECK_H__ +irc_t *torture_irc(void); gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2); #endif /* __BITLBEE_CHECK_H__ */ diff --git a/user.h b/user.h index b8896d92..176e364e 100644 --- a/user.h +++ b/user.h @@ -22,6 +22,8 @@ if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef __USER_H__ +#define __USER_H__ typedef struct __USER { @@ -55,3 +57,5 @@ int user_del( irc_t *irc, char *nick ); G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick ); G_MODULE_EXPORT user_t *user_findhandle( struct gaim_connection *gc, char *handle ); void user_rename( irc_t *irc, char *oldnick, char *newnick ); + +#endif /* __USER_H__ */ -- cgit v1.2.3 From 8c073a6e77edd56bc3d58d6b4af2a40f005aacad Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 21 Jan 2007 22:38:50 +0100 Subject: Add testsuite for crypting. --- tests/Makefile | 2 +- tests/check.c | 4 ++++ tests/check_crypting.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/check_crypting.c diff --git a/tests/Makefile b/tests/Makefile index b9da83c9..7c959890 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ clean: main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check_crypting.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 9fee07e3..bf76a89d 100644 --- a/tests/check.c +++ b/tests/check.c @@ -56,6 +56,9 @@ Suite *help_suite(void); /* From check_user.c */ Suite *user_suite(void); +/* From check_crypting.c */ +Suite *crypting_suite(void); + int main (int argc, char **argv) { int nf; @@ -98,6 +101,7 @@ int main (int argc, char **argv) srunner_add_suite(sr, irc_suite()); srunner_add_suite(sr, help_suite()); srunner_add_suite(sr, user_suite()); + srunner_add_suite(sr, crypting_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_crypting.c b/tests/check_crypting.c new file mode 100644 index 00000000..b8e5e1e0 --- /dev/null +++ b/tests/check_crypting.c @@ -0,0 +1,47 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include "bitlbee.h" +#include "crypting.h" +#include "testsuite.h" + +START_TEST(test_check_pass_valid) + fail_unless (checkpass ("foo", "acbd18db4cc2f85cedef654fccc4a4d8") == 0); + fail_unless (checkpass ("invalidpass", "acbd18db4cc2f85cedef654fccc4a4d8") == -1); + +END_TEST + +START_TEST(test_hashpass) + fail_unless (strcmp(hashpass("foo"), "acbd18db4cc2f85cedef654fccc4a4d8") == 0); +END_TEST + +START_TEST(test_obfucrypt) + char *raw = obfucrypt("some line", "bla"); + fail_unless(strcmp(raw, "\xd5\xdb\xce\xc7\x8c\xcd\xcb\xda\xc6") == 0); +END_TEST + +START_TEST(test_deobfucrypt) + char *raw = deobfucrypt("\xd5\xdb\xce\xc7\x8c\xcd\xcb\xda\xc6", "bla"); + fail_unless(strcmp(raw, "some line") == 0); +END_TEST + +START_TEST(test_obfucrypt_bidirectional) + char *plain = g_strdup("this is a line"); + char *raw = obfucrypt(plain, "foo"); + fail_unless(strcmp(plain, deobfucrypt(raw, "foo")) == 0); +END_TEST + +Suite *crypting_suite (void) +{ + Suite *s = suite_create("Crypting"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_check_pass_valid); + tcase_add_test (tc_core, test_hashpass); + tcase_add_test (tc_core, test_obfucrypt); + tcase_add_test (tc_core, test_deobfucrypt); + tcase_add_test (tc_core, test_obfucrypt_bidirectional); + return s; +} -- cgit v1.2.3 From 7738014d6a9ad81806ddb4e06092791dbd10b616 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 21 Jan 2007 23:08:56 +0100 Subject: Add tests for set --- set.h | 2 + tests/Makefile | 2 +- tests/check.c | 4 ++ tests/check_set.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.h | 2 + 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/check_set.c diff --git a/set.h b/set.h index 32f7a0e6..05d737e4 100644 --- a/set.h +++ b/set.h @@ -26,6 +26,8 @@ #ifndef __SET_H__ #define __SET_H__ +struct set; + /* This used to be specific to irc_t structures, but it's more generic now (so it can also be used for account_t structs). It's pretty simple, but so far pretty useful. diff --git a/tests/Makefile b/tests/Makefile index 7c959890..2c45354d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,7 +10,7 @@ clean: main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check_crypting.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index bf76a89d..488d9608 100644 --- a/tests/check.c +++ b/tests/check.c @@ -59,6 +59,9 @@ Suite *user_suite(void); /* From check_crypting.c */ Suite *crypting_suite(void); +/* From check_set.c */ +Suite *set_suite(void); + int main (int argc, char **argv) { int nf; @@ -102,6 +105,7 @@ int main (int argc, char **argv) srunner_add_suite(sr, help_suite()); srunner_add_suite(sr, user_suite()); srunner_add_suite(sr, crypting_suite()); + srunner_add_suite(sr, set_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_set.c b/tests/check_set.c new file mode 100644 index 00000000..b1ea973d --- /dev/null +++ b/tests/check_set.c @@ -0,0 +1,130 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include "set.h" +#include "testsuite.h" + +START_TEST(test_set_add) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "default", NULL, data); + fail_unless(s == t); + fail_unless(t->data == data); + fail_unless(strcmp(t->def, "default") == 0); +END_TEST + +START_TEST(test_set_add_existing) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "default", NULL, data); + t = set_add(&s, "name", "newdefault", NULL, data); + fail_unless(s == t); + fail_unless(strcmp(t->def, "newdefault") == 0); +END_TEST + +START_TEST(test_set_find_unknown) + set_t *s = NULL, *t; + fail_unless (set_find(&s, "foo") == NULL); +END_TEST + +START_TEST(test_set_find) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "default", NULL, data); + fail_unless(s == t); + fail_unless(set_find(&s, "name") == t); +END_TEST + +START_TEST(test_set_get_str_default) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "default", NULL, data); + fail_unless(s == t); + fail_unless(strcmp(set_getstr(&s, "name"), "default") == 0); +END_TEST + +START_TEST(test_set_get_bool_default) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "true", NULL, data); + fail_unless(s == t); + fail_unless(set_getbool(&s, "name")); +END_TEST + +START_TEST(test_set_get_bool_integer) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "3", NULL, data); + fail_unless(s == t); + fail_unless(set_getbool(&s, "name") == 3); +END_TEST + +START_TEST(test_set_get_bool_unknown) + set_t *s = NULL; + fail_unless(set_getbool(&s, "name") == 0); +END_TEST + +START_TEST(test_set_get_str_value) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "default", NULL, data); + set_setstr(&s, "name", "foo"); + fail_unless(strcmp(set_getstr(&s, "name"), "foo") == 0); +END_TEST + +START_TEST(test_set_get_str_unknown) + set_t *s = NULL; + fail_unless(set_getstr(&s, "name") == NULL); +END_TEST + +START_TEST(test_setint) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "10", NULL, data); + set_setint(&s, "name", 3); + fail_unless(set_getint(&s, "name") == 3); +END_TEST + +START_TEST(test_setstr) + void *data = "data"; + set_t *s = NULL, *t; + t = set_add(&s, "name", "foo", NULL, data); + set_setstr(&s, "name", "bloe"); + fail_unless(strcmp(set_getstr(&s, "name"), "bloe") == 0); +END_TEST + +START_TEST(test_setstr_implicit) + void *data = "data"; + set_t *s = NULL, *t; + set_setstr(&s, "name", "bloe"); + fail_unless(set_find(&s, "name") != NULL); +END_TEST + +START_TEST(test_set_get_int_unknown) + set_t *s = NULL; + fail_unless(set_getint(&s, "foo") == 0); +END_TEST + +Suite *set_suite (void) +{ + Suite *s = suite_create("Set"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, test_set_add); + tcase_add_test (tc_core, test_set_add_existing); + tcase_add_test (tc_core, test_set_find_unknown); + tcase_add_test (tc_core, test_set_find); + tcase_add_test (tc_core, test_set_get_str_default); + tcase_add_test (tc_core, test_set_get_str_value); + tcase_add_test (tc_core, test_set_get_str_unknown); + tcase_add_test (tc_core, test_set_get_bool_default); + tcase_add_test (tc_core, test_set_get_bool_integer); + tcase_add_test (tc_core, test_set_get_bool_unknown); + tcase_add_test (tc_core, test_set_get_int_unknown); + tcase_add_test (tc_core, test_setint); + tcase_add_test (tc_core, test_setstr); + tcase_add_test (tc_core, test_setstr_implicit); + return s; +} diff --git a/tests/testsuite.h b/tests/testsuite.h index 79227041..0b169198 100644 --- a/tests/testsuite.h +++ b/tests/testsuite.h @@ -1,6 +1,8 @@ #ifndef __BITLBEE_CHECK_H__ #define __BITLBEE_CHECK_H__ +#include "irc.h" + irc_t *torture_irc(void); gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2); -- cgit v1.2.3 From 348c11b16c156979ef2c7141ca7450af693b3713 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Mon, 22 Jan 2007 10:42:55 +0100 Subject: Add lcov target --- Makefile | 5 +++++ lib/Makefile | 1 + protocols/Makefile | 1 + protocols/jabber/Makefile | 1 + protocols/msn/Makefile | 1 + protocols/oscar/Makefile | 1 + protocols/yahoo/Makefile | 1 + 7 files changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 3044d9b2..de9dcecc 100644 --- a/Makefile +++ b/Makefile @@ -49,9 +49,14 @@ distclean: clean $(subdirs) check: all $(MAKE) -C tests +lcov: gcov: check gcov *.c +lcov: check + lcov --directory . --capture --output-file bitlbee.info + genhtml -o coverage bitlbee.info + install-doc: $(MAKE) -C doc install diff --git a/lib/Makefile b/lib/Makefile index 33073c27..a9038987 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,6 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: lib.o check: all +lcov: gcov: gcov *.c diff --git a/protocols/Makefile b/protocols/Makefile index 7f793bc4..f7d76e0f 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -26,6 +26,7 @@ LFLAGS += -r # [SH] Phony targets all: protocols.o check: all +lcov: gcov: gcov *.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 27a29be4..7a185d00 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -17,6 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: jabber_mod.o check: all +lcov: gcov: gcov *.c diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index f53b34ba..3440658d 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -17,6 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: msn_mod.o check: all +lcov: gcov: gcov *.c diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index ed2d7f83..95e85ec2 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -17,6 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: oscar_mod.o check: all +lcov: gcov: gcov *.c diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index 34c3551a..2cfd147b 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -17,6 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: yahoo_mod.o check: all +lcov: gcov: gcov *.c -- cgit v1.2.3 From 5c5a586d73330f3f3f2c1b0d6d9f1caddfb79850 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 17:05:29 +0000 Subject: configure script tweaks. --- configure | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure b/configure index d31109f2..c1243dcd 100755 --- a/configure +++ b/configure @@ -17,7 +17,7 @@ plugindir='$prefix/lib/bitlbee/' includedir='$prefix/include/bitlbee/' libevent='/usr/' pidfile='/var/run/bitlbee.pid' -ipcsocket='/var/run/bitlbee' +ipcsocket='/var/run/bitlbee.sock' pcdir='$prefix/lib/pkgconfig' msn=1 @@ -106,7 +106,6 @@ MANDIR=$mandir DATADIR=$datadir PLUGINDIR=$plugindir CONFIG=$config -IPCSOCKET=$ipcsocket INCLUDEDIR=$includedir PCDIR=$pcdir @@ -338,6 +337,11 @@ fi if [ "$ldap" = 0 ]; then echo "#undef WITH_LDAP" >> config.h elif [ "$ldap" = 1 ]; then + echo + echo 'LDAP support is a work in progress and does NOT work AT ALL right now.' + echo + exit 1 + echo "#define WITH_LDAP 1" >> config.h STORAGES="$STORAGES ldap" fi -- cgit v1.2.3 From 7e0af5345f398a439459ac1752b8a946fb53a87e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 17:10:14 +0000 Subject: configure --pidfile= actually works now. --- conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.c b/conf.c index 13f150a7..24f6133b 100644 --- a/conf.c +++ b/conf.c @@ -62,7 +62,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->oper_pass = NULL; conf->configdir = g_strdup( CONFIG ); conf->plugindir = g_strdup( PLUGINDIR ); - conf->pidfile = g_strdup( "/var/run/bitlbee.pid" ); + conf->pidfile = g_strdup( PIDFILE ); conf->motdfile = g_strdup( ETCDIR "/motd.txt" ); conf->ping_interval = 180; conf->ping_timeout = 300; -- cgit v1.2.3 From f959495182db79b0c3b51c6bc4e9fcacdc591c40 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 17:19:01 +0000 Subject: Preventing infinite loop while cleaning up accounts in irc_free(). Closes #245. --- irc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/irc.c b/irc.c index f9654034..eb4a395d 100644 --- a/irc.c +++ b/irc.c @@ -255,7 +255,12 @@ void irc_free(irc_t * irc) query_del(irc, irc->queries); while (irc->accounts) - account_del(irc, irc->accounts); + if (irc->accounts->gc == NULL) + account_del(irc, irc->accounts); + else + /* Nasty hack, but account_del() doesn't work in this + case and we don't want infinite loops, do we? ;-) */ + irc->accounts = irc->accounts->next; while (irc->set) set_del(&irc->set, irc->set->key); -- cgit v1.2.3 From 46af1074101f0354490ea3940f16d6f84467de0e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 17:34:19 +0000 Subject: Fixed uninitialized memory issue in bitlbee.c listen socket setup code. Fixes #230 and #183. --- bitlbee.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bitlbee.c b/bitlbee.c index 5870bbad..6a3625ee 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -68,6 +68,7 @@ int bitlbee_daemon_init() setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); #ifdef IPV6 + memset( &listen_addr6, 0, sizeof( listen_addr6 ) ); listen_addr6.sin6_family = AF_INET6; listen_addr6.sin6_port = htons( global.conf->port ); if( ( i = inet_pton( AF_INET6, ipv6_wrap( global.conf->iface ), &listen_addr6.sin6_addr ) ) != 1 ) @@ -75,6 +76,7 @@ int bitlbee_daemon_init() /* Forget about IPv6 in this function. */ use_ipv6 = 0; #endif + memset( &listen_addr, 0, sizeof( listen_addr ) ); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons( global.conf->port ); if( strcmp( global.conf->iface, "::" ) == 0 ) -- cgit v1.2.3 From 8de63c3fdfb532e85f7d93778e63032f7c84b631 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 17:37:54 +0000 Subject: AIX fixup. See #230. --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index c1243dcd..10775c6d 100755 --- a/configure +++ b/configure @@ -468,6 +468,9 @@ SunOS ) echo 'EFLAGS+=-lresolv -lnsl -lsocket' >> Makefile.settings echo 'STRIP=\# skip strip' >> Makefile.settings ;; +AIX ) + echo 'EFLAGS+=-Wl,-brtl' >> Makefile.settings +;; CYGWIN* ) echo 'Cygwin is not officially supported.' ;; -- cgit v1.2.3 From 0f4c1bb59f2c939cabddd02e226954a3cfa02a7b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 22:45:39 +0000 Subject: Added Jabber server port number restrictions. --- protocols/jabber/jabber.c | 11 ++++++++++- protocols/jabber/jabber.h | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index a60cd4aa..fa9c3473 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -36,7 +36,7 @@ static void jabber_acc_init( account_t *acc ) { set_t *s; - s = set_add( &acc->set, "port", "5222", set_eval_int, acc ); + s = set_add( &acc->set, "port", JABBER_PORT_DEFAULT, set_eval_int, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); @@ -160,6 +160,15 @@ static void jabber_login( account_t *acc ) set_login_progress( gc, 0, "Connecting" ); + if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN || + set_getint( &acc->set, "port" ) > JABBER_PORT_MAX ) + { + serv_got_crap( gc, "Incorrect port number, must be in the %d-%d range", + JABBER_PORT_MIN, JABBER_PORT_MAX ); + signoff( gc ); + return; + } + /* For non-SSL connections we can try to use the port # from the SRV reply, but let's not do that when using SSL, SSL usually runs on non-standard ports... */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 628cb03a..0a0f3c2c 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -51,6 +51,10 @@ typedef enum XEP85 (typing notification shite). */ } jabber_buddy_flags_t; +#define JABBER_PORT_DEFAULT "5222" +#define JABBER_PORT_MIN 5220 +#define JABBER_PORT_MAX 5229 + struct jabber_data { struct gaim_connection *gc; -- cgit v1.2.3 From 34337a71b8d8ad7d50fdf1152efbe5c3dde4bb90 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 22:46:21 +0000 Subject: Fixed a possible issue with corrupted .nicks files in text_load(). --- storage_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_text.c b/storage_text.c index 3a11facf..7c29d95a 100644 --- a/storage_text.c +++ b/storage_text.c @@ -97,7 +97,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i if( !fp ) return STORAGE_NO_SUCH_USER; while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) { - if( ( acc = acc_lookup[proto] ) == NULL ) + if( proto < 0 || proto > 8 || ( acc = acc_lookup[proto] ) == NULL ) continue; http_decode( s ); -- cgit v1.2.3 From dcf0f3e77ffd38ce3cc5d3c1eedfc655ff75a8f9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 22:46:50 +0000 Subject: Fixed Makefiles (make distclean was completely broken). --- Makefile | 2 +- doc/CHANGES | 2 +- tests/Makefile | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3044d9b2..27d420a8 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ clean: $(subdirs) distclean: clean $(subdirs) rm -f Makefile.settings config.h bitlbee.pc find . -name 'DEADJOE' -o -name '*.orig' -o -name '*.rej' -o -name '*~' -exec rm -f {} \; - $(MAKE) -C test distclean + $(MAKE) -C tests distclean check: all $(MAKE) -C tests diff --git a/doc/CHANGES b/doc/CHANGES index 567a8ae6..4c1d2ece 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,4 @@ -Version x.x: +Version 1.1: (1.1.x will be a (hopefully short) development release) - Added ForkDaemon mode next to the existing Daemon- and inetd modes. With ForkDaemon you can run BitlBee as a stand-alone daemon and every connection will run in its own process. No more need to configure inetd, and still you diff --git a/tests/Makefile b/tests/Makefile index 9dd3df7c..588bae61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,4 @@ -include ../Makefile.settings +-include ../Makefile.settings LFLAGS +=-lcheck @@ -8,6 +8,8 @@ all: check clean: rm -f check *.o +distclean: clean + main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o -- cgit v1.2.3 From 21782b3d081a3ac0d6c7c0e57736e4342b73779a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 22:52:48 +0000 Subject: Silencing some (hopefully) bogus warnings because too many people will be annoyed by them. --- protocols/jabber/presence.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index b56acb51..2e6b41ab 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -39,7 +39,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { if( !( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { - serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from ); + if( set_getbool( &gc->irc->set, "debug" ) ) + serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -71,7 +72,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { if( jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) == NULL ) { - serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); + if( set_getbool( &gc->irc->set, "debug" ) ) + serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } -- cgit v1.2.3 From d4589cb29dc06e68e9872316cfcd460c78e6aba3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 23:47:17 +0000 Subject: Little doc/help update. --- conf.c | 2 +- doc/CHANGES | 5 ++++- doc/README | 19 ++++++------------- doc/bitlbee.8 | 4 ++++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/conf.c b/conf.c index 24f6133b..09fd08e1 100644 --- a/conf.c +++ b/conf.c @@ -131,7 +131,7 @@ conf_t *conf_load( int argc, char *argv[] ) } else if( opt == 'h' ) { - printf( "Usage: bitlbee [-D [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n" + printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n" " [-c <file>] [-d <dir>] [-h]\n" "\n" "An IRC-to-other-chat-networks gateway\n" diff --git a/doc/CHANGES b/doc/CHANGES index 4c1d2ece..8e0fde42 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,7 @@ -Version 1.1: (1.1.x will be a (hopefully short) development release) +Version 1.1: +- First BitlBee development/testing RELEASE. This should be quite stable + though (and for most people more stable than 1.0.x). It just has a couple + of rough edges and needs a bit more testing. - Added ForkDaemon mode next to the existing Daemon- and inetd modes. With ForkDaemon you can run BitlBee as a stand-alone daemon and every connection will run in its own process. No more need to configure inetd, and still you diff --git a/doc/README b/doc/README index 75988004..bb6596ba 100644 --- a/doc/README +++ b/doc/README @@ -46,7 +46,7 @@ DEPENDENCIES ============ BitlBee's only real dependency is GLib. This is available on virtually every -platform. Any recent version of GLib (2.0 or higher) will work. +platform. Any recent version of GLib (2.4 or higher) will work. These days, MSN Messenger clients have to connect to the MS Passport servers through HTTPS. BitlBee can use several SSL libraries for this: GnuTLS, NSS @@ -183,17 +183,10 @@ LEGAL BitlBee is distributed under the GPL (GNU General Public License). See the file COPYING for this license. -Unfortunately some parts of the Gaim Jabber plugin (most notably the XML -code) were licensed under the MPL (Mozilla Public License) version 1.1. We -could not relicense this code under the GPL. As such it is still licensed -under the MPL. The parts of the code to which this applies are marked as -such. - -The MPL is provided in the file MPL-1.1.txt. This license is not GPL -compatible. It is however a free software license. - -Another part (the md5 algorithm) is licensed under the Aladdin license. -This license can be found in the files, to which this applies. +The MD5 algorithm code is licensed under the Aladdin license. This license +can be found in the files, to which this applies. The SHA1 algorithm code +is licensed under the Mozilla Public License, see http://www.mozilla.org/MPL/ +for details. The Yahoo! library used by BitlBee is libyahoo2 <http://libyahoo2.sf.net/>, also licensed under the GPL. @@ -201,5 +194,5 @@ also licensed under the GPL. BitlBee - An IRC to other chat networks gateway <http://www.bitlbee.org/> - Copyright (C) 2002-2006 Wilmer van der Gaast <wilmer@gaast.net> + Copyright (C) 2002-2007 Wilmer van der Gaast <wilmer@gaast.net> and others diff --git a/doc/bitlbee.8 b/doc/bitlbee.8 index 201e366e..ae1cfb05 100644 --- a/doc/bitlbee.8 +++ b/doc/bitlbee.8 @@ -62,6 +62,10 @@ option. Run in daemon mode. In this mode, BitlBee forks to the background and waits for new connections. All clients will be served from one process. This is still experimental. See the note above for more information. +.IP "-F" +Run in ForkDaemon mode. This is similar to ordinary daemon mode, but every +client gets its own process. Easier to set up than inetd mode, but without +the possible stability issues. .IP "-i \fIaddress\fP" Only useful when running in daemon mode, to specify the network interface (identified by IP address) to which the daemon should attach. Use this if -- cgit v1.2.3 From 6cfcfdf92b50719e8c08cc933879dae00a484215 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 23:48:02 +0000 Subject: Added the right version tag. --- bitlbee.h | 2 +- doc/CHANGES | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index f068aeac..f82f763a 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -29,7 +29,7 @@ #define _GNU_SOURCE /* Stupid GNU :-P */ #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "BZR" +#define BITLBEE_VERSION "1.1dev" #define VERSION BITLBEE_VERSION #define MAX_STRING 128 diff --git a/doc/CHANGES b/doc/CHANGES index 8e0fde42..8fb53608 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,4 @@ -Version 1.1: +Version 1.1dev: - First BitlBee development/testing RELEASE. This should be quite stable though (and for most people more stable than 1.0.x). It just has a couple of rough edges and needs a bit more testing. -- cgit v1.2.3 From b6423a0964c121edfb7a4318b1d909916d099d4d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 18 Feb 2007 23:57:12 +0000 Subject: Little fix copied from Jelmer's integration branch, want to import the rest after doing this devel release because there are quite a lot of changes in it. --- doc/CHANGES | 1 + lib/url.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/CHANGES b/doc/CHANGES index 8fb53608..3f509c46 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -21,6 +21,7 @@ Version 1.1dev: - Many, many, MANY little changes, improvements, fixes. Using non-blocking I/O as much as possible, fixed lots of little bugs (including bugs that affected daemon mode stability). See the bzr logs for more information. +- Added units tests, will have to add some more before the real release. - Most important change: New file format for user data (accounts, nicks and settings). Migration to the new format should happen transparently, BitlBee will read the old files and once you quit/save it will save in the diff --git a/lib/url.c b/lib/url.c index e4deac78..c6fdc4c8 100644 --- a/lib/url.c +++ b/lib/url.c @@ -99,7 +99,7 @@ int url_set( url_t *url, char *set_url ) url->port = 80; else if( url->proto == PROTO_HTTPS ) url->port = 443; - else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 ) + else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS5 ) url->port = 1080; } -- cgit v1.2.3 From 723e611603236aab794ffbbc312705b8309b3f81 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 26 Feb 2007 04:46:35 +0000 Subject: Removed boolean code from set_getint() and added bits of help to set.h. --- set.c | 3 --- set.h | 14 +++++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/set.c b/set.c index 8d872503..184c3243 100644 --- a/set.c +++ b/set.c @@ -91,9 +91,6 @@ int set_getint( set_t **head, char *key ) if( !s ) return 0; - if( ( g_strcasecmp( s, "true" ) == 0 ) || ( g_strcasecmp( s, "yes" ) == 0 ) || ( g_strcasecmp( s, "on" ) == 0 ) ) - return 1; - if( sscanf( s, "%d", &i ) != 1 ) return 0; diff --git a/set.h b/set.h index 37d2430f..fd03a396 100644 --- a/set.h +++ b/set.h @@ -31,7 +31,10 @@ remembers a default value for every setting. And to prevent the user from setting invalid values, you can write an evaluator function for every setting, which can check a new value and block it by returning - NULL, or replace it by returning a new value. See struct set.eval. */ + NULL, or replace it by returning a new value. See struct set.eval. + One thing that is really missing here is additional data for the + evaluator. This could be useful to add minimum and maximum values for + integers, for example. */ typedef char *(*set_eval) ( struct set *set, char *value ); @@ -45,7 +48,9 @@ typedef struct set char *def; /* Default value. If the set_setstr() function notices a new value is exactly the same as the default, value gets set to NULL. So when - you read a setting, don't forget about this! */ + you read a setting, don't forget about this! + In fact, you should only read values using + set_getstr/int(). */ int flags; /* See account.h, for example. set.c doesn't use this (yet?). */ @@ -67,9 +72,8 @@ set_t *set_find( set_t **head, char *key ); returned string, and don't free() it! */ G_MODULE_EXPORT char *set_getstr( set_t **head, char *key ); -/* Get an integer. Right now this also converts true/false/on/off/etc to - numbers, but this is for historical reasons, please use set_getbool() - for booleans instead. */ +/* Get an integer. In previous versions set_getint() was also used to read + boolean values, but this SHOULD be done with set_getbool() now! */ G_MODULE_EXPORT int set_getint( set_t **head, char *key ); G_MODULE_EXPORT int set_getbool( set_t **head, char *key ); -- cgit v1.2.3 From fa29d09342c79b886efacee4cfc3078be5f5a722 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 27 Mar 2007 22:53:11 -0700 Subject: Preparing for Jabber conference room support. --- irc.c | 8 ++++---- irc_commands.c | 10 +++++----- motd.txt | 2 +- protocols/msn/msn.c | 27 ++++++++++++------------- protocols/msn/msn.h | 4 ++-- protocols/msn/sb.c | 20 ++++++++++--------- protocols/nogaim.c | 48 +++++++++++++++++++-------------------------- protocols/nogaim.h | 48 +++++++++++++++++++++++---------------------- protocols/oscar/oscar.c | 52 ++++++++++++++----------------------------------- protocols/yahoo/yahoo.c | 38 ++++++++++++++---------------------- root_commands.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 158 insertions(+), 147 deletions(-) diff --git a/irc.c b/irc.c index eb4a395d..5551f559 100644 --- a/irc.c +++ b/irc.c @@ -658,7 +658,7 @@ void irc_names( irc_t *irc, char *channel ) strcat( namelist, " " ); } } - else if( ( c = conv_findchannel( channel ) ) ) + else if( ( c = chat_by_channel( channel ) ) ) { GList *l; @@ -811,7 +811,7 @@ void irc_topic( irc_t *irc, char *channel ) } else { - struct conversation *c = conv_findchannel( channel ); + struct conversation *c = chat_by_channel( channel ); if( c ) irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title ); @@ -949,7 +949,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) if( *nick == '#' || *nick == '&' ) { - if( !( c = conv_findchannel( nick ) ) ) + if( !( c = chat_by_channel( nick ) ) ) { irc_reply( irc, 403, "%s :Channel does not exist", nick ); return( 0 ); @@ -1037,7 +1037,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) } else if( c && c->gc && c->gc->acc && c->gc->acc->prpl ) { - return( bim_chat_msg( c->gc, c->id, s ) ); + return( bim_chat_msg( c, s ) ); } return( 0 ); diff --git a/irc_commands.c b/irc_commands.c index b1045c93..023bd0d4 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -143,7 +143,7 @@ static void irc_cmd_part( irc_t *irc, char **cmd ) irc_part( irc, u, irc->channel ); irc_join( irc, u, irc->channel ); } - else if( ( c = conv_findchannel( cmd[1] ) ) ) + else if( ( c = chat_by_channel( cmd[1] ) ) ) { user_t *u = user_find( irc, irc->nick ); @@ -152,7 +152,7 @@ static void irc_cmd_part( irc_t *irc, char **cmd ) if( c->gc ) { c->joined = 0; - c->gc->acc->prpl->chat_leave( c->gc, c->id ); + c->gc->acc->prpl->chat_leave( c ); } } else @@ -200,13 +200,13 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) static void irc_cmd_invite( irc_t *irc, char **cmd ) { char *nick = cmd[1], *channel = cmd[2]; - struct conversation *c = conv_findchannel( channel ); + struct conversation *c = chat_by_channel( channel ); user_t *u = user_find( irc, nick ); if( u && c && ( u->gc == c->gc ) ) if( c->gc && c->gc->acc->prpl->chat_invite ) { - c->gc->acc->prpl->chat_invite( c->gc, c->id, "", u->handle ); + c->gc->acc->prpl->chat_invite( c, "", u->handle ); irc_reply( irc, 341, "%s %s", nick, channel ); return; } @@ -286,7 +286,7 @@ static void irc_cmd_who( irc_t *irc, char **cmd ) irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); u = u->next; } - else if( ( c = conv_findchannel( channel ) ) ) + else if( ( c = chat_by_channel( channel ) ) ) for( l = c->in_room; l; l = l->next ) { if( ( u = user_findhandle( c->gc, l->data ) ) ) diff --git a/motd.txt b/motd.txt index cbf813f0..9e854d54 100644 --- a/motd.txt +++ b/motd.txt @@ -13,6 +13,6 @@ information. The developers of the Bee hope you have a buzzing time. -* BitlBee development team: wilmer, ctrlsoft, Maurits +* BitlBee development team: wilmer, jelmer, Maurits ... Buzzing, haha, get it? diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 663bff8c..a73d85d4 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -240,9 +240,9 @@ static void msn_remove_buddy( struct gaim_connection *gc, char *who, char *group msn_buddy_list_remove( gc, "FL", who ); } -static int msn_chat_send( struct gaim_connection *gc, int id, char *message ) +static int msn_chat_send( struct conversation *c, char *message ) { - struct msn_switchboard *sb = msn_sb_by_id( gc, id ); + struct msn_switchboard *sb = msn_sb_by_chat( c ); if( sb ) return( msn_sb_sendmessage( sb, message ) ); @@ -250,9 +250,9 @@ static int msn_chat_send( struct gaim_connection *gc, int id, char *message ) return( 0 ); } -static void msn_chat_invite( struct gaim_connection *gc, int id, char *msg, char *who ) +static void msn_chat_invite( struct conversation *c, char *msg, char *who ) { - struct msn_switchboard *sb = msn_sb_by_id( gc, id ); + struct msn_switchboard *sb = msn_sb_by_chat( c ); char buf[1024]; if( sb ) @@ -262,15 +262,15 @@ static void msn_chat_invite( struct gaim_connection *gc, int id, char *msg, char } } -static void msn_chat_leave( struct gaim_connection *gc, int id ) +static void msn_chat_leave( struct conversation *c ) { - struct msn_switchboard *sb = msn_sb_by_id( gc, id ); + struct msn_switchboard *sb = msn_sb_by_chat( c ); if( sb ) msn_sb_write( sb, "OUT\r\n", 5 ); } -static int msn_chat_open( struct gaim_connection *gc, char *who ) +static struct conversation *msn_chat_open( struct gaim_connection *gc, char *who ) { struct msn_switchboard *sb; struct msn_data *md = gc->proto_data; @@ -279,8 +279,7 @@ static int msn_chat_open( struct gaim_connection *gc, char *who ) if( ( sb = msn_sb_by_handle( gc, who ) ) ) { debug( "Converting existing switchboard to %s to a groupchat", who ); - msn_sb_to_chat( sb ); - return( 1 ); + return msn_sb_to_chat( sb ); } else { @@ -291,10 +290,7 @@ static int msn_chat_open( struct gaim_connection *gc, char *who ) debug( "Trying to reuse an existing switchboard as a groupchat with %s", who ); g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) - { - msn_sb_to_chat( sb ); - return( 1 ); - } + return msn_sb_to_chat( sb ); } /* If the stuff above failed for some reason: */ @@ -313,10 +309,11 @@ static int msn_chat_open( struct gaim_connection *gc, char *who ) /* Queue the magic message and cross your fingers. */ md->msgq = g_slist_append( md->msgq, m ); - return( 1 ); + /* FIXME: Can I try to return something here already? */ + return NULL; } - return( 0 ); + return NULL; } static void msn_keepalive( struct gaim_connection *gc ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index b4777d41..78cc3caf 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -168,9 +168,9 @@ const struct msn_status_code *msn_status_by_number( int number ); int msn_sb_write( struct msn_switchboard *sb, char *s, int len ); struct msn_switchboard *msn_sb_create( struct gaim_connection *gc, char *host, int port, char *key, int session ); struct msn_switchboard *msn_sb_by_handle( struct gaim_connection *gc, char *handle ); -struct msn_switchboard *msn_sb_by_id( struct gaim_connection *gc, int id ); +struct msn_switchboard *msn_sb_by_chat( struct conversation *c ); struct msn_switchboard *msn_sb_spare( struct gaim_connection *gc ); int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); -void msn_sb_to_chat( struct msn_switchboard *sb ); +struct conversation *msn_sb_to_chat( struct msn_switchboard *sb ); void msn_sb_destroy( struct msn_switchboard *sb ); gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 7ec340bd..8e912273 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -85,16 +85,16 @@ struct msn_switchboard *msn_sb_by_handle( struct gaim_connection *gc, char *hand return( NULL ); } -struct msn_switchboard *msn_sb_by_id( struct gaim_connection *gc, int id ) +struct msn_switchboard *msn_sb_by_chat( struct conversation *c ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = c->gc->proto_data; struct msn_switchboard *sb; GSList *l; for( l = md->switchboards; l; l = l->next ) { sb = l->data; - if( sb->chat && sb->chat->id == id ) + if( sb->chat == c ) return( sb ); } @@ -176,14 +176,14 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) } } -void msn_sb_to_chat( struct msn_switchboard *sb ) +struct conversation *msn_sb_to_chat( struct msn_switchboard *sb ) { struct gaim_connection *gc = sb->gc; char buf[1024]; /* Create the groupchat structure. */ g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( gc, ++msn_chat_id, buf ); + sb->chat = serv_got_joined_chat( gc, buf ); /* Populate the channel. */ if( sb->who ) add_chat_buddy( sb->chat, sb->who ); @@ -195,6 +195,8 @@ void msn_sb_to_chat( struct msn_switchboard *sb ) g_free( sb->who ); sb->who = NULL; } + + return sb->chat; } void msn_sb_destroy( struct msn_switchboard *sb ) @@ -229,7 +231,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) if( sb->chat ) { - serv_got_chat_left( gc, sb->chat->id ); + serv_got_chat_left( sb->chat ); } if( sb->handler ) @@ -371,7 +373,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( num == 1 ) { g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( gc, ++msn_chat_id, buf ); + sb->chat = serv_got_joined_chat( gc, buf ); g_free( sb->who ); sb->who = NULL; @@ -609,7 +611,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int } else if( sb->chat ) { - serv_got_chat_in( gc, sb->chat->id, cmd[1], 0, body, 0 ); + serv_got_chat_in( sb->chat, cmd[1], 0, body, 0 ); } else { @@ -668,7 +670,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int } else if( sb->chat ) { - serv_got_chat_in( gc, sb->chat->id, cmd[1], 0, buf, 0 ); + serv_got_chat_in( sb->chat, cmd[1], 0, buf, 0 ); } else { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index b627a23a..e983352f 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -681,15 +681,14 @@ void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int } } -void serv_got_chat_left( struct gaim_connection *gc, int id ) +void serv_got_chat_left( struct conversation *c ) { - struct conversation *c, *l = NULL; + struct gaim_connection *gc = c->gc; + struct conversation *l = NULL; GList *ir; if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "You were removed from conversation %d", (int) id ); - - for( c = gc->conversations; c && c->id != id; c = (l=c)->next ); + serv_got_crap( gc, "You were removed from conversation 0x%x", (int) c ); if( c ) { @@ -719,9 +718,9 @@ void serv_got_chat_left( struct gaim_connection *gc, int id ) } } -void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whisper, char *msg, time_t mtime ) +void serv_got_chat_in( struct conversation *c, char *who, int whisper, char *msg, time_t mtime ) { - struct conversation *c; + struct gaim_connection *gc = c->gc; user_t *u; /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ @@ -729,7 +728,6 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe return; u = user_findhandle( gc, who ); - for( c = gc->conversations; c && c->id != id; c = c->next ); if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) @@ -738,13 +736,12 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe if( c && u ) irc_privmsg( gc->irc, u, "PRIVMSG", c->channel, "", msg ); else - serv_got_crap( gc, "Message from/to conversation %s@%d (unknown conv/user): %s", who, id, msg ); + serv_got_crap( gc, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); } -struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, char *handle ) +struct conversation *serv_got_joined_chat( struct gaim_connection *gc, char *handle ) { struct conversation *c; - char *s; /* This one just creates the conversation structure, user won't see anything yet */ @@ -754,21 +751,16 @@ struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, c c = c->next = g_new0( struct conversation, 1 ); } else - gc->conversations = c = g_new0( struct conversation, 1); + gc->conversations = c = g_new0( struct conversation, 1 ); - c->id = id; c->gc = gc; c->title = g_strdup( handle ); - - s = g_new( char, 16 ); - sprintf( s, "&chat_%03d", gc->irc->c_id++ ); - c->channel = g_strdup( s ); - g_free( s ); + c->channel = g_strdup_printf( "&chat_%03d", gc->irc->c_id++ ); if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "Creating new conversation: (id=%d,handle=%s)", id, handle ); + serv_got_crap( gc, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); - return( c ); + return c; } @@ -780,7 +772,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) int me = 0; if( set_getbool( &b->gc->irc->set, "debug" ) ) - serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); + serv_got_crap( b->gc, "User %s added to conversation 0x%x", handle, (int) b ); /* It might be yourself! */ if( b->gc->acc->prpl->handle_cmp( handle, b->gc->username ) == 0 ) @@ -814,7 +806,7 @@ void remove_chat_buddy( struct conversation *b, char *handle, char *reason ) int me = 0; if( set_getbool( &b->gc->irc->set, "debug" ) ) - serv_got_crap( b->gc, "User %s removed from conversation %d (%s)", handle, b->id, reason ? reason : "" ); + serv_got_crap( b->gc, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); /* It might be yourself! */ if( g_strcasecmp( handle, b->gc->username ) == 0 ) @@ -857,7 +849,7 @@ static int remove_chat_buddy_silent( struct conversation *b, char *handle ) /* Misc. BitlBee stuff which shouldn't really be here */ -struct conversation *conv_findchannel( char *channel ) +struct conversation *chat_by_channel( char *channel ) { struct gaim_connection *gc; struct conversation *c; @@ -869,10 +861,10 @@ struct conversation *conv_findchannel( char *channel ) gc = l->data; for( c = gc->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); if( c ) - return( c ); + return c; } - return( NULL ); + return NULL; } char *set_eval_away_devoice( set_t *set, char *value ) @@ -957,18 +949,18 @@ int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flag return st; } -int bim_chat_msg( struct gaim_connection *gc, int id, char *msg ) +int bim_chat_msg( struct conversation *c, char *msg ) { char *buf = NULL; int st; - if( ( gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) + if( ( c->gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { buf = escape_html( msg ); msg = buf; } - st = gc->acc->prpl->chat_send( gc, id, msg ); + st = c->gc->acc->prpl->chat_send( c, msg ); g_free( buf ); return st; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index bae4489f..6afa1801 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -99,26 +99,25 @@ struct conversation { struct gaim_connection *gc; /* stuff used just for chat */ - GList *in_room; - GList *ignored; - int id; - - /* BitlBee */ - struct conversation *next; - char *channel; - char *title; - char joined; - void *data; + GList *in_room; + GList *ignored; + + /* BitlBee */ + struct conversation *next; + char *channel; + char *title; + char joined; + void *data; }; struct buddy { char name[80]; char show[BUDDY_ALIAS_MAXLEN]; - int present; + int present; int evil; time_t signon; time_t idle; - int uc; + int uc; guint caps; /* woohoo! */ void *proto_data; /* what a hack */ struct gaim_connection *gc; /* the connection it belongs to */ @@ -152,11 +151,13 @@ struct prpl { void (* alias_buddy) (struct gaim_connection *, char *who); /* save/store buddy's alias on server list/roster */ /* Group chat stuff. */ - void (* join_chat) (struct gaim_connection *, GList *data); - void (* chat_invite) (struct gaim_connection *, int id, char *who, char *message); - void (* chat_leave) (struct gaim_connection *, int id); - int (* chat_send) (struct gaim_connection *, int id, char *message); - int (* chat_open) (struct gaim_connection *, char *who); + void (* chat_invite) (struct conversation *, char *who, char *message); + void (* chat_leave) (struct conversation *); + int (* chat_send) (struct conversation *, char *message); + struct conversation * + (* chat_open) (struct gaim_connection *, char *who); + struct conversation * + (* chat_join) (struct gaim_connection *, char *chat, char *nick, char *password); /* DIE! */ char *(* get_status_string) (struct gaim_connection *gc, int stat); @@ -182,7 +183,7 @@ G_MODULE_EXPORT void register_protocol(struct prpl *); /* nogaim.c */ int bim_set_away( struct gaim_connection *gc, char *away ); int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flags ); -int bim_chat_msg( struct gaim_connection *gc, int id, char *msg ); +int bim_chat_msg( struct conversation *c, char *msg ); void bim_add_allow( struct gaim_connection *gc, char *handle ); void bim_rem_allow( struct gaim_connection *gc, char *handle ); @@ -223,15 +224,16 @@ G_MODULE_EXPORT void remove_chat_buddy( struct conversation *b, char *handle, ch /* prpl.c */ G_MODULE_EXPORT void show_got_added( struct gaim_connection *gc, char *handle, const char *realname ); -/* server.c */ +/* server.c */ G_MODULE_EXPORT void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); G_MODULE_EXPORT void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); G_MODULE_EXPORT void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int type ); G_MODULE_EXPORT void serv_got_chat_invite( struct gaim_connection *gc, char *handle, char *who, char *msg, GList *data ); -G_MODULE_EXPORT struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, char *handle ); -G_MODULE_EXPORT void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whisper, char *msg, time_t mtime ); -G_MODULE_EXPORT void serv_got_chat_left( struct gaim_connection *gc, int id ); +G_MODULE_EXPORT struct conversation *serv_got_joined_chat( struct gaim_connection *gc, char *handle ); +G_MODULE_EXPORT void serv_got_chat_in( struct conversation *c, char *who, int whisper, char *msg, time_t mtime ); +G_MODULE_EXPORT void serv_got_chat_left( struct conversation *c ); -struct conversation *conv_findchannel( char *channel ); +struct conversation *chat_by_channel( char *channel ); +struct conversation *chat_by_id( int id ); #endif diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 72078b3c..05539442 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -157,22 +157,6 @@ static char *extract_name(const char *name) { return tmp; } -static struct chat_connection *find_oscar_chat(struct gaim_connection *gc, int id) { - GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; - struct chat_connection *c = NULL; - - while (g) { - c = (struct chat_connection *)g->data; - if (c->id == id) - break; - g = g->next; - c = NULL; - } - - return c; -} - - static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, aim_conn_t *conn) { GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; @@ -768,7 +752,8 @@ static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { chatcon = find_oscar_chat_by_conn(gc, fr->conn); chatcon->id = id; - chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show); + chatcon->cnv = serv_got_joined_chat(gc, chatcon->show); + chatcon->cnv->data = chatcon; return 1; } @@ -1579,7 +1564,7 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) { tmp = g_malloc(BUF_LONG); g_snprintf(tmp, BUF_LONG, "%s", msg); - serv_got_chat_in(gc, ccon->id, info->sn, 0, tmp, time((time_t)NULL)); + serv_got_chat_in(ccon->cnv, info->sn, 0, tmp, time((time_t)NULL)); g_free(tmp); return 1; @@ -2520,8 +2505,9 @@ int oscar_send_typing(struct gaim_connection *gc, char * who, int typing) return( aim_im_sendmtn(od->sess, 1, who, typing ? 0x0002 : 0x0000) ); } -int oscar_chat_send(struct gaim_connection * gc, int id, char *message) +int oscar_chat_send(struct conversation *c, char *message) { + struct gaim_connection *gc = c->gc; struct oscar_data * od = (struct oscar_data*)gc->proto_data; struct chat_connection * ccon; int ret; @@ -2529,8 +2515,7 @@ int oscar_chat_send(struct gaim_connection * gc, int id, char *message) guint16 flags; char *s; - if(!(ccon = find_oscar_chat(gc, id))) - return -1; + ccon = c->data; for (s = message; *s; s++) if (*s & 128) @@ -2567,13 +2552,11 @@ int oscar_chat_send(struct gaim_connection * gc, int id, char *message) return (ret >= 0); } -void oscar_chat_invite(struct gaim_connection * gc, int id, char *message, char *who) +void oscar_chat_invite(struct conversation *c, char *message, char *who) { + struct gaim_connection *gc = c->gc; struct oscar_data * od = (struct oscar_data *)gc->proto_data; - struct chat_connection *ccon = find_oscar_chat(gc, id); - - if (ccon == NULL) - return; + struct chat_connection *ccon = c->data; aim_chat_invite(od->sess, od->conn, who, message ? message : "", ccon->exchange, ccon->name, 0x0); @@ -2584,7 +2567,7 @@ void oscar_chat_kill(struct gaim_connection *gc, struct chat_connection *cc) struct oscar_data *od = (struct oscar_data *)gc->proto_data; /* Notify the conversation window that we've left the chat */ - serv_got_chat_left(gc, cc->id); + serv_got_chat_left(cc->cnv); /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); @@ -2596,19 +2579,14 @@ void oscar_chat_kill(struct gaim_connection *gc, struct chat_connection *cc) g_free(cc); } -void oscar_chat_leave(struct gaim_connection * gc, int id) +void oscar_chat_leave(struct conversation *c) { - struct chat_connection * ccon = find_oscar_chat(gc, id); - - if(ccon == NULL) - return; - - oscar_chat_kill(gc, ccon); + oscar_chat_kill(c->gc, c->data); } int oscar_chat_join(struct gaim_connection * gc, char * name) { - struct oscar_data * od = (struct oscar_data *)gc->proto_data; + struct oscar_data * od = (struct oscar_data *)gc->proto_data; aim_conn_t * cur; @@ -2626,7 +2604,7 @@ int oscar_chat_join(struct gaim_connection * gc, char * name) } } -int oscar_chat_open(struct gaim_connection * gc, char *who) +struct conversation *oscar_chat_open(struct gaim_connection * gc, char *who) { struct oscar_data * od = (struct oscar_data *)gc->proto_data; int ret; @@ -2641,7 +2619,7 @@ int oscar_chat_open(struct gaim_connection * gc, char *who) g_free(chatname); - return ret; + return NULL; } void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 6f286196..e0dcabff 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -139,7 +139,7 @@ static void byahoo_close( struct gaim_connection *gc ) GSList *l; while( gc->conversations ) - serv_got_chat_left( gc, gc->conversations->id ); + serv_got_chat_left( gc->conversations ); for( l = yd->buddygroups; l; l = l->next ) { @@ -331,40 +331,31 @@ static char *byahoo_get_status_string( struct gaim_connection *gc, int stat ) } } -static int byahoo_chat_send( struct gaim_connection *gc, int id, char *message ) +static int byahoo_chat_send( struct conversation *c, char *message ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; - struct conversation *c; + struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; - for( c = gc->conversations; c && c->id != id; c = c->next ); - yahoo_conference_message( yd->y2_id, NULL, c->data, c->title, message, 1 ); return( 0 ); } -static void byahoo_chat_invite( struct gaim_connection *gc, int id, char *msg, char *who ) +static void byahoo_chat_invite( struct conversation *c, char *msg, char *who ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; - struct conversation *c; - - for( c = gc->conversations; c && c->id != id; c = c->next ); + struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ); } -static void byahoo_chat_leave( struct gaim_connection *gc, int id ) +static void byahoo_chat_leave( struct conversation *c ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; - struct conversation *c; - - for( c = gc->conversations; c && c->id != id; c = c->next ); + struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); - serv_got_chat_left( gc, c->id ); + serv_got_chat_left( c ); } -static int byahoo_chat_open( struct gaim_connection *gc, char *who ) +static struct conversation *byahoo_chat_open( struct gaim_connection *gc, char *who ) { struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; struct conversation *c; @@ -374,7 +365,7 @@ static int byahoo_chat_open( struct gaim_connection *gc, char *who ) roomname = g_new0( char, strlen( gc->username ) + 16 ); g_snprintf( roomname, strlen( gc->username ) + 16, "%s-Bee-%d", gc->username, byahoo_chat_id ); - c = serv_got_joined_chat( gc, ++byahoo_chat_id, roomname ); + c = serv_got_joined_chat( gc, roomname ); add_chat_buddy( c, gc->username ); /* FIXME: Free this thing when the chat's destroyed. We can't *always* @@ -386,7 +377,7 @@ static int byahoo_chat_open( struct gaim_connection *gc, char *who ) g_free( roomname ); - return( 1 ); + return c; } void byahoo_init( ) @@ -804,7 +795,7 @@ static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); - serv_got_chat_left( inv->gc, inv->c->id ); + serv_got_chat_left( inv->c ); g_free( inv->name ); g_free( inv ); } @@ -819,7 +810,7 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList inv = g_malloc( sizeof( struct byahoo_conf_invitation ) ); memset( inv, 0, sizeof( struct byahoo_conf_invitation ) ); inv->name = g_strdup( room ); - inv->c = serv_got_joined_chat( gc, ++byahoo_chat_id, room ); + inv->c = serv_got_joined_chat( gc, room ); inv->c->data = members; inv->yid = id; inv->members = members; @@ -871,7 +862,8 @@ void ext_yahoo_conf_message( int id, char *who, char *room, char *msg, int utf8 for( c = gc->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); - serv_got_chat_in( gc, c ? c->id : 0, who, 0, m, 0 ); + if( c ) + serv_got_chat_in( c, who, 0, m, 0 ); g_free( m ); } diff --git a/root_commands.c b/root_commands.c index 116f1d06..ff2d8b37 100644 --- a/root_commands.c +++ b/root_commands.c @@ -884,6 +884,53 @@ static void cmd_qlist( irc_t *irc, char **cmd ) irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } +static void cmd_join_chat( irc_t *irc, char **cmd ) +{ + account_t *a; + struct gaim_connection *gc; + char *chat, *channel, *nick = NULL, *password = NULL; + struct conversation *c; + + if( !( a = account_get( irc, cmd[1] ) ) ) + { + irc_usermsg( irc, "Invalid account" ); + return; + } + else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + { + irc_usermsg( irc, "That account is not on-line" ); + return; + } + else if( a->prpl->chat_join == NULL ) + { + irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); + return; + } + gc = a->gc; + + chat = cmd[2]; + if( cmd[3] ) + { + channel = g_strdup( cmd[3] ); + } + else + { + char *s; + + channel = g_strdup( chat ); + if( ( s = strchr( channel, '@' ) ) ) + *s = 0; + } + if( cmd[3] && cmd[4] ) + nick = cmd[4]; + if( cmd[3] && cmd[4] && cmd[5] ) + password = cmd[5]; + + c = a->prpl->chat_join( gc, chat, nick, password ); + + g_free( channel ); +} + const command_t commands[] = { { "help", 0, cmd_help, 0 }, { "identify", 1, cmd_identify, 0 }, @@ -903,5 +950,6 @@ const command_t commands[] = { { "blist", 0, cmd_blist, 0 }, { "nick", 1, cmd_nick, 0 }, { "qlist", 0, cmd_qlist, 0 }, + { "join_chat", 2, cmd_join_chat, 0 }, { NULL } }; -- cgit v1.2.3 From 0da65d5fb37691ed4d31f7ab4058732f1440db6b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 30 Mar 2007 22:40:45 -0700 Subject: s/gaim_connection/im_connection/ and some other minor API changes. The rest will come tomorrow. It compiles, I'll leave the real testing up to someone else. ;-) --- account.c | 16 +- account.h | 2 +- irc.c | 42 ++-- irc_commands.c | 36 ++-- protocols/jabber/io.c | 154 +++++++------- protocols/jabber/iq.c | 136 ++++++------ protocols/jabber/jabber.c | 92 ++++---- protocols/jabber/jabber.h | 46 ++-- protocols/jabber/jabber_util.c | 54 ++--- protocols/jabber/message.c | 12 +- protocols/jabber/presence.c | 40 ++-- protocols/jabber/sasl.c | 48 ++--- protocols/msn/msn.c | 144 ++++++------- protocols/msn/msn.h | 26 +-- protocols/msn/msn_util.c | 40 ++-- protocols/msn/ns.c | 224 ++++++++++---------- protocols/msn/sb.c | 68 +++--- protocols/nogaim.c | 428 ++++++++++++++++++------------------- protocols/nogaim.h | 148 ++++++------- protocols/oscar/aim.h | 2 +- protocols/oscar/im.c | 4 +- protocols/oscar/oscar.c | 464 ++++++++++++++++++++--------------------- protocols/oscar/service.c | 4 +- protocols/yahoo/yahoo.c | 215 ++++++++++--------- query.c | 18 +- query.h | 6 +- root_commands.c | 120 +++++------ user.c | 12 +- user.h | 4 +- 29 files changed, 1306 insertions(+), 1299 deletions(-) diff --git a/account.c b/account.c index 95aa9b7c..03d05586 100644 --- a/account.c +++ b/account.c @@ -64,8 +64,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) /* This function adds some more settings (and might want to do more things that have to be done now, although I can't think of anything. */ - if( prpl->acc_init ) - prpl->acc_init( a ); + if( prpl->init ) + prpl->init( a ); return( a ); } @@ -75,7 +75,7 @@ char *set_eval_account( set_t *set, char *value ) account_t *acc = set->data; /* Double-check: We refuse to edit on-line accounts. */ - if( set->flags & ACC_SET_OFFLINE_ONLY && acc->gc ) + if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic ) return NULL; if( strcmp( set->key, "username" ) == 0 ) @@ -179,7 +179,7 @@ void account_del( irc_t *irc, account_t *acc ) for( a = irc->accounts; a; a = (l=a)->next ) if( a == acc ) { - if( a->gc ) return; /* Caller should have checked, accounts still in use can't be deleted. */ + if( a->ic ) return; /* Caller should have checked, accounts still in use can't be deleted. */ if( l ) { @@ -208,7 +208,7 @@ void account_del( irc_t *irc, account_t *acc ) void account_on( irc_t *irc, account_t *a ) { - if( a->gc ) + if( a->ic ) { /* Trying to enable an already-enabled account */ return; @@ -222,9 +222,9 @@ void account_on( irc_t *irc, account_t *a ) void account_off( irc_t *irc, account_t *a ) { - a->gc->wants_to_die = TRUE; - signoff( a->gc ); - a->gc = NULL; + a->ic->wants_to_die = TRUE; + signoff( a->ic ); + a->ic = NULL; if( a->reconnect ) { /* Shouldn't happen */ diff --git a/account.h b/account.h index 83f47a89..a81ca928 100644 --- a/account.h +++ b/account.h @@ -40,7 +40,7 @@ typedef struct account GHashTable *nicks; struct irc *irc; - struct gaim_connection *gc; + struct im_connection *ic; struct account *next; } account_t; diff --git a/irc.c b/irc.c index 5551f559..b1cae1d9 100644 --- a/irc.c +++ b/irc.c @@ -229,9 +229,9 @@ void irc_free(irc_t * irc) irc_connection_list = g_slist_remove( irc_connection_list, irc ); for (account = irc->accounts; account; account = account->next) { - if (account->gc) { - account->gc->wants_to_die = TRUE; - signoff(account->gc); + if (account->ic) { + account->ic->wants_to_die = TRUE; + signoff(account->ic); } else if (account->reconnect) { cancel_auto_reconnect(account); } @@ -255,7 +255,7 @@ void irc_free(irc_t * irc) query_del(irc, irc->queries); while (irc->accounts) - if (irc->accounts->gc == NULL) + if (irc->accounts->ic == NULL) account_del(irc, irc->accounts); else /* Nasty hack, but account_del() doesn't work in this @@ -632,7 +632,7 @@ void irc_names( irc_t *irc, char *channel ) { user_t *u; char namelist[385] = ""; - struct conversation *c = NULL; + struct groupchat *c = NULL; char *ops = set_getstr( &irc->set, "ops" ); /* RFCs say there is no error reply allowed on NAMES, so when the @@ -648,7 +648,7 @@ void irc_names( irc_t *irc, char *channel ) *namelist = 0; } - if( u->gc && !u->away && set_getbool( &irc->set, "away_devoice" ) ) + if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) ) strcat( namelist, "+" ); else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) || ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ) @@ -667,7 +667,7 @@ void irc_names( irc_t *irc, char *channel ) sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick, strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick ); - for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->gc, l->data ) ) ) + for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) ) { if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) { @@ -811,7 +811,7 @@ void irc_topic( irc_t *irc, char *channel ) } else { - struct conversation *c = chat_by_channel( channel ); + struct groupchat *c = chat_by_channel( channel ); if( c ) irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title ); @@ -910,17 +910,17 @@ void irc_kill( irc_t *irc, user_t *u ) char *nick, *s; char reason[128]; - if( u->gc && u->gc->flags & OPT_LOGGING_OUT ) + if( u->ic && u->ic->flags & OPT_LOGGING_OUT ) { - if( u->gc->acc->server ) + if( u->ic->acc->server ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, - u->gc->acc->server ); - else if( ( s = strchr( u->gc->username, '@' ) ) ) + u->ic->acc->server ); + else if( ( s = strchr( u->ic->username, '@' ) ) ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, s + 1 ); else g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost, - u->gc->acc->prpl->name, irc->myhost ); + u->ic->acc->prpl->name, irc->myhost ); /* proto_opt might contain garbage after the : */ if( ( s = strchr( reason, ':' ) ) ) @@ -944,7 +944,7 @@ void irc_kill( irc_t *irc, user_t *u ) int irc_send( irc_t *irc, char *nick, char *s, int flags ) { - struct conversation *c = NULL; + struct groupchat *c = NULL; user_t *u = NULL; if( *nick == '#' || *nick == '&' ) @@ -996,13 +996,13 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) } else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 ) { - if( u && u->gc && u->gc->acc->prpl->send_typing && strlen( s ) >= 10 ) + if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 ) { time_t current_typing_notice = time( NULL ); if( current_typing_notice - u->last_typing_notice >= 5 ) { - u->gc->acc->prpl->send_typing( u->gc, u->handle, s[8] == '1' ); + u->ic->acc->prpl->send_typing( u->ic, u->handle, s[8] == '1' ); u->last_typing_notice = current_typing_notice; } } @@ -1035,9 +1035,9 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) return 1; } } - else if( c && c->gc && c->gc->acc && c->gc->acc->prpl ) + else if( c && c->ic && c->ic->acc && c->ic->acc->prpl ) { - return( bim_chat_msg( c, s ) ); + return( bim_chat_msg( c, s, 0 ) ); } return( 0 ); @@ -1052,7 +1052,7 @@ static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_cond return FALSE; u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */ - bim_buddy_msg( u->gc, u->handle, u->sendbuf, u->sendbuf_flags ); + bim_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); g_free( u->sendbuf ); u->sendbuf = NULL; @@ -1065,7 +1065,7 @@ static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_cond void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) { - if( !u || !u->gc ) return; + if( !u || !u->ic ) return; if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 ) { @@ -1104,7 +1104,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) } else { - bim_buddy_msg( u->gc, u->handle, msg, flags ); + bim_buddy_msg( u->ic, u->handle, msg, flags ); } } diff --git a/irc_commands.c b/irc_commands.c index 023bd0d4..d65cf720 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -133,7 +133,7 @@ static void irc_cmd_names( irc_t *irc, char **cmd ) static void irc_cmd_part( irc_t *irc, char **cmd ) { - struct conversation *c; + struct groupchat *c; if( g_strcasecmp( cmd[1], irc->channel ) == 0 ) { @@ -149,10 +149,10 @@ static void irc_cmd_part( irc_t *irc, char **cmd ) irc_part( irc, u, c->channel ); - if( c->gc ) + if( c->ic ) { c->joined = 0; - c->gc->acc->prpl->chat_leave( c ); + c->ic->acc->prpl->chat_leave( c ); } } else @@ -172,11 +172,11 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) { user_t *u = user_find( irc, cmd[1] + 1 ); - if( u && u->gc && u->gc->acc->prpl->chat_open ) + if( u && u->ic && u->ic->acc->prpl->chat_with ) { irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] ); - if( !u->gc->acc->prpl->chat_open( u->gc, u->handle ) ) + if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) ) { irc_usermsg( irc, "Could not open a groupchat with %s.", u->nick ); } @@ -200,13 +200,13 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) static void irc_cmd_invite( irc_t *irc, char **cmd ) { char *nick = cmd[1], *channel = cmd[2]; - struct conversation *c = chat_by_channel( channel ); + struct groupchat *c = chat_by_channel( channel ); user_t *u = user_find( irc, nick ); - if( u && c && ( u->gc == c->gc ) ) - if( c->gc && c->gc->acc->prpl->chat_invite ) + if( u && c && ( u->ic == c->ic ) ) + if( c->ic && c->ic->acc->prpl->chat_invite ) { - c->gc->acc->prpl->chat_invite( c, "", u->handle ); + c->ic->acc->prpl->chat_invite( c, "", u->handle ); irc_reply( irc, 341, "%s %s", nick, channel ); return; } @@ -270,7 +270,7 @@ static void irc_cmd_who( irc_t *irc, char **cmd ) { char *channel = cmd[1]; user_t *u = irc->users; - struct conversation *c; + struct groupchat *c; GList *l; if( !channel || *channel == '0' || *channel == '*' || !*channel ) @@ -289,7 +289,7 @@ static void irc_cmd_who( irc_t *irc, char **cmd ) else if( ( c = chat_by_channel( channel ) ) ) for( l = c->in_room; l; l = l->next ) { - if( ( u = user_findhandle( c->gc, l->data ) ) ) + if( ( u = user_findhandle( c->ic, l->data ) ) ) irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); } else if( ( u = user_find( irc, channel ) ) ) @@ -459,10 +459,10 @@ static void irc_cmd_away( irc_t *irc, char **cmd ) for( a = irc->accounts; a; a = a->next ) { - struct gaim_connection *gc = a->gc; + struct im_connection *ic = a->ic; - if( gc && gc->flags & OPT_LOGGED_IN ) - bim_set_away( gc, u->away ); + if( ic && ic->flags & OPT_LOGGED_IN ) + bim_set_away( ic, u->away ); } } @@ -475,10 +475,10 @@ static void irc_cmd_whois( irc_t *irc, char **cmd ) { irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname ); - if( u->gc ) - irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->acc->user, - u->gc->acc->server && *u->gc->acc->server ? u->gc->acc->server : "", - u->gc->acc->prpl->name ); + if( u->ic ) + irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user, + u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "", + u->ic->acc->prpl->name ); else irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index f05cc93d..6e699301 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -25,23 +25,23 @@ #include "ssl_client.h" static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ); -static gboolean jabber_write_queue( struct gaim_connection *gc ); +static gboolean jabber_write_queue( struct im_connection *ic ); -int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ) +int jabber_write_packet( struct im_connection *ic, struct xt_node *node ) { char *buf; int st; buf = xt_to_string( node ); - st = jabber_write( gc, buf, strlen( buf ) ); + st = jabber_write( ic, buf, strlen( buf ) ); g_free( buf ); return st; } -int jabber_write( struct gaim_connection *gc, char *buf, int len ) +int jabber_write( struct im_connection *ic, char *buf, int len ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; gboolean ret; if( jd->tx_len == 0 ) @@ -53,8 +53,8 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) /* Try if we can write it immediately so we don't have to do it via the event handler. If not, add the handler. (In most cases it probably won't be necessary.) */ - if( ( ret = jabber_write_queue( gc ) ) && jd->tx_len > 0 ) - jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, gc ); + if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 ) + jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, ic ); } else { @@ -84,16 +84,16 @@ int jabber_write( struct gaim_connection *gc, char *buf, int len ) the socket is ready for more data). */ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ) { - struct jabber_data *jd = ((struct gaim_connection *)data)->proto_data; + struct jabber_data *jd = ((struct im_connection *)data)->proto_data; return jd->fd != -1 && jabber_write_queue( data ) && jd->tx_len > 0; } -static gboolean jabber_write_queue( struct gaim_connection *gc ) +static gboolean jabber_write_queue( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; int st; if( jd->ssl ) @@ -116,8 +116,8 @@ static gboolean jabber_write_queue( struct gaim_connection *gc ) closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ jd->fd = -1; - hide_login_progress_error( gc, "Short write() to server" ); - signoff( gc ); + hide_login_progress_error( ic, "Short write() to server" ); + signoff( ic ); return FALSE; } else if( st > 0 ) @@ -141,8 +141,8 @@ static gboolean jabber_write_queue( struct gaim_connection *gc ) static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; char buf[512]; int st; @@ -159,8 +159,8 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition /* Parse. */ if( xt_feed( jd->xt, buf, st ) < 0 ) { - hide_login_progress_error( gc, "XML stream error" ); - signoff( gc ); + hide_login_progress_error( ic, "XML stream error" ); + signoff( ic ); return FALSE; } @@ -175,7 +175,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( jd->flags & JFLAG_STREAM_RESTART ) { jd->flags &= ~JFLAG_STREAM_RESTART; - jabber_start_stream( gc ); + jabber_start_stream( ic ); } /* Garbage collection. */ @@ -195,28 +195,28 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition /* If there's no version attribute, assume this is an old server that can't do SASL authentication. */ - if( !sasl_supported( gc ) ) + if( !sasl_supported( ic ) ) { /* If there's no version= tag, we suppose this server does NOT implement: XMPP 1.0, SASL and TLS. */ - if( set_getbool( &gc->acc->set, "tls" ) ) + if( set_getbool( &ic->acc->set, "tls" ) ) { - hide_login_progress( gc, "TLS is turned on for this " + hide_login_progress( ic, "TLS is turned on for this " "account, but is not supported by this server" ); - signoff( gc ); + signoff( ic ); return FALSE; } else { - return jabber_init_iq_auth( gc ); + return jabber_init_iq_auth( ic ); } } } else { - hide_login_progress( gc, "XML stream error" ); - signoff( gc ); + hide_login_progress( ic, "XML stream error" ); + signoff( ic ); return FALSE; } } @@ -226,8 +226,8 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition closesocket( jd->fd ); jd->fd = -1; - hide_login_progress_error( gc, "Error while reading from server" ); - signoff( gc ); + hide_login_progress_error( ic, "Error while reading from server" ); + signoff( ic ); return FALSE; } @@ -237,24 +237,24 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; if( source == -1 ) { - hide_login_progress( gc, "Could not connect to server" ); - signoff( gc ); + hide_login_progress( ic, "Could not connect to server" ); + signoff( ic ); return FALSE; } - set_login_progress( gc, 1, "Connected to server, logging in" ); + set_login_progress( ic, 1, "Connected to server, logging in" ); - return jabber_start_stream( gc ); + return jabber_start_stream( ic ); } gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; if( source == NULL ) { @@ -262,14 +262,14 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co already, set it to NULL here to prevent a double cleanup: */ jd->ssl = NULL; - hide_login_progress( gc, "Could not connect to server" ); - signoff( gc ); + hide_login_progress( ic, "Could not connect to server" ); + signoff( ic ); return FALSE; } - set_login_progress( gc, 1, "Connected to server, logging in" ); + set_login_progress( ic, 1, "Connected to server, logging in" ); - return jabber_start_stream( gc ); + return jabber_start_stream( ic ); } static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) @@ -280,12 +280,12 @@ static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply; int trytls; - trytls = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0; + trytls = g_strcasecmp( set_getstr( &ic->acc->set, "tls" ), "try" ) == 0; c = xt_find_node( node->children, "starttls" ); if( c && !jd->ssl ) { @@ -294,20 +294,20 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) c = xt_find_node( c->children, "required" ); - if( c && ( !trytls && !set_getbool( &gc->acc->set, "tls" ) ) ) + if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) ) { - hide_login_progress( gc, "Server requires TLS connections, but TLS is turned off for this account" ); - signoff( gc ); + hide_login_progress( ic, "Server requires TLS connections, but TLS is turned off for this account" ); + signoff( ic ); return XT_ABORT; } /* Only run this if the tls setting is set to true or try: */ - if( ( trytls || set_getbool( &gc->acc->set, "tls" ) ) ) + if( ( trytls || set_getbool( &ic->acc->set, "tls" ) ) ) { reply = xt_new_node( "starttls", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_TLS ); - if( !jabber_write_packet( gc, reply ) ) + if( !jabber_write_packet( ic, reply ) ) { xt_free_node( reply ); return XT_ABORT; @@ -324,10 +324,10 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) habit of not advertising <starttls/> anymore when already using SSL/TLS. */ - if( !trytls && set_getbool( &gc->acc->set, "tls" ) ) + if( !trytls && set_getbool( &ic->acc->set, "tls" ) ) { - hide_login_progress( gc, "TLS is turned on for this account, but is not supported by this server" ); - signoff( gc ); + hide_login_progress( ic, "TLS is turned on for this account, but is not supported by this server" ); + signoff( ic ); return XT_ABORT; } @@ -345,20 +345,20 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) support it after all, we should try to do authentication the other way. jabber.com doesn't seem to do SASL while it pretends to be XMPP 1.0 compliant! */ - else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) ) + else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( ic ) ) { - if( !jabber_init_iq_auth( gc ) ) + if( !jabber_init_iq_auth( ic ) ) return XT_ABORT; } if( ( c = xt_find_node( node->children, "bind" ) ) ) { - reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); xt_add_attr( reply, "xmlns", XMLNS_BIND ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); + jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); - if( !jabber_write_packet( gc, reply ) ) + if( !jabber_write_packet( ic, reply ) ) return XT_ABORT; jd->flags |= JFLAG_WAIT_BIND; @@ -369,9 +369,9 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) reply = xt_new_node( "session", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_SESSION ); reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); + jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); - if( !jabber_write_packet( gc, reply ) ) + if( !jabber_write_packet( ic, reply ) ) return XT_ABORT; jd->flags |= JFLAG_WAIT_SESSION; @@ -382,7 +382,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) to bind/initialize the session. */ if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( ic ) ) return XT_ABORT; } @@ -391,8 +391,8 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; char *xmlns; xmlns = xt_find_attr( node, "xmlns" ); @@ -416,16 +416,16 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) } jd->w_inpa = jd->r_inpa = 0; - set_login_progress( gc, 1, "Converting stream to TLS" ); + set_login_progress( ic, 1, "Converting stream to TLS" ); - jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, gc ); + jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic ); return XT_HANDLED; } static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct xt_node *c; char *s, *type = NULL, *text = NULL; @@ -451,8 +451,8 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) /* Tssk... */ if( type == NULL ) { - hide_login_progress_error( gc, "Unknown stream error reported by server" ); - signoff( gc ); + hide_login_progress_error( ic, "Unknown stream error reported by server" ); + signoff( ic ); return XT_ABORT; } @@ -461,17 +461,17 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) infinite loop! */ if( strcmp( type, "conflict" ) == 0 ) { - hide_login_progress( gc, "Account and resource used from a different location" ); - gc->wants_to_die = TRUE; + hide_login_progress( ic, "Account and resource used from a different location" ); + ic->wants_to_die = TRUE; } else { s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); - hide_login_progress_error( gc, s ); + hide_login_progress_error( ic, s ); g_free( s ); } - signoff( gc ); + signoff( ic ); return XT_ABORT; } @@ -499,35 +499,35 @@ static const struct xt_handler_entry jabber_handlers[] = { { NULL, NULL, NULL } }; -gboolean jabber_start_stream( struct gaim_connection *gc ) +gboolean jabber_start_stream( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; int st; char *greet; /* We'll start our stream now, so prepare everything to receive one from the server too. */ xt_free( jd->xt ); /* In case we're RE-starting. */ - jd->xt = xt_new( gc ); + jd->xt = xt_new( ic ); jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; if( jd->r_inpa <= 0 ) - jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc ); + jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); greet = g_strdup_printf( "<?xml version='1.0' ?>" "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server ); - st = jabber_write( gc, greet, strlen( greet ) ); + st = jabber_write( ic, greet, strlen( greet ) ); g_free( greet ); return st; } -void jabber_end_stream( struct gaim_connection *gc ) +void jabber_end_stream( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; /* Let's only do this if the queue is currently empty, otherwise it'd take too long anyway. */ @@ -537,14 +537,14 @@ void jabber_end_stream( struct gaim_connection *gc ) struct xt_node *node; int st = 1; - if( gc->flags & OPT_LOGGED_IN ) + if( ic->flags & OPT_LOGGED_IN ) { node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); } if( st ) - jabber_write( gc, eos, strlen( eos ) ); + jabber_write( ic, eos, strlen( eos ) ); } } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 914dd02b..86d97e15 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -23,13 +23,13 @@ #include "jabber.h" -static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); -static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *type, *s; int st, pack = 1; @@ -38,8 +38,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !type ) { - hide_login_progress_error( gc, "Received IQ packet without type." ); - signoff( gc ); + hide_login_progress_error( ic, "Received IQ packet without type." ); + signoff( ic ); return XT_ABORT; } @@ -59,16 +59,16 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) entry = g_hash_table_lookup( jd->node_cache, s ); if( entry == NULL ) - serv_got_crap( gc, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); + serv_got_crap( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); else if( entry->func ) - return entry->func( gc, node, entry->node ); + return entry->func( ic, node, entry->node ); } else if( strcmp( type, "get" ) == 0 ) { if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type ); + serv_got_crap( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -131,7 +131,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - serv_got_crap( gc, "WARNING: Received incomplete IQ-%s packet", type ); + serv_got_crap( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -140,20 +140,20 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) sent even if we added this buddy in our own session. */ if( strcmp( s, XMLNS_ROSTER ) == 0 ) { - int bare_len = strlen( gc->acc->user ); + int bare_len = strlen( ic->acc->user ); if( ( s = xt_find_attr( node, "from" ) ) == NULL || - ( strncmp( s, gc->acc->user, bare_len ) == 0 && + ( strncmp( s, ic->acc->user, bare_len ) == 0 && ( s[bare_len] == 0 || s[bare_len] == '/' ) ) ) { - jabber_parse_roster( gc, node, NULL ); + jabber_parse_roster( ic, node, NULL ); /* Should we generate a reply here? Don't think it's very important... */ } else { - serv_got_crap( gc, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); + serv_got_crap( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -181,7 +181,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) xt_add_attr( reply, "id", s ); } - st = jabber_write_packet( gc, reply ); + st = jabber_write_packet( ic, reply ); xt_free_node( reply ); if( !st ) return XT_ABORT; @@ -190,12 +190,12 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) return XT_HANDLED; } -static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); -static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -int jabber_init_iq_auth( struct gaim_connection *gc ) +int jabber_init_iq_auth( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct xt_node *node; int st; @@ -203,23 +203,23 @@ int jabber_init_iq_auth( struct gaim_connection *gc ) xt_add_attr( node, "xmlns", XMLNS_AUTH ); node = jabber_make_packet( "iq", "get", NULL, node ); - jabber_cache_add( gc, node, jabber_do_iq_auth ); - st = jabber_write_packet( gc, node ); + jabber_cache_add( ic, node, jabber_do_iq_auth ); + st = jabber_write_packet( ic, node ); return st; } -static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct xt_node *reply, *query; xt_status st; char *s; if( !( query = xt_find_node( node->children, "query" ) ) ) { - serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" ); - signoff( gc ); + serv_got_crap( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + signoff( ic ); return XT_HANDLED; } @@ -227,7 +227,7 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * reply = xt_new_node( "query", NULL, NULL ); xt_add_attr( reply, "xmlns", XMLNS_AUTH ); xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); - xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); + xt_add_child( reply, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) { @@ -240,7 +240,7 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * shaInit( &sha ); shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); - shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); + shaUpdate( &sha, (unsigned char*) ic->acc->pass, strlen( ic->acc->pass ) ); shaFinal( &sha, hash ); for( i = 0; i < 20; i ++ ) @@ -251,40 +251,40 @@ static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node * else if( xt_find_node( query->children, "password" ) ) { /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ - xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); + xt_add_child( reply, xt_new_node( "password", ic->acc->pass, NULL ) ); } else { xt_free_node( reply ); - hide_login_progress( gc, "Can't find suitable authentication method" ); - signoff( gc ); + hide_login_progress( ic, "Can't find suitable authentication method" ); + signoff( ic ); return XT_ABORT; } reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( gc, reply, jabber_finish_iq_auth ); - st = jabber_write_packet( gc, reply ); + jabber_cache_add( ic, reply, jabber_finish_iq_auth ); + st = jabber_write_packet( ic, reply ); return st ? XT_HANDLED : XT_ABORT; } -static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; char *type; if( !( type = xt_find_attr( node, "type" ) ) ) { - serv_got_crap( gc, "WARNING: Received incomplete IQ packet while authenticating" ); - signoff( gc ); + serv_got_crap( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + signoff( ic ); return XT_HANDLED; } if( strcmp( type, "error" ) == 0 ) { - hide_login_progress( gc, "Authentication failure" ); - signoff( gc ); + hide_login_progress( ic, "Authentication failure" ); + signoff( ic ); return XT_ABORT; } else if( strcmp( type, "result" ) == 0 ) @@ -292,16 +292,16 @@ static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_no /* This happens when we just successfully authenticated the old (non-SASL) way. */ jd->flags |= JFLAG_AUTHENTICATED; - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( ic ) ) return XT_ABORT; } return XT_HANDLED; } -xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct xt_node *c; char *s; @@ -309,8 +309,8 @@ xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node { c = xt_find_node( c->children, "jid" ); if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && - strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) - serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); + strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 ) + serv_got_crap( ic, "Server changed session resource string to `%s'", s + 1 ); jd->flags &= ~JFLAG_WAIT_BIND; } @@ -321,38 +321,38 @@ xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) { - if( !jabber_get_roster( gc ) ) + if( !jabber_get_roster( ic ) ) return XT_ABORT; } return XT_HANDLED; } -int jabber_get_roster( struct gaim_connection *gc ) +int jabber_get_roster( struct im_connection *ic ) { struct xt_node *node; int st; - set_login_progress( gc, 1, "Authenticated, requesting buddy list" ); + set_login_progress( ic, 1, "Authenticated, requesting buddy list" ); node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "get", NULL, node ); - jabber_cache_add( gc, node, jabber_parse_roster ); - st = jabber_write_packet( gc, node ); + jabber_cache_add( ic, node, jabber_parse_roster ); + st = jabber_write_packet( ic, node ); return st; } -static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct xt_node *query, *c; int initial = ( orig != NULL ); if( !( query = xt_find_node( node->children, "query" ) ) ) { - serv_got_crap( gc, "WARNING: Received NULL roster packet" ); + serv_got_crap( ic, "WARNING: Received NULL roster packet" ); return XT_HANDLED; } @@ -370,24 +370,24 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node else if( initial ) { if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) - add_buddy( gc, NULL, jid, name ); + add_buddy( ic, NULL, jid, name ); } else { /* This is a roster push item. Find out what changed exactly. */ if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) { - if( find_buddy( gc, jid ) == NULL ) - add_buddy( gc, NULL, jid, name ); + if( find_buddy( ic, jid ) == NULL ) + add_buddy( ic, NULL, jid, name ); else if( name ) - serv_buddy_rename( gc, jid, name ); + serv_buddy_rename( ic, jid, name ); } else if( strcmp( sub, "remove" ) == 0 ) { /* Don't have any API call for this yet! So let's just try to handle this as well as we can. */ - jabber_buddy_remove_bare( gc, jid ); - serv_got_update( gc, jid, 0, 0, 0, 0, 0, 0 ); + jabber_buddy_remove_bare( ic, jid ); + serv_got_update( ic, jid, 0, 0, 0, 0, 0, 0 ); /* FIXME! */ } } @@ -396,12 +396,12 @@ static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node } if( initial ) - account_online( gc ); + account_online( ic ); return XT_HANDLED; } -int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ) +int jabber_get_vcard( struct im_connection *ic, char *bare_jid ) { struct xt_node *node; @@ -412,13 +412,13 @@ int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ) xt_add_attr( node, "xmlns", XMLNS_VCARD ); node = jabber_make_packet( "iq", "get", bare_jid, node ); - jabber_cache_add( gc, node, jabber_iq_display_vcard ); - return jabber_write_packet( gc, node ); + jabber_cache_add( ic, node, jabber_iq_display_vcard ); + return jabber_write_packet( ic, node ); } -static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { - struct xt_node *vc, *c, *sc; /* subchild, gc is already in use ;-) */ + struct xt_node *vc, *c, *sc; /* subchild, ic is already in use ;-) */ GString *reply; char *s; @@ -427,7 +427,7 @@ static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_ ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) { s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ - serv_got_crap( gc, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); + serv_got_crap( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); return XT_HANDLED; } @@ -535,13 +535,13 @@ static xt_status jabber_iq_display_vcard( struct gaim_connection *gc, struct xt_ /* *sigh* */ - serv_got_crap( gc, reply->str ); + serv_got_crap( ic, reply->str ); g_string_free( reply, TRUE ); return XT_HANDLED; } -int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) +int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ) { struct xt_node *node; int st; @@ -557,13 +557,13 @@ int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ) xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; } -int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) +int jabber_remove_from_roster( struct im_connection *ic, char *handle ) { struct xt_node *node; int st; @@ -578,7 +578,7 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ) xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index fa9c3473..23de1103 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -32,7 +32,7 @@ #include "bitlbee.h" #include "jabber.h" -static void jabber_acc_init( account_t *acc ) +static void jabber_init( account_t *acc ) { set_t *s; @@ -58,21 +58,21 @@ static void jabber_acc_init( account_t *acc ) static void jabber_login( account_t *acc ) { - struct gaim_connection *gc = new_gaim_conn( acc ); + struct im_connection *ic = new_gaim_conn( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); struct ns_srv_reply *srv = NULL; char *connect_to, *s; - jd->gc = gc; - gc->proto_data = jd; + jd->ic = ic; + ic->proto_data = jd; jd->username = g_strdup( acc->user ); jd->server = strchr( jd->username, '@' ); if( jd->server == NULL ) { - hide_login_progress( gc, "Incomplete account name (format it like <username@jabberserver.name>)" ); - signoff( gc ); + hide_login_progress( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); + signoff( ic ); return; } @@ -158,14 +158,14 @@ static void jabber_login( account_t *acc ) else connect_to = jd->server; - set_login_progress( gc, 0, "Connecting" ); + set_login_progress( ic, 0, "Connecting" ); if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN || set_getint( &acc->set, "port" ) > JABBER_PORT_MAX ) { - serv_got_crap( gc, "Incorrect port number, must be in the %d-%d range", + serv_got_crap( ic, "Incorrect port number, must be in the %d-%d range", JABBER_PORT_MIN, JABBER_PORT_MAX ); - signoff( gc ); + signoff( ic ); return; } @@ -174,27 +174,27 @@ static void jabber_login( account_t *acc ) non-standard ports... */ if( set_getbool( &acc->set, "ssl" ) ) { - jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); + jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, ic ); jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1; } else { - jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); + jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic ); } g_free( srv ); if( jd->fd == -1 ) { - hide_login_progress( gc, "Could not connect to server" ); - signoff( gc ); + hide_login_progress( ic, "Could not connect to server" ); + signoff( ic ); } } -static void jabber_close( struct gaim_connection *gc ) +static void jabber_logout( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; - jabber_end_stream( gc ); + jabber_end_stream( ic ); if( jd->r_inpa >= 0 ) b_event_remove( jd->r_inpa ); @@ -218,14 +218,14 @@ static void jabber_close( struct gaim_connection *gc ) g_free( jd ); } -static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) +static int jabber_send_im( struct im_connection *ic, char *who, char *message, int flags ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; struct xt_node *node; int st; - bud = jabber_buddy_by_jid( gc, who, 0 ); + bud = jabber_buddy_by_jid( ic, who, 0 ); node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); @@ -250,13 +250,13 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message, bud->flags |= JBFLAG_PROBED_XEP85; } - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; } -static GList *jabber_away_states( struct gaim_connection *gc ) +static GList *jabber_away_states( struct im_connection *ic ) { static GList *l = NULL; int i; @@ -268,13 +268,13 @@ static GList *jabber_away_states( struct gaim_connection *gc ) return l; } -static void jabber_get_info( struct gaim_connection *gc, char *who ) +static void jabber_get_info( struct im_connection *ic, char *who ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; if( strchr( who, '/' ) ) - bud = jabber_buddy_by_jid( gc, who, 0 ); + bud = jabber_buddy_by_jid( ic, who, 0 ); else { char *s = jabber_normalize( who ); @@ -284,19 +284,19 @@ static void jabber_get_info( struct gaim_connection *gc, char *who ) while( bud ) { - serv_got_crap( gc, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", + serv_got_crap( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", bud->full_jid, bud->priority, bud->away_state ? bud->away_state->full_name : "(none)", bud->away_message ? : "(none)" ); bud = bud->next; } - jabber_get_vcard( gc, bud ? bud->full_jid : who ); + jabber_get_vcard( ic, bud ? bud->full_jid : who ); } -static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char *message ) +static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_away_state *state; /* Save all this info. We need it, for example, when changing the priority setting. */ @@ -305,43 +305,43 @@ static void jabber_set_away( struct gaim_connection *gc, char *state_txt, char * g_free( jd->away_message ); jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; - presence_send_update( gc ); + presence_send_update( ic ); } -static void jabber_add_buddy( struct gaim_connection *gc, char *who ) +static void jabber_add_buddy( struct im_connection *ic, char *who, char *group ) { - if( jabber_add_to_roster( gc, who, NULL ) ) - presence_send_request( gc, who, "subscribe" ); + if( jabber_add_to_roster( ic, who, NULL ) ) + presence_send_request( ic, who, "subscribe" ); } -static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group ) +static void jabber_remove_buddy( struct im_connection *ic, char *who, char *group ) { /* We should always do this part. Clean up our administration a little bit. */ - jabber_buddy_remove_bare( gc, who ); + jabber_buddy_remove_bare( ic, who ); - if( jabber_remove_from_roster( gc, who ) ) - presence_send_request( gc, who, "unsubscribe" ); + if( jabber_remove_from_roster( ic, who ) ) + presence_send_request( ic, who, "unsubscribe" ); } -static void jabber_keepalive( struct gaim_connection *gc ) +static void jabber_keepalive( struct im_connection *ic ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ - jabber_write( gc, "\n", 1 ); + jabber_write( ic, "\n", 1 ); /* This runs the garbage collection every minute, which means every packet is in the cache for about a minute (which should be enough AFAIK). */ - jabber_cache_clean( gc ); + jabber_cache_clean( ic ); } -static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing ) +static int jabber_send_typing( struct im_connection *ic, char *who, int typing ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; /* Enable typing notification related code from now. */ jd->flags |= JFLAG_WANT_TYPING; - if( ( bud = jabber_buddy_by_jid( gc, who, 0 ) ) == NULL ) + if( ( bud = jabber_buddy_by_jid( ic, who, 0 ) ) == NULL ) { /* Sending typing notifications to unknown buddies is unsupported for now. Shouldn't be a problem, I think. */ @@ -368,7 +368,7 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing xt_add_attr( node, "xmlns", XMLNS_CHATSTATES ); node = jabber_make_packet( "message", "chat", bud->full_jid, node ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; @@ -377,14 +377,14 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing return 1; } -void jabber_init() +void jabber_initmodule() { struct prpl *ret = g_new0( struct prpl, 1 ); ret->name = "jabber"; ret->login = jabber_login; - ret->acc_init = jabber_acc_init; - ret->close = jabber_close; + ret->init = jabber_init; + ret->logout = jabber_logout; ret->send_im = jabber_send_im; ret->away_states = jabber_away_states; // ret->get_status_string = jabber_get_status_string; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 0a0f3c2c..42f57ae1 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -57,7 +57,7 @@ typedef enum struct jabber_data { - struct gaim_connection *gc; + struct im_connection *ic; int fd; void *ssl; @@ -86,7 +86,7 @@ struct jabber_away_state char *full_name; }; -typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); +typedef xt_status (*jabber_cache_event) ( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); struct jabber_cache_entry { @@ -136,33 +136,33 @@ struct jabber_buddy /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); -int jabber_init_iq_auth( struct gaim_connection *gc ); -xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); -int jabber_get_roster( struct gaim_connection *gc ); -int jabber_get_vcard( struct gaim_connection *gc, char *bare_jid ); -int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); -int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); +int jabber_init_iq_auth( struct im_connection *ic ); +xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +int jabber_get_roster( struct im_connection *ic ); +int jabber_get_vcard( struct im_connection *ic, char *bare_jid ); +int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ); +int jabber_remove_from_roster( struct im_connection *ic, char *handle ); /* message.c */ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); /* presence.c */ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); -int presence_send_update( struct gaim_connection *gc ); -int presence_send_request( struct gaim_connection *gc, char *handle, char *request ); +int presence_send_update( struct im_connection *ic ); +int presence_send_request( struct im_connection *ic, char *handle, char *request ); /* jabber_util.c */ char *set_eval_priority( set_t *set, char *value ); char *set_eval_tls( set_t *set, char *value ); struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type ); -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ); -struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); +void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ); +struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); void jabber_cache_entry_free( gpointer entry ); -void jabber_cache_clean( struct gaim_connection *gc ); +void jabber_cache_clean( struct im_connection *ic ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); -void jabber_buddy_ask( struct gaim_connection *gc, char *handle ); +void jabber_buddy_ask( struct im_connection *ic, char *handle ); char *jabber_normalize( char *orig ); typedef enum @@ -171,25 +171,25 @@ typedef enum GET_BUDDY_EXACT = 2, /* Get an exact message (only makes sense with bare JIDs). */ } get_buddy_flags_t; -struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid ); -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid, get_buddy_flags_t flags ); -int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ); -int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ); +struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); +struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); +int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); +int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); extern const struct jabber_away_state jabber_away_state_list[]; /* io.c */ -int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); -int jabber_write( struct gaim_connection *gc, char *buf, int len ); +int jabber_write_packet( struct im_connection *ic, struct xt_node *node ); +int jabber_write( struct im_connection *ic, char *buf, int len ); gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ); -gboolean jabber_start_stream( struct gaim_connection *gc ); -void jabber_end_stream( struct gaim_connection *gc ); +gboolean jabber_start_stream( struct im_connection *ic ); +void jabber_end_stream( struct im_connection *ic ); /* sasl.c */ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ); xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); -gboolean sasl_supported( struct gaim_connection *gc ); +gboolean sasl_supported( struct im_connection *ic ); #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 4ca0c1fc..cc237b03 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -41,7 +41,7 @@ char *set_eval_priority( set_t *set, char *value ) /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ - if( acc->gc ) + if( acc->ic ) { /* Although set_eval functions usually are very nice and convenient, they have one disadvantage: If I would just @@ -57,7 +57,7 @@ char *set_eval_priority( set_t *set, char *value ) /* (Yes, sorry, I prefer the hack. :-P) */ - presence_send_update( acc->gc ); + presence_send_update( acc->ic ); } return value; @@ -129,9 +129,9 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get a new id= tag, and do NOT free() the packet after writing it! */ -void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) +void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); @@ -158,9 +158,9 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpo during the first run and deleting marked nodes during a next run, every node should be available in the cache for at least a minute (assuming the function is indeed called every minute). */ -void jabber_cache_clean( struct gaim_connection *gc ) +void jabber_cache_clean( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); } @@ -213,17 +213,17 @@ const struct jabber_away_state *jabber_away_state_by_name( char *name ) struct jabber_buddy_ask_data { - struct gaim_connection *gc; + struct im_connection *ic; char *handle; char *realname; }; static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla ) { - presence_send_request( bla->gc, bla->handle, "subscribed" ); + presence_send_request( bla->ic, bla->handle, "subscribed" ); - if( find_buddy( bla->gc, bla->handle ) == NULL ) - show_got_added( bla->gc, bla->handle, NULL ); + if( find_buddy( bla->ic, bla->handle ) == NULL ) + show_got_added( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla ); @@ -231,22 +231,22 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla ) { - presence_send_request( bla->gc, bla->handle, "subscribed" ); + presence_send_request( bla->ic, bla->handle, "subscribed" ); g_free( bla->handle ); g_free( bla ); } -void jabber_buddy_ask( struct gaim_connection *gc, char *handle ) +void jabber_buddy_ask( struct im_connection *ic, char *handle ) { struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 ); char *buf; - bla->gc = gc; + bla->ic = ic; bla->handle = g_strdup( handle ); buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); - do_ask_dialog( gc, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + do_ask_dialog( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } @@ -270,9 +270,9 @@ char *jabber_normalize( char *orig ) buddies from transports don't (usually) have resources. So we'll really have to deal with that properly. Set their ->resource property to NULL. Do *NOT* allow to mix this stuff, though... */ -struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid_ ) +struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *new, *bi; char *s, *full_jid; @@ -342,9 +342,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji /* Finds a buddy from our structures. Can find both full- and bare JIDs. When asked for a bare JID, it uses the "resource_select" setting to see which resource to pick. */ -struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_, get_buddy_flags_t flags ) +struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; char *s, *jid; @@ -370,10 +370,10 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ } } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid ) ) { *s = '/'; - bud = jabber_buddy_add( gc, jid ); + bud = jabber_buddy_add( ic, jid ); } g_free( jid ); @@ -390,8 +390,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( gc, jid_ ) ) ? - jabber_buddy_add( gc, jid_ ) : NULL; + return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid_ ) ) ? + jabber_buddy_add( ic, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ return NULL; @@ -408,7 +408,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ best_time = bud; } - if( ( set = set_getstr( &gc->acc->set, "resource_select" ) ) == NULL ) + if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL ) return NULL; else if( strcmp( set, "activity" ) == 0 ) return best_time; @@ -420,9 +420,9 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid_ /* Remove one specific full JID from our list. Use this when a buddy goes off-line (because (s)he can still be online from a different location. XXX: See above, we should accept bare JIDs too... */ -int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) +int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *prev, *bi; char *s, *full_jid; @@ -494,9 +494,9 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid_ ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid_ ) +int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *next; char *bare_jid; diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index ac72f661..6c105d1d 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -25,7 +25,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); struct xt_node *body = xt_find_node( node->children, "body" ), *c; @@ -46,7 +46,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( ( s = strchr( from, '/' ) ) ) { - if( ( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) ) ) + if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) ) bud->last_act = time( NULL ); else *s = 0; /* We need to generate a bare JID now. */ @@ -75,7 +75,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) fullmsg = g_string_append( fullmsg, body->text ); if( fullmsg->len > 0 ) - serv_got_im( gc, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len ); + serv_got_im( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len ); g_string_free( fullmsg, TRUE ); @@ -83,18 +83,18 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( xt_find_node( node->children, "composing" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 1 ); + serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 1 ); } /* No need to send a "stopped typing" signal when there's a message. */ else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 0 ); + serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 0 ); } else if( xt_find_node( node->children, "paused" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( gc, bud ? bud->bare_jid : from, 0, 2 ); + serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 2 ); } if( s ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 2e6b41ab..2db32fd1 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -25,7 +25,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; @@ -37,10 +37,10 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( type == NULL ) { - if( !( bud = jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) + if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { - if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "WARNING: Could not handle presence information from JID: %s", from ); + if( set_getbool( &ic->irc->set, "debug" ) ) + serv_got_crap( ic, "WARNING: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -65,19 +65,19 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; - serv_got_update( gc, bud->bare_jid, 1, 0, 0, 0, + serv_got_update( ic, bud->bare_jid, 1, 0, 0, 0, bud->away_state ? UC_UNAVAILABLE : 0, 0 ); } else if( strcmp( type, "unavailable" ) == 0 ) { - if( jabber_buddy_by_jid( gc, from, GET_BUDDY_EXACT ) == NULL ) + if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL ) { - if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); + if( set_getbool( &ic->irc->set, "debug" ) ) + serv_got_crap( ic, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } - jabber_buddy_remove( gc, from ); + jabber_buddy_remove( ic, from ); if( ( s = strchr( from, '/' ) ) ) { @@ -85,24 +85,24 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* Only count this as offline if there's no other resource available anymore. */ - if( jabber_buddy_by_jid( gc, from, 0 ) == NULL ) - serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + if( jabber_buddy_by_jid( ic, from, 0 ) == NULL ) + serv_got_update( ic, from, 0, 0, 0, 0, 0, 0 ); *s = '/'; } else { - serv_got_update( gc, from, 0, 0, 0, 0, 0, 0 ); + serv_got_update( ic, from, 0, 0, 0, 0, 0, 0 ); } } else if( strcmp( type, "subscribe" ) == 0 ) { - jabber_buddy_ask( gc, from ); + jabber_buddy_ask( ic, from ); } else if( strcmp( type, "subscribed" ) == 0 ) { /* Not sure about this one, actually... */ - serv_got_crap( gc, "%s just accepted your authorization request", from ); + serv_got_crap( ic, "%s just accepted your authorization request", from ); } else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) { @@ -130,29 +130,29 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* Whenever presence information is updated, call this function to inform the server. */ -int presence_send_update( struct gaim_connection *gc ) +int presence_send_update( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; struct xt_node *node; char *show = jd->away_state->code; char *status = jd->away_message; int st; node = jabber_make_packet( "presence", NULL, NULL, NULL ); - xt_add_child( node, xt_new_node( "priority", set_getstr( &gc->acc->set, "priority" ), NULL ) ); + xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) ); if( show && *show ) xt_add_child( node, xt_new_node( "show", show, NULL ) ); if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; } /* Send a subscribe/unsubscribe request to a buddy. */ -int presence_send_request( struct gaim_connection *gc, char *handle, char *request ) +int presence_send_request( struct im_connection *ic, char *handle, char *request ) { struct xt_node *node; int st; @@ -161,7 +161,7 @@ int presence_send_request( struct gaim_connection *gc, char *handle, char *reque xt_add_attr( node, "to", handle ); xt_add_attr( node, "type", request ); - st = jabber_write_packet( gc, node ); + st = jabber_write_packet( ic, node ); xt_free_node( node ); return st; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 68953ced..4943f59e 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -26,25 +26,25 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply; char *s; int sup_plain = 0, sup_digest = 0; - if( !sasl_supported( gc ) ) + if( !sasl_supported( ic ) ) { /* Should abort this now, since we should already be doing IQ authentication. Strange things happen when you try to do both... */ - serv_got_crap( gc, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); + serv_got_crap( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); return XT_HANDLED; } s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - signoff( gc ); + signoff( ic ); return XT_ABORT; } @@ -61,8 +61,8 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) if( !sup_plain && !sup_digest ) { - hide_login_progress( gc, "No known SASL authentication schemes supported" ); - signoff( gc ); + hide_login_progress( ic, "No known SASL authentication schemes supported" ); + signoff( ic ); return XT_ABORT; } @@ -82,17 +82,17 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) xt_add_attr( reply, "mechanism", "PLAIN" ); /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ - len = strlen( jd->username ) + strlen( gc->acc->pass ) + 2; + len = strlen( jd->username ) + strlen( ic->acc->pass ) + 2; s = g_malloc( len + 1 ); s[0] = 0; strcpy( s + 1, jd->username ); - strcpy( s + 2 + strlen( jd->username ), gc->acc->pass ); + strcpy( s + 2 + strlen( jd->username ), ic->acc->pass ); reply->text = base64_encode( s, len ); reply->text_len = strlen( reply->text ); g_free( s ); } - if( !jabber_write_packet( gc, reply ) ) + if( !jabber_write_packet( ic, reply ) ) { xt_free_node( reply ); return XT_ABORT; @@ -180,8 +180,8 @@ static char *sasl_get_part( char *data, char *field ) xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; struct xt_node *reply = NULL; char *nonce = NULL, *realm = NULL, *cnonce = NULL, cnonce_bin[30]; char *digest_uri = NULL; @@ -221,7 +221,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) /* Generate the MD5 hash of username:realm:password, I decided to call it H. */ md5_init( &H ); - s = g_strdup_printf( "%s:%s:%s", jd->username, realm, gc->acc->pass ); + s = g_strdup_printf( "%s:%s:%s", jd->username, realm, ic->acc->pass ); md5_append( &H, (unsigned char *) s, strlen( s ) ); g_free( s ); md5_finish( &H, Hr ); @@ -271,15 +271,15 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) reply = xt_new_node( "response", s, NULL ); xt_add_attr( reply, "xmlns", XMLNS_SASL ); - if( !jabber_write_packet( gc, reply ) ) + if( !jabber_write_packet( ic, reply ) ) goto silent_error; ret = XT_HANDLED; goto silent_error; error: - hide_login_progress( gc, "Incorrect SASL challenge received" ); - signoff( gc ); + hide_login_progress( ic, "Incorrect SASL challenge received" ); + signoff( ic ); silent_error: g_free( digest_uri ); @@ -295,26 +295,26 @@ silent_error: xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) { - struct gaim_connection *gc = data; - struct jabber_data *jd = gc->proto_data; + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; char *s; s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - signoff( gc ); + signoff( ic ); return XT_ABORT; } if( strcmp( node->name, "success" ) == 0 ) { - set_login_progress( gc, 1, "Authentication finished" ); + set_login_progress( ic, 1, "Authentication finished" ); jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; } else if( strcmp( node->name, "failure" ) == 0 ) { - hide_login_progress( gc, "Authentication failure" ); - signoff( gc ); + hide_login_progress( ic, "Authentication failure" ); + signoff( ic ); return XT_ABORT; } @@ -324,9 +324,9 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) /* This one is needed to judge if we'll do authentication using IQ or SASL. It's done by checking if the <stream:stream> from the server has a version attribute. I don't know if this is the right way though... */ -gboolean sasl_supported( struct gaim_connection *gc ) +gboolean sasl_supported( struct im_connection *ic ) { - struct jabber_data *jd = gc->proto_data; + struct jabber_data *jd = ic->proto_data; return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL; } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index a73d85d4..afc90627 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -28,7 +28,7 @@ static char *msn_set_display_name( set_t *set, char *value ); -static void msn_acc_init( account_t *acc ) +static void msn_init( account_t *acc ) { set_t *s; @@ -38,38 +38,38 @@ static void msn_acc_init( account_t *acc ) static void msn_login( account_t *acc ) { - struct gaim_connection *gc = new_gaim_conn( acc ); + struct im_connection *ic = new_gaim_conn( acc ); struct msn_data *md = g_new0( struct msn_data, 1 ); - gc->proto_data = md; + ic->proto_data = md; md->fd = -1; if( strchr( acc->user, '@' ) == NULL ) { - hide_login_progress( gc, "Invalid account name" ); - signoff( gc ); + hide_login_progress( ic, "Invalid account name" ); + signoff( ic ); return; } - set_login_progress( gc, 1, "Connecting" ); + set_login_progress( ic, 1, "Connecting" ); - md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, gc ); + md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, ic ); if( md->fd < 0 ) { - hide_login_progress( gc, "Could not connect to server" ); - signoff( gc ); + hide_login_progress( ic, "Could not connect to server" ); + signoff( ic ); return; } - md->gc = gc; + md->ic = ic; md->away_state = msn_away_state_list; - msn_connections = g_slist_append( msn_connections, gc ); + msn_connections = g_slist_append( msn_connections, ic ); } -static void msn_close( struct gaim_connection *gc ) +static void msn_logout( struct im_connection *ic ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; GSList *l; if( md ) @@ -95,7 +95,7 @@ static void msn_close( struct gaim_connection *gc ) { m = l->data; - serv_got_crap( gc, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); + serv_got_crap( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); g_free( m->who ); g_free( m->text ); g_free( m ); @@ -110,23 +110,23 @@ static void msn_close( struct gaim_connection *gc ) g_free( md ); } - for( l = gc->permit; l; l = l->next ) + for( l = ic->permit; l; l = l->next ) g_free( l->data ); - g_slist_free( gc->permit ); + g_slist_free( ic->permit ); - for( l = gc->deny; l; l = l->next ) + for( l = ic->deny; l; l = l->next ) g_free( l->data ); - g_slist_free( gc->deny ); + g_slist_free( ic->deny ); - msn_connections = g_slist_remove( msn_connections, gc ); + msn_connections = g_slist_remove( msn_connections, ic ); } -static int msn_send_im( struct gaim_connection *gc, char *who, char *message, int len, int away ) +static int msn_send_im( struct im_connection *ic, char *who, char *message, int away ) { struct msn_switchboard *sb; - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; - if( ( sb = msn_sb_by_handle( gc, who ) ) ) + if( ( sb = msn_sb_by_handle( ic, who ) ) ) { return( msn_sb_sendmessage( sb, message ) ); } @@ -141,7 +141,7 @@ static int msn_send_im( struct gaim_connection *gc, char *who, char *message, in m->text = g_strdup( message ); /* FIXME: *CHECK* the reliability of using spare sb's! */ - if( ( sb = msn_sb_spare( gc ) ) ) + if( ( sb = msn_sb_spare( ic ) ) ) { debug( "Trying to use a spare switchboard to message %s", who ); @@ -159,7 +159,7 @@ static int msn_send_im( struct gaim_connection *gc, char *who, char *message, in /* If we reach this line, there was no spare switchboard, so let's make one. */ g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); - if( !msn_write( gc, buf, strlen( buf ) ) ) + if( !msn_write( ic, buf, strlen( buf ) ) ) { g_free( m->who ); g_free( m->text ); @@ -179,7 +179,7 @@ static int msn_send_im( struct gaim_connection *gc, char *who, char *message, in return( 0 ); } -static GList *msn_away_states( struct gaim_connection *gc ) +static GList *msn_away_states( struct im_connection *ic ) { static GList *l = NULL; int i; @@ -191,7 +191,7 @@ static GList *msn_away_states( struct gaim_connection *gc ) return l; } -static char *msn_get_status_string( struct gaim_connection *gc, int number ) +static char *msn_get_status_string( struct im_connection *ic, int number ) { const struct msn_away_state *st = msn_away_state_by_number( number ); @@ -201,10 +201,10 @@ static char *msn_get_status_string( struct gaim_connection *gc, int number ) return( "" ); } -static void msn_set_away( struct gaim_connection *gc, char *state, char *message ) +static void msn_set_away( struct im_connection *ic, char *state, char *message ) { char buf[1024]; - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; const struct msn_away_state *st; if( strcmp( state, GAIM_AWAY_CUSTOM ) == 0 ) @@ -216,41 +216,41 @@ static void msn_set_away( struct gaim_connection *gc, char *state, char *message md->away_state = st; g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, st->code ); - msn_write( gc, buf, strlen( buf ) ); + msn_write( ic, buf, strlen( buf ) ); } -static void msn_set_info( struct gaim_connection *gc, char *info ) +static void msn_set_my_name( struct im_connection *ic, char *info ) { - msn_set_display_name( set_find( &gc->acc->set, "display_name" ), info ); + msn_set_display_name( set_find( &ic->acc->set, "display_name" ), info ); } -static void msn_get_info(struct gaim_connection *gc, char *who) +static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - serv_got_crap( gc, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); + serv_got_crap( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); } -static void msn_add_buddy( struct gaim_connection *gc, char *who ) +static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) { - msn_buddy_list_add( gc, "FL", who, who ); + msn_buddy_list_add( ic, "FL", who, who ); } -static void msn_remove_buddy( struct gaim_connection *gc, char *who, char *group ) +static void msn_remove_buddy( struct im_connection *ic, char *who, char *group ) { - msn_buddy_list_remove( gc, "FL", who ); + msn_buddy_list_remove( ic, "FL", who ); } -static int msn_chat_send( struct conversation *c, char *message ) +static void msn_chat_send( struct groupchat *c, char *message, int flags ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); if( sb ) - return( msn_sb_sendmessage( sb, message ) ); - else - return( 0 ); + msn_sb_sendmessage( sb, message ); + /* FIXME: Error handling (although this can't happen unless something's + already severely broken) disappeared here! */ } -static void msn_chat_invite( struct conversation *c, char *msg, char *who ) +static void msn_chat_invite( struct groupchat *c, char *msg, char *who ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); char buf[1024]; @@ -262,7 +262,7 @@ static void msn_chat_invite( struct conversation *c, char *msg, char *who ) } } -static void msn_chat_leave( struct conversation *c ) +static void msn_chat_leave( struct groupchat *c ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); @@ -270,13 +270,13 @@ static void msn_chat_leave( struct conversation *c ) msn_sb_write( sb, "OUT\r\n", 5 ); } -static struct conversation *msn_chat_open( struct gaim_connection *gc, char *who ) +static struct groupchat *msn_chat_with( struct im_connection *ic, char *who ) { struct msn_switchboard *sb; - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; char buf[1024]; - if( ( sb = msn_sb_by_handle( gc, who ) ) ) + if( ( sb = msn_sb_by_handle( ic, who ) ) ) { debug( "Converting existing switchboard to %s to a groupchat", who ); return msn_sb_to_chat( sb ); @@ -285,7 +285,7 @@ static struct conversation *msn_chat_open( struct gaim_connection *gc, char *who { struct msn_message *m; - if( ( sb = msn_sb_spare( gc ) ) ) + if( ( sb = msn_sb_spare( ic ) ) ) { debug( "Trying to reuse an existing switchboard as a groupchat with %s", who ); g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); @@ -298,7 +298,7 @@ static struct conversation *msn_chat_open( struct gaim_connection *gc, char *who /* Request a new switchboard. */ g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); - if( !msn_write( gc, buf, strlen( buf ) ) ) + if( !msn_write( ic, buf, strlen( buf ) ) ) return( 0 ); /* Create a magic message. This is quite hackish, but who cares? :-P */ @@ -316,43 +316,43 @@ static struct conversation *msn_chat_open( struct gaim_connection *gc, char *who return NULL; } -static void msn_keepalive( struct gaim_connection *gc ) +static void msn_keepalive( struct im_connection *ic ) { - msn_write( gc, "PNG\r\n", strlen( "PNG\r\n" ) ); + msn_write( ic, "PNG\r\n", strlen( "PNG\r\n" ) ); } -static void msn_add_permit( struct gaim_connection *gc, char *who ) +static void msn_add_permit( struct im_connection *ic, char *who ) { - msn_buddy_list_add( gc, "AL", who, who ); + msn_buddy_list_add( ic, "AL", who, who ); } -static void msn_rem_permit( struct gaim_connection *gc, char *who ) +static void msn_rem_permit( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( gc, "AL", who ); + msn_buddy_list_remove( ic, "AL", who ); } -static void msn_add_deny( struct gaim_connection *gc, char *who ) +static void msn_add_deny( struct im_connection *ic, char *who ) { struct msn_switchboard *sb; - msn_buddy_list_add( gc, "BL", who, who ); + msn_buddy_list_add( ic, "BL", who, who ); /* If there's still a conversation with this person, close it. */ - if( ( sb = msn_sb_by_handle( gc, who ) ) ) + if( ( sb = msn_sb_by_handle( ic, who ) ) ) { msn_sb_destroy( sb ); } } -static void msn_rem_deny( struct gaim_connection *gc, char *who ) +static void msn_rem_deny( struct im_connection *ic, char *who ) { - msn_buddy_list_remove( gc, "BL", who ); + msn_buddy_list_remove( ic, "BL", who ); } -static int msn_send_typing( struct gaim_connection *gc, char *who, int typing ) +static int msn_send_typing( struct im_connection *ic, char *who, int typing ) { if( typing ) - return( msn_send_im( gc, who, TYPING_NOTIFICATION_MESSAGE, strlen( TYPING_NOTIFICATION_MESSAGE ), 0 ) ); + return( msn_send_im( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) ); else return( 1 ); } @@ -360,26 +360,26 @@ static int msn_send_typing( struct gaim_connection *gc, char *who, int typing ) static char *msn_set_display_name( set_t *set, char *value ) { account_t *acc = set->data; - struct gaim_connection *gc = acc->gc; + struct im_connection *ic = acc->ic; struct msn_data *md; char buf[1024], *fn; /* Double-check. */ - if( gc == NULL ) + if( ic == NULL ) return NULL; - md = gc->proto_data; + md = ic->proto_data; if( strlen( value ) > 129 ) { - serv_got_crap( gc, "Maximum name length exceeded" ); + serv_got_crap( ic, "Maximum name length exceeded" ); return NULL; } fn = msn_http_encode( value ); - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, gc->username, fn ); - msn_write( gc, buf, strlen( buf ) ); + g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->username, fn ); + msn_write( ic, buf, strlen( buf ) ); g_free( fn ); /* Returning NULL would be better, because the server still has to @@ -388,26 +388,26 @@ static char *msn_set_display_name( set_t *set, char *value ) return value; } -void msn_init() +void msn_initmodule() { struct prpl *ret = g_new0(struct prpl, 1); ret->name = "msn"; ret->login = msn_login; - ret->acc_init = msn_acc_init; - ret->close = msn_close; + ret->init = msn_init; + ret->logout = msn_logout; ret->send_im = msn_send_im; ret->away_states = msn_away_states; ret->get_status_string = msn_get_status_string; ret->set_away = msn_set_away; - ret->set_info = msn_set_info; ret->get_info = msn_get_info; + ret->set_my_name = msn_set_my_name; ret->add_buddy = msn_add_buddy; ret->remove_buddy = msn_remove_buddy; ret->chat_send = msn_chat_send; ret->chat_invite = msn_chat_invite; ret->chat_leave = msn_chat_leave; - ret->chat_open = msn_chat_open; + ret->chat_with = msn_chat_with; ret->keepalive = msn_keepalive; ret->add_permit = msn_add_permit; ret->rem_permit = msn_rem_permit; diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 78cc3caf..721466d6 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -56,7 +56,7 @@ struct msn_data { - struct gaim_connection *gc; + struct im_connection *ic; int fd; struct msn_handler_data *handler; @@ -74,7 +74,7 @@ struct msn_data struct msn_switchboard { - struct gaim_connection *gc; + struct im_connection *ic; int fd; gint inp; @@ -88,7 +88,7 @@ struct msn_switchboard GSList *msgq; char *who; - struct conversation *chat; + struct groupchat *chat; }; struct msn_away_state @@ -148,11 +148,11 @@ GSList *msn_switchboards; gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); /* msn_util.c */ -int msn_write( struct gaim_connection *gc, char *s, int len ); -int msn_logged_in( struct gaim_connection *gc ); -int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char *realname ); -int msn_buddy_list_remove( struct gaim_connection *gc, char *list, char *who ); -void msn_buddy_ask( struct gaim_connection *gc, char *handle, char *realname ); +int msn_write( struct im_connection *ic, char *s, int len ); +int msn_logged_in( struct im_connection *ic ); +int msn_buddy_list_add( struct im_connection *ic, char *list, char *who, char *realname ); +int msn_buddy_list_remove( struct im_connection *ic, char *list, char *who ); +void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); @@ -166,11 +166,11 @@ const struct msn_status_code *msn_status_by_number( int number ); /* sb.c */ int msn_sb_write( struct msn_switchboard *sb, char *s, int len ); -struct msn_switchboard *msn_sb_create( struct gaim_connection *gc, char *host, int port, char *key, int session ); -struct msn_switchboard *msn_sb_by_handle( struct gaim_connection *gc, char *handle ); -struct msn_switchboard *msn_sb_by_chat( struct conversation *c ); -struct msn_switchboard *msn_sb_spare( struct gaim_connection *gc ); +struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ); +struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); +struct msn_switchboard *msn_sb_spare( struct im_connection *ic ); int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); -struct conversation *msn_sb_to_chat( struct msn_switchboard *sb ); +struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ); void msn_sb_destroy( struct msn_switchboard *sb ); gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index ff4c148c..1be1586c 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -27,38 +27,38 @@ #include "msn.h" #include <ctype.h> -int msn_write( struct gaim_connection *gc, char *s, int len ) +int msn_write( struct im_connection *ic, char *s, int len ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; int st; st = write( md->fd, s, len ); if( st != len ) { - hide_login_progress_error( gc, "Short write() to main server" ); - signoff( gc ); + hide_login_progress_error( ic, "Short write() to main server" ); + signoff( ic ); return( 0 ); } return( 1 ); } -int msn_logged_in( struct gaim_connection *gc ) +int msn_logged_in( struct im_connection *ic ) { - account_online( gc ); + account_online( ic ); return( 0 ); } -int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char *realname_ ) +int msn_buddy_list_add( struct im_connection *ic, char *list, char *who, char *realname_ ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; char buf[1024], *realname; realname = msn_http_encode( realname_ ); g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s\r\n", ++md->trId, list, who, realname ); - if( msn_write( gc, buf, strlen( buf ) ) ) + if( msn_write( ic, buf, strlen( buf ) ) ) { g_free( realname ); @@ -70,13 +70,13 @@ int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char return( 0 ); } -int msn_buddy_list_remove( struct gaim_connection *gc, char *list, char *who ) +int msn_buddy_list_remove( struct im_connection *ic, char *list, char *who ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; char buf[1024]; g_snprintf( buf, sizeof( buf ), "REM %d %s %s\r\n", ++md->trId, list, who ); - if( msn_write( gc, buf, strlen( buf ) ) ) + if( msn_write( ic, buf, strlen( buf ) ) ) return( 1 ); return( 0 ); @@ -84,17 +84,17 @@ int msn_buddy_list_remove( struct gaim_connection *gc, char *list, char *who ) struct msn_buddy_ask_data { - struct gaim_connection *gc; + struct im_connection *ic; char *handle; char *realname; }; static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) { - msn_buddy_list_add( bla->gc, "AL", bla->handle, bla->realname ); + msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); - if( find_buddy( bla->gc, bla->handle ) == NULL ) - show_got_added( bla->gc, bla->handle, NULL ); + if( find_buddy( bla->ic, bla->handle ) == NULL ) + show_got_added( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla->realname ); @@ -103,26 +103,26 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) static void msn_buddy_ask_no( gpointer w, struct msn_buddy_ask_data *bla ) { - msn_buddy_list_add( bla->gc, "BL", bla->handle, bla->realname ); + msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname ); g_free( bla->handle ); g_free( bla->realname ); g_free( bla ); } -void msn_buddy_ask( struct gaim_connection *gc, char *handle, char *realname ) +void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ) { struct msn_buddy_ask_data *bla = g_new0( struct msn_buddy_ask_data, 1 ); char buf[1024]; - bla->gc = gc; + bla->ic = ic; bla->handle = g_strdup( handle ); bla->realname = g_strdup( realname ); g_snprintf( buf, sizeof( buf ), "The user %s (%s) wants to add you to his/her buddy list.", handle, realname ); - do_ask_dialog( gc, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); + do_ask_dialog( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); } char *msn_findheader( char *text, char *header, int len ) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 9774f3e2..9d86a68e 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -37,26 +37,26 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct msn_data *md; char s[1024]; - if( !g_slist_find( msn_connections, gc ) ) + if( !g_slist_find( msn_connections, ic ) ) return FALSE; if( source == -1 ) { - hide_login_progress( gc, "Could not connect to server" ); - signoff( gc ); + hide_login_progress( ic, "Could not connect to server" ); + signoff( ic ); return FALSE; } - md = gc->proto_data; + md = ic->proto_data; if( !md->handler ) { md->handler = g_new0( struct msn_handler_data, 1 ); - md->handler->data = gc; + md->handler->data = ic; md->handler->exec_command = msn_ns_command; md->handler->exec_message = msn_ns_message; } @@ -72,10 +72,10 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) md->handler->rxq = g_new0( char, 1 ); g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId ); - if( msn_write( gc, s, strlen( s ) ) ) + if( msn_write( ic, s, strlen( s ) ) ) { - gc->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc ); - set_login_progress( gc, 1, "Connected to server, waiting for reply" ); + ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic ); + set_login_progress( ic, 1, "Connected to server, waiting for reply" ); } return FALSE; @@ -83,13 +83,13 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ) { - struct gaim_connection *gc = data; - struct msn_data *md = gc->proto_data; + struct im_connection *ic = data; + struct msn_data *md = ic->proto_data; if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ { - hide_login_progress( gc, "Error while reading from server" ); - signoff( gc ); + hide_login_progress( ic, "Error while reading from server" ); + signoff( ic ); return FALSE; } @@ -99,8 +99,8 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { - struct gaim_connection *gc = data; - struct msn_data *md = gc->proto_data; + struct im_connection *ic = data; + struct msn_data *md = ic->proto_data; char buf[1024]; if( num_parts == 0 ) @@ -113,20 +113,20 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) { - hide_login_progress( gc, "Unsupported protocol" ); - signoff( gc ); + hide_login_progress( ic, "Unsupported protocol" ); + signoff( ic ); return( 0 ); } g_snprintf( buf, sizeof( buf ), "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", - ++md->trId, gc->username ); - return( msn_write( gc, buf, strlen( buf ) ) ); + ++md->trId, ic->username ); + return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "CVR" ) == 0 ) { /* We don't give a damn about the information we just received */ - g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, gc->username ); - return( msn_write( gc, buf, strlen( buf ) ) ); + g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->username ); + return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "XFR" ) == 0 ) { @@ -135,24 +135,24 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 ) { - b_event_remove( gc->inpa ); - gc->inpa = 0; + b_event_remove( ic->inpa ); + ic->inpa = 0; closesocket( md->fd ); server = strchr( cmd[3], ':' ); if( !server ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } *server = 0; port = atoi( server + 1 ); server = cmd[3]; - set_login_progress( gc, 1, "Transferring to other server" ); + set_login_progress( ic, 1, "Transferring to other server" ); - md->fd = proxy_connect( server, port, msn_ns_connected, gc ); + md->fd = proxy_connect( server, port, msn_ns_connected, ic ); } else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 ) { @@ -161,8 +161,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[3], ':' ); if( !server ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } *server = 0; @@ -171,13 +171,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[4], "CKI" ) != 0 ) { - hide_login_progress_error( gc, "Unknown authentication method for switchboard" ); - signoff( gc ); + hide_login_progress_error( ic, "Unknown authentication method for switchboard" ); + signoff( ic ); return( 0 ); } debug( "Connecting to a new switchboard with key %s", cmd[5] ); - sb = msn_sb_create( gc, server, port, cmd[5], MSN_SB_NEW ); + sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ); if( md->msgq ) { @@ -203,8 +203,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } } @@ -213,10 +213,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* Time for some Passport black magic... */ - if( !passport_get_id( msn_auth_got_passport_id, gc, gc->username, gc->password, cmd[4] ) ) + if( !passport_get_id( msn_auth_got_passport_id, ic, ic->username, ic->password, cmd[4] ) ) { - hide_login_progress_error( gc, "Error while contacting Passport server" ); - signoff( gc ); + hide_login_progress_error( ic, "Error while contacting Passport server" ); + signoff( ic ); return( 0 ); } } @@ -226,24 +226,24 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) http_decode( cmd[4] ); - strncpy( gc->displayname, cmd[4], sizeof( gc->displayname ) ); - gc->displayname[sizeof(gc->displayname)-1] = 0; + strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); + ic->displayname[sizeof(ic->displayname)-1] = 0; - if( ( s = set_find( &gc->acc->set, "display_name" ) ) ) + if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) { g_free( s->value ); s->value = g_strdup( cmd[4] ); } - set_login_progress( gc, 1, "Authenticated, getting buddy list" ); + set_login_progress( ic, 1, "Authenticated, getting buddy list" ); g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); - return( msn_write( gc, buf, strlen( buf ) ) ); + return( msn_write( ic, buf, strlen( buf ) ) ); } else { - hide_login_progress( gc, "Unknown authentication type" ); - signoff( gc ); + hide_login_progress( ic, "Unknown authentication type" ); + signoff( ic ); return( 0 ); } } @@ -251,8 +251,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( num_parts != 4 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } @@ -260,8 +260,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->handler->msglen <= 0 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } } @@ -275,14 +275,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) md->grouplist = g_new0( char *, md->groupcount ); if( !*cmd[3] || md->buddycount == 0 ) - msn_logged_in( gc ); + msn_logged_in( ic ); } else { /* Hrrm... This SYN reply doesn't really look like something we expected. Let's assume everything is okay. */ - msn_logged_in( gc ); + msn_logged_in( ic ); } } else if( strcmp( cmd[0], "LST" ) == 0 ) @@ -291,8 +291,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 && num_parts != 5 ) { - hide_login_progress( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } @@ -307,33 +307,33 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 ) group = md->grouplist[num]; - add_buddy( gc, group, cmd[1], cmd[2] ); + add_buddy( ic, group, cmd[1], cmd[2] ); } if( list & 2 ) /* AL */ { - gc->permit = g_slist_append( gc->permit, g_strdup( cmd[1] ) ); + ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) ); } if( list & 4 ) /* BL */ { - gc->deny = g_slist_append( gc->deny, g_strdup( cmd[1] ) ); + ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) ); } if( list & 8 ) /* RL */ { if( ( list & 6 ) == 0 ) - msn_buddy_ask( gc, cmd[1], cmd[2] ); + msn_buddy_ask( ic, cmd[1], cmd[2] ); } if( --md->buddycount == 0 ) { - if( gc->flags & OPT_LOGGED_IN ) + if( ic->flags & OPT_LOGGED_IN ) { - serv_got_crap( gc, "Successfully transferred to different server" ); + serv_got_crap( ic, "Successfully transferred to different server" ); g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); - return( msn_write( gc, buf, strlen( buf ) ) ); + return( msn_write( ic, buf, strlen( buf ) ) ); } else { - msn_logged_in( gc ); + msn_logged_in( ic ); } } } @@ -343,8 +343,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } @@ -362,8 +362,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 3 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } @@ -376,7 +376,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) for( i = 0; i < 16; i ++ ) g_snprintf( buf + strlen( buf ), 3, "%02x", digest[i] ); - return( msn_write( gc, buf, strlen( buf ) ) ); + return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "ILN" ) == 0 ) { @@ -384,13 +384,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 6 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } http_decode( cmd[4] ); - serv_buddy_rename( gc, cmd[3], cmd[4] ); + serv_buddy_rename( ic, cmd[3], cmd[4] ); st = msn_away_state_by_code( cmd[2] ); if( !st ) @@ -399,12 +399,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) st = msn_away_state_list; } - serv_got_update( gc, cmd[3], 1, 0, 0, 0, st->number, 0 ); + serv_got_update( ic, cmd[3], 1, 0, 0, 0, st->number, 0 ); } else if( strcmp( cmd[0], "FLN" ) == 0 ) { if( cmd[1] ) - serv_got_update( gc, cmd[1], 0, 0, 0, 0, 0, 0 ); + serv_got_update( ic, cmd[1], 0, 0, 0, 0, 0, 0 ); } else if( strcmp( cmd[0], "NLN" ) == 0 ) { @@ -412,13 +412,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 5 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } http_decode( cmd[3] ); - serv_buddy_rename( gc, cmd[2], cmd[3] ); + serv_buddy_rename( ic, cmd[2], cmd[3] ); st = msn_away_state_by_code( cmd[1] ); if( !st ) @@ -427,7 +427,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) st = msn_away_state_list; } - serv_got_update( gc, cmd[2], 1, 0, 0, 0, st->number, 0 ); + serv_got_update( ic, cmd[2], 1, 0, 0, 0, st->number, 0 ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { @@ -437,8 +437,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 7 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } @@ -447,8 +447,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[2], ':' ); if( !server ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } *server = 0; @@ -457,14 +457,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[3], "CKI" ) != 0 ) { - hide_login_progress_error( gc, "Unknown authentication method for switchboard" ); - signoff( gc ); + hide_login_progress_error( ic, "Unknown authentication method for switchboard" ); + signoff( ic ); return( 0 ); } debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] ); - sb = msn_sb_create( gc, server, port, cmd[4], session ); + sb = msn_sb_create( ic, server, port, cmd[4], session ); sb->who = g_strdup( cmd[5] ); } else if( strcmp( cmd[0], "ADD" ) == 0 ) @@ -477,60 +477,60 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strchr( cmd[4], '@' ) == NULL ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } /* We got added by someone. If we don't have this person in permit/deny yet, inform the user. */ - for( l = gc->permit; l; l = l->next ) + for( l = ic->permit; l; l = l->next ) if( g_strcasecmp( l->data, cmd[4] ) == 0 ) return( 1 ); - for( l = gc->deny; l; l = l->next ) + for( l = ic->deny; l; l = l->next ) if( g_strcasecmp( l->data, cmd[4] ) == 0 ) return( 1 ); - msn_buddy_ask( gc, cmd[4], cmd[5] ); + msn_buddy_ask( ic, cmd[4], cmd[5] ); } } else if( strcmp( cmd[0], "OUT" ) == 0 ) { if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) { - hide_login_progress_error( gc, "Someone else logged in with your account" ); - gc->wants_to_die = 1; + hide_login_progress_error( ic, "Someone else logged in with your account" ); + ic->wants_to_die = 1; } else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) { - hide_login_progress_error( gc, "Terminating session because of server shutdown" ); + hide_login_progress_error( ic, "Terminating session because of server shutdown" ); } else { - hide_login_progress_error( gc, "Session terminated by remote server (reason unknown)" ); + hide_login_progress_error( ic, "Session terminated by remote server (reason unknown)" ); } - signoff( gc ); + signoff( ic ); return( 0 ); } else if( strcmp( cmd[0], "REA" ) == 0 ) { if( num_parts != 5 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } - if( g_strcasecmp( cmd[3], gc->username ) == 0 ) + if( g_strcasecmp( cmd[3], ic->username ) == 0 ) { set_t *s; http_decode( cmd[4] ); - strncpy( gc->displayname, cmd[4], sizeof( gc->displayname ) ); - gc->displayname[sizeof(gc->displayname)-1] = 0; + strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); + ic->displayname[sizeof(ic->displayname)-1] = 0; - if( ( s = set_find( &gc->acc->set, "display_name" ) ) ) + if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) { g_free( s->value ); s->value = g_strdup( cmd[4] ); @@ -540,19 +540,19 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { /* This is not supposed to happen, but let's handle it anyway... */ http_decode( cmd[4] ); - serv_buddy_rename( gc, cmd[3], cmd[4] ); + serv_buddy_rename( ic, cmd[3], cmd[4] ); } } else if( strcmp( cmd[0], "IPG" ) == 0 ) { - do_error_dialog( gc, "Received IPG command, we don't handle them yet.", "MSN" ); + do_error_dialog( ic, "Received IPG command, we don't handle them yet.", "MSN" ); md->handler->msglen = atoi( cmd[1] ); if( md->handler->msglen <= 0 ) { - hide_login_progress_error( gc, "Syntax error" ); - signoff( gc ); + hide_login_progress_error( ic, "Syntax error" ); + signoff( ic ); return( 0 ); } } @@ -562,11 +562,11 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) const struct msn_status_code *err = msn_status_by_number( num ); g_snprintf( buf, sizeof( buf ), "Error reported by MSN server: %s", err->text ); - do_error_dialog( gc, buf, "MSN" ); + do_error_dialog( ic, buf, "MSN" ); if( err->flags & STATUS_FATAL ) { - signoff( gc ); + signoff( ic ); return( 0 ); } } @@ -580,7 +580,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; char *body; int blen = 0; @@ -616,7 +616,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( mtype && strcmp( mtype, "1" ) == 0 ) { if( arg1 ) - serv_got_crap( gc, "The server is going down for maintenance in %s minutes.", arg1 ); + serv_got_crap( ic, "The server is going down for maintenance in %s minutes.", arg1 ); } if( arg1 ) g_free( arg1 ); @@ -633,7 +633,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( inbox && folders ) { - serv_got_crap( gc, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); + serv_got_crap( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); } } else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 ) @@ -643,7 +643,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( from && fromname ) { - serv_got_crap( gc, "Received an e-mail message from %s <%s>.", fromname, from ); + serv_got_crap( ic, "Received an e-mail message from %s <%s>.", fromname, from ); } } else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) @@ -664,8 +664,8 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int static void msn_auth_got_passport_id( struct passport_reply *rep ) { - struct gaim_connection *gc = rep->data; - struct msn_data *md = gc->proto_data; + struct im_connection *ic = rep->data; + struct msn_data *md = ic->proto_data; char *key = rep->result; char buf[1024]; @@ -676,14 +676,14 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) err = g_strdup_printf( "Error during Passport authentication (%s)", rep->error_string ? rep->error_string : "Unknown error" ); - hide_login_progress( gc, err ); - signoff( gc ); + hide_login_progress( ic, err ); + signoff( ic ); g_free( err ); } else { g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key ); - msn_write( gc, buf, strlen( buf ) ); + msn_write( ic, buf, strlen( buf ) ); } } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 8e912273..f9c755a5 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -47,9 +47,9 @@ int msn_sb_write( struct msn_switchboard *sb, char *s, int len ) return( 1 ); } -struct msn_switchboard *msn_sb_create( struct gaim_connection *gc, char *host, int port, char *key, int session ) +struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; struct msn_switchboard *sb = g_new0( struct msn_switchboard, 1 ); sb->fd = proxy_connect( host, port, msn_sb_connected, sb ); @@ -59,7 +59,7 @@ struct msn_switchboard *msn_sb_create( struct gaim_connection *gc, char *host, i return( NULL ); } - sb->gc = gc; + sb->ic = ic; sb->key = g_strdup( key ); sb->session = session; @@ -69,9 +69,9 @@ struct msn_switchboard *msn_sb_create( struct gaim_connection *gc, char *host, i return( sb ); } -struct msn_switchboard *msn_sb_by_handle( struct gaim_connection *gc, char *handle ) +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; GSList *l; @@ -85,9 +85,9 @@ struct msn_switchboard *msn_sb_by_handle( struct gaim_connection *gc, char *hand return( NULL ); } -struct msn_switchboard *msn_sb_by_chat( struct conversation *c ) +struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ) { - struct msn_data *md = c->gc->proto_data; + struct msn_data *md = c->ic->proto_data; struct msn_switchboard *sb; GSList *l; @@ -101,9 +101,9 @@ struct msn_switchboard *msn_sb_by_chat( struct conversation *c ) return( NULL ); } -struct msn_switchboard *msn_sb_spare( struct gaim_connection *gc ) +struct msn_switchboard *msn_sb_spare( struct im_connection *ic ) { - struct msn_data *md = gc->proto_data; + struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; GSList *l; @@ -141,9 +141,9 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) } else { - i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->gc->username ); + i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->username ); buf = g_new0( char, i ); - i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->gc->username ); + i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->username ); } /* Build the final packet (MSG command + the message). */ @@ -176,18 +176,18 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) } } -struct conversation *msn_sb_to_chat( struct msn_switchboard *sb ) +struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ) { - struct gaim_connection *gc = sb->gc; + struct im_connection *ic = sb->ic; char buf[1024]; /* Create the groupchat structure. */ g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( gc, buf ); + sb->chat = serv_got_joined_chat( ic, buf ); /* Populate the channel. */ if( sb->who ) add_chat_buddy( sb->chat, sb->who ); - add_chat_buddy( sb->chat, gc->username ); + add_chat_buddy( sb->chat, ic->username ); /* And make sure the switchboard doesn't look like a regular chat anymore. */ if( sb->who ) @@ -201,8 +201,8 @@ struct conversation *msn_sb_to_chat( struct msn_switchboard *sb ) void msn_sb_destroy( struct msn_switchboard *sb ) { - struct gaim_connection *gc = sb->gc; - struct msn_data *md = gc->proto_data; + struct im_connection *ic = sb->ic; + struct msn_data *md = ic->proto_data; debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" ); @@ -221,7 +221,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) } g_slist_free( sb->msgq ); - serv_got_crap( gc, "Warning: Closing down MSN switchboard connection with " + serv_got_crap( ic, "Warning: Closing down MSN switchboard connection with " "unsent message to %s, you'll have to resend it.", sb->who ? sb->who : "(unknown)" ); } @@ -252,7 +252,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; - struct gaim_connection *gc; + struct im_connection *ic; struct msn_data *md; char buf[1024]; @@ -260,8 +260,8 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) if( !g_slist_find( msn_switchboards, sb ) ) return FALSE; - gc = sb->gc; - md = gc->proto_data; + ic = sb->ic; + md = ic->proto_data; if( source != sb->fd ) { @@ -279,9 +279,9 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) sb->handler->exec_message = msn_sb_message; if( sb->session == MSN_SB_NEW ) - g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, gc->username, sb->key ); + g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->username, sb->key ); else - g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, gc->username, sb->key, sb->session ); + g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->username, sb->key, sb->session ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); @@ -309,7 +309,7 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c static int msn_sb_command( gpointer data, char **cmd, int num_parts ) { struct msn_switchboard *sb = data; - struct gaim_connection *gc = sb->gc; + struct im_connection *ic = sb->ic; char buf[1024]; if( !num_parts ) @@ -320,8 +320,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "XFR" ) == 0 ) { - hide_login_progress_error( gc, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); - signoff( gc ); + hide_login_progress_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); + signoff( ic ); return( 0 ); } else if( strcmp( cmd[0], "USR" ) == 0 ) @@ -373,7 +373,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( num == 1 ) { g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( gc, buf ); + sb->chat = serv_got_joined_chat( ic, buf ); g_free( sb->who ); sb->who = NULL; @@ -383,7 +383,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( num == tot ) { - add_chat_buddy( sb->chat, gc->username ); + add_chat_buddy( sb->chat, ic->username ); } } } @@ -528,7 +528,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) const struct msn_status_code *err = msn_status_by_number( num ); g_snprintf( buf, sizeof( buf ), "Error reported by switchboard server: %s", err->text ); - do_error_dialog( gc, buf, "MSN" ); + do_error_dialog( ic, buf, "MSN" ); if( err->flags & STATUS_SB_FATAL ) { @@ -537,7 +537,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( err->flags & STATUS_FATAL ) { - signoff( gc ); + signoff( ic ); return 0; } else if( err->flags & STATUS_SB_IM_SPARE ) @@ -578,7 +578,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ) { struct msn_switchboard *sb = data; - struct gaim_connection *gc = sb->gc; + struct im_connection *ic = sb->ic; char *body; int blen = 0; @@ -607,7 +607,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( sb->who ) { - serv_got_im( gc, cmd[1], body, 0, 0, blen ); + serv_got_im( ic, cmd[1], body, 0, 0, blen ); } else if( sb->chat ) { @@ -666,7 +666,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( sb->who ) { - serv_got_im( gc, cmd[1], buf, 0, 0, strlen( buf ) ); + serv_got_im( ic, cmd[1], buf, 0, 0, strlen( buf ) ); } else if( sb->chat ) { @@ -683,7 +683,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( who ) { - serv_got_typing( gc, who, 5, 1 ); + serv_got_typing( ic, who, 5, 1 ); g_free( who ); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index e983352f..987c08f2 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -35,7 +35,7 @@ #include "nogaim.h" #include <ctype.h> -static int remove_chat_buddy_silent( struct conversation *b, char *handle ); +static int remove_chat_buddy_silent( struct groupchat *b, char *handle ); GSList *connections; @@ -114,25 +114,25 @@ struct prpl *find_protocol(const char *name) /* nogaim.c */ void nogaim_init() { - extern void msn_init(); - extern void oscar_init(); - extern void byahoo_init(); - extern void jabber_init(); + extern void msn_initmodule(); + extern void oscar_initmodule(); + extern void byahoo_initmodule(); + extern void jabber_initmodule(); #ifdef WITH_MSN - msn_init(); + msn_initmodule(); #endif #ifdef WITH_OSCAR - oscar_init(); + oscar_initmodule(); #endif #ifdef WITH_YAHOO - byahoo_init(); + byahoo_initmodule(); #endif #ifdef WITH_JABBER - jabber_init(); + jabber_initmodule(); #endif #ifdef WITH_PLUGINS @@ -144,59 +144,59 @@ GSList *get_connections() { return connections; } /* multi.c */ -struct gaim_connection *new_gaim_conn( account_t *acc ) +struct im_connection *new_gaim_conn( account_t *acc ) { - struct gaim_connection *gc; + struct im_connection *ic; - gc = g_new0( struct gaim_connection, 1 ); + ic = g_new0( struct im_connection, 1 ); /* Maybe we should get rid of this memory waste later. ;-) */ - g_snprintf( gc->username, sizeof( gc->username ), "%s", acc->user ); - g_snprintf( gc->password, sizeof( gc->password ), "%s", acc->pass ); + g_snprintf( ic->username, sizeof( ic->username ), "%s", acc->user ); + g_snprintf( ic->password, sizeof( ic->password ), "%s", acc->pass ); - gc->irc = acc->irc; - gc->acc = acc; - acc->gc = gc; + ic->irc = acc->irc; + ic->acc = acc; + acc->ic = ic; - connections = g_slist_append( connections, gc ); + connections = g_slist_append( connections, ic ); - return( gc ); + return( ic ); } -void destroy_gaim_conn( struct gaim_connection *gc ) +void destroy_gaim_conn( struct im_connection *ic ) { account_t *a; /* Destroy the pointer to this connection from the account list */ - for( a = gc->irc->accounts; a; a = a->next ) - if( a->gc == gc ) + for( a = ic->irc->accounts; a; a = a->next ) + if( a->ic == ic ) { - a->gc = NULL; + a->ic = NULL; break; } - connections = g_slist_remove( connections, gc ); - g_free( gc ); + connections = g_slist_remove( connections, ic ); + g_free( ic ); } -void set_login_progress( struct gaim_connection *gc, int step, char *msg ) +void set_login_progress( struct im_connection *ic, int step, char *msg ) { - serv_got_crap( gc, "Logging in: %s", msg ); + serv_got_crap( ic, "Logging in: %s", msg ); } /* Errors *while* logging in */ -void hide_login_progress( struct gaim_connection *gc, char *msg ) +void hide_login_progress( struct im_connection *ic, char *msg ) { - serv_got_crap( gc, "Login error: %s", msg ); + serv_got_crap( ic, "Login error: %s", msg ); } /* Errors *after* logging in */ -void hide_login_progress_error( struct gaim_connection *gc, char *msg ) +void hide_login_progress_error( struct im_connection *ic, char *msg ) { - serv_got_crap( gc, "Logged out: %s", msg ); + serv_got_crap( ic, "Logged out: %s", msg ); } -void serv_got_crap( struct gaim_connection *gc, char *format, ... ) +void serv_got_crap( struct im_connection *ic, char *format, ... ) { va_list params; char *text; @@ -206,54 +206,54 @@ void serv_got_crap( struct gaim_connection *gc, char *format, ... ) text = g_strdup_vprintf( format, params ); va_end( params ); - if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( text ); /* Try to find a different connection on the same protocol. */ - for( a = gc->irc->accounts; a; a = a->next ) - if( a->prpl == gc->acc->prpl && a->gc != gc ) + for( a = ic->irc->accounts; a; a = a->next ) + if( a->prpl == ic->acc->prpl && a->ic != ic ) break; /* If we found one, include the screenname in the message. */ if( a ) - irc_usermsg( gc->irc, "%s(%s) - %s", gc->acc->prpl->name, gc->username, text ); + irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->username, text ); else - irc_usermsg( gc->irc, "%s - %s", gc->acc->prpl->name, text ); + irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text ); g_free( text ); } static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) { - struct gaim_connection *gc = d; + struct im_connection *ic = d; - if( gc->acc->prpl->keepalive ) - gc->acc->prpl->keepalive( gc ); + if( ic->acc->prpl->keepalive ) + ic->acc->prpl->keepalive( ic ); return TRUE; } -void account_online( struct gaim_connection *gc ) +void account_online( struct im_connection *ic ) { user_t *u; /* MSN servers sometimes redirect you to a different server and do the whole login sequence again, so these "late" calls to this function should be handled correctly. (IOW, ignored) */ - if( gc->flags & OPT_LOGGED_IN ) + if( ic->flags & OPT_LOGGED_IN ) return; - u = user_find( gc->irc, gc->irc->nick ); + u = user_find( ic->irc, ic->irc->nick ); - serv_got_crap( gc, "Logged in" ); + serv_got_crap( ic, "Logged in" ); - gc->keepalive = b_timeout_add( 60000, send_keepalive, gc ); - gc->flags |= OPT_LOGGED_IN; + ic->keepalive = b_timeout_add( 60000, send_keepalive, ic ); + ic->flags |= OPT_LOGGED_IN; /* Also necessary when we're not away, at least for some of the protocols. */ - bim_set_away( gc, u->away ); + bim_set_away( ic, u->away ); } gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) @@ -273,29 +273,29 @@ void cancel_auto_reconnect( account_t *a ) a->reconnect = 0; } -void signoff( struct gaim_connection *gc ) +void signoff( struct im_connection *ic ) { - irc_t *irc = gc->irc; + irc_t *irc = ic->irc; user_t *t, *u = irc->users; account_t *a; /* Nested calls might happen sometimes, this is probably the best place to catch them. */ - if( gc->flags & OPT_LOGGING_OUT ) + if( ic->flags & OPT_LOGGING_OUT ) return; else - gc->flags |= OPT_LOGGING_OUT; + ic->flags |= OPT_LOGGING_OUT; - serv_got_crap( gc, "Signing off.." ); + serv_got_crap( ic, "Signing off.." ); - b_event_remove( gc->keepalive ); - gc->keepalive = 0; - gc->acc->prpl->close( gc ); - b_event_remove( gc->inpa ); + b_event_remove( ic->keepalive ); + ic->keepalive = 0; + ic->acc->prpl->logout( ic ); + b_event_remove( ic->inpa ); while( u ) { - if( u->gc == gc ) + if( u->ic == ic ) { t = u->next; user_del( irc, u->nick ); @@ -305,65 +305,65 @@ void signoff( struct gaim_connection *gc ) u = u->next; } - query_del_by_gc( gc->irc, gc ); + query_del_by_conn( ic->irc, ic ); for( a = irc->accounts; a; a = a->next ) - if( a->gc == gc ) + if( a->ic == ic ) break; if( !a ) { /* Uhm... This is very sick. */ } - else if( !gc->wants_to_die && set_getbool( &irc->set, "auto_reconnect" ) && + else if( !ic->wants_to_die && set_getbool( &irc->set, "auto_reconnect" ) && set_getbool( &a->set, "auto_reconnect" ) ) { int delay = set_getint( &irc->set, "auto_reconnect_delay" ); - serv_got_crap( gc, "Reconnecting in %d seconds..", delay ); + serv_got_crap( ic, "Reconnecting in %d seconds..", delay ); a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); } - destroy_gaim_conn( gc ); + destroy_gaim_conn( ic ); } /* dialogs.c */ -void do_error_dialog( struct gaim_connection *gc, char *msg, char *title ) +void do_error_dialog( struct im_connection *ic, char *msg, char *title ) { if( msg && title ) - serv_got_crap( gc, "Error: %s: %s", title, msg ); + serv_got_crap( ic, "Error: %s: %s", title, msg ); else if( msg ) - serv_got_crap( gc, "Error: %s", msg ); + serv_got_crap( ic, "Error: %s", msg ); else if( title ) - serv_got_crap( gc, "Error: %s", title ); + serv_got_crap( ic, "Error: %s", title ); else - serv_got_crap( gc, "Error" ); + serv_got_crap( ic, "Error" ); } -void do_ask_dialog( struct gaim_connection *gc, char *msg, void *data, void *doit, void *dont ) +void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) { - query_add( gc->irc, gc, msg, doit, dont, data ); + query_add( ic->irc, ic, msg, doit, dont, data ); } /* list.c */ -void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *realname ) +void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ) { user_t *u; char nick[MAX_NICK_LENGTH+1]; char *s; - irc_t *irc = gc->irc; + irc_t *irc = ic->irc; if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */ - serv_got_crap( gc, "Receiving user add from handle: %s", handle ); + serv_got_crap( ic, "Receiving user add from handle: %s", handle ); - if( user_findhandle( gc, handle ) ) + if( user_findhandle( ic, handle ) ) { if( set_getbool( &irc->set, "debug" ) ) - serv_got_crap( gc, "User already exists, ignoring add request: %s", handle ); + serv_got_crap( ic, "User already exists, ignoring add request: %s", handle ); return; @@ -371,9 +371,9 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( gc->acc, handle, realname ) ); + strcpy( nick, nick_get( ic->acc, handle, realname ) ); - u = user_add( gc->irc, nick ); + u = user_add( ic->irc, nick ); if( !realname || !*realname ) realname = nick; u->realname = g_strdup( realname ); @@ -383,15 +383,15 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea u->host = g_strdup( s + 1 ); u->user = g_strndup( handle, s - handle ); } - else if( gc->acc->server ) + else if( ic->acc->server ) { char *colon; - if( ( colon = strchr( gc->acc->server, ':' ) ) ) - u->host = g_strndup( gc->acc->server, - colon - gc->acc->server ); + if( ( colon = strchr( ic->acc->server, ':' ) ) ) + u->host = g_strndup( ic->acc->server, + colon - ic->acc->server ); else - u->host = g_strdup( gc->acc->server ); + u->host = g_strdup( ic->acc->server ); u->user = g_strdup( handle ); @@ -402,23 +402,23 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } else { - u->host = g_strdup( gc->acc->prpl->name ); + u->host = g_strdup( ic->acc->prpl->name ); u->user = g_strdup( handle ); } - u->gc = gc; + u->ic = ic; u->handle = g_strdup( handle ); if( group ) u->group = g_strdup( group ); u->send_handler = buddy_send_handler; u->last_typing_notice = 0; } -struct buddy *find_buddy( struct gaim_connection *gc, char *handle ) +struct buddy *find_buddy( struct im_connection *ic, char *handle ) { static struct buddy b[1]; user_t *u; - u = user_findhandle( gc, handle ); + u = user_findhandle( ic, handle ); if( !u ) return( NULL ); @@ -427,20 +427,20 @@ struct buddy *find_buddy( struct gaim_connection *gc, char *handle ) strncpy( b->name, handle, 80 ); strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN ); b->present = u->online; - b->gc = u->gc; + b->ic = u->ic; return( b ); } -void signoff_blocked( struct gaim_connection *gc ) +void signoff_blocked( struct im_connection *ic ) { return; /* Make all blocked users look invisible (TODO?) */ } -void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname ) +void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ) { - user_t *u = user_findhandle( gc, handle ); + user_t *u = user_findhandle( ic, handle ); if( !u ) return; @@ -450,8 +450,8 @@ void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname u->realname = g_strdup( realname ); - if( ( gc->flags & OPT_LOGGED_IN ) && set_getbool( &gc->irc->set, "display_namechanges" ) ) - serv_got_crap( gc, "User `%s' changed name to `%s'", u->nick, u->realname ); + if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) + serv_got_crap( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); } } @@ -460,7 +460,7 @@ void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname struct show_got_added_data { - struct gaim_connection *gc; + struct im_connection *ic; char *handle; }; @@ -472,51 +472,51 @@ void show_got_added_no( gpointer w, struct show_got_added_data *data ) void show_got_added_yes( gpointer w, struct show_got_added_data *data ) { - data->gc->acc->prpl->add_buddy( data->gc, data->handle ); - add_buddy( data->gc, NULL, data->handle, data->handle ); + data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL ); + add_buddy( data->ic, NULL, data->handle, data->handle ); return show_got_added_no( w, data ); } -void show_got_added( struct gaim_connection *gc, char *handle, const char *realname ) +void show_got_added( struct im_connection *ic, char *handle, const char *realname ) { struct show_got_added_data *data = g_new0( struct show_got_added_data, 1 ); char *s; /* TODO: Make a setting for this! */ - if( user_findhandle( gc, handle ) != NULL ) + if( user_findhandle( ic, handle ) != NULL ) return; s = g_strdup_printf( "The user %s is not in your buddy list yet. Do you want to add him/her now?", handle ); - data->gc = gc; + data->ic = ic; data->handle = g_strdup( handle ); - query_add( gc->irc, gc, s, show_got_added_yes, show_got_added_no, data ); + query_add( ic->irc, ic, s, show_got_added_yes, show_got_added_no, data ); } /* server.c */ -void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ) +void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ) { user_t *u; int oa, oo; - u = user_findhandle( gc, handle ); + u = user_findhandle( ic, handle ); if( !u ) { - if( g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "add" ) == 0 ) + if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 ) { - add_buddy( gc, NULL, handle, NULL ); - u = user_findhandle( gc, handle ); + add_buddy( ic, NULL, handle, NULL ); + u = user_findhandle( ic, handle ); } else { - if( set_getbool( &gc->irc->set, "debug" ) || g_strcasecmp( set_getstr( &gc->irc->set, "handle_unknown" ), "ignore" ) != 0 ) + if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { - serv_got_crap( gc, "serv_got_update() for handle %s:", handle ); - serv_got_crap( gc, "loggedin = %d, type = %d", loggedin, type ); + serv_got_crap( ic, "serv_got_update() for handle %s:", handle ); + serv_got_crap( ic, "loggedin = %d, type = %d", loggedin, type ); } return; @@ -536,26 +536,26 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in if( loggedin && !u->online ) { - irc_spawn( gc->irc, u ); + irc_spawn( ic->irc, u ); u->online = 1; } else if( !loggedin && u->online ) { - struct conversation *c; + struct groupchat *c; - irc_kill( gc->irc, u ); + irc_kill( ic->irc, u ); u->online = 0; /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */ - for( c = gc->conversations; c; c = c->next ) + for( c = ic->conversations; c; c = c->next ) remove_chat_buddy_silent( c, handle ); } - if( ( type & UC_UNAVAILABLE ) && ( strcmp( gc->acc->prpl->name, "oscar" ) == 0 || strcmp( gc->acc->prpl->name, "icq" ) == 0 ) ) + if( ( type & UC_UNAVAILABLE ) && ( strcmp( ic->acc->prpl->name, "oscar" ) == 0 || strcmp( ic->acc->prpl->name, "icq" ) == 0 ) ) { u->away = g_strdup( "Away" ); } - else if( ( type & UC_UNAVAILABLE ) && ( strcmp( gc->acc->prpl->name, "jabber" ) == 0 ) ) + else if( ( type & UC_UNAVAILABLE ) && ( strcmp( ic->acc->prpl->name, "jabber" ) == 0 ) ) { if( type & UC_DND ) u->away = g_strdup( "Do Not Disturb" ); @@ -564,30 +564,30 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in else // if( type & UC_AWAY ) u->away = g_strdup( "Away" ); } - else if( ( type & UC_UNAVAILABLE ) && gc->acc->prpl->get_status_string ) + else if( ( type & UC_UNAVAILABLE ) && ic->acc->prpl->get_status_string ) { - u->away = g_strdup( gc->acc->prpl->get_status_string( gc, type ) ); + u->away = g_strdup( ic->acc->prpl->get_status_string( ic, type ) ); } else u->away = NULL; /* LISPy... */ - if( ( set_getbool( &gc->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ + if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ ( u->online ) && /* Don't touch offline people */ ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ { - irc_write( gc->irc, ":%s MODE %s %cv %s", gc->irc->myhost, - gc->irc->channel, u->away?'-':'+', u->nick ); + irc_write( ic->irc, ":%s MODE %s %cv %s", ic->irc->myhost, + ic->irc->channel, u->away?'-':'+', u->nick ); } } -void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 flags, time_t mtime, gint len ) +void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ) { - irc_t *irc = gc->irc; + irc_t *irc = ic->irc; user_t *u; - u = user_findhandle( gc, handle ); + u = user_findhandle( ic, handle ); if( !u ) { @@ -596,7 +596,7 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f if( g_strcasecmp( h, "ignore" ) == 0 ) { if( set_getbool( &irc->set, "debug" ) ) - serv_got_crap( gc, "Ignoring message from unknown handle %s", handle ); + serv_got_crap( ic, "Ignoring message from unknown handle %s", handle ); return; } @@ -612,19 +612,19 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f private = 0; } - add_buddy( gc, NULL, handle, NULL ); - u = user_findhandle( gc, handle ); + add_buddy( ic, NULL, handle, NULL ); + u = user_findhandle( ic, handle ); u->is_private = private; } else { - serv_got_crap( gc, "Message from unknown handle %s:", handle ); + serv_got_crap( ic, "Message from unknown handle %s:", handle ); u = user_find( irc, irc->mynick ); } } - if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); while( strlen( msg ) > 425 ) @@ -660,14 +660,14 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f irc_msgfrom( irc, u->nick, msg ); } -void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int type ) +void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ) { user_t *u; - if( !set_getbool( &gc->irc->set, "typing_notice" ) ) + if( !set_getbool( &ic->irc->set, "typing_notice" ) ) return; - if( ( u = user_findhandle( gc, handle ) ) ) { + if( ( u = user_findhandle( ic, handle ) ) ) { /* If type is: * 0: user has stopped typing * 1: user is actively typing @@ -676,19 +676,19 @@ void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int if (type == 0 || type == 1 || type == 2) { char buf[256]; g_snprintf(buf, 256, "\1TYPING %d\1", type); - irc_privmsg( gc->irc, u, "PRIVMSG", gc->irc->nick, NULL, buf ); + irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf ); } } } -void serv_got_chat_left( struct conversation *c ) +void serv_got_chat_left( struct groupchat *c ) { - struct gaim_connection *gc = c->gc; - struct conversation *l = NULL; + struct im_connection *ic = c->ic; + struct groupchat *l = NULL; GList *ir; - if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "You were removed from conversation 0x%x", (int) c ); + if( set_getbool( &ic->irc->set, "debug" ) ) + serv_got_crap( ic, "You were removed from conversation 0x%x", (int) c ); if( c ) { @@ -696,18 +696,18 @@ void serv_got_chat_left( struct conversation *c ) { user_t *u, *r; - r = user_find( gc->irc, gc->irc->mynick ); - irc_privmsg( gc->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" ); + r = user_find( ic->irc, ic->irc->mynick ); + irc_privmsg( ic->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" ); - u = user_find( gc->irc, gc->irc->nick ); - irc_kick( gc->irc, u, c->channel, r ); - /* irc_part( gc->irc, u, c->channel ); */ + u = user_find( ic->irc, ic->irc->nick ); + irc_kick( ic->irc, u, c->channel, r ); + /* irc_part( ic->irc, u, c->channel ); */ } if( l ) l->next = c->next; else - gc->conversations = c->next; + ic->conversations = c->next; for( ir = c->in_room; ir; ir = ir->next ) g_free( ir->data ); @@ -718,47 +718,47 @@ void serv_got_chat_left( struct conversation *c ) } } -void serv_got_chat_in( struct conversation *c, char *who, int whisper, char *msg, time_t mtime ) +void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ) { - struct gaim_connection *gc = c->gc; + struct im_connection *ic = c->ic; user_t *u; /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ - if( g_strcasecmp( who, gc->username ) == 0 ) + if( g_strcasecmp( who, ic->username ) == 0 ) return; - u = user_findhandle( gc, who ); + u = user_findhandle( ic, who ); - if( ( g_strcasecmp( set_getstr( &gc->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( gc->flags & OPT_CONN_HTML ) && set_getbool( &gc->irc->set, "strip_html" ) ) ) + if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); if( c && u ) - irc_privmsg( gc->irc, u, "PRIVMSG", c->channel, "", msg ); + irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", msg ); else - serv_got_crap( gc, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); + serv_got_crap( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); } -struct conversation *serv_got_joined_chat( struct gaim_connection *gc, char *handle ) +struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) { - struct conversation *c; + struct groupchat *c; /* This one just creates the conversation structure, user won't see anything yet */ - if( gc->conversations ) + if( ic->conversations ) { - for( c = gc->conversations; c->next; c = c->next ); - c = c->next = g_new0( struct conversation, 1 ); + for( c = ic->conversations; c->next; c = c->next ); + c = c->next = g_new0( struct groupchat, 1 ); } else - gc->conversations = c = g_new0( struct conversation, 1 ); + ic->conversations = c = g_new0( struct groupchat, 1 ); - c->gc = gc; + c->ic = ic; c->title = g_strdup( handle ); - c->channel = g_strdup_printf( "&chat_%03d", gc->irc->c_id++ ); + c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); - if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); + if( set_getbool( &ic->irc->set, "debug" ) ) + serv_got_crap( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); return c; } @@ -766,20 +766,20 @@ struct conversation *serv_got_joined_chat( struct gaim_connection *gc, char *han /* buddy_chat.c */ -void add_chat_buddy( struct conversation *b, char *handle ) +void add_chat_buddy( struct groupchat *b, char *handle ) { - user_t *u = user_findhandle( b->gc, handle ); + user_t *u = user_findhandle( b->ic, handle ); int me = 0; - if( set_getbool( &b->gc->irc->set, "debug" ) ) - serv_got_crap( b->gc, "User %s added to conversation 0x%x", handle, (int) b ); + if( set_getbool( &b->ic->irc->set, "debug" ) ) + serv_got_crap( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); /* It might be yourself! */ - if( b->gc->acc->prpl->handle_cmp( handle, b->gc->username ) == 0 ) + if( b->ic->acc->prpl->handle_cmp( handle, b->ic->username ) == 0 ) { - u = user_find( b->gc->irc, b->gc->irc->nick ); + u = user_find( b->ic->irc, b->ic->irc->nick ); if( !b->joined ) - irc_join( b->gc->irc, u, b->channel ); + irc_join( b->ic->irc, u, b->channel ); b->joined = me = 1; } @@ -787,45 +787,45 @@ void add_chat_buddy( struct conversation *b, char *handle ) your contact list. Try to handle that here */ if( !u ) { - add_buddy( b->gc, NULL, handle, NULL ); - u = user_findhandle( b->gc, handle ); + add_buddy( b->ic, NULL, handle, NULL ); + u = user_findhandle( b->ic, handle ); } /* Add the handle to the room userlist, if it's not 'me' */ if( !me ) { if( b->joined ) - irc_join( b->gc->irc, u, b->channel ); + irc_join( b->ic->irc, u, b->channel ); b->in_room = g_list_append( b->in_room, g_strdup( handle ) ); } } -void remove_chat_buddy( struct conversation *b, char *handle, char *reason ) +void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ) { user_t *u; int me = 0; - if( set_getbool( &b->gc->irc->set, "debug" ) ) - serv_got_crap( b->gc, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); + if( set_getbool( &b->ic->irc->set, "debug" ) ) + serv_got_crap( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); /* It might be yourself! */ - if( g_strcasecmp( handle, b->gc->username ) == 0 ) + if( g_strcasecmp( handle, b->ic->username ) == 0 ) { - u = user_find( b->gc->irc, b->gc->irc->nick ); + u = user_find( b->ic->irc, b->ic->irc->nick ); b->joined = 0; me = 1; } else { - u = user_findhandle( b->gc, handle ); + u = user_findhandle( b->ic, handle ); } if( remove_chat_buddy_silent( b, handle ) ) if( ( b->joined || me ) && u ) - irc_part( b->gc->irc, u, b->channel ); + irc_part( b->ic->irc, u, b->channel ); } -static int remove_chat_buddy_silent( struct conversation *b, char *handle ) +static int remove_chat_buddy_silent( struct groupchat *b, char *handle ) { GList *i; @@ -849,17 +849,17 @@ static int remove_chat_buddy_silent( struct conversation *b, char *handle ) /* Misc. BitlBee stuff which shouldn't really be here */ -struct conversation *chat_by_channel( char *channel ) +struct groupchat *chat_by_channel( char *channel ) { - struct gaim_connection *gc; - struct conversation *c; + struct im_connection *ic; + struct groupchat *c; GSList *l; /* This finds the connection which has a conversation which belongs to this channel */ for( l = connections; l; l = l->next ) { - gc = l->data; - for( c = gc->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); + ic = l->data; + for( c = ic->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); if( c ) return c; } @@ -898,7 +898,7 @@ char *set_eval_away_devoice( set_t *set, char *value ) while( u ) { - if( u->gc && u->online && !u->away ) + if( u->ic && u->online && !u->away ) { if( ( strlen( list ) + strlen( u->nick ) ) >= 79 ) { @@ -932,49 +932,49 @@ char *set_eval_away_devoice( set_t *set, char *value ) /* The plan is to not allow straight calls to prpl functions anymore, but do them all from some wrappers. We'll start to define some down here: */ -int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flags ) +int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ) { char *buf = NULL; int st; - if( ( gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) + if( ( ic->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { buf = escape_html( msg ); msg = buf; } - st = gc->acc->prpl->send_im( gc, handle, msg, strlen( msg ), flags ); + st = ic->acc->prpl->send_im( ic, handle, msg, flags ); g_free( buf ); return st; } -int bim_chat_msg( struct conversation *c, char *msg ) +int bim_chat_msg( struct groupchat *c, char *msg, int flags ) { char *buf = NULL; int st; - if( ( c->gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) + if( ( c->ic->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { buf = escape_html( msg ); msg = buf; } - st = c->gc->acc->prpl->chat_send( c, msg ); + c->ic->acc->prpl->chat_send( c, msg, flags ); g_free( buf ); - return st; + return 1; } static char *bim_away_alias_find( GList *gcm, char *away ); -int bim_set_away( struct gaim_connection *gc, char *away ) +int bim_set_away( struct im_connection *ic, char *away ) { GList *m, *ms; char *s; if( !away ) away = ""; - ms = m = gc->acc->prpl->away_states( gc ); + ms = m = ic->acc->prpl->away_states( ic ); while( m ) { @@ -995,19 +995,19 @@ int bim_set_away( struct gaim_connection *gc, char *away ) if( m ) { - gc->acc->prpl->set_away( gc, m->data, *away ? away : NULL ); + ic->acc->prpl->set_away( ic, m->data, *away ? away : NULL ); } else { s = bim_away_alias_find( ms, away ); if( s ) { - gc->acc->prpl->set_away( gc, s, away ); - if( set_getbool( &gc->irc->set, "debug" ) ) - serv_got_crap( gc, "Setting away state to %s", s ); + ic->acc->prpl->set_away( ic, s, away ); + if( set_getbool( &ic->irc->set, "debug" ) ) + serv_got_crap( ic, "Setting away state to %s", s ); } else - gc->acc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away ); + ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away ); } return( 1 ); @@ -1055,48 +1055,48 @@ static char *bim_away_alias_find( GList *gcm, char *away ) return( NULL ); } -void bim_add_allow( struct gaim_connection *gc, char *handle ) +void bim_add_allow( struct im_connection *ic, char *handle ) { - if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) + if( g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) { - gc->permit = g_slist_prepend( gc->permit, g_strdup( handle ) ); + ic->permit = g_slist_prepend( ic->permit, g_strdup( handle ) ); } - gc->acc->prpl->add_permit( gc, handle ); + ic->acc->prpl->add_permit( ic, handle ); } -void bim_rem_allow( struct gaim_connection *gc, char *handle ) +void bim_rem_allow( struct im_connection *ic, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) + if( ( l = g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); - gc->permit = g_slist_delete_link( gc->permit, l ); + ic->permit = g_slist_delete_link( ic->permit, l ); } - gc->acc->prpl->rem_permit( gc, handle ); + ic->acc->prpl->rem_permit( ic, handle ); } -void bim_add_block( struct gaim_connection *gc, char *handle ) +void bim_add_block( struct im_connection *ic, char *handle ) { - if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) + if( g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) { - gc->deny = g_slist_prepend( gc->deny, g_strdup( handle ) ); + ic->deny = g_slist_prepend( ic->deny, g_strdup( handle ) ); } - gc->acc->prpl->add_deny( gc, handle ); + ic->acc->prpl->add_deny( ic, handle ); } -void bim_rem_block( struct gaim_connection *gc, char *handle ) +void bim_rem_block( struct im_connection *ic, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) + if( ( l = g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); - gc->deny = g_slist_delete_link( gc->deny, l ); + ic->deny = g_slist_delete_link( ic->deny, l ); } - gc->acc->prpl->rem_deny( gc, handle ); + ic->acc->prpl->rem_deny( ic, handle ); } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 6afa1801..82472fd3 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -61,7 +61,7 @@ #define OPT_LOGGING_OUT 0x00020000 /* ok. now the fun begins. first we create a connection structure */ -struct gaim_connection +struct im_connection { account_t *acc; guint32 flags; @@ -91,19 +91,19 @@ struct gaim_connection /* BitlBee */ irc_t *irc; - struct conversation *conversations; + struct groupchat *conversations; }; /* struct buddy_chat went away and got merged with this. */ -struct conversation { - struct gaim_connection *gc; +struct groupchat { + struct im_connection *ic; /* stuff used just for chat */ GList *in_room; GList *ignored; /* BitlBee */ - struct conversation *next; + struct groupchat *next; char *channel; char *title; char joined; @@ -120,49 +120,57 @@ struct buddy { int uc; guint caps; /* woohoo! */ void *proto_data; /* what a hack */ - struct gaim_connection *gc; /* the connection it belongs to */ + struct im_connection *ic; /* the connection it belongs to */ }; struct prpl { int options; const char *name; - void (* acc_init) (account_t *); + /* Added this one to be able to add per-account settings, don't think + it should be used for anything else. */ + void (* init) (account_t *); + /* These should all be pretty obvious. */ void (* login) (account_t *); - void (* keepalive) (struct gaim_connection *); - void (* close) (struct gaim_connection *); - - int (* send_im) (struct gaim_connection *, char *who, char *message, int len, int away); - void (* set_away) (struct gaim_connection *, char *state, char *message); - void (* get_away) (struct gaim_connection *, char *who); - int (* send_typing) (struct gaim_connection *, char *who, int typing); - - void (* add_buddy) (struct gaim_connection *, char *name); - void (* group_buddy) (struct gaim_connection *, char *who, char *old_group, char *new_group); - void (* remove_buddy) (struct gaim_connection *, char *name, char *group); - void (* add_permit) (struct gaim_connection *, char *name); - void (* add_deny) (struct gaim_connection *, char *name); - void (* rem_permit) (struct gaim_connection *, char *name); - void (* rem_deny) (struct gaim_connection *, char *name); - void (* set_permit_deny)(struct gaim_connection *); - - void (* set_info) (struct gaim_connection *, char *info); - void (* get_info) (struct gaim_connection *, char *who); - void (* alias_buddy) (struct gaim_connection *, char *who); /* save/store buddy's alias on server list/roster */ + void (* keepalive) (struct im_connection *); + void (* logout) (struct im_connection *); + + int (* send_im) (struct im_connection *, char *to, char *message, int flags); + void (* set_away) (struct im_connection *, char *state, char *message); + void (* get_away) (struct im_connection *, char *who); + int (* send_typing) (struct im_connection *, char *who, int typing); + + /* For now BitlBee doesn't really handle groups, just set it to NULL. */ + void (* add_buddy) (struct im_connection *, char *name, char *group); + void (* remove_buddy) (struct im_connection *, char *name, char *group); + + /* Block list stuff. */ + void (* add_permit) (struct im_connection *, char *who); + void (* add_deny) (struct im_connection *, char *who); + void (* rem_permit) (struct im_connection *, char *who); + void (* rem_deny) (struct im_connection *, char *who); + /* Doesn't actually have UI hooks. */ + void (* set_permit_deny)(struct im_connection *); + + /* Request profile info. Free-formatted stuff, the IM module gives back + this info via imc_log(). */ + void (* get_info) (struct im_connection *, char *who); + void (* set_my_name) (struct im_connection *, char *name); + void (* set_name) (struct im_connection *, char *who, char *name); /* Group chat stuff. */ - void (* chat_invite) (struct conversation *, char *who, char *message); - void (* chat_leave) (struct conversation *); - int (* chat_send) (struct conversation *, char *message); - struct conversation * - (* chat_open) (struct gaim_connection *, char *who); - struct conversation * - (* chat_join) (struct gaim_connection *, char *chat, char *nick, char *password); + void (* chat_invite) (struct groupchat *, char *who, char *message); + void (* chat_leave) (struct groupchat *); + void (* chat_send) (struct groupchat *, char *message, int flags); + struct groupchat * + (* chat_with) (struct im_connection *, char *who); + struct groupchat * + (* chat_join) (struct im_connection *, char *chat, char *nick, char *password); /* DIE! */ - char *(* get_status_string) (struct gaim_connection *gc, int stat); + char *(* get_status_string) (struct im_connection *ic, int stat); - GList *(* away_states)(struct gaim_connection *gc); + GList *(* away_states)(struct im_connection *ic); /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ int (* handle_cmp) (const char *who1, const char *who2); @@ -181,14 +189,14 @@ G_MODULE_EXPORT struct prpl *find_protocol(const char *name); G_MODULE_EXPORT void register_protocol(struct prpl *); /* nogaim.c */ -int bim_set_away( struct gaim_connection *gc, char *away ); -int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flags ); -int bim_chat_msg( struct conversation *c, char *msg ); +int bim_set_away( struct im_connection *ic, char *away ); +int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); +int bim_chat_msg( struct groupchat *c, char *msg, int flags ); -void bim_add_allow( struct gaim_connection *gc, char *handle ); -void bim_rem_allow( struct gaim_connection *gc, char *handle ); -void bim_add_block( struct gaim_connection *gc, char *handle ); -void bim_rem_block( struct gaim_connection *gc, char *handle ); +void bim_add_allow( struct im_connection *ic, char *handle ); +void bim_rem_allow( struct im_connection *ic, char *handle ); +void bim_add_block( struct im_connection *ic, char *handle ); +void bim_rem_block( struct im_connection *ic, char *handle ); void nogaim_init(); char *set_eval_away_devoice( set_t *set, char *value ); @@ -197,43 +205,43 @@ gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); void cancel_auto_reconnect( struct account *a ); /* multi.c */ -G_MODULE_EXPORT struct gaim_connection *new_gaim_conn( account_t *acc ); -G_MODULE_EXPORT void destroy_gaim_conn( struct gaim_connection *gc ); -G_MODULE_EXPORT void set_login_progress( struct gaim_connection *gc, int step, char *msg ); -G_MODULE_EXPORT void hide_login_progress( struct gaim_connection *gc, char *msg ); -G_MODULE_EXPORT void hide_login_progress_error( struct gaim_connection *gc, char *msg ); -G_MODULE_EXPORT void serv_got_crap( struct gaim_connection *gc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); -G_MODULE_EXPORT void account_online( struct gaim_connection *gc ); -G_MODULE_EXPORT void signoff( struct gaim_connection *gc ); +G_MODULE_EXPORT struct im_connection *new_gaim_conn( account_t *acc ); +G_MODULE_EXPORT void destroy_gaim_conn( struct im_connection *ic ); +G_MODULE_EXPORT void set_login_progress( struct im_connection *ic, int step, char *msg ); +G_MODULE_EXPORT void hide_login_progress( struct im_connection *ic, char *msg ); +G_MODULE_EXPORT void hide_login_progress_error( struct im_connection *ic, char *msg ); +G_MODULE_EXPORT void serv_got_crap( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +G_MODULE_EXPORT void account_online( struct im_connection *ic ); +G_MODULE_EXPORT void signoff( struct im_connection *ic ); /* dialogs.c */ -G_MODULE_EXPORT void do_error_dialog( struct gaim_connection *gc, char *msg, char *title ); -G_MODULE_EXPORT void do_ask_dialog( struct gaim_connection *gc, char *msg, void *data, void *doit, void *dont ); +G_MODULE_EXPORT void do_error_dialog( struct im_connection *ic, char *msg, char *title ); +G_MODULE_EXPORT void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); /* list.c */ -G_MODULE_EXPORT void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *realname ); -G_MODULE_EXPORT struct buddy *find_buddy( struct gaim_connection *gc, char *handle ); -G_MODULE_EXPORT void signoff_blocked( struct gaim_connection *gc ); +G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ); +G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void signoff_blocked( struct im_connection *ic ); -G_MODULE_EXPORT void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname ); +G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ); /* buddy_chat.c */ -G_MODULE_EXPORT void add_chat_buddy( struct conversation *b, char *handle ); -G_MODULE_EXPORT void remove_chat_buddy( struct conversation *b, char *handle, char *reason ); +G_MODULE_EXPORT void add_chat_buddy( struct groupchat *b, char *handle ); +G_MODULE_EXPORT void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ); /* prpl.c */ -G_MODULE_EXPORT void show_got_added( struct gaim_connection *gc, char *handle, const char *realname ); +G_MODULE_EXPORT void show_got_added( struct im_connection *ic, char *handle, const char *realname ); /* server.c */ -G_MODULE_EXPORT void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); -G_MODULE_EXPORT void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); -G_MODULE_EXPORT void serv_got_typing( struct gaim_connection *gc, char *handle, int timeout, int type ); -G_MODULE_EXPORT void serv_got_chat_invite( struct gaim_connection *gc, char *handle, char *who, char *msg, GList *data ); -G_MODULE_EXPORT struct conversation *serv_got_joined_chat( struct gaim_connection *gc, char *handle ); -G_MODULE_EXPORT void serv_got_chat_in( struct conversation *c, char *who, int whisper, char *msg, time_t mtime ); -G_MODULE_EXPORT void serv_got_chat_left( struct conversation *c ); - -struct conversation *chat_by_channel( char *channel ); -struct conversation *chat_by_id( int id ); +G_MODULE_EXPORT void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); +G_MODULE_EXPORT void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); +G_MODULE_EXPORT void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ); +G_MODULE_EXPORT void serv_got_chat_invite( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); +G_MODULE_EXPORT struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ); +G_MODULE_EXPORT void serv_got_chat_left( struct groupchat *c ); + +struct groupchat *chat_by_channel( char *channel ); +struct groupchat *chat_by_id( int id ); #endif diff --git a/protocols/oscar/aim.h b/protocols/oscar/aim.h index 93887103..81ea5f9e 100644 --- a/protocols/oscar/aim.h +++ b/protocols/oscar/aim.h @@ -573,7 +573,7 @@ struct aim_chat_roominfo { }; struct aim_chat_invitation { - struct gaim_connection * gc; + struct im_connection * ic; char * name; guint8 exchange; }; diff --git a/protocols/oscar/im.c b/protocols/oscar/im.c index 7cccabc7..bc2c2abe 100644 --- a/protocols/oscar/im.c +++ b/protocols/oscar/im.c @@ -1416,7 +1416,7 @@ static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod guint8 msgtype, msgflags; guint8 *plugin; int i = 0, tmp = 0; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; /* at the moment we just can deal with requests, not with cancel or accept */ if (args->status != 0) return; @@ -1468,7 +1468,7 @@ static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod case AIM_MTYPE_AUTOFFC: case 0x9c: /* ICQ 5 seems to send this */ aim_send_im_ch2_statusmessage(sess, userinfo->sn, args->cookie, - gc->away ? gc->away : "", sess->aim_icq_state, dc); + ic->away ? ic->away : "", sess->aim_icq_state, dc); break; } diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 05539442..d2c6af1e 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -115,21 +115,21 @@ struct chat_connection { aim_conn_t *conn; int inpa; int id; - struct gaim_connection *gc; /* i hate this. */ - struct conversation *cnv; /* bah. */ + struct im_connection *ic; /* i hate this. */ + struct groupchat *cnv; /* bah. */ int maxlen; int maxvis; }; struct ask_direct { - struct gaim_connection *gc; + struct im_connection *ic; char *sn; char ip[64]; guint8 cookie[8]; }; struct icq_auth { - struct gaim_connection *gc; + struct im_connection *ic; guint32 uin; }; @@ -157,9 +157,9 @@ static char *extract_name(const char *name) { return tmp; } -static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, +static struct chat_connection *find_oscar_chat_by_conn(struct im_connection *ic, aim_conn_t *conn) { - GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; + GSList *g = ((struct oscar_data *)ic->proto_data)->oscar_chats; struct chat_connection *c = NULL; while (g) { @@ -242,34 +242,34 @@ static gboolean oscar_callback(gpointer data, gint source, b_input_condition condition) { aim_conn_t *conn = (aim_conn_t *)data; aim_session_t *sess = aim_conn_getsess(conn); - struct gaim_connection *gc = sess ? sess->aux_data : NULL; + struct im_connection *ic = sess ? sess->aux_data : NULL; struct oscar_data *odata; - if (!gc) { - /* gc is null. we return, else we seg SIGSEG on next line. */ + if (!ic) { + /* ic is null. we return, else we seg SIGSEG on next line. */ return FALSE; } - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { /* oh boy. this is probably bad. i guess the only thing we * can really do is return? */ return FALSE; } - odata = (struct oscar_data *)gc->proto_data; + odata = (struct oscar_data *)ic->proto_data; if (condition & GAIM_INPUT_READ) { if (aim_get_command(odata->sess, conn) >= 0) { aim_rxdispatch(odata->sess); if (odata->killme) - signoff(gc); + signoff(ic); } else { if ((conn->type == AIM_CONN_TYPE_BOS) || !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { - hide_login_progress_error(gc, _("Disconnected.")); - signoff(gc); + hide_login_progress_error(ic, _("Disconnected.")); + signoff(ic); } else if (conn->type == AIM_CONN_TYPE_CHAT) { - struct chat_connection *c = find_oscar_chat_by_conn(gc, conn); + struct chat_connection *c = find_oscar_chat_by_conn(ic, conn); char buf[BUF_LONG]; c->conn = NULL; if (c->inpa > 0) @@ -312,34 +312,34 @@ static gboolean oscar_callback(gpointer data, gint source, static gboolean oscar_login_connect(gpointer data, gint source, b_input_condition cond) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; aim_conn_t *conn; - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { closesocket(source); return FALSE; } - odata = gc->proto_data; + odata = ic->proto_data; sess = odata->sess; conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); if (source < 0) { - hide_login_progress(gc, _("Couldn't connect to host")); - signoff(gc); + hide_login_progress(ic, _("Couldn't connect to host")); + signoff(ic); return FALSE; } aim_conn_completeconnect(sess, conn); - gc->inpa = b_input_add(conn->fd, GAIM_INPUT_READ, + ic->inpa = b_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn); return FALSE; } -static void oscar_acc_init(account_t *acc) +static void oscar_init(account_t *acc) { set_t *s; @@ -356,17 +356,17 @@ static void oscar_login(account_t *acc) { aim_session_t *sess; aim_conn_t *conn; char buf[256]; - struct gaim_connection *gc = new_gaim_conn(acc); - struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1); + struct im_connection *ic = new_gaim_conn(acc); + struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); if (isdigit(acc->user[0])) { odata->icq = TRUE; /* This is odd but it's necessary for a proper do_import and do_export. We don't do those anymore, but let's stick with it, just in case it accidentally fixes something else too... </bitlbee> */ - gc->password[8] = 0; + ic->password[8] = 0; } else { - gc->flags |= OPT_CONN_HTML; + ic->flags |= OPT_CONN_HTML; } sess = g_new0(aim_session_t, 1); @@ -377,44 +377,44 @@ static void oscar_login(account_t *acc) { * see if things need to be sent. */ aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL); odata->sess = sess; - sess->aux_data = gc; + sess->aux_data = ic; conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (conn == NULL) { - hide_login_progress(gc, _("Unable to login to AIM")); - signoff(gc); + hide_login_progress(ic, _("Unable to login to AIM")); + signoff(ic); return; } if (acc->server == NULL) { - hide_login_progress(gc, "No servername specified"); - signoff(gc); + hide_login_progress(ic, "No servername specified"); + signoff(ic); return; } if (g_strcasecmp(acc->server, "login.icq.com") != 0 && g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { - serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); + serv_got_crap(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); } - g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username); - set_login_progress(gc, 2, buf); + g_snprintf(buf, sizeof(buf), _("Signon: %s"), ic->username); + set_login_progress(ic, 2, buf); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); conn->status |= AIM_CONN_STATUS_INPROGRESS; - conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, gc); + conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, ic); if (conn->fd < 0) { - hide_login_progress(gc, _("Couldn't connect to host")); - signoff(gc); + hide_login_progress(ic, _("Couldn't connect to host")); + signoff(ic); return; } - aim_request_login(sess, conn, gc->username); + aim_request_login(sess, conn, ic->username); } -static void oscar_close(struct gaim_connection *gc) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; +static void oscar_logout(struct im_connection *ic) { + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; while (odata->oscar_chats) { struct chat_connection *n = odata->oscar_chats->data; @@ -437,8 +437,8 @@ static void oscar_close(struct gaim_connection *gc) { g_free(odata->newp); if (odata->oldp) g_free(odata->oldp); - if (gc->inpa > 0) - b_event_remove(gc->inpa); + if (ic->inpa > 0) + b_event_remove(ic->inpa); if (odata->cnpa > 0) b_event_remove(odata->cnpa); if (odata->paspa > 0) @@ -446,35 +446,35 @@ static void oscar_close(struct gaim_connection *gc) { aim_session_kill(odata->sess); g_free(odata->sess); odata->sess = NULL; - g_free(gc->proto_data); - gc->proto_data = NULL; + g_free(ic->proto_data); + ic->proto_data = NULL; } static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; aim_conn_t *bosconn; - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { closesocket(source); return FALSE; } - odata = gc->proto_data; + odata = ic->proto_data; sess = odata->sess; bosconn = odata->conn; if (source < 0) { - hide_login_progress(gc, _("Could Not Connect")); - signoff(gc); + hide_login_progress(ic, _("Could Not Connect")); + signoff(ic); return FALSE; } aim_conn_completeconnect(sess, bosconn); - gc->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, + ic->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); - set_login_progress(gc, 4, _("Connection established, cookie sent")); + set_login_progress(ic, 4, _("Connection established, cookie sent")); return FALSE; } @@ -485,8 +485,8 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { int i; char *host; int port; aim_conn_t *bosconn; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *od = ic->proto_data; port = AIM_LOGIN_PORT; va_start(ap, fr); @@ -497,23 +497,23 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { switch (info->errorcode) { case 0x05: /* Incorrect nick/password */ - hide_login_progress(gc, _("Incorrect nickname or password.")); + hide_login_progress(ic, _("Incorrect nickname or password.")); // plugin_event(event_error, (void *)980, 0, 0, 0); break; case 0x11: /* Suspended account */ - hide_login_progress(gc, _("Your account is currently suspended.")); + hide_login_progress(ic, _("Your account is currently suspended.")); break; case 0x18: /* connecting too frequently */ - hide_login_progress(gc, _("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.")); + hide_login_progress(ic, _("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.")); break; case 0x1c: /* client too old */ - hide_login_progress(gc, _("The client version you are using is too old. Please upgrade at " WEBSITE)); + hide_login_progress(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE)); break; default: - hide_login_progress(gc, _("Authentication Failed")); + hide_login_progress(ic, _("Authentication Failed")); break; } od->killme = TRUE; @@ -525,7 +525,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); if (bosconn == NULL) { - hide_login_progress(gc, _("Internal Error")); + hide_login_progress(ic, _("Internal Error")); od->killme = TRUE; return 0; } @@ -559,7 +559,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parseaiminfo, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parsemtn, 0); - ((struct oscar_data *)gc->proto_data)->conn = bosconn; + ((struct oscar_data *)ic->proto_data)->conn = bosconn; for (i = 0; i < (int)strlen(info->bosip); i++) { if (info->bosip[i] == ':') { port = atoi(&(info->bosip[i+1])); @@ -568,21 +568,21 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { } host = g_strndup(info->bosip, i); bosconn->status |= AIM_CONN_STATUS_INPROGRESS; - bosconn->fd = proxy_connect(host, port, oscar_bos_connect, gc); + bosconn->fd = proxy_connect(host, port, oscar_bos_connect, ic); g_free(host); if (bosconn->fd < 0) { - hide_login_progress(gc, _("Could Not Connect")); + hide_login_progress(ic, _("Could Not Connect")); od->killme = TRUE; return 0; } aim_sendcookie(sess, bosconn, info->cookie); - b_event_remove(gc->inpa); + b_event_remove(ic->inpa); return 1; } struct pieceofcrap { - struct gaim_connection *gc; + struct im_connection *ic; unsigned long offset; unsigned long len; char *modname; @@ -594,7 +594,7 @@ struct pieceofcrap { static gboolean damn_you(gpointer data, gint source, b_input_condition c) { struct pieceofcrap *pos = data; - struct oscar_data *od = pos->gc->proto_data; + struct oscar_data *od = pos->ic->proto_data; char in = '\0'; int x = 0; unsigned char m[17]; @@ -609,7 +609,7 @@ static gboolean damn_you(gpointer data, gint source, b_input_condition c) in = '\0'; } if (in != '\n') { - do_error_dialog(pos->gc, "Gaim was unable to get a valid hash for logging into AIM." + do_error_dialog(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly.", "Login Error"); b_event_remove(pos->inpa); closesocket(pos->fd); @@ -632,7 +632,7 @@ static gboolean straight_to_hell(gpointer data, gint source, b_input_condition c char buf[BUF_LONG]; if (source < 0) { - do_error_dialog(pos->gc, "Gaim was unable to get a valid hash for logging into AIM." + do_error_dialog(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly.", "Login Error"); if (pos->modname) g_free(pos->modname); @@ -698,7 +698,7 @@ int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) { */ pos = g_new0(struct pieceofcrap, 1); - pos->gc = sess->aux_data; + pos->ic = sess->aux_data; pos->conn = fr->conn; pos->offset = offset; @@ -726,19 +726,19 @@ static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) { #endif char *key; va_list ap; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; va_start(ap, fr); key = va_arg(ap, char *); va_end(ap); - aim_send_login(sess, fr->conn, gc->username, gc->password, &info, key); + aim_send_login(sess, fr->conn, ic->username, ic->password, &info, key); return 1; } static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; struct chat_connection *chatcon; static int id = 1; @@ -750,9 +750,9 @@ static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { aim_clientready(sess, fr->conn); - chatcon = find_oscar_chat_by_conn(gc, fr->conn); + chatcon = find_oscar_chat_by_conn(ic, fr->conn); chatcon->id = id; - chatcon->cnv = serv_got_joined_chat(gc, chatcon->show); + chatcon->cnv = serv_got_joined_chat(ic, chatcon->show); chatcon->cnv->data = chatcon; return 1; @@ -771,17 +771,17 @@ static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) { } static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; aim_conn_t *tstconn; - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { closesocket(source); return FALSE; } - odata = gc->proto_data; + odata = ic->proto_data; sess = odata->sess; tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV); @@ -799,17 +799,17 @@ static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condit static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition cond) { - struct gaim_connection *gc = data; + struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; aim_conn_t *tstconn; - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { closesocket(source); return FALSE; } - odata = gc->proto_data; + odata = ic->proto_data; sess = odata->sess; tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); @@ -828,12 +828,12 @@ static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition cond) { struct chat_connection *ccon = data; - struct gaim_connection *gc = ccon->gc; + struct im_connection *ic = ccon->ic; struct oscar_data *odata; aim_session_t *sess; aim_conn_t *tstconn; - if (!g_slist_find(get_connections(), gc)) { + if (!g_slist_find(get_connections(), ic)) { closesocket(source); g_free(ccon->show); g_free(ccon->name); @@ -841,7 +841,7 @@ static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition return FALSE; } - odata = gc->proto_data; + odata = ic->proto_data; sess = odata->sess; tstconn = ccon->conn; @@ -866,7 +866,7 @@ static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; struct aim_redirect_data *redir; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; aim_conn_t *tstconn; int i; char *host; @@ -898,7 +898,7 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { // aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0); tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - tstconn->fd = proxy_connect(host, port, oscar_auth_connect, gc); + tstconn->fd = proxy_connect(host, port, oscar_auth_connect, ic); if (tstconn->fd < 0) { aim_conn_kill(sess, &tstconn); g_free(host); @@ -915,7 +915,7 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0); tstconn->status |= AIM_CONN_STATUS_INPROGRESS; - tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, gc); + tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, ic); if (tstconn->fd < 0) { aim_conn_kill(sess, &tstconn); g_free(host); @@ -937,7 +937,7 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { ccon = g_new0(struct chat_connection, 1); ccon->conn = tstconn; - ccon->gc = gc; + ccon->ic = ic; ccon->fd = -1; ccon->name = g_strdup(redir->chat.room); ccon->exchange = redir->chat.exchange; @@ -966,8 +966,8 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { } static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *od = ic->proto_data; aim_userinfo_t *info; time_t time_idle = 0, signon = 0; int type = 0; @@ -1017,12 +1017,12 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) signon = time(NULL) - info->sessionlen; - tmp = g_strdup(normalize(gc->username)); + tmp = g_strdup(normalize(ic->username)); if (!strcmp(tmp, normalize(info->sn))) - g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", info->sn); + g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); g_free(tmp); - serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon, + serv_got_update(ic, info->sn, 1, info->warnlevel/10, signon, time_idle, type, caps); return 1; @@ -1031,20 +1031,20 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) { aim_userinfo_t *info; va_list ap; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); va_end(ap); - serv_got_update(gc, info->sn, 0, 0, 0, 0, 0, 0); + serv_got_update(ic, info->sn, 0, 0, 0, 0, 0, 0); return 1; } static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { char *tmp = g_malloc(BUF_LONG + 1); - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; int flags = 0; if (args->icbmflags & AIM_IMFLAGS_AWAY) @@ -1082,7 +1082,7 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ g_snprintf(tmp, BUF_LONG, "%s", args->msg); strip_linefeed(tmp); - serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); + serv_got_im(ic, userinfo->sn, tmp, flags, time(NULL), -1); g_free(tmp); return 1; @@ -1092,7 +1092,7 @@ void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv); void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv); static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; if (args->status != AIM_RENDEZVOUS_PROPOSE) return 1; @@ -1110,11 +1110,11 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", name, userinfo->sn, args->msg ); - inv->gc = gc; + inv->ic = ic; inv->exchange = *exch; inv->name = g_strdup(name); - do_ask_dialog( gc, txt, inv, oscar_accept_chat, oscar_reject_chat); + do_ask_dialog( ic, txt, inv, oscar_accept_chat, oscar_reject_chat); if (name) g_free(name); @@ -1125,14 +1125,14 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { char *uin, message; - struct oscar_data *od = (struct oscar_data *)data->gc->proto_data; + struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; uin = g_strdup_printf("%u", data->uin); message = 0; aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); - if(find_buddy(data->gc, uin) == NULL) - show_got_added(data->gc, uin, NULL); + if(find_buddy(data->ic, uin) == NULL) + show_got_added(data->ic, uin, NULL); g_free(uin); g_free(data); @@ -1140,7 +1140,7 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) { char *uin, *message; - struct oscar_data *od = (struct oscar_data *)data->gc->proto_data; + struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; uin = g_strdup_printf("%u", data->uin); message = g_strdup_printf("No reason given."); @@ -1155,7 +1155,7 @@ static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) { /* * For when other people ask you for authorization */ -static void gaim_icq_authask(struct gaim_connection *gc, guint32 uin, char *msg) { +static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) { struct icq_auth *data = g_new(struct icq_auth, 1); char *reason = NULL; char *dialog_msg; @@ -1164,14 +1164,14 @@ static void gaim_icq_authask(struct gaim_connection *gc, guint32 uin, char *msg) reason = msg + 6; dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s", uin, reason ? reason : "No reason given."); - data->gc = gc; + data->ic = ic; data->uin = uin; - do_ask_dialog(gc, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); + do_ask_dialog(ic, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); g_free(dialog_msg); } static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; switch (args->type) { case 0x0001: { /* An almost-normal instant message. Mac ICQ sends this. It's peculiar. */ @@ -1179,7 +1179,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ uin = g_strdup_printf("%u", args->uin); message = g_strdup(args->msg); strip_linefeed(message); - serv_got_im(gc, uin, message, 0, time(NULL), -1); + serv_got_im(ic, uin, message, 0, time(NULL), -1); g_free(uin); g_free(message); } break; @@ -1198,14 +1198,14 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } strip_linefeed(message); - serv_got_im(gc, uin, message, 0, time(NULL), -1); + serv_got_im(ic, uin, message, 0, time(NULL), -1); g_free(uin); g_free(m); g_free(message); } break; case 0x0006: { /* Someone requested authorization */ - gaim_icq_authask(gc, args->uin, args->msg); + gaim_icq_authask(ic, args->uin, args->msg); } break; case 0x0007: { /* Someone has denied you authorization */ @@ -1417,8 +1417,8 @@ static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; guint16 type; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; va_start(ap, fr); type = (guint16)va_arg(ap, unsigned int); @@ -1476,7 +1476,7 @@ static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; - struct gaim_connection *g = sess->aux_data; + struct im_connection *g = sess->aux_data; struct chat_connection *c = NULL; @@ -1499,7 +1499,7 @@ static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; int count, i; aim_userinfo_t *info; - struct gaim_connection *g = sess->aux_data; + struct im_connection *g = sess->aux_data; struct chat_connection *c = NULL; @@ -1527,8 +1527,8 @@ static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) { char *roomdesc; guint16 unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; guint32 creationtime; - struct gaim_connection *gc = sess->aux_data; - struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn); + struct im_connection *ic = sess->aux_data; + struct chat_connection *ccon = find_oscar_chat_by_conn(ic, fr->conn); va_start(ap, fr); roominfo = va_arg(ap, struct aim_chat_roominfo *); @@ -1554,8 +1554,8 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; aim_userinfo_t *info; char *msg; - struct gaim_connection *gc = sess->aux_data; - struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn); + struct im_connection *ic = sess->aux_data; + struct chat_connection *ccon = find_oscar_chat_by_conn(ic, fr->conn); char *tmp; va_start(ap, fr); @@ -1616,14 +1616,14 @@ static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; aim_userinfo_t *info; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); va_end(ap); - gc->evil = info->warnlevel/10; - /* gc->correction_time = (info->onlinesince - gc->login_time); */ + ic->evil = info->warnlevel/10; + /* ic->correction_time = (info->onlinesince - ic->login_time); */ return 1; } @@ -1645,8 +1645,8 @@ static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) { } static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *od = gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *od = ic->proto_data; aim_clientready(sess, fr->conn); @@ -1703,8 +1703,8 @@ static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; guint16 maxsiglen; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; va_start(ap, fr); maxsiglen = va_arg(ap, int); @@ -1714,7 +1714,7 @@ static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) /* FIXME: It seems we're not really using this, and it broke now that struct aim_user is dead. - aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps); + aim_bos_setprofile(sess, fr->conn, ic->user->user_info, NULL, gaim_caps); */ return 1; @@ -1723,8 +1723,8 @@ static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; guint16 maxbuddies, maxwatchers; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; va_start(ap, fr); maxbuddies = (guint16)va_arg(ap, unsigned int); @@ -1740,8 +1740,8 @@ static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) { guint16 maxpermits, maxdenies; va_list ap; - struct gaim_connection *gc = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct im_connection *ic = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; va_start(ap, fr); maxpermits = (guint16)va_arg(ap, unsigned int); @@ -1764,7 +1764,7 @@ static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; struct aim_icq_offlinemsg *msg; - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; va_start(ap, fr); msg = va_arg(ap, struct aim_icq_offlinemsg *); @@ -1777,7 +1777,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); g_snprintf(sender, sizeof(sender), "%u", msg->sender); strip_linefeed(dialog_msg); - serv_got_im(gc, sender, dialog_msg, 0, t, -1); + serv_got_im(ic, sender, dialog_msg, 0, t, -1); g_free(dialog_msg); } break; @@ -1798,13 +1798,13 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { } strip_linefeed(dialog_msg); - serv_got_im(gc, sender, dialog_msg, 0, t, -1); + serv_got_im(ic, sender, dialog_msg, 0, t, -1); g_free(dialog_msg); g_free(m); } break; case 0x0006: { /* Authorization request */ - gaim_icq_authask(gc, msg->sender, msg->msg); + gaim_icq_authask(ic, msg->sender, msg->msg); } break; case 0x0007: { /* Someone has denied you authorization */ @@ -1832,14 +1832,14 @@ static int gaim_offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...) return 1; } -static void oscar_keepalive(struct gaim_connection *gc) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; +static void oscar_keepalive(struct im_connection *ic) { + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; aim_flap_nop(odata->sess, odata->conn); } -static int oscar_send_im(struct gaim_connection *gc, char *name, char *message, int len, int imflags) { - struct oscar_data *odata = (struct oscar_data *)gc->proto_data; - int ret = 0; +static int oscar_send_im(struct im_connection *ic, char *name, char *message, int imflags) { + struct oscar_data *odata = (struct oscar_data *)ic->proto_data; + int ret = 0, len = strlen(message); if (imflags & IM_FLAG_AWAY) { ret = aim_send_im(odata->sess, name, AIM_IMFLAGS_AWAY, message); } else { @@ -1891,7 +1891,7 @@ static int oscar_send_im(struct gaim_connection *gc, char *name, char *message, return ret; } -static void oscar_get_info(struct gaim_connection *g, char *name) { +static void oscar_get_info(struct im_connection *g, char *name) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; if (odata->icq) aim_icq_getallinfo(odata->sess, name); @@ -1901,7 +1901,7 @@ static void oscar_get_info(struct gaim_connection *g, char *name) { } } -static void oscar_get_away(struct gaim_connection *g, char *who) { +static void oscar_get_away(struct im_connection *g, char *who) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; if (odata->icq) { struct buddy *budlight = find_buddy(g, who); @@ -1913,7 +1913,7 @@ static void oscar_get_away(struct gaim_connection *g, char *who) { aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); } -static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *state, const char *message) +static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message) { if (!g_strcasecmp(state, _("Visible"))) { @@ -1925,13 +1925,13 @@ static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od } /* else... */ if (od->rights.maxawaymsglen == 0) - do_error_dialog(gc, "oscar_set_away_aim called before locate rights received", "Protocol Error"); + do_error_dialog(ic, "oscar_set_away_aim called before locate rights received", "Protocol Error"); aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); - if (gc->away) - g_free(gc->away); - gc->away = NULL; + if (ic->away) + g_free(ic->away); + ic->away = NULL; if (!message) { aim_bos_setprofile(od->sess, od->conn, NULL, "", gaim_caps); @@ -1943,26 +1943,26 @@ static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od errstr = g_strdup_printf("Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); - do_error_dialog(gc, errstr, "Away Message Too Long"); + do_error_dialog(ic, errstr, "Away Message Too Long"); g_free(errstr); } - gc->away = g_strndup(message, od->rights.maxawaymsglen); - aim_bos_setprofile(od->sess, od->conn, NULL, gc->away, gaim_caps); + ic->away = g_strndup(message, od->rights.maxawaymsglen); + aim_bos_setprofile(od->sess, od->conn, NULL, ic->away, gaim_caps); return; } -static void oscar_set_away_icq(struct gaim_connection *gc, struct oscar_data *od, const char *state, const char *message) +static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message) { const char *msg = NULL; gboolean no_message = FALSE; /* clean old states */ - if (gc->away) { - g_free(gc->away); - gc->away = NULL; + if (ic->away) { + g_free(ic->away); + ic->away = NULL; } od->sess->aim_icq_state = 0; @@ -1978,33 +1978,33 @@ static void oscar_set_away_icq(struct gaim_connection *gc, struct oscar_data *od aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } else if (!g_strcasecmp(state, "Away")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY; } else if (!g_strcasecmp(state, "Do Not Disturb")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTODND; } else if (!g_strcasecmp(state, "Not Available")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTONA; } else if (!g_strcasecmp(state, "Occupied")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTOBUSY; } else if (!g_strcasecmp(state, "Free For Chat")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTOFFC; } else if (!g_strcasecmp(state, "Invisible")) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); } else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) { if (no_message) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } else { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); - gc->away = g_strdup(msg); + ic->away = g_strdup(msg); od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY; } } @@ -2012,23 +2012,23 @@ static void oscar_set_away_icq(struct gaim_connection *gc, struct oscar_data *od return; } -static void oscar_set_away(struct gaim_connection *gc, char *state, char *message) +static void oscar_set_away(struct im_connection *ic, char *state, char *message) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; + struct oscar_data *od = (struct oscar_data *)ic->proto_data; - oscar_set_away_aim(gc, od, state, message); + oscar_set_away_aim(ic, od, state, message); if (od->icq) - oscar_set_away_icq(gc, od, state, message); + oscar_set_away_icq(ic, od, state, message); return; } -static void oscar_add_buddy(struct gaim_connection *g, char *name) { +static void oscar_add_buddy(struct im_connection *g, char *name, char *group) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; aim_ssi_addbuddies(odata->sess, odata->conn, OSCAR_GROUP, &name, 1, 0); } -static void oscar_remove_buddy(struct gaim_connection *g, char *name, char *group) { +static void oscar_remove_buddy(struct im_connection *g, char *name, char *group) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; struct aim_ssi_item *ssigroup; while ((ssigroup = aim_ssi_itemlist_findparent(odata->sess->ssi.items, name)) && !aim_ssi_delbuddies(odata->sess, odata->conn, ssigroup->name, &name, 1)); @@ -2039,7 +2039,7 @@ static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) { } static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; struct aim_ssi_item *curitem; int tmp; @@ -2048,13 +2048,13 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { for (curitem=sess->ssi.items; curitem; curitem=curitem->next) { switch (curitem->type) { case 0x0000: /* Buddy */ - if ((curitem->name) && (!find_buddy(gc, curitem->name))) { + if ((curitem->name) && (!find_buddy(ic, curitem->name))) { char *realname = NULL; if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) realname = aim_gettlv_str(curitem->data, 0x0131, 1); - add_buddy(gc, NULL, curitem->name, realname); + add_buddy(ic, NULL, curitem->name, realname); if (realname) g_free(realname); @@ -2064,11 +2064,11 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { case 0x0002: /* Permit buddy */ if (curitem->name) { GSList *list; - for (list=gc->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next); + for (list=ic->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next); if (!list) { char *name; name = g_strdup(normalize(curitem->name)); - gc->permit = g_slist_append(gc->permit, name); + ic->permit = g_slist_append(ic->permit, name); tmp++; } } @@ -2077,11 +2077,11 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { case 0x0003: /* Deny buddy */ if (curitem->name) { GSList *list; - for (list=gc->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next); + for (list=ic->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next); if (!list) { char *name; name = g_strdup(normalize(curitem->name)); - gc->deny = g_slist_append(gc->deny, name); + ic->deny = g_slist_append(ic->deny, name); tmp++; } } @@ -2090,8 +2090,8 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { case 0x0004: /* Permit/deny setting */ if (curitem->data) { guint8 permdeny; - if ((permdeny = aim_ssi_getpermdeny(sess->ssi.items)) && (permdeny != gc->permdeny)) { - gc->permdeny = permdeny; + if ((permdeny = aim_ssi_getpermdeny(sess->ssi.items)) && (permdeny != ic->permdeny)) { + ic->permdeny = permdeny; tmp++; } } @@ -2109,7 +2109,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { aim_icq_reqofflinemsgs(sess); /* Now that we have a buddy list, we can tell BitlBee that we're online. */ - account_online(gc); + account_online(ic); return 1; } @@ -2154,22 +2154,22 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) return( 1 ); } -static void oscar_set_permit_deny(struct gaim_connection *gc) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; +static void oscar_set_permit_deny(struct im_connection *ic) { + struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (od->icq) { GSList *list; char buf[MAXMSGLEN]; int at; - switch(gc->permdeny) { + switch(ic->permdeny) { case 1: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, gc->username); + aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, ic->username); break; case 2: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, gc->username); + aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, ic->username); break; case 3: - list = gc->permit; + list = ic->permit; at = 0; while (list) { at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); @@ -2178,7 +2178,7 @@ static void oscar_set_permit_deny(struct gaim_connection *gc) { aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf); break; case 4: - list = gc->deny; + list = ic->deny; at = 0; while (list) { at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data); @@ -2189,15 +2189,15 @@ static void oscar_set_permit_deny(struct gaim_connection *gc) { default: break; } - signoff_blocked(gc); + signoff_blocked(ic); } else { if (od->sess->ssi.received_data) - aim_ssi_setpermdeny(od->sess, od->conn, gc->permdeny, 0xffffffff); + aim_ssi_setpermdeny(od->sess, od->conn, ic->permdeny, 0xffffffff); } } -static void oscar_add_permit(struct gaim_connection *gc, char *who) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; +static void oscar_add_permit(struct im_connection *ic, char *who) { + struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (od->icq) { aim_ssi_auth_reply(od->sess, od->conn, who, 1, ""); } else { @@ -2206,8 +2206,8 @@ static void oscar_add_permit(struct gaim_connection *gc, char *who) { } } -static void oscar_add_deny(struct gaim_connection *gc, char *who) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; +static void oscar_add_deny(struct im_connection *ic, char *who) { + struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (od->icq) { aim_ssi_auth_reply(od->sess, od->conn, who, 0, ""); } else { @@ -2216,25 +2216,25 @@ static void oscar_add_deny(struct gaim_connection *gc, char *who) { } } -static void oscar_rem_permit(struct gaim_connection *gc, char *who) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; +static void oscar_rem_permit(struct im_connection *ic, char *who) { + struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (!od->icq) { if (od->sess->ssi.received_data) aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_PERMIT); } } -static void oscar_rem_deny(struct gaim_connection *gc, char *who) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; +static void oscar_rem_deny(struct im_connection *ic, char *who) { + struct oscar_data *od = (struct oscar_data *)ic->proto_data; if (!od->icq) { if (od->sess->ssi.received_data) aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_DENY); } } -static GList *oscar_away_states(struct gaim_connection *gc) +static GList *oscar_away_states(struct im_connection *ic) { - struct oscar_data *od = gc->proto_data; + struct oscar_data *od = ic->proto_data; GList *m = NULL; if (!od->icq) @@ -2253,7 +2253,7 @@ static GList *oscar_away_states(struct gaim_connection *gc) static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; gchar who[16]; GString *str; va_list ap; @@ -2329,7 +2329,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) g_string_sprintfa(str, "\n"); } - serv_got_crap(gc, "%s\n%s", _("User Info"), str->str); + serv_got_crap(ic, "%s\n%s", _("User Info"), str->str); g_string_free(str, TRUE); return 1; @@ -2394,7 +2394,7 @@ static char *oscar_encoding_to_utf8(char *encoding, char *text, int textlen) static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; + struct im_connection *ic = sess->aux_data; va_list ap; aim_userinfo_t *userinfo; guint16 infotype; @@ -2423,18 +2423,18 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) idletime.tm_min = userinfo->idletime % 60; idletime.tm_sec = 0; strftime(buff, 256, _("%d days %H hours %M minutes"), &idletime); - serv_got_crap(gc, "%s: %s", _("Idle Time"), buff); + serv_got_crap(ic, "%s: %s", _("Idle Time"), buff); } if(text) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - serv_got_crap(gc, "%s\n%s", _("User Info"), utf8); + serv_got_crap(ic, "%s\n%s", _("User Info"), utf8); } else { - serv_got_crap(gc, _("No user info available.")); + serv_got_crap(ic, _("No user info available.")); } } else if(infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - serv_got_crap(gc, "%s\n%s", _("Away Message"), utf8); + serv_got_crap(ic, "%s\n%s", _("Away Message"), utf8); } g_free(utf8); @@ -2444,7 +2444,7 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection * gc = sess->aux_data; + struct im_connection * ic = sess->aux_data; va_list ap; guint16 type1, type2; char * sn; @@ -2457,23 +2457,23 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) if(type2 == 0x0002) { /* User is typing */ - serv_got_typing(gc, sn, 0, 1); + serv_got_typing(ic, sn, 0, 1); } else if (type2 == 0x0001) { /* User has typed something, but is not actively typing (stale) */ - serv_got_typing(gc, sn, 0, 2); + serv_got_typing(ic, sn, 0, 2); } else { /* User has stopped typing */ - serv_got_typing(gc, sn, 0, 0); + serv_got_typing(ic, sn, 0, 0); } return 1; } -static char *oscar_get_status_string( struct gaim_connection *gc, int number ) +static char *oscar_get_status_string( struct im_connection *ic, int number ) { - struct oscar_data *od = gc->proto_data; + struct oscar_data *od = ic->proto_data; if( ! number & UC_UNAVAILABLE ) { @@ -2499,16 +2499,16 @@ static char *oscar_get_status_string( struct gaim_connection *gc, int number ) } } -int oscar_send_typing(struct gaim_connection *gc, char * who, int typing) +int oscar_send_typing(struct im_connection *ic, char * who, int typing) { - struct oscar_data *od = gc->proto_data; + struct oscar_data *od = ic->proto_data; return( aim_im_sendmtn(od->sess, 1, who, typing ? 0x0002 : 0x0000) ); } -int oscar_chat_send(struct conversation *c, char *message) +void oscar_chat_send(struct groupchat *c, char *message, int msgflags) { - struct gaim_connection *gc = c->gc; - struct oscar_data * od = (struct oscar_data*)gc->proto_data; + struct im_connection *ic = c->ic; + struct oscar_data * od = (struct oscar_data*)ic->proto_data; struct chat_connection * ccon; int ret; guint8 len = strlen(message); @@ -2549,22 +2549,22 @@ int oscar_chat_send(struct conversation *c, char *message) g_free(s); } - return (ret >= 0); +/* return (ret >= 0); */ } -void oscar_chat_invite(struct conversation *c, char *message, char *who) +void oscar_chat_invite(struct groupchat *c, char *message, char *who) { - struct gaim_connection *gc = c->gc; - struct oscar_data * od = (struct oscar_data *)gc->proto_data; + struct im_connection *ic = c->ic; + struct oscar_data * od = (struct oscar_data *)ic->proto_data; struct chat_connection *ccon = c->data; aim_chat_invite(od->sess, od->conn, who, message ? message : "", ccon->exchange, ccon->name, 0x0); } -void oscar_chat_kill(struct gaim_connection *gc, struct chat_connection *cc) +void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; + struct oscar_data *od = (struct oscar_data *)ic->proto_data; /* Notify the conversation window that we've left the chat */ serv_got_chat_left(cc->cnv); @@ -2579,14 +2579,14 @@ void oscar_chat_kill(struct gaim_connection *gc, struct chat_connection *cc) g_free(cc); } -void oscar_chat_leave(struct conversation *c) +void oscar_chat_leave(struct groupchat *c) { - oscar_chat_kill(c->gc, c->data); + oscar_chat_kill(c->ic, c->data); } -int oscar_chat_join(struct gaim_connection * gc, char * name) +int oscar_chat_join(struct im_connection * ic, char * name) { - struct oscar_data * od = (struct oscar_data *)gc->proto_data; + struct oscar_data * od = (struct oscar_data *)ic->proto_data; aim_conn_t * cur; @@ -2604,16 +2604,16 @@ int oscar_chat_join(struct gaim_connection * gc, char * name) } } -struct conversation *oscar_chat_open(struct gaim_connection * gc, char *who) +struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) { - struct oscar_data * od = (struct oscar_data *)gc->proto_data; + struct oscar_data * od = (struct oscar_data *)ic->proto_data; int ret; static int chat_id = 0; char * chatname; - chatname = g_strdup_printf("%s%d", gc->username, chat_id++); + chatname = g_strdup_printf("%s%d", ic->username, chat_id++); - ret = oscar_chat_join(gc, chatname); + ret = oscar_chat_join(ic, chatname); aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0); @@ -2624,7 +2624,7 @@ struct conversation *oscar_chat_open(struct gaim_connection * gc, char *who) void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv) { - oscar_chat_join(inv->gc, inv->name); + oscar_chat_join(inv->ic, inv->name); g_free(inv->name); g_free(inv); } @@ -2635,14 +2635,15 @@ void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv) g_free(inv); } -void oscar_init() +void oscar_initmodule() { struct prpl *ret = g_new0(struct prpl, 1); ret->name = "oscar"; ret->away_states = oscar_away_states; + ret->init = oscar_init; ret->login = oscar_login; - ret->acc_init = oscar_acc_init; - ret->close = oscar_close; + ret->keepalive = oscar_keepalive; + ret->logout = oscar_logout; ret->send_im = oscar_send_im; ret->get_info = oscar_get_info; ret->set_away = oscar_set_away; @@ -2652,13 +2653,12 @@ void oscar_init() ret->chat_send = oscar_chat_send; ret->chat_invite = oscar_chat_invite; ret->chat_leave = oscar_chat_leave; - ret->chat_open = oscar_chat_open; + ret->chat_with = oscar_chat_with; ret->add_permit = oscar_add_permit; ret->add_deny = oscar_add_deny; ret->rem_permit = oscar_rem_permit; ret->rem_deny = oscar_rem_deny; ret->set_permit_deny = oscar_set_permit_deny; - ret->keepalive = oscar_keepalive; ret->get_status_string = oscar_get_status_string; ret->send_typing = oscar_send_typing; diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index d55e0987..2a3dd1fb 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -731,11 +731,11 @@ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status) aim_tlvlist_t *tl = NULL; guint32 data; int tlvlen; - struct gaim_connection *gc = sess ? sess->aux_data : NULL; + struct im_connection *ic = sess ? sess->aux_data : NULL; data = AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */ - if (gc && set_getbool(&gc->acc->set, "web_aware")) + if (ic && set_getbool(&ic->acc->set, "web_aware")) data |= AIM_ICQ_STATE_WEBAWARE; tlvlen = aim_addtlvtochain32(&tl, 0x0006, data); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index e0dcabff..52db9007 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -57,10 +57,10 @@ struct byahoo_input_data struct byahoo_conf_invitation { char *name; - struct conversation *c; + struct groupchat *c; int yid; YList *members; - struct gaim_connection *gc; + struct im_connection *ic; }; static GSList *byahoo_inputs = NULL; @@ -122,24 +122,24 @@ static char *byahoo_strip( char *in ) static void byahoo_login( account_t *acc ) { - struct gaim_connection *gc = new_gaim_conn( acc ); - struct byahoo_data *yd = gc->proto_data = g_new0( struct byahoo_data, 1 ); + struct im_connection *ic = new_gaim_conn( acc ); + struct byahoo_data *yd = ic->proto_data = g_new0( struct byahoo_data, 1 ); yd->logged_in = FALSE; yd->current_status = YAHOO_STATUS_AVAILABLE; - set_login_progress( gc, 1, "Connecting" ); + set_login_progress( ic, 1, "Connecting" ); yd->y2_id = yahoo_init( acc->user, acc->pass ); yahoo_login( yd->y2_id, yd->current_status ); } -static void byahoo_close( struct gaim_connection *gc ) +static void byahoo_logout( struct im_connection *ic ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; GSList *l; - while( gc->conversations ) - serv_got_chat_left( gc->conversations ); + while( ic->conversations ) + serv_got_chat_left( ic->conversations ); for( l = yd->buddygroups; l; l = l->next ) { @@ -159,42 +159,42 @@ static void byahoo_close( struct gaim_connection *gc ) g_free( yd ); } -static void byahoo_get_info(struct gaim_connection *gc, char *who) +static void byahoo_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - serv_got_crap(gc, "%s\n%s: %s%s", _("User Info"), + serv_got_crap(ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), yahoo_get_profile_url(), who); } -static int byahoo_send_im( struct gaim_connection *gc, char *who, char *what, int len, int flags ) +static int byahoo_send_im( struct im_connection *ic, char *who, char *what, int flags ) { - struct byahoo_data *yd = gc->proto_data; + struct byahoo_data *yd = ic->proto_data; yahoo_send_im( yd->y2_id, NULL, who, what, 1 ); return 1; } -static int byahoo_send_typing( struct gaim_connection *gc, char *who, int typing ) +static int byahoo_send_typing( struct im_connection *ic, char *who, int typing ) { - struct byahoo_data *yd = gc->proto_data; + struct byahoo_data *yd = ic->proto_data; yahoo_send_typing( yd->y2_id, NULL, who, typing ); return 1; } -static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg ) +static void byahoo_set_away( struct im_connection *ic, char *state, char *msg ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - gc->away = NULL; + ic->away = NULL; if( state && msg && g_strcasecmp( state, msg ) != 0 ) { yd->current_status = YAHOO_STATUS_CUSTOM; - gc->away = ""; + ic->away = ""; } else if( state ) { @@ -203,11 +203,11 @@ static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg away state. */ msg = NULL; - gc->away = ""; + ic->away = ""; if( g_strcasecmp( state, "Available" ) == 0 ) { yd->current_status = YAHOO_STATUS_AVAILABLE; - gc->away = NULL; + ic->away = NULL; } else if( g_strcasecmp( state, "Be Right Back" ) == 0 ) yd->current_status = YAHOO_STATUS_BRB; @@ -233,16 +233,16 @@ static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg { yd->current_status = YAHOO_STATUS_AVAILABLE; - gc->away = NULL; + ic->away = NULL; } } else yd->current_status = YAHOO_STATUS_AVAILABLE; - yahoo_set_away( yd->y2_id, yd->current_status, msg, gc->away != NULL ); + yahoo_set_away( yd->y2_id, yd->current_status, msg, ic->away != NULL ); } -static GList *byahoo_away_states( struct gaim_connection *gc ) +static GList *byahoo_away_states( struct im_connection *ic ) { GList *m = NULL; @@ -262,23 +262,23 @@ static GList *byahoo_away_states( struct gaim_connection *gc ) return m; } -static void byahoo_keepalive( struct gaim_connection *gc ) +static void byahoo_keepalive( struct im_connection *ic ) { - struct byahoo_data *yd = gc->proto_data; + struct byahoo_data *yd = ic->proto_data; yahoo_keepalive( yd->y2_id ); } -static void byahoo_add_buddy( struct gaim_connection *gc, char *who ) +static void byahoo_add_buddy( struct im_connection *ic, char *who, char *group ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - yahoo_add_buddy( yd->y2_id, who, BYAHOO_DEFAULT_GROUP ); + yahoo_add_buddy( yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP ); } -static void byahoo_remove_buddy( struct gaim_connection *gc, char *who, char *group ) +static void byahoo_remove_buddy( struct im_connection *ic, char *who, char *group ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; GSList *bgl; yahoo_remove_buddy( yd->y2_id, who, BYAHOO_DEFAULT_GROUP ); @@ -292,7 +292,7 @@ static void byahoo_remove_buddy( struct gaim_connection *gc, char *who, char *gr } } -static char *byahoo_get_status_string( struct gaim_connection *gc, int stat ) +static char *byahoo_get_status_string( struct im_connection *ic, int stat ) { enum yahoo_status a = stat >> 1; @@ -331,42 +331,40 @@ static char *byahoo_get_status_string( struct gaim_connection *gc, int stat ) } } -static int byahoo_chat_send( struct conversation *c, char *message ) +static void byahoo_chat_send( struct groupchat *c, char *message, int flags ) { - struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; yahoo_conference_message( yd->y2_id, NULL, c->data, c->title, message, 1 ); - - return( 0 ); } -static void byahoo_chat_invite( struct conversation *c, char *msg, char *who ) +static void byahoo_chat_invite( struct groupchat *c, char *msg, char *who ) { - struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ); } -static void byahoo_chat_leave( struct conversation *c ) +static void byahoo_chat_leave( struct groupchat *c ) { - struct byahoo_data *yd = (struct byahoo_data *) c->gc->proto_data; + struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); serv_got_chat_left( c ); } -static struct conversation *byahoo_chat_open( struct gaim_connection *gc, char *who ) +static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) { - struct byahoo_data *yd = (struct byahoo_data *) gc->proto_data; - struct conversation *c; + struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; + struct groupchat *c; char *roomname; YList *members; - roomname = g_new0( char, strlen( gc->username ) + 16 ); - g_snprintf( roomname, strlen( gc->username ) + 16, "%s-Bee-%d", gc->username, byahoo_chat_id ); + roomname = g_new0( char, strlen( ic->username ) + 16 ); + g_snprintf( roomname, strlen( ic->username ) + 16, "%s-Bee-%d", ic->username, byahoo_chat_id ); - c = serv_got_joined_chat( gc, roomname ); - add_chat_buddy( c, gc->username ); + c = serv_got_joined_chat( ic, roomname ); + add_chat_buddy( c, ic->username ); /* FIXME: Free this thing when the chat's destroyed. We can't *always* do this because it's not always created here. */ @@ -380,18 +378,19 @@ static struct conversation *byahoo_chat_open( struct gaim_connection *gc, char * return c; } -void byahoo_init( ) +void byahoo_initmodule( ) { struct prpl *ret = g_new0(struct prpl, 1); ret->name = "yahoo"; ret->login = byahoo_login; - ret->close = byahoo_close; + ret->keepalive = byahoo_keepalive; + ret->logout = byahoo_logout; + ret->send_im = byahoo_send_im; ret->get_info = byahoo_get_info; ret->away_states = byahoo_away_states; ret->set_away = byahoo_set_away; - ret->keepalive = byahoo_keepalive; ret->add_buddy = byahoo_add_buddy; ret->remove_buddy = byahoo_remove_buddy; ret->get_status_string = byahoo_get_status_string; @@ -400,26 +399,26 @@ void byahoo_init( ) ret->chat_send = byahoo_chat_send; ret->chat_invite = byahoo_chat_invite; ret->chat_leave = byahoo_chat_leave; - ret->chat_open = byahoo_chat_open; + ret->chat_with = byahoo_chat_with; ret->handle_cmp = g_strcasecmp; register_protocol(ret); } -static struct gaim_connection *byahoo_get_gc_by_id( int id ) +static struct im_connection *byahoo_get_ic_by_id( int id ) { GSList *l; - struct gaim_connection *gc; + struct im_connection *ic; struct byahoo_data *yd; for( l = get_connections(); l; l = l->next ) { - gc = l->data; - yd = gc->proto_data; + ic = l->data; + yd = ic->proto_data; - if( strcmp( gc->acc->prpl->name, "yahoo" ) == 0 && yd->y2_id == id ) - return( gc ); + if( strcmp( ic->acc->prpl->name, "yahoo" ) == 0 && yd->y2_id == id ) + return( ic ); } return( NULL ); @@ -440,7 +439,7 @@ void byahoo_connect_callback( gpointer data, gint source, b_input_condition cond { struct byahoo_connect_callback_data *d = data; - if( !byahoo_get_gc_by_id( d->id ) ) + if( !byahoo_get_ic_by_id( d->id ) ) { g_free( d ); return; @@ -462,7 +461,7 @@ gboolean byahoo_read_ready_callback( gpointer data, gint source, b_input_conditi { struct byahoo_read_ready_data *d = data; - if( !byahoo_get_gc_by_id( d->id ) ) + if( !byahoo_get_ic_by_id( d->id ) ) /* WTF doesn't libyahoo clean this up? */ return FALSE; @@ -483,7 +482,7 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit { struct byahoo_write_ready_data *d = data; - if( !byahoo_get_gc_by_id( d->id ) ) + if( !byahoo_get_ic_by_id( d->id ) ) /* WTF doesn't libyahoo clean this up? */ return FALSE; @@ -494,10 +493,10 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit void ext_yahoo_login_response( int id, int succ, char *url ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); struct byahoo_data *yd = NULL; - if( gc == NULL ) + if( ic == NULL ) { /* libyahoo2 seems to call this one twice when something went wrong sometimes. Don't know why. Because we clean @@ -507,11 +506,11 @@ void ext_yahoo_login_response( int id, int succ, char *url ) return; } - yd = (struct byahoo_data *) gc->proto_data; + yd = (struct byahoo_data *) ic->proto_data; if( succ == YAHOO_LOGIN_OK ) { - account_online( gc ); + account_online( ic ); yd->logged_in = TRUE; } @@ -531,7 +530,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) else if( succ == YAHOO_LOGIN_DUPL ) { errstr = "Logged in on a different machine or device"; - gc->wants_to_die = TRUE; + ic->wants_to_die = TRUE; } else if( succ == YAHOO_LOGIN_SOCK ) errstr = "Socket problem"; @@ -550,20 +549,20 @@ void ext_yahoo_login_response( int id, int succ, char *url ) } if( yd->logged_in ) - hide_login_progress_error( gc, s ); + hide_login_progress_error( ic, s ); else - hide_login_progress( gc, s ); + hide_login_progress( ic, s ); g_free( s ); - signoff( gc ); + signoff( ic ); } } void ext_yahoo_got_buddies( int id, YList *buds ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); - struct byahoo_data *yd = gc->proto_data; + struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct byahoo_data *yd = ic->proto_data; YList *bl = buds; while( bl ) @@ -580,7 +579,7 @@ void ext_yahoo_got_buddies( int id, YList *buds ) yd->buddygroups = g_slist_append( yd->buddygroups, bg ); } - add_buddy( gc, b->group, b->id, b->real_name ); + add_buddy( ic, b->group, b->id, b->real_name ); bl = bl->next; } } @@ -599,68 +598,68 @@ void ext_yahoo_got_cookies( int id ) void ext_yahoo_status_changed( int id, char *who, int stat, char *msg, int away ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_update( gc, who, stat != YAHOO_STATUS_OFFLINE, 0, 0, + serv_got_update( ic, who, stat != YAHOO_STATUS_OFFLINE, 0, 0, ( stat == YAHOO_STATUS_IDLE ) ? away : 0, ( stat != YAHOO_STATUS_AVAILABLE ) | ( stat << 1 ), 0 ); } void ext_yahoo_got_im( int id, char *who, char *msg, long tm, int stat, int utf8 ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); char *m = byahoo_strip( msg ); - serv_got_im( gc, who, m, 0, 0, strlen( m ) ); + serv_got_im( ic, who, m, 0, 0, strlen( m ) ); g_free( m ); } void ext_yahoo_got_file( int id, char *who, char *url, long expires, char *msg, char *fname, unsigned long fesize ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( gc, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); + serv_got_crap( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); } void ext_yahoo_typing_notify( int id, char *who, int stat ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); if (stat == 1) { /* User is typing */ - serv_got_typing( gc, who, 1, 1 ); + serv_got_typing( ic, who, 1, 1 ); } else { /* User stopped typing */ - serv_got_typing( gc, who, 1, 0 ); + serv_got_typing( ic, who, 1, 0 ); } } void ext_yahoo_system_message( int id, char *msg ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( gc, "Yahoo! system message: %s", msg ); + serv_got_crap( ic, "Yahoo! system message: %s", msg ); } void ext_yahoo_webcam_invite( int id, char *from ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( gc, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); + serv_got_crap( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); } void ext_yahoo_error( int id, char *err, int fatal ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); if( fatal ) { - hide_login_progress_error( gc, err ); - signoff( gc ); + hide_login_progress_error( ic, err ); + signoff( ic ); } else { - do_error_dialog( gc, err, "Yahoo! error" ); + do_error_dialog( ic, err, "Yahoo! error" ); } } @@ -787,7 +786,7 @@ int ext_yahoo_connect(char *host, int port) static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); - add_chat_buddy( inv->c, inv->gc->username ); + add_chat_buddy( inv->c, inv->ic->username ); g_free( inv->name ); g_free( inv ); } @@ -802,7 +801,7 @@ static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList *members ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); struct byahoo_conf_invitation *inv; char txt[1024]; YList *m; @@ -810,34 +809,34 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList inv = g_malloc( sizeof( struct byahoo_conf_invitation ) ); memset( inv, 0, sizeof( struct byahoo_conf_invitation ) ); inv->name = g_strdup( room ); - inv->c = serv_got_joined_chat( gc, room ); + inv->c = serv_got_joined_chat( ic, room ); inv->c->data = members; inv->yid = id; inv->members = members; - inv->gc = gc; + inv->ic = ic; for( m = members; m; m = m->next ) - if( g_strcasecmp( m->data, gc->username ) != 0 ) + if( g_strcasecmp( m->data, ic->username ) != 0 ) add_chat_buddy( inv->c, m->data ); g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg ); - do_ask_dialog( gc, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); + do_ask_dialog( ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); } void ext_yahoo_conf_userdecline( int id, char *who, char *room, char *msg ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( gc, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); + serv_got_crap( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); } void ext_yahoo_conf_userjoin( int id, char *who, char *room ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); - struct conversation *c; + struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct groupchat *c; - for( c = gc->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) add_chat_buddy( c, who ); @@ -845,10 +844,10 @@ void ext_yahoo_conf_userjoin( int id, char *who, char *room ) void ext_yahoo_conf_userleave( int id, char *who, char *room ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); - struct conversation *c; + struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct groupchat *c; - for( c = gc->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) remove_chat_buddy( c, who, "" ); @@ -856,11 +855,11 @@ void ext_yahoo_conf_userleave( int id, char *who, char *room ) void ext_yahoo_conf_message( int id, char *who, char *room, char *msg, int utf8 ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); char *m = byahoo_strip( msg ); - struct conversation *c; + struct groupchat *c; - for( c = gc->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) serv_got_chat_in( c, who, 0, m, 0 ); @@ -909,12 +908,12 @@ void ext_yahoo_game_notify( int id, char *who, int stat ) void ext_yahoo_mail_notify( int id, char *from, char *subj, int cnt ) { - struct gaim_connection *gc = byahoo_get_gc_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id( id ); if( from && subj ) - serv_got_crap( gc, "Received e-mail message from %s with subject `%s'", from, subj ); + serv_got_crap( ic, "Received e-mail message from %s with subject `%s'", from, subj ); else if( cnt > 0 ) - serv_got_crap( gc, "Received %d new e-mails", cnt ); + serv_got_crap( ic, "Received %d new e-mails", cnt ); } void ext_yahoo_webcam_invite_reply( int id, char *from, int accept ) diff --git a/query.c b/query.c index 40dbb439..c95ff4e1 100644 --- a/query.c +++ b/query.c @@ -29,11 +29,11 @@ static void query_display( irc_t *irc, query_t *q ); static query_t *query_default( irc_t *irc ); -query_t *query_add( irc_t *irc, struct gaim_connection *gc, char *question, void *yes, void *no, void *data ) +query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, void *yes, void *no, void *data ) { query_t *q = g_new0( query_t, 1 ); - q->gc = gc; + q->ic = ic; q->question = g_strdup( question ); q->yes = yes; q->no = no; @@ -96,7 +96,7 @@ void query_del( irc_t *irc, query_t *q ) g_free( q ); } -void query_del_by_gc( irc_t *irc, struct gaim_connection *gc ) +void query_del_by_conn( irc_t *irc, struct im_connection *ic ) { query_t *q, *n, *def; int count = 0; @@ -106,7 +106,7 @@ void query_del_by_gc( irc_t *irc, struct gaim_connection *gc ) while( q ) { - if( q->gc == gc ) + if( q->ic == ic ) { n = q->next; query_del( irc, q ); @@ -121,7 +121,7 @@ void query_del_by_gc( irc_t *irc, struct gaim_connection *gc ) } if( count > 0 ) - serv_got_crap( gc, "Flushed %d unanswered question(s) for this connection.", count ); + serv_got_crap( ic, "Flushed %d unanswered question(s) for this connection.", count ); q = query_default( irc ); if( q && q != def ) @@ -139,12 +139,12 @@ void query_answer( irc_t *irc, query_t *q, int ans ) } if( ans ) { - serv_got_crap( q->gc, "Accepted: %s", q->question ); + serv_got_crap( q->ic, "Accepted: %s", q->question ); q->yes( NULL, q->data ); } else { - serv_got_crap( q->gc, "Rejected: %s", q->question ); + serv_got_crap( q->ic, "Rejected: %s", q->question ); q->no( NULL, q->data ); } q->data = NULL; @@ -157,9 +157,9 @@ void query_answer( irc_t *irc, query_t *q, int ans ) static void query_display( irc_t *irc, query_t *q ) { - if( q->gc ) + if( q->ic ) { - serv_got_crap( q->gc, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); + serv_got_crap( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); } else { diff --git a/query.h b/query.h index 2f29a739..b64642c2 100644 --- a/query.h +++ b/query.h @@ -28,7 +28,7 @@ typedef struct query { - struct gaim_connection *gc; + struct im_connection *ic; char *question; void (* yes) ( gpointer w, void *data ); void (* no) ( gpointer w, void *data ); @@ -36,9 +36,9 @@ typedef struct query struct query *next; } query_t; -query_t *query_add( irc_t *irc, struct gaim_connection *gc, char *question, void *yes, void *no, void *data ); +query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, void *yes, void *no, void *data ); void query_del( irc_t *irc, query_t *q ); -void query_del_by_gc( irc_t *irc, struct gaim_connection *gc ); +void query_del_by_conn( irc_t *irc, struct im_connection *ic ); void query_answer( irc_t *irc, query_t *q, int ans ); #endif diff --git a/root_commands.c b/root_commands.c index ff2d8b37..ee6df91d 100644 --- a/root_commands.c +++ b/root_commands.c @@ -247,7 +247,7 @@ static void cmd_account( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Invalid account" ); } - else if( a->gc ) + else if( a->ic ) { irc_usermsg( irc, "Account is still logged in, can't delete" ); } @@ -268,9 +268,9 @@ static void cmd_account( irc_t *irc, char **cmd ) { char *con; - if( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) + if( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) con = " (connected)"; - else if( a->gc ) + else if( a->ic ) con = " (connecting)"; else if( a->reconnect ) con = " (awaiting reconnect)"; @@ -289,7 +289,7 @@ static void cmd_account( irc_t *irc, char **cmd ) { if( ( a = account_get( irc, cmd[2] ) ) ) { - if( a->gc ) + if( a->ic ) { irc_usermsg( irc, "Account already online" ); return; @@ -311,7 +311,7 @@ static void cmd_account( irc_t *irc, char **cmd ) irc_usermsg( irc, "Trying to get all accounts connected..." ); for( a = irc->accounts; a; a = a->next ) - if( !a->gc && a->auto_connect ) + if( !a->ic && a->auto_connect ) account_on( irc, a ); } else @@ -328,7 +328,7 @@ static void cmd_account( irc_t *irc, char **cmd ) for( a = irc->accounts; a; a = a->next ) { - if( a->gc ) + if( a->ic ) account_off( irc, a ); else if( a->reconnect ) cancel_auto_reconnect( a ); @@ -336,7 +336,7 @@ static void cmd_account( irc_t *irc, char **cmd ) } else if( ( a = account_get( irc, cmd[2] ) ) ) { - if( a->gc ) + if( a->ic ) { account_off( irc, a ); } @@ -386,13 +386,13 @@ static void cmd_account( irc_t *irc, char **cmd ) { set_t *s = set_find( &a->set, set_name ); - if( a->gc && s && s->flags & ACC_SET_OFFLINE_ONLY ) + if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY ) { g_free( acc_handle ); irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "off" ); return; } - else if( !a->gc && s && s->flags & ACC_SET_ONLINE_ONLY ) + else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY ) { g_free( acc_handle ); irc_usermsg( irc, "This setting can only be changed when the account is %s-line", "on" ); @@ -449,7 +449,7 @@ static void cmd_add( irc_t *irc, char **cmd ) irc_usermsg( irc, "Invalid account" ); return; } - else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); return; @@ -476,27 +476,27 @@ static void cmd_add( irc_t *irc, char **cmd ) /* By making this optional, you can talk to people without having to add them to your *real* (server-side) contact list. */ if( add_for_real ) - a->gc->acc->prpl->add_buddy( a->gc, cmd[2] ); + a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); - add_buddy( a->gc, NULL, cmd[2], cmd[2] ); + add_buddy( a->ic, NULL, cmd[2], cmd[2] ); - irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->gc, cmd[2] )->nick ); + irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->ic, cmd[2] )->nick ); } static void cmd_info( irc_t *irc, char **cmd ) { - struct gaim_connection *gc; + struct im_connection *ic; account_t *a; if( !cmd[2] ) { user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) + if( !u || !u->ic ) { irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); return; } - gc = u->gc; + ic = u->ic; cmd[2] = u->handle; } else if( !( a = account_get( irc, cmd[1] ) ) ) @@ -504,19 +504,19 @@ static void cmd_info( irc_t *irc, char **cmd ) irc_usermsg( irc, "Invalid account" ); return; } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); return; } - if( !gc->acc->prpl->get_info ) + if( !ic->acc->prpl->get_info ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } else { - gc->acc->prpl->get_info( gc, cmd[2] ); + ic->acc->prpl->get_info( ic, cmd[2] ); } } @@ -551,7 +551,7 @@ static void cmd_rename( irc_t *irc, char **cmd ) } else if( u->send_handler == buddy_send_handler ) { - nick_set( u->gc->acc, u->handle, cmd[2] ); + nick_set( u->ic->acc, u->handle, cmd[2] ); } irc_usermsg( irc, "Nick successfully changed" ); @@ -563,15 +563,15 @@ static void cmd_remove( irc_t *irc, char **cmd ) user_t *u; char *s; - if( !( u = user_find( irc, cmd[1] ) ) || !u->gc ) + if( !( u = user_find( irc, cmd[1] ) ) || !u->ic ) { irc_usermsg( irc, "Buddy `%s' not found", cmd[1] ); return; } s = g_strdup( u->handle ); - u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); - nick_del( u->gc->acc, u->handle ); + u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL ); + nick_del( u->ic->acc, u->handle ); user_del( irc, cmd[1] ); irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); @@ -582,10 +582,10 @@ static void cmd_remove( irc_t *irc, char **cmd ) static void cmd_block( irc_t *irc, char **cmd ) { - struct gaim_connection *gc; + struct im_connection *ic; account_t *a; - if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->gc ) + if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic ) { char *format; GSList *l; @@ -596,9 +596,9 @@ static void cmd_block( irc_t *irc, char **cmd ) format = "%-32.32s %-16.16s"; irc_usermsg( irc, format, "Handle", "Nickname" ); - for( l = a->gc->deny; l; l = l->next ) + for( l = a->ic->deny; l; l = l->next ) { - user_t *u = user_findhandle( a->gc, l->data ); + user_t *u = user_findhandle( a->ic, l->data ); irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); } irc_usermsg( irc, "End of list." ); @@ -608,12 +608,12 @@ static void cmd_block( irc_t *irc, char **cmd ) else if( !cmd[2] ) { user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) + if( !u || !u->ic ) { irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); return; } - gc = u->gc; + ic = u->ic; cmd[2] = u->handle; } else if( !( a = account_get( irc, cmd[1] ) ) ) @@ -621,30 +621,30 @@ static void cmd_block( irc_t *irc, char **cmd ) irc_usermsg( irc, "Invalid account" ); return; } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); return; } - if( !gc->acc->prpl->add_deny || !gc->acc->prpl->rem_permit ) + if( !ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } else { - bim_rem_allow( gc, cmd[2] ); - bim_add_block( gc, cmd[2] ); + bim_rem_allow( ic, cmd[2] ); + bim_add_block( ic, cmd[2] ); irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] ); } } static void cmd_allow( irc_t *irc, char **cmd ) { - struct gaim_connection *gc; + struct im_connection *ic; account_t *a; - if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->gc ) + if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic ) { char *format; GSList *l; @@ -655,9 +655,9 @@ static void cmd_allow( irc_t *irc, char **cmd ) format = "%-32.32s %-16.16s"; irc_usermsg( irc, format, "Handle", "Nickname" ); - for( l = a->gc->permit; l; l = l->next ) + for( l = a->ic->permit; l; l = l->next ) { - user_t *u = user_findhandle( a->gc, l->data ); + user_t *u = user_findhandle( a->ic, l->data ); irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" ); } irc_usermsg( irc, "End of list." ); @@ -667,12 +667,12 @@ static void cmd_allow( irc_t *irc, char **cmd ) else if( !cmd[2] ) { user_t *u = user_find( irc, cmd[1] ); - if( !u || !u->gc ) + if( !u || !u->ic ) { irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] ); return; } - gc = u->gc; + ic = u->ic; cmd[2] = u->handle; } else if( !( a = account_get( irc, cmd[1] ) ) ) @@ -680,20 +680,20 @@ static void cmd_allow( irc_t *irc, char **cmd ) irc_usermsg( irc, "Invalid account" ); return; } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); return; } - if( !gc->acc->prpl->rem_deny || !gc->acc->prpl->add_permit ) + if( !ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } else { - bim_rem_block( gc, cmd[2] ); - bim_add_allow( gc, cmd[2] ); + bim_rem_block( ic, cmd[2] ); + bim_add_allow( ic, cmd[2] ); irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] ); } @@ -802,32 +802,32 @@ static void cmd_blist( irc_t *irc, char **cmd ) irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" ); - for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away ) + for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away ) { if( online == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, "Online" ); } n_online ++; } - for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away ) + for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away ) { if( away == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, u->away ); } n_away ++; } - for( u = irc->users; u; u = u->next ) if( u->gc && !u->online ) + for( u = irc->users; u; u = u->next ) if( u->ic && !u->online ) { if( offline == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); irc_usermsg( irc, format, u->nick, s, "Offline" ); } n_offline ++; @@ -844,15 +844,15 @@ static void cmd_nick( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Invalid account"); } - else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); } else if ( !cmd[2] ) { - irc_usermsg( irc, "Your name is `%s'" , a->gc->displayname ? a->gc->displayname : "NULL" ); + irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" ); } - else if ( !a->prpl->set_info ) + else if ( !a->prpl->set_my_name ) { irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); } @@ -860,7 +860,7 @@ static void cmd_nick( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Setting your name to `%s'", cmd[2] ); - a->prpl->set_info( a->gc, cmd[2] ); + a->prpl->set_my_name( a->ic, cmd[2] ); } } @@ -878,8 +878,8 @@ static void cmd_qlist( irc_t *irc, char **cmd ) irc_usermsg( irc, "Pending queries:" ); for( num = 0; q; q = q->next, num ++ ) - if( q->gc ) /* Not necessary yet, but it might come later */ - irc_usermsg( irc, "%d, %s(%s): %s", num, q->gc->acc->prpl->name, q->gc->username, q->question ); + if( q->ic ) /* Not necessary yet, but it might come later */ + irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->username, q->question ); else irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } @@ -887,16 +887,16 @@ static void cmd_qlist( irc_t *irc, char **cmd ) static void cmd_join_chat( irc_t *irc, char **cmd ) { account_t *a; - struct gaim_connection *gc; + struct im_connection *ic; char *chat, *channel, *nick = NULL, *password = NULL; - struct conversation *c; + struct groupchat *c; if( !( a = account_get( irc, cmd[1] ) ) ) { irc_usermsg( irc, "Invalid account" ); return; } - else if( !( a->gc && ( a->gc->flags & OPT_LOGGED_IN ) ) ) + else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) ) { irc_usermsg( irc, "That account is not on-line" ); return; @@ -906,7 +906,7 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); return; } - gc = a->gc; + ic = a->ic; chat = cmd[2]; if( cmd[3] ) @@ -926,7 +926,7 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) if( cmd[3] && cmd[4] && cmd[5] ) password = cmd[5]; - c = a->prpl->chat_join( gc, chat, nick, password ); + c = a->prpl->chat_join( ic, chat, nick, password ); g_free( channel ); } diff --git a/user.c b/user.c index ff65fe66..232e3a58 100644 --- a/user.c +++ b/user.c @@ -140,21 +140,21 @@ user_t *user_find( irc_t *irc, char *nick ) return( NULL ); } -user_t *user_findhandle( struct gaim_connection *gc, char *handle ) +user_t *user_findhandle( struct im_connection *ic, char *handle ) { user_t *u; char *nick; /* First, let's try a hash lookup. If it works, it's probably faster. */ - if( ( nick = g_hash_table_lookup( gc->acc->nicks, handle ) ) && - ( u = user_find( gc->irc, nick ) ) && - ( gc->acc->prpl->handle_cmp( handle, u->handle ) == 0 ) ) + if( ( nick = g_hash_table_lookup( ic->acc->nicks, handle ) ) && + ( u = user_find( ic->irc, nick ) ) && + ( ic->acc->prpl->handle_cmp( handle, u->handle ) == 0 ) ) return u; /* However, it doesn't always work, so in that case we'll have to dig through the whole userlist. :-( */ - for( u = gc->irc->users; u; u = u->next ) - if( u->gc == gc && u->handle && gc->acc->prpl->handle_cmp( u->handle, handle ) == 0 ) + for( u = ic->irc->users; u; u = u->next ) + if( u->ic == ic && u->handle && ic->acc->prpl->handle_cmp( u->handle, handle ) == 0 ) return u; return NULL; diff --git a/user.h b/user.h index b8896d92..d0a62bdc 100644 --- a/user.h +++ b/user.h @@ -37,7 +37,7 @@ typedef struct __USER char *handle; char *group; - struct gaim_connection *gc; + struct im_connection *ic; char *sendbuf; time_t last_typing_notice; @@ -53,5 +53,5 @@ typedef struct __USER user_t *user_add( struct irc *irc, char *nick ); int user_del( irc_t *irc, char *nick ); G_MODULE_EXPORT user_t *user_find( irc_t *irc, char *nick ); -G_MODULE_EXPORT user_t *user_findhandle( struct gaim_connection *gc, char *handle ); +G_MODULE_EXPORT user_t *user_findhandle( struct im_connection *ic, char *handle ); void user_rename( irc_t *irc, char *oldnick, char *newnick ); -- cgit v1.2.3 From aef4828a1dc51de10a43bb7dd5d023de9971295b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 5 Apr 2007 22:20:31 -0700 Subject: More cleanups, mainly in the callbacks. Replaced things like do_error_dialog() and (set|hide)_login_progress(_error)?() with things that hopefully make more sense. Although it's still not really great... --- account.c | 2 +- irc.c | 2 +- protocols/jabber/io.c | 54 ++++++++++---------- protocols/jabber/iq.c | 40 +++++++-------- protocols/jabber/jabber.c | 18 +++---- protocols/jabber/presence.c | 6 +-- protocols/jabber/sasl.c | 20 ++++---- protocols/msn/msn.c | 18 +++---- protocols/msn/msn_util.c | 6 +-- protocols/msn/ns.c | 121 ++++++++++++++++++++++--------------------- protocols/msn/sb.c | 11 ++-- protocols/nogaim.c | 107 ++++++++++++++++++++------------------ protocols/nogaim.h | 15 +++--- protocols/oscar/chat.c | 6 +-- protocols/oscar/chatnav.c | 10 ++-- protocols/oscar/icq.c | 2 +- protocols/oscar/im.c | 8 +-- protocols/oscar/info.c | 6 +-- protocols/oscar/oscar.c | 122 ++++++++++++++++++++------------------------ protocols/oscar/rxqueue.c | 2 +- protocols/oscar/search.c | 2 +- protocols/oscar/service.c | 4 +- protocols/oscar/txqueue.c | 8 +-- protocols/yahoo/yahoo.c | 37 ++++++-------- query.c | 8 +-- 25 files changed, 308 insertions(+), 327 deletions(-) diff --git a/account.c b/account.c index 03d05586..9245a6e9 100644 --- a/account.c +++ b/account.c @@ -223,7 +223,7 @@ void account_on( irc_t *irc, account_t *a ) void account_off( irc_t *irc, account_t *a ) { a->ic->wants_to_die = TRUE; - signoff( a->ic ); + imc_logout( a->ic ); a->ic = NULL; if( a->reconnect ) { diff --git a/irc.c b/irc.c index b1cae1d9..a78a0153 100644 --- a/irc.c +++ b/irc.c @@ -231,7 +231,7 @@ void irc_free(irc_t * irc) for (account = irc->accounts; account; account = account->next) { if (account->ic) { account->ic->wants_to_die = TRUE; - signoff(account->ic); + imc_logout(account->ic); } else if (account->reconnect) { cancel_auto_reconnect(account); } diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 6e699301..699c7019 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -116,8 +116,8 @@ static gboolean jabber_write_queue( struct im_connection *ic ) closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ jd->fd = -1; - hide_login_progress_error( ic, "Short write() to server" ); - signoff( ic ); + imc_error( ic, "Short write() to server" ); + imc_logout( ic ); return FALSE; } else if( st > 0 ) @@ -159,8 +159,8 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition /* Parse. */ if( xt_feed( jd->xt, buf, st ) < 0 ) { - hide_login_progress_error( ic, "XML stream error" ); - signoff( ic ); + imc_error( ic, "XML stream error" ); + imc_logout( ic ); return FALSE; } @@ -202,9 +202,9 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition SASL and TLS. */ if( set_getbool( &ic->acc->set, "tls" ) ) { - hide_login_progress( ic, "TLS is turned on for this " + imc_error( ic, "TLS is turned on for this " "account, but is not supported by this server" ); - signoff( ic ); + imc_logout( ic ); return FALSE; } else @@ -215,8 +215,8 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } else { - hide_login_progress( ic, "XML stream error" ); - signoff( ic ); + imc_error( ic, "XML stream error" ); + imc_logout( ic ); return FALSE; } } @@ -226,8 +226,8 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition closesocket( jd->fd ); jd->fd = -1; - hide_login_progress_error( ic, "Error while reading from server" ); - signoff( ic ); + imc_error( ic, "Error while reading from server" ); + imc_logout( ic ); return FALSE; } @@ -241,12 +241,12 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c if( source == -1 ) { - hide_login_progress( ic, "Could not connect to server" ); - signoff( ic ); + imc_error( ic, "Could not connect to server" ); + imc_logout( ic ); return FALSE; } - set_login_progress( ic, 1, "Connected to server, logging in" ); + imc_log( ic, "Connected to server, logging in" ); return jabber_start_stream( ic ); } @@ -262,19 +262,19 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co already, set it to NULL here to prevent a double cleanup: */ jd->ssl = NULL; - hide_login_progress( ic, "Could not connect to server" ); - signoff( ic ); + imc_error( ic, "Could not connect to server" ); + imc_logout( ic ); return FALSE; } - set_login_progress( ic, 1, "Connected to server, logging in" ); + imc_log( ic, "Connected to server, logging in" ); return jabber_start_stream( ic ); } static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) { - signoff( data ); + imc_logout( data ); return XT_ABORT; } @@ -296,8 +296,8 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) ) { - hide_login_progress( ic, "Server requires TLS connections, but TLS is turned off for this account" ); - signoff( ic ); + imc_error( ic, "Server requires TLS connections, but TLS is turned off for this account" ); + imc_logout( ic ); return XT_ABORT; } @@ -326,8 +326,8 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( !trytls && set_getbool( &ic->acc->set, "tls" ) ) { - hide_login_progress( ic, "TLS is turned on for this account, but is not supported by this server" ); - signoff( ic ); + imc_error( ic, "TLS is turned on for this account, but is not supported by this server" ); + imc_logout( ic ); return XT_ABORT; } @@ -416,7 +416,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) } jd->w_inpa = jd->r_inpa = 0; - set_login_progress( ic, 1, "Converting stream to TLS" ); + imc_log( ic, "Converting stream to TLS" ); jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic ); @@ -451,8 +451,8 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) /* Tssk... */ if( type == NULL ) { - hide_login_progress_error( ic, "Unknown stream error reported by server" ); - signoff( ic ); + imc_error( ic, "Unknown stream error reported by server" ); + imc_logout( ic ); return XT_ABORT; } @@ -461,17 +461,17 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) infinite loop! */ if( strcmp( type, "conflict" ) == 0 ) { - hide_login_progress( ic, "Account and resource used from a different location" ); + imc_error( ic, "Account and resource used from a different location" ); ic->wants_to_die = TRUE; } else { s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); - hide_login_progress_error( ic, s ); + imc_error( ic, s ); g_free( s ); } - signoff( ic ); + imc_logout( ic ); return XT_ABORT; } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 86d97e15..e1848272 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -38,8 +38,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !type ) { - hide_login_progress_error( ic, "Received IQ packet without type." ); - signoff( ic ); + imc_error( ic, "Received IQ packet without type." ); + imc_logout( ic ); return XT_ABORT; } @@ -59,7 +59,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) entry = g_hash_table_lookup( jd->node_cache, s ); if( entry == NULL ) - serv_got_crap( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); + imc_log( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); else if( entry->func ) return entry->func( ic, node, entry->node ); } @@ -68,7 +68,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - serv_got_crap( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imc_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -131,7 +131,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - serv_got_crap( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imc_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -153,7 +153,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else { - serv_got_crap( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); + imc_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -218,8 +218,8 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no if( !( query = xt_find_node( node->children, "query" ) ) ) { - serv_got_crap( ic, "WARNING: Received incomplete IQ packet while authenticating" ); - signoff( ic ); + imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imc_logout( ic ); return XT_HANDLED; } @@ -257,8 +257,8 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no { xt_free_node( reply ); - hide_login_progress( ic, "Can't find suitable authentication method" ); - signoff( ic ); + imc_error( ic, "Can't find suitable authentication method" ); + imc_logout( ic ); return XT_ABORT; } @@ -276,15 +276,15 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node if( !( type = xt_find_attr( node, "type" ) ) ) { - serv_got_crap( ic, "WARNING: Received incomplete IQ packet while authenticating" ); - signoff( ic ); + imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imc_logout( ic ); return XT_HANDLED; } if( strcmp( type, "error" ) == 0 ) { - hide_login_progress( ic, "Authentication failure" ); - signoff( ic ); + imc_error( ic, "Authentication failure" ); + imc_logout( ic ); return XT_ABORT; } else if( strcmp( type, "result" ) == 0 ) @@ -310,7 +310,7 @@ xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, c = xt_find_node( c->children, "jid" ); if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 ) - serv_got_crap( ic, "Server changed session resource string to `%s'", s + 1 ); + imc_log( ic, "Server changed session resource string to `%s'", s + 1 ); jd->flags &= ~JFLAG_WAIT_BIND; } @@ -333,7 +333,7 @@ int jabber_get_roster( struct im_connection *ic ) struct xt_node *node; int st; - set_login_progress( ic, 1, "Authenticated, requesting buddy list" ); + imc_log( ic, "Authenticated, requesting buddy list" ); node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); @@ -352,7 +352,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * if( !( query = xt_find_node( node->children, "query" ) ) ) { - serv_got_crap( ic, "WARNING: Received NULL roster packet" ); + imc_log( ic, "WARNING: Received NULL roster packet" ); return XT_HANDLED; } @@ -396,7 +396,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * } if( initial ) - account_online( ic ); + imc_connected( ic ); return XT_HANDLED; } @@ -427,7 +427,7 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) { s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ - serv_got_crap( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); + imc_log( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); return XT_HANDLED; } @@ -535,7 +535,7 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no /* *sigh* */ - serv_got_crap( ic, reply->str ); + imc_log( ic, reply->str ); g_string_free( reply, TRUE ); return XT_HANDLED; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 23de1103..ec0df487 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -58,7 +58,7 @@ static void jabber_init( account_t *acc ) static void jabber_login( account_t *acc ) { - struct im_connection *ic = new_gaim_conn( acc ); + struct im_connection *ic = imc_new( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); struct ns_srv_reply *srv = NULL; char *connect_to, *s; @@ -71,8 +71,8 @@ static void jabber_login( account_t *acc ) if( jd->server == NULL ) { - hide_login_progress( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); - signoff( ic ); + imc_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); + imc_logout( ic ); return; } @@ -158,14 +158,14 @@ static void jabber_login( account_t *acc ) else connect_to = jd->server; - set_login_progress( ic, 0, "Connecting" ); + imc_log( ic, "Connecting" ); if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN || set_getint( &acc->set, "port" ) > JABBER_PORT_MAX ) { - serv_got_crap( ic, "Incorrect port number, must be in the %d-%d range", + imc_log( ic, "Incorrect port number, must be in the %d-%d range", JABBER_PORT_MIN, JABBER_PORT_MAX ); - signoff( ic ); + imc_logout( ic ); return; } @@ -185,8 +185,8 @@ static void jabber_login( account_t *acc ) if( jd->fd == -1 ) { - hide_login_progress( ic, "Could not connect to server" ); - signoff( ic ); + imc_error( ic, "Could not connect to server" ); + imc_logout( ic ); } } @@ -284,7 +284,7 @@ static void jabber_get_info( struct im_connection *ic, char *who ) while( bud ) { - serv_got_crap( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", + imc_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", bud->full_jid, bud->priority, bud->away_state ? bud->away_state->full_name : "(none)", bud->away_message ? : "(none)" ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 2db32fd1..634948bf 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -40,7 +40,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) - serv_got_crap( ic, "WARNING: Could not handle presence information from JID: %s", from ); + imc_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -73,7 +73,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) - serv_got_crap( ic, "WARNING: Received presence information from unknown JID: %s", from ); + imc_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } @@ -102,7 +102,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else if( strcmp( type, "subscribed" ) == 0 ) { /* Not sure about this one, actually... */ - serv_got_crap( ic, "%s just accepted your authorization request", from ); + imc_log( ic, "%s just accepted your authorization request", from ); } else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) { diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 4943f59e..ab6f6c00 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -37,14 +37,14 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) /* Should abort this now, since we should already be doing IQ authentication. Strange things happen when you try to do both... */ - serv_got_crap( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); + imc_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); return XT_HANDLED; } s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - signoff( ic ); + imc_logout( ic ); return XT_ABORT; } @@ -61,8 +61,8 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) if( !sup_plain && !sup_digest ) { - hide_login_progress( ic, "No known SASL authentication schemes supported" ); - signoff( ic ); + imc_error( ic, "No known SASL authentication schemes supported" ); + imc_logout( ic ); return XT_ABORT; } @@ -278,8 +278,8 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) goto silent_error; error: - hide_login_progress( ic, "Incorrect SASL challenge received" ); - signoff( ic ); + imc_error( ic, "Incorrect SASL challenge received" ); + imc_logout( ic ); silent_error: g_free( digest_uri ); @@ -302,19 +302,19 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - signoff( ic ); + imc_logout( ic ); return XT_ABORT; } if( strcmp( node->name, "success" ) == 0 ) { - set_login_progress( ic, 1, "Authentication finished" ); + imc_log( ic, "Authentication finished" ); jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; } else if( strcmp( node->name, "failure" ) == 0 ) { - hide_login_progress( ic, "Authentication failure" ); - signoff( ic ); + imc_error( ic, "Authentication failure" ); + imc_logout( ic ); return XT_ABORT; } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index afc90627..860be01b 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -38,7 +38,7 @@ static void msn_init( account_t *acc ) static void msn_login( account_t *acc ) { - struct im_connection *ic = new_gaim_conn( acc ); + struct im_connection *ic = imc_new( acc ); struct msn_data *md = g_new0( struct msn_data, 1 ); ic->proto_data = md; @@ -46,18 +46,18 @@ static void msn_login( account_t *acc ) if( strchr( acc->user, '@' ) == NULL ) { - hide_login_progress( ic, "Invalid account name" ); - signoff( ic ); + imc_error( ic, "Invalid account name" ); + imc_logout( ic ); return; } - set_login_progress( ic, 1, "Connecting" ); + imc_log( ic, "Connecting" ); md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, ic ); if( md->fd < 0 ) { - hide_login_progress( ic, "Could not connect to server" ); - signoff( ic ); + imc_error( ic, "Could not connect to server" ); + imc_logout( ic ); return; } @@ -95,7 +95,7 @@ static void msn_logout( struct im_connection *ic ) { m = l->data; - serv_got_crap( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); + imc_log( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); g_free( m->who ); g_free( m->text ); g_free( m ); @@ -227,7 +227,7 @@ static void msn_set_my_name( struct im_connection *ic, char *info ) static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - serv_got_crap( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); + imc_log( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); } static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) @@ -372,7 +372,7 @@ static char *msn_set_display_name( set_t *set, char *value ) if( strlen( value ) > 129 ) { - serv_got_crap( ic, "Maximum name length exceeded" ); + imc_log( ic, "Maximum name length exceeded" ); return NULL; } diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 1be1586c..72411095 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -35,8 +35,8 @@ int msn_write( struct im_connection *ic, char *s, int len ) st = write( md->fd, s, len ); if( st != len ) { - hide_login_progress_error( ic, "Short write() to main server" ); - signoff( ic ); + imc_error( ic, "Short write() to main server" ); + imc_logout( ic ); return( 0 ); } @@ -45,7 +45,7 @@ int msn_write( struct im_connection *ic, char *s, int len ) int msn_logged_in( struct im_connection *ic ) { - account_online( ic ); + imc_connected( ic ); return( 0 ); } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 9d86a68e..e4530b8f 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -46,8 +46,8 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) if( source == -1 ) { - hide_login_progress( ic, "Could not connect to server" ); - signoff( ic ); + imc_error( ic, "Could not connect to server" ); + imc_logout( ic ); return FALSE; } @@ -75,7 +75,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) if( msn_write( ic, s, strlen( s ) ) ) { ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic ); - set_login_progress( ic, 1, "Connected to server, waiting for reply" ); + imc_log( ic, "Connected to server, waiting for reply" ); } return FALSE; @@ -88,8 +88,8 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ { - hide_login_progress( ic, "Error while reading from server" ); - signoff( ic ); + imc_error( ic, "Error while reading from server" ); + imc_logout( ic ); return FALSE; } @@ -113,8 +113,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) { - hide_login_progress( ic, "Unsupported protocol" ); - signoff( ic ); + imc_error( ic, "Unsupported protocol" ); + imc_logout( ic ); return( 0 ); } @@ -142,15 +142,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[3], ':' ); if( !server ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } *server = 0; port = atoi( server + 1 ); server = cmd[3]; - set_login_progress( ic, 1, "Transferring to other server" ); + imc_log( ic, "Transferring to other server" ); md->fd = proxy_connect( server, port, msn_ns_connected, ic ); } @@ -161,8 +161,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[3], ':' ); if( !server ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } *server = 0; @@ -171,8 +171,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[4], "CKI" ) != 0 ) { - hide_login_progress_error( ic, "Unknown authentication method for switchboard" ); - signoff( ic ); + imc_error( ic, "Unknown authentication method for switchboard" ); + imc_logout( ic ); return( 0 ); } @@ -203,8 +203,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } } @@ -215,8 +215,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) /* Time for some Passport black magic... */ if( !passport_get_id( msn_auth_got_passport_id, ic, ic->username, ic->password, cmd[4] ) ) { - hide_login_progress_error( ic, "Error while contacting Passport server" ); - signoff( ic ); + imc_error( ic, "Error while contacting Passport server" ); + imc_logout( ic ); return( 0 ); } } @@ -235,15 +235,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) s->value = g_strdup( cmd[4] ); } - set_login_progress( ic, 1, "Authenticated, getting buddy list" ); + imc_log( ic, "Authenticated, getting buddy list" ); g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); return( msn_write( ic, buf, strlen( buf ) ) ); } else { - hide_login_progress( ic, "Unknown authentication type" ); - signoff( ic ); + imc_error( ic, "Unknown authentication type" ); + imc_logout( ic ); return( 0 ); } } @@ -251,8 +251,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( num_parts != 4 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -260,8 +260,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->handler->msglen <= 0 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } } @@ -291,8 +291,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 && num_parts != 5 ) { - hide_login_progress( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -327,7 +327,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( ic->flags & OPT_LOGGED_IN ) { - serv_got_crap( ic, "Successfully transferred to different server" ); + imc_log( ic, "Successfully transferred to different server" ); g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); return( msn_write( ic, buf, strlen( buf ) ) ); } @@ -343,8 +343,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -362,8 +362,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 3 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -384,8 +384,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 6 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -412,8 +412,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 5 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -437,8 +437,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 7 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -447,8 +447,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[2], ':' ); if( !server ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } *server = 0; @@ -457,8 +457,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[3], "CKI" ) != 0 ) { - hide_login_progress_error( ic, "Unknown authentication method for switchboard" ); - signoff( ic ); + imc_error( ic, "Unknown authentication method for switchboard" ); + imc_logout( ic ); return( 0 ); } @@ -477,8 +477,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strchr( cmd[4], '@' ) == NULL ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -498,27 +498,27 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) { - hide_login_progress_error( ic, "Someone else logged in with your account" ); + imc_error( ic, "Someone else logged in with your account" ); ic->wants_to_die = 1; } else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) { - hide_login_progress_error( ic, "Terminating session because of server shutdown" ); + imc_error( ic, "Terminating session because of server shutdown" ); } else { - hide_login_progress_error( ic, "Session terminated by remote server (reason unknown)" ); + imc_error( ic, "Session terminated by remote server (reason unknown)" ); } - signoff( ic ); + imc_logout( ic ); return( 0 ); } else if( strcmp( cmd[0], "REA" ) == 0 ) { if( num_parts != 5 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } @@ -545,14 +545,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "IPG" ) == 0 ) { - do_error_dialog( ic, "Received IPG command, we don't handle them yet.", "MSN" ); + imc_error( ic, "Received IPG command, we don't handle them yet." ); md->handler->msglen = atoi( cmd[1] ); if( md->handler->msglen <= 0 ) { - hide_login_progress_error( ic, "Syntax error" ); - signoff( ic ); + imc_error( ic, "Syntax error" ); + imc_logout( ic ); return( 0 ); } } @@ -561,12 +561,11 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); - g_snprintf( buf, sizeof( buf ), "Error reported by MSN server: %s", err->text ); - do_error_dialog( ic, buf, "MSN" ); + imc_error( ic, "Error reported by MSN server: %s", err->text ); if( err->flags & STATUS_FATAL ) { - signoff( ic ); + imc_logout( ic ); return( 0 ); } } @@ -616,7 +615,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( mtype && strcmp( mtype, "1" ) == 0 ) { if( arg1 ) - serv_got_crap( ic, "The server is going down for maintenance in %s minutes.", arg1 ); + imc_log( ic, "The server is going down for maintenance in %s minutes.", arg1 ); } if( arg1 ) g_free( arg1 ); @@ -633,7 +632,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( inbox && folders ) { - serv_got_crap( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); + imc_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); } } else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 ) @@ -643,7 +642,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( from && fromname ) { - serv_got_crap( ic, "Received an e-mail message from %s <%s>.", fromname, from ); + imc_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); } } else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) @@ -676,8 +675,8 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) err = g_strdup_printf( "Error during Passport authentication (%s)", rep->error_string ? rep->error_string : "Unknown error" ); - hide_login_progress( ic, err ); - signoff( ic ); + imc_error( ic, err ); + imc_logout( ic ); g_free( err ); } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index f9c755a5..f7007d32 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -221,7 +221,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) } g_slist_free( sb->msgq ); - serv_got_crap( ic, "Warning: Closing down MSN switchboard connection with " + imc_log( ic, "Warning: Closing down MSN switchboard connection with " "unsent message to %s, you'll have to resend it.", sb->who ? sb->who : "(unknown)" ); } @@ -320,8 +320,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "XFR" ) == 0 ) { - hide_login_progress_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); - signoff( ic ); + imc_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); + imc_logout( ic ); return( 0 ); } else if( strcmp( cmd[0], "USR" ) == 0 ) @@ -527,8 +527,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); - g_snprintf( buf, sizeof( buf ), "Error reported by switchboard server: %s", err->text ); - do_error_dialog( ic, buf, "MSN" ); + imc_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) { @@ -537,7 +536,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( err->flags & STATUS_FATAL ) { - signoff( ic ); + imc_logout( ic ); return 0; } else if( err->flags & STATUS_SB_IM_SPARE ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 987c08f2..0c042bac 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -144,7 +144,7 @@ GSList *get_connections() { return connections; } /* multi.c */ -struct im_connection *new_gaim_conn( account_t *acc ) +struct im_connection *imc_new( account_t *acc ) { struct im_connection *ic; @@ -163,7 +163,7 @@ struct im_connection *new_gaim_conn( account_t *acc ) return( ic ); } -void destroy_gaim_conn( struct im_connection *ic ) +void imc_free( struct im_connection *ic ) { account_t *a; @@ -179,24 +179,7 @@ void destroy_gaim_conn( struct im_connection *ic ) g_free( ic ); } -void set_login_progress( struct im_connection *ic, int step, char *msg ) -{ - serv_got_crap( ic, "Logging in: %s", msg ); -} - -/* Errors *while* logging in */ -void hide_login_progress( struct im_connection *ic, char *msg ) -{ - serv_got_crap( ic, "Login error: %s", msg ); -} - -/* Errors *after* logging in */ -void hide_login_progress_error( struct im_connection *ic, char *msg ) -{ - serv_got_crap( ic, "Logged out: %s", msg ); -} - -void serv_got_crap( struct im_connection *ic, char *format, ... ) +static void serv_got_crap( struct im_connection *ic, char *format, ... ) { va_list params; char *text; @@ -224,6 +207,40 @@ void serv_got_crap( struct im_connection *ic, char *format, ... ) g_free( text ); } +void imc_log( struct im_connection *ic, char *format, ... ) +{ + va_list params; + char *text; + + va_start( params, format ); + text = g_strdup_vprintf( format, params ); + va_end( params ); + + if( ic->flags & OPT_LOGGED_IN ) + serv_got_crap( ic, "%s", text ); + else + serv_got_crap( ic, "Logging in: %s", text ); + + g_free( text ); +} + +void imc_error( struct im_connection *ic, char *format, ... ) +{ + va_list params; + char *text; + + va_start( params, format ); + text = g_strdup_vprintf( format, params ); + va_end( params ); + + if( ic->flags & OPT_LOGGED_IN ) + serv_got_crap( ic, "Error: %s", text ); + else + serv_got_crap( ic, "Couldn't log in: %s", text ); + + g_free( text ); +} + static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) { struct im_connection *ic = d; @@ -234,7 +251,7 @@ static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) return TRUE; } -void account_online( struct im_connection *ic ) +void imc_connected( struct im_connection *ic ) { user_t *u; @@ -246,7 +263,7 @@ void account_online( struct im_connection *ic ) u = user_find( ic->irc, ic->irc->nick ); - serv_got_crap( ic, "Logged in" ); + imc_log( ic, "Logged in" ); ic->keepalive = b_timeout_add( 60000, send_keepalive, ic ); ic->flags |= OPT_LOGGED_IN; @@ -273,7 +290,7 @@ void cancel_auto_reconnect( account_t *a ) a->reconnect = 0; } -void signoff( struct im_connection *ic ) +void imc_logout( struct im_connection *ic ) { irc_t *irc = ic->irc; user_t *t, *u = irc->users; @@ -286,7 +303,7 @@ void signoff( struct im_connection *ic ) else ic->flags |= OPT_LOGGING_OUT; - serv_got_crap( ic, "Signing off.." ); + imc_log( ic, "Signing off.." ); b_event_remove( ic->keepalive ); ic->keepalive = 0; @@ -320,28 +337,16 @@ void signoff( struct im_connection *ic ) { int delay = set_getint( &irc->set, "auto_reconnect_delay" ); - serv_got_crap( ic, "Reconnecting in %d seconds..", delay ); + imc_log( ic, "Reconnecting in %d seconds..", delay ); a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); } - destroy_gaim_conn( ic ); + imc_free( ic ); } /* dialogs.c */ -void do_error_dialog( struct im_connection *ic, char *msg, char *title ) -{ - if( msg && title ) - serv_got_crap( ic, "Error: %s: %s", title, msg ); - else if( msg ) - serv_got_crap( ic, "Error: %s", msg ); - else if( title ) - serv_got_crap( ic, "Error: %s", title ); - else - serv_got_crap( ic, "Error" ); -} - void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) { query_add( ic->irc, ic, msg, doit, dont, data ); @@ -358,12 +363,12 @@ void add_buddy( struct im_connection *ic, char *group, char *handle, char *realn irc_t *irc = ic->irc; if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */ - serv_got_crap( ic, "Receiving user add from handle: %s", handle ); + imc_log( ic, "Receiving user add from handle: %s", handle ); if( user_findhandle( ic, handle ) ) { if( set_getbool( &irc->set, "debug" ) ) - serv_got_crap( ic, "User already exists, ignoring add request: %s", handle ); + imc_log( ic, "User already exists, ignoring add request: %s", handle ); return; @@ -451,7 +456,7 @@ void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ) u->realname = g_strdup( realname ); if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) - serv_got_crap( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); + imc_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); } } @@ -515,8 +520,8 @@ void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int { if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { - serv_got_crap( ic, "serv_got_update() for handle %s:", handle ); - serv_got_crap( ic, "loggedin = %d, type = %d", loggedin, type ); + imc_log( ic, "serv_got_update() for handle %s:", handle ); + imc_log( ic, "loggedin = %d, type = %d", loggedin, type ); } return; @@ -596,7 +601,7 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla if( g_strcasecmp( h, "ignore" ) == 0 ) { if( set_getbool( &irc->set, "debug" ) ) - serv_got_crap( ic, "Ignoring message from unknown handle %s", handle ); + imc_log( ic, "Ignoring message from unknown handle %s", handle ); return; } @@ -618,7 +623,7 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla } else { - serv_got_crap( ic, "Message from unknown handle %s:", handle ); + imc_log( ic, "Message from unknown handle %s:", handle ); u = user_find( irc, irc->mynick ); } } @@ -688,7 +693,7 @@ void serv_got_chat_left( struct groupchat *c ) GList *ir; if( set_getbool( &ic->irc->set, "debug" ) ) - serv_got_crap( ic, "You were removed from conversation 0x%x", (int) c ); + imc_log( ic, "You were removed from conversation 0x%x", (int) c ); if( c ) { @@ -736,7 +741,7 @@ void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, t if( c && u ) irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", msg ); else - serv_got_crap( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); + imc_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); } struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) @@ -758,7 +763,7 @@ struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); if( set_getbool( &ic->irc->set, "debug" ) ) - serv_got_crap( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); + imc_log( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); return c; } @@ -772,7 +777,7 @@ void add_chat_buddy( struct groupchat *b, char *handle ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - serv_got_crap( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); + imc_log( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); /* It might be yourself! */ if( b->ic->acc->prpl->handle_cmp( handle, b->ic->username ) == 0 ) @@ -806,7 +811,7 @@ void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - serv_got_crap( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); + imc_log( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); /* It might be yourself! */ if( g_strcasecmp( handle, b->ic->username ) == 0 ) @@ -1004,7 +1009,7 @@ int bim_set_away( struct im_connection *ic, char *away ) { ic->acc->prpl->set_away( ic, s, away ); if( set_getbool( &ic->irc->set, "debug" ) ) - serv_got_crap( ic, "Setting away state to %s", s ); + imc_log( ic, "Setting away state to %s", s ); } else ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 82472fd3..53e3b23b 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -205,17 +205,14 @@ gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); void cancel_auto_reconnect( struct account *a ); /* multi.c */ -G_MODULE_EXPORT struct im_connection *new_gaim_conn( account_t *acc ); -G_MODULE_EXPORT void destroy_gaim_conn( struct im_connection *ic ); -G_MODULE_EXPORT void set_login_progress( struct im_connection *ic, int step, char *msg ); -G_MODULE_EXPORT void hide_login_progress( struct im_connection *ic, char *msg ); -G_MODULE_EXPORT void hide_login_progress_error( struct im_connection *ic, char *msg ); -G_MODULE_EXPORT void serv_got_crap( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); -G_MODULE_EXPORT void account_online( struct im_connection *ic ); -G_MODULE_EXPORT void signoff( struct im_connection *ic ); +G_MODULE_EXPORT struct im_connection *imc_new( account_t *acc ); +G_MODULE_EXPORT void imc_free( struct im_connection *ic ); +G_MODULE_EXPORT void imc_log( struct im_connection *ic, char *format, ... ); +G_MODULE_EXPORT void imc_error( struct im_connection *ic, char *format, ... ); +G_MODULE_EXPORT void imc_connected( struct im_connection *ic ); +G_MODULE_EXPORT void imc_logout( struct im_connection *ic ); /* dialogs.c */ -G_MODULE_EXPORT void do_error_dialog( struct im_connection *ic, char *msg, char *title ); G_MODULE_EXPORT void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); /* list.c */ diff --git a/protocols/oscar/chat.c b/protocols/oscar/chat.c index df535c4f..82aa5421 100644 --- a/protocols/oscar/chat.c +++ b/protocols/oscar/chat.c @@ -53,7 +53,7 @@ aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name) if (cur->type != AIM_CONN_TYPE_CHAT) continue; if (!cur->priv) { - do_error_dialog(sess->aux_data, "chat connection with no name!", "Gaim"); + imc_error(sess->aux_data, "chat connection with no name!"); continue; } @@ -396,7 +396,7 @@ static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a detaillevel = aimbs_get8(bs); if (detaillevel != 0x02) { - do_error_dialog(sess->aux_data, "Only detaillevel 0x2 is support at the moment", "Gaim"); + imc_error(sess->aux_data, "Only detaillevel 0x2 is support at the moment"); return 1; } @@ -614,7 +614,7 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, channel = aimbs_get16(bs); if (channel != 0x0003) { - do_error_dialog(sess->aux_data, "unknown channel!", "Gaim"); + imc_error(sess->aux_data, "unknown channel!"); return 0; } diff --git a/protocols/oscar/chatnav.c b/protocols/oscar/chatnav.c index c7e11765..05fdf6fa 100644 --- a/protocols/oscar/chatnav.c +++ b/protocols/oscar/chatnav.c @@ -285,7 +285,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t tlvlist = aim_readtlvchain(bs); if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) { - do_error_dialog(sess->aux_data, "no bigblock in top tlv in create room response", "Gaim"); + imc_error(sess->aux_data, "no bigblock in top tlv in create room response"); aim_freetlvchain(&tlvlist); return 0; @@ -300,7 +300,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t detaillevel = aimbs_get8(&bbbs); if (detaillevel != 0x02) { - do_error_dialog(sess->aux_data, "unknown detaillevel in create room response", "Gaim"); + imc_error(sess->aux_data, "unknown detaillevel in create room response"); aim_freetlvchain(&tlvlist); g_free(ck); return 0; @@ -366,12 +366,12 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai int ret = 0; if (!(snac2 = aim_remsnac(sess, snac->id))) { - do_error_dialog(sess->aux_data, "received response to unknown request!", "Gaim"); + imc_error(sess->aux_data, "received response to unknown request!"); return 0; } if (snac2->family != 0x000d) { - do_error_dialog(sess->aux_data, "recieved response that maps to corrupt request!", "Gaim"); + imc_error(sess->aux_data, "recieved response that maps to corrupt request!"); return 0; } @@ -388,7 +388,7 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai else if (snac2->type == 0x0008) /* create room */ ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); else - do_error_dialog(sess->aux_data, "unknown request subtype", "Gaim"); + imc_error(sess->aux_data, "unknown request subtype"); if (snac2) g_free(snac2->data); diff --git a/protocols/oscar/icq.c b/protocols/oscar/icq.c index 23959b75..d3c7c182 100644 --- a/protocols/oscar/icq.c +++ b/protocols/oscar/icq.c @@ -239,7 +239,7 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, if (!(tl = aim_readtlvchain(bs)) || !(datatlv = aim_gettlv(tl, 0x0001, 1))) { aim_freetlvchain(&tl); - do_error_dialog(sess->aux_data, "corrupt ICQ response\n", "Gaim"); + imc_error(sess->aux_data, "corrupt ICQ response\n"); return 0; } diff --git a/protocols/oscar/im.c b/protocols/oscar/im.c index bc2c2abe..ac3d08d4 100644 --- a/protocols/oscar/im.c +++ b/protocols/oscar/im.c @@ -936,7 +936,7 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a channel = aimbs_get16(bs); if (channel != 0x01) { - do_error_dialog(sess->aux_data, "icbm: ICBM recieved on unsupported channel. Ignoring.", "Gaim"); + imc_error(sess->aux_data, "icbm: ICBM recieved on unsupported channel. Ignoring."); return 0; } @@ -1344,7 +1344,7 @@ static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r args.extdata = aimbs_getraw(bs, args.extdatalen); } else { - // do_error_dialog(sess->aux_data, "Unknown TLV encountered", "Gaim"); + // imc_error(sess->aux_data, "Unknown TLV encountered"); } /* @@ -1516,7 +1516,7 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r */ cookie2 = aimbs_getraw(&bbs, 8); if (memcmp(cookie, cookie2, 8) != 0) - do_error_dialog(sess->aux_data, "rend: warning cookies don't match!", "Gaim"); + imc_error(sess->aux_data, "rend: warning cookies don't match!"); memcpy(args.cookie, cookie2, 8); g_free(cookie2); @@ -1782,7 +1782,7 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a } else { - do_error_dialog(sess->aux_data, "ICBM received on an unsupported channel. Ignoring.", "Gaim"); + imc_error(sess->aux_data, "ICBM received on an unsupported channel. Ignoring."); return 0; } diff --git a/protocols/oscar/info.c b/protocols/oscar/info.c index 0f1bcfd2..d1ed2059 100644 --- a/protocols/oscar/info.c +++ b/protocols/oscar/info.c @@ -473,7 +473,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * * */ #ifdef DEBUG - // do_error_dialog(sess->aux_data, G_STRLOC, "Unknown TLV encountered"); + // imc_error(sess->aux_data, G_STRLOC); #endif } @@ -634,7 +634,7 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim origsnac = aim_remsnac(sess, snac->id); if (!origsnac || !origsnac->data) { - do_error_dialog(sess->aux_data, "major problem: no snac stored!", "Gaim"); + imc_error(sess->aux_data, "major problem: no snac stored!"); return 0; } @@ -643,7 +643,7 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) && (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) && (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) { - do_error_dialog(sess->aux_data, "unknown infotype in request!", "Gaim"); + imc_error(sess->aux_data, "unknown infotype in request!"); return 0; } diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index d2c6af1e..929b63d3 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -262,23 +262,21 @@ static gboolean oscar_callback(gpointer data, gint source, if (aim_get_command(odata->sess, conn) >= 0) { aim_rxdispatch(odata->sess); if (odata->killme) - signoff(ic); + imc_logout(ic); } else { if ((conn->type == AIM_CONN_TYPE_BOS) || !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { - hide_login_progress_error(ic, _("Disconnected.")); - signoff(ic); + imc_error(ic, _("Disconnected.")); + imc_logout(ic); } else if (conn->type == AIM_CONN_TYPE_CHAT) { struct chat_connection *c = find_oscar_chat_by_conn(ic, conn); - char buf[BUF_LONG]; c->conn = NULL; if (c->inpa > 0) b_event_remove(c->inpa); c->inpa = 0; c->fd = -1; aim_conn_kill(odata->sess, &conn); - sprintf(buf, _("You have been disconnected from chat room %s."), c->name); - do_error_dialog(sess->aux_data, buf, _("Chat Error!")); + imc_error(sess->aux_data, _("You have been disconnected from chat room %s."), c->name); } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { if (odata->cnpa > 0) b_event_remove(odata->cnpa); @@ -289,8 +287,7 @@ static gboolean oscar_callback(gpointer data, gint source, odata->create_rooms = g_slist_remove(odata->create_rooms, cr); g_free(cr); - do_error_dialog(sess->aux_data, _("Chat is currently unavailable"), - _("Gaim - Chat")); + imc_error(sess->aux_data, _("Chat is currently unavailable")); } aim_conn_kill(odata->sess, &conn); } else if (conn->type == AIM_CONN_TYPE_AUTH) { @@ -327,8 +324,8 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); if (source < 0) { - hide_login_progress(ic, _("Couldn't connect to host")); - signoff(ic); + imc_error(ic, _("Couldn't connect to host")); + imc_logout(ic); return FALSE; } @@ -355,8 +352,7 @@ static void oscar_init(account_t *acc) static void oscar_login(account_t *acc) { aim_session_t *sess; aim_conn_t *conn; - char buf[256]; - struct im_connection *ic = new_gaim_conn(acc); + struct im_connection *ic = imc_new(acc); struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); if (isdigit(acc->user[0])) { @@ -381,24 +377,23 @@ static void oscar_login(account_t *acc) { conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (conn == NULL) { - hide_login_progress(ic, _("Unable to login to AIM")); - signoff(ic); + imc_error(ic, _("Unable to login to AIM")); + imc_logout(ic); return; } if (acc->server == NULL) { - hide_login_progress(ic, "No servername specified"); - signoff(ic); + imc_error(ic, "No servername specified"); + imc_logout(ic); return; } if (g_strcasecmp(acc->server, "login.icq.com") != 0 && g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { - serv_got_crap(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); + imc_log(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); } - g_snprintf(buf, sizeof(buf), _("Signon: %s"), ic->username); - set_login_progress(ic, 2, buf); + imc_log(ic, _("Signon: %s"), ic->username); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); @@ -406,8 +401,8 @@ static void oscar_login(account_t *acc) { conn->status |= AIM_CONN_STATUS_INPROGRESS; conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, ic); if (conn->fd < 0) { - hide_login_progress(ic, _("Couldn't connect to host")); - signoff(ic); + imc_error(ic, _("Couldn't connect to host")); + imc_logout(ic); return; } aim_request_login(sess, conn, ic->username); @@ -466,15 +461,15 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition bosconn = odata->conn; if (source < 0) { - hide_login_progress(ic, _("Could Not Connect")); - signoff(ic); + imc_error(ic, _("Could Not Connect")); + imc_logout(ic); return FALSE; } aim_conn_completeconnect(sess, bosconn); ic->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); - set_login_progress(ic, 4, _("Connection established, cookie sent")); + imc_log(ic, _("Connection established, cookie sent")); return FALSE; } @@ -497,23 +492,23 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { switch (info->errorcode) { case 0x05: /* Incorrect nick/password */ - hide_login_progress(ic, _("Incorrect nickname or password.")); + imc_error(ic, _("Incorrect nickname or password.")); // plugin_event(event_error, (void *)980, 0, 0, 0); break; case 0x11: /* Suspended account */ - hide_login_progress(ic, _("Your account is currently suspended.")); + imc_error(ic, _("Your account is currently suspended.")); break; case 0x18: /* connecting too frequently */ - hide_login_progress(ic, _("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.")); + imc_error(ic, _("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.")); break; case 0x1c: /* client too old */ - hide_login_progress(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE)); + imc_error(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE)); break; default: - hide_login_progress(ic, _("Authentication Failed")); + imc_error(ic, _("Authentication Failed")); break; } od->killme = TRUE; @@ -525,7 +520,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); if (bosconn == NULL) { - hide_login_progress(ic, _("Internal Error")); + imc_error(ic, _("Internal Error")); od->killme = TRUE; return 0; } @@ -571,7 +566,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { bosconn->fd = proxy_connect(host, port, oscar_bos_connect, ic); g_free(host); if (bosconn->fd < 0) { - hide_login_progress(ic, _("Could Not Connect")); + imc_error(ic, _("Could Not Connect")); od->killme = TRUE; return 0; } @@ -609,8 +604,8 @@ static gboolean damn_you(gpointer data, gint source, b_input_condition c) in = '\0'; } if (in != '\n') { - do_error_dialog(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." - " You may be disconnected shortly.", "Login Error"); + imc_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." + " You may be disconnected shortly."); b_event_remove(pos->inpa); closesocket(pos->fd); g_free(pos); @@ -632,8 +627,8 @@ static gboolean straight_to_hell(gpointer data, gint source, b_input_condition c char buf[BUF_LONG]; if (source < 0) { - do_error_dialog(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." - " You may be disconnected shortly.", "Login Error"); + imc_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." + " You may be disconnected shortly."); if (pos->modname) g_free(pos->modname); g_free(pos); @@ -710,8 +705,8 @@ int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) { if (pos->modname) g_free(pos->modname); g_free(pos); - do_error_dialog(sess->aux_data, "Gaim was unable to get a valid hash for logging into AIM." - " You may be disconnected shortly.", "Login Error"); + imc_error(sess->aux_data, "Gaim was unable to get a valid hash for logging into AIM." + " You may be disconnected shortly."); } pos->fd = fd; @@ -1209,11 +1204,11 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } break; case 0x0007: { /* Someone has denied you authorization */ - serv_got_crap(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); + imc_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); } break; case 0x0008: { /* Someone has granted you authorization */ - serv_got_crap(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); + imc_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); } break; case 0x0012: { @@ -1338,7 +1333,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { userinfo->sn); break; } - do_error_dialog(sess->aux_data, buf, _("Gaim - Error")); + imc_error(sess->aux_data, buf); return 1; } @@ -1346,16 +1341,13 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; guint16 reason; - char *m; va_start(ap, fr); reason = (guint16)va_arg(ap, unsigned int); va_end(ap); - m = g_strdup_printf(_("SNAC threw error: %s\n"), - reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error"); - do_error_dialog(sess->aux_data, m, _("Gaim - Oscar SNAC Error")); - g_free(m); + imc_error(sess->aux_data, _("SNAC threw error: %s"), + reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error"); return 1; } @@ -1364,16 +1356,14 @@ static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; char *destn; guint16 reason; - char buf[1024]; va_start(ap, fr); reason = (guint16)va_arg(ap, unsigned int); destn = va_arg(ap, char *); va_end(ap); - sprintf(buf, _("Your message to %s did not get sent: %s"), destn, + imc_error(sess->aux_data, _("Your message to %s did not get sent: %s"), destn, (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); - do_error_dialog(sess->aux_data, buf, _("Gaim - Error")); return 1; } @@ -1382,17 +1372,14 @@ static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; char *destn; guint16 reason; - char buf[1024]; va_start(ap, fr); reason = (guint16)va_arg(ap, unsigned int); destn = va_arg(ap, char *); va_end(ap); - sprintf(buf, _("User information for %s unavailable: %s"), destn, + imc_error(sess->aux_data, _("User information for %s unavailable: %s"), destn, (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); - do_error_dialog(sess->aux_data, buf, _("Gaim - Error")); - return 1; } @@ -1408,8 +1395,7 @@ static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); if (id < 4) - do_error_dialog(sess->aux_data, _("Your connection may be lost."), - _("AOL error")); + imc_error(sess->aux_data, _("Your connection may be lost.")); return 1; } @@ -1603,8 +1589,8 @@ static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { } else if (code == AIM_RATE_CODE_WARNING) { aim_conn_setlatency(fr->conn, windowsize/4); } else if (code == AIM_RATE_CODE_LIMIT) { - do_error_dialog(sess->aux_data, _("The last message was not sent because you are over the rate limit. " - "Please wait 10 seconds and try again."), _("Gaim - Error")); + imc_error(sess->aux_data, _("The last message was not sent because you are over the rate limit. " + "Please wait 10 seconds and try again.")); aim_conn_setlatency(fr->conn, windowsize/2); } else if (code == AIM_RATE_CODE_CLEARLIMIT) { aim_conn_setlatency(fr->conn, 0); @@ -1808,11 +1794,11 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { } break; case 0x0007: { /* Someone has denied you authorization */ - serv_got_crap(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); + imc_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); } break; case 0x0008: { /* Someone has granted you authorization */ - serv_got_crap(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); + imc_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); } break; case 0x0012: { @@ -1925,7 +1911,7 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } /* else... */ if (od->rights.maxawaymsglen == 0) - do_error_dialog(ic, "oscar_set_away_aim called before locate rights received", "Protocol Error"); + imc_error(ic, "oscar_set_away_aim called before locate rights received"); aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1943,7 +1929,7 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, errstr = g_strdup_printf("Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); - do_error_dialog(ic, errstr, "Away Message Too Long"); + imc_error(ic, errstr); g_free(errstr); } @@ -2109,7 +2095,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { aim_icq_reqofflinemsgs(sess); /* Now that we have a buddy list, we can tell BitlBee that we're online. */ - account_online(ic); + imc_connected(ic); return 1; } @@ -2131,7 +2117,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) if( count & 1 ) { /* Hmm, the length should be even... */ - do_error_dialog( sess->aux_data, "Received SSI ACK package with non-even length", "Gaim - Error" ); + imc_error( sess->aux_data, "Received SSI ACK package with non-even length"); return( 0 ); } count >>= 1; @@ -2142,7 +2128,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) st = aimbs_get16( &fr->data ); if( st == 0x0E ) { - serv_got_crap( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); + imc_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); aim_ssi_auth_request( sess, fr->conn, list, "" ); aim_ssi_addbuddies( sess, fr->conn, OSCAR_GROUP, &list, 1, 1 ); @@ -2329,7 +2315,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) g_string_sprintfa(str, "\n"); } - serv_got_crap(ic, "%s\n%s", _("User Info"), str->str); + imc_log(ic, "%s\n%s", _("User Info"), str->str); g_string_free(str, TRUE); return 1; @@ -2423,18 +2409,18 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) idletime.tm_min = userinfo->idletime % 60; idletime.tm_sec = 0; strftime(buff, 256, _("%d days %H hours %M minutes"), &idletime); - serv_got_crap(ic, "%s: %s", _("Idle Time"), buff); + imc_log(ic, "%s: %s", _("Idle Time"), buff); } if(text) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - serv_got_crap(ic, "%s\n%s", _("User Info"), utf8); + imc_log(ic, "%s\n%s", _("User Info"), utf8); } else { - serv_got_crap(ic, _("No user info available.")); + imc_log(ic, _("No user info available.")); } } else if(infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - serv_got_crap(ic, "%s\n%s", _("Away Message"), utf8); + imc_log(ic, "%s\n%s", _("Away Message"), utf8); } g_free(utf8); diff --git a/protocols/oscar/rxqueue.c b/protocols/oscar/rxqueue.c index 6e8dd29c..b5a83be8 100644 --- a/protocols/oscar/rxqueue.c +++ b/protocols/oscar/rxqueue.c @@ -391,7 +391,7 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) aim_bstream_rewind(&flaphdr); start = aimbs_get8(&flaphdr); - do_error_dialog(sess->aux_data, "FLAP framing disrupted", "Gaim"); + imc_error(sess->aux_data, "FLAP framing disrupted"); aim_conn_close(conn); return -1; } diff --git a/protocols/oscar/search.c b/protocols/oscar/search.c index 9685a3d1..c557e35f 100644 --- a/protocols/oscar/search.c +++ b/protocols/oscar/search.c @@ -38,7 +38,7 @@ static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo /* XXX the modules interface should have already retrieved this for us */ if (!(snac2 = aim_remsnac(sess, snac->id))) { - do_error_dialog(sess->aux_data, "couldn't get snac", "Gaim"); + imc_error(sess->aux_data, "couldn't get snac"); return 0; } diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index 2a3dd1fb..69d53d00 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -566,7 +566,7 @@ static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_ group = aimbs_get16(bs); - do_error_dialog(sess->aux_data, "bifurcated migration unsupported", "Gaim"); + imc_error(sess->aux_data, "bifurcated migration unsupported"); } tl = aim_readtlvchain(bs); @@ -893,7 +893,7 @@ int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guin aimbs_put32(&fr->data, 0xecf8427e); */ } else - do_error_dialog(sess->aux_data, "WARNING: unknown hash request", "Gaim"); + imc_error(sess->aux_data, "WARNING: unknown hash request"); } diff --git a/protocols/oscar/txqueue.c b/protocols/oscar/txqueue.c index 6b4854c5..bd8db49d 100644 --- a/protocols/oscar/txqueue.c +++ b/protocols/oscar/txqueue.c @@ -29,7 +29,7 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g aim_frame_t *fr; if (!conn) { - do_error_dialog(sess->aux_data, "no connection specified", "Gaim"); + imc_error(sess->aux_data, "no connection specified"); return NULL; } @@ -45,7 +45,7 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g fr->hdr.flap.type = chan; } else - do_error_dialog(sess->aux_data, "unknown framing", "Gaim"); + imc_error(sess->aux_data, "unknown framing"); if (datalen > 0) { guint8 *data; @@ -79,7 +79,7 @@ static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr) { if (!fr->conn) { - do_error_dialog(sess->aux_data, "WARNING: enqueueing packet with no connection", "Gaim"); + imc_error(sess->aux_data, "WARNING: enqueueing packet with no connection"); fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); } @@ -119,7 +119,7 @@ static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr) { if (!fr->conn) { - do_error_dialog(sess->aux_data, "packet has no connection", "Gaim"); + imc_error(sess->aux_data, "packet has no connection"); aim_frame_destroy(fr); return 0; } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 52db9007..424a0ad1 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -122,13 +122,13 @@ static char *byahoo_strip( char *in ) static void byahoo_login( account_t *acc ) { - struct im_connection *ic = new_gaim_conn( acc ); + struct im_connection *ic = imc_new( acc ); struct byahoo_data *yd = ic->proto_data = g_new0( struct byahoo_data, 1 ); yd->logged_in = FALSE; yd->current_status = YAHOO_STATUS_AVAILABLE; - set_login_progress( ic, 1, "Connecting" ); + imc_log( ic, "Connecting" ); yd->y2_id = yahoo_init( acc->user, acc->pass ); yahoo_login( yd->y2_id, yd->current_status ); } @@ -162,7 +162,7 @@ static void byahoo_logout( struct im_connection *ic ) static void byahoo_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - serv_got_crap(ic, "%s\n%s: %s%s", _("User Info"), + imc_log(ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), yahoo_get_profile_url(), who); } @@ -510,7 +510,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) if( succ == YAHOO_LOGIN_OK ) { - account_online( ic ); + imc_connected( ic ); yd->logged_in = TRUE; } @@ -549,13 +549,13 @@ void ext_yahoo_login_response( int id, int succ, char *url ) } if( yd->logged_in ) - hide_login_progress_error( ic, s ); + imc_error( ic, s ); else - hide_login_progress( ic, s ); + imc_error( ic, s ); g_free( s ); - signoff( ic ); + imc_logout( ic ); } } @@ -618,7 +618,7 @@ void ext_yahoo_got_file( int id, char *who, char *url, long expires, char *msg, { struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); + imc_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); } void ext_yahoo_typing_notify( int id, char *who, int stat ) @@ -638,29 +638,24 @@ void ext_yahoo_system_message( int id, char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( ic, "Yahoo! system message: %s", msg ); + imc_log( ic, "Yahoo! system message: %s", msg ); } void ext_yahoo_webcam_invite( int id, char *from ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); + imc_log( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); } void ext_yahoo_error( int id, char *err, int fatal ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); + imc_error( ic, "%s", err ); + if( fatal ) - { - hide_login_progress_error( ic, err ); - signoff( ic ); - } - else - { - do_error_dialog( ic, err, "Yahoo! error" ); - } + imc_logout( ic ); } /* TODO: Clear up the mess of inp and d structures */ @@ -828,7 +823,7 @@ void ext_yahoo_conf_userdecline( int id, char *who, char *room, char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - serv_got_crap( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); + imc_log( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); } void ext_yahoo_conf_userjoin( int id, char *who, char *room ) @@ -911,9 +906,9 @@ void ext_yahoo_mail_notify( int id, char *from, char *subj, int cnt ) struct im_connection *ic = byahoo_get_ic_by_id( id ); if( from && subj ) - serv_got_crap( ic, "Received e-mail message from %s with subject `%s'", from, subj ); + imc_log( ic, "Received e-mail message from %s with subject `%s'", from, subj ); else if( cnt > 0 ) - serv_got_crap( ic, "Received %d new e-mails", cnt ); + imc_log( ic, "Received %d new e-mails", cnt ); } void ext_yahoo_webcam_invite_reply( int id, char *from, int accept ) diff --git a/query.c b/query.c index c95ff4e1..e7a55afd 100644 --- a/query.c +++ b/query.c @@ -121,7 +121,7 @@ void query_del_by_conn( irc_t *irc, struct im_connection *ic ) } if( count > 0 ) - serv_got_crap( ic, "Flushed %d unanswered question(s) for this connection.", count ); + imc_log( ic, "Flushed %d unanswered question(s) for this connection.", count ); q = query_default( irc ); if( q && q != def ) @@ -139,12 +139,12 @@ void query_answer( irc_t *irc, query_t *q, int ans ) } if( ans ) { - serv_got_crap( q->ic, "Accepted: %s", q->question ); + imc_log( q->ic, "Accepted: %s", q->question ); q->yes( NULL, q->data ); } else { - serv_got_crap( q->ic, "Rejected: %s", q->question ); + imc_log( q->ic, "Rejected: %s", q->question ); q->no( NULL, q->data ); } q->data = NULL; @@ -159,7 +159,7 @@ static void query_display( irc_t *irc, query_t *q ) { if( q->ic ) { - serv_got_crap( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); + imc_log( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); } else { -- cgit v1.2.3 From 552e641194147078c7858059df9916d5d548b7a1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 5 Apr 2007 22:34:23 -0700 Subject: Now that all these functions take format strings, I have to make sure I use that and don't introduce vulnerabilities. :-) --- protocols/jabber/io.c | 4 +--- protocols/msn/ns.c | 10 ++-------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 699c7019..bf52fb4e 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -466,9 +466,7 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) } else { - s = g_strdup_printf( "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); - imc_error( ic, s ); - g_free( s ); + imc_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); } imc_logout( ic ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index e4530b8f..81ad1941 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -670,15 +670,9 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) if( key == NULL ) { - char *err; - - err = g_strdup_printf( "Error during Passport authentication (%s)", - rep->error_string ? rep->error_string : "Unknown error" ); - - imc_error( ic, err ); + imc_error( ic, "Error during Passport authentication (%s)", + rep->error_string ? rep->error_string : "Unknown error" ); imc_logout( ic ); - - g_free( err ); } else { -- cgit v1.2.3 From cd4723c257f9f7bd8d4a46c6562f93c2aefc3dbb Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 14:59:52 -0700 Subject: More format string problems. --- protocols/jabber/iq.c | 2 +- protocols/oscar/oscar.c | 28 +++++++--------------------- protocols/yahoo/yahoo.c | 18 ++---------------- 3 files changed, 10 insertions(+), 38 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e1848272..86dca30a 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -535,7 +535,7 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no /* *sigh* */ - imc_log( ic, reply->str ); + imc_log( ic, "%s", reply->str ); g_string_free( reply, TRUE ); return XT_HANDLED; diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 929b63d3..abc2f4be 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1263,7 +1263,6 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; guint16 chan, nummissed, reason; aim_userinfo_t *userinfo; - char buf[1024]; va_start(ap, fr); chan = (guint16)va_arg(ap, unsigned int); @@ -1275,8 +1274,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { switch(reason) { case 0: /* Invalid (0) */ - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was invalid.") : _("You missed %d messages from %s because they were invalid."), @@ -1285,8 +1283,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 1: /* Message too large */ - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was too large.") : _("You missed %d messages from %s because they were too large."), @@ -1295,8 +1292,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 2: /* Rate exceeded */ - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because the rate limit has been exceeded.") : _("You missed %d messages from %s because the rate limit has been exceeded."), @@ -1305,8 +1301,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 3: /* Evil Sender */ - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was too evil.") : _("You missed %d messages from %s because they are too evil."), @@ -1315,8 +1310,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 4: /* Evil Receiver */ - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because you are too evil.") : _("You missed %d messages from %s because you are too evil."), @@ -1324,8 +1318,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { userinfo->sn); break; default: - g_snprintf(buf, - sizeof(buf), + imc_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s for unknown reasons.") : _("You missed %d messages from %s for unknown reasons."), @@ -1333,7 +1326,6 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { userinfo->sn); break; } - imc_error(sess->aux_data, buf); return 1; } @@ -1925,13 +1917,7 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } if (strlen(message) > od->rights.maxawaymsglen) { - gchar *errstr; - - errstr = g_strdup_printf("Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); - - imc_error(ic, errstr); - - g_free(errstr); + imc_error(ic, "Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); } ic->away = g_strndup(message, od->rights.maxawaymsglen); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 424a0ad1..c10c3103 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -517,7 +517,6 @@ void ext_yahoo_login_response( int id, int succ, char *url ) else { char *errstr; - char *s; yd->logged_in = FALSE; @@ -538,22 +537,9 @@ void ext_yahoo_login_response( int id, int succ, char *url ) errstr = "Unknown error"; if( url && *url ) - { - s = g_malloc( strlen( "Error %d (%s). See %s for more information." ) + strlen( url ) + strlen( errstr ) + 16 ); - sprintf( s, "Error %d (%s). See %s for more information.", succ, errstr, url ); - } + imc_error( ic, "Error %d (%s). See %s for more information.", succ, errstr, url ); else - { - s = g_malloc( strlen( "Error %d (%s)" ) + strlen( errstr ) + 16 ); - sprintf( s, "Error %d (%s)", succ, errstr ); - } - - if( yd->logged_in ) - imc_error( ic, s ); - else - imc_error( ic, s ); - - g_free( s ); + imc_error( ic, "Error %d (%s)", succ, errstr ); imc_logout( ic ); } -- cgit v1.2.3 From c2fb38096ea4e75a680e57e103d4a4986aa84c75 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 15:39:35 -0700 Subject: Cleaned up struct im_connection. No more username/password stuff since it's in acc too. wants_to_die is now an argument to imc_logout(). --- account.c | 3 +-- irc.c | 5 ++-- protocols/jabber/io.c | 27 +++++++++++---------- protocols/jabber/iq.c | 10 ++++---- protocols/jabber/jabber.c | 6 ++--- protocols/jabber/sasl.c | 12 +++++---- protocols/msn/msn.c | 6 ++--- protocols/msn/msn_util.c | 2 +- protocols/msn/ns.c | 62 ++++++++++++++++++++++++----------------------- protocols/msn/sb.c | 16 ++++++------ protocols/nogaim.c | 22 +++++------------ protocols/nogaim.h | 6 +---- protocols/oscar/oscar.c | 33 +++++++++++++------------ protocols/yahoo/yahoo.c | 16 ++++++------ root_commands.c | 2 +- 15 files changed, 109 insertions(+), 119 deletions(-) diff --git a/account.c b/account.c index 9245a6e9..1b0d7f26 100644 --- a/account.c +++ b/account.c @@ -222,8 +222,7 @@ void account_on( irc_t *irc, account_t *a ) void account_off( irc_t *irc, account_t *a ) { - a->ic->wants_to_die = TRUE; - imc_logout( a->ic ); + imc_logout( a->ic, TRUE ); a->ic = NULL; if( a->reconnect ) { diff --git a/irc.c b/irc.c index a78a0153..08ffa753 100644 --- a/irc.c +++ b/irc.c @@ -230,8 +230,7 @@ void irc_free(irc_t * irc) for (account = irc->accounts; account; account = account->next) { if (account->ic) { - account->ic->wants_to_die = TRUE; - imc_logout(account->ic); + imc_logout(account->ic, TRUE); } else if (account->reconnect) { cancel_auto_reconnect(account); } @@ -915,7 +914,7 @@ void irc_kill( irc_t *irc, user_t *u ) if( u->ic->acc->server ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, u->ic->acc->server ); - else if( ( s = strchr( u->ic->username, '@' ) ) ) + else if( ( s = strchr( u->ic->acc->user, '@' ) ) ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, s + 1 ); else diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index bf52fb4e..c64901f7 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -117,7 +117,7 @@ static gboolean jabber_write_queue( struct im_connection *ic ) jd->fd = -1; imc_error( ic, "Short write() to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } else if( st > 0 ) @@ -160,7 +160,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition if( xt_feed( jd->xt, buf, st ) < 0 ) { imc_error( ic, "XML stream error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -204,7 +204,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition { imc_error( ic, "TLS is turned on for this " "account, but is not supported by this server" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return FALSE; } else @@ -216,7 +216,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition else { imc_error( ic, "XML stream error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } } @@ -227,7 +227,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition jd->fd = -1; imc_error( ic, "Error while reading from server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -242,7 +242,7 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c if( source == -1 ) { imc_error( ic, "Could not connect to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -263,7 +263,7 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co jd->ssl = NULL; imc_error( ic, "Could not connect to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -274,7 +274,7 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) { - imc_logout( data ); + imc_logout( data, TRUE ); return XT_ABORT; } @@ -297,7 +297,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) ) { imc_error( ic, "Server requires TLS connections, but TLS is turned off for this account" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -327,7 +327,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( !trytls && set_getbool( &ic->acc->set, "tls" ) ) { imc_error( ic, "TLS is turned on for this account, but is not supported by this server" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -428,6 +428,7 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) struct im_connection *ic = data; struct xt_node *c; char *s, *type = NULL, *text = NULL; + int allow_reconnect = TRUE; for( c = node->children; c; c = c->next ) { @@ -452,7 +453,7 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) if( type == NULL ) { imc_error( ic, "Unknown stream error reported by server" ); - imc_logout( ic ); + imc_logout( ic, allow_reconnect ); return XT_ABORT; } @@ -462,14 +463,14 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) if( strcmp( type, "conflict" ) == 0 ) { imc_error( ic, "Account and resource used from a different location" ); - ic->wants_to_die = TRUE; + allow_reconnect = FALSE; } else { imc_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); } - imc_logout( ic ); + imc_logout( ic, allow_reconnect ); return XT_ABORT; } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 86dca30a..fc6f223d 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -39,7 +39,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !type ) { imc_error( ic, "Received IQ packet without type." ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return XT_ABORT; } @@ -219,7 +219,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no if( !( query = xt_find_node( node->children, "query" ) ) ) { imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -258,7 +258,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no xt_free_node( reply ); imc_error( ic, "Can't find suitable authentication method" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -277,14 +277,14 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node if( !( type = xt_find_attr( node, "type" ) ) ) { imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_HANDLED; } if( strcmp( type, "error" ) == 0 ) { imc_error( ic, "Authentication failure" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } else if( strcmp( type, "result" ) == 0 ) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index ec0df487..af294d90 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -72,7 +72,7 @@ static void jabber_login( account_t *acc ) if( jd->server == NULL ) { imc_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return; } @@ -165,7 +165,7 @@ static void jabber_login( account_t *acc ) { imc_log( ic, "Incorrect port number, must be in the %d-%d range", JABBER_PORT_MIN, JABBER_PORT_MAX ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return; } @@ -186,7 +186,7 @@ static void jabber_login( account_t *acc ) if( jd->fd == -1 ) { imc_error( ic, "Could not connect to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); } } diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index ab6f6c00..cbd40fb1 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -44,7 +44,8 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - imc_logout( ic ); + imc_log( ic, "Stream error while authenticating" ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -62,7 +63,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) if( !sup_plain && !sup_digest ) { imc_error( ic, "No known SASL authentication schemes supported" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -279,7 +280,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) error: imc_error( ic, "Incorrect SASL challenge received" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); silent_error: g_free( digest_uri ); @@ -302,7 +303,8 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - imc_logout( ic ); + imc_log( ic, "Stream error while authenticating" ); + imc_logout( ic, FALSE ); return XT_ABORT; } @@ -314,7 +316,7 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) else if( strcmp( node->name, "failure" ) == 0 ) { imc_error( ic, "Authentication failure" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return XT_ABORT; } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 860be01b..74a41322 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -47,7 +47,7 @@ static void msn_login( account_t *acc ) if( strchr( acc->user, '@' ) == NULL ) { imc_error( ic, "Invalid account name" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return; } @@ -57,7 +57,7 @@ static void msn_login( account_t *acc ) if( md->fd < 0 ) { imc_error( ic, "Could not connect to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return; } @@ -378,7 +378,7 @@ static char *msn_set_display_name( set_t *set, char *value ) fn = msn_http_encode( value ); - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->username, fn ); + g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); msn_write( ic, buf, strlen( buf ) ); g_free( fn ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 72411095..67e17b08 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -36,7 +36,7 @@ int msn_write( struct im_connection *ic, char *s, int len ) if( st != len ) { imc_error( ic, "Short write() to main server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 81ad1941..77bb4939 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -47,7 +47,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) if( source == -1 ) { imc_error( ic, "Could not connect to server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -89,7 +89,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ { imc_error( ic, "Error while reading from server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return FALSE; } @@ -114,18 +114,18 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) { imc_error( ic, "Unsupported protocol" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return( 0 ); } g_snprintf( buf, sizeof( buf ), "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", - ++md->trId, ic->username ); + ++md->trId, ic->acc->user ); return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "CVR" ) == 0 ) { /* We don't give a damn about the information we just received */ - g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->username ); + g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->acc->user ); return( msn_write( ic, buf, strlen( buf ) ) ); } else if( strcmp( cmd[0], "XFR" ) == 0 ) @@ -143,7 +143,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( !server ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } *server = 0; @@ -162,7 +162,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( !server ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } *server = 0; @@ -172,7 +172,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[4], "CKI" ) != 0 ) { imc_error( ic, "Unknown authentication method for switchboard" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -204,7 +204,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } } @@ -213,10 +213,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* Time for some Passport black magic... */ - if( !passport_get_id( msn_auth_got_passport_id, ic, ic->username, ic->password, cmd[4] ) ) + if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) { imc_error( ic, "Error while contacting Passport server" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } } @@ -243,7 +243,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) else { imc_error( ic, "Unknown authentication type" ); - imc_logout( ic ); + imc_logout( ic, FALSE ); return( 0 ); } } @@ -252,7 +252,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -261,7 +261,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->handler->msglen <= 0 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } } @@ -292,7 +292,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 && num_parts != 5 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -344,7 +344,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -363,7 +363,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 3 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -385,7 +385,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 6 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -413,7 +413,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 5 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -438,7 +438,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 7 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -448,7 +448,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( !server ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } *server = 0; @@ -458,7 +458,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[3], "CKI" ) != 0 ) { imc_error( ic, "Unknown authentication method for switchboard" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -478,7 +478,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strchr( cmd[4], '@' ) == NULL ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } @@ -496,10 +496,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "OUT" ) == 0 ) { + int allow_reconnect = TRUE; + if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) { imc_error( ic, "Someone else logged in with your account" ); - ic->wants_to_die = 1; + allow_reconnect = FALSE; } else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) { @@ -510,7 +512,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imc_error( ic, "Session terminated by remote server (reason unknown)" ); } - imc_logout( ic ); + imc_logout( ic, allow_reconnect ); return( 0 ); } else if( strcmp( cmd[0], "REA" ) == 0 ) @@ -518,11 +520,11 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 5 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } - if( g_strcasecmp( cmd[3], ic->username ) == 0 ) + if( g_strcasecmp( cmd[3], ic->acc->user ) == 0 ) { set_t *s; @@ -552,7 +554,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->handler->msglen <= 0 ) { imc_error( ic, "Syntax error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } } @@ -565,7 +567,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( err->flags & STATUS_FATAL ) { - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } } @@ -672,7 +674,7 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) { imc_error( ic, "Error during Passport authentication (%s)", rep->error_string ? rep->error_string : "Unknown error" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); } else { diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index f7007d32..f8413856 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -141,9 +141,9 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) } else { - i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->username ); + i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user ); buf = g_new0( char, i ); - i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->username ); + i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user ); } /* Build the final packet (MSG command + the message). */ @@ -187,7 +187,7 @@ struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ) /* Populate the channel. */ if( sb->who ) add_chat_buddy( sb->chat, sb->who ); - add_chat_buddy( sb->chat, ic->username ); + add_chat_buddy( sb->chat, ic->acc->user ); /* And make sure the switchboard doesn't look like a regular chat anymore. */ if( sb->who ) @@ -279,9 +279,9 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) sb->handler->exec_message = msn_sb_message; if( sb->session == MSN_SB_NEW ) - g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->username, sb->key ); + g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->acc->user, sb->key ); else - g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->username, sb->key, sb->session ); + g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); if( msn_sb_write( sb, buf, strlen( buf ) ) ) sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); @@ -321,7 +321,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "XFR" ) == 0 ) { imc_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); - imc_logout( ic ); + imc_logout( ic, TRUE ); return( 0 ); } else if( strcmp( cmd[0], "USR" ) == 0 ) @@ -383,7 +383,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( num == tot ) { - add_chat_buddy( sb->chat, ic->username ); + add_chat_buddy( sb->chat, ic->acc->user ); } } } @@ -536,7 +536,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( err->flags & STATUS_FATAL ) { - imc_logout( ic ); + imc_logout( ic, TRUE ); return 0; } else if( err->flags & STATUS_SB_IM_SPARE ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 0c042bac..273cc6c8 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -150,10 +150,6 @@ struct im_connection *imc_new( account_t *acc ) ic = g_new0( struct im_connection, 1 ); - /* Maybe we should get rid of this memory waste later. ;-) */ - g_snprintf( ic->username, sizeof( ic->username ), "%s", acc->user ); - g_snprintf( ic->password, sizeof( ic->password ), "%s", acc->pass ); - ic->irc = acc->irc; ic->acc = acc; acc->ic = ic; @@ -200,7 +196,7 @@ static void serv_got_crap( struct im_connection *ic, char *format, ... ) /* If we found one, include the screenname in the message. */ if( a ) - irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->username, text ); + irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text ); else irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text ); @@ -290,7 +286,7 @@ void cancel_auto_reconnect( account_t *a ) a->reconnect = 0; } -void imc_logout( struct im_connection *ic ) +void imc_logout( struct im_connection *ic, int allow_reconnect ) { irc_t *irc = ic->irc; user_t *t, *u = irc->users; @@ -332,7 +328,7 @@ void imc_logout( struct im_connection *ic ) { /* Uhm... This is very sick. */ } - else if( !ic->wants_to_die && set_getbool( &irc->set, "auto_reconnect" ) && + else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) && set_getbool( &a->set, "auto_reconnect" ) ) { int delay = set_getint( &irc->set, "auto_reconnect_delay" ); @@ -437,11 +433,6 @@ struct buddy *find_buddy( struct im_connection *ic, char *handle ) return( b ); } -void signoff_blocked( struct im_connection *ic ) -{ - return; /* Make all blocked users look invisible (TODO?) */ -} - void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ) { @@ -729,7 +720,7 @@ void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, t user_t *u; /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ - if( g_strcasecmp( who, ic->username ) == 0 ) + if( g_strcasecmp( who, ic->acc->user ) == 0 ) return; u = user_findhandle( ic, who ); @@ -780,7 +771,7 @@ void add_chat_buddy( struct groupchat *b, char *handle ) imc_log( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); /* It might be yourself! */ - if( b->ic->acc->prpl->handle_cmp( handle, b->ic->username ) == 0 ) + if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 ) { u = user_find( b->ic->irc, b->ic->irc->nick ); if( !b->joined ) @@ -814,7 +805,7 @@ void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ) imc_log( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); /* It might be yourself! */ - if( g_strcasecmp( handle, b->ic->username ) == 0 ) + if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) { u = user_find( b->ic->irc, b->ic->irc->nick ); b->joined = 0; @@ -957,7 +948,6 @@ int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags int bim_chat_msg( struct groupchat *c, char *msg, int flags ) { char *buf = NULL; - int st; if( ( c->ic->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 53e3b23b..08df1750 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -79,14 +79,10 @@ struct im_connection GSList *deny; int permdeny; - char username[64]; char displayname[128]; - char password[32]; - char *away; int evil; - gboolean wants_to_die; /* defaults to FALSE */ /* BitlBee */ irc_t *irc; @@ -210,7 +206,7 @@ G_MODULE_EXPORT void imc_free( struct im_connection *ic ); G_MODULE_EXPORT void imc_log( struct im_connection *ic, char *format, ... ); G_MODULE_EXPORT void imc_error( struct im_connection *ic, char *format, ... ); G_MODULE_EXPORT void imc_connected( struct im_connection *ic ); -G_MODULE_EXPORT void imc_logout( struct im_connection *ic ); +G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect ); /* dialogs.c */ G_MODULE_EXPORT void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index abc2f4be..d95c7068 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -262,12 +262,12 @@ static gboolean oscar_callback(gpointer data, gint source, if (aim_get_command(odata->sess, conn) >= 0) { aim_rxdispatch(odata->sess); if (odata->killme) - imc_logout(ic); + imc_logout(ic, TRUE); } else { if ((conn->type == AIM_CONN_TYPE_BOS) || !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { imc_error(ic, _("Disconnected.")); - imc_logout(ic); + imc_logout(ic, TRUE); } else if (conn->type == AIM_CONN_TYPE_CHAT) { struct chat_connection *c = find_oscar_chat_by_conn(ic, conn); c->conn = NULL; @@ -325,7 +325,7 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio if (source < 0) { imc_error(ic, _("Couldn't connect to host")); - imc_logout(ic); + imc_logout(ic, TRUE); return FALSE; } @@ -360,7 +360,9 @@ static void oscar_login(account_t *acc) { /* This is odd but it's necessary for a proper do_import and do_export. We don't do those anymore, but let's stick with it, just in case it accidentally fixes something else too... </bitlbee> */ - ic->password[8] = 0; + /* ic->acc->pass[8] = 0; + Not touching this anymore now that it belongs to account_t! + Let's hope nothing will break. ;-) */ } else { ic->flags |= OPT_CONN_HTML; } @@ -378,13 +380,13 @@ static void oscar_login(account_t *acc) { conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (conn == NULL) { imc_error(ic, _("Unable to login to AIM")); - imc_logout(ic); + imc_logout(ic, TRUE); return; } if (acc->server == NULL) { imc_error(ic, "No servername specified"); - imc_logout(ic); + imc_logout(ic, FALSE); return; } @@ -393,7 +395,7 @@ static void oscar_login(account_t *acc) { imc_log(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); } - imc_log(ic, _("Signon: %s"), ic->username); + imc_log(ic, _("Signon: %s"), ic->acc->user); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); @@ -402,10 +404,10 @@ static void oscar_login(account_t *acc) { conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, ic); if (conn->fd < 0) { imc_error(ic, _("Couldn't connect to host")); - imc_logout(ic); + imc_logout(ic, TRUE); return; } - aim_request_login(sess, conn, ic->username); + aim_request_login(sess, conn, ic->acc->user); } static void oscar_logout(struct im_connection *ic) { @@ -462,7 +464,7 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition if (source < 0) { imc_error(ic, _("Could Not Connect")); - imc_logout(ic); + imc_logout(ic, TRUE); return FALSE; } @@ -727,7 +729,7 @@ static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) { key = va_arg(ap, char *); va_end(ap); - aim_send_login(sess, fr->conn, ic->username, ic->password, &info, key); + aim_send_login(sess, fr->conn, ic->acc->user, ic->acc->pass, &info, key); return 1; } @@ -1012,7 +1014,7 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) signon = time(NULL) - info->sessionlen; - tmp = g_strdup(normalize(ic->username)); + tmp = g_strdup(normalize(ic->acc->user)); if (!strcmp(tmp, normalize(info->sn))) g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); g_free(tmp); @@ -2135,10 +2137,10 @@ static void oscar_set_permit_deny(struct im_connection *ic) { switch(ic->permdeny) { case 1: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, ic->username); + aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, ic->acc->user); break; case 2: - aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, ic->username); + aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, ic->acc->user); break; case 3: list = ic->permit; @@ -2161,7 +2163,6 @@ static void oscar_set_permit_deny(struct im_connection *ic) { default: break; } - signoff_blocked(ic); } else { if (od->sess->ssi.received_data) aim_ssi_setpermdeny(od->sess, od->conn, ic->permdeny, 0xffffffff); @@ -2583,7 +2584,7 @@ struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) static int chat_id = 0; char * chatname; - chatname = g_strdup_printf("%s%d", ic->username, chat_id++); + chatname = g_strdup_printf("%s%d", ic->acc->user, chat_id++); ret = oscar_chat_join(ic, chatname); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index c10c3103..ae66b209 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -360,11 +360,10 @@ static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) char *roomname; YList *members; - roomname = g_new0( char, strlen( ic->username ) + 16 ); - g_snprintf( roomname, strlen( ic->username ) + 16, "%s-Bee-%d", ic->username, byahoo_chat_id ); + roomname = g_strdup_printf( "%s-Bee-%d", ic->acc->user, byahoo_chat_id ); c = serv_got_joined_chat( ic, roomname ); - add_chat_buddy( c, ic->username ); + add_chat_buddy( c, ic->acc->user ); /* FIXME: Free this thing when the chat's destroyed. We can't *always* do this because it's not always created here. */ @@ -517,6 +516,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) else { char *errstr; + int allow_reconnect = TRUE; yd->logged_in = FALSE; @@ -529,7 +529,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) else if( succ == YAHOO_LOGIN_DUPL ) { errstr = "Logged in on a different machine or device"; - ic->wants_to_die = TRUE; + allow_reconnect = FALSE; } else if( succ == YAHOO_LOGIN_SOCK ) errstr = "Socket problem"; @@ -541,7 +541,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) else imc_error( ic, "Error %d (%s)", succ, errstr ); - imc_logout( ic ); + imc_logout( ic, allow_reconnect ); } } @@ -641,7 +641,7 @@ void ext_yahoo_error( int id, char *err, int fatal ) imc_error( ic, "%s", err ); if( fatal ) - imc_logout( ic ); + imc_logout( ic, TRUE ); } /* TODO: Clear up the mess of inp and d structures */ @@ -767,7 +767,7 @@ int ext_yahoo_connect(char *host, int port) static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); - add_chat_buddy( inv->c, inv->ic->username ); + add_chat_buddy( inv->c, inv->ic->acc->user ); g_free( inv->name ); g_free( inv ); } @@ -797,7 +797,7 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList inv->ic = ic; for( m = members; m; m = m->next ) - if( g_strcasecmp( m->data, ic->username ) != 0 ) + if( g_strcasecmp( m->data, ic->acc->user ) != 0 ) add_chat_buddy( inv->c, m->data ); g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg ); diff --git a/root_commands.c b/root_commands.c index ee6df91d..0b3d6844 100644 --- a/root_commands.c +++ b/root_commands.c @@ -879,7 +879,7 @@ static void cmd_qlist( irc_t *irc, char **cmd ) for( num = 0; q; q = q->next, num ++ ) if( q->ic ) /* Not necessary yet, but it might come later */ - irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->username, q->question ); + irc_usermsg( irc, "%d, %s(%s): %s", num, q->ic->acc->prpl->name, q->ic->acc->user, q->question ); else irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } -- cgit v1.2.3 From 84b045d409f1e8da6d8bf379c6fef7236dcd9bcd Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 18:03:08 -0700 Subject: s/imc/imcb/ for callback functions. Moved things aroundin nogaim.h a little bit, grouping things by category instead of original Gaim 0.58 filename. --- Makefile | 2 +- irc.c | 6 +-- irc_commands.c | 2 +- protocols/jabber/io.c | 30 ++++++------- protocols/jabber/iq.c | 30 ++++++------- protocols/jabber/jabber.c | 12 ++--- protocols/jabber/jabber_util.c | 4 +- protocols/jabber/presence.c | 6 +-- protocols/jabber/sasl.c | 14 +++--- protocols/msn/msn.c | 14 +++--- protocols/msn/msn_util.c | 8 ++-- protocols/msn/ns.c | 70 ++++++++++++++--------------- protocols/msn/sb.c | 6 +-- protocols/nogaim.c | 91 +++++++++++++++++-------------------- protocols/nogaim.h | 86 ++++++++++++++++------------------- protocols/oscar/chat.c | 6 +-- protocols/oscar/chatnav.c | 10 ++--- protocols/oscar/icq.c | 2 +- protocols/oscar/im.c | 8 ++-- protocols/oscar/info.c | 6 +-- protocols/oscar/oscar.c | 100 ++++++++++++++++++++--------------------- protocols/oscar/rxqueue.c | 2 +- protocols/oscar/search.c | 2 +- protocols/oscar/service.c | 4 +- protocols/oscar/txqueue.c | 8 ++-- protocols/yahoo/yahoo.c | 28 ++++++------ query.c | 8 ++-- root_commands.c | 8 ++-- 28 files changed, 277 insertions(+), 296 deletions(-) diff --git a/Makefile b/Makefile index 27d420a8..811e96be 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ # Program variables objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h -subdirs = protocols lib +subdirs = lib protocols # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) diff --git a/irc.c b/irc.c index 08ffa753..7181e660 100644 --- a/irc.c +++ b/irc.c @@ -1036,7 +1036,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) } else if( c && c->ic && c->ic->acc && c->ic->acc->prpl ) { - return( bim_chat_msg( c, s, 0 ) ); + return( imc_chat_msg( c, s, 0 ) ); } return( 0 ); @@ -1051,7 +1051,7 @@ static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_cond return FALSE; u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */ - bim_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); + imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags ); g_free( u->sendbuf ); u->sendbuf = NULL; @@ -1103,7 +1103,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ) } else { - bim_buddy_msg( u->ic, u->handle, msg, flags ); + imc_buddy_msg( u->ic, u->handle, msg, flags ); } } diff --git a/irc_commands.c b/irc_commands.c index d65cf720..016b6f84 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -462,7 +462,7 @@ static void irc_cmd_away( irc_t *irc, char **cmd ) struct im_connection *ic = a->ic; if( ic && ic->flags & OPT_LOGGED_IN ) - bim_set_away( ic, u->away ); + imc_set_away( ic, u->away ); } } diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index c64901f7..67deb3a6 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -116,7 +116,7 @@ static gboolean jabber_write_queue( struct im_connection *ic ) closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ jd->fd = -1; - imc_error( ic, "Short write() to server" ); + imcb_error( ic, "Short write() to server" ); imc_logout( ic, TRUE ); return FALSE; } @@ -159,7 +159,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition /* Parse. */ if( xt_feed( jd->xt, buf, st ) < 0 ) { - imc_error( ic, "XML stream error" ); + imcb_error( ic, "XML stream error" ); imc_logout( ic, TRUE ); return FALSE; } @@ -202,7 +202,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition SASL and TLS. */ if( set_getbool( &ic->acc->set, "tls" ) ) { - imc_error( ic, "TLS is turned on for this " + imcb_error( ic, "TLS is turned on for this " "account, but is not supported by this server" ); imc_logout( ic, FALSE ); return FALSE; @@ -215,7 +215,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } else { - imc_error( ic, "XML stream error" ); + imcb_error( ic, "XML stream error" ); imc_logout( ic, TRUE ); return FALSE; } @@ -226,7 +226,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition closesocket( jd->fd ); jd->fd = -1; - imc_error( ic, "Error while reading from server" ); + imcb_error( ic, "Error while reading from server" ); imc_logout( ic, TRUE ); return FALSE; } @@ -241,12 +241,12 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c if( source == -1 ) { - imc_error( ic, "Could not connect to server" ); + imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } - imc_log( ic, "Connected to server, logging in" ); + imcb_log( ic, "Connected to server, logging in" ); return jabber_start_stream( ic ); } @@ -262,12 +262,12 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co already, set it to NULL here to prevent a double cleanup: */ jd->ssl = NULL; - imc_error( ic, "Could not connect to server" ); + imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } - imc_log( ic, "Connected to server, logging in" ); + imcb_log( ic, "Connected to server, logging in" ); return jabber_start_stream( ic ); } @@ -296,7 +296,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) ) { - imc_error( ic, "Server requires TLS connections, but TLS is turned off for this account" ); + imcb_error( ic, "Server requires TLS connections, but TLS is turned off for this account" ); imc_logout( ic, FALSE ); return XT_ABORT; @@ -326,7 +326,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) if( !trytls && set_getbool( &ic->acc->set, "tls" ) ) { - imc_error( ic, "TLS is turned on for this account, but is not supported by this server" ); + imcb_error( ic, "TLS is turned on for this account, but is not supported by this server" ); imc_logout( ic, FALSE ); return XT_ABORT; @@ -416,7 +416,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) } jd->w_inpa = jd->r_inpa = 0; - imc_log( ic, "Converting stream to TLS" ); + imcb_log( ic, "Converting stream to TLS" ); jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic ); @@ -452,7 +452,7 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) /* Tssk... */ if( type == NULL ) { - imc_error( ic, "Unknown stream error reported by server" ); + imcb_error( ic, "Unknown stream error reported by server" ); imc_logout( ic, allow_reconnect ); return XT_ABORT; } @@ -462,12 +462,12 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) infinite loop! */ if( strcmp( type, "conflict" ) == 0 ) { - imc_error( ic, "Account and resource used from a different location" ); + imcb_error( ic, "Account and resource used from a different location" ); allow_reconnect = FALSE; } else { - imc_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); + imcb_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); } imc_logout( ic, allow_reconnect ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index fc6f223d..53be819e 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -38,7 +38,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !type ) { - imc_error( ic, "Received IQ packet without type." ); + imcb_error( ic, "Received IQ packet without type." ); imc_logout( ic, TRUE ); return XT_ABORT; } @@ -59,7 +59,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) entry = g_hash_table_lookup( jd->node_cache, s ); if( entry == NULL ) - imc_log( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); + imcb_log( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); else if( entry->func ) return entry->func( ic, node, entry->node ); } @@ -68,7 +68,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - imc_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -131,7 +131,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - imc_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -153,7 +153,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else { - imc_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); + imcb_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -218,7 +218,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no if( !( query = xt_find_node( node->children, "query" ) ) ) { - imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -257,7 +257,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no { xt_free_node( reply ); - imc_error( ic, "Can't find suitable authentication method" ); + imcb_error( ic, "Can't find suitable authentication method" ); imc_logout( ic, FALSE ); return XT_ABORT; } @@ -276,14 +276,14 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node if( !( type = xt_find_attr( node, "type" ) ) ) { - imc_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } if( strcmp( type, "error" ) == 0 ) { - imc_error( ic, "Authentication failure" ); + imcb_error( ic, "Authentication failure" ); imc_logout( ic, FALSE ); return XT_ABORT; } @@ -310,7 +310,7 @@ xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, c = xt_find_node( c->children, "jid" ); if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 ) - imc_log( ic, "Server changed session resource string to `%s'", s + 1 ); + imcb_log( ic, "Server changed session resource string to `%s'", s + 1 ); jd->flags &= ~JFLAG_WAIT_BIND; } @@ -333,7 +333,7 @@ int jabber_get_roster( struct im_connection *ic ) struct xt_node *node; int st; - imc_log( ic, "Authenticated, requesting buddy list" ); + imcb_log( ic, "Authenticated, requesting buddy list" ); node = xt_new_node( "query", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); @@ -352,7 +352,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * if( !( query = xt_find_node( node->children, "query" ) ) ) { - imc_log( ic, "WARNING: Received NULL roster packet" ); + imcb_log( ic, "WARNING: Received NULL roster packet" ); return XT_HANDLED; } @@ -396,7 +396,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * } if( initial ) - imc_connected( ic ); + imcb_connected( ic ); return XT_HANDLED; } @@ -427,7 +427,7 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) { s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ - imc_log( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); + imcb_log( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); return XT_HANDLED; } @@ -535,7 +535,7 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no /* *sigh* */ - imc_log( ic, "%s", reply->str ); + imcb_log( ic, "%s", reply->str ); g_string_free( reply, TRUE ); return XT_HANDLED; diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index af294d90..e560fda0 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -58,7 +58,7 @@ static void jabber_init( account_t *acc ) static void jabber_login( account_t *acc ) { - struct im_connection *ic = imc_new( acc ); + struct im_connection *ic = imcb_new( acc ); struct jabber_data *jd = g_new0( struct jabber_data, 1 ); struct ns_srv_reply *srv = NULL; char *connect_to, *s; @@ -71,7 +71,7 @@ static void jabber_login( account_t *acc ) if( jd->server == NULL ) { - imc_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); + imcb_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); imc_logout( ic, FALSE ); return; } @@ -158,12 +158,12 @@ static void jabber_login( account_t *acc ) else connect_to = jd->server; - imc_log( ic, "Connecting" ); + imcb_log( ic, "Connecting" ); if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN || set_getint( &acc->set, "port" ) > JABBER_PORT_MAX ) { - imc_log( ic, "Incorrect port number, must be in the %d-%d range", + imcb_log( ic, "Incorrect port number, must be in the %d-%d range", JABBER_PORT_MIN, JABBER_PORT_MAX ); imc_logout( ic, FALSE ); return; @@ -185,7 +185,7 @@ static void jabber_login( account_t *acc ) if( jd->fd == -1 ) { - imc_error( ic, "Could not connect to server" ); + imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); } } @@ -284,7 +284,7 @@ static void jabber_get_info( struct im_connection *ic, char *who ) while( bud ) { - imc_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", + imcb_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s", bud->full_jid, bud->priority, bud->away_state ? bud->away_state->full_name : "(none)", bud->away_message ? : "(none)" ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index cc237b03..949a7a4b 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -223,7 +223,7 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla presence_send_request( bla->ic, bla->handle, "subscribed" ); if( find_buddy( bla->ic, bla->handle ) == NULL ) - show_got_added( bla->ic, bla->handle, NULL ); + imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla ); @@ -246,7 +246,7 @@ void jabber_buddy_ask( struct im_connection *ic, char *handle ) bla->handle = g_strdup( handle ); buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); - do_ask_dialog( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); + imcb_ask( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); g_free( buf ); } diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 634948bf..4007c84e 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -40,7 +40,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imc_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); + imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -73,7 +73,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imc_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); + imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } @@ -102,7 +102,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else if( strcmp( type, "subscribed" ) == 0 ) { /* Not sure about this one, actually... */ - imc_log( ic, "%s just accepted your authorization request", from ); + imcb_log( ic, "%s just accepted your authorization request", from ); } else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) { diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index cbd40fb1..69199a8b 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -37,14 +37,14 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) /* Should abort this now, since we should already be doing IQ authentication. Strange things happen when you try to do both... */ - imc_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); + imcb_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); return XT_HANDLED; } s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - imc_log( ic, "Stream error while authenticating" ); + imcb_log( ic, "Stream error while authenticating" ); imc_logout( ic, FALSE ); return XT_ABORT; } @@ -62,7 +62,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) if( !sup_plain && !sup_digest ) { - imc_error( ic, "No known SASL authentication schemes supported" ); + imcb_error( ic, "No known SASL authentication schemes supported" ); imc_logout( ic, FALSE ); return XT_ABORT; } @@ -279,7 +279,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) goto silent_error; error: - imc_error( ic, "Incorrect SASL challenge received" ); + imcb_error( ic, "Incorrect SASL challenge received" ); imc_logout( ic, FALSE ); silent_error: @@ -303,19 +303,19 @@ xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) s = xt_find_attr( node, "xmlns" ); if( !s || strcmp( s, XMLNS_SASL ) != 0 ) { - imc_log( ic, "Stream error while authenticating" ); + imcb_log( ic, "Stream error while authenticating" ); imc_logout( ic, FALSE ); return XT_ABORT; } if( strcmp( node->name, "success" ) == 0 ) { - imc_log( ic, "Authentication finished" ); + imcb_log( ic, "Authentication finished" ); jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; } else if( strcmp( node->name, "failure" ) == 0 ) { - imc_error( ic, "Authentication failure" ); + imcb_error( ic, "Authentication failure" ); imc_logout( ic, FALSE ); return XT_ABORT; } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 74a41322..676a8ad7 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -38,7 +38,7 @@ static void msn_init( account_t *acc ) static void msn_login( account_t *acc ) { - struct im_connection *ic = imc_new( acc ); + struct im_connection *ic = imcb_new( acc ); struct msn_data *md = g_new0( struct msn_data, 1 ); ic->proto_data = md; @@ -46,17 +46,17 @@ static void msn_login( account_t *acc ) if( strchr( acc->user, '@' ) == NULL ) { - imc_error( ic, "Invalid account name" ); + imcb_error( ic, "Invalid account name" ); imc_logout( ic, FALSE ); return; } - imc_log( ic, "Connecting" ); + imcb_log( ic, "Connecting" ); md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, ic ); if( md->fd < 0 ) { - imc_error( ic, "Could not connect to server" ); + imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return; } @@ -95,7 +95,7 @@ static void msn_logout( struct im_connection *ic ) { m = l->data; - imc_log( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); + imcb_log( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); g_free( m->who ); g_free( m->text ); g_free( m ); @@ -227,7 +227,7 @@ static void msn_set_my_name( struct im_connection *ic, char *info ) static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - imc_log( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); + imcb_log( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); } static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) @@ -372,7 +372,7 @@ static char *msn_set_display_name( set_t *set, char *value ) if( strlen( value ) > 129 ) { - imc_log( ic, "Maximum name length exceeded" ); + imcb_log( ic, "Maximum name length exceeded" ); return NULL; } diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 67e17b08..80f351a2 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -35,7 +35,7 @@ int msn_write( struct im_connection *ic, char *s, int len ) st = write( md->fd, s, len ); if( st != len ) { - imc_error( ic, "Short write() to main server" ); + imcb_error( ic, "Short write() to main server" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -45,7 +45,7 @@ int msn_write( struct im_connection *ic, char *s, int len ) int msn_logged_in( struct im_connection *ic ) { - imc_connected( ic ); + imcb_connected( ic ); return( 0 ); } @@ -94,7 +94,7 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); if( find_buddy( bla->ic, bla->handle ) == NULL ) - show_got_added( bla->ic, bla->handle, NULL ); + imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); g_free( bla->realname ); @@ -122,7 +122,7 @@ void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ) g_snprintf( buf, sizeof( buf ), "The user %s (%s) wants to add you to his/her buddy list.", handle, realname ); - do_ask_dialog( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); + imcb_ask( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); } char *msn_findheader( char *text, char *header, int len ) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 77bb4939..ba428d82 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -46,7 +46,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) if( source == -1 ) { - imc_error( ic, "Could not connect to server" ); + imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); return FALSE; } @@ -75,7 +75,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) if( msn_write( ic, s, strlen( s ) ) ) { ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic ); - imc_log( ic, "Connected to server, waiting for reply" ); + imcb_log( ic, "Connected to server, waiting for reply" ); } return FALSE; @@ -88,7 +88,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ { - imc_error( ic, "Error while reading from server" ); + imcb_error( ic, "Error while reading from server" ); imc_logout( ic, TRUE ); return FALSE; @@ -113,7 +113,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) { - imc_error( ic, "Unsupported protocol" ); + imcb_error( ic, "Unsupported protocol" ); imc_logout( ic, FALSE ); return( 0 ); } @@ -142,7 +142,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[3], ':' ); if( !server ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -150,7 +150,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) port = atoi( server + 1 ); server = cmd[3]; - imc_log( ic, "Transferring to other server" ); + imcb_log( ic, "Transferring to other server" ); md->fd = proxy_connect( server, port, msn_ns_connected, ic ); } @@ -161,7 +161,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[3], ':' ); if( !server ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -171,7 +171,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[4], "CKI" ) != 0 ) { - imc_error( ic, "Unknown authentication method for switchboard" ); + imcb_error( ic, "Unknown authentication method for switchboard" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -203,7 +203,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -215,7 +215,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) /* Time for some Passport black magic... */ if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) { - imc_error( ic, "Error while contacting Passport server" ); + imcb_error( ic, "Error while contacting Passport server" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -235,14 +235,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) s->value = g_strdup( cmd[4] ); } - imc_log( ic, "Authenticated, getting buddy list" ); + imcb_log( ic, "Authenticated, getting buddy list" ); g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); return( msn_write( ic, buf, strlen( buf ) ) ); } else { - imc_error( ic, "Unknown authentication type" ); + imcb_error( ic, "Unknown authentication type" ); imc_logout( ic, FALSE ); return( 0 ); } @@ -251,7 +251,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( num_parts != 4 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -260,7 +260,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( md->handler->msglen <= 0 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -291,7 +291,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 && num_parts != 5 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -327,7 +327,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( ic->flags & OPT_LOGGED_IN ) { - imc_log( ic, "Successfully transferred to different server" ); + imcb_log( ic, "Successfully transferred to different server" ); g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); return( msn_write( ic, buf, strlen( buf ) ) ); } @@ -343,7 +343,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 4 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -362,7 +362,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 3 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -384,7 +384,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 6 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -412,7 +412,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 5 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -437,7 +437,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts != 7 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -447,7 +447,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) server = strchr( cmd[2], ':' ); if( !server ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -457,7 +457,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[3], "CKI" ) != 0 ) { - imc_error( ic, "Unknown authentication method for switchboard" ); + imcb_error( ic, "Unknown authentication method for switchboard" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -477,7 +477,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( strchr( cmd[4], '@' ) == NULL ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -500,16 +500,16 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) { - imc_error( ic, "Someone else logged in with your account" ); + imcb_error( ic, "Someone else logged in with your account" ); allow_reconnect = FALSE; } else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) { - imc_error( ic, "Terminating session because of server shutdown" ); + imcb_error( ic, "Terminating session because of server shutdown" ); } else { - imc_error( ic, "Session terminated by remote server (reason unknown)" ); + imcb_error( ic, "Session terminated by remote server (reason unknown)" ); } imc_logout( ic, allow_reconnect ); @@ -519,7 +519,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { if( num_parts != 5 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -547,13 +547,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else if( strcmp( cmd[0], "IPG" ) == 0 ) { - imc_error( ic, "Received IPG command, we don't handle them yet." ); + imcb_error( ic, "Received IPG command, we don't handle them yet." ); md->handler->msglen = atoi( cmd[1] ); if( md->handler->msglen <= 0 ) { - imc_error( ic, "Syntax error" ); + imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -563,7 +563,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); - imc_error( ic, "Error reported by MSN server: %s", err->text ); + imcb_error( ic, "Error reported by MSN server: %s", err->text ); if( err->flags & STATUS_FATAL ) { @@ -617,7 +617,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( mtype && strcmp( mtype, "1" ) == 0 ) { if( arg1 ) - imc_log( ic, "The server is going down for maintenance in %s minutes.", arg1 ); + imcb_log( ic, "The server is going down for maintenance in %s minutes.", arg1 ); } if( arg1 ) g_free( arg1 ); @@ -634,7 +634,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( inbox && folders ) { - imc_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); + imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); } } else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 ) @@ -644,7 +644,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int if( from && fromname ) { - imc_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); + imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); } } else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) @@ -672,7 +672,7 @@ static void msn_auth_got_passport_id( struct passport_reply *rep ) if( key == NULL ) { - imc_error( ic, "Error during Passport authentication (%s)", + imcb_error( ic, "Error during Passport authentication (%s)", rep->error_string ? rep->error_string : "Unknown error" ); imc_logout( ic, TRUE ); } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index f8413856..614fb79c 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -221,7 +221,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) } g_slist_free( sb->msgq ); - imc_log( ic, "Warning: Closing down MSN switchboard connection with " + imcb_log( ic, "Warning: Closing down MSN switchboard connection with " "unsent message to %s, you'll have to resend it.", sb->who ? sb->who : "(unknown)" ); } @@ -320,7 +320,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( strcmp( cmd[0], "XFR" ) == 0 ) { - imc_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); + imcb_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); imc_logout( ic, TRUE ); return( 0 ); } @@ -527,7 +527,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) int num = atoi( cmd[0] ); const struct msn_status_code *err = msn_status_by_number( num ); - imc_error( ic, "Error reported by switchboard server: %s", err->text ); + imcb_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 273cc6c8..6121d398 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -144,7 +144,7 @@ GSList *get_connections() { return connections; } /* multi.c */ -struct im_connection *imc_new( account_t *acc ) +struct im_connection *imcb_new( account_t *acc ) { struct im_connection *ic; @@ -203,7 +203,7 @@ static void serv_got_crap( struct im_connection *ic, char *format, ... ) g_free( text ); } -void imc_log( struct im_connection *ic, char *format, ... ) +void imcb_log( struct im_connection *ic, char *format, ... ) { va_list params; char *text; @@ -220,7 +220,7 @@ void imc_log( struct im_connection *ic, char *format, ... ) g_free( text ); } -void imc_error( struct im_connection *ic, char *format, ... ) +void imcb_error( struct im_connection *ic, char *format, ... ) { va_list params; char *text; @@ -247,7 +247,7 @@ static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) return TRUE; } -void imc_connected( struct im_connection *ic ) +void imcb_connected( struct im_connection *ic ) { user_t *u; @@ -259,14 +259,14 @@ void imc_connected( struct im_connection *ic ) u = user_find( ic->irc, ic->irc->nick ); - imc_log( ic, "Logged in" ); + imcb_log( ic, "Logged in" ); ic->keepalive = b_timeout_add( 60000, send_keepalive, ic ); ic->flags |= OPT_LOGGED_IN; /* Also necessary when we're not away, at least for some of the protocols. */ - bim_set_away( ic, u->away ); + imc_set_away( ic, u->away ); } gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) @@ -299,7 +299,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) else ic->flags |= OPT_LOGGING_OUT; - imc_log( ic, "Signing off.." ); + imcb_log( ic, "Signing off.." ); b_event_remove( ic->keepalive ); ic->keepalive = 0; @@ -333,7 +333,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) { int delay = set_getint( &irc->set, "auto_reconnect_delay" ); - imc_log( ic, "Reconnecting in %d seconds..", delay ); + imcb_log( ic, "Reconnecting in %d seconds..", delay ); a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); } @@ -343,7 +343,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) /* dialogs.c */ -void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) +void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ) { query_add( ic->irc, ic, msg, doit, dont, data ); } @@ -359,12 +359,12 @@ void add_buddy( struct im_connection *ic, char *group, char *handle, char *realn irc_t *irc = ic->irc; if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */ - imc_log( ic, "Receiving user add from handle: %s", handle ); + imcb_log( ic, "Receiving user add from handle: %s", handle ); if( user_findhandle( ic, handle ) ) { if( set_getbool( &irc->set, "debug" ) ) - imc_log( ic, "User already exists, ignoring add request: %s", handle ); + imcb_log( ic, "User already exists, ignoring add request: %s", handle ); return; @@ -447,7 +447,7 @@ void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ) u->realname = g_strdup( realname ); if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) - imc_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); + imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); } } @@ -474,7 +474,7 @@ void show_got_added_yes( gpointer w, struct show_got_added_data *data ) return show_got_added_no( w, data ); } -void show_got_added( struct im_connection *ic, char *handle, const char *realname ) +void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ) { struct show_got_added_data *data = g_new0( struct show_got_added_data, 1 ); char *s; @@ -511,8 +511,8 @@ void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int { if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { - imc_log( ic, "serv_got_update() for handle %s:", handle ); - imc_log( ic, "loggedin = %d, type = %d", loggedin, type ); + imcb_log( ic, "serv_got_update() for handle %s:", handle ); + imcb_log( ic, "loggedin = %d, type = %d", loggedin, type ); } return; @@ -551,15 +551,6 @@ void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int { u->away = g_strdup( "Away" ); } - else if( ( type & UC_UNAVAILABLE ) && ( strcmp( ic->acc->prpl->name, "jabber" ) == 0 ) ) - { - if( type & UC_DND ) - u->away = g_strdup( "Do Not Disturb" ); - else if( type & UC_XA ) - u->away = g_strdup( "Extended Away" ); - else // if( type & UC_AWAY ) - u->away = g_strdup( "Away" ); - } else if( ( type & UC_UNAVAILABLE ) && ic->acc->prpl->get_status_string ) { u->away = g_strdup( ic->acc->prpl->get_status_string( ic, type ) ); @@ -592,7 +583,7 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla if( g_strcasecmp( h, "ignore" ) == 0 ) { if( set_getbool( &irc->set, "debug" ) ) - imc_log( ic, "Ignoring message from unknown handle %s", handle ); + imcb_log( ic, "Ignoring message from unknown handle %s", handle ); return; } @@ -614,7 +605,7 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla } else { - imc_log( ic, "Message from unknown handle %s:", handle ); + imcb_log( ic, "Message from unknown handle %s:", handle ); u = user_find( irc, irc->mynick ); } } @@ -684,7 +675,7 @@ void serv_got_chat_left( struct groupchat *c ) GList *ir; if( set_getbool( &ic->irc->set, "debug" ) ) - imc_log( ic, "You were removed from conversation 0x%x", (int) c ); + imcb_log( ic, "You were removed from conversation 0x%x", (int) c ); if( c ) { @@ -732,7 +723,7 @@ void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, t if( c && u ) irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", msg ); else - imc_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); + imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); } struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) @@ -754,7 +745,7 @@ struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); if( set_getbool( &ic->irc->set, "debug" ) ) - imc_log( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); + imcb_log( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); return c; } @@ -768,7 +759,7 @@ void add_chat_buddy( struct groupchat *b, char *handle ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - imc_log( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); + imcb_log( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); /* It might be yourself! */ if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 ) @@ -802,7 +793,7 @@ void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - imc_log( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); + imcb_log( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); /* It might be yourself! */ if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) @@ -928,7 +919,7 @@ char *set_eval_away_devoice( set_t *set, char *value ) /* The plan is to not allow straight calls to prpl functions anymore, but do them all from some wrappers. We'll start to define some down here: */ -int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ) +int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ) { char *buf = NULL; int st; @@ -945,7 +936,7 @@ int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags return st; } -int bim_chat_msg( struct groupchat *c, char *msg, int flags ) +int imc_chat_msg( struct groupchat *c, char *msg, int flags ) { char *buf = NULL; @@ -961,9 +952,9 @@ int bim_chat_msg( struct groupchat *c, char *msg, int flags ) return 1; } -static char *bim_away_alias_find( GList *gcm, char *away ); +static char *imc_away_alias_find( GList *gcm, char *away ); -int bim_set_away( struct im_connection *ic, char *away ) +int imc_set_away( struct im_connection *ic, char *away ) { GList *m, *ms; char *s; @@ -994,12 +985,12 @@ int bim_set_away( struct im_connection *ic, char *away ) } else { - s = bim_away_alias_find( ms, away ); + s = imc_away_alias_find( ms, away ); if( s ) { ic->acc->prpl->set_away( ic, s, away ); if( set_getbool( &ic->irc->set, "debug" ) ) - imc_log( ic, "Setting away state to %s", s ); + imcb_log( ic, "Setting away state to %s", s ); } else ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away ); @@ -1008,7 +999,7 @@ int bim_set_away( struct im_connection *ic, char *away ) return( 1 ); } -static char *bim_away_alias_list[8][5] = +static char *imc_away_alias_list[8][5] = { { "Away from computer", "Away", "Extended away", NULL }, { "NA", "N/A", "Not available", NULL }, @@ -1020,28 +1011,28 @@ static char *bim_away_alias_list[8][5] = { NULL } }; -static char *bim_away_alias_find( GList *gcm, char *away ) +static char *imc_away_alias_find( GList *gcm, char *away ) { GList *m; int i, j; - for( i = 0; *bim_away_alias_list[i]; i ++ ) + for( i = 0; *imc_away_alias_list[i]; i ++ ) { - for( j = 0; bim_away_alias_list[i][j]; j ++ ) - if( g_strncasecmp( away, bim_away_alias_list[i][j], strlen( bim_away_alias_list[i][j] ) ) == 0 ) + for( j = 0; imc_away_alias_list[i][j]; j ++ ) + if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 ) break; - if( !bim_away_alias_list[i][j] ) /* If we reach the end, this row */ + if( !imc_away_alias_list[i][j] ) /* If we reach the end, this row */ continue; /* is not what we want. Next! */ /* Now find an entry in this row which exists in gcm */ - for( j = 0; bim_away_alias_list[i][j]; j ++ ) + for( j = 0; imc_away_alias_list[i][j]; j ++ ) { m = gcm; while( m ) { - if( g_strcasecmp( bim_away_alias_list[i][j], m->data ) == 0 ) - return( bim_away_alias_list[i][j] ); + if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 ) + return( imc_away_alias_list[i][j] ); m = m->next; } } @@ -1050,7 +1041,7 @@ static char *bim_away_alias_find( GList *gcm, char *away ) return( NULL ); } -void bim_add_allow( struct im_connection *ic, char *handle ) +void imc_add_allow( struct im_connection *ic, char *handle ) { if( g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) { @@ -1060,7 +1051,7 @@ void bim_add_allow( struct im_connection *ic, char *handle ) ic->acc->prpl->add_permit( ic, handle ); } -void bim_rem_allow( struct im_connection *ic, char *handle ) +void imc_rem_allow( struct im_connection *ic, char *handle ) { GSList *l; @@ -1073,7 +1064,7 @@ void bim_rem_allow( struct im_connection *ic, char *handle ) ic->acc->prpl->rem_permit( ic, handle ); } -void bim_add_block( struct im_connection *ic, char *handle ) +void imc_add_block( struct im_connection *ic, char *handle ) { if( g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) { @@ -1083,7 +1074,7 @@ void bim_add_block( struct im_connection *ic, char *handle ) ic->acc->prpl->add_deny( ic, handle ); } -void bim_rem_block( struct im_connection *ic, char *handle ) +void imc_rem_block( struct im_connection *ic, char *handle ) { GSList *l; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 08df1750..cc2dcea4 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -149,7 +149,7 @@ struct prpl { void (* set_permit_deny)(struct im_connection *); /* Request profile info. Free-formatted stuff, the IM module gives back - this info via imc_log(). */ + this info via imcb_log(). */ void (* get_info) (struct im_connection *, char *who); void (* set_my_name) (struct im_connection *, char *name); void (* set_name) (struct im_connection *, char *who, char *name); @@ -174,67 +174,57 @@ struct prpl { #define UC_UNAVAILABLE 1 -/* JABBER */ -#define UC_AWAY (0x02 | UC_UNAVAILABLE) -#define UC_CHAT 0x04 -#define UC_XA (0x08 | UC_UNAVAILABLE) -#define UC_DND (0x10 | UC_UNAVAILABLE) - +/* im_api core stuff. */ +void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); G_MODULE_EXPORT struct prpl *find_protocol(const char *name); G_MODULE_EXPORT void register_protocol(struct prpl *); -/* nogaim.c */ -int bim_set_away( struct im_connection *ic, char *away ); -int bim_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); -int bim_chat_msg( struct groupchat *c, char *msg, int flags ); - -void bim_add_allow( struct im_connection *ic, char *handle ); -void bim_rem_allow( struct im_connection *ic, char *handle ); -void bim_add_block( struct im_connection *ic, char *handle ); -void bim_rem_block( struct im_connection *ic, char *handle ); - -void nogaim_init(); -char *set_eval_away_devoice( set_t *set, char *value ); - -gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); -void cancel_auto_reconnect( struct account *a ); - -/* multi.c */ -G_MODULE_EXPORT struct im_connection *imc_new( account_t *acc ); -G_MODULE_EXPORT void imc_free( struct im_connection *ic ); -G_MODULE_EXPORT void imc_log( struct im_connection *ic, char *format, ... ); -G_MODULE_EXPORT void imc_error( struct im_connection *ic, char *format, ... ); -G_MODULE_EXPORT void imc_connected( struct im_connection *ic ); +/* Connection management. */ +G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc ); +G_MODULE_EXPORT void imcb_free( struct im_connection *ic ); +G_MODULE_EXPORT void imcb_connected( struct im_connection *ic ); G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect ); -/* dialogs.c */ -G_MODULE_EXPORT void do_ask_dialog( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); +/* Communicating with the user. */ +G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ); +G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ); +G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); +G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ); -/* list.c */ -G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ); -G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle ); -G_MODULE_EXPORT void signoff_blocked( struct im_connection *ic ); - -G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ); - -/* buddy_chat.c */ +/* Groupchats */ G_MODULE_EXPORT void add_chat_buddy( struct groupchat *b, char *handle ); G_MODULE_EXPORT void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ); - -/* prpl.c */ -G_MODULE_EXPORT void show_got_added( struct im_connection *ic, char *handle, const char *realname ); - -/* server.c */ -G_MODULE_EXPORT void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); -G_MODULE_EXPORT void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); -G_MODULE_EXPORT void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ); G_MODULE_EXPORT void serv_got_chat_invite( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); G_MODULE_EXPORT struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ); G_MODULE_EXPORT void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ); G_MODULE_EXPORT void serv_got_chat_left( struct groupchat *c ); - struct groupchat *chat_by_channel( char *channel ); struct groupchat *chat_by_id( int id ); +/* Buddy management */ +G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ); +G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ); + +/* Buddy activity */ +G_MODULE_EXPORT void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); +G_MODULE_EXPORT void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); +G_MODULE_EXPORT void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ); + +/* Actions, or whatever. */ +int imc_set_away( struct im_connection *ic, char *away ); +int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); +int imc_chat_msg( struct groupchat *c, char *msg, int flags ); + +void imc_add_allow( struct im_connection *ic, char *handle ); +void imc_rem_allow( struct im_connection *ic, char *handle ); +void imc_add_block( struct im_connection *ic, char *handle ); +void imc_rem_block( struct im_connection *ic, char *handle ); + +/* Misc. stuff */ +char *set_eval_away_devoice( set_t *set, char *value ); +gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); +void cancel_auto_reconnect( struct account *a ); + #endif diff --git a/protocols/oscar/chat.c b/protocols/oscar/chat.c index 82aa5421..fbf45693 100644 --- a/protocols/oscar/chat.c +++ b/protocols/oscar/chat.c @@ -53,7 +53,7 @@ aim_conn_t *aim_chat_getconn(aim_session_t *sess, const char *name) if (cur->type != AIM_CONN_TYPE_CHAT) continue; if (!cur->priv) { - imc_error(sess->aux_data, "chat connection with no name!"); + imcb_error(sess->aux_data, "chat connection with no name!"); continue; } @@ -396,7 +396,7 @@ static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a detaillevel = aimbs_get8(bs); if (detaillevel != 0x02) { - imc_error(sess->aux_data, "Only detaillevel 0x2 is support at the moment"); + imcb_error(sess->aux_data, "Only detaillevel 0x2 is support at the moment"); return 1; } @@ -614,7 +614,7 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, channel = aimbs_get16(bs); if (channel != 0x0003) { - imc_error(sess->aux_data, "unknown channel!"); + imcb_error(sess->aux_data, "unknown channel!"); return 0; } diff --git a/protocols/oscar/chatnav.c b/protocols/oscar/chatnav.c index 05fdf6fa..d94d3c7b 100644 --- a/protocols/oscar/chatnav.c +++ b/protocols/oscar/chatnav.c @@ -285,7 +285,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t tlvlist = aim_readtlvchain(bs); if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) { - imc_error(sess->aux_data, "no bigblock in top tlv in create room response"); + imcb_error(sess->aux_data, "no bigblock in top tlv in create room response"); aim_freetlvchain(&tlvlist); return 0; @@ -300,7 +300,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t detaillevel = aimbs_get8(&bbbs); if (detaillevel != 0x02) { - imc_error(sess->aux_data, "unknown detaillevel in create room response"); + imcb_error(sess->aux_data, "unknown detaillevel in create room response"); aim_freetlvchain(&tlvlist); g_free(ck); return 0; @@ -366,12 +366,12 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai int ret = 0; if (!(snac2 = aim_remsnac(sess, snac->id))) { - imc_error(sess->aux_data, "received response to unknown request!"); + imcb_error(sess->aux_data, "received response to unknown request!"); return 0; } if (snac2->family != 0x000d) { - imc_error(sess->aux_data, "recieved response that maps to corrupt request!"); + imcb_error(sess->aux_data, "recieved response that maps to corrupt request!"); return 0; } @@ -388,7 +388,7 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai else if (snac2->type == 0x0008) /* create room */ ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); else - imc_error(sess->aux_data, "unknown request subtype"); + imcb_error(sess->aux_data, "unknown request subtype"); if (snac2) g_free(snac2->data); diff --git a/protocols/oscar/icq.c b/protocols/oscar/icq.c index d3c7c182..f7c02e04 100644 --- a/protocols/oscar/icq.c +++ b/protocols/oscar/icq.c @@ -239,7 +239,7 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, if (!(tl = aim_readtlvchain(bs)) || !(datatlv = aim_gettlv(tl, 0x0001, 1))) { aim_freetlvchain(&tl); - imc_error(sess->aux_data, "corrupt ICQ response\n"); + imcb_error(sess->aux_data, "corrupt ICQ response\n"); return 0; } diff --git a/protocols/oscar/im.c b/protocols/oscar/im.c index ac3d08d4..51d8ec74 100644 --- a/protocols/oscar/im.c +++ b/protocols/oscar/im.c @@ -936,7 +936,7 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a channel = aimbs_get16(bs); if (channel != 0x01) { - imc_error(sess->aux_data, "icbm: ICBM recieved on unsupported channel. Ignoring."); + imcb_error(sess->aux_data, "icbm: ICBM recieved on unsupported channel. Ignoring."); return 0; } @@ -1344,7 +1344,7 @@ static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r args.extdata = aimbs_getraw(bs, args.extdatalen); } else { - // imc_error(sess->aux_data, "Unknown TLV encountered"); + // imcb_error(sess->aux_data, "Unknown TLV encountered"); } /* @@ -1516,7 +1516,7 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r */ cookie2 = aimbs_getraw(&bbs, 8); if (memcmp(cookie, cookie2, 8) != 0) - imc_error(sess->aux_data, "rend: warning cookies don't match!"); + imcb_error(sess->aux_data, "rend: warning cookies don't match!"); memcpy(args.cookie, cookie2, 8); g_free(cookie2); @@ -1782,7 +1782,7 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a } else { - imc_error(sess->aux_data, "ICBM received on an unsupported channel. Ignoring."); + imcb_error(sess->aux_data, "ICBM received on an unsupported channel. Ignoring."); return 0; } diff --git a/protocols/oscar/info.c b/protocols/oscar/info.c index d1ed2059..7cc1dbbc 100644 --- a/protocols/oscar/info.c +++ b/protocols/oscar/info.c @@ -473,7 +473,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * * */ #ifdef DEBUG - // imc_error(sess->aux_data, G_STRLOC); + // imcb_error(sess->aux_data, G_STRLOC); #endif } @@ -634,7 +634,7 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim origsnac = aim_remsnac(sess, snac->id); if (!origsnac || !origsnac->data) { - imc_error(sess->aux_data, "major problem: no snac stored!"); + imcb_error(sess->aux_data, "major problem: no snac stored!"); return 0; } @@ -643,7 +643,7 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) && (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) && (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) { - imc_error(sess->aux_data, "unknown infotype in request!"); + imcb_error(sess->aux_data, "unknown infotype in request!"); return 0; } diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index d95c7068..99f839e4 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -266,7 +266,7 @@ static gboolean oscar_callback(gpointer data, gint source, } else { if ((conn->type == AIM_CONN_TYPE_BOS) || !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { - imc_error(ic, _("Disconnected.")); + imcb_error(ic, _("Disconnected.")); imc_logout(ic, TRUE); } else if (conn->type == AIM_CONN_TYPE_CHAT) { struct chat_connection *c = find_oscar_chat_by_conn(ic, conn); @@ -276,7 +276,7 @@ static gboolean oscar_callback(gpointer data, gint source, c->inpa = 0; c->fd = -1; aim_conn_kill(odata->sess, &conn); - imc_error(sess->aux_data, _("You have been disconnected from chat room %s."), c->name); + imcb_error(sess->aux_data, _("You have been disconnected from chat room %s."), c->name); } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { if (odata->cnpa > 0) b_event_remove(odata->cnpa); @@ -287,7 +287,7 @@ static gboolean oscar_callback(gpointer data, gint source, odata->create_rooms = g_slist_remove(odata->create_rooms, cr); g_free(cr); - imc_error(sess->aux_data, _("Chat is currently unavailable")); + imcb_error(sess->aux_data, _("Chat is currently unavailable")); } aim_conn_kill(odata->sess, &conn); } else if (conn->type == AIM_CONN_TYPE_AUTH) { @@ -324,7 +324,7 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH); if (source < 0) { - imc_error(ic, _("Couldn't connect to host")); + imcb_error(ic, _("Couldn't connect to host")); imc_logout(ic, TRUE); return FALSE; } @@ -352,7 +352,7 @@ static void oscar_init(account_t *acc) static void oscar_login(account_t *acc) { aim_session_t *sess; aim_conn_t *conn; - struct im_connection *ic = imc_new(acc); + struct im_connection *ic = imcb_new(acc); struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); if (isdigit(acc->user[0])) { @@ -379,23 +379,23 @@ static void oscar_login(account_t *acc) { conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (conn == NULL) { - imc_error(ic, _("Unable to login to AIM")); + imcb_error(ic, _("Unable to login to AIM")); imc_logout(ic, TRUE); return; } if (acc->server == NULL) { - imc_error(ic, "No servername specified"); + imcb_error(ic, "No servername specified"); imc_logout(ic, FALSE); return; } if (g_strcasecmp(acc->server, "login.icq.com") != 0 && g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { - imc_log(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); + imcb_log(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); } - imc_log(ic, _("Signon: %s"), ic->acc->user); + imcb_log(ic, _("Signon: %s"), ic->acc->user); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); @@ -403,7 +403,7 @@ static void oscar_login(account_t *acc) { conn->status |= AIM_CONN_STATUS_INPROGRESS; conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, ic); if (conn->fd < 0) { - imc_error(ic, _("Couldn't connect to host")); + imcb_error(ic, _("Couldn't connect to host")); imc_logout(ic, TRUE); return; } @@ -463,7 +463,7 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition bosconn = odata->conn; if (source < 0) { - imc_error(ic, _("Could Not Connect")); + imcb_error(ic, _("Could Not Connect")); imc_logout(ic, TRUE); return FALSE; } @@ -471,7 +471,7 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition aim_conn_completeconnect(sess, bosconn); ic->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn); - imc_log(ic, _("Connection established, cookie sent")); + imcb_log(ic, _("Connection established, cookie sent")); return FALSE; } @@ -494,23 +494,23 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { switch (info->errorcode) { case 0x05: /* Incorrect nick/password */ - imc_error(ic, _("Incorrect nickname or password.")); + imcb_error(ic, _("Incorrect nickname or password.")); // plugin_event(event_error, (void *)980, 0, 0, 0); break; case 0x11: /* Suspended account */ - imc_error(ic, _("Your account is currently suspended.")); + imcb_error(ic, _("Your account is currently suspended.")); break; case 0x18: /* connecting too frequently */ - imc_error(ic, _("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.")); + imcb_error(ic, _("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.")); break; case 0x1c: /* client too old */ - imc_error(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE)); + imcb_error(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE)); break; default: - imc_error(ic, _("Authentication Failed")); + imcb_error(ic, _("Authentication Failed")); break; } od->killme = TRUE; @@ -522,7 +522,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); if (bosconn == NULL) { - imc_error(ic, _("Internal Error")); + imcb_error(ic, _("Internal Error")); od->killme = TRUE; return 0; } @@ -568,7 +568,7 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { bosconn->fd = proxy_connect(host, port, oscar_bos_connect, ic); g_free(host); if (bosconn->fd < 0) { - imc_error(ic, _("Could Not Connect")); + imcb_error(ic, _("Could Not Connect")); od->killme = TRUE; return 0; } @@ -606,7 +606,7 @@ static gboolean damn_you(gpointer data, gint source, b_input_condition c) in = '\0'; } if (in != '\n') { - imc_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." + imcb_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly."); b_event_remove(pos->inpa); closesocket(pos->fd); @@ -629,7 +629,7 @@ static gboolean straight_to_hell(gpointer data, gint source, b_input_condition c char buf[BUF_LONG]; if (source < 0) { - imc_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." + imcb_error(pos->ic, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly."); if (pos->modname) g_free(pos->modname); @@ -707,7 +707,7 @@ int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) { if (pos->modname) g_free(pos->modname); g_free(pos); - imc_error(sess->aux_data, "Gaim was unable to get a valid hash for logging into AIM." + imcb_error(sess->aux_data, "Gaim was unable to get a valid hash for logging into AIM." " You may be disconnected shortly."); } pos->fd = fd; @@ -1111,7 +1111,7 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ inv->exchange = *exch; inv->name = g_strdup(name); - do_ask_dialog( ic, txt, inv, oscar_accept_chat, oscar_reject_chat); + imcb_ask( ic, txt, inv, oscar_accept_chat, oscar_reject_chat); if (name) g_free(name); @@ -1129,7 +1129,7 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); if(find_buddy(data->ic, uin) == NULL) - show_got_added(data->ic, uin, NULL); + imcb_ask_add(data->ic, uin, NULL); g_free(uin); g_free(data); @@ -1163,7 +1163,7 @@ static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) { dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s", uin, reason ? reason : "No reason given."); data->ic = ic; data->uin = uin; - do_ask_dialog(ic, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); + imcb_ask(ic, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); g_free(dialog_msg); } @@ -1206,11 +1206,11 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } break; case 0x0007: { /* Someone has denied you authorization */ - imc_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); + imcb_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); } break; case 0x0008: { /* Someone has granted you authorization */ - imc_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); + imcb_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); } break; case 0x0012: { @@ -1276,7 +1276,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { switch(reason) { case 0: /* Invalid (0) */ - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was invalid.") : _("You missed %d messages from %s because they were invalid."), @@ -1285,7 +1285,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 1: /* Message too large */ - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was too large.") : _("You missed %d messages from %s because they were too large."), @@ -1294,7 +1294,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 2: /* Rate exceeded */ - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because the rate limit has been exceeded.") : _("You missed %d messages from %s because the rate limit has been exceeded."), @@ -1303,7 +1303,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 3: /* Evil Sender */ - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because it was too evil.") : _("You missed %d messages from %s because they are too evil."), @@ -1312,7 +1312,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { break; case 4: /* Evil Receiver */ - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s because you are too evil.") : _("You missed %d messages from %s because you are too evil."), @@ -1320,7 +1320,7 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { userinfo->sn); break; default: - imc_error(sess->aux_data, + imcb_error(sess->aux_data, nummissed == 1 ? _("You missed %d message from %s for unknown reasons.") : _("You missed %d messages from %s for unknown reasons."), @@ -1340,7 +1340,7 @@ static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) { reason = (guint16)va_arg(ap, unsigned int); va_end(ap); - imc_error(sess->aux_data, _("SNAC threw error: %s"), + imcb_error(sess->aux_data, _("SNAC threw error: %s"), reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error"); return 1; @@ -1356,7 +1356,7 @@ static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) { destn = va_arg(ap, char *); va_end(ap); - imc_error(sess->aux_data, _("Your message to %s did not get sent: %s"), destn, + imcb_error(sess->aux_data, _("Your message to %s did not get sent: %s"), destn, (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); return 1; @@ -1372,7 +1372,7 @@ static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) { destn = va_arg(ap, char *); va_end(ap); - imc_error(sess->aux_data, _("User information for %s unavailable: %s"), destn, + imcb_error(sess->aux_data, _("User information for %s unavailable: %s"), destn, (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); return 1; @@ -1389,7 +1389,7 @@ static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); if (id < 4) - imc_error(sess->aux_data, _("Your connection may be lost.")); + imcb_error(sess->aux_data, _("Your connection may be lost.")); return 1; } @@ -1583,7 +1583,7 @@ static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { } else if (code == AIM_RATE_CODE_WARNING) { aim_conn_setlatency(fr->conn, windowsize/4); } else if (code == AIM_RATE_CODE_LIMIT) { - imc_error(sess->aux_data, _("The last message was not sent because you are over the rate limit. " + imcb_error(sess->aux_data, _("The last message was not sent because you are over the rate limit. " "Please wait 10 seconds and try again.")); aim_conn_setlatency(fr->conn, windowsize/2); } else if (code == AIM_RATE_CODE_CLEARLIMIT) { @@ -1788,11 +1788,11 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { } break; case 0x0007: { /* Someone has denied you authorization */ - imc_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); + imcb_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); } break; case 0x0008: { /* Someone has granted you authorization */ - imc_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); + imcb_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); } break; case 0x0012: { @@ -1905,7 +1905,7 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } /* else... */ if (od->rights.maxawaymsglen == 0) - imc_error(ic, "oscar_set_away_aim called before locate rights received"); + imcb_error(ic, "oscar_set_away_aim called before locate rights received"); aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1919,7 +1919,7 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } if (strlen(message) > od->rights.maxawaymsglen) { - imc_error(ic, "Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); + imcb_error(ic, "Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); } ic->away = g_strndup(message, od->rights.maxawaymsglen); @@ -2083,7 +2083,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { aim_icq_reqofflinemsgs(sess); /* Now that we have a buddy list, we can tell BitlBee that we're online. */ - imc_connected(ic); + imcb_connected(ic); return 1; } @@ -2105,7 +2105,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) if( count & 1 ) { /* Hmm, the length should be even... */ - imc_error( sess->aux_data, "Received SSI ACK package with non-even length"); + imcb_error( sess->aux_data, "Received SSI ACK package with non-even length"); return( 0 ); } count >>= 1; @@ -2116,7 +2116,7 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) st = aimbs_get16( &fr->data ); if( st == 0x0E ) { - imc_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); + imcb_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); aim_ssi_auth_request( sess, fr->conn, list, "" ); aim_ssi_addbuddies( sess, fr->conn, OSCAR_GROUP, &list, 1, 1 ); @@ -2302,7 +2302,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) g_string_sprintfa(str, "\n"); } - imc_log(ic, "%s\n%s", _("User Info"), str->str); + imcb_log(ic, "%s\n%s", _("User Info"), str->str); g_string_free(str, TRUE); return 1; @@ -2396,18 +2396,18 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) idletime.tm_min = userinfo->idletime % 60; idletime.tm_sec = 0; strftime(buff, 256, _("%d days %H hours %M minutes"), &idletime); - imc_log(ic, "%s: %s", _("Idle Time"), buff); + imcb_log(ic, "%s: %s", _("Idle Time"), buff); } if(text) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - imc_log(ic, "%s\n%s", _("User Info"), utf8); + imcb_log(ic, "%s\n%s", _("User Info"), utf8); } else { - imc_log(ic, _("No user info available.")); + imcb_log(ic, _("No user info available.")); } } else if(infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); - imc_log(ic, "%s\n%s", _("Away Message"), utf8); + imcb_log(ic, "%s\n%s", _("Away Message"), utf8); } g_free(utf8); diff --git a/protocols/oscar/rxqueue.c b/protocols/oscar/rxqueue.c index b5a83be8..34f389af 100644 --- a/protocols/oscar/rxqueue.c +++ b/protocols/oscar/rxqueue.c @@ -391,7 +391,7 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) aim_bstream_rewind(&flaphdr); start = aimbs_get8(&flaphdr); - imc_error(sess->aux_data, "FLAP framing disrupted"); + imcb_error(sess->aux_data, "FLAP framing disrupted"); aim_conn_close(conn); return -1; } diff --git a/protocols/oscar/search.c b/protocols/oscar/search.c index c557e35f..3570e4df 100644 --- a/protocols/oscar/search.c +++ b/protocols/oscar/search.c @@ -38,7 +38,7 @@ static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo /* XXX the modules interface should have already retrieved this for us */ if (!(snac2 = aim_remsnac(sess, snac->id))) { - imc_error(sess->aux_data, "couldn't get snac"); + imcb_error(sess->aux_data, "couldn't get snac"); return 0; } diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index 69d53d00..3a180780 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -566,7 +566,7 @@ static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_ group = aimbs_get16(bs); - imc_error(sess->aux_data, "bifurcated migration unsupported"); + imcb_error(sess->aux_data, "bifurcated migration unsupported"); } tl = aim_readtlvchain(bs); @@ -893,7 +893,7 @@ int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guin aimbs_put32(&fr->data, 0xecf8427e); */ } else - imc_error(sess->aux_data, "WARNING: unknown hash request"); + imcb_error(sess->aux_data, "WARNING: unknown hash request"); } diff --git a/protocols/oscar/txqueue.c b/protocols/oscar/txqueue.c index bd8db49d..4416025a 100644 --- a/protocols/oscar/txqueue.c +++ b/protocols/oscar/txqueue.c @@ -29,7 +29,7 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g aim_frame_t *fr; if (!conn) { - imc_error(sess->aux_data, "no connection specified"); + imcb_error(sess->aux_data, "no connection specified"); return NULL; } @@ -45,7 +45,7 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g fr->hdr.flap.type = chan; } else - imc_error(sess->aux_data, "unknown framing"); + imcb_error(sess->aux_data, "unknown framing"); if (datalen > 0) { guint8 *data; @@ -79,7 +79,7 @@ static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr) { if (!fr->conn) { - imc_error(sess->aux_data, "WARNING: enqueueing packet with no connection"); + imcb_error(sess->aux_data, "WARNING: enqueueing packet with no connection"); fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); } @@ -119,7 +119,7 @@ static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr) { if (!fr->conn) { - imc_error(sess->aux_data, "packet has no connection"); + imcb_error(sess->aux_data, "packet has no connection"); aim_frame_destroy(fr); return 0; } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index ae66b209..e380d0ae 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -122,13 +122,13 @@ static char *byahoo_strip( char *in ) static void byahoo_login( account_t *acc ) { - struct im_connection *ic = imc_new( acc ); + struct im_connection *ic = imcb_new( acc ); struct byahoo_data *yd = ic->proto_data = g_new0( struct byahoo_data, 1 ); yd->logged_in = FALSE; yd->current_status = YAHOO_STATUS_AVAILABLE; - imc_log( ic, "Connecting" ); + imcb_log( ic, "Connecting" ); yd->y2_id = yahoo_init( acc->user, acc->pass ); yahoo_login( yd->y2_id, yd->current_status ); } @@ -162,7 +162,7 @@ static void byahoo_logout( struct im_connection *ic ) static void byahoo_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - imc_log(ic, "%s\n%s: %s%s", _("User Info"), + imcb_log(ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), yahoo_get_profile_url(), who); } @@ -509,7 +509,7 @@ void ext_yahoo_login_response( int id, int succ, char *url ) if( succ == YAHOO_LOGIN_OK ) { - imc_connected( ic ); + imcb_connected( ic ); yd->logged_in = TRUE; } @@ -537,9 +537,9 @@ void ext_yahoo_login_response( int id, int succ, char *url ) errstr = "Unknown error"; if( url && *url ) - imc_error( ic, "Error %d (%s). See %s for more information.", succ, errstr, url ); + imcb_error( ic, "Error %d (%s). See %s for more information.", succ, errstr, url ); else - imc_error( ic, "Error %d (%s)", succ, errstr ); + imcb_error( ic, "Error %d (%s)", succ, errstr ); imc_logout( ic, allow_reconnect ); } @@ -604,7 +604,7 @@ void ext_yahoo_got_file( int id, char *who, char *url, long expires, char *msg, { struct im_connection *ic = byahoo_get_ic_by_id( id ); - imc_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); + imcb_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); } void ext_yahoo_typing_notify( int id, char *who, int stat ) @@ -624,21 +624,21 @@ void ext_yahoo_system_message( int id, char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - imc_log( ic, "Yahoo! system message: %s", msg ); + imcb_log( ic, "Yahoo! system message: %s", msg ); } void ext_yahoo_webcam_invite( int id, char *from ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - imc_log( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); + imcb_log( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); } void ext_yahoo_error( int id, char *err, int fatal ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - imc_error( ic, "%s", err ); + imcb_error( ic, "%s", err ); if( fatal ) imc_logout( ic, TRUE ); @@ -802,14 +802,14 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg ); - do_ask_dialog( ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); + imcb_ask( ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); } void ext_yahoo_conf_userdecline( int id, char *who, char *room, char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - imc_log( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); + imcb_log( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); } void ext_yahoo_conf_userjoin( int id, char *who, char *room ) @@ -892,9 +892,9 @@ void ext_yahoo_mail_notify( int id, char *from, char *subj, int cnt ) struct im_connection *ic = byahoo_get_ic_by_id( id ); if( from && subj ) - imc_log( ic, "Received e-mail message from %s with subject `%s'", from, subj ); + imcb_log( ic, "Received e-mail message from %s with subject `%s'", from, subj ); else if( cnt > 0 ) - imc_log( ic, "Received %d new e-mails", cnt ); + imcb_log( ic, "Received %d new e-mails", cnt ); } void ext_yahoo_webcam_invite_reply( int id, char *from, int accept ) diff --git a/query.c b/query.c index e7a55afd..99be2bee 100644 --- a/query.c +++ b/query.c @@ -121,7 +121,7 @@ void query_del_by_conn( irc_t *irc, struct im_connection *ic ) } if( count > 0 ) - imc_log( ic, "Flushed %d unanswered question(s) for this connection.", count ); + imcb_log( ic, "Flushed %d unanswered question(s) for this connection.", count ); q = query_default( irc ); if( q && q != def ) @@ -139,12 +139,12 @@ void query_answer( irc_t *irc, query_t *q, int ans ) } if( ans ) { - imc_log( q->ic, "Accepted: %s", q->question ); + imcb_log( q->ic, "Accepted: %s", q->question ); q->yes( NULL, q->data ); } else { - imc_log( q->ic, "Rejected: %s", q->question ); + imcb_log( q->ic, "Rejected: %s", q->question ); q->no( NULL, q->data ); } q->data = NULL; @@ -159,7 +159,7 @@ static void query_display( irc_t *irc, query_t *q ) { if( q->ic ) { - imc_log( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); + imcb_log( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); } else { diff --git a/root_commands.c b/root_commands.c index 0b3d6844..acbf579f 100644 --- a/root_commands.c +++ b/root_commands.c @@ -633,8 +633,8 @@ static void cmd_block( irc_t *irc, char **cmd ) } else { - bim_rem_allow( ic, cmd[2] ); - bim_add_block( ic, cmd[2] ); + imc_rem_allow( ic, cmd[2] ); + imc_add_block( ic, cmd[2] ); irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] ); } } @@ -692,8 +692,8 @@ static void cmd_allow( irc_t *irc, char **cmd ) } else { - bim_rem_block( ic, cmd[2] ); - bim_add_allow( ic, cmd[2] ); + imc_rem_block( ic, cmd[2] ); + imc_add_allow( ic, cmd[2] ); irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] ); } -- cgit v1.2.3 From 6bbb939e953bbe1ca9ed3101a1569abe4521f543 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 21:01:13 -0700 Subject: Split serv_got_update() into imcb_buddy_(status|times). (Well, the second one isn't implemented yet, but I'll do that later.) At last I got rid of the hack called get_status_string(). And now Yahoo seems to mess up away messages... --- irc_commands.c | 2 +- protocols/jabber/iq.c | 2 +- protocols/jabber/presence.c | 15 +++++-- protocols/msn/msn.c | 11 ----- protocols/msn/ns.c | 8 ++-- protocols/nogaim.c | 57 ++++++++++++++----------- protocols/nogaim.h | 24 +++++------ protocols/oscar/oscar.c | 79 +++++++++------------------------- protocols/yahoo/yahoo.c | 101 +++++++++++++++++++++++++------------------- 9 files changed, 140 insertions(+), 159 deletions(-) diff --git a/irc_commands.c b/irc_commands.c index 016b6f84..8d841aaa 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -262,7 +262,7 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd ) { irc->is_private = 1; } - irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 ); + irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 ); } } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 53be819e..46ae9a64 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -387,7 +387,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * /* Don't have any API call for this yet! So let's just try to handle this as well as we can. */ jabber_buddy_remove_bare( ic, jid ); - serv_got_update( ic, jid, 0, 0, 0, 0, 0, 0 ); + imcb_buddy_status( ic, jid, 0, NULL, NULL ); /* FIXME! */ } } diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 4007c84e..6bc8117f 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -37,6 +37,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( type == NULL ) { + int is_away = 0; + if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) @@ -51,7 +53,11 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) bud->away_message = NULL; if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) + { bud->away_state = (void*) jabber_away_state_by_code( c->text ); + if( strcmp( c->text, "chat" ) != 0 ) + is_away = OPT_AWAY; + } else { bud->away_state = NULL; @@ -65,8 +71,9 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; - serv_got_update( ic, bud->bare_jid, 1, 0, 0, 0, - bud->away_state ? UC_UNAVAILABLE : 0, 0 ); + /* FIXME: What to send if there are other resources??? */ + imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, + bud->away_state->full_name, bud->away_message ); } else if( strcmp( type, "unavailable" ) == 0 ) { @@ -86,13 +93,13 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* Only count this as offline if there's no other resource available anymore. */ if( jabber_buddy_by_jid( ic, from, 0 ) == NULL ) - serv_got_update( ic, from, 0, 0, 0, 0, 0, 0 ); + imcb_buddy_status( ic, from, 0, NULL, NULL ); *s = '/'; } else { - serv_got_update( ic, from, 0, 0, 0, 0, 0, 0 ); + imcb_buddy_status( ic, from, 0, NULL, NULL ); } } else if( strcmp( type, "subscribe" ) == 0 ) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 676a8ad7..5eea68af 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -191,16 +191,6 @@ static GList *msn_away_states( struct im_connection *ic ) return l; } -static char *msn_get_status_string( struct im_connection *ic, int number ) -{ - const struct msn_away_state *st = msn_away_state_by_number( number ); - - if( st ) - return( (char*) st->name ); - else - return( "" ); -} - static void msn_set_away( struct im_connection *ic, char *state, char *message ) { char buf[1024]; @@ -398,7 +388,6 @@ void msn_initmodule() ret->logout = msn_logout; ret->send_im = msn_send_im; ret->away_states = msn_away_states; - ret->get_status_string = msn_get_status_string; ret->set_away = msn_set_away; ret->get_info = msn_get_info; ret->set_my_name = msn_set_my_name; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index ba428d82..c80fc177 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -399,12 +399,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) st = msn_away_state_list; } - serv_got_update( ic, cmd[3], 1, 0, 0, 0, st->number, 0 ); + imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | + ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); } else if( strcmp( cmd[0], "FLN" ) == 0 ) { if( cmd[1] ) - serv_got_update( ic, cmd[1], 0, 0, 0, 0, 0, 0 ); + imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); } else if( strcmp( cmd[0], "NLN" ) == 0 ) { @@ -427,7 +428,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) st = msn_away_state_list; } - serv_got_update( ic, cmd[2], 1, 0, 0, 0, st->number, 0 ); + imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | + ( st->number ? OPT_AWAY : 0 ), st->name, NULL ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 6121d398..ef30f749 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -186,7 +186,7 @@ static void serv_got_crap( struct im_connection *ic, char *format, ... ) va_end( params ); if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) + ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( text ); /* Try to find a different connection on the same protocol. */ @@ -493,32 +493,31 @@ void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname /* server.c */ -void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ) +void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ) { user_t *u; int oa, oo; - u = user_findhandle( ic, handle ); + u = user_findhandle( ic, (char*) handle ); if( !u ) { if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 ) { - add_buddy( ic, NULL, handle, NULL ); - u = user_findhandle( ic, handle ); + add_buddy( ic, NULL, (char*) handle, NULL ); + u = user_findhandle( ic, (char*) handle ); } else { if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 ) { - imcb_log( ic, "serv_got_update() for handle %s:", handle ); - imcb_log( ic, "loggedin = %d, type = %d", loggedin, type ); + imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle ); + imcb_log( ic, "flags = %d, state = %s, message = %s", flags, + state ? state : "NULL", message ? message : "NULL" ); } return; } - /* Why did we have this here.... - return; */ } oa = u->away != NULL; @@ -530,12 +529,12 @@ void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int u->away = NULL; } - if( loggedin && !u->online ) + if( ( flags & OPT_LOGGED_IN ) && !u->online ) { irc_spawn( ic->irc, u ); u->online = 1; } - else if( !loggedin && u->online ) + else if( !( flags & OPT_LOGGED_IN ) && u->online ) { struct groupchat *c; @@ -544,19 +543,29 @@ void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */ for( c = ic->conversations; c; c = c->next ) - remove_chat_buddy_silent( c, handle ); + remove_chat_buddy_silent( c, (char*) handle ); } - if( ( type & UC_UNAVAILABLE ) && ( strcmp( ic->acc->prpl->name, "oscar" ) == 0 || strcmp( ic->acc->prpl->name, "icq" ) == 0 ) ) - { - u->away = g_strdup( "Away" ); - } - else if( ( type & UC_UNAVAILABLE ) && ic->acc->prpl->get_status_string ) + if( flags & OPT_AWAY ) { - u->away = g_strdup( ic->acc->prpl->get_status_string( ic, type ) ); + if( state && message ) + { + u->away = g_strdup_printf( "%s (%s)", state, message ); + } + else if( state ) + { + u->away = g_strdup( state ); + } + else if( message ) + { + u->away = g_strdup( message ); + } + else + { + u->away = g_strdup( "Away" ); + } } - else - u->away = NULL; + /* else waste_any_state_information_for_now(); */ /* LISPy... */ if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) && /* Don't do a thing when user doesn't want it */ @@ -611,7 +620,7 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla } if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) + ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); while( strlen( msg ) > 425 ) @@ -717,7 +726,7 @@ void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, t u = user_findhandle( ic, who ); if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || - ( ( ic->flags & OPT_CONN_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) + ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); if( c && u ) @@ -924,7 +933,7 @@ int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags char *buf = NULL; int st; - if( ( ic->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) + if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { buf = escape_html( msg ); msg = buf; @@ -940,7 +949,7 @@ int imc_chat_msg( struct groupchat *c, char *msg, int flags ) { char *buf = NULL; - if( ( c->ic->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) + if( ( c->ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) { buf = escape_html( msg ); msg = buf; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index cc2dcea4..62d8db41 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -5,7 +5,8 @@ \********************************************************************/ /* - * nogaim + * nogaim, soon to be known as im_api. Not a separate product (unless + * someone would be interested in such a thing), just a new name. * * Gaim without gaim - for BitlBee * @@ -14,7 +15,7 @@ * * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * (and possibly other members of the Gaim team) - * Copyright 2002-2004 Wilmer van der Gaast <wilmer@gaast.net> + * Copyright 2002-2007 Wilmer van der Gaast <wilmer@gaast.net> */ /* @@ -43,7 +44,6 @@ #include "md5.h" #include "sha.h" - #define BUF_LEN MSG_LEN #define BUF_LONG ( BUF_LEN * 2 ) #define MSG_LEN 2048 @@ -53,18 +53,19 @@ #define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */ #define WEBSITE "http://www.bitlbee.org/" -#define IM_FLAG_AWAY 0x0020 #define GAIM_AWAY_CUSTOM "Custom" -#define OPT_CONN_HTML 0x00000001 -#define OPT_LOGGED_IN 0x00010000 -#define OPT_LOGGING_OUT 0x00020000 +/* Sharing flags between buddies and connections. Or planning to, at least... */ +#define OPT_LOGGED_IN 0x00000001 +#define OPT_LOGGING_OUT 0x00000002 +#define OPT_AWAY 0x00000004 +#define OPT_DOES_HTML 0x00000010 /* ok. now the fun begins. first we create a connection structure */ struct im_connection { account_t *acc; - guint32 flags; + u_int32_t flags; /* each connection then can have its own protocol-specific data */ void *proto_data; @@ -163,9 +164,6 @@ struct prpl { struct groupchat * (* chat_join) (struct im_connection *, char *chat, char *nick, char *password); - /* DIE! */ - char *(* get_status_string) (struct im_connection *ic, int stat); - GList *(* away_states)(struct im_connection *ic); /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ @@ -200,7 +198,6 @@ G_MODULE_EXPORT struct groupchat *serv_got_joined_chat( struct im_connection *ic G_MODULE_EXPORT void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ); G_MODULE_EXPORT void serv_got_chat_left( struct groupchat *c ); struct groupchat *chat_by_channel( char *channel ); -struct groupchat *chat_by_id( int id ); /* Buddy management */ G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ); @@ -208,7 +205,8 @@ G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ); /* Buddy activity */ -G_MODULE_EXPORT void serv_got_update( struct im_connection *ic, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps ); +G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); +/* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); G_MODULE_EXPORT void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); G_MODULE_EXPORT void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 99f839e4..d05868b0 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -364,7 +364,7 @@ static void oscar_login(account_t *acc) { Not touching this anymore now that it belongs to account_t! Let's hope nothing will break. ;-) */ } else { - ic->flags |= OPT_CONN_HTML; + ic->flags |= OPT_DOES_HTML; } sess = g_new0(aim_session_t, 1); @@ -967,45 +967,35 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { struct oscar_data *od = ic->proto_data; aim_userinfo_t *info; time_t time_idle = 0, signon = 0; - int type = 0; - int caps = 0; - char *tmp; + int flags = OPT_LOGGED_IN; + char *tmp, *state_string = NULL; va_list ap; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); va_end(ap); - if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES) - caps = info->capabilities; - if (info->flags & AIM_FLAG_ACTIVEBUDDY) - type |= UC_AB; - if ((!od->icq) && (info->present & AIM_USERINFO_PRESENT_FLAGS)) { - if (info->flags & AIM_FLAG_UNCONFIRMED) - type |= UC_UNCONFIRMED; - if (info->flags & AIM_FLAG_ADMINISTRATOR) - type |= UC_ADMIN; - if (info->flags & AIM_FLAG_AOL) - type |= UC_AOL; - if (info->flags & AIM_FLAG_FREE) - type |= UC_NORMAL; if (info->flags & AIM_FLAG_AWAY) - type |= UC_UNAVAILABLE; - if (info->flags & AIM_FLAG_WIRELESS) - type |= UC_WIRELESS; + flags |= OPT_AWAY; } + if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) { - type = (info->icqinfo.status << 7); if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) && (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) { - type |= UC_UNAVAILABLE; + flags |= OPT_AWAY; } + + if( info->icqinfo.status & AIM_ICQ_STATE_DND ) + state_string = "Do Not Disturb"; + else if( info->icqinfo.status & AIM_ICQ_STATE_OUT ) + state_string = "Not Available"; + else if( info->icqinfo.status & AIM_ICQ_STATE_BUSY ) + state_string = "Occupied"; + else if( info->icqinfo.status & AIM_ICQ_STATE_INVISIBLE ) + state_string = "Invisible"; } - if (caps & AIM_CAPS_ICQ) - caps ^= AIM_CAPS_ICQ; - if (info->present & AIM_USERINFO_PRESENT_IDLE) { time(&time_idle); time_idle -= info->idletime*60; @@ -1019,8 +1009,8 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); g_free(tmp); - serv_got_update(ic, info->sn, 1, info->warnlevel/10, signon, - time_idle, type, caps); + imcb_buddy_status(ic, info->sn, flags, state_string, NULL); + /* imcb_buddy_times(ic, info->sn, signon, time_idle); */ return 1; } @@ -1034,7 +1024,7 @@ static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) { info = va_arg(ap, aim_userinfo_t *); va_end(ap); - serv_got_update(ic, info->sn, 0, 0, 0, 0, 0, 0); + imcb_buddy_status(ic, info->sn, 0, NULL, NULL ); return 1; } @@ -1045,7 +1035,7 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ int flags = 0; if (args->icbmflags & AIM_IMFLAGS_AWAY) - flags |= IM_FLAG_AWAY; + flags |= OPT_AWAY; if ((args->icbmflags & AIM_IMFLAGS_UNICODE) || (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)) { char *src; @@ -1820,7 +1810,7 @@ static void oscar_keepalive(struct im_connection *ic) { static int oscar_send_im(struct im_connection *ic, char *name, char *message, int imflags) { struct oscar_data *odata = (struct oscar_data *)ic->proto_data; int ret = 0, len = strlen(message); - if (imflags & IM_FLAG_AWAY) { + if (imflags & OPT_AWAY) { ret = aim_send_im(odata->sess, name, AIM_IMFLAGS_AWAY, message); } else { struct aim_sendimext_args args; @@ -2444,34 +2434,6 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) return 1; } -static char *oscar_get_status_string( struct im_connection *ic, int number ) -{ - struct oscar_data *od = ic->proto_data; - - if( ! number & UC_UNAVAILABLE ) - { - return( NULL ); - } - else if( od->icq ) - { - number >>= 7; - if( number & AIM_ICQ_STATE_DND ) - return( "Do Not Disturb" ); - else if( number & AIM_ICQ_STATE_OUT ) - return( "Not Available" ); - else if( number & AIM_ICQ_STATE_BUSY ) - return( "Occupied" ); - else if( number & AIM_ICQ_STATE_INVISIBLE ) - return( "Invisible" ); - else - return( "Away" ); - } - else - { - return( "Away" ); - } -} - int oscar_send_typing(struct im_connection *ic, char * who, int typing) { struct oscar_data *od = ic->proto_data; @@ -2632,7 +2594,6 @@ void oscar_initmodule() ret->rem_permit = oscar_rem_permit; ret->rem_deny = oscar_rem_deny; ret->set_permit_deny = oscar_set_permit_deny; - ret->get_status_string = oscar_get_status_string; ret->send_typing = oscar_send_typing; ret->handle_cmp = aim_sncmp; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index e380d0ae..dec42bdc 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -292,45 +292,6 @@ static void byahoo_remove_buddy( struct im_connection *ic, char *who, char *grou } } -static char *byahoo_get_status_string( struct im_connection *ic, int stat ) -{ - enum yahoo_status a = stat >> 1; - - 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 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_CUSTOM: - return "Away"; - case YAHOO_STATUS_IDLE: - return "Idle"; - case YAHOO_STATUS_OFFLINE: - return "Offline"; - case YAHOO_STATUS_NOTIFY: - return "Notify"; - default: - return "Away"; - } -} - static void byahoo_chat_send( struct groupchat *c, char *message, int flags ) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; @@ -392,7 +353,6 @@ void byahoo_initmodule( ) ret->set_away = byahoo_set_away; ret->add_buddy = byahoo_add_buddy; ret->remove_buddy = byahoo_remove_buddy; - ret->get_status_string = byahoo_get_status_string; ret->send_typing = byahoo_send_typing; ret->chat_send = byahoo_chat_send; @@ -585,10 +545,65 @@ void ext_yahoo_got_cookies( int id ) void ext_yahoo_status_changed( int id, char *who, int stat, char *msg, int away ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); + char *state_string = NULL; + int flags = OPT_LOGGED_IN; + + if( away ) + flags |= OPT_AWAY; + + switch (stat) + { + case YAHOO_STATUS_BRB: + state_string = "Be Right Back"; + break; + case YAHOO_STATUS_BUSY: + state_string = "Busy"; + break; + case YAHOO_STATUS_NOTATHOME: + state_string = "Not At Home"; + break; + case YAHOO_STATUS_NOTATDESK: + state_string = "Not At Desk"; + break; + case YAHOO_STATUS_NOTINOFFICE: + state_string = "Not In Office"; + break; + case YAHOO_STATUS_ONPHONE: + state_string = "On Phone"; + break; + case YAHOO_STATUS_ONVACATION: + state_string = "On Vacation"; + break; + case YAHOO_STATUS_OUTTOLUNCH: + state_string = "Out To Lunch"; + break; + case YAHOO_STATUS_STEPPEDOUT: + state_string = "Stepped Out"; + break; + case YAHOO_STATUS_INVISIBLE: + state_string = "Invisible"; + break; + case YAHOO_STATUS_CUSTOM: + state_string = "Away"; + break; + case YAHOO_STATUS_IDLE: + state_string = "Idle"; + break; + case YAHOO_STATUS_OFFLINE: + state_string = "Offline"; + flags = 0; + break; + case YAHOO_STATUS_NOTIFY: + state_string = "Notify"; + break; + } + + imcb_buddy_status( ic, who, flags, state_string, msg ); - serv_got_update( ic, who, stat != YAHOO_STATUS_OFFLINE, 0, 0, - ( stat == YAHOO_STATUS_IDLE ) ? away : 0, - ( stat != YAHOO_STATUS_AVAILABLE ) | ( stat << 1 ), 0 ); + /* Not implemented yet... + if( stat == YAHOO_STATUS_IDLE ) + imcb_buddy_times( ic, who, 0, away ); + */ } void ext_yahoo_got_im( int id, char *who, char *msg, long tm, int stat, int utf8 ) -- cgit v1.2.3 From cfc8d58f4c15048e943800272017f69804bb61b7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 21:31:52 -0700 Subject: Updating the Yahoo! module. This seems to fix handling of incoming away states/messages, should fix some issues with group chats, and unfortunately also adds some crap which I don't want to clean up for now. --- protocols/yahoo/libyahoo2.c | 571 ++++++++++++++++++++++++++++++++----- protocols/yahoo/yahoo.c | 102 ++++--- protocols/yahoo/yahoo2.h | 7 +- protocols/yahoo/yahoo2_callbacks.h | 229 +++++++-------- protocols/yahoo/yahoo2_types.h | 15 +- protocols/yahoo/yahoo_util.c | 14 +- 6 files changed, 696 insertions(+), 242 deletions(-) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 69b63baa..38041ad4 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -104,6 +104,8 @@ void yahoo_register_callbacks(struct yahoo_callbacks * tyc) #define YAHOO_CALLBACK(x) x #endif +static int yahoo_send_data(int fd, void *data, int len); + int yahoo_log_message(char * fmt, ...) { char out[1024]; @@ -203,7 +205,12 @@ enum yahoo_service { /* these are easier to see in hex */ YAHOO_SERVICE_CHATEXIT = 0x9b, YAHOO_SERVICE_CHATLOGOUT = 0xa0, YAHOO_SERVICE_CHATPING, - YAHOO_SERVICE_COMMENT = 0xa8 + YAHOO_SERVICE_COMMENT = 0xa8, + YAHOO_SERVICE_STEALTH = 0xb9, + YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd, + YAHOO_SERVICE_PICTURE = 0xbe, + YAHOO_SERVICE_PICTURE_UPDATE = 0xc1, + YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2 }; struct yahoo_pair { @@ -740,6 +747,9 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet yahoo_packet_dump(data, len); + if( yid->type == YAHOO_CONNECTION_FT ) + yahoo_send_data(yid->fd, data, len); + else yahoo_add_to_send_queue(yid, data, len); FREE(data); } @@ -925,6 +935,7 @@ static void yahoo_process_notify(struct yahoo_input_data *yid, struct yahoo_pack struct yahoo_data *yd = yid->yd; char *msg = NULL; char *from = NULL; + char *to = NULL; int stat = 0; int accept = 0; char *ind = NULL; @@ -933,6 +944,8 @@ static void yahoo_process_notify(struct yahoo_input_data *yid, struct yahoo_pack struct yahoo_pair *pair = l->data; if (pair->key == 4) from = pair->value; + if (pair->key == 5) + to = pair->value; if (pair->key == 49) msg = pair->value; if (pair->key == 13) @@ -950,19 +963,19 @@ static void yahoo_process_notify(struct yahoo_input_data *yid, struct yahoo_pack return; if (!strncasecmp(msg, "TYPING", strlen("TYPING"))) - YAHOO_CALLBACK(ext_yahoo_typing_notify)(yd->client_id, from, stat); + YAHOO_CALLBACK(ext_yahoo_typing_notify)(yd->client_id, to, from, stat); else if (!strncasecmp(msg, "GAME", strlen("GAME"))) - YAHOO_CALLBACK(ext_yahoo_game_notify)(yd->client_id, from, stat); + YAHOO_CALLBACK(ext_yahoo_game_notify)(yd->client_id, to, from, stat); else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { if (!strcmp(ind, " ")) { - YAHOO_CALLBACK(ext_yahoo_webcam_invite)(yd->client_id, from); + YAHOO_CALLBACK(ext_yahoo_webcam_invite)(yd->client_id, to, from); } else { accept = atoi(ind); /* accept the invitation (-1 = deny 1 = accept) */ if (accept < 0) accept = 0; - YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply)(yd->client_id, from, accept); + YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply)(yd->client_id, to, from, accept); } } else @@ -1021,7 +1034,7 @@ static void yahoo_process_filetransfer(struct yahoo_input_data *yid, struct yaho *tmp = '\0'; } if(url && from) - YAHOO_CALLBACK(ext_yahoo_got_file)(yd->client_id, from, url, expires, msg, filename, filesize); + YAHOO_CALLBACK(ext_yahoo_got_file)(yd->client_id, to, from, url, expires, msg, filename, filesize); } @@ -1095,31 +1108,31 @@ static void yahoo_process_conference(struct yahoo_input_data *yid, struct yahoo_ if(pkt->status == 2) ; else if(members) - YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members); + YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, id, host, room, msg, members); else if(msg) - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, msg, 0); + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, msg, 0, E_CONFNOTAVAIL); break; case YAHOO_SERVICE_CONFADDINVITE: if(pkt->status == 2) ; else - YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members); + YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, id, host, room, msg, members); break; case YAHOO_SERVICE_CONFDECLINE: if(who) - YAHOO_CALLBACK(ext_yahoo_conf_userdecline)(yd->client_id, who, room, msg); + YAHOO_CALLBACK(ext_yahoo_conf_userdecline)(yd->client_id, id, who, room, msg); break; case YAHOO_SERVICE_CONFLOGON: if(who) - YAHOO_CALLBACK(ext_yahoo_conf_userjoin)(yd->client_id, who, room); + YAHOO_CALLBACK(ext_yahoo_conf_userjoin)(yd->client_id, id, who, room); break; case YAHOO_SERVICE_CONFLOGOFF: if(who) - YAHOO_CALLBACK(ext_yahoo_conf_userleave)(yd->client_id, who, room); + YAHOO_CALLBACK(ext_yahoo_conf_userleave)(yd->client_id, id, who, room); break; case YAHOO_SERVICE_CONFMSG: if(who) - YAHOO_CALLBACK(ext_yahoo_conf_message)(yd->client_id, who, room, msg, utf8); + YAHOO_CALLBACK(ext_yahoo_conf_message)(yd->client_id, id, who, room, msg, utf8); break; } } @@ -1127,6 +1140,7 @@ static void yahoo_process_conference(struct yahoo_input_data *yid, struct yahoo_ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet *pkt) { char *msg = NULL; + char *id = NULL; char *who = NULL; char *room = NULL; char *topic = NULL; @@ -1143,6 +1157,11 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; + if (pair->key == 1) { + /* My identity */ + id = pair->value; + } + if (pair->key == 104) { /* Room name */ room = pair->value; @@ -1217,12 +1236,12 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet if(!room) { if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */ - YAHOO_CALLBACK(ext_yahoo_chat_yahoologout)(yid->yd->client_id); + YAHOO_CALLBACK(ext_yahoo_chat_yahoologout)(yid->yd->client_id, id); return ; } if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr) { - YAHOO_CALLBACK(ext_yahoo_chat_yahooerror)(yid->yd->client_id); - return ; + YAHOO_CALLBACK(ext_yahoo_chat_yahooerror)(yid->yd->client_id, id); + return; } WARNING(("We didn't get a room name, ignoring packet")); @@ -1235,7 +1254,7 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet WARNING(("Count of members doesn't match No. of members we got")); } if(firstjoin && members) { - YAHOO_CALLBACK(ext_yahoo_chat_join)(yid->yd->client_id, room, topic, members, yid->fd); + YAHOO_CALLBACK(ext_yahoo_chat_join)(yid->yd->client_id, id, room, topic, members, yid->fd); } else if(who) { if(y_list_length(members) != 1) { WARNING(("Got more than 1 member on a normal join")); @@ -1244,7 +1263,7 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet while(members) { YList *n = members->next; currentmember = members->data; - YAHOO_CALLBACK(ext_yahoo_chat_userjoin)(yid->yd->client_id, room, currentmember); + YAHOO_CALLBACK(ext_yahoo_chat_userjoin)(yid->yd->client_id, id, room, currentmember); y_list_free_1(members); members=n; } @@ -1252,12 +1271,12 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet break; case YAHOO_SERVICE_CHATEXIT: if(who) { - YAHOO_CALLBACK(ext_yahoo_chat_userleave)(yid->yd->client_id, room, who); + YAHOO_CALLBACK(ext_yahoo_chat_userleave)(yid->yd->client_id, id, room, who); } break; case YAHOO_SERVICE_COMMENT: if(who) { - YAHOO_CALLBACK(ext_yahoo_chat_message)(yid->yd->client_id, who, room, msg, msgtype, utf8); + YAHOO_CALLBACK(ext_yahoo_chat_message)(yid->yd->client_id, id, who, room, msg, msgtype, utf8); } break; } @@ -1316,9 +1335,9 @@ static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_pac if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) { YAHOO_CALLBACK(ext_yahoo_system_message)(yd->client_id, message->msg); } else if (pkt->status <= 2 || pkt->status == 5) { - YAHOO_CALLBACK(ext_yahoo_got_im)(yd->client_id, message->from, message->msg, message->tm, pkt->status, message->utf8); + YAHOO_CALLBACK(ext_yahoo_got_im)(yd->client_id, message->to, message->from, message->msg, message->tm, pkt->status, message->utf8); } else if (pkt->status == 0xffffffff) { - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, message->msg, 0); + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, message->msg, 0, E_SYSTEM); } free(message); } @@ -1331,13 +1350,32 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack { YList *l; struct yahoo_data *yd = yid->yd; - char *name = NULL; - int state = 0; - int away = 0; - int idle = 0; - char *msg = NULL; + + struct user + { + char *name; /* 7 name */ + int state; /* 10 state */ + int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ + int mobile; /* 60 mobile */ + char *msg; /* 19 custom status message */ + int away; /* 47 away (or invisible)*/ + int buddy_session; /* 11 state */ + int f17; /* 17 in chat? then what about flags? */ + int idle; /* 137 seconds idle */ + int f138; /* 138 state */ + char *f184; /* 184 state */ + int f192; /* 192 state */ + int f10001; /* 10001 state */ + int f10002; /* 10002 state */ + int f198; /* 198 state */ + char *f197; /* 197 state */ + char *f205; /* 205 state */ + int f213; /* 213 state */ + } *u; + + YList *users = 0; - if(pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { + if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL); return; } @@ -1361,51 +1399,87 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack NOTICE(("key %d:%s", pair->key, pair->value)); break; case 7: /* the current buddy */ - name = pair->value; + u = y_new0(struct user, 1); + u->name = pair->value; + users = y_list_prepend(users, u); break; case 10: /* state */ - state = strtol(pair->value, NULL, 10); + ((struct user*)users->data)->state = strtol(pair->value, NULL, 10); break; case 19: /* custom status message */ - msg = pair->value; + ((struct user*)users->data)->msg = pair->value; break; case 47: /* is it an away message or not */ - away = atoi(pair->value); + ((struct user*)users->data)->away = atoi(pair->value); break; case 137: /* seconds idle */ - idle = atoi(pair->value); + ((struct user*)users->data)->idle = atoi(pair->value); break; - case 11: /* what is this? */ - NOTICE(("key %d:%s", pair->key, pair->value)); + case 11: /* this is the buddy's session id */ + ((struct user*)users->data)->buddy_session = atoi(pair->value); break; case 17: /* in chat? */ + ((struct user*)users->data)->f17 = atoi(pair->value); break; - case 13: /* in pager? */ - if (pkt->service == YAHOO_SERVICE_LOGOFF || strtol(pair->value, NULL, 10) == 0) { - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, YAHOO_STATUS_OFFLINE, NULL, 1); - break; - } - if (state == YAHOO_STATUS_AVAILABLE) { - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, NULL, 0); - } else if (state == YAHOO_STATUS_CUSTOM) { - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away); - } else { - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, NULL, idle); - } - + case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ + ((struct user*)users->data)->flags = atoi(pair->value); break; - case 60: + case 60: /* SMS -> 1 MOBILE USER */ /* sometimes going offline makes this 2, but invisible never sends it */ - NOTICE(("key %d:%s", pair->key, pair->value)); - break; + ((struct user*)users->data)->mobile = atoi(pair->value); + break; + case 138: + ((struct user*)users->data)->f138 = atoi(pair->value); + break; + case 184: + ((struct user*)users->data)->f184 = pair->value; + break; + case 192: + ((struct user*)users->data)->f192 = atoi(pair->value); + break; + case 10001: + ((struct user*)users->data)->f10001 = atoi(pair->value); + break; + case 10002: + ((struct user*)users->data)->f10002 = atoi(pair->value); + break; + case 198: + ((struct user*)users->data)->f198 = atoi(pair->value); + break; + case 197: + ((struct user*)users->data)->f197 = pair->value; + break; + case 205: + ((struct user*)users->data)->f205 = pair->value; + break; + case 213: + ((struct user*)users->data)->f213 = atoi(pair->value); + break; case 16: /* Custom error message */ - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0); + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM); break; default: WARNING(("unknown status key %d:%s", pair->key, pair->value)); break; } } + + while (users) { + YList *t = users; + struct user *u = users->data; + + if (u->name != NULL) { + if (pkt->service == YAHOO_SERVICE_LOGOFF || u->flags == 0) { + YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); + } else { + YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile); + } + } + + users = y_list_remove_link(users, users); + y_list_free_1(t); + FREE(u); + } } static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) @@ -1511,6 +1585,113 @@ static void yahoo_process_verify(struct yahoo_input_data *yid, struct yahoo_pack } +static void yahoo_process_picture_checksum( struct yahoo_input_data *yid, struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *from = NULL; + char *to = NULL; + int checksum = 0; + YList *l; + + for(l = pkt->hash; l; l = l->next) + { + struct yahoo_pair *pair = l->data; + + switch(pair->key) + { + case 1: + case 4: + from = pair->value; + case 5: + to = pair->value; + break; + case 212: + break; + case 192: + checksum = atoi( pair->value ); + break; + } + } + + YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum)(yd->client_id,to,from,checksum); +} + +static void yahoo_process_picture(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + char *url = NULL; + char *from = NULL; + char *to = NULL; + int status = 0; + int checksum = 0; + YList *l; + + for(l = pkt->hash; l; l = l->next) + { + struct yahoo_pair *pair = l->data; + + switch(pair->key) + { + case 1: + case 4: /* sender */ + from = pair->value; + break; + case 5: /* we */ + to = pair->value; + break; + case 13: /* request / sending */ + status = atoi( pair->value ); + break; + case 20: /* url */ + url = pair->value; + break; + case 192: /*checksum */ + checksum = atoi( pair->value ); + break; + } + } + + switch( status ) + { + case 1: /* this is a request, ignore for now */ + YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request)(yd->client_id, to, from); + break; + case 2: /* this is cool - we get a picture :) */ + YAHOO_CALLBACK(ext_yahoo_got_buddyicon)(yd->client_id,to, from, url, checksum); + break; + } +} + +static void yahoo_process_picture_upload(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +{ + struct yahoo_data *yd = yid->yd; + YList *l; + char *url = NULL; + + if ( pkt->status != 1 ) + return; /* something went wrong */ + + for(l = pkt->hash; l; l = l->next) + { + struct yahoo_pair *pair = l->data; + + switch(pair->key) + { + case 5: /* we */ + break; + case 20: /* url */ + url = pair->value; + break; + case 27: /* local filename */ + break; + case 38: /* time */ + break; + } + } + + YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded)(yd->client_id, url); +} + static void yahoo_process_auth_pre_0x0b(struct yahoo_input_data *yid, const char *seed, const char *sn) { @@ -2153,6 +2334,8 @@ static void yahoo_process_contact(struct yahoo_input_data *yid, struct yahoo_pac int state = YAHOO_STATUS_AVAILABLE; int online = FALSE; int away = 0; + int idle = 0; + int mobile = 0; YList *l; @@ -2174,12 +2357,17 @@ static void yahoo_process_contact(struct yahoo_input_data *yid, struct yahoo_pac online = strtol(pair->value, NULL, 10); else if (pair->key == 47) away = strtol(pair->value, NULL, 10); + else if (pair->key == 137) + idle = strtol(pair->value, NULL, 10); + else if (pair->key == 60) + mobile = strtol(pair->value, NULL, 10); + } if (id) YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, id, who, msg); else if (name) - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away); + YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away, idle, mobile); else if(pkt->status == 0x07) YAHOO_CALLBACK(ext_yahoo_rejected)(yd->client_id, who, msg); } @@ -2307,7 +2495,7 @@ static void yahoo_process_ignore(struct yahoo_input_data *yid, struct yahoo_pack */ /* if(status) - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, status, who, 0); + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status); */ } @@ -2331,7 +2519,7 @@ static void yahoo_process_voicechat(struct yahoo_input_data *yid, struct yahoo_p room=pair->value; } - NOTICE(("got voice chat invite from %s in %s", who, room)); + NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, me)); /* * send: s:0 1:me 5:who 57:room 13:1 * ???? s:4 5:who 10:99 19:-1615114531 @@ -2343,6 +2531,21 @@ static void yahoo_process_voicechat(struct yahoo_input_data *yid, struct yahoo_p */ } +static void yahoo_process_ping(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +{ + char *errormsg = NULL; + + YList *l; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + if (pair->key == 16) + errormsg = pair->value; + } + + NOTICE(("got ping packet")); + YAHOO_CALLBACK(ext_yahoo_got_ping)(yid->yd->client_id, errormsg); +} + static void _yahoo_webcam_get_server_connected(int fd, int error, void *d) { struct yahoo_input_data *yid = d; @@ -2518,6 +2721,9 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack case YAHOO_SERVICE_WEBCAM: yahoo_process_webcam_key(yid, pkt); break; + case YAHOO_SERVICE_PING: + yahoo_process_ping(yid, pkt); + break; case YAHOO_SERVICE_IDLE: case YAHOO_SERVICE_MAILSTAT: case YAHOO_SERVICE_CHATINVITE: @@ -2525,7 +2731,6 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack case YAHOO_SERVICE_NEWPERSONALMAIL: case YAHOO_SERVICE_ADDIDENT: case YAHOO_SERVICE_ADDIGNORE: - case YAHOO_SERVICE_PING: case YAHOO_SERVICE_GOTGROUPRENAME: case YAHOO_SERVICE_GROUPRENAME: case YAHOO_SERVICE_PASSTHROUGH2: @@ -2537,6 +2742,15 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack WARNING(("unhandled service 0x%02x", pkt->service)); yahoo_dump_unhandled(pkt); break; + case YAHOO_SERVICE_PICTURE: + yahoo_process_picture(yid, pkt); + break; + case YAHOO_SERVICE_PICTURE_CHECKSUM: + yahoo_process_picture_checksum(yid, pkt); + break; + case YAHOO_SERVICE_PICTURE_UPLOAD: + yahoo_process_picture_upload(yid, pkt); + break; default: WARNING(("unknown service 0x%02x", pkt->service)); yahoo_dump_unhandled(pkt); @@ -3346,7 +3560,7 @@ int yahoo_read_ready(int id, int fd, void *data) DEBUG_MSG(("len == %d (<= 0)", len)); if(yid->type == YAHOO_CONNECTION_PAGER) { - YAHOO_CALLBACK(ext_yahoo_login_response)(yid->yd->client_id, YAHOO_LOGIN_SOCK, NULL); + YAHOO_CALLBACK(ext_yahoo_error)(yid->yd->client_id, "Connection closed by server", 1, E_CONNECTION); } yahoo_process_connection[yid->type](yid, 1); @@ -3494,11 +3708,12 @@ int yahoo_get_fd(int id) return yid->fd; } -void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8) +void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8, int picture) { struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_packet *pkt = NULL; struct yahoo_data *yd; + char pic_str[10]; if(!yid) return; @@ -3507,6 +3722,8 @@ void yahoo_send_im(int id, const char *from, const char *who, const char *what, pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id); + snprintf(pic_str, sizeof(pic_str), "%d", picture); + if(from && strcmp(from, yd->user)) yahoo_packet_hash(pkt, 0, yd->user); yahoo_packet_hash(pkt, 1, from?from:yd->user); @@ -3518,6 +3735,7 @@ void yahoo_send_im(int id, const char *from, const char *who, const char *what, yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */ yahoo_packet_hash(pkt, 64, "0"); + yahoo_packet_hash(pkt, 206, pic_str); yahoo_send_packet(yid, pkt, 0); @@ -3570,12 +3788,24 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) service = YAHOO_SERVICE_ISBACK; else service = YAHOO_SERVICE_ISAWAY; - pkt = yahoo_packet_new(service, yd->current_status, yd->session_id); - snprintf(s, sizeof(s), "%d", yd->current_status); - yahoo_packet_hash(pkt, 10, s); - if (yd->current_status == YAHOO_STATUS_CUSTOM) { - yahoo_packet_hash(pkt, 19, msg); - yahoo_packet_hash(pkt, 47, away?"1":"0"); + + if ((away == 2) && (yd->current_status == YAHOO_STATUS_AVAILABLE)) { + pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_BRB, yd->session_id); + yahoo_packet_hash(pkt, 10, "999"); + yahoo_packet_hash(pkt, 47, "2"); + }else { + pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id); + snprintf(s, sizeof(s), "%d", yd->current_status); + yahoo_packet_hash(pkt, 10, s); + if (yd->current_status == YAHOO_STATUS_CUSTOM) { + yahoo_packet_hash(pkt, 19, msg); + yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); + } else { + yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); + } + + + } yahoo_send_packet(yid, pkt, 0); @@ -3816,7 +4046,7 @@ void yahoo_chat_keepalive (int id) yahoo_packet_free (pkt); } -void yahoo_add_buddy(int id, const char *who, const char *group) +void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg) { struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; @@ -3833,6 +4063,8 @@ void yahoo_add_buddy(int id, const char *who, const char *group) yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 7, who); yahoo_packet_hash(pkt, 65, group); + if (msg != NULL) /* add message/request "it's me add me" */ + yahoo_packet_hash(pkt, 14, msg); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } @@ -3898,6 +4130,28 @@ void yahoo_ignore_buddy(int id, const char *who, int unignore) yahoo_packet_free(pkt); } +void yahoo_stealth_buddy(int id, const char *who, int unstealth) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if(!yid) + return; + yd = yid->yd; + + if (!yd->logged_in) + return; + + pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH, YAHOO_STATUS_AVAILABLE, yd->session_id); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 7, who); + yahoo_packet_hash(pkt, 31, unstealth?"2":"1"); + yahoo_packet_hash(pkt, 13, "2"); + yahoo_send_packet(yid, pkt, 0); + yahoo_packet_free(pkt); +} + void yahoo_change_buddy_group(int id, const char *who, const char *old_group, const char *new_group) { struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); @@ -4206,6 +4460,100 @@ void yahoo_chat_logoff(int id, const char *from) yahoo_packet_free(pkt); } +void yahoo_buddyicon_request(int id, const char *who) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + if( !yid ) + return; + + yd = yid->yd; + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 4, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 13, "1"); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_info(int id, const char *who, const char *url, int checksum) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char checksum_str[10]; + + if( !yid ) + return; + + yd = yid->yd; + + snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 4, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 13, "2"); + yahoo_packet_hash(pkt, 20, url); + yahoo_packet_hash(pkt, 192, checksum_str); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_update(int id, const char *who, int type) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char type_str[10]; + + if( !yid ) + return; + + yd = yid->yd; + + snprintf(type_str, sizeof(type_str), "%d", type); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 206, type_str); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + +void yahoo_send_picture_checksum(int id, const char *who, int checksum) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + struct yahoo_data *yd; + struct yahoo_packet *pkt; + char checksum_str[10]; + + if( !yid ) + return; + + yd = yid->yd; + + snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0); + yahoo_packet_hash(pkt, 1, yd->user); + if( who != 0 ) + yahoo_packet_hash(pkt, 5, who); + yahoo_packet_hash(pkt, 192, checksum_str); + yahoo_packet_hash(pkt, 212, "1"); + yahoo_send_packet(yid, pkt, 0); + + yahoo_packet_free(pkt); +} + void yahoo_webcam_close_feed(int id, const char *who) { struct yahoo_input_data *yid = find_input_by_id_and_webcam_user(id, who); @@ -4409,6 +4757,99 @@ struct send_file_data { void *user_data; }; +static void _yahoo_send_picture_connected(int id, int fd, int error, void *data) +{ + struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT); + struct send_file_data *sfd = data; + struct yahoo_packet *pkt = sfd->pkt; + unsigned char buff[1024]; + + if(fd <= 0) { + sfd->callback(id, fd, error, sfd->user_data); + FREE(sfd); + yahoo_packet_free(pkt); + inputs = y_list_remove(inputs, yid); + FREE(yid); + return; + } + + yid->fd = fd; + yahoo_send_packet(yid, pkt, 8); + yahoo_packet_free(pkt); + + snprintf((char *)buff, sizeof(buff), "29"); + buff[2] = 0xc0; + buff[3] = 0x80; + + write(yid->fd, buff, 4); + + /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */ + + sfd->callback(id, fd, error, sfd->user_data); + FREE(sfd); + inputs = y_list_remove(inputs, yid); + /* + while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) { + if(!strcmp(buff, "")) + break; +} + + */ + yahoo_input_close(yid); +} + +void yahoo_send_picture(int id, const char *name, unsigned long size, + yahoo_get_fd_callback callback, void *data) +{ + struct yahoo_data *yd = find_conn_by_id(id); + struct yahoo_input_data *yid; + struct yahoo_server_settings *yss; + struct yahoo_packet *pkt = NULL; + char size_str[10]; + char expire_str[10]; + long content_length=0; + unsigned char buff[1024]; + char url[255]; + struct send_file_data *sfd; + + if(!yd) + return; + + yss = yd->server_settings; + + yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; + yid->type = YAHOO_CONNECTION_FT; + + pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id); + + snprintf(size_str, sizeof(size_str), "%ld", size); + snprintf(expire_str, sizeof(expire_str), "%ld", (long)604800); + + yahoo_packet_hash(pkt, 0, yd->user); + yahoo_packet_hash(pkt, 1, yd->user); + yahoo_packet_hash(pkt, 14, ""); + yahoo_packet_hash(pkt, 27, name); + yahoo_packet_hash(pkt, 28, size_str); + yahoo_packet_hash(pkt, 38, expire_str); + + + content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt); + + snprintf(url, sizeof(url), "http://%s:%d/notifyft", + yss->filetransfer_host, yss->filetransfer_port); + snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s", + yd->cookie_y, yd->cookie_t); + inputs = y_list_prepend(inputs, yid); + + sfd = y_new0(struct send_file_data, 1); + sfd->pkt = pkt; + sfd->callback = callback; + sfd->user_data = data; + yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size, + _yahoo_send_picture_connected, sfd); +} + static void _yahoo_send_file_connected(int id, int fd, int error, void *data) { struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index dec42bdc..6f6590df 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -66,7 +66,7 @@ struct byahoo_conf_invitation static GSList *byahoo_inputs = NULL; static int byahoo_chat_id = 0; -static char *byahoo_strip( char *in ) +static char *byahoo_strip( const char *in ) { int len; @@ -85,7 +85,7 @@ static char *byahoo_strip( char *in ) } else if( strncmp( in, "\e[", 2 ) == 0 ) { - char *s; + const char *s; for( s = in + 2; *s && *s != 'm'; s ++ ); @@ -171,7 +171,7 @@ static int byahoo_send_im( struct im_connection *ic, char *who, char *what, int { struct byahoo_data *yd = ic->proto_data; - yahoo_send_im( yd->y2_id, NULL, who, what, 1 ); + yahoo_send_im( yd->y2_id, NULL, who, what, 1, 0 ); return 1; } @@ -239,7 +239,7 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg ) else yd->current_status = YAHOO_STATUS_AVAILABLE; - yahoo_set_away( yd->y2_id, yd->current_status, msg, ic->away != NULL ); + yahoo_set_away( yd->y2_id, yd->current_status, msg, ic->away != NULL ? 2 : 0 ); } static GList *byahoo_away_states( struct im_connection *ic ) @@ -273,7 +273,7 @@ static void byahoo_add_buddy( struct im_connection *ic, char *who, char *group ) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - yahoo_add_buddy( yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP ); + yahoo_add_buddy( yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP, NULL ); } static void byahoo_remove_buddy( struct im_connection *ic, char *who, char *group ) @@ -450,7 +450,7 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit return FALSE; } -void ext_yahoo_login_response( int id, int succ, char *url ) +void ext_yahoo_login_response( int id, int succ, const char *url ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); struct byahoo_data *yd = NULL; @@ -542,7 +542,7 @@ void ext_yahoo_got_cookies( int id ) { } -void ext_yahoo_status_changed( int id, char *who, int stat, char *msg, int away ) +void ext_yahoo_status_changed( int id, const char *who, int stat, const char *msg, int away, int idle, int mobile ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); char *state_string = NULL; @@ -606,50 +606,52 @@ void ext_yahoo_status_changed( int id, char *who, int stat, char *msg, int away */ } -void ext_yahoo_got_im( int id, char *who, char *msg, long tm, int stat, int utf8 ) +void ext_yahoo_got_im( int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8 ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); char *m = byahoo_strip( msg ); - serv_got_im( ic, who, m, 0, 0, strlen( m ) ); + serv_got_im( ic, (char*) who, (char*) m, 0, 0, strlen( m ) ); g_free( m ); } -void ext_yahoo_got_file( int id, char *who, char *url, long expires, char *msg, char *fname, unsigned long fesize ) +void ext_yahoo_got_file( int id, + const char *ignored, + const char *who, const char *url, long expires, const char *msg, const char *fname, unsigned long fesize ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); imcb_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); } -void ext_yahoo_typing_notify( int id, char *who, int stat ) +void ext_yahoo_typing_notify( int id, const char *ignored, const char *who, int stat ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); if (stat == 1) { /* User is typing */ - serv_got_typing( ic, who, 1, 1 ); + serv_got_typing( ic, (char*) who, 1, 1 ); } else { /* User stopped typing */ - serv_got_typing( ic, who, 1, 0 ); + serv_got_typing( ic, (char*) who, 1, 0 ); } } -void ext_yahoo_system_message( int id, char *msg ) +void ext_yahoo_system_message( int id, const char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); imcb_log( ic, "Yahoo! system message: %s", msg ); } -void ext_yahoo_webcam_invite( int id, char *from ) +void ext_yahoo_webcam_invite( int id, const char *ignored, const char *from ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); imcb_log( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); } -void ext_yahoo_error( int id, char *err, int fatal ) +void ext_yahoo_error( int id, const char *err, int fatal, int num ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); @@ -718,7 +720,7 @@ void ext_yahoo_remove_handler( int id, int tag ) b_event_remove( tag ); } -int ext_yahoo_connect_async( int id, char *host, int port, yahoo_connect_callback callback, void *data ) +int ext_yahoo_connect_async( int id, const char *host, int port, yahoo_connect_callback callback, void *data ) { struct byahoo_connect_callback_data *d; int fd; @@ -739,7 +741,7 @@ int ext_yahoo_connect_async( int id, char *host, int port, yahoo_connect_callbac /* Because we don't want asynchronous connects in BitlBee, and because libyahoo doesn't seem to use this one anyway, this one is now defunct. */ -int ext_yahoo_connect(char *host, int port) +int ext_yahoo_connect(const char *host, int port) { #if 0 struct sockaddr_in serv_addr; @@ -795,7 +797,8 @@ static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) g_free( inv ); } -void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList *members ) +void ext_yahoo_got_conf_invite( int id, const char *ignored, + const char *who, const char *room, const char *msg, YList *members ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); struct byahoo_conf_invitation *inv; @@ -805,7 +808,7 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList inv = g_malloc( sizeof( struct byahoo_conf_invitation ) ); memset( inv, 0, sizeof( struct byahoo_conf_invitation ) ); inv->name = g_strdup( room ); - inv->c = serv_got_joined_chat( ic, room ); + inv->c = serv_got_joined_chat( ic, (char*) room ); inv->c->data = members; inv->yid = id; inv->members = members; @@ -820,14 +823,14 @@ void ext_yahoo_got_conf_invite( int id, char *who, char *room, char *msg, YList imcb_ask( ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); } -void ext_yahoo_conf_userdecline( int id, char *who, char *room, char *msg ) +void ext_yahoo_conf_userdecline( int id, const char *ignored, const char *who, const char *room, const char *msg ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); imcb_log( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); } -void ext_yahoo_conf_userjoin( int id, char *who, char *room ) +void ext_yahoo_conf_userjoin( int id, const char *ignored, const char *who, const char *room ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); struct groupchat *c; @@ -835,10 +838,11 @@ void ext_yahoo_conf_userjoin( int id, char *who, char *room ) for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - add_chat_buddy( c, who ); + add_chat_buddy( c, (char*) who ); } -void ext_yahoo_conf_userleave( int id, char *who, char *room ) +void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, const char *room ) + { struct im_connection *ic = byahoo_get_ic_by_id( id ); struct groupchat *c; @@ -846,10 +850,10 @@ void ext_yahoo_conf_userleave( int id, char *who, char *room ) for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - remove_chat_buddy( c, who, "" ); + remove_chat_buddy( c, (char*) who, "" ); } -void ext_yahoo_conf_message( int id, char *who, char *room, char *msg, int utf8 ) +void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8 ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); char *m = byahoo_strip( msg ); @@ -858,51 +862,55 @@ void ext_yahoo_conf_message( int id, char *who, char *room, char *msg, int utf8 for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - serv_got_chat_in( c, who, 0, m, 0 ); + serv_got_chat_in( c, (char*) who, 0, (char*) m, 0 ); g_free( m ); } -void ext_yahoo_chat_cat_xml( int id, char *xml ) +void ext_yahoo_chat_cat_xml( int id, const char *xml ) { } -void ext_yahoo_chat_join( int id, char *room, char *topic, YList *members, int fd ) +void ext_yahoo_chat_join( int id, const char *who, const char *room, const char *topic, YList *members, int fd ) { } -void ext_yahoo_chat_userjoin( int id, char *room, struct yahoo_chat_member *who ) +void ext_yahoo_chat_userjoin( int id, const char *me, const char *room, struct yahoo_chat_member *who ) { + free(who->id); + free(who->alias); + free(who->location); + free(who); } -void ext_yahoo_chat_userleave( int id, char *room, char *who ) +void ext_yahoo_chat_userleave( int id, const char *me, const char *room, const char *who ) { } -void ext_yahoo_chat_message( int id, char *who, char *room, char *msg, int msgtype, int utf8 ) +void ext_yahoo_chat_message( int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, int utf8 ) { } -void ext_yahoo_chat_yahoologout( int id ) +void ext_yahoo_chat_yahoologout( int id, const char *me ) { } -void ext_yahoo_chat_yahooerror( int id ) +void ext_yahoo_chat_yahooerror( int id, const char *me ) { } -void ext_yahoo_contact_added( int id, char *myid, char *who, char *msg ) +void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg ) { } -void ext_yahoo_rejected( int id, char *who, char *msg ) +void ext_yahoo_rejected( int id, const char *who, const char *msg ) { } -void ext_yahoo_game_notify( int id, char *who, int stat ) +void ext_yahoo_game_notify( int id, const char *me, const char *who, int stat ) { } -void ext_yahoo_mail_notify( int id, char *from, char *subj, int cnt ) +void ext_yahoo_mail_notify( int id, const char *from, const char *subj, int cnt ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); @@ -912,11 +920,11 @@ void ext_yahoo_mail_notify( int id, char *from, char *subj, int cnt ) imcb_log( ic, "Received %d new e-mails", cnt ); } -void ext_yahoo_webcam_invite_reply( int id, char *from, int accept ) +void ext_yahoo_webcam_invite_reply( int id, const char *me, const char *from, int accept ) { } -void ext_yahoo_webcam_closed( int id, char *who, int reason ) +void ext_yahoo_webcam_closed( int id, const char *who, int reason ) { } @@ -924,7 +932,7 @@ void ext_yahoo_got_search_result( int id, int found, int start, int total, YList { } -void ext_yahoo_webcam_viewer( int id, char *who, int connect ) +void ext_yahoo_webcam_viewer( int id, const char *who, int connect ) { } @@ -932,7 +940,7 @@ void ext_yahoo_webcam_data_request( int id, int send ) { } -int ext_yahoo_log( char *fmt, ... ) +int ext_yahoo_log( const char *fmt, ... ) { return( 0 ); } @@ -940,3 +948,13 @@ int ext_yahoo_log( char *fmt, ... ) void ext_yahoo_got_webcam_image( int id, const char * who, const unsigned char *image, unsigned int image_size, unsigned int real_size, unsigned int timestamp ) { } + +void ext_yahoo_got_ping( int id, const char *msg) +{ +} + +void ext_yahoo_got_buddyicon (int id, const char *me, const char *who, const char *url, int checksum) {} +void ext_yahoo_got_buddyicon_checksum (int id, const char *me,const char *who, int checksum) {} + +void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who){} +void ext_yahoo_buddyicon_uploaded(int id, const char *url){} diff --git a/protocols/yahoo/yahoo2.h b/protocols/yahoo/yahoo2.h index 5ac5e4f9..e54e09fb 100644 --- a/protocols/yahoo/yahoo2.h +++ b/protocols/yahoo/yahoo2.h @@ -119,7 +119,7 @@ void yahoo_chat_keepalive(int id); /* from is the identity you're sending from. if NULL, the default is used */ /* utf8 is whether msg is a utf8 string or not. */ -void yahoo_send_im(int id, const char *from, const char *who, const char *msg, int utf8); +void yahoo_send_im(int id, const char *from, const char *who, const char *msg, int utf8, int picture); /* if type is true, send typing notice, else send stopped typing notice */ void yahoo_send_typing(int id, const char *from, const char *who, int typ); @@ -127,9 +127,10 @@ void yahoo_send_typing(int id, const char *from, const char *who, int typ); /* away says whether the custom message is an away message or a sig */ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away); -void yahoo_add_buddy(int id, const char *who, const char *group); +void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg); void yahoo_remove_buddy(int id, const char *who, const char *group); void yahoo_reject_buddy(int id, const char *who, const char *msg); +void yahoo_stealth_buddy(int id, const char *who, int unstealth); /* if unignore is true, unignore, else ignore */ void yahoo_ignore_buddy(int id, const char *who, int unignore); void yahoo_change_buddy_group(int id, const char *who, const char *old_group, const char *new_group); @@ -213,6 +214,8 @@ const char * yahoo_get_cookie(int id, const char *which); /* You'll have to do urlencoding yourself, but see yahoo_httplib.h first */ const char * yahoo_get_profile_url( void ); +void yahoo_buddyicon_request(int id, const char *who); + #include "yahoo_httplib.h" #ifdef __cplusplus diff --git a/protocols/yahoo/yahoo2_callbacks.h b/protocols/yahoo/yahoo2_callbacks.h index 1ab8a9d7..b7f4e99b 100644 --- a/protocols/yahoo/yahoo2_callbacks.h +++ b/protocols/yahoo/yahoo2_callbacks.h @@ -30,7 +30,6 @@ */ - #ifndef YAHOO2_CALLBACKS_H #define YAHOO2_CALLBACKS_H @@ -66,7 +65,6 @@ typedef enum { typedef void (*yahoo_connect_callback)(int fd, int error, void *callback_data); - /* * The following functions need to be implemented in the client * interface. They will be called by the library when each @@ -95,9 +93,7 @@ struct yahoo_callbacks { * succ - enum yahoo_login_status * url - url to reactivate account if locked */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_login_response)(int id, int succ, char *url); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_login_response)(int id, int succ, const char *url); /* @@ -110,8 +106,6 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_login_response)(int id, int succ, char *url); void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddies)(int id, YList * buds); - - /* * Name: ext_yahoo_got_ignore * Called when the ignore list is got from the server @@ -122,9 +116,6 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddies)(int id, YList * buds); void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore)(int id, YList * igns); - - - /* * Name: ext_yahoo_got_identities * Called when the contact list is got from the server @@ -135,9 +126,6 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore)(int id, YList * igns); void YAHOO_CALLBACK_TYPE(ext_yahoo_got_identities)(int id, YList * ids); - - - /* * Name: ext_yahoo_got_cookies * Called when the cookie list is got from the server @@ -147,6 +135,14 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_identities)(int id, YList * ids); void YAHOO_CALLBACK_TYPE(ext_yahoo_got_cookies)(int id); +/* + * Name: ext_yahoo_got_ping + * Called when the ping packet is received from the server + * Params: + * id - the id that identifies the server connection + * errormsg - optional error message + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ping)(int id, const char *errormsg); /* @@ -158,11 +154,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_cookies)(int id); * stat - status code (enum yahoo_status) * msg - the message if stat == YAHOO_STATUS_CUSTOM * away - whether the contact is away or not (YAHOO_STATUS_CUSTOM) - * for YAHOO_STATUS_IDLE, this is the number of seconds he is idle + * idle - this is the number of seconds he is idle [if he is idle] + * mobile - this is set for mobile users/buddies + * TODO: add support for pager, chat, and game states */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed)(int id, char *who, int stat, char *msg, int away); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed)(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile); /* @@ -170,6 +166,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed)(int id, char *who, int stat, * Called when remote user sends you a message. * Params: * id - the id that identifies the server connection + * me - the identity the message was sent to * who - the handle of the remote user * msg - the message - NULL if stat == 2 * tm - timestamp of message if offline @@ -179,9 +176,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed)(int id, char *who, int stat, * 5 * utf8 - whether the message is encoded as utf8 or not */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_got_im)(int id, char *who, char *msg, long tm, int stat, int utf8); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_im)(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8); /* @@ -189,14 +184,13 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_im)(int id, char *who, char *msg, long tm * Called when remote user sends you a conference invitation. * Params: * id - the id that identifies the server connection + * me - the identity the invitation was sent to * who - the user inviting you * room - the room to join * msg - the message * members - the initial members of the conference (null terminated list) */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_got_conf_invite)(int id, char *who, char *room, char *msg, YList *members); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_conf_invite)(int id, const char *me, const char *who, const char *room, const char *msg, YList *members); /* @@ -204,13 +198,12 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_conf_invite)(int id, char *who, char *roo * Called when someone declines to join the conference. * Params: * id - the id that identifies the server connection + * me - the identity in the conference * who - the user who has declined * room - the room * msg - the declining message */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userdecline)(int id, char *who, char *room, char *msg); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userdecline)(int id, const char *me, const char *who, const char *room, const char *msg); /* @@ -218,12 +211,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userdecline)(int id, char *who, char *ro * Called when someone joins the conference. * Params: * id - the id that identifies the server connection + * me - the identity in the conference * who - the user who has joined * room - the room joined */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userjoin)(int id, char *who, char *room); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userjoin)(int id, const char *me, const char *who, const char *room); /* @@ -231,33 +223,21 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userjoin)(int id, char *who, char *room) * Called when someone leaves the conference. * Params: * id - the id that identifies the server connection + * me - the identity in the conference * who - the user who has left * room - the room left */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userleave)(int id, char *who, char *room); - - - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userleave)(int id, const char *me, const char *who, const char *room); /* * Name: ext_yahoo_chat_cat_xml - * Called when joining the chatroom. + * Called when ? * Params: * id - the id that identifies the server connection - * room - the room joined, used in all other chat calls, freed by - * library after call - * topic - the topic of the room, freed by library after call - * members - the initial members of the chatroom (null terminated YList of - * yahoo_chat_member's) Must be freed by the client + * xml - ? */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml)(int id, char *xml); - - - - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml)(int id, const char *xml); /* @@ -265,6 +245,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml)(int id, char *xml); * Called when joining the chatroom. * Params: * id - the id that identifies the server connection + * me - the identity in the chatroom * room - the room joined, used in all other chat calls, freed by * library after call * topic - the topic of the room, freed by library after call @@ -272,11 +253,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml)(int id, char *xml); * of yahoo_chat_member's) Must be freed by the client * fd - the socket where the connection is coming from (for tracking) */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join)(int id, char *room, char *topic, YList *members, int fd); - - - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join)(int id, const char *me, const char *room, const char *topic, YList *members, int fd); /* @@ -284,12 +261,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join)(int id, char *room, char *topic, Y * Called when someone joins the chatroom. * Params: * id - the id that identifies the server connection + * me - the identity in the chatroom * room - the room joined * who - the user who has joined, Must be freed by the client */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userjoin)(int id, char *room, struct yahoo_chat_member *who); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userjoin)(int id, const char *me, const char *room, struct yahoo_chat_member *who); /* @@ -297,12 +273,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userjoin)(int id, char *room, struct yah * Called when someone leaves the chatroom. * Params: * id - the id that identifies the server connection + * me - the identity in the chatroom * room - the room left * who - the user who has left (Just the User ID) */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave)(int id, char *room, char *who); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave)(int id, const char *me, const char *room, const char *who); /* @@ -310,6 +285,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave)(int id, char *room, char *who * Called when someone messages in the chatroom. * Params: * id - the id that identifies the server connection + * me - the identity in the chatroom * room - the room * who - the user who messaged (Just the user id) * msg - the message @@ -317,7 +293,8 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave)(int id, char *room, char *who * 2 = /me type message * utf8 - whether the message is utf8 encoded or not */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_message)(int id, char *who, char *room, char *msg, int msgtype, int utf8); +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_message)(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, int utf8); + /* * @@ -328,10 +305,12 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_message)(int id, char *who, char *room, * of the disconnect request before doing anything here (auto-join's etc) * Params: * id - the id that identifies this connection + * me - the identity in the chatroom * Returns: * nothing. */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahoologout)(int id); +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahoologout)(int id, const char *me); + /* * @@ -343,25 +322,25 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahoologout)(int id); * of the error before doing anything about it. * Params: * id - the id that identifies this connection + * me - the identity in the chatroom * Returns: * nothing. */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahooerror)(int id, const char *me); -void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahooerror)(int id); /* * Name: ext_yahoo_conf_message * Called when someone messages in the conference. * Params: * id - the id that identifies the server connection + * me - the identity the conf message was sent to * who - the user who messaged * room - the room * msg - the message * utf8 - whether the message is utf8 encoded or not */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message)(int id, char *who, char *room, char *msg, int utf8); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message)(int id, const char *me, const char *who, const char *room, const char *msg, int utf8); /* @@ -369,6 +348,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message)(int id, char *who, char *room, * Called when someone sends you a file * Params: * id - the id that identifies the server connection + * me - the identity the file was sent to * who - the user who sent the file * url - the file url * expires - the expiry date of the file on the server (timestamp) @@ -376,9 +356,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message)(int id, char *who, char *room, * fname- the file name if direct transfer * fsize- the file size if direct transfer */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file)(int id, char *who, char *url, long expires, char *msg, char *fname, unsigned long fesize); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file)(int id, const char *me, const char *who, const char *url, long expires, const char *msg, const char *fname, unsigned long fesize); /* @@ -390,9 +368,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file)(int id, char *who, char *url, long * who - who was added * msg - any message sent */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_added)(int id, char *myid, char *who, char *msg); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_added)(int id, const char *myid, const char *who, const char *msg); /* @@ -403,9 +379,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_added)(int id, char *myid, char *who, * who - who rejected you * msg - any message sent */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_rejected)(int id, char *who, char *msg); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_rejected)(int id, const char *who, const char *msg); /* @@ -413,12 +387,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_rejected)(int id, char *who, char *msg); * Called when remote user starts or stops typing. * Params: * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to * who - the handle of the remote user * stat - 1 if typing, 0 if stopped typing */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_typing_notify)(int id, char *who, int stat); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_typing_notify)(int id, const char *me, const char *who, int stat); /* @@ -426,12 +399,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_typing_notify)(int id, char *who, int stat); * Called when remote user starts or stops a game. * Params: * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to * who - the handle of the remote user * stat - 1 if game, 0 if stopped gaming */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify)(int id, char *who, int stat); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify)(int id, const char *me, const char *who, int stat); /* @@ -443,9 +415,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify)(int id, char *who, int stat); * subj - the subject of the mail - NULL if only mail count * cnt - mail count - 0 if new mail notification */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_mail_notify)(int id, char *from, char *subj, int cnt); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_mail_notify)(int id, const char *from, const char *subj, int cnt); /* @@ -455,17 +425,49 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_mail_notify)(int id, char *from, char *subj, * id - the id that identifies the server connection * msg - the message */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message)(int id, char *msg); - - - - - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message)(int id, const char *msg); +/* + * Name: ext_yahoo_got_buddyicon + * Buddy icon received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the person the buddy icon is for + * url - the url to use to load the icon + * checksum - the checksum of the icon content + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon)(int id, const char *me, const char *who, const char *url, int checksum); +/* + * Name: ext_yahoo_got_buddyicon_checksum + * Buddy icon checksum received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy icon checksum is for + * checksum - the checksum of the icon content + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_checksum)(int id, const char *me,const char *who, int checksum); +/* + * Name: ext_yahoo_got_buddyicon_request + * Buddy icon request received + * Params: + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy that requested the buddy icon + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_request)(int id, const char *me, const char *who); +/* + * Name: ext_yahoo_got_buddyicon_request + * Buddy icon request received + * Params: + * id - the id that identifies the server connection + * url - remote url, the uploaded buddy icon can be fetched from + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_buddyicon_uploaded)(int id, const char *url); /* * Name: ext_yahoo_got_webcam_image @@ -495,18 +497,15 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_webcam_image)(int id, const char * who, unsigned int timestamp); - - /* * Name: ext_yahoo_webcam_invite * Called when you get a webcam invitation * Params: * id - the id that identifies the server connection + * me - identity the invitation is to * from - who the invitation is from */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite)(int id, char *from); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite)(int id, const char *me, const char *from); /* @@ -514,11 +513,11 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite)(int id, char *from); * Called when you get a response to a webcam invitation * Params: * id - the id that identifies the server connection + * me - identity the invitation response is to * from - who the invitation response is from * accept - 0 (decline), 1 (accept) */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite_reply)(int id, char *from, int accept); - +void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite_reply)(int id, const char *me, const char *from, int accept); /* @@ -533,7 +532,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite_reply)(int id, char *from, int * 3 = user declines permission * 4 = user does not have webcam online */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_closed)(int id, char *who, int reason); +void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_closed)(int id, const char *who, int reason); /* @@ -551,7 +550,6 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_closed)(int id, char *who, int reason) void YAHOO_CALLBACK_TYPE(ext_yahoo_got_search_result)(int id, int found, int start, int total, YList *contacts); - /* * Name: ext_yahoo_error * Called on error. @@ -559,10 +557,9 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_search_result)(int id, int found, int sta * id - the id that identifies the server connection * err - the error message * fatal- whether this error is fatal to the connection or not + * num - Which error is this */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_error)(int id, char *err, int fatal); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_error)(int id, const char *err, int fatal, int num); /* @@ -573,9 +570,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_error)(int id, char *err, int fatal); * who - the viewer * connect - 0=disconnect 1=connect 2=request */ -void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_viewer)(int id, char *who, int connect); - - +void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_viewer)(int id, const char *who, int connect); /* @@ -588,8 +583,6 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_viewer)(int id, char *who, int connect void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_data_request)(int id, int send); - - /* * Name: ext_yahoo_log * Called to log a message. @@ -598,13 +591,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_data_request)(int id, int send); * Returns: * 0 */ -int YAHOO_CALLBACK_TYPE(ext_yahoo_log)(char *fmt, ...); - - - - - - +int YAHOO_CALLBACK_TYPE(ext_yahoo_log)(const char *fmt, ...); /* @@ -623,8 +610,6 @@ int YAHOO_CALLBACK_TYPE(ext_yahoo_log)(char *fmt, ...); int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler)(int id, int fd, yahoo_input_condition cond, void *data); - - /* * Name: ext_yahoo_remove_handler * Remove the listener for the fd. @@ -635,9 +620,6 @@ int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler)(int id, int fd, yahoo_input_condi void YAHOO_CALLBACK_TYPE(ext_yahoo_remove_handler)(int id, int tag); - - - /* * Name: ext_yahoo_connect * Connect to a host:port @@ -647,13 +629,7 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_remove_handler)(int id, int tag); * Returns: * a unix file descriptor to the socket */ -int YAHOO_CALLBACK_TYPE(ext_yahoo_connect)(char *host, int port); - - - - - - +int YAHOO_CALLBACK_TYPE(ext_yahoo_connect)(const char *host, int port); /* @@ -674,7 +650,7 @@ int YAHOO_CALLBACK_TYPE(ext_yahoo_connect)(char *host, int port); * Returns: * a unix file descriptor to the socket */ -int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async)(int id, char *host, int port, +int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async)(int id, const char *host, int port, yahoo_connect_callback callback, void *callback_data); #ifdef USE_STRUCT_CALLBACKS @@ -685,7 +661,7 @@ int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async)(int id, char *host, int port, * before doing anything else */ void yahoo_register_callbacks(struct yahoo_callbacks * tyc); - + #undef YAHOO_CALLBACK_TYPE #endif @@ -695,3 +671,4 @@ void yahoo_register_callbacks(struct yahoo_callbacks * tyc); #endif #endif + diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h index 1a92b267..df1756eb 100644 --- a/protocols/yahoo/yahoo2_types.h +++ b/protocols/yahoo/yahoo2_types.h @@ -29,6 +29,7 @@ extern "C" { #endif enum yahoo_status { + YAHOO_STATUS_DISCONNECTED = -1, YAHOO_STATUS_AVAILABLE = 0, YAHOO_STATUS_BRB, YAHOO_STATUS_BUSY, @@ -42,13 +43,15 @@ enum yahoo_status { 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_NOTIFY = 0x16 + YAHOO_STATUS_NOTIFY = 0x16 /* TYPING */ }; #define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */ enum yahoo_login_status { YAHOO_LOGIN_OK = 0, + YAHOO_LOGIN_LOGOFF = 2, YAHOO_LOGIN_UNAME = 3, YAHOO_LOGIN_PASSWD = 13, YAHOO_LOGIN_LOCK = 14, @@ -57,6 +60,9 @@ enum yahoo_login_status { }; enum yahoo_error { + E_UNKNOWN = -1, + E_CONNECTION = -2, + E_SYSTEM = -3, E_CUSTOM = 0, /* responses from ignore buddy */ @@ -78,6 +84,7 @@ enum yahoo_log_level { YAHOO_LOG_DEBUG }; +#define YAHOO_PROTO_VER 0x000b /* Yahoo style/color directives */ #define YAHOO_COLOR_BLACK "\033[30m" @@ -115,6 +122,12 @@ enum yahoo_webcam_direction_type { YAHOO_WEBCAM_UPLOAD }; +enum yahoo_stealth_visibility_type { + YAHOO_STEALTH_DEFAULT = 0, + YAHOO_STEALTH_ONLINE, + YAHOO_STEALTH_PERM_OFFLINE +}; + /* chat member attribs */ #define YAHOO_CHAT_MALE 0x8000 #define YAHOO_CHAT_FEMALE 0x10000 diff --git a/protocols/yahoo/yahoo_util.c b/protocols/yahoo/yahoo_util.c index 7babfa49..5375205f 100644 --- a/protocols/yahoo/yahoo_util.c +++ b/protocols/yahoo/yahoo_util.c @@ -68,13 +68,15 @@ char ** y_strsplit(char * str, char * sep, int nelem) char *s, *p; int i=0; int l = strlen(sep); - if(nelem < 0) { + if(nelem <= 0) { char * s; nelem=0; - for(s=strstr(str, sep); s; s=strstr(s+l, sep),nelem++) - ; - if(strcmp(str+strlen(str)-l, sep)) - nelem++; + if (*str) { + for(s=strstr(str, sep); s; s=strstr(s+l, sep),nelem++) + ; + if(strcmp(str+strlen(str)-l, sep)) + nelem++; + } } vector = y_new(char *, nelem + 1); @@ -86,7 +88,7 @@ char ** y_strsplit(char * str, char * sep, int nelem) vector[i][len] = '\0'; } - if(i<nelem) /* str didn't end with sep */ + if(i<nelem && *str) /* str didn't end with sep, and str isn't empty */ vector[i++] = strdup(p); vector[i] = NULL; -- cgit v1.2.3 From b3cae44de28b62a282f2ba32260048174abc83e7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Apr 2007 21:44:08 -0700 Subject: Forgot to credit Greg for the update, and sorry to infamous41md for having your nick misspelled in the CREDITS file for so long! --- doc/CREDITS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/CREDITS b/doc/CREDITS index 83a19f51..f805c251 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -49,9 +49,11 @@ The authors thank the following people: - Elizabeth Krumbach, for her help on the docs. - Frank Thieme, for the info-command enhancements and other patches. - Marcus Dennis, for some bitlbeed enhancements. -- 1nfamus, for security auditing BitlBee code. +- infamous41md, for security auditing BitlBee code. - Tijmen Ruizendaal, for some useful BitlBee-related irssi scripts. - Ed Schouten, for reporting bugs. +- Greg (gropeep.org), for updating the Yahoo! module to fix some issues + that were there for quite some time already. - And all other users who help us by sending useful bug reports, positive feedback, nice patches and cool addons. Mentioning you all would make -- cgit v1.2.3 From 717e3bf045e5ebfb9b71e9260c8e573daefa7900 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 16 Apr 2007 20:57:30 -0700 Subject: Hopefully improved Yahoo! "markup" stripping. --- protocols/yahoo/yahoo.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 6f6590df..aad9d2df 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -70,7 +70,7 @@ static char *byahoo_strip( const char *in ) { int len; - /* This should get rid of HTML tags at the beginning of the string. */ + /* This should get rid of the markup noise at the beginning of the string. */ while( *in ) { if( g_strncasecmp( in, "<font", 5 ) == 0 || @@ -100,17 +100,23 @@ static char *byahoo_strip( const char *in ) } } - /* This is supposed to get rid of the closing HTML tags at the end of the line. */ + /* This is supposed to get rid of the noise at the end of the line. */ len = strlen( in ); - while( len > 0 && in[len-1] == '>' ) + while( len > 0 && ( in[len-1] == '>' || in[len-1] == 'm' ) ) { int blen = len; + const char *search; - len --; - while( len > 0 && ( in[len] != '<' || in[len+1] != '/' ) ) + if( in[len-1] == '>' ) + search = "</"; + else + search = "\e["; + + len -= 3; + while( len > 0 && strncmp( in + len, search, 2 ) != 0 ) len --; - if( len == 0 && ( in[len] != '<' || in[len+1] != '/' ) ) + if( len <= 0 && strncmp( in, search, 2 ) != 0 ) { len = blen; break; -- cgit v1.2.3 From 9624fdf0d6f170d8caa7948fb1b3a138b05e1d8c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 16 Apr 2007 21:49:17 -0700 Subject: API cleanup pretty much complete. Fixed pretty much everything except the buddy/groupchat related functions. --- protocols/jabber/message.c | 8 ++++---- protocols/msn/sb.c | 6 +++--- protocols/nogaim.c | 25 ++++++++++--------------- protocols/nogaim.h | 14 +++++++------- protocols/oscar/oscar.c | 16 ++++++++-------- protocols/yahoo/yahoo.c | 15 ++++++--------- 6 files changed, 38 insertions(+), 46 deletions(-) diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 6c105d1d..19edbdfd 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -75,7 +75,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) fullmsg = g_string_append( fullmsg, body->text ); if( fullmsg->len > 0 ) - serv_got_im( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0, fullmsg->len ); + imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0 ); g_string_free( fullmsg, TRUE ); @@ -83,18 +83,18 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( xt_find_node( node->children, "composing" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 1 ); + imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_TYPING ); } /* No need to send a "stopped typing" signal when there's a message. */ else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 0 ); + imcb_buddy_typing( ic, bud ? bud->bare_jid : from, 0 ); } else if( xt_find_node( node->children, "paused" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - serv_got_typing( ic, bud ? bud->bare_jid : from, 0, 2 ); + imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_THINKING ); } if( s ) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 614fb79c..c3eaef60 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -606,7 +606,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( sb->who ) { - serv_got_im( ic, cmd[1], body, 0, 0, blen ); + imcb_buddy_msg( ic, cmd[1], body, 0, 0 ); } else if( sb->chat ) { @@ -665,7 +665,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( sb->who ) { - serv_got_im( ic, cmd[1], buf, 0, 0, strlen( buf ) ); + imcb_buddy_msg( ic, cmd[1], buf, 0, 0 ); } else if( sb->chat ) { @@ -682,7 +682,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int if( who ) { - serv_got_typing( ic, who, 5, 1 ); + imcb_buddy_typing( ic, who, OPT_TYPING ); g_free( who ); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index ef30f749..2a452e57 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -423,7 +423,7 @@ struct buddy *find_buddy( struct im_connection *ic, char *handle ) if( !u ) return( NULL ); - + memset( b, 0, sizeof( b ) ); strncpy( b->name, handle, 80 ); strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN ); @@ -574,11 +574,11 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ { irc_write( ic->irc, ":%s MODE %s %cv %s", ic->irc->myhost, - ic->irc->channel, u->away?'-':'+', u->nick ); + ic->irc->channel, u->away?'-':'+', u->nick ); } } -void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ) +void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ) { irc_t *irc = ic->irc; user_t *u; @@ -656,24 +656,19 @@ void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 fla irc_msgfrom( irc, u->nick, msg ); } -void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ) +void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ) { user_t *u; if( !set_getbool( &ic->irc->set, "typing_notice" ) ) return; - if( ( u = user_findhandle( ic, handle ) ) ) { - /* If type is: - * 0: user has stopped typing - * 1: user is actively typing - * 2: user has entered text, but is not actively typing - */ - if (type == 0 || type == 1 || type == 2) { - char buf[256]; - g_snprintf(buf, 256, "\1TYPING %d\1", type); - irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf ); - } + if( ( u = user_findhandle( ic, handle ) ) ) + { + char buf[256]; + + g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 ); + irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf ); } } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 62d8db41..e249ae0e 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -49,17 +49,19 @@ #define MSG_LEN 2048 #define BUF_LEN MSG_LEN -#define SELF_ALIAS_LEN 400 #define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */ #define WEBSITE "http://www.bitlbee.org/" #define GAIM_AWAY_CUSTOM "Custom" -/* Sharing flags between buddies and connections. Or planning to, at least... */ +/* Sharing flags between all kinds of things. I just hope I won't hit any + limits before 32-bit machines become extinct. ;-) */ #define OPT_LOGGED_IN 0x00000001 #define OPT_LOGGING_OUT 0x00000002 #define OPT_AWAY 0x00000004 #define OPT_DOES_HTML 0x00000010 +#define OPT_TYPING 0x00000100 +#define OPT_THINKING 0x00000200 /* ok. now the fun begins. first we create a connection structure */ struct im_connection @@ -135,7 +137,7 @@ struct prpl { int (* send_im) (struct im_connection *, char *to, char *message, int flags); void (* set_away) (struct im_connection *, char *state, char *message); void (* get_away) (struct im_connection *, char *who); - int (* send_typing) (struct im_connection *, char *who, int typing); + int (* send_typing) (struct im_connection *, char *who, int flags); /* For now BitlBee doesn't really handle groups, just set it to NULL. */ void (* add_buddy) (struct im_connection *, char *name, char *group); @@ -170,8 +172,6 @@ struct prpl { int (* handle_cmp) (const char *who1, const char *who2); }; -#define UC_UNAVAILABLE 1 - /* im_api core stuff. */ void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); @@ -207,8 +207,8 @@ G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, /* Buddy activity */ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); -G_MODULE_EXPORT void serv_got_im( struct im_connection *ic, char *handle, char *msg, guint32 flags, time_t mtime, gint len ); -G_MODULE_EXPORT void serv_got_typing( struct im_connection *ic, char *handle, int timeout, int type ); +G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); /* Actions, or whatever. */ int imc_set_away( struct im_connection *ic, char *away ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index d05868b0..407aba7f 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1069,7 +1069,7 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ g_snprintf(tmp, BUF_LONG, "%s", args->msg); strip_linefeed(tmp); - serv_got_im(ic, userinfo->sn, tmp, flags, time(NULL), -1); + imcb_buddy_msg(ic, userinfo->sn, tmp, flags, 0); g_free(tmp); return 1; @@ -1166,7 +1166,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ uin = g_strdup_printf("%u", args->uin); message = g_strdup(args->msg); strip_linefeed(message); - serv_got_im(ic, uin, message, 0, time(NULL), -1); + imcb_buddy_msg(ic, uin, message, 0, 0); g_free(uin); g_free(message); } break; @@ -1185,7 +1185,7 @@ static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } strip_linefeed(message); - serv_got_im(ic, uin, message, 0, time(NULL), -1); + imcb_buddy_msg(ic, uin, message, 0, 0); g_free(uin); g_free(m); g_free(message); @@ -1747,7 +1747,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); g_snprintf(sender, sizeof(sender), "%u", msg->sender); strip_linefeed(dialog_msg); - serv_got_im(ic, sender, dialog_msg, 0, t, -1); + imcb_buddy_msg(ic, sender, dialog_msg, 0, t); g_free(dialog_msg); } break; @@ -1768,7 +1768,7 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { } strip_linefeed(dialog_msg); - serv_got_im(ic, sender, dialog_msg, 0, t, -1); + imcb_buddy_msg(ic, sender, dialog_msg, 0, t); g_free(dialog_msg); g_free(m); } break; @@ -2420,15 +2420,15 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) if(type2 == 0x0002) { /* User is typing */ - serv_got_typing(ic, sn, 0, 1); + imcb_buddy_typing(ic, sn, OPT_TYPING); } else if (type2 == 0x0001) { /* User has typed something, but is not actively typing (stale) */ - serv_got_typing(ic, sn, 0, 2); + imcb_buddy_typing(ic, sn, OPT_THINKING); } else { /* User has stopped typing */ - serv_got_typing(ic, sn, 0, 0); + imcb_buddy_typing(ic, sn, 0); } return 1; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index aad9d2df..191a197c 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -617,7 +617,7 @@ void ext_yahoo_got_im( int id, const char *me, const char *who, const char *msg, struct im_connection *ic = byahoo_get_ic_by_id( id ); char *m = byahoo_strip( msg ); - serv_got_im( ic, (char*) who, (char*) m, 0, 0, strlen( m ) ); + imcb_buddy_msg( ic, (char*) who, (char*) m, 0, 0 ); g_free( m ); } @@ -633,14 +633,11 @@ void ext_yahoo_got_file( int id, void ext_yahoo_typing_notify( int id, const char *ignored, const char *who, int stat ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - if (stat == 1) { - /* User is typing */ - serv_got_typing( ic, (char*) who, 1, 1 ); - } - else { - /* User stopped typing */ - serv_got_typing( ic, (char*) who, 1, 0 ); - } + + if( stat == 1 ) + imcb_buddy_typing( ic, (char*) who, OPT_TYPING ); + else + imcb_buddy_typing( ic, (char*) who, 0 ); } void ext_yahoo_system_message( int id, const char *msg ) -- cgit v1.2.3 From 33dc2618520409c0d52efff335fe299c26f6dd42 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 17 Apr 2007 19:49:49 -0700 Subject: Fixed NULL pointer dereference in Jabber code. --- protocols/jabber/presence.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 6bc8117f..f577e56a 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -73,7 +73,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* FIXME: What to send if there are other resources??? */ imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - bud->away_state->full_name, bud->away_message ); + ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, + bud->away_message ); } else if( strcmp( type, "unavailable" ) == 0 ) { -- cgit v1.2.3 From f0cb961652cbd639e89dcd88a86f20a2414146c4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 18 Apr 2007 23:03:43 -0700 Subject: More API changes: buddy list management. imcb_add_buddy() is now a *real* callback, it's only called from inside IM-modules. This makes sure a buddy only gets added to the BitlBee structures if the add was successful. This gets rid of the weirdness described in #55. Unfortunately for now this change breaks A) automatic renaming of ICQ contacts (if there are names stored in the contact list) B) add -tmp. --- protocols/jabber/iq.c | 22 +++++++--------------- protocols/jabber/jabber_util.c | 6 +++--- protocols/msn/msn_util.c | 2 +- protocols/msn/ns.c | 26 +++++++++++++++++--------- protocols/nogaim.c | 42 +++++++++++++++++------------------------- protocols/nogaim.h | 7 ++++--- protocols/oscar/oscar.c | 24 +++++++++++++++++------- protocols/yahoo/libyahoo2.c | 19 +++++++++++++------ protocols/yahoo/yahoo.c | 7 ++++++- root_commands.c | 12 ++++++------ 10 files changed, 91 insertions(+), 76 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 46ae9a64..2aa9d432 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -359,28 +359,20 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * c = query->children; while( ( c = xt_find_node( c, "item" ) ) ) { + struct xt_node *group = xt_find_node( node->children, "group" ); char *jid = xt_find_attr( c, "jid" ); char *name = xt_find_attr( c, "name" ); char *sub = xt_find_attr( c, "subscription" ); - if( !jid || !sub ) - { - /* Maybe warn. But how likely is this to happen in the first place? */ - } - else if( initial ) + if( jid && sub ) { - if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) - add_buddy( ic, NULL, jid, name ); - } - else - { - /* This is a roster push item. Find out what changed exactly. */ if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) { - if( find_buddy( ic, jid ) == NULL ) - add_buddy( ic, NULL, jid, name ); - else if( name ) - serv_buddy_rename( ic, jid, name ); + if( initial || imcb_find_buddy( ic, jid ) == NULL ) + imcb_add_buddy( ic, jid, ( group && group->text_len ) ? + group->text : NULL ); + + imcb_rename_buddy( ic, jid, name ); } else if( strcmp( sub, "remove" ) == 0 ) { diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 949a7a4b..3c0e71f4 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -222,7 +222,7 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla { presence_send_request( bla->ic, bla->handle, "subscribed" ); - if( find_buddy( bla->ic, bla->handle ) == NULL ) + if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); @@ -370,7 +370,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, } } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) ) { *s = '/'; bud = jabber_buddy_add( ic, jid ); @@ -390,7 +390,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, if( bud == NULL ) /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid_ ) ) ? + return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ? jabber_buddy_add( ic, jid_ ) : NULL; else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) /* We want an exact match, so in thise case there shouldn't be a /resource. */ diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 80f351a2..c9eb5ee2 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -93,7 +93,7 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla ) { msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname ); - if( find_buddy( bla->ic, bla->handle ) == NULL ) + if( imcb_find_buddy( bla->ic, bla->handle ) == NULL ) imcb_ask_add( bla->ic, bla->handle, NULL ); g_free( bla->handle ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index c80fc177..9bd7f152 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -304,10 +304,11 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) char *group = NULL; int num; - if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 ) + if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount ) group = md->grouplist[num]; - add_buddy( ic, group, cmd[1], cmd[2] ); + imcb_add_buddy( ic, cmd[1], group ); + imcb_rename_buddy( ic, cmd[1], cmd[2] ); } if( list & 2 ) /* AL */ { @@ -390,7 +391,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } http_decode( cmd[4] ); - serv_buddy_rename( ic, cmd[3], cmd[4] ); + imcb_rename_buddy( ic, cmd[3], cmd[4] ); st = msn_away_state_by_code( cmd[2] ); if( !st ) @@ -419,7 +420,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } http_decode( cmd[3] ); - serv_buddy_rename( ic, cmd[2], cmd[3] ); + imcb_rename_buddy( ic, cmd[2], cmd[3] ); st = msn_away_state_by_code( cmd[1] ); if( !st ) @@ -481,20 +482,27 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { imcb_error( ic, "Syntax error" ); imc_logout( ic, TRUE ); - return( 0 ); + return 0; } - /* We got added by someone. If we don't have this person in permit/deny yet, inform the user. */ + /* We got added by someone. If we don't have this + person in permit/deny yet, inform the user. */ for( l = ic->permit; l; l = l->next ) if( g_strcasecmp( l->data, cmd[4] ) == 0 ) - return( 1 ); + return 1; for( l = ic->deny; l; l = l->next ) if( g_strcasecmp( l->data, cmd[4] ) == 0 ) - return( 1 ); + return 1; msn_buddy_ask( ic, cmd[4], cmd[5] ); } + else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 ) + { + http_decode( cmd[5] ); + imcb_add_buddy( ic, cmd[4], NULL ); + imcb_rename_buddy( ic, cmd[4], cmd[5] ); + } } else if( strcmp( cmd[0], "OUT" ) == 0 ) { @@ -544,7 +552,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) { /* This is not supposed to happen, but let's handle it anyway... */ http_decode( cmd[4] ); - serv_buddy_rename( ic, cmd[3], cmd[4] ); + imcb_rename_buddy( ic, cmd[3], cmd[4] ); } } else if( strcmp( cmd[0], "IPG" ) == 0 ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 2a452e57..02a1bf71 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -351,16 +351,12 @@ void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void /* list.c */ -void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ) +void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ) { user_t *u; - char nick[MAX_NICK_LENGTH+1]; - char *s; + char nick[MAX_NICK_LENGTH+1], *s; irc_t *irc = ic->irc; - if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */ - imcb_log( ic, "Receiving user add from handle: %s", handle ); - if( user_findhandle( ic, handle ) ) { if( set_getbool( &irc->set, "debug" ) ) @@ -368,16 +364,19 @@ void add_buddy( struct im_connection *ic, char *group, char *handle, char *realn return; - /* Buddy seems to exist already. Let's ignore this request then... */ + /* Buddy seems to exist already. Let's ignore this request then... + Eventually subsequent calls to this function *should* be possible + when a buddy is in multiple groups. But for now BitlBee doesn't + even support groups so let's silently ignore this for now. */ } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( ic->acc, handle, realname ) ); + strcpy( nick, nick_get( ic->acc, handle, NULL ) ); u = user_add( ic->irc, nick ); - if( !realname || !*realname ) realname = nick; - u->realname = g_strdup( realname ); +// if( !realname || !*realname ) realname = nick; +// u->realname = g_strdup( realname ); if( ( s = strchr( handle, '@' ) ) ) { @@ -386,14 +385,7 @@ void add_buddy( struct im_connection *ic, char *group, char *handle, char *realn } else if( ic->acc->server ) { - char *colon; - - if( ( colon = strchr( ic->acc->server, ':' ) ) ) - u->host = g_strndup( ic->acc->server, - colon - ic->acc->server ); - else - u->host = g_strdup( ic->acc->server ); - + u->host = g_strdup( ic->acc->server ); u->user = g_strdup( handle ); /* s/ /_/ ... important for AOL screennames */ @@ -414,7 +406,7 @@ void add_buddy( struct im_connection *ic, char *group, char *handle, char *realn u->last_typing_notice = 0; } -struct buddy *find_buddy( struct im_connection *ic, char *handle ) +struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ) { static struct buddy b[1]; user_t *u; @@ -434,11 +426,11 @@ struct buddy *find_buddy( struct im_connection *ic, char *handle ) } -void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ) +void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) { user_t *u = user_findhandle( ic, handle ); - if( !u ) return; + if( !u || !realname ) return; if( g_strcasecmp( u->realname, realname ) != 0 ) { @@ -469,7 +461,7 @@ void show_got_added_no( gpointer w, struct show_got_added_data *data ) void show_got_added_yes( gpointer w, struct show_got_added_data *data ) { data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL ); - add_buddy( data->ic, NULL, data->handle, data->handle ); + /* imcb_add_buddy( data->ic, NULL, data->handle, data->handle ); */ return show_got_added_no( w, data ); } @@ -504,7 +496,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, { if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 ) { - add_buddy( ic, NULL, (char*) handle, NULL ); + imcb_add_buddy( ic, (char*) handle, NULL ); u = user_findhandle( ic, (char*) handle ); } else @@ -608,7 +600,7 @@ void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_ private = 0; } - add_buddy( ic, NULL, handle, NULL ); + imcb_add_buddy( ic, handle, NULL ); u = user_findhandle( ic, handle ); u->is_private = private; } @@ -778,7 +770,7 @@ void add_chat_buddy( struct groupchat *b, char *handle ) your contact list. Try to handle that here */ if( !u ) { - add_buddy( b->ic, NULL, handle, NULL ); + imcb_add_buddy( b->ic, handle, NULL ); u = user_findhandle( b->ic, handle ); } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index e249ae0e..e17c9523 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -200,9 +200,10 @@ G_MODULE_EXPORT void serv_got_chat_left( struct groupchat *c ); struct groupchat *chat_by_channel( char *channel ); /* Buddy management */ -G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname ); -G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle ); -G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname ); +G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ); +G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ); +G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ); /* Buddy activity */ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 407aba7f..7e5dbee0 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1118,7 +1118,7 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) { message = 0; aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); - if(find_buddy(data->ic, uin) == NULL) + if(imcb_find_buddy(data->ic, uin) == NULL) imcb_ask_add(data->ic, uin, NULL); g_free(uin); @@ -1874,7 +1874,7 @@ static void oscar_get_info(struct im_connection *g, char *name) { static void oscar_get_away(struct im_connection *g, char *who) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; if (odata->icq) { - struct buddy *budlight = find_buddy(g, who); + struct buddy *budlight = imcb_find_buddy(g, who); if (budlight) if ((budlight->uc & 0xff80) >> 7) if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) @@ -2012,16 +2012,18 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { for (curitem=sess->ssi.items; curitem; curitem=curitem->next) { switch (curitem->type) { case 0x0000: /* Buddy */ - if ((curitem->name) && (!find_buddy(ic, curitem->name))) { + if ((curitem->name) && (!imcb_find_buddy(ic, curitem->name))) { char *realname = NULL; if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) realname = aim_gettlv_str(curitem->data, 0x0131, 1); - add_buddy(ic, NULL, curitem->name, realname); + imcb_add_buddy(ic, curitem->name, NULL); - if (realname) - g_free(realname); + if (realname) { + imcb_rename_buddy(ic, curitem->name, realname); + g_free(realname); + } } break; @@ -2104,13 +2106,21 @@ static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) for( i = 0; i < count; i ++ ) { st = aimbs_get16( &fr->data ); - if( st == 0x0E ) + if( st == 0x00 ) + { + imcb_add_buddy( sess->aux_data, list, NULL ); + } + else if( st == 0x0E ) { imcb_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); aim_ssi_auth_request( sess, fr->conn, list, "" ); aim_ssi_addbuddies( sess, fr->conn, OSCAR_GROUP, &list, 1, 1 ); } + else + { + imcb_error( sess->aux_data, "Error while adding buddy: 0x%04x", st ); + } list += strlen( list ) + 1; } } diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 38041ad4..5beae687 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -2402,12 +2402,19 @@ static void yahoo_process_buddyadd(struct yahoo_input_data *yid, struct yahoo_pa if(!where) where = "Unknown"; - bud = y_new0(struct yahoo_buddy, 1); - bud->id = strdup(who); - bud->group = strdup(where); - bud->real_name = NULL; - - yd->buddies = y_list_append(yd->buddies, bud); + /* status: 0 == Successful, 1 == Error (does not exist), 2 == Already in list */ + if( status == 0 ) { + bud = y_new0(struct yahoo_buddy, 1); + bud->id = strdup(who); + bud->group = strdup(where); + bud->real_name = NULL; + + yd->buddies = y_list_append(yd->buddies, bud); + + /* Possibly called already, but at least the call above doesn't + seem to happen every time (not anytime I tried). */ + YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, me, who, NULL); + } /* YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */ } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 191a197c..c3d57a94 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -531,7 +531,9 @@ void ext_yahoo_got_buddies( int id, YList *buds ) yd->buddygroups = g_slist_append( yd->buddygroups, bg ); } - add_buddy( ic, b->group, b->id, b->real_name ); + imcb_add_buddy( ic, b->id, b->group ); + imcb_rename_buddy( ic, b->id, b->real_name ); + bl = bl->next; } } @@ -903,6 +905,9 @@ void ext_yahoo_chat_yahooerror( int id, const char *me ) void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg ) { + /* Groups schmoups. If I want to handle groups properly I can get the + buddy data from some internal libyahoo2 structure. */ + imcb_add_buddy( byahoo_get_ic_by_id( id ), (char*) who, NULL ); } void ext_yahoo_rejected( int id, const char *who, const char *msg ) diff --git a/root_commands.c b/root_commands.c index acbf579f..a7582936 100644 --- a/root_commands.c +++ b/root_commands.c @@ -436,11 +436,11 @@ static void cmd_account( irc_t *irc, char **cmd ) static void cmd_add( irc_t *irc, char **cmd ) { account_t *a; - int add_for_real = 1; + int add_on_server = 1; if( g_strcasecmp( cmd[1], "-tmp" ) == 0 ) { - add_for_real = 0; + add_on_server = 0; cmd ++; /* So evil... :-D */ } @@ -475,12 +475,12 @@ static void cmd_add( irc_t *irc, char **cmd ) /* By making this optional, you can talk to people without having to add them to your *real* (server-side) contact list. */ - if( add_for_real ) + if( add_on_server ) a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); - - add_buddy( a->ic, NULL, cmd[2], cmd[2] ); - irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->ic, cmd[2] )->nick ); + /* add_buddy( a->ic, NULL, cmd[2], cmd[2] ); */ + + irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2] ); } static void cmd_info( irc_t *irc, char **cmd ) -- cgit v1.2.3 From d323394cf97afa79bc2a75f5f2dd0f88bf1b8fa4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 19 Apr 2007 21:49:30 -0700 Subject: New code to use nicknames stored in ICQ contact lists. --- nick.c | 25 ++++++++++++++++--------- nick.h | 3 ++- protocols/nogaim.c | 25 +++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/nick.c b/nick.c index 14794bf3..5e24547a 100644 --- a/nick.c +++ b/nick.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2006 Wilmer van der Gaast and others * + * Copyright 2002-2007 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to fetch, save and handle nicknames for your buddies */ @@ -52,7 +52,7 @@ void nick_set( account_t *acc, const char *handle, const char *nick ) g_hash_table_replace( acc->nicks, store_handle, store_nick ); } -char *nick_get( account_t *acc, const char *handle, const char *realname ) +char *nick_get( account_t *acc, const char *handle ) { static char nick[MAX_NICK_LENGTH+1]; char *store_handle, *found_nick; @@ -76,12 +76,6 @@ char *nick_get( account_t *acc, const char *handle, const char *realname ) while( *s ) *(s++) = 0; - /* All-digit handles (mainly ICQ UINs) aren't cool, try to - use the realname instead. */ - for( s = nick; *s && isdigit( *s ); s ++ ); - if( !*s && realname && *realname ) - g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname ); - nick_strip( nick ); if( set_getbool( &acc->irc->set, "lcnicks" ) ) nick_lc( nick ); @@ -129,6 +123,19 @@ char *nick_get( account_t *acc, const char *handle, const char *realname ) return nick; } +/* Just check if there is a nickname set for this buddy or if we'd have to + generate one. */ +int nick_saved( account_t *acc, const char *handle ) +{ + char *store_handle, *found; + + store_handle = clean_handle( handle ); + found = g_hash_table_lookup( acc->nicks, store_handle ); + g_free( store_handle ); + + return found != NULL; +} + void nick_del( account_t *acc, const char *handle ) { g_hash_table_remove( acc->nicks, handle ); @@ -175,7 +182,7 @@ int nick_ok( const char *nick ) int nick_lc( char *nick ) { - static char tab[256] = { 0 }; + static char tab[128] = { 0 }; int i; if( tab['A'] == 0 ) diff --git a/nick.h b/nick.h index 5274cb13..bb7816f0 100644 --- a/nick.h +++ b/nick.h @@ -24,7 +24,8 @@ */ void nick_set( account_t *acc, const char *handle, const char *nick ); -char *nick_get( account_t *acc, const char *handle, const char *realname ); +char *nick_get( account_t *acc, const char *handle ); +int nick_saved( account_t *acc, const char *handle ); void nick_del( account_t *acc, const char *handle ); void nick_strip( char *nick ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 02a1bf71..2fa6277e 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -371,7 +371,7 @@ void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ) } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( ic->acc, handle, NULL ) ); + strcpy( nick, nick_get( ic->acc, handle ) ); u = user_add( ic->irc, nick ); @@ -425,10 +425,10 @@ struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ) return( b ); } - void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) { user_t *u = user_findhandle( ic, handle ); + char *s, newnick[MAX_NICK_LENGTH+1]; if( !u || !realname ) return; @@ -440,6 +440,27 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); + + if( !u->online && !nick_saved( ic->acc, handle ) ) + { + /* Detect numeric handles: */ + for( s = u->user; isdigit( *s ); s++ ); + + if( *s == 0 ) + { + /* If we reached the end of the string, it only contained numbers. + Seems to be an ICQ# then, so hopefully realname contains + something more useful. */ + strcpy( newnick, realname ); + + /* Some processing to make sure this string is a valid IRC nickname. */ + nick_strip( newnick ); + if( set_getbool( &ic->irc->set, "lcnicks" ) ) + nick_lc( newnick ); + + u->nick = g_strdup( newnick ); + } + } } } -- cgit v1.2.3 From 61ae52c5fbe8fbaf75adb148cd05c357590e8807 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 19 Apr 2007 22:19:06 -0700 Subject: Renamed/slightly changed syntax of groupchat callback functions. --- protocols/msn/sb.c | 24 ++++++++++++------------ protocols/nogaim.c | 10 +++++----- protocols/nogaim.h | 19 +++++++++---------- protocols/oscar/oscar.c | 10 +++++----- protocols/yahoo/yahoo.c | 22 +++++++++++----------- 5 files changed, 42 insertions(+), 43 deletions(-) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index c3eaef60..1693cb95 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -183,11 +183,11 @@ struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ) /* Create the groupchat structure. */ g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( ic, buf ); + sb->chat = imcb_chat_new( ic, buf ); /* Populate the channel. */ - if( sb->who ) add_chat_buddy( sb->chat, sb->who ); - add_chat_buddy( sb->chat, ic->acc->user ); + if( sb->who ) imcb_chat_add_buddy( sb->chat, sb->who ); + imcb_chat_add_buddy( sb->chat, ic->acc->user ); /* And make sure the switchboard doesn't look like a regular chat anymore. */ if( sb->who ) @@ -231,7 +231,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) if( sb->chat ) { - serv_got_chat_left( sb->chat ); + imcb_chat_removed( sb->chat ); } if( sb->handler ) @@ -373,17 +373,17 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) if( num == 1 ) { g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = serv_got_joined_chat( ic, buf ); + sb->chat = imcb_chat_new( ic, buf ); g_free( sb->who ); sb->who = NULL; } - add_chat_buddy( sb->chat, cmd[4] ); + imcb_chat_add_buddy( sb->chat, cmd[4] ); if( num == tot ) { - add_chat_buddy( sb->chat, ic->acc->user ); + imcb_chat_add_buddy( sb->chat, ic->acc->user ); } } } @@ -461,11 +461,11 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) /* This SB is a one-to-one chat right now, but someone else is joining. */ msn_sb_to_chat( sb ); - add_chat_buddy( sb->chat, cmd[1] ); + imcb_chat_add_buddy( sb->chat, cmd[1] ); } else if( sb->chat ) { - add_chat_buddy( sb->chat, cmd[1] ); + imcb_chat_add_buddy( sb->chat, cmd[1] ); sb->ready = 1; } else @@ -515,7 +515,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else if( sb->chat ) { - remove_chat_buddy( sb->chat, cmd[1], "" ); + imcb_chat_remove_buddy( sb->chat, cmd[1], "" ); } else { @@ -610,7 +610,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int } else if( sb->chat ) { - serv_got_chat_in( sb->chat, cmd[1], 0, body, 0 ); + imcb_chat_msg( sb->chat, cmd[1], body, 0, 0 ); } else { @@ -669,7 +669,7 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int } else if( sb->chat ) { - serv_got_chat_in( sb->chat, cmd[1], 0, buf, 0 ); + imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 ); } else { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 2fa6277e..c27a684d 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -685,7 +685,7 @@ void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags } } -void serv_got_chat_left( struct groupchat *c ) +void imcb_chat_removed( struct groupchat *c ) { struct im_connection *ic = c->ic; struct groupchat *l = NULL; @@ -722,7 +722,7 @@ void serv_got_chat_left( struct groupchat *c ) } } -void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ) +void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ) { struct im_connection *ic = c->ic; user_t *u; @@ -743,7 +743,7 @@ void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, t imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); } -struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) +struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) { struct groupchat *c; @@ -770,7 +770,7 @@ struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ) /* buddy_chat.c */ -void add_chat_buddy( struct groupchat *b, char *handle ) +void imcb_chat_add_buddy( struct groupchat *b, char *handle ) { user_t *u = user_findhandle( b->ic, handle ); int me = 0; @@ -804,7 +804,7 @@ void add_chat_buddy( struct groupchat *b, char *handle ) } } -void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ) +void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) { user_t *u; int me = 0; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index e17c9523..c4b079ab 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -93,7 +93,6 @@ struct im_connection struct groupchat *conversations; }; -/* struct buddy_chat went away and got merged with this. */ struct groupchat { struct im_connection *ic; @@ -190,15 +189,6 @@ G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ); G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ); -/* Groupchats */ -G_MODULE_EXPORT void add_chat_buddy( struct groupchat *b, char *handle ); -G_MODULE_EXPORT void remove_chat_buddy( struct groupchat *b, char *handle, char *reason ); -G_MODULE_EXPORT void serv_got_chat_invite( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); -G_MODULE_EXPORT struct groupchat *serv_got_joined_chat( struct im_connection *ic, char *handle ); -G_MODULE_EXPORT void serv_got_chat_in( struct groupchat *c, char *who, int whisper, char *msg, time_t mtime ); -G_MODULE_EXPORT void serv_got_chat_left( struct groupchat *c ); -struct groupchat *chat_by_channel( char *channel ); - /* Buddy management */ G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ); G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ); @@ -211,6 +201,15 @@ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *ha G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); +/* Groupchats */ +G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); +G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); +G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); +G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c ); +struct groupchat *chat_by_channel( char *channel ); + /* Actions, or whatever. */ int imc_set_away( struct im_connection *ic, char *away ); int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 7e5dbee0..a23e8a5a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -749,7 +749,7 @@ static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { chatcon = find_oscar_chat_by_conn(ic, fr->conn); chatcon->id = id; - chatcon->cnv = serv_got_joined_chat(ic, chatcon->show); + chatcon->cnv = imcb_chat_new(ic, chatcon->show); chatcon->cnv->data = chatcon; return 1; @@ -1460,7 +1460,7 @@ static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; for (i = 0; i < count; i++) - add_chat_buddy(c->cnv, info[i].sn); + imcb_chat_add_buddy(c->cnv, info[i].sn); return 1; } @@ -1483,7 +1483,7 @@ static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; for (i = 0; i < count; i++) - remove_chat_buddy(c->cnv, info[i].sn, NULL); + imcb_chat_remove_buddy(c->cnv, info[i].sn, NULL); return 1; } @@ -1534,7 +1534,7 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) { tmp = g_malloc(BUF_LONG); g_snprintf(tmp, BUF_LONG, "%s", msg); - serv_got_chat_in(ccon->cnv, info->sn, 0, tmp, time((time_t)NULL)); + imcb_chat_msg(ccon->cnv, info->sn, tmp, 0, 0); g_free(tmp); return 1; @@ -2512,7 +2512,7 @@ void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc) struct oscar_data *od = (struct oscar_data *)ic->proto_data; /* Notify the conversation window that we've left the chat */ - serv_got_chat_left(cc->cnv); + imcb_chat_removed(cc->cnv); /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index c3d57a94..7bf3f333 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -145,7 +145,7 @@ static void byahoo_logout( struct im_connection *ic ) GSList *l; while( ic->conversations ) - serv_got_chat_left( ic->conversations ); + imcb_chat_removed( ic->conversations ); for( l = yd->buddygroups; l; l = l->next ) { @@ -317,7 +317,7 @@ static void byahoo_chat_leave( struct groupchat *c ) struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); - serv_got_chat_left( c ); + imcb_chat_removed( c ); } static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) @@ -329,8 +329,8 @@ static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) roomname = g_strdup_printf( "%s-Bee-%d", ic->acc->user, byahoo_chat_id ); - c = serv_got_joined_chat( ic, roomname ); - add_chat_buddy( c, ic->acc->user ); + c = imcb_chat_new( ic, roomname ); + imcb_chat_add_buddy( c, ic->acc->user ); /* FIXME: Free this thing when the chat's destroyed. We can't *always* do this because it's not always created here. */ @@ -789,7 +789,7 @@ int ext_yahoo_connect(const char *host, int port) static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); - add_chat_buddy( inv->c, inv->ic->acc->user ); + imcb_chat_add_buddy( inv->c, inv->ic->acc->user ); g_free( inv->name ); g_free( inv ); } @@ -797,7 +797,7 @@ static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); - serv_got_chat_left( inv->c ); + imcb_chat_removed( inv->c ); g_free( inv->name ); g_free( inv ); } @@ -813,7 +813,7 @@ void ext_yahoo_got_conf_invite( int id, const char *ignored, inv = g_malloc( sizeof( struct byahoo_conf_invitation ) ); memset( inv, 0, sizeof( struct byahoo_conf_invitation ) ); inv->name = g_strdup( room ); - inv->c = serv_got_joined_chat( ic, (char*) room ); + inv->c = imcb_chat_new( ic, (char*) room ); inv->c->data = members; inv->yid = id; inv->members = members; @@ -821,7 +821,7 @@ void ext_yahoo_got_conf_invite( int id, const char *ignored, for( m = members; m; m = m->next ) if( g_strcasecmp( m->data, ic->acc->user ) != 0 ) - add_chat_buddy( inv->c, m->data ); + imcb_chat_add_buddy( inv->c, m->data ); g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg ); @@ -843,7 +843,7 @@ void ext_yahoo_conf_userjoin( int id, const char *ignored, const char *who, cons for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - add_chat_buddy( c, (char*) who ); + imcb_chat_add_buddy( c, (char*) who ); } void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, const char *room ) @@ -855,7 +855,7 @@ void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, con for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - remove_chat_buddy( c, (char*) who, "" ); + imcb_chat_remove_buddy( c, (char*) who, "" ); } void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8 ) @@ -867,7 +867,7 @@ void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) - serv_got_chat_in( c, (char*) who, 0, (char*) m, 0 ); + imcb_chat_msg( c, (char*) who, (char*) m, 0, 0 ); g_free( m ); } -- cgit v1.2.3 From b0eaa5b5a0ab866791992f6f1d7f011d012d103d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Apr 2007 20:23:39 -0700 Subject: No auto reconnect when the user does "account off" (in fact this auto reconnect gets cancelled immediately, but the message is confusing). --- account.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account.c b/account.c index 1b0d7f26..388d04d0 100644 --- a/account.c +++ b/account.c @@ -222,7 +222,7 @@ void account_on( irc_t *irc, account_t *a ) void account_off( irc_t *irc, account_t *a ) { - imc_logout( a->ic, TRUE ); + imc_logout( a->ic, FALSE ); a->ic = NULL; if( a->reconnect ) { -- cgit v1.2.3 From f6c963b97d3f686ca5410f1896cf8e266b455c22 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Apr 2007 21:13:21 -0700 Subject: Renamed some more prpl functions. --- protocols/jabber/jabber.c | 6 +++--- protocols/msn/msn.c | 10 +++++----- protocols/nogaim.c | 5 ++--- protocols/nogaim.h | 8 ++++---- protocols/oscar/oscar.c | 8 ++++---- protocols/yahoo/yahoo.c | 8 ++++---- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e560fda0..c38be72e 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -218,7 +218,7 @@ static void jabber_logout( struct im_connection *ic ) g_free( jd ); } -static int jabber_send_im( struct im_connection *ic, char *who, char *message, int flags ) +static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; @@ -385,7 +385,7 @@ void jabber_initmodule() ret->login = jabber_login; ret->init = jabber_init; ret->logout = jabber_logout; - ret->send_im = jabber_send_im; + ret->buddy_msg = jabber_buddy_msg; ret->away_states = jabber_away_states; // ret->get_status_string = jabber_get_status_string; ret->set_away = jabber_set_away; @@ -393,7 +393,7 @@ void jabber_initmodule() ret->get_info = jabber_get_info; ret->add_buddy = jabber_add_buddy; ret->remove_buddy = jabber_remove_buddy; -// ret->chat_send = jabber_chat_send; +// ret->chat_msg = jabber_chat_msg; // ret->chat_invite = jabber_chat_invite; // ret->chat_leave = jabber_chat_leave; // ret->chat_open = jabber_chat_open; diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 5eea68af..6d774806 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -121,7 +121,7 @@ static void msn_logout( struct im_connection *ic ) msn_connections = g_slist_remove( msn_connections, ic ); } -static int msn_send_im( struct im_connection *ic, char *who, char *message, int away ) +static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away ) { struct msn_switchboard *sb; struct msn_data *md = ic->proto_data; @@ -230,7 +230,7 @@ static void msn_remove_buddy( struct im_connection *ic, char *who, char *group ) msn_buddy_list_remove( ic, "FL", who ); } -static void msn_chat_send( struct groupchat *c, char *message, int flags ) +static void msn_chat_msg( struct groupchat *c, char *message, int flags ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); @@ -342,7 +342,7 @@ static void msn_rem_deny( struct im_connection *ic, char *who ) static int msn_send_typing( struct im_connection *ic, char *who, int typing ) { if( typing ) - return( msn_send_im( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) ); + return( msn_buddy_msg( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) ); else return( 1 ); } @@ -386,14 +386,14 @@ void msn_initmodule() ret->login = msn_login; ret->init = msn_init; ret->logout = msn_logout; - ret->send_im = msn_send_im; + ret->buddy_msg = msn_buddy_msg; ret->away_states = msn_away_states; ret->set_away = msn_set_away; ret->get_info = msn_get_info; ret->set_my_name = msn_set_my_name; ret->add_buddy = msn_add_buddy; ret->remove_buddy = msn_remove_buddy; - ret->chat_send = msn_chat_send; + ret->chat_msg = msn_chat_msg; ret->chat_invite = msn_chat_invite; ret->chat_leave = msn_chat_leave; ret->chat_with = msn_chat_with; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index c27a684d..a70d6eca 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -281,7 +281,6 @@ gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) void cancel_auto_reconnect( account_t *a ) { - /* while( b_event_remove_by_data( (gpointer) a ) ); */ b_event_remove( a->reconnect ); a->reconnect = 0; } @@ -947,7 +946,7 @@ int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags msg = buf; } - st = ic->acc->prpl->send_im( ic, handle, msg, flags ); + st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags ); g_free( buf ); return st; @@ -963,7 +962,7 @@ int imc_chat_msg( struct groupchat *c, char *msg, int flags ) msg = buf; } - c->ic->acc->prpl->chat_send( c, msg, flags ); + c->ic->acc->prpl->chat_msg( c, msg, flags ); g_free( buf ); return 1; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index c4b079ab..abf299e0 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -133,7 +133,7 @@ struct prpl { void (* keepalive) (struct im_connection *); void (* logout) (struct im_connection *); - int (* send_im) (struct im_connection *, char *to, char *message, int flags); + int (* buddy_msg) (struct im_connection *, char *to, char *message, int flags); void (* set_away) (struct im_connection *, char *state, char *message); void (* get_away) (struct im_connection *, char *who); int (* send_typing) (struct im_connection *, char *who, int flags); @@ -159,7 +159,7 @@ struct prpl { /* Group chat stuff. */ void (* chat_invite) (struct groupchat *, char *who, char *message); void (* chat_leave) (struct groupchat *); - void (* chat_send) (struct groupchat *, char *message, int flags); + void (* chat_msg) (struct groupchat *, char *message, int flags); struct groupchat * (* chat_with) (struct im_connection *, char *who); struct groupchat * @@ -174,8 +174,8 @@ struct prpl { /* im_api core stuff. */ void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); -G_MODULE_EXPORT struct prpl *find_protocol(const char *name); -G_MODULE_EXPORT void register_protocol(struct prpl *); +G_MODULE_EXPORT struct prpl *find_protocol( const char *name ); +G_MODULE_EXPORT void register_protocol( struct prpl * ); /* Connection management. */ G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index a23e8a5a..a088624a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1807,7 +1807,7 @@ static void oscar_keepalive(struct im_connection *ic) { aim_flap_nop(odata->sess, odata->conn); } -static int oscar_send_im(struct im_connection *ic, char *name, char *message, int imflags) { +static int oscar_buddy_msg(struct im_connection *ic, char *name, char *message, int imflags) { struct oscar_data *odata = (struct oscar_data *)ic->proto_data; int ret = 0, len = strlen(message); if (imflags & OPT_AWAY) { @@ -2450,7 +2450,7 @@ int oscar_send_typing(struct im_connection *ic, char * who, int typing) return( aim_im_sendmtn(od->sess, 1, who, typing ? 0x0002 : 0x0000) ); } -void oscar_chat_send(struct groupchat *c, char *message, int msgflags) +void oscar_chat_msg(struct groupchat *c, char *message, int msgflags) { struct im_connection *ic = c->ic; struct oscar_data * od = (struct oscar_data*)ic->proto_data; @@ -2589,13 +2589,13 @@ void oscar_initmodule() ret->login = oscar_login; ret->keepalive = oscar_keepalive; ret->logout = oscar_logout; - ret->send_im = oscar_send_im; + ret->buddy_msg = oscar_buddy_msg; ret->get_info = oscar_get_info; ret->set_away = oscar_set_away; ret->get_away = oscar_get_away; ret->add_buddy = oscar_add_buddy; ret->remove_buddy = oscar_remove_buddy; - ret->chat_send = oscar_chat_send; + ret->chat_msg = oscar_chat_msg; ret->chat_invite = oscar_chat_invite; ret->chat_leave = oscar_chat_leave; ret->chat_with = oscar_chat_with; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 7bf3f333..0a49baac 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -173,7 +173,7 @@ static void byahoo_get_info(struct im_connection *ic, char *who) who); } -static int byahoo_send_im( struct im_connection *ic, char *who, char *what, int flags ) +static int byahoo_buddy_msg( struct im_connection *ic, char *who, char *what, int flags ) { struct byahoo_data *yd = ic->proto_data; @@ -298,7 +298,7 @@ static void byahoo_remove_buddy( struct im_connection *ic, char *who, char *grou } } -static void byahoo_chat_send( struct groupchat *c, char *message, int flags ) +static void byahoo_chat_msg( struct groupchat *c, char *message, int flags ) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; @@ -353,7 +353,7 @@ void byahoo_initmodule( ) ret->keepalive = byahoo_keepalive; ret->logout = byahoo_logout; - ret->send_im = byahoo_send_im; + ret->buddy_msg = byahoo_buddy_msg; ret->get_info = byahoo_get_info; ret->away_states = byahoo_away_states; ret->set_away = byahoo_set_away; @@ -361,7 +361,7 @@ void byahoo_initmodule( ) ret->remove_buddy = byahoo_remove_buddy; ret->send_typing = byahoo_send_typing; - ret->chat_send = byahoo_chat_send; + ret->chat_msg = byahoo_chat_msg; ret->chat_invite = byahoo_chat_invite; ret->chat_leave = byahoo_chat_leave; ret->chat_with = byahoo_chat_with; -- cgit v1.2.3 From d11dd2f07d869282acfcdf5951f8e82d65afa234 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Apr 2007 21:22:44 -0700 Subject: Added G_GNUC_PRINTF() to imcb_(log|error) to keep an eye on fmt string issues. --- protocols/nogaim.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index abf299e0..bc91db3e 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -184,8 +184,8 @@ G_MODULE_EXPORT void imcb_connected( struct im_connection *ic ); G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect ); /* Communicating with the user. */ -G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ); -G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ); +G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ); -- cgit v1.2.3 From 17fa798247bf1a9b18de2c4848039f940d819f31 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Apr 2007 22:02:05 -0700 Subject: Jabber module should always send the status information of the primary resource now, instead of just whatever came in last. --- protocols/jabber/presence.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index f577e56a..ef92740a 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -71,10 +71,10 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; - /* FIXME: What to send if there are other resources??? */ - imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, - bud->away_message ); + if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) + imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, + ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, + bud->away_message ); } else if( strcmp( type, "unavailable" ) == 0 ) { -- cgit v1.2.3 From df1fb67d1dbf52d138f63e0d917dda2412d4fc0b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 20 Apr 2007 22:18:40 -0700 Subject: Consistency; Using OPT_T(YP|HINK)ING for outgoing typing notfication crap too. --- irc.c | 2 +- protocols/jabber/jabber.c | 10 +++++----- protocols/msn/msn.c | 2 +- protocols/nogaim.h | 4 ++-- protocols/oscar/oscar.c | 2 +- protocols/yahoo/yahoo.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/irc.c b/irc.c index 7181e660..e953bfad 100644 --- a/irc.c +++ b/irc.c @@ -1001,7 +1001,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) if( current_typing_notice - u->last_typing_notice >= 5 ) { - u->ic->acc->prpl->send_typing( u->ic, u->handle, s[8] == '1' ); + u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 ); u->last_typing_notice = current_typing_notice; } } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index c38be72e..edad5dbd 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -357,12 +357,12 @@ static int jabber_send_typing( struct im_connection *ic, char *who, int typing ) char *type; int st; - if( typing == 0 ) - type = "active"; - else if( typing == 2 ) - type = "paused"; - else /* if( typing == 1 ) */ + if( typing & OPT_TYPING ) type = "composing"; + else if( typing & OPT_THINKING ) + type = "paused"; + else + type = "active"; node = xt_new_node( type, NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_CHATSTATES ); diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 6d774806..df04e30d 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -341,7 +341,7 @@ static void msn_rem_deny( struct im_connection *ic, char *who ) static int msn_send_typing( struct im_connection *ic, char *who, int typing ) { - if( typing ) + if( typing & OPT_TYPING ) return( msn_buddy_msg( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) ); else return( 1 ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index bc91db3e..6be7b489 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -60,8 +60,8 @@ #define OPT_LOGGING_OUT 0x00000002 #define OPT_AWAY 0x00000004 #define OPT_DOES_HTML 0x00000010 -#define OPT_TYPING 0x00000100 -#define OPT_THINKING 0x00000200 +#define OPT_TYPING 0x00000100 /* Some pieces of code make assumptions */ +#define OPT_THINKING 0x00000200 /* about these values... Stupid me! */ /* ok. now the fun begins. first we create a connection structure */ struct im_connection diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index a088624a..1ca932f3 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2447,7 +2447,7 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) int oscar_send_typing(struct im_connection *ic, char * who, int typing) { struct oscar_data *od = ic->proto_data; - return( aim_im_sendmtn(od->sess, 1, who, typing ? 0x0002 : 0x0000) ); + return( aim_im_sendmtn(od->sess, 1, who, (typing & OPT_TYPING) ? 0x0002 : 0x0000) ); } void oscar_chat_msg(struct groupchat *c, char *message, int msgflags) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 0a49baac..69fc29bb 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -186,7 +186,7 @@ static int byahoo_send_typing( struct im_connection *ic, char *who, int typing ) { struct byahoo_data *yd = ic->proto_data; - yahoo_send_typing( yd->y2_id, NULL, who, typing ); + yahoo_send_typing( yd->y2_id, NULL, who, ( typing & OPT_TYPING ) != 0 ); return 1; } -- cgit v1.2.3 From c737ba70c7b3510ffb6bed8f9373e63b1a150c1b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 21 Apr 2007 19:15:36 -0700 Subject: join_chat root command works for AIM chats now. (Was trivial to add and useful for testing.) --- protocols/nogaim.h | 2 +- protocols/oscar/oscar.c | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 6be7b489..59f9e870 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -163,7 +163,7 @@ struct prpl { struct groupchat * (* chat_with) (struct im_connection *, char *who); struct groupchat * - (* chat_join) (struct im_connection *, char *chat, char *nick, char *password); + (* chat_join) (struct im_connection *, char *room, char *nick, char *password); GList *(* away_states)(struct im_connection *ic); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 1ca932f3..0c175df6 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2529,36 +2529,39 @@ void oscar_chat_leave(struct groupchat *c) oscar_chat_kill(c->ic, c->data); } -int oscar_chat_join(struct im_connection * ic, char * name) +struct groupchat *oscar_chat_join(struct im_connection * ic, char * room, char * nick, char * password ) { struct oscar_data * od = (struct oscar_data *)ic->proto_data; - aim_conn_t * cur; if((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) { - - return (aim_chatnav_createroom(od->sess, cur, name, 4) == 0); - + int st; + + st = aim_chatnav_createroom(od->sess, cur, room, 4); + + return NULL; } else { struct create_room * cr = g_new0(struct create_room, 1); + cr->exchange = 4; - cr->name = g_strdup(name); + cr->name = g_strdup(room); od->create_rooms = g_slist_append(od->create_rooms, cr); aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_CHATNAV); - return 1; + + return NULL; } } struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) { struct oscar_data * od = (struct oscar_data *)ic->proto_data; - int ret; + struct groupchat *ret; static int chat_id = 0; char * chatname; chatname = g_strdup_printf("%s%d", ic->acc->user, chat_id++); - ret = oscar_chat_join(ic, chatname); + ret = oscar_chat_join(ic, chatname, NULL, NULL); aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0); @@ -2569,7 +2572,7 @@ struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv) { - oscar_chat_join(inv->ic, inv->name); + oscar_chat_join(inv->ic, inv->name, NULL, NULL); g_free(inv->name); g_free(inv); } @@ -2599,6 +2602,7 @@ void oscar_initmodule() ret->chat_invite = oscar_chat_invite; ret->chat_leave = oscar_chat_leave; ret->chat_with = oscar_chat_with; + ret->chat_join = oscar_chat_join; ret->add_permit = oscar_add_permit; ret->add_deny = oscar_add_deny; ret->rem_permit = oscar_rem_permit; -- cgit v1.2.3 From e35d1a121d5fb2da3698fbe4a365fe38d0097665 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Apr 2007 13:44:27 -0700 Subject: Read-only support for Jabber conferences (non-anonymous rooms only). Just don't use this, you're really not going to like it. :-) --- protocols/jabber/Makefile | 2 +- protocols/jabber/conference.c | 193 +++++++++++++++++++++++++++++++++++++++++ protocols/jabber/jabber.c | 22 ++++- protocols/jabber/jabber.h | 26 +++++- protocols/jabber/jabber_util.c | 35 +++++++- protocols/jabber/message.c | 13 ++- protocols/jabber/presence.c | 29 ++++++- protocols/jabber/xmltree.c | 2 + protocols/msn/sb.c | 2 +- protocols/nogaim.c | 21 +++-- protocols/nogaim.h | 6 +- protocols/oscar/oscar.c | 2 +- protocols/yahoo/yahoo.c | 14 +-- root_commands.c | 15 +++- 14 files changed, 341 insertions(+), 41 deletions(-) create mode 100644 protocols/jabber/conference.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 3c9e4949..1d5368b1 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o +objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c new file mode 100644 index 00000000..ffc4f844 --- /dev/null +++ b/protocols/jabber/conference.c @@ -0,0 +1,193 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Jabber module - Conference rooms * +* * +* Copyright 2007 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + +#include "jabber.h" + +struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ) +{ + struct jabber_chat *jc; + struct xt_node *node; + struct groupchat *c; + char *roomjid; + + roomjid = g_strdup_printf( "%s/%s", room, nick ); + node = xt_new_node( "x", NULL, NULL ); + xt_add_attr( node, "xmlns", XMLNS_MUC ); + node = jabber_make_packet( "presence", NULL, roomjid, node ); + + if( !jabber_write_packet( ic, node ) ) + { + g_free( roomjid ); + xt_free_node( node ); + return NULL; + } + xt_free_node( node ); + + jc = g_new0( struct jabber_chat, 1 ); + jc->name = jabber_normalize( room ); + + if( ( jc->me = jabber_buddy_add( ic, roomjid ) ) == NULL ) + { + g_free( roomjid ); + g_free( jc->name ); + g_free( jc ); + return NULL; + } + g_free( roomjid ); + + c = imcb_chat_new( ic, room ); + c->data = jc; + + return c; +} + +int jabber_chat_leave( struct groupchat *c, const char *reason ) +{ + struct im_connection *ic = c->ic; + struct jabber_chat *jc = c->data; + struct xt_node *node; + + node = xt_new_node( "x", NULL, NULL ); + xt_add_attr( node, "xmlns", XMLNS_MUC ); + node = jabber_make_packet( "presence", "unavailable", jc->me->full_jid, node ); + + if( !jabber_write_packet( ic, node ) ) + { + xt_free_node( node ); + return 0; + } + xt_free_node( node ); + + /* Remove all participants from jc->buddies and clean up our data. */ + jabber_buddy_remove_bare( ic, jc->name ); + g_free( jc->name ); + g_free( jc ); + + /* And the generic stuff. */ + imcb_chat_free( c ); + + return 1; +} + +/* Not really the same syntax as the normal pkt_ functions, but this isn't + called by the xmltree parser exactly and this way I can add some extra + parameters so we won't have to repeat too many things done by the caller + already. */ +void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) +{ + struct groupchat *chat; + struct xt_node *c; + char *type = xt_find_attr( node, "type" ); + struct jabber_chat *jc; + char *s; + + if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL ) + { + /* How could this happen?? We could do kill( self, 11 ) + now or just wait for the OS to do it. :-) */ + return; + } + + jc = chat->data; + + if( type == NULL && !( bud->flags & JBFLAG_IS_CHATROOM ) ) + { + bud->flags |= JBFLAG_IS_CHATROOM; + /* If this one wasn't set yet, this buddy just joined the chat. + Slightly hackish way of finding out eh? ;-) */ + + /* This is pretty messy... */ + for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) + if( ( s = xt_find_attr( c, "xmlns" ) ) && + ( strcmp( s, XMLNS_MUC_USER ) == 0 ) ) + { + c = xt_find_node( c->children, "item" ); + if( ( s = xt_find_attr( c, "jid" ) ) ) + { + /* Yay, found what we need. :-) */ + bud->orig_jid = g_strdup( s ); + break; + } + } + + /* Won't handle this for now. */ + if( bud->orig_jid == NULL ) + return; + + s = strchr( bud->orig_jid, '/' ); + if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ + imcb_chat_add_buddy( chat, bud->orig_jid ); + if( s ) *s = '/'; + } + else if( type ) /* This only gets called if type=="unavailable" */ + { + /* Won't handle this for now. */ + if( bud->orig_jid == NULL ) + return; + s = strchr( bud->orig_jid, '/' ); + if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ + imcb_chat_remove_buddy( chat, bud->orig_jid, NULL ); + if( s ) *s = '/'; + + if( bud == jc->me ) + { + g_free( jc->name ); + g_free( jc ); + imcb_chat_free( chat ); + } + } +} + +void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) +{ + struct xt_node *body = xt_find_node( node->children, "body" ); + struct groupchat *chat; + char *s; + + if( bud == NULL ) + { + s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */ + if( strchr( s, '/' ) == NULL ) + /* This is fine, the groupchat itself isn't in jd->buddies. */ + imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" ); + else + /* This, however, isn't fine! */ + imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" ); + + return; + } + else if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL ) + { + /* How could this happen?? We could do kill( self, 11 ) + now or just wait for the OS to do it. :-) */ + return; + } + + if( body && body->text_len > 0 ) + { + s = strchr( bud->orig_jid, '/' ); + if( s ) *s = 0; + imcb_chat_msg( chat, bud->orig_jid, body->text, 0, 0 ); + if( s ) *s = '/'; + } +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index edad5dbd..f9473015 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -323,6 +323,24 @@ static void jabber_remove_buddy( struct im_connection *ic, char *who, char *grou presence_send_request( ic, who, "unsubscribe" ); } +static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room, char *nick, char *password ) +{ + if( strchr( room, '@' ) == NULL ) + imcb_error( ic, "Invalid room name: %s", room ); + else if( jabber_chat_by_name( ic, room ) ) + imcb_error( ic, "Already present in chat `%s'", room ); + else + return jabber_chat_join( ic, room, nick, password ); + + return NULL; +} + +static void jabber_chat_leave_( struct groupchat *c ) +{ + if( c ) + jabber_chat_leave( c, NULL ); +} + static void jabber_keepalive( struct im_connection *ic ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ @@ -395,8 +413,8 @@ void jabber_initmodule() ret->remove_buddy = jabber_remove_buddy; // ret->chat_msg = jabber_chat_msg; // ret->chat_invite = jabber_chat_invite; -// ret->chat_leave = jabber_chat_leave; -// ret->chat_open = jabber_chat_open; + ret->chat_leave = jabber_chat_leave_; + ret->chat_join = jabber_chat_join_; ret->keepalive = jabber_keepalive; ret->send_typing = jabber_send_typing; ret->handle_cmp = g_strcasecmp; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 42f57ae1..dd771910 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -49,6 +49,8 @@ typedef enum sure it gets sent only once. */ JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support XEP85 (typing notification shite). */ + JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for + groupchat state info too. */ } jabber_buddy_flags_t; #define JABBER_PORT_DEFAULT "5222" @@ -100,6 +102,9 @@ struct jabber_buddy char *full_jid; char *resource; + /* Groupchat-only */ + char *orig_jid; + int priority; struct jabber_away_state *away_state; char *away_message; @@ -110,6 +115,13 @@ struct jabber_buddy struct jabber_buddy *next; }; +struct jabber_chat +{ + int flags; + char *name; + struct jabber_buddy *me; +}; + /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the first one should be used, but when storing a packet in the cache, a "special" kind of ID is assigned to make it easier later to figure out @@ -133,6 +145,8 @@ struct jabber_buddy #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ +#define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ +#define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */ /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); @@ -163,18 +177,20 @@ void jabber_cache_clean( struct im_connection *ic ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); void jabber_buddy_ask( struct im_connection *ic, char *handle ); -char *jabber_normalize( char *orig ); +char *jabber_normalize( const char *orig ); typedef enum { GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */ - GET_BUDDY_EXACT = 2, /* Get an exact message (only makes sense with bare JIDs). */ + GET_BUDDY_EXACT = 2, /* Get an exact match (only makes sense with bare JIDs). */ + GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */ } get_buddy_flags_t; struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); +struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ); extern const struct jabber_away_state jabber_away_state_list[]; @@ -192,4 +208,10 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); gboolean sasl_supported( struct im_connection *ic ); +/* conference.c */ +struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ); +int jabber_chat_leave( struct groupchat *c, const char *reason ); +void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); +void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); + #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 3c0e71f4..86ddf7bc 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -47,7 +47,7 @@ char *set_eval_priority( set_t *set, char *value ) convenient, they have one disadvantage: If I would just call p_s_u() now to send the new prio setting, it would send the old setting because the set->value gets changed - when the eval returns a non-NULL value. + after the (this) eval returns a non-NULL value. So now I can choose between implementing post-set functions next to evals, or just do this little hack: */ @@ -128,7 +128,7 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so - it'll get a new id= tag, and do NOT free() the packet after writing it! */ + it'll get a new id= tag, and do NOT free() the packet after sending it! */ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = ic->proto_data; @@ -251,7 +251,7 @@ void jabber_buddy_ask( struct im_connection *ic, char *handle ) } /* Returns a new string. Don't leak it! */ -char *jabber_normalize( char *orig ) +char *jabber_normalize( const char *orig ) { int len, i; char *new; @@ -352,6 +352,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, if( ( s = strchr( jid, '/' ) ) ) { + int none_found = 0; + *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) { @@ -369,8 +371,16 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, break; } } + else + { + /* This hack is there to make sure that O_CREAT will + work if there's already another resouce present + for this JID, even if it's an unknown buddy. This + is done to handle conferences properly. */ + none_found = 1; + } - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) ) + if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) { *s = '/'; bud = jabber_buddy_add( ic, jid ); @@ -530,3 +540,20 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) return 0; } } + +struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ) +{ + char *normalized = jabber_normalize( name ); + struct groupchat *ret; + struct jabber_chat *jc; + + for( ret = ic->groupchats; ret; ret = ret->next ) + { + jc = ret->data; + if( strcmp( normalized, jc->name ) == 0 ) + break; + } + g_free( normalized ); + + return ret; +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 19edbdfd..8a4ecaf4 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -29,24 +29,29 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); struct xt_node *body = xt_find_node( node->children, "body" ), *c; + struct jabber_buddy *bud = NULL; char *s; + if( !from ) + return XT_HANDLED; /* Consider this packet corrupted. */ + + bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ); + if( type && strcmp( type, "error" ) == 0 ) { /* Handle type=error packet. */ } - else if( type && strcmp( type, "groupchat" ) == 0 ) + else if( type && from && strcmp( type, "groupchat" ) == 0 ) { - /* TODO! */ + jabber_chat_pkt_message( ic, bud, node ); } else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */ { - struct jabber_buddy *bud = NULL; GString *fullmsg = g_string_new( "" ); if( ( s = strchr( from, '/' ) ) ) { - if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) ) + if( bud ) bud->last_act = time( NULL ); else *s = 0; /* We need to generate a bare JID now. */ diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index ef92740a..096b4fd5 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -30,11 +30,20 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; struct jabber_buddy *bud; + int is_chat = 0; char *s; if( !from ) return XT_HANDLED; + if( ( s = strchr( from, '/' ) ) ) + { + *s = 0; + if( jabber_chat_by_name( ic, from ) ) + is_chat = 1; + *s = '/'; + } + if( type == NULL ) { int is_away = 0; @@ -71,23 +80,35 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; - if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) + if( is_chat ) + jabber_chat_pkt_presence( ic, bud, node ); + else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, bud->away_message ); } else if( strcmp( type, "unavailable" ) == 0 ) { - if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL ) + if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } + /* Handle this before we delete the JID. */ + if( is_chat ) + { + jabber_chat_pkt_presence( ic, bud, node ); + } + jabber_buddy_remove( ic, from ); - if( ( s = strchr( from, '/' ) ) ) + if( is_chat ) + { + /* Nothing else to do for now? */ + } + else if( ( s = strchr( from, '/' ) ) ) { *s = 0; @@ -95,6 +116,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) available anymore. */ if( jabber_buddy_by_jid( ic, from, 0 ) == NULL ) imcb_buddy_status( ic, from, 0, NULL, NULL ); + /* FIXME: If this resource was not away and another resource is, + we should definitely send an update here. */ *s = '/'; } diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 7a165a1e..c8bef362 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -187,6 +187,8 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) /* If there's no parent, the handler should mention <root> as a parent. */ g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) { + xt_print( node ); + st = xt->handlers[i].func( node, xt->data ); if( st == XT_ABORT ) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 1693cb95..cb9e2cab 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -231,7 +231,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) if( sb->chat ) { - imcb_chat_removed( sb->chat ); + imcb_chat_free( sb->chat ); } if( sb->handler ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index a70d6eca..f3dbb0b8 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -553,8 +553,8 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, irc_kill( ic->irc, u ); u->online = 0; - /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */ - for( c = ic->conversations; c; c = c->next ) + /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */ + for( c = ic->groupchats; c; c = c->next ) remove_chat_buddy_silent( c, (char*) handle ); } @@ -684,10 +684,10 @@ void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags } } -void imcb_chat_removed( struct groupchat *c ) +void imcb_chat_free( struct groupchat *c ) { struct im_connection *ic = c->ic; - struct groupchat *l = NULL; + struct groupchat *l; GList *ir; if( set_getbool( &ic->irc->set, "debug" ) ) @@ -707,10 +707,13 @@ void imcb_chat_removed( struct groupchat *c ) /* irc_part( ic->irc, u, c->channel ); */ } + /* Find the previous chat in the linked list. */ + for( l = ic->groupchats; l && l->next != c; l = l->next ); + if( l ) l->next = c->next; else - ic->conversations = c->next; + ic->groupchats = c->next; for( ir = c->in_room; ir; ir = ir->next ) g_free( ir->data ); @@ -748,13 +751,13 @@ struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) /* This one just creates the conversation structure, user won't see anything yet */ - if( ic->conversations ) + if( ic->groupchats ) { - for( c = ic->conversations; c->next; c = c->next ); + for( c = ic->groupchats; c->next; c = c->next ); c = c->next = g_new0( struct groupchat, 1 ); } else - ic->conversations = c = g_new0( struct groupchat, 1 ); + ic->groupchats = c = g_new0( struct groupchat, 1 ); c->ic = ic; c->title = g_strdup( handle ); @@ -862,7 +865,7 @@ struct groupchat *chat_by_channel( char *channel ) for( l = connections; l; l = l->next ) { ic = l->data; - for( c = ic->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); + for( c = ic->groupchats; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); if( c ) return c; } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 59f9e870..b26cf73e 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -90,17 +90,15 @@ struct im_connection /* BitlBee */ irc_t *irc; - struct groupchat *conversations; + struct groupchat *groupchats; }; struct groupchat { struct im_connection *ic; - /* stuff used just for chat */ GList *in_room; GList *ignored; - /* BitlBee */ struct groupchat *next; char *channel; char *title; @@ -207,7 +205,7 @@ G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); -G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c ); +G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); struct groupchat *chat_by_channel( char *channel ); /* Actions, or whatever. */ diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 0c175df6..b72c683a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2512,7 +2512,7 @@ void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc) struct oscar_data *od = (struct oscar_data *)ic->proto_data; /* Notify the conversation window that we've left the chat */ - imcb_chat_removed(cc->cnv); + imcb_chat_free(cc->cnv); /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 69fc29bb..28a72877 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -144,8 +144,8 @@ static void byahoo_logout( struct im_connection *ic ) struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; GSList *l; - while( ic->conversations ) - imcb_chat_removed( ic->conversations ); + while( ic->groupchats ) + imcb_chat_free( ic->groupchats ); for( l = yd->buddygroups; l; l = l->next ) { @@ -317,7 +317,7 @@ static void byahoo_chat_leave( struct groupchat *c ) struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); - imcb_chat_removed( c ); + imcb_chat_free( c ); } static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) @@ -797,7 +797,7 @@ static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv ) static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv ) { yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); - imcb_chat_removed( inv->c ); + imcb_chat_free( inv->c ); g_free( inv->name ); g_free( inv ); } @@ -840,7 +840,7 @@ void ext_yahoo_conf_userjoin( int id, const char *ignored, const char *who, cons struct im_connection *ic = byahoo_get_ic_by_id( id ); struct groupchat *c; - for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) imcb_chat_add_buddy( c, (char*) who ); @@ -852,7 +852,7 @@ void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, con struct im_connection *ic = byahoo_get_ic_by_id( id ); struct groupchat *c; - for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) imcb_chat_remove_buddy( c, (char*) who, "" ); @@ -864,7 +864,7 @@ void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const char *m = byahoo_strip( msg ); struct groupchat *c; - for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next ); + for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next ); if( c ) imcb_chat_msg( c, (char*) who, (char*) m, 0, 0 ); diff --git a/root_commands.c b/root_commands.c index a7582936..2b57fb4f 100644 --- a/root_commands.c +++ b/root_commands.c @@ -923,12 +923,21 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) } if( cmd[3] && cmd[4] ) nick = cmd[4]; + else + nick = irc->nick; if( cmd[3] && cmd[4] && cmd[5] ) password = cmd[5]; - c = a->prpl->chat_join( ic, chat, nick, password ); - - g_free( channel ); + if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) ) + { + g_free( c->channel ); + c->channel = channel; + } + else + { + irc_usermsg( irc, "Tried to join chat, not sure if this was successful" ); + g_free( channel ); + } } const command_t commands[] = { -- cgit v1.2.3 From 43671b964b636520a54e343542c5958b30e9f589 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Apr 2007 16:39:37 -0700 Subject: You can send messages too now. But it's still very kludgy and doesn't work with anonymous rooms (ie about 95% of all available Jabber chatrooms?). --- protocols/jabber/conference.c | 29 +++++++++++++++++-------- protocols/jabber/jabber.c | 9 ++++++-- protocols/jabber/jabber.h | 3 +++ protocols/jabber/jabber_util.c | 49 ++++++++++++++++++++++++++++++++++++++++++ protocols/jabber/message.c | 3 ++- protocols/jabber/xmltree.c | 2 +- 6 files changed, 82 insertions(+), 13 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index ffc4f844..397fad85 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -61,6 +61,25 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * return c; } +int jabber_chat_msg( struct groupchat *c, char *message, int flags ) +{ + struct im_connection *ic = c->ic; + struct jabber_chat *jc = c->data; + struct xt_node *node; + + node = xt_new_node( "body", message, NULL ); + node = jabber_make_packet( "message", "groupchat", jc->name, node ); + + if( !jabber_write_packet( ic, node ) ) + { + xt_free_node( node ); + return 0; + } + xt_free_node( node ); + + return 1; +} + int jabber_chat_leave( struct groupchat *c, const char *reason ) { struct im_connection *ic = c->ic; @@ -78,14 +97,6 @@ int jabber_chat_leave( struct groupchat *c, const char *reason ) } xt_free_node( node ); - /* Remove all participants from jc->buddies and clean up our data. */ - jabber_buddy_remove_bare( ic, jc->name ); - g_free( jc->name ); - g_free( jc ); - - /* And the generic stuff. */ - imcb_chat_free( c ); - return 1; } @@ -187,7 +198,7 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud { s = strchr( bud->orig_jid, '/' ); if( s ) *s = 0; - imcb_chat_msg( chat, bud->orig_jid, body->text, 0, 0 ); + imcb_chat_msg( chat, bud->orig_jid, body->text, 0, jabber_get_timestamp( node ) ); if( s ) *s = '/'; } } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index f9473015..6c0f6240 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -335,6 +335,12 @@ static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room return NULL; } +static void jabber_chat_msg_( struct groupchat *c, char *message, int flags ) +{ + if( c && message ) + jabber_chat_msg( c, message, flags ); +} + static void jabber_chat_leave_( struct groupchat *c ) { if( c ) @@ -405,13 +411,12 @@ void jabber_initmodule() ret->logout = jabber_logout; ret->buddy_msg = jabber_buddy_msg; ret->away_states = jabber_away_states; -// ret->get_status_string = jabber_get_status_string; ret->set_away = jabber_set_away; // ret->set_info = jabber_set_info; ret->get_info = jabber_get_info; ret->add_buddy = jabber_add_buddy; ret->remove_buddy = jabber_remove_buddy; -// ret->chat_msg = jabber_chat_msg; + ret->chat_msg = jabber_chat_msg_; // ret->chat_invite = jabber_chat_invite; ret->chat_leave = jabber_chat_leave_; ret->chat_join = jabber_chat_join_; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index dd771910..57e24b5f 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -143,6 +143,7 @@ struct jabber_chat #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ +#define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ @@ -191,6 +192,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, g int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ); +time_t jabber_get_timestamp( struct xt_node *xt ); extern const struct jabber_away_state jabber_away_state_list[]; @@ -210,6 +212,7 @@ gboolean sasl_supported( struct im_connection *ic ); /* conference.c */ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ); +int jabber_chat_msg( struct groupchat *ic, char *message, int flags ); int jabber_chat_leave( struct groupchat *c, const char *reason ); void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 86ddf7bc..091e6c7d 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -557,3 +557,52 @@ struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *nam return ret; } + +time_t jabber_get_timestamp( struct xt_node *xt ) +{ + struct tm tp, utc; + struct xt_node *c; + time_t res, tres; + char *s = NULL; + + for( c = xt->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) + { + if( ( s = xt_find_attr( c, "xmlns" ) ) && strcmp( s, XMLNS_DELAY ) == 0 ) + break; + } + + if( !c || !( s = xt_find_attr( c, "stamp" ) ) ) + return 0; + + memset( &tp, 0, sizeof( tp ) ); + if( sscanf( s, "%4d%2d%2dT%2d:%2d:%2d", &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) != 6 ) + return 0; + + tp.tm_year -= 1900; + tp.tm_mon --; + tp.tm_isdst = -1; /* GRRRRRRRRRRR */ + + res = mktime( &tp ); + /* Problem is, mktime() just gave us the GMT timestamp for the + given local time... While the given time WAS NOT local. So + we should fix this now. + + Now I could choose between messing with environment variables + (kludgy) or using timegm() (not portable)... Or doing the + following, which I actually prefer... */ + gmtime_r( &res, &utc ); + utc.tm_isdst = -1; /* Once more: GRRRRRRRRRRRRRRRRRR!!! */ + if( utc.tm_hour == tp.tm_hour && utc.tm_min == tp.tm_min ) + /* Sweet! We're in UTC right now... */ + return res; + + tres = mktime( &utc ); + res += res - tres; + + /* Yes, this is a hack. And it will go wrong around DST changes. + BUT this is more likely to be threadsafe than messing with + environment variables, and possibly more portable... */ + + return res; +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 8a4ecaf4..198fc3b9 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -80,7 +80,8 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) fullmsg = g_string_append( fullmsg, body->text ); if( fullmsg->len > 0 ) - imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0 ); + imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, + 0, jabber_get_timestamp( node ) ); g_string_free( fullmsg, TRUE ); diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index c8bef362..9e16b939 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -187,7 +187,7 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) /* If there's no parent, the handler should mention <root> as a parent. */ g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) { - xt_print( node ); +// xt_print( node ); st = xt->handlers[i].func( node, xt->data ); -- cgit v1.2.3 From 0e7ab64dfb66192a875c37322ca6f8a364ec5bc8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Apr 2007 19:58:44 -0700 Subject: Got rid of one HORRIBLE stupidity called chat_by_channel(), which still used the GLOBAL IM connections list, allowing user A to interfere with user B's groupchats if running in daemon mode. I can't believe this was still there... --- irc.c | 22 +++++++++++++++++++--- irc.h | 1 + irc_commands.c | 6 +++--- protocols/jabber/conference.c | 4 ++-- protocols/nogaim.c | 18 ------------------ protocols/nogaim.h | 1 - root_commands.c | 15 ++++++++++++++- 7 files changed, 39 insertions(+), 28 deletions(-) diff --git a/irc.c b/irc.c index e953bfad..eec0ce11 100644 --- a/irc.c +++ b/irc.c @@ -657,7 +657,7 @@ void irc_names( irc_t *irc, char *channel ) strcat( namelist, " " ); } } - else if( ( c = chat_by_channel( channel ) ) ) + else if( ( c = irc_chat_by_channel( irc, channel ) ) ) { GList *l; @@ -810,7 +810,7 @@ void irc_topic( irc_t *irc, char *channel ) } else { - struct groupchat *c = chat_by_channel( channel ); + struct groupchat *c = irc_chat_by_channel( irc, channel ); if( c ) irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title ); @@ -948,7 +948,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags ) if( *nick == '#' || *nick == '&' ) { - if( !( c = chat_by_channel( nick ) ) ) + if( !( c = irc_chat_by_channel( irc, nick ) ) ) { irc_reply( irc, 403, "%s :Channel does not exist", nick ); return( 0 ); @@ -1214,3 +1214,19 @@ static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ) return TRUE; } + +struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ) +{ + struct groupchat *c; + account_t *a; + + /* This finds the connection which has a conversation which belongs to this channel */ + for( a = irc->accounts; a; a = a->next ) + { + for( c = a->ic->groupchats; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); + if( c ) + return c; + } + + return NULL; +} diff --git a/irc.h b/irc.h index 5b770180..8be3579e 100644 --- a/irc.h +++ b/irc.h @@ -139,5 +139,6 @@ int irc_msgfrom( irc_t *irc, char *nick, char *msg ); int irc_noticefrom( irc_t *irc, char *nick, char *msg ); void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags ); +struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ); #endif diff --git a/irc_commands.c b/irc_commands.c index 8d841aaa..266d9732 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -143,7 +143,7 @@ static void irc_cmd_part( irc_t *irc, char **cmd ) irc_part( irc, u, irc->channel ); irc_join( irc, u, irc->channel ); } - else if( ( c = chat_by_channel( cmd[1] ) ) ) + else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) ) { user_t *u = user_find( irc, irc->nick ); @@ -200,7 +200,7 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) static void irc_cmd_invite( irc_t *irc, char **cmd ) { char *nick = cmd[1], *channel = cmd[2]; - struct groupchat *c = chat_by_channel( channel ); + struct groupchat *c = irc_chat_by_channel( irc, channel ); user_t *u = user_find( irc, nick ); if( u && c && ( u->ic == c->ic ) ) @@ -286,7 +286,7 @@ static void irc_cmd_who( irc_t *irc, char **cmd ) irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname ); u = u->next; } - else if( ( c = chat_by_channel( channel ) ) ) + else if( ( c = irc_chat_by_channel( irc, channel ) ) ) for( l = c->in_room; l; l = l->next ) { if( ( u = user_findhandle( c->ic, l->data ) ) ) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 397fad85..c16236b3 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -101,7 +101,7 @@ int jabber_chat_leave( struct groupchat *c, const char *reason ) } /* Not really the same syntax as the normal pkt_ functions, but this isn't - called by the xmltree parser exactly and this way I can add some extra + called by the xmltree parser directly and this way I can add some extra parameters so we won't have to repeat too many things done by the caller already. */ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) @@ -150,7 +150,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu imcb_chat_add_buddy( chat, bud->orig_jid ); if( s ) *s = '/'; } - else if( type ) /* This only gets called if type=="unavailable" */ + else if( type ) /* This only gets called if type is NULL or "unavailable" */ { /* Won't handle this for now. */ if( bud->orig_jid == NULL ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index f3dbb0b8..5b1c4346 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -855,24 +855,6 @@ static int remove_chat_buddy_silent( struct groupchat *b, char *handle ) /* Misc. BitlBee stuff which shouldn't really be here */ -struct groupchat *chat_by_channel( char *channel ) -{ - struct im_connection *ic; - struct groupchat *c; - GSList *l; - - /* This finds the connection which has a conversation which belongs to this channel */ - for( l = connections; l; l = l->next ) - { - ic = l->data; - for( c = ic->groupchats; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); - if( c ) - return c; - } - - return NULL; -} - char *set_eval_away_devoice( set_t *set, char *value ) { irc_t *irc = set->data; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index b26cf73e..4eb5cea1 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -206,7 +206,6 @@ G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); -struct groupchat *chat_by_channel( char *channel ); /* Actions, or whatever. */ int imc_set_away( struct im_connection *ic, char *away ); diff --git a/root_commands.c b/root_commands.c index 2b57fb4f..9965c2e8 100644 --- a/root_commands.c +++ b/root_commands.c @@ -917,7 +917,7 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) { char *s; - channel = g_strdup( chat ); + channel = g_strdup_printf( "&%s", chat ); if( ( s = strchr( channel, '@' ) ) ) *s = 0; } @@ -928,6 +928,19 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) if( cmd[3] && cmd[4] && cmd[5] ) password = cmd[5]; + if( channel[0] != '#' && channel[0] != '&' ) + { + irc_usermsg( irc, "Invalid channel name: %s", channel ); + g_free( channel ); + return; + } + else if( g_strcasecmp( channel, irc->channel ) == 0 || irc_chat_by_channel( irc, channel ) ) + { + irc_usermsg( irc, "Channel already exists: %s", channel ); + g_free( channel ); + return; + } + if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) ) { g_free( c->channel ); -- cgit v1.2.3 From 2d317bbe8def887fb796b2daaa958c59d8f4c070 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 22 Apr 2007 22:18:47 -0700 Subject: Fixes: handling of being kicked, now sending <presence/> tags to all conferences the user's in. --- protocols/jabber/conference.c | 2 ++ protocols/jabber/presence.c | 11 +++++++++++ protocols/jabber/xmltree.c | 2 +- protocols/nogaim.c | 9 ++++++--- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index c16236b3..f0d8f050 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -162,6 +162,8 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( bud == jc->me ) { + jabber_buddy_remove_bare( ic, jc->name ); + g_free( jc->name ); g_free( jc ); imcb_chat_free( chat ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 096b4fd5..1310fce3 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -167,6 +167,7 @@ int presence_send_update( struct im_connection *ic ) struct xt_node *node; char *show = jd->away_state->code; char *status = jd->away_message; + struct groupchat *c; int st; node = jabber_make_packet( "presence", NULL, NULL, NULL ); @@ -178,6 +179,16 @@ int presence_send_update( struct im_connection *ic ) st = jabber_write_packet( ic, node ); + /* Have to send this update to all groupchats too, the server won't + do this automatically. */ + for( c = ic->groupchats; c && st; c = c->next ) + { + struct jabber_chat *jc = c->data; + + xt_add_attr( node, "to", jc->me->full_jid ); + st = jabber_write_packet( ic, node ); + } + xt_free_node( node ); return st; } diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 9e16b939..c8bef362 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -187,7 +187,7 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) /* If there's no parent, the handler should mention <root> as a parent. */ g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) { -// xt_print( node ); + xt_print( node ); st = xt->handlers[i].func( node, xt->data ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 5b1c4346..5a9f5b3e 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -806,6 +806,7 @@ void imcb_chat_add_buddy( struct groupchat *b, char *handle ) } } +/* This function is one BIG hack... :-( EREWRITE */ void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) { user_t *u; @@ -817,6 +818,9 @@ void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) /* It might be yourself! */ if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) { + if( b->joined == 0 ) + return; + u = user_find( b->ic->irc, b->ic->irc->nick ); b->joined = 0; me = 1; @@ -826,9 +830,8 @@ void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) u = user_findhandle( b->ic, handle ); } - if( remove_chat_buddy_silent( b, handle ) ) - if( ( b->joined || me ) && u ) - irc_part( b->ic->irc, u, b->channel ); + if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) ) + irc_part( b->ic->irc, u, b->channel ); } static int remove_chat_buddy_silent( struct groupchat *b, char *handle ) -- cgit v1.2.3 From 6286f80d6dc1dc4cb8106b4e209a8578d7cebe56 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 25 Apr 2007 21:41:34 -0700 Subject: Prepared the Jabber module for anonymous rooms, but the BitlBee core doesn't deal with it very well, and I don't really know yet how I'll solve this... :-( --- protocols/jabber/conference.c | 31 +++++++++++++++++-------------- protocols/jabber/jabber.h | 6 ++++-- protocols/jabber/jabber_util.c | 3 +++ protocols/nogaim.h | 1 + 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index f0d8f050..dde2b8b5 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -136,28 +136,31 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( ( s = xt_find_attr( c, "jid" ) ) ) { /* Yay, found what we need. :-) */ - bud->orig_jid = g_strdup( s ); + bud->ext_jid = g_strdup( s ); break; } } - /* Won't handle this for now. */ - if( bud->orig_jid == NULL ) - return; + /* Make up some other handle, if necessary. */ + if( bud->ext_jid == NULL ) + { + /* Don't want the nick to be at the end, so let's + think of some slightly different notation to use + for anonymous groupchat participants in BitlBee. */ + bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid ); + bud->flags |= JBFLAG_IS_ANONYMOUS; + } - s = strchr( bud->orig_jid, '/' ); + s = strchr( bud->ext_jid, '/' ); if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ - imcb_chat_add_buddy( chat, bud->orig_jid ); + imcb_chat_add_buddy( chat, bud->ext_jid ); if( s ) *s = '/'; } else if( type ) /* This only gets called if type is NULL or "unavailable" */ { - /* Won't handle this for now. */ - if( bud->orig_jid == NULL ) - return; - s = strchr( bud->orig_jid, '/' ); - if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ - imcb_chat_remove_buddy( chat, bud->orig_jid, NULL ); + s = strchr( bud->ext_jid, '/' ); + if( s ) *s = 0; + imcb_chat_remove_buddy( chat, bud->ext_jid, NULL ); if( s ) *s = '/'; if( bud == jc->me ) @@ -198,9 +201,9 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud if( body && body->text_len > 0 ) { - s = strchr( bud->orig_jid, '/' ); + s = strchr( bud->ext_jid, '/' ); if( s ) *s = 0; - imcb_chat_msg( chat, bud->orig_jid, body->text, 0, jabber_get_timestamp( node ) ); + imcb_chat_msg( chat, bud->ext_jid, body->text, 0, jabber_get_timestamp( node ) ); if( s ) *s = '/'; } } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 57e24b5f..ba61920c 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -51,6 +51,8 @@ typedef enum XEP85 (typing notification shite). */ JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for groupchat state info too. */ + JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have + have a real JID. */ } jabber_buddy_flags_t; #define JABBER_PORT_DEFAULT "5222" @@ -102,8 +104,8 @@ struct jabber_buddy char *full_jid; char *resource; - /* Groupchat-only */ - char *orig_jid; + char *ext_jid; /* The JID to use in BitlBee. The real JID if possible, */ + /* otherwise something similar to the conference JID. */ int priority; struct jabber_away_state *away_state; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 091e6c7d..4dae3287 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -450,6 +450,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) { g_hash_table_remove( jd->buddies, bud->bare_jid ); g_free( bud->bare_jid ); + g_free( bud->ext_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); @@ -482,6 +483,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) item, because we're removing the first. */ g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); + g_free( bi->ext_jid ); g_free( bi->full_jid ); g_free( bi->away_message ); g_free( bi ); @@ -525,6 +527,7 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) while( bud ) { next = bud->next; + g_free( bud->ext_jid ); g_free( bud->full_jid ); g_free( bud->away_message ); g_free( bud ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 4eb5cea1..6bbee6f7 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -60,6 +60,7 @@ #define OPT_LOGGING_OUT 0x00000002 #define OPT_AWAY 0x00000004 #define OPT_DOES_HTML 0x00000010 +#define OPT_LOCALBUDDY 0x00000020 /* For nicks local to one groupchat */ #define OPT_TYPING 0x00000100 /* Some pieces of code make assumptions */ #define OPT_THINKING 0x00000200 /* about these values... Stupid me! */ -- cgit v1.2.3 From 05bcd20ba58357673225984d8f308baa6d34b726 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 27 Apr 2007 22:20:56 -0700 Subject: s/Gender: Unknown// in OSCAR profile info. If we don't know, just don't mention it, like the other vars. --- protocols/oscar/oscar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 0c175df6..426dd4a2 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2254,7 +2254,8 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) } } info_string_append(str, "\n", _("Mobile Phone"), info->mobile); - info_string_append(str, "\n", _("Gender"), info->gender==1 ? _("Female") : info->gender==2 ? _("Male") : _("Unknown")); + if (info->gender != 0) + info_string_append(str, "\n", _("Gender"), info->gender==1 ? _("Female") : _("Male")); if (info->birthyear || info->birthmonth || info->birthday) { char date[30]; struct tm tm; -- cgit v1.2.3 From bb95d43e263530805224005ca246addb6bb199fa Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 4 Jun 2007 12:32:37 +0100 Subject: Added a real XML-console to the Jabber module! Add the handle "xmlconsole" (without any @server part) to your contact list and you'll see all XMPP traffic going in and out, and messages sent to the buddy will be sent as packets to the server. --- protocols/jabber/io.c | 29 +++++++++++++++++++++++++++++ protocols/jabber/jabber.c | 21 +++++++++++++++++++++ protocols/jabber/jabber.h | 23 +++++++++++++---------- protocols/jabber/xmltree.c | 2 -- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 67deb3a6..edde5a8d 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -44,6 +44,15 @@ int jabber_write( struct im_connection *ic, char *buf, int len ) struct jabber_data *jd = ic->proto_data; gboolean ret; + if( jd->flags & JFLAG_XMLCONSOLE ) + { + char *msg; + + msg = g_strdup_printf( "TX: %s", buf ); + imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 ); + g_free( msg ); + } + if( jd->tx_len == 0 ) { /* If the queue is empty, allocate a new buffer. */ @@ -483,7 +492,27 @@ static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) return XT_HANDLED; } +static xt_status jabber_xmlconsole( struct xt_node *node, gpointer data ) +{ + struct im_connection *ic = data; + struct jabber_data *jd = ic->proto_data; + + if( jd->flags & JFLAG_XMLCONSOLE ) + { + char *msg, *pkt; + + pkt = xt_to_string( node ); + msg = g_strdup_printf( "RX: %s", pkt ); + imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 ); + g_free( msg ); + g_free( pkt ); + } + + return XT_NEXT; +} + static const struct xt_handler_entry jabber_handlers[] = { + { NULL, "stream:stream", jabber_xmlconsole }, { "stream:stream", "<root>", jabber_end_of_stream }, { "message", "stream:stream", jabber_pkt_message }, { "presence", "stream:stream", jabber_pkt_presence }, diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 6c0f6240..b70af944 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -225,6 +225,9 @@ static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, struct xt_node *node; int st; + if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) + return jabber_write( ic, message, strlen( message ) ); + bud = jabber_buddy_by_jid( ic, who, 0 ); node = xt_new_node( "body", message, NULL ); @@ -310,12 +313,30 @@ static void jabber_set_away( struct im_connection *ic, char *state_txt, char *me static void jabber_add_buddy( struct im_connection *ic, char *who, char *group ) { + struct jabber_data *jd = ic->proto_data; + + if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) + { + jd->flags |= JFLAG_XMLCONSOLE; + imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); + return; + } + if( jabber_add_to_roster( ic, who, NULL ) ) presence_send_request( ic, who, "subscribe" ); } static void jabber_remove_buddy( struct im_connection *ic, char *who, char *group ) { + struct jabber_data *jd = ic->proto_data; + + if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) + { + jd->flags &= ~JFLAG_XMLCONSOLE; + /* FIXME imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); */ + return; + } + /* We should always do this part. Clean up our administration a little bit. */ jabber_buddy_remove_bare( ic, who ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index ba61920c..2fb01fdc 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -31,16 +31,17 @@ typedef enum { - JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream + JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ - JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ - JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after + JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ + JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ - JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply + JFLAG_WAIT_SESSION = 8, /* Set if we sent a <session> tag and need a reply before we continue. */ - JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ - JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this + JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ + JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this activates all XEP-85 related code. */ + JFLAG_XMLCONSOLE = 64, /* If the user added an xmlconsole buddy. */ } jabber_flags_t; typedef enum @@ -55,10 +56,6 @@ typedef enum have a real JID. */ } jabber_buddy_flags_t; -#define JABBER_PORT_DEFAULT "5222" -#define JABBER_PORT_MIN 5220 -#define JABBER_PORT_MAX 5229 - struct jabber_data { struct im_connection *ic; @@ -124,6 +121,12 @@ struct jabber_chat struct jabber_buddy *me; }; +#define JABBER_XMLCONSOLE_HANDLE "xmlconsole" + +#define JABBER_PORT_DEFAULT "5222" +#define JABBER_PORT_MIN 5220 +#define JABBER_PORT_MAX 5229 + /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the first one should be used, but when storing a packet in the cache, a "special" kind of ID is assigned to make it easier later to figure out diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index c8bef362..7a165a1e 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -187,8 +187,6 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) /* If there's no parent, the handler should mention <root> as a parent. */ g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) { - xt_print( node ); - st = xt->handlers[i].func( node, xt->data ); if( st == XT_ABORT ) -- cgit v1.2.3 From 54f2f55f983f4b6bb8a58772bbd1137580e3307f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@hypnofrog.dub.corp.google.com> Date: Mon, 4 Jun 2007 12:45:33 +0100 Subject: Now anonymous rooms should really work. This makes sure the self-join will actually be recognized properly. This is running on my work machine for a few days already. --- protocols/jabber/conference.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index dde2b8b5..a97590ba 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -144,10 +144,14 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu /* Make up some other handle, if necessary. */ if( bud->ext_jid == NULL ) { - /* Don't want the nick to be at the end, so let's - think of some slightly different notation to use - for anonymous groupchat participants in BitlBee. */ - bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid ); + if( bud == jc->me ) + bud->ext_jid = g_strdup( ic->acc->user ); + else + /* Don't want the nick to be at the end, so let's + think of some slightly different notation to use + for anonymous groupchat participants in BitlBee. */ + bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid ); + bud->flags |= JBFLAG_IS_ANONYMOUS; } -- cgit v1.2.3 From d06eabf19ec3f849d8bab22c13d43e4eba9a48ee Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 4 Jun 2007 14:22:05 +0100 Subject: Added imcb_buddy_nick_hint so the Jabber conference module can suggest sane nicknames for chatroom participants. There'll probably be a lot of underscores now, but this is by far the cleanest way to implement this, I think. At least now whispers will work properly. Also using this function call to set names for ICQ contacts in a slightly saner way. --- nick.c | 14 ++++++++++--- nick.h | 1 + protocols/jabber/conference.c | 3 +++ protocols/jabber/iq.c | 6 +++++- protocols/nogaim.c | 47 +++++++++++++++++++++++-------------------- protocols/nogaim.h | 1 + protocols/oscar/oscar.c | 1 + 7 files changed, 47 insertions(+), 26 deletions(-) diff --git a/nick.c b/nick.c index 5e24547a..88c3faea 100644 --- a/nick.c +++ b/nick.c @@ -56,7 +56,6 @@ char *nick_get( account_t *acc, const char *handle ) { static char nick[MAX_NICK_LENGTH+1]; char *store_handle, *found_nick; - int inf_protection = 256; memset( nick, 0, MAX_NICK_LENGTH + 1 ); @@ -82,6 +81,17 @@ char *nick_get( account_t *acc, const char *handle ) } g_free( store_handle ); + /* Make sure the nick doesn't collide with an existing one by adding + underscores and that kind of stuff, if necessary. */ + nick_dedupe( acc, handle, nick ); + + return nick; +} + +void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ) +{ + int inf_protection = 256; + /* Now, find out if the nick is already in use at the moment, and make subtle changes to make it unique. */ while( !nick_ok( nick ) || user_find( acc->irc, nick ) ) @@ -119,8 +129,6 @@ char *nick_get( account_t *acc, const char *handle ) break; } } - - return nick; } /* Just check if there is a nickname set for this buddy or if we'd have to diff --git a/nick.h b/nick.h index bb7816f0..31298275 100644 --- a/nick.h +++ b/nick.h @@ -25,6 +25,7 @@ void nick_set( account_t *acc, const char *handle, const char *nick ); char *nick_get( account_t *acc, const char *handle ); +void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] ); int nick_saved( account_t *acc, const char *handle ); void nick_del( account_t *acc, const char *handle ); void nick_strip( char *nick ); diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index a97590ba..b77e037b 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -159,6 +159,9 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ imcb_chat_add_buddy( chat, bud->ext_jid ); if( s ) *s = '/'; + + if( bud != jc->me ) + imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource ); } else if( type ) /* This only gets called if type is NULL or "unavailable" */ { diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 2aa9d432..62e6a183 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -372,7 +372,11 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * imcb_add_buddy( ic, jid, ( group && group->text_len ) ? group->text : NULL ); - imcb_rename_buddy( ic, jid, name ); + if( name ) + { + imcb_rename_buddy( ic, jid, name ); + imcb_buddy_nick_hint( ic, jid, name ); + } } else if( strcmp( sub, "remove" ) == 0 ) { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 5a9f5b3e..71cebacd 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -427,7 +427,6 @@ struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ) void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) { user_t *u = user_findhandle( ic, handle ); - char *s, newnick[MAX_NICK_LENGTH+1]; if( !u || !realname ) return; @@ -439,30 +438,34 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) ) imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname ); - - if( !u->online && !nick_saved( ic->acc, handle ) ) - { - /* Detect numeric handles: */ - for( s = u->user; isdigit( *s ); s++ ); - - if( *s == 0 ) - { - /* If we reached the end of the string, it only contained numbers. - Seems to be an ICQ# then, so hopefully realname contains - something more useful. */ - strcpy( newnick, realname ); - - /* Some processing to make sure this string is a valid IRC nickname. */ - nick_strip( newnick ); - if( set_getbool( &ic->irc->set, "lcnicks" ) ) - nick_lc( newnick ); - - u->nick = g_strdup( newnick ); - } - } } } +/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM + modules to suggest a nickname for a handle. */ +void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) +{ + user_t *u = user_findhandle( ic, handle ); + char newnick[MAX_NICK_LENGTH+1]; + + if( !u->online && !nick_saved( ic->acc, handle ) ) + { + /* Only do this if the person isn't online yet (which should + be the case if we just added it) and if the user hasn't + assigned a nickname to this buddy already. */ + + strcpy( newnick, nick ); + + /* Some processing to make sure this string is a valid IRC nickname. */ + nick_strip( newnick ); + if( set_getbool( &ic->irc->set, "lcnicks" ) ) + nick_lc( newnick ); + + nick_dedupe( ic->acc, handle, newnick ); + + u->nick = g_strdup( newnick ); + } +} /* prpl.c */ diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 6bbee6f7..74a63306 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -193,6 +193,7 @@ G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, cha G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ); G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ); +G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ); /* Buddy activity */ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index b72c683a..39d14811 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2021,6 +2021,7 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { imcb_add_buddy(ic, curitem->name, NULL); if (realname) { + imcb_buddy_nick_hint(ic, curitem->name, realname); imcb_rename_buddy(ic, curitem->name, realname); g_free(realname); } -- cgit v1.2.3 From e0e2a71ed3e7937ed5da85af95be016a8441547b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 4 Jun 2007 14:36:51 +0100 Subject: Fixed retarded use of strcpy() and no longer using Jabber fullnames for nickname generation. IM fullnames and IRC nicknames are just *different*. --- bitlbee.c | 2 +- protocols/jabber/iq.c | 3 --- protocols/nogaim.c | 5 +++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 6a3625ee..c4a2da1e 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -124,7 +124,7 @@ int bitlbee_daemon_init() else if( i != 0 ) exit( 0 ); - chdir( "/" ); +// chdir( "/" ); /* Sometimes std* are already closed (for example when we're in a RESTARTed BitlBee process. So let's only close TTY-fds. */ diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 62e6a183..0050fb5b 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -373,10 +373,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * group->text : NULL ); if( name ) - { imcb_rename_buddy( ic, jid, name ); - imcb_buddy_nick_hint( ic, jid, name ); - } } else if( strcmp( sub, "remove" ) == 0 ) { diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 71cebacd..06bd8e4b 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -448,13 +448,14 @@ void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) user_t *u = user_findhandle( ic, handle ); char newnick[MAX_NICK_LENGTH+1]; - if( !u->online && !nick_saved( ic->acc, handle ) ) + if( u && !u->online && !nick_saved( ic->acc, handle ) ) { /* Only do this if the person isn't online yet (which should be the case if we just added it) and if the user hasn't assigned a nickname to this buddy already. */ - strcpy( newnick, nick ); + strncpy( newnick, nick, MAX_NICK_LENGTH ); + newnick[MAX_NICK_LENGTH] = 0; /* Some processing to make sure this string is a valid IRC nickname. */ nick_strip( newnick ); -- cgit v1.2.3 From c570c86bd6c08c77d851ac81a9603dcd13c7804a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 4 Jun 2007 16:56:09 +0100 Subject: Calling imcb_add_buddy() before setting the nickname. This is the only way to set the nickname in time before BitlBee sends the JOIN. --- protocols/jabber/conference.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index b77e037b..09a63cbc 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -155,13 +155,16 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu bud->flags |= JBFLAG_IS_ANONYMOUS; } + if( bud != jc->me ) + { + imcb_add_buddy( ic, bud->ext_jid, NULL ); + imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource ); + } + s = strchr( bud->ext_jid, '/' ); if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ imcb_chat_add_buddy( chat, bud->ext_jid ); if( s ) *s = '/'; - - if( bud != jc->me ) - imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource ); } else if( type ) /* This only gets called if type is NULL or "unavailable" */ { -- cgit v1.2.3 From 7e9dc74b15901b182be2a1d20bafdba696e4f5f2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 14 Jun 2007 00:30:59 +0100 Subject: Fixed the duplicate-nick problem. Very very very stupid bug... :-( --- protocols/nogaim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 06bd8e4b..6c564c8c 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -464,7 +464,7 @@ void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) nick_dedupe( ic->acc, handle, newnick ); - u->nick = g_strdup( newnick ); + user_rename( ic->irc, u->nick, newnick ); } } -- cgit v1.2.3 From 43d8cc5909aa45aee0b3368e70275469b0f8de22 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 14 Jun 2007 00:31:18 +0100 Subject: Fixed a memory management problem that caused some strange nickname issues. --- protocols/nogaim.c | 8 ++++++-- user.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 6c564c8c..a1a97dc3 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -446,7 +446,7 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) { user_t *u = user_findhandle( ic, handle ); - char newnick[MAX_NICK_LENGTH+1]; + char newnick[MAX_NICK_LENGTH+1], *orig_nick; if( u && !u->online && !nick_saved( ic->acc, handle ) ) { @@ -464,7 +464,11 @@ void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) nick_dedupe( ic->acc, handle, newnick ); - user_rename( ic->irc, u->nick, newnick ); + /* u->nick will be freed halfway the process, so it can't be + passed as an argument. */ + orig_nick = g_strdup( u->nick ); + user_rename( ic->irc, orig_nick, newnick ); + g_free( orig_nick ); } } diff --git a/user.c b/user.c index 232e3a58..26676dd4 100644 --- a/user.c +++ b/user.c @@ -160,6 +160,7 @@ user_t *user_findhandle( struct im_connection *ic, char *handle ) return NULL; } +/* DO NOT PASS u->nick FOR oldnick !!! */ void user_rename( irc_t *irc, char *oldnick, char *newnick ) { user_t *u = user_find( irc, oldnick ); -- cgit v1.2.3 From 998b1035a6c8349b3661861eeb5d9d1f4082ba0a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 14 Jun 2007 00:31:39 +0100 Subject: Added imcb_remove_buddy() so deletions in Jabber roster pushes actually work. This also solves the issue of underscores appearing and disappearing in their nicknames when people leave/join a chat. --- bitlbee.c | 2 +- protocols/jabber/conference.c | 4 +++- protocols/jabber/iq.c | 5 +---- protocols/jabber/jabber.c | 2 +- protocols/nogaim.c | 8 ++++++++ 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index c4a2da1e..cbccd9ea 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -69,6 +69,7 @@ int bitlbee_daemon_init() #ifdef IPV6 memset( &listen_addr6, 0, sizeof( listen_addr6 ) ); + memset( &listen_addr, 0, sizeof( listen_addr ) ); listen_addr6.sin6_family = AF_INET6; listen_addr6.sin6_port = htons( global.conf->port ); if( ( i = inet_pton( AF_INET6, ipv6_wrap( global.conf->iface ), &listen_addr6.sin6_addr ) ) != 1 ) @@ -76,7 +77,6 @@ int bitlbee_daemon_init() /* Forget about IPv6 in this function. */ use_ipv6 = 0; #endif - memset( &listen_addr, 0, sizeof( listen_addr ) ); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons( global.conf->port ); if( strcmp( global.conf->iface, "::" ) == 0 ) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 09a63cbc..1b392655 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -166,11 +166,13 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu imcb_chat_add_buddy( chat, bud->ext_jid ); if( s ) *s = '/'; } - else if( type ) /* This only gets called if type is NULL or "unavailable" */ + else if( type ) /* type can only be NULL or "unavailable" in this function */ { s = strchr( bud->ext_jid, '/' ); if( s ) *s = 0; imcb_chat_remove_buddy( chat, bud->ext_jid, NULL ); + if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS ) + imcb_remove_buddy( ic, bud->ext_jid, NULL ); if( s ) *s = '/'; if( bud == jc->me ) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 0050fb5b..e5c5dde2 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -377,11 +377,8 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * } else if( strcmp( sub, "remove" ) == 0 ) { - /* Don't have any API call for this yet! So let's - just try to handle this as well as we can. */ jabber_buddy_remove_bare( ic, jid ); - imcb_buddy_status( ic, jid, 0, NULL, NULL ); - /* FIXME! */ + imcb_remove_buddy( ic, jid, NULL ); } } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b70af944..ad28c93c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -333,7 +333,7 @@ static void jabber_remove_buddy( struct im_connection *ic, char *who, char *grou if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) { jd->flags &= ~JFLAG_XMLCONSOLE; - /* FIXME imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); */ + imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); return; } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index a1a97dc3..4f04993c 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -441,6 +441,14 @@ void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ) } } +void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ) +{ + user_t *u; + + if( ( u = user_findhandle( ic, handle ) ) ) + user_del( ic->irc, u->nick ); +} + /* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM modules to suggest a nickname for a handle. */ void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) -- cgit v1.2.3 From bdda9e9ae418e19bd8fa57a019267f567d537018 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 14 Jun 2007 00:32:56 +0100 Subject: Fixed irc_chat_by_channel() to not break if using multiple IM accounts where some of them are down. --- irc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/irc.c b/irc.c index eec0ce11..ee7288bf 100644 --- a/irc.c +++ b/irc.c @@ -1223,9 +1223,17 @@ struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel ) /* This finds the connection which has a conversation which belongs to this channel */ for( a = irc->accounts; a; a = a->next ) { - for( c = a->ic->groupchats; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next ); - if( c ) - return c; + if( a->ic == NULL ) + continue; + + c = a->ic->groupchats; + while( c ) + { + if( c->channel && g_strcasecmp( c->channel, channel ) == 0 ) + return c; + + c = c->next; + } } return NULL; -- cgit v1.2.3 From a3d5766eba9b1225d41cede5d817a48c3a3e0b7d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 20 Jun 2007 00:28:45 +0100 Subject: Not calling imcb_remove_buddy() right after removing the XML console buddy anymore. --- protocols/jabber/jabber.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index ad28c93c..f09583ec 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -333,7 +333,11 @@ static void jabber_remove_buddy( struct im_connection *ic, char *who, char *grou if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) { jd->flags &= ~JFLAG_XMLCONSOLE; + /* Not necessary for now. And for now the code isn't too + happy if the buddy is completely gone right after calling + this function already. imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); + */ return; } -- cgit v1.2.3 From f7b44f2c094f99f03182485a30d95a029a84f809 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 30 Jun 2007 22:52:44 +0100 Subject: Added help information for the join_chat command and its five arguments, which were completely undocumented so far. Also removed the import_buddies information because that command doesn't exist anymore anyway. --- doc/user-guide/commands.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 36678da2..6646d0db 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -810,27 +810,27 @@ </bitlbee-command> - <bitlbee-command name="import_buddies"> - <short-description>Copy local buddy list to server (normally only needed when upgrading)</short-description> - <syntax>import_buddies <connection> [clear]</syntax> + <bitlbee-command name="join_chat"> + <short-description>Join a named groupchat/conference room</short-description> + <syntax>import_buddies <connection> <room name> [<channel name>] [<room nickname>] [<password>]</syntax> <description> <para> - This command copies the locally stored buddy list to the server. This command exists for upgrading purposes. Previous versions of BitlBee didn't support server-side buddy lists for ICQ, so the list was stored locally. + On most IM-networks groupchats can be started using the /join command. (<emphasis>/join #foo</emphasis> to start a chatroom with you and <emphasis>foo</emphasis>) This doesn't work with names groupchats though (which exist on Jabber networks and AIM, for example), instead you can use this command. </para> <para> - Since version 0.91 however, server-side contact lists are supported for all protocols, so the local list is now ignored. When upgrading from an older BitlBee to version 0.91, you might need this command to get your buddy list back. + The first two arguments are required. <emphasis>room name</emphasis> is the name of the chatroom on the IM-network. <emphasis>channel name</emphasis> is the IRC channel name BitlBee should map this to. <emphasis>room nickname</emphasis> is the nickname you want to have in this channel. If you don't give these options, BitlBee will do the right guesses. </para> <para> - The only argument this command needs is your ICQ account identification. If your serverside buddy list contains some old buddies you don't want anymore, you can pass <emphasis>clear</emphasis> as a second argument. - </para> - - <para> - After giving this command, you have to wait for a while before all the adds are handled, because of ICQ's rate limiting. If your buddy list is very large and the ICQ server starts complaining, you might have to reconnect and enter this command again. + The following command will join you to the chatroom called <emphasis>bitlbee@conference.bitlbee.org</emphasis>. The channel will be called <emphasis>&bitlbee-help</emphasis> because <emphasis>&bitlbee</emphasis> will already be in use. Your nickname will be <emphasis>help-me</emphasis>. </para> </description> + <ircexample> + <ircline nick="wilmer">join_chat jabber bitlbee@conference.bitlbee.org &bitlbee-help help-me</ircline> + </ircexample> + </bitlbee-command> </chapter> -- cgit v1.2.3 From 7bf4326f7a9b2a2aec8b292ecbc876d4349d2624 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Jul 2007 13:20:23 +0100 Subject: Better groupchat channel name generation/verification. --- root_commands.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/root_commands.c b/root_commands.c index 9965c2e8..8ffebd8e 100644 --- a/root_commands.c +++ b/root_commands.c @@ -911,7 +911,10 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) chat = cmd[2]; if( cmd[3] ) { - channel = g_strdup( cmd[3] ); + if( channel[0] != '#' && channel[0] != '&' ) + channel = g_strdup_printf( "&%s", cmd[3] ); + else + channel = g_strdup( cmd[3] ); } else { @@ -928,7 +931,7 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) if( cmd[3] && cmd[4] && cmd[5] ) password = cmd[5]; - if( channel[0] != '#' && channel[0] != '&' ) + if( !nick_ok( channel + 1 ) ) { irc_usermsg( irc, "Invalid channel name: %s", channel ); g_free( channel ); -- cgit v1.2.3 From 40ef702d3e500eb38d7410114ace54e8a70b151e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Jul 2007 14:08:47 +0100 Subject: Less copy-pasting in the service discovery reply and added MUC support to that list. And adding some const stuff in the xmltree functions. --- protocols/jabber/iq.c | 27 +++++++++++++-------------- protocols/jabber/xmltree.c | 8 ++++---- protocols/jabber/xmltree.h | 8 ++++---- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e5c5dde2..4738817a 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -98,26 +98,25 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { + const char *features[] = { XMLNS_VERSION, + XMLNS_TIME, + XMLNS_CHATSTATES, + XMLNS_MUC, + NULL }; + const char **f; + c = xt_new_node( "identity", NULL, NULL ); xt_add_attr( c, "category", "client" ); xt_add_attr( c, "type", "pc" ); xt_add_attr( c, "name", "BitlBee" ); xt_add_child( reply, c ); - c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", XMLNS_VERSION ); - xt_add_child( reply, c ); - - c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", XMLNS_TIME ); - xt_add_child( reply, c ); - - c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", XMLNS_CHATSTATES ); - xt_add_child( reply, c ); - - /* Later this can be useful to announce things like - MUC support. */ + for( f = features; *f; f ++ ) + { + c = xt_new_node( "feature", NULL, NULL ); + xt_add_attr( c, "var", *f ); + xt_add_child( reply, c ); + } } else { diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 7a165a1e..b1edd55d 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -441,7 +441,7 @@ void xt_free( struct xt_parser *xt ) /* To find a node's child with a specific name, pass the node's children list, not the node itself! The reason you have to do this by hand: So that you can also use this function as a find-next. */ -struct xt_node *xt_find_node( struct xt_node *node, char *name ) +struct xt_node *xt_find_node( struct xt_node *node, const char *name ) { while( node ) { @@ -454,7 +454,7 @@ struct xt_node *xt_find_node( struct xt_node *node, char *name ) return node; } -char *xt_find_attr( struct xt_node *node, char *key ) +char *xt_find_attr( struct xt_node *node, const char *key ) { int i; @@ -523,7 +523,7 @@ void xt_add_child( struct xt_node *parent, struct xt_node *child ) } } -void xt_add_attr( struct xt_node *node, char *key, char *value ) +void xt_add_attr( struct xt_node *node, const char *key, const char *value ) { int i; @@ -550,7 +550,7 @@ void xt_add_attr( struct xt_node *node, char *key, char *value ) node->attr[i].value = g_strdup( value ); } -int xt_remove_attr( struct xt_node *node, char *key ) +int xt_remove_attr( struct xt_node *node, const char *key ) { int i, last; diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h index 70850c1d..b8b61641 100644 --- a/protocols/jabber/xmltree.h +++ b/protocols/jabber/xmltree.h @@ -86,12 +86,12 @@ void xt_print( struct xt_node *node ); struct xt_node *xt_dup( struct xt_node *node ); void xt_free_node( struct xt_node *node ); void xt_free( struct xt_parser *xt ); -struct xt_node *xt_find_node( struct xt_node *node, char *name ); -char *xt_find_attr( struct xt_node *node, char *key ); +struct xt_node *xt_find_node( struct xt_node *node, const char *name ); +char *xt_find_attr( struct xt_node *node, const char *key ); struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); void xt_add_child( struct xt_node *parent, struct xt_node *child ); -void xt_add_attr( struct xt_node *node, char *key, char *value ); -int xt_remove_attr( struct xt_node *node, char *key ); +void xt_add_attr( struct xt_node *node, const char *key, const char *value ); +int xt_remove_attr( struct xt_node *node, const char *key ); #endif -- cgit v1.2.3 From 2758cfed0abcb529975af34fdb4d2603febbf1a3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Jul 2007 16:22:42 +0100 Subject: Properly updating away state info if one resource goes down while another one's still there. Not sending offline notifications is great, but updating the away state info is even better. :-) --- protocols/jabber/presence.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 1310fce3..63d4f66a 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -30,7 +30,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; struct jabber_buddy *bud; - int is_chat = 0; + int is_chat = 0, is_away = 0; char *s; if( !from ) @@ -46,8 +46,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( type == NULL ) { - int is_away = 0; - if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) @@ -112,12 +110,23 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { *s = 0; - /* Only count this as offline if there's no other resource - available anymore. */ - if( jabber_buddy_by_jid( ic, from, 0 ) == NULL ) + /* If another resource is still available, send its presence + information. */ + if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) ) + { + if( bud->away_state && ( *bud->away_state->code == 0 || + strcmp( bud->away_state->code, "chat" ) == 0 ) ) + is_away = OPT_AWAY; + + imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, + ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, + bud->away_message ); + } + else + { + /* Otherwise, count him/her as offline now. */ imcb_buddy_status( ic, from, 0, NULL, NULL ); - /* FIXME: If this resource was not away and another resource is, - we should definitely send an update here. */ + } *s = '/'; } -- cgit v1.2.3 From b9f8b870f7b884747b747be91ce0ac797a7c6e82 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Jul 2007 17:29:21 +0100 Subject: Better handling of private messages via groupchats. --- protocols/jabber/conference.c | 8 +++++--- protocols/jabber/jabber.c | 6 +++++- protocols/jabber/jabber.h | 1 + protocols/jabber/jabber_util.c | 37 ++++++++++++++++++++++++++++++++++++- protocols/jabber/message.c | 11 +++++++---- 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 1b392655..d8c18df7 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -127,7 +127,9 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu /* If this one wasn't set yet, this buddy just joined the chat. Slightly hackish way of finding out eh? ;-) */ - /* This is pretty messy... */ + /* This is pretty messy... Here it sets ext_jid to the real + JID of the participant. Works for non-anonymized channels. + Might break if someone joins a chat twice, though. */ for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) if( ( s = xt_find_attr( c, "xmlns" ) ) && ( strcmp( s, XMLNS_MUC_USER ) == 0 ) ) @@ -136,7 +138,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( ( s = xt_find_attr( c, "jid" ) ) ) { /* Yay, found what we need. :-) */ - bud->ext_jid = g_strdup( s ); + bud->ext_jid = jabber_normalize( s ); break; } } @@ -145,7 +147,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( bud->ext_jid == NULL ) { if( bud == jc->me ) - bud->ext_jid = g_strdup( ic->acc->user ); + bud->ext_jid = jabber_normalize( ic->acc->user ); else /* Don't want the nick to be at the end, so let's think of some slightly different notation to use diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index f09583ec..e1cef48b 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -223,12 +223,16 @@ static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; struct xt_node *node; + char *s; int st; if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) return jabber_write( ic, message, strlen( message ) ); - bud = jabber_buddy_by_jid( ic, who, 0 ); + if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) ) + bud = jabber_buddy_by_ext_jid( ic, who, 0 ); + else + bud = jabber_buddy_by_jid( ic, who, 0 ); node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 2fb01fdc..51550af8 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -194,6 +194,7 @@ typedef enum struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); +struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 4dae3287..53f97ff0 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -319,6 +319,8 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ } else { + /* Keep in mind that full_jid currently isn't really + a full JID... */ new->bare_jid = g_strdup( full_jid ); g_hash_table_insert( jd->buddies, new->bare_jid, new ); } @@ -332,7 +334,8 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ else { /* Let's waste some more bytes of RAM instead of to make - memory management a total disaster here.. */ + memory management a total disaster here. And it saves + me one g_free() call in this function. :-P */ new->full_jid = full_jid; } @@ -427,6 +430,38 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, } } +/* I'm keeping a separate ext_jid attribute to save a JID that makes sense + to export to BitlBee. This is mainly for groupchats right now. It's + a bit of a hack, but I just think having the user nickname in the hostname + part of the hostmask doesn't look nice on IRC. Normally you can convert + a normal JID to ext_jid by swapping the part before and after the / and + replacing the / with a =. But there should be some stripping (@s are + allowed in Jabber nicks...). */ +struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) +{ + struct jabber_buddy *bud; + char *s, *jid; + + jid = jabber_normalize( jid_ ); + + if( ( s = strchr( jid, '=' ) ) == NULL ) + return NULL; + + for( bud = jabber_buddy_by_jid( ic, s + 1, GET_BUDDY_FIRST ); bud; bud = bud->next ) + { + /* Hmmm, could happen if not all people in the chat are anonymized? */ + if( bud->ext_jid == NULL ) + continue; + + if( strcmp( bud->ext_jid, jid ) == 0 ) + break; + } + + g_free( jid ); + + return bud; +} + /* Remove one specific full JID from our list. Use this when a buddy goes off-line (because (s)he can still be online from a different location. XXX: See above, we should accept bare JIDs too... */ diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 198fc3b9..52ee3a53 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -52,7 +52,10 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( ( s = strchr( from, '/' ) ) ) { if( bud ) + { bud->last_act = time( NULL ); + from = bud->ext_jid ? : bud->bare_jid; + } else *s = 0; /* We need to generate a bare JID now. */ } @@ -80,7 +83,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) fullmsg = g_string_append( fullmsg, body->text ); if( fullmsg->len > 0 ) - imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, + imcb_buddy_msg( ic, from, fullmsg->str, 0, jabber_get_timestamp( node ) ); g_string_free( fullmsg, TRUE ); @@ -89,18 +92,18 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) if( xt_find_node( node->children, "composing" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_TYPING ); + imcb_buddy_typing( ic, from, OPT_TYPING ); } /* No need to send a "stopped typing" signal when there's a message. */ else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, bud ? bud->bare_jid : from, 0 ); + imcb_buddy_typing( ic, from, 0 ); } else if( xt_find_node( node->children, "paused" ) ) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_THINKING ); + imcb_buddy_typing( ic, from, OPT_THINKING ); } if( s ) -- cgit v1.2.3 From 9c9b37cbfa27a038bc57624cb9001f8db019290c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 1 Jul 2007 20:58:23 +0100 Subject: Keeping an original (not normalized) copy of the user's nickname. This fixes a bug reported by James Teh in the monster ticket #20. There's no proper garbage collection yet in the Jabber conference code, really have to do that soon. :-( --- protocols/jabber/conference.c | 7 +++++-- protocols/jabber/jabber.h | 1 + protocols/jabber/presence.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index d8c18df7..d236f0bb 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -53,7 +53,10 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * g_free( jc ); return NULL; } - g_free( roomjid ); + + /* roomjid isn't normalized yet, and we need an original version + of the nick to send a proper presence update. */ + jc->my_full_jid = roomjid; c = imcb_chat_new( ic, room ); c->data = jc; @@ -88,7 +91,7 @@ int jabber_chat_leave( struct groupchat *c, const char *reason ) node = xt_new_node( "x", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_MUC ); - node = jabber_make_packet( "presence", "unavailable", jc->me->full_jid, node ); + node = jabber_make_packet( "presence", "unavailable", jc->my_full_jid, node ); if( !jabber_write_packet( ic, node ) ) { diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 51550af8..bc639fea 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -118,6 +118,7 @@ struct jabber_chat { int flags; char *name; + char *my_full_jid; /* Separate copy because of case sensitivity. */ struct jabber_buddy *me; }; diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 63d4f66a..e53978ea 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -194,7 +194,7 @@ int presence_send_update( struct im_connection *ic ) { struct jabber_chat *jc = c->data; - xt_add_attr( node, "to", jc->me->full_jid ); + xt_add_attr( node, "to", jc->my_full_jid ); st = jabber_write_packet( ic, node ); } -- cgit v1.2.3 From c3774175d29802202afb226a2661d0c3c52fb7b1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Jul 2007 10:30:48 +0100 Subject: Cleaning up groupchats when shutting down the Jabber connection. The cleaning up of groupchats isn't done very well yet, but this will at least keep things sane. --- protocols/jabber/jabber.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e1cef48b..9df1dc74 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -196,6 +196,9 @@ static void jabber_logout( struct im_connection *ic ) jabber_end_stream( ic ); + while( ic->groupchats ) + imcb_chat_free( ic->groupchats ); + if( jd->r_inpa >= 0 ) b_event_remove( jd->r_inpa ); if( jd->w_inpa >= 0 ) -- cgit v1.2.3 From 1962ac169c14c7b24e276caac0976b8983496fd5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Jul 2007 22:07:43 +0100 Subject: Fixed nick hint function to only set the nick if it's different from the current one (otherwise the dedupe function will dedupe the nick against itself). --- protocols/nogaim.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 4f04993c..22d82ecb 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -470,13 +470,19 @@ void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick ) if( set_getbool( &ic->irc->set, "lcnicks" ) ) nick_lc( newnick ); - nick_dedupe( ic->acc, handle, newnick ); - - /* u->nick will be freed halfway the process, so it can't be - passed as an argument. */ - orig_nick = g_strdup( u->nick ); - user_rename( ic->irc, orig_nick, newnick ); - g_free( orig_nick ); + if( strcmp( u->nick, newnick ) != 0 ) + { + /* Only do this if newnick is different from the current one. + If rejoining a channel, maybe we got this nick already + (and dedupe would only add an underscore. */ + nick_dedupe( ic->acc, handle, newnick ); + + /* u->nick will be freed halfway the process, so it can't be + passed as an argument. */ + orig_nick = g_strdup( u->nick ); + user_rename( ic->irc, orig_nick, newnick ); + g_free( orig_nick ); + } } } -- cgit v1.2.3 From 5d7dc007a418be0c897000e888e747047729c756 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Jul 2007 22:24:04 +0100 Subject: Stripping of unwanted characters (@ and =) in channel nicknames. --- protocols/jabber/conference.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index d236f0bb..24b5631a 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -150,13 +150,23 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( bud->ext_jid == NULL ) { if( bud == jc->me ) + { bud->ext_jid = jabber_normalize( ic->acc->user ); + } else + { + int i; + /* Don't want the nick to be at the end, so let's think of some slightly different notation to use for anonymous groupchat participants in BitlBee. */ bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid ); - + + /* And strip any unwanted characters. */ + for( i = 0; bud->resource[i]; i ++ ) + if( bud->ext_jid[i] == '=' || bud->ext_jid[i] == '@' ) + bud->ext_jid[i] = '_'; + } bud->flags |= JBFLAG_IS_ANONYMOUS; } -- cgit v1.2.3 From 9da0bbfd42609f0f3864b5a16a3c1c378b7217c9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 2 Jul 2007 23:12:03 +0100 Subject: Added (and using) jabber_chat_free() for better memory management, fixed channel name generation code in root_commands.c and fixed one memory leak in jabber_buddy_remove_bare(). --- protocols/jabber/conference.c | 21 ++++++++++++++------- protocols/jabber/jabber.c | 2 +- protocols/jabber/jabber.h | 1 + protocols/jabber/jabber_util.c | 19 +++++++++++-------- root_commands.c | 2 +- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 24b5631a..f49dbd1c 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -64,6 +64,19 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * return c; } +void jabber_chat_free( struct groupchat *c ) +{ + struct jabber_chat *jc = c->data; + + jabber_buddy_remove_bare( c->ic, jc->name ); + + g_free( jc->my_full_jid ); + g_free( jc->name ); + g_free( jc ); + + imcb_chat_free( c ); +} + int jabber_chat_msg( struct groupchat *c, char *message, int flags ) { struct im_connection *ic = c->ic; @@ -191,13 +204,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu if( s ) *s = '/'; if( bud == jc->me ) - { - jabber_buddy_remove_bare( ic, jc->name ); - - g_free( jc->name ); - g_free( jc ); - imcb_chat_free( chat ); - } + jabber_chat_free( chat ); } } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 9df1dc74..9176cd68 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -197,7 +197,7 @@ static void jabber_logout( struct im_connection *ic ) jabber_end_stream( ic ); while( ic->groupchats ) - imcb_chat_free( ic->groupchats ); + jabber_chat_free( ic->groupchats ); if( jd->r_inpa >= 0 ) b_event_remove( jd->r_inpa ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index bc639fea..90c1e9f6 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -219,6 +219,7 @@ gboolean sasl_supported( struct im_connection *ic ); /* conference.c */ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ); +void jabber_chat_free( struct groupchat *c ); int jabber_chat_msg( struct groupchat *ic, char *message, int flags ); int jabber_chat_leave( struct groupchat *c, const char *reason ); void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 53f97ff0..5b91c5ed 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -541,26 +541,31 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) +int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *next; - char *bare_jid; - if( strchr( bare_jid_, '/' ) ) + if( strchr( bare_jid, '/' ) ) return 0; - bare_jid = jabber_normalize( bare_jid_ ); - - if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) + if( ( bud = jabber_buddy_by_jid( ic, bare_jid, GET_BUDDY_FIRST ) ) ) { /* Most important: Remove the hash reference. We don't know this buddy anymore. */ g_hash_table_remove( jd->buddies, bud->bare_jid ); + g_free( bud->bare_jid ); /* Deallocate the linked list of resources. */ while( bud ) { + /* ext_jid && anonymous means that this buddy is + specific to one groupchat (the one we're + currently cleaning up) so it can be deleted + completely. */ + if( bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS ) + imcb_remove_buddy( ic, bud->ext_jid, NULL ); + next = bud->next; g_free( bud->ext_jid ); g_free( bud->full_jid ); @@ -569,12 +574,10 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ ) bud = next; } - g_free( bare_jid ); return 1; } else { - g_free( bare_jid ); return 0; } } diff --git a/root_commands.c b/root_commands.c index 8ffebd8e..0f9f776c 100644 --- a/root_commands.c +++ b/root_commands.c @@ -911,7 +911,7 @@ static void cmd_join_chat( irc_t *irc, char **cmd ) chat = cmd[2]; if( cmd[3] ) { - if( channel[0] != '#' && channel[0] != '&' ) + if( cmd[3][0] != '#' && cmd[3][0] != '&' ) channel = g_strdup_printf( "&%s", cmd[3] ); else channel = g_strdup( cmd[3] ); -- cgit v1.2.3 From 19a8088455308088139d0b2f6a8d0d4fbf982b29 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 6 Jul 2007 00:36:48 +0100 Subject: Adding debian/ tree to the repository again. Updated it to include all 1.0.x versions and some other changes. Might soon start building snapshots again. :-) --- debian/README.Debian | 22 ++ debian/bitlbee.init | 82 +++++ debian/changelog | 306 +++++++++++++++++ debian/conffiles | 2 + debian/config | 19 + debian/control | 13 + debian/copyright | 895 ++++++++++++++++++++++++++++++++++++++++++++++++ debian/po/POTFILES.in | 1 + debian/po/cs.po | 44 +++ debian/po/de.po | 45 +++ debian/po/es.po | 61 ++++ debian/po/fr.po | 44 +++ debian/po/ja.po | 45 +++ debian/po/nl.po | 44 +++ debian/po/pt.po | 35 ++ debian/po/pt_BR.po | 44 +++ debian/po/sv.po | 43 +++ debian/po/templates.pot | 41 +++ debian/po/vi.po | 32 ++ debian/postinst | 68 ++++ debian/postrm | 11 + debian/prerm | 8 + debian/rules | 83 +++++ debian/templates | 8 + 24 files changed, 1996 insertions(+) create mode 100644 debian/README.Debian create mode 100755 debian/bitlbee.init create mode 100644 debian/changelog create mode 100644 debian/conffiles create mode 100755 debian/config create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/po/POTFILES.in create mode 100644 debian/po/cs.po create mode 100644 debian/po/de.po create mode 100644 debian/po/es.po create mode 100644 debian/po/fr.po create mode 100644 debian/po/ja.po create mode 100644 debian/po/nl.po create mode 100644 debian/po/pt.po create mode 100644 debian/po/pt_BR.po create mode 100644 debian/po/sv.po create mode 100644 debian/po/templates.pot create mode 100644 debian/po/vi.po create mode 100755 debian/postinst create mode 100755 debian/postrm create mode 100755 debian/prerm create mode 100755 debian/rules create mode 100644 debian/templates diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 00000000..e2102fc8 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,22 @@ + *** NEWS (Version 1.1 and later) *** + +Starting from version 1.1, BitlBee has a forking daemon mode. The Debian +package now uses this mode by default, instead of inetd mode. If you don't +want to use this, you can disable the init scripts (best way to do this is +by editing /etc/default/bitlbee) and restore the inetd.conf entry. This +should be necessary only once, it won't be touched during upgrades. + +-------------------------------------------------------------------------- + +Debconf should have asked you on what port you want BitlBee to run. If it +did not, the port number should be 6667 or 6668. (6668 if you already got +something running at 6667) + +Fire up your favourite IRC client and connect to localhost:6667 (or 6668), +and read the documentation (type help for a list of commands). + +Have fun! + +The /usr/share/doc/bitlbee/examples/ directory contains some programs and +scripts you might like or need. They're not really examples but it's quite +normal behaviour to put small contrib stuff like that in there. diff --git a/debian/bitlbee.init b/debian/bitlbee.init new file mode 100755 index 00000000..baf1a0c6 --- /dev/null +++ b/debian/bitlbee.init @@ -0,0 +1,82 @@ +#! /bin/sh +# +# Init script for BitlBee Debian package. Based on skeleton init script: +# +# Version: @(#)skeleton 2.85-23 28-Jul-2004 miquels@cistron.nl +# + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DESC="BitlBee IRC/IM gateway" +NAME=bitlbee +DAEMON=/usr/sbin/$NAME +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Gracefully exit if the package has been removed. +[ -x $DAEMON ] || exit 0 + +# Default value +BITLBEE_PORT=6667 +DAEMON_OPT=-F + +# Read config file if it is present. +if [ -r /etc/default/$NAME ]; then + . /etc/default/$NAME +fi + +[ "$BITLBEE_DISABLED" = "1" ] && exit 0 + + +# +# Function that starts the daemon/service. +# +d_start() { + # Make sure BitlBee can actually write its PID... + touch /var/run/bitlbee.pid + chown bitlbee /var/run/bitlbee.pid + + start-stop-daemon --start --quiet --pidfile $PIDFILE \ + -c bitlbee -g nogroup \ + --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $DAEMON_OPT +} + +# +# Function that stops the daemon/service. +# +d_stop() { + start-stop-daemon --stop --quiet --pidfile $PIDFILE \ + --name $NAME +} + + +case "$1" in + start) + echo -n "Starting $DESC: $NAME" + d_start + echo "." + ;; + stop) + echo -n "Stopping $DESC: $NAME" + d_stop + echo "." + ;; + #reload) + # + # No reload target, but there's a REHASH command which we + # might use later... + # + #;; + restart|force-reload) + echo -n "Restarting $DESC: $NAME" + d_stop + sleep 1 + d_start + echo "." + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000..c48704b9 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,306 @@ +bitlbee (1.1.1dev-0pre) unstable; urgency=low + + * Switched to the new forking daemon mode. Added /etc/default/bitlbee + file, an init script. People who want to stick with inetd can do so, see + the defaults file. + * Got rid of debconf Woody compatibility stuff. + + -- Wilmer van der Gaast <wilmer@gaast.net> Fri, 6 Jul 2007 00:27:38 +0100 + +bitlbee (1.0.3-1.3) unstable; urgency=low + + * Non-maintainer upload to fix a minor error. + * Remove extra debian/#rules# + + -- Christian Perrier <bubulle@debian.org> Tue, 20 Feb 2007 07:49:18 +0100 + +bitlbee (1.0.3-1.2) unstable; urgency=low + + * Non-maintainer upload to fix pending l10n issues. + * Debconf translations: + - Portuguese. Closes: #386348 + + -- Christian Perrier <bubulle@debian.org> Sun, 18 Feb 2007 20:23:28 +0100 + +bitlbee (1.0.3-1.1) unstable; urgency=low + + * Non-maintainer upload. + * debian/control: Replace netkit-inetd dependency with a versioned + dependency on netbase. netbase provides the appropriate inetd + dependency. Closes: #382682. + + -- Roger Leigh <rleigh@debian.org> Sun, 20 Aug 2006 17:07:02 +0100 + +bitlbee (1.0.3-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 8 Jul 2006 11:32:57 +0200 + +bitlbee (1.0.2-2) unstable; urgency=low + + * Added a po-debconf build-dependency, which I forgot when removing the + Woody hack from 1.0.2-1. (Closes: #361503) + + -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 8 Apr 2006 22:09:19 +0200 + +bitlbee (1.0.2-1) unstable; urgency=low + + * New upstream release. + * Avoids calling update-inetd if it's unavailable. (Closes: #350463) + * Also using userdel instead of deluser now to avoid another bug. :-) + * Only creates an inetd.conf entry when installing for the first time. + (Closes: #349570) (This unfortunately breaks dpkg-reconfigure, but at + least there's a warning...) + + -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 8 Apr 2006 14:17:52 +0200 + +bitlbee (1.0.1-1) unstable; urgency=low + + * New upstream release + + -- Wilmer van der Gaast <wilmer@gaast.net> Tue, 17 Jan 2006 17:26:20 +0100 + +bitlbee (1.0-1) unstable; urgency=low + + * New upstream release + * bitlbee has a useless Build-Depends: on debconf-2.0 (Closes: + #341783) + + -- Wilmer van der Gaast <wilmer@gaast.net> Mon, 5 Dec 2005 17:59:07 +0100 + +bitlbee (0.99-1) unstable; urgency=low + + * Should build on Debian GNU/kFreeBSD now. (Closes: #336965) + * New upstream version. + + -- Wilmer van der Gaast <wilmer@gaast.net> Thu, 3 Nov 2005 21:06:53 +0100 + +bitlbee (0.93a-1) unstable; urgency=low + + * Added Swedish and Spanish translations. (Closes: #333881, #331302) + * Changed debconf dependency. (Closes: #331762) + * Changed libgnutls dependency. (Closes: #335751) + * Fixed one crash-on-disconnect bug in the OSCAR module. + + -- Wilmer van der Gaast <wilmer@gaast.net> Tue, 1 Nov 2005 18:25:56 +0100 + +bitlbee (0.92-2) unstable; urgency=low + + * Added the patch that allows to connect to alternate Jabber servers. + Necessary for connecting to Google Talk. (Closes: #324832) + * Also possibly fixes some more problems with losing data when disk is + full. + * Added Vietnamese and Brazilian DebConf translations. Sorry for being + so late. (Closes: #297058, #313158) + + -- Wilmer van der Gaast <lintux@debian.org> Thu, 8 Sep 2005 19:55:56 +0200 + +bitlbee (0.92-1) unstable; urgency=low + + * New upstream release. + * Implemented support for the IRC WATCH command and got rid of the + IRC_MAX_ARGS limit. (Closes: #283504) + * Added Czech translation. (Closes: #293615) + + -- Wilmer van der Gaast <lintux@debian.org> Thu, 24 Feb 2005 17:11:32 +0100 + +bitlbee (0.91-3) unstable; urgency=low + + * Fixed a small bug in postrm which caused problems when removing/upgrading. + + -- Wilmer van der Gaast <lintux@debian.org> Sun, 10 Oct 2004 08:59:52 +0200 + +bitlbee (0.91-2) unstable; urgency=low + + * Removed the part that messes with tcpd configuration files because it + causes troubles for some people and because it's no problem for users + to edit those files by hand. (Closes: #275418) + When upgrading from previous versions, the bitlbee line won't be removed + from your tcpd conffiles. (This is only done when purging a BitlBee + install) You don't have to worry about BitlBee suddenly opening for the + whole world because of the removal of this feature. + * Updated German translation. (Closes: #274655) + * Removed the unreliable check for an existing BitlBee installation (a + /etc/passwd grep) and replaced it with something more reliable. + + -- Wilmer van der Gaast <lintux@debian.org> Sat, 9 Oct 2004 19:06:33 +0200 + +bitlbee (0.91-1) unstable; urgency=low + + * info-command works for Jabber connections now. (Closes: #232712) + * Saner code for duplicate nickname prevention. (Closes: #234285) + * Support for Jabber connections over SSL. (Closes: #252458) + * If the user chooses for noinetd.conf installation, this setting is now + remembered during reinstalls. (Closes: #260533) + * An up-to-date Japanse DebConf template. (Closes: #271091) + + -- Wilmer van der Gaast <lintux@debian.org> Sat, 25 Sep 2004 18:18:17 +0200 + +bitlbee (0.90a-2) unstable; urgency=low + + * Using libgnutls11 now. (Closes: #264740) + * postinst no longer appends newlines to hosts.* because grep already + makes sure the last line is terminated with a newline. (Closes: #253278) + * Added Japanese DebConf templates. (Closes: #259801) + * Installing BitlBee in inetd.conf is now optional. (Closes: #260533) + + -- Wilmer van der Gaast <lintux@debian.org> Mon, 6 Sep 2004 20:04:22 +0200 + +bitlbee (0.90a-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <lintux@debian.org> Mon, 28 Jun 2004 20:30:26 +0200 + +bitlbee (0.90-1) unstable; urgency=low + + * New upstream release. + * Added German DebConf translation. (Closes: #250787) + + -- Wilmer van der Gaast <lintux@debian.org> Sat, 29 May 2004 11:51:56 +0200 + +bitlbee (0.85a-1) unstable; urgency=low + + * New upstream release. This one should fix build problems on arm. + + -- Wilmer van der Gaast <lintux@debian.org> Thu, 25 Mar 2004 00:12:33 +0100 + +bitlbee (0.85-1) unstable; urgency=low + + * New upstream release. + * This version has a command line switch to specify alternate configuration + files/settings directories. (Closes: #207060) + + -- Wilmer van der Gaast <lintux@debian.org> Sat, 13 Mar 2004 22:19:35 +0100 + +bitlbee (0.84-2) unstable; urgency=low + + * Converted debconf templates to po2debconf format, without breaking + building on older (non-po2debconf) systems. Thanks to Martin Quinson. + (Closes: #205816) + * Added French debconf templates. Thanks to Christian Perrier. + (Closes: #206593) + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 3 Mar 2004 21:19:12 +0100 + +bitlbee (0.84-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <lintux@debian.org> Fri, 13 Feb 2004 20:13:53 +0100 + +bitlbee (0.83-2) unstable; urgency=low + + * Removed libsoup dependency, BitlBee now uses libgnutls directly. + (Closes: #208475, #230895) + * Now including preprocessed documentation files to save some time on + slow buildd's (and fix build problems on archs without a working + sgmltools package). + + -- Wilmer van der Gaast <lintux@debian.org> Fri, 6 Feb 2004 01:26:27 +0100 + +bitlbee (0.83-1) unstable; urgency=low + + * Added bitlbee.conf to conffiles. Should've done that before, sorry. + * Sorry, still with MSN support disabled, because Debian's default + libsoup package won't work with BitlBee-MSN. + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 31 Dec 2003 00:56:57 +0100 + +bitlbee (0.82-1) unstable; urgency=low + + * New upstream release. + * Disabled MSN support in the Debian version for now, because it needs + a patched version of libsoup. If you want MSN support, you'll have to + create one yourself and install a patched version of libsoup. + + -- Wilmer van der Gaast <lintux@debian.org> Fri, 31 Oct 2003 21:51:01 +0100 + +bitlbee (0.81a-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 16 Oct 2003 16:21:31 +0200 + +bitlbee (0.81-1) unstable; urgency=low + + * New upstream release. + * Fixes Yahoo! problems. (Closes: #213876) + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 15 Oct 2003 16:00:00 +0200 + +bitlbee (0.80-1) unstable; urgency=low + + * New upstream release. + * preinst now unlinks the old helpfile while upgrading, see README.Debian + for details. + * 'Upgraded' to standards 3.5.9. + * "jabber: Non-ascii away messages not supported" patch included. + (Closes: #195852) + + -- Wilmer van der Gaast <lintux@debian.org> Tue, 24 Jun 2003 20:00:00 +0200 + +bitlbee (0.74a-1) unstable; urgency=low + + * This one actually does contain the bugfix 0.74 should've had. + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 11 Jun 2003 13:44:01 +0200 + +bitlbee (0.74-1) unstable; urgency=high + + * Security release, fixing a little not-too-dangerous security bug. + + -- Wilmer van der Gaast <lintux@debian.org> Tue, 10 Jun 2003 22:50:19 +0200 + +bitlbee (0.73-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <lintux@debian.org> Sun, 13 Apr 2003 01:20:49 +0200 + +bitlbee (0.72-2) unstable; urgency=low + + * Now uses '127.0.0.1' as default for hosts.allow instead of 'localhost'. + (Closes: #174219) + * Fixed some other portability issues. (Closes: #177394) + * Added w3m builddep, needed for .txt documentation generation. + * Removed jadetex builddep because it seems not to be necessary after all. + + -- Wilmer van der Gaast <lintux@debian.org> Tue, 21 Jan 2003 01:35:46 +0100 + +bitlbee (0.72-1) unstable; urgency=low + + * BitlBee doesn't have tcpd in it anymore; external tcpd is used now. + * Added an examples/ directory. + * Fixed arm/ppc/s390 portability issue on char signedness. (Closes: #161026) + + -- Wilmer van der Gaast <lintux@debian.org> Thu, 19 Dec 2002 00:24:29 +0100 + +bitlbee (0.71-1) unstable; urgency=low + + * New upstream release. + + -- Wilmer van der Gaast <lintux@debian.org> Mon, 16 Sep 2002 01:02:09 +0200 + +bitlbee (0.7-2) unstable; urgency=low + + * Second try at a good upload. + + -- Wilmer van der Gaast <lintux@debian.org> Thu, 15 Aug 2002 20:14:54 +0200 + +bitlbee (0.7-1) unstable; urgency=low + + * First public release. (Closes: #153190) + + -- Wilmer van der Gaast <lintux@debian.org> Sat, 10 Aug 2002 04:47:07 +0200 + +bitlbee (0.6-1) unstable; urgency=low + + * Initial Release. (Testing only, not for release.) + + -- Wilmer van der Gaast <lintux@debian.org> Wed, 10 Jul 2002 11:02:28 +0200 + +Local variables: +mode: debian-changelog +End: diff --git a/debian/conffiles b/debian/conffiles new file mode 100644 index 00000000..2ccc958d --- /dev/null +++ b/debian/conffiles @@ -0,0 +1,2 @@ +/etc/bitlbee/motd.txt +/etc/bitlbee/bitlbee.conf diff --git a/debian/config b/debian/config new file mode 100755 index 00000000..3a04813d --- /dev/null +++ b/debian/config @@ -0,0 +1,19 @@ +#!/bin/sh -e + +. /usr/share/debconf/confmodule + +db_title BitlBee + +db_get bitlbee/serveport +if [ "$RET" = "stillhavetoask" ]; then + if netstat -ltn | grep ':6667' 2> /dev/null > /dev/null; then + port=6668; + else + port=6667; + fi + db_set bitlbee/serveport $port; +fi + +if db_input medium bitlbee/serveport; then + db_go; +fi diff --git a/debian/control b/debian/control new file mode 100644 index 00000000..139174a6 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: bitlbee +Section: net +Priority: optional +Maintainer: Wilmer van der Gaast <wilmer@gaast.net> +Standards-Version: 3.5.9 +Build-Depends: libglib2.0-dev | libglib-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf + +Package: bitlbee +Architecture: any +Depends: ${shlibs:Depends}, adduser, net-tools, ${debconf-depends}, debianutils (>= 1.16) +Description: An IRC to other chat networks gateway + This program can be used as an IRC server which forwards everything you + say to people on other chat networks: Jabber, ICQ, AIM, MSN and Yahoo. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 00000000..53c04657 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,895 @@ +This package was debianized by Wilmer van der Gaast <lintux@debian.org> on +Mon, 8 Jul 2002 13:17:42 +0200. + +The source can be downloaded from http://www.bitlbee.org/ + +Authors: Wilmer van der Gaast, Sjoerd Hemminga, Jelmer Vernooij, + Maurits Dijkstra and others. + +Mainly Copyright 2002-2004 Wilmer van der Gaast. +Some parts are borrowed from Gaim (version 0.58) <http://gaim.sf.net/>. +For the copyrights on those parts, please read the Gaim source code. + +BitlBee License: + +============================================================================ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +============================================================================ + + + +Parts of the program (parts of the Jabber module, the XML parser to be more +specific) are licensed under the Mozilla license (version 1.1): + +============================================================================ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] +============================================================================ + + + +The MD5 generator used for authentication in some modules is written by +Aladdin Enterprises: + +============================================================================ + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +============================================================================ + + + +The SGML-formatted documentation is written by Jelmer Vernooij +<jelmer@nl.linux.org> under the GNU Free Documentation License: + +============================================================================ + GNU Free Documentation License + Version 1.1, March 2000 + + Copyright (C) 2000 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. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have no Invariant Sections, write "with no Invariant Sections" +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write "no Front-Cover Texts" instead of +"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. +============================================================================ diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in new file mode 100644 index 00000000..f17ddcfe --- /dev/null +++ b/debian/po/POTFILES.in @@ -0,0 +1 @@ +[type: gettext/rfc822deb] bitlbee.templates.master diff --git a/debian/po/cs.po b/debian/po/cs.po new file mode 100644 index 00000000..558c8602 --- /dev/null +++ b/debian/po/cs.po @@ -0,0 +1,44 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2005-02-04 12:31+0100\n" +"Last-Translator: Miroslav Kure <kurem@debian.cz>\n" +"Language-Team: Czech <debian-l10n-czech@debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Na kter้m TCP portu mแ BitlBee naslouchat p๘ํchozํm spojenํm?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee normแln์ naslouchแ na b์พn้m IRC portu 6667. Pokud mแte spuนt์n i " +"reแln IRC daemon, tak to nemusํ bt nejlepนํ nแpad. Vhodnแ alternativa m๙พe " +"bt 6668. Ponechแte-li pole prแzdn้, znamenแ to, พe se BitlBee nebude " +"spouนt์t automaticky." diff --git a/debian/po/de.po b/debian/po/de.po new file mode 100644 index 00000000..2264bf27 --- /dev/null +++ b/debian/po/de.po @@ -0,0 +1,45 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans# +# Developers do not need to manually edit POT or PO files. +# Erik Schanze <mail@erikschanze.de>, 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee_0.90a-2_de\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2004-10-03 14:33+0200\n" +"Last-Translator: Erik Schanze <mail@erikschanze.de>\n" +"Language-Team: German <debian-l10n-german@lists.debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.3.1\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "An welchem TCP-Port soll BitlBee auf Verbindungen warten?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee lauscht normalerweise an dem รผblichen IRC-Port 6667. Dies ist aber " +"keine gute Idee, wenn Sie auรŸerdem noch einen richtigen IRC-Dienst " +"betreiben. Das Port 6668 ist eine gute Alternative. Wenn Sie keinen Wert " +"eingeben, wird BitlBee nicht automatisch starten." diff --git a/debian/po/es.po b/debian/po/es.po new file mode 100644 index 00000000..44c525b9 --- /dev/null +++ b/debian/po/es.po @@ -0,0 +1,61 @@ +# bitlbee po-debconf translation to Spanish +# Copyright (C) 2005 Software in the Public Interest +# This file is distributed under the same license as the bitlbee package. +# +# Changes: +# - Initial translation +# Cรฉsar Gรณmez Martรญn <cesar.gomez@gmail.com> +# +# +# Traductores, si no conoce el formato PO, merece la pena leer la +# documentaciรณn de gettext, especialmente las secciones dedicadas a este +# formato, por ejemplo ejecutando: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# Equipo de traducciรณn al espaรฑol, por favor, lean antes de traducir +# los siguientes documentos: +# +# - El proyecto de traducciรณn de Debian al espaรฑol +# http://www.debian.org/intl/spanish/ +# especialmente las notas de traducciรณn en +# http://www.debian.org/intl/spanish/notas +# +# - La guรญa de traducciรณn de po's de debconf: +# /usr/share/doc/po-debconf/README-trans +# o http://www.debian.org/intl/l10n/po-debconf/README-trans +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2005-08-24 19:37+0100\n" +"Last-Translator: Cรฉsar Gรณmez Martรญn <cesar.gomez@gmail.com>\n" +"Language-Team: Debian l10n spanish <debian-l10n-spanish@lists.debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Spanish\n" +"X-Poedit-Country: SPAIN\n" +"X-Poedit-SourceCharset: utf-8\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "ยฟEn quรฉ puerto TCP quiere que BitlBee escuche conexiones?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee normalmente escucha en el puerto 6667, que se usa tambiรฉn para IRC. " +"Por esta razรณn no es muy buena idea poner a BitlBee a escuchar en ese puerto " +"si tambiรฉn se estรก ejecutando un demonio real de IRC, en este caso el puerto " +"6668 puede ser una buena alternativa. Si deja este valor en blanco BitlBee " +"no se ejecutarรก automรกticamente." diff --git a/debian/po/fr.po b/debian/po/fr.po new file mode 100644 index 00000000..562a0229 --- /dev/null +++ b/debian/po/fr.po @@ -0,0 +1,44 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee (0.80-1)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2003-08-07 08:45+0100\n" +"Last-Translator: Christian Perrier <bubulle@debian.org>\n" +"Language-Team: French <debian-l10n-french@lists.debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Sur quel port TCP BitlBee doit-il ๊tre เ l'้coute ?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee est usuellement เ l'้coute sur le port IRC standard : 6667. Cela " +"n'est pas forc้ment un choix adapt้ si vous utilisez en m๊me temps un vrai " +"d้mon IRC. Dans ce cas, choisir 6668 est conseill้. Si vous ne souhaitez pas " +"lancer BitlBee automatiquement, veuillez laissez ce champs vide." diff --git a/debian/po/ja.po b/debian/po/ja.po new file mode 100644 index 00000000..c94bbbe4 --- /dev/null +++ b/debian/po/ja.po @@ -0,0 +1,45 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee 0.90a-2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2004-09-11 13:30+0900\n" +"Last-Translator: Hideki Yamane <henrich@samba.gr.jp>\n" +"Language-Team: Japanese <debian-japanese@lists.debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=EUC-JP\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "BitlBee คฯกขภยณคฮคฟคแคหคษคฮ TCP ฅกผฅศค๒ listen คทคคนคซ?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee คฯฤฬพ๏คฮพ์น็กขษธฝเคฮ IRC ฅกผฅศศึนๆควคขค๋ 6667 ค๒ listen คทคคนกฃฦฑออ" +"คหคทคฦผยบคฮ IRC ฅวกผฅโฅ๓ค๒ฦฐบ๎คตคปคฦคคค๋พ์น็กขคณค์คฯคขคค๊ฮษคคนอคจควคฯฬตคคคซ" +"คโคทค์คคปค๓กฃยๅค๏ค๊คห 6668 ค๒ปศคฆคฮคฌฮษคคคซคโรฮค์คคปค๓กฃคณค์ค๒ถ๕คฮคคคหคท" +"คฦคชคฑคะกขBitlBee คฯผซฦฐลชคหคฯตฏฦฐคสคฏคสค๊คคนกฃ" diff --git a/debian/po/nl.po b/debian/po/nl.po new file mode 100644 index 00000000..f9a97d76 --- /dev/null +++ b/debian/po/nl.po @@ -0,0 +1,44 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee (0.90a-2)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2004-09-06 20:16+0200\n" +"Last-Translator: Wilmer van der Gaast <wilmer@gaast.net>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Op welke TCP poort moet BitlBee draaien?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"Normaal 'luistert' BitlBee op de gebruikelijke IRC poort, 6667. Als je al " +"een andere IRC daemon draait is dat onmogelijk. Kies dan bijvoorbeeld voor " +"poort 6668. Als je niet wil dat BitlBee automatisch gestart wordt, vul hier " +"dan niets in." diff --git a/debian/po/pt.po b/debian/po/pt.po new file mode 100644 index 00000000..7eb3380d --- /dev/null +++ b/debian/po/pt.po @@ -0,0 +1,35 @@ +# Portuguese translation of bitlbee's debconf messages. # This file is distributed under the same license as the bitlbee package. +# 2006, Marco Ferra <mferra@debianpt.org> +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee 1.0.3-1.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-13 18:53+0100\n" +"PO-Revision-Date: 2007-01-26 22:34+0000\n" +"Last-Translator: Marco Ferra <mferra@debianpt.org>\n" +"Language-Team: Portuguese <traduz@debianpt.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:1001 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Em que porta TCP deverรก o BitlBee escutar por conexรตes?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:1001 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"O BitlBee normalmente escuta na porta do IRC 6667. Isto poderรก nรฃo ser " +"uma ideia excelente quando estรก a correr um 'daemon' de IRC ao mesmo tempo. " +"Nesse caso a porta 6668 poderรก ser uma boa alternativa. Deixar este campo " +"vazio significa que o BitlBee nรฃo irรก correr automaticamente." + diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po new file mode 100644 index 00000000..35193fee --- /dev/null +++ b/debian/po/pt_BR.po @@ -0,0 +1,44 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2005-02-26 16:14-0300\n" +"Last-Translator: Andr้ Luํs Lopes <andrelop@debian.org>\n" +"Language-Team: Debian-BR Project <debian-l10n-portuguese@lists.debian.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Em qual porta TCP o BitlBee deverแ ouvir por conex๕es ?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"O BitlBee normalmente ouve na porta de IRC padrใo, 6667. Por้m, esta pode " +"nใo ser uma boa id้ia quando voc๊ estแ rodando um daemon IRC real tamb้m. " +"6689 pode ser uma boa alternativa. Deixar esse valor em branco significa que " +"o BitlBee nใo serแ executado automaticamente." diff --git a/debian/po/sv.po b/debian/po/sv.po new file mode 100644 index 00000000..06a9a8ee --- /dev/null +++ b/debian/po/sv.po @@ -0,0 +1,43 @@ +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# Developers do not need to manually edit POT or PO files. +# , fuzzy +# +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee 0.92-2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2005-10-03 23:18+0200\n" +"Last-Translator: Daniel Nylander <po@danielnylander.se>\n" +"Language-Team: Swedish <sv@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Pๅ vilken TCP-port ska BitlBee lyssna pๅ efter anslutningar?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"BitlBee lyssnar normalt pๅ den standardporten f๖r IRC, 6667. Detta kanske " +"inte ไr en bra ide om du k๖r en riktig IRC-daemon pๅ samma system. 6668 kan " +"vara ett bra alternativ dๅ. Lไmnar du detta vไrde blankt betyder det att " +"BitlBee inte kommer att startas automatiskt." diff --git a/debian/po/templates.pot b/debian/po/templates.pot new file mode 100644 index 00000000..1a3ab2b8 --- /dev/null +++ b/debian/po/templates.pot @@ -0,0 +1,41 @@ +# +# Translators, if you are not familiar with the PO format, gettext +# documentation is worth reading, especially sections dedicated to +# this format, e.g. by running: +# info -n '(gettext)PO Files' +# info -n '(gettext)Header Entry' +# +# Some information specific to po-debconf are available at +# /usr/share/doc/po-debconf/README-trans +# or http://www.debian.org/intl/l10n/po-debconf/README-trans +# +# Developers do not need to manually edit POT or PO files. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" diff --git a/debian/po/vi.po b/debian/po/vi.po new file mode 100644 index 00000000..2bcb5908 --- /dev/null +++ b/debian/po/vi.po @@ -0,0 +1,32 @@ +# Vietnamese translation for bitlbee. +# Copyright ยฉ 2005 Free Software Foundation, Inc. +# Clytie Siddall <clytie@riverland.net.au>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee 0.92-1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-09-25 18:12+0200\n" +"PO-Revision-Date: 2005-06-12 18:34+0930\n" +"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n" +"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Trรฌnh BitlBee nรชn lแบฏng nghe sแปฑ kแบฟt nแป‘i trรชn cแป•ng TCP nร o?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:4 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "Trรฌnh BitlBee thฦฐแปng lแบฏng nghe trรชn cแป•ng IRC bรฌnh thฦฐแปng, 6667. Cรณ lแบฝ nรณ khรดng phแบฃi lร  mแป™t รฝ kiแบฟn tแป‘t nแบฟu bแบกn cลฉng cรณ chแบกy mแป™t trรฌnh nแปn (dรฆmon) IRC thแบญt. Nhฦฐ thแบฟ thรฌ, cแป•ng 6668 cรณ thแปƒ lร  mแป™t ฤ‘iแปu thay thแบฟ tแป‘t. Nแบฟu bแบกn bแป giรก trแป‹ nร y rแป—ng, thรฌ trรฌnh BitlBee sแบฝ khรดng tแปฑ ฤ‘แป™ng chแบกy." diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 00000000..6c99c40d --- /dev/null +++ b/debian/postinst @@ -0,0 +1,68 @@ +#!/bin/sh -e + +. /usr/share/debconf/confmodule + +db_get bitlbee/serveport +PORT="$RET" + +CONFDIR=/var/lib/bitlbee/ + +update-rc.d bitlbee defaults > /dev/null 2>&1 + +## Load default option. Don't want to put this in debconf (yet?) +BITLBEE_OPTS=-F +BITLBEE_DISABLED=0 +BITLBEE_UPGRADE_DONT_RESTART=0 +[ -r /etc/default/bitlbee ] && source /etc/default/bitlbee + +if [ "$BITLBEE_DISABLED" = "0" ]; then + ## In case it's still there (if we're upgrading right now) + update-inetd --remove '.*/usr/sbin/bitlbee' +fi + +cat<<EOF>/etc/default/bitlbee +## /etc/default/bitlbee: Auto-generated/updated script. +## +## Don't edit this line, use dpkg-reconfigure bitlbee +BITLBEE_PORT="$PORT" + +## Use single-process or forking daemon mode? Can't be changed from debconf, +## but maintainer scripts will save your changes here. +BITLBEE_OPTS="$BITLBEE_OPTS" + +## In case you want to stick with inetd mode (or if you just want to disable +## the init scripts for some other reason), you can disable the init script +## here. (Just set it to 1) +BITLBEE_DISABLED=$BITLBEE_DISABLED + +## As a server operator, you can use the RESTART command to restart only the +## master process while keeping all the child processes and their IPC +## connections. By enabling this, the maintainer scripts won't restart +## BitlBee during upgrades so you can restart the master process by hand. +BITLBEE_UPGRADE_DONT_RESTART=$BITLBEE_UPGRADE_DONT_RESTART +EOF + +## Bye-bye DebConf, we don't need you anymore. +db_stop + +if [ -n "$2" -a "$BITLBEE_UPGRADE_DONT_RESTART" != "1" ]; then + /etc/init.d/bitlbee restart +fi + +## If we're upgrading, we'll probably skip this next part +if [ -d $CONFDIR ] && chown -R bitlbee $CONFDIR; then + echo 'BitlBee (probably) already installed, skipping user/configdir installation' + exit 0 +fi + +adduser --system --home /var/lib/bitlbee/ --disabled-login --disabled-password bitlbee +chmod 700 /var/lib/bitlbee/ + +## Can't do this in packaging phase: Don't know the UID yet. Access to +## the file should be limited, now that it stores passwords. +chmod 600 /etc/bitlbee/bitlbee.conf +chown bitlbee /etc/bitlbee/bitlbee.conf + +if [ -z "$2" ]; then + /etc/init.d/bitlbee start +fi diff --git a/debian/postrm b/debian/postrm new file mode 100755 index 00000000..cef99f13 --- /dev/null +++ b/debian/postrm @@ -0,0 +1,11 @@ +#!/bin/sh -e + +[ "$1" = "purge" ] || exit 0 + +if [ -e /usr/share/debconf/confmodule ]; then + . /usr/share/debconf/confmodule; + db_purge; +fi + +update-rc.d bitlbee remove > /dev/null 2>&1 || true +deluser --remove-home bitlbee || true diff --git a/debian/prerm b/debian/prerm new file mode 100755 index 00000000..c02b13f4 --- /dev/null +++ b/debian/prerm @@ -0,0 +1,8 @@ +#!/bin/sh -e + +if [ "$1" = "upgrade" ]; then + ## To prevent the help function from breaking in currently running BitlBee processes + rm -f /usr/share/bitlbee/help.txt +else + /etc/init.d/bitlbee stop || exit 0 +fi diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..eb0417db --- /dev/null +++ b/debian/rules @@ -0,0 +1,83 @@ +#!/usr/bin/make -f + +DEBUG ?= 0 + +# Want to use the full package version number instead of just the release. +BITLBEE_VERSION ?= "$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')" +export BITLBEE_VERSION + + +build-arch: build-arch-stamp +build-arch-stamp: + if [ ! -d debian ]; then exit 1; fi + ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee $(DEB_BUILD_OPTIONS) + $(MAKE) +# $(MAKE) -C doc/ all + touch build-arch-stamp + +clean: + if [ "`whoami`" != "root" -o ! -d debian ]; then exit 1; fi + rm -rf build-arch-stamp debian/bitlbee debian/*.substvars debian/files + -$(MAKE) distclean +# -$(MAKE) -C doc/ clean + + +install-arch: build-arch + if [ "`whoami`" != "root" -o ! -d debian ]; then exit 1; fi + mkdir -p debian/bitlbee/DEBIAN/ + $(MAKE) install install-etc DESTDIR=`pwd`/debian/bitlbee + + mkdir -p debian/bitlbee/usr/share/doc/bitlbee/ + cp doc/user-guide/user-guide.txt debian/bitlbee/usr/share/doc/bitlbee/ + cp doc/user-guide/user-guide.html debian/bitlbee/usr/share/doc/bitlbee/ + +binary-arch: build-arch install-arch + if [ "`whoami`" != "root" -o ! -d debian ]; then exit 1; fi + + chmod 755 debian/post* debian/pre* debian/config debian/bitlbee.init + + mkdir -p debian/bitlbee/usr/share/doc/bitlbee/examples/ debian/bitlbee/etc/init.d/ + -cp doc/RELEASE-SPEECH* debian/bitlbee/usr/share/doc/bitlbee/ && gzip -9 debian/bitlbee/usr/share/doc/bitlbee/RELEASE-SPEECH* + cp doc/CREDITS doc/AUTHORS doc/README doc/FAQ debian/README.Debian debian/bitlbee/usr/share/doc/bitlbee/ + cp debian/changelog debian/bitlbee/usr/share/doc/bitlbee/changelog.Debian + cp debian/copyright debian/bitlbee/usr/share/doc/bitlbee/copyright + cp doc/CHANGES debian/bitlbee/usr/share/doc/bitlbee/changelog + cp utils/* debian/bitlbee/usr/share/doc/bitlbee/examples/ + cp debian/bitlbee.init debian/bitlbee/etc/init.d/bitlbee + cd debian/bitlbee/usr/share/; \ + gzip -9 doc/bitlbee/changelog.Debian doc/bitlbee/changelog doc/bitlbee/user-guide.txt \ + doc/bitlbee/examples/* man/man8/bitlbee.8 man/man5/bitlbee.conf.5 + + chown -R root.root debian/bitlbee/ + find debian/bitlbee/usr/share/ -type d -exec chmod 755 {} \; + find debian/bitlbee/usr/share/ -type f -exec chmod 644 {} \; + + cp debian/prerm debian/bitlbee/DEBIAN/ + cp debian/postinst debian/bitlbee/DEBIAN/ + cp debian/postrm debian/bitlbee/DEBIAN/ + cp debian/config debian/bitlbee/DEBIAN/ + + po2debconf debian/templates > debian/bitlbee/DEBIAN/templates + cp debian/conffiles debian/bitlbee/DEBIAN/ + + if [ "$(DEBUG)" = "0" ]; then strip -R .comment -R .note debian/bitlbee/usr/sbin/bitlbee; fi + + cd debian/bitlbee; \ + find usr -type f -exec md5sum {} \; > DEBIAN/md5sums + dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee +ifdef BITLBEE_VERSION + dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' +else + dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' +endif + + dpkg --build debian/bitlbee .. + +debug-build: + BITLBEE_VERSION=\"`date +%Y%m%d`-`hostname`-debug\" debian/rules clean binary DEBUG=1 + +binary: binary-arch +build: build-arch +install: install-arch + +.PHONY: build-arch build clean binary-arch binary install-arch install diff --git a/debian/templates b/debian/templates new file mode 100644 index 00000000..0cd04426 --- /dev/null +++ b/debian/templates @@ -0,0 +1,8 @@ +Template: bitlbee/serveport +Type: string +Default: stillhavetoask +_Description: On what TCP port should BitlBee listen for connections? + BitlBee normally listens on the regular IRC port, 6667. This might not be + a very good idea when you're running a real IRC daemon as well. 6668 might + be a good alternative. Leaving this value blank means that BitlBee will not + be run automatically. -- cgit v1.2.3 From c4f2c6a64ee0f2de10c172e337528d6a6a9a3e62 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 6 Jul 2007 09:11:13 +0100 Subject: Removed MPL from debian/copyright because the old Jabber module is gone now. --- debian/changelog | 3 +- debian/copyright | 477 ------------------------------------------------------- 2 files changed, 2 insertions(+), 478 deletions(-) diff --git a/debian/changelog b/debian/changelog index c48704b9..ae524f73 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,8 +4,9 @@ bitlbee (1.1.1dev-0pre) unstable; urgency=low file, an init script. People who want to stick with inetd can do so, see the defaults file. * Got rid of debconf Woody compatibility stuff. + * No more MPL code in BitlBee, thanks to the Jabber module rewrite! - -- Wilmer van der Gaast <wilmer@gaast.net> Fri, 6 Jul 2007 00:27:38 +0100 + -- Wilmer van der Gaast <wilmer@gaast.net> Fri, 06 Jul 2007 09:09:36 +0100 bitlbee (1.0.3-1.3) unstable; urgency=low diff --git a/debian/copyright b/debian/copyright index 53c04657..3f2ecc8e 100644 --- a/debian/copyright +++ b/debian/copyright @@ -31,483 +31,6 @@ BitlBee License: -Parts of the program (parts of the Jabber module, the XML parser to be more -specific) are licensed under the Mozilla license (version 1.1): - -============================================================================ - MOZILLA PUBLIC LICENSE - Version 1.1 - - --------------- - -1. Definitions. - - 1.0.1. "Commercial Use" means distribution or otherwise making the - Covered Code available to a third party. - - 1.1. "Contributor" means each entity that creates or contributes to - the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Code, prior Modifications used by a Contributor, and the Modifications - made by that particular Contributor. - - 1.3. "Covered Code" means the Original Code or Modifications or the - combination of the Original Code and Modifications, in each case - including portions thereof. - - 1.4. "Electronic Distribution Mechanism" means a mechanism generally - accepted in the software development community for the electronic - transfer of data. - - 1.5. "Executable" means Covered Code in any form other than Source - Code. - - 1.6. "Initial Developer" means the individual or entity identified - as the Initial Developer in the Source Code notice required by Exhibit - A. - - 1.7. "Larger Work" means a work which combines Covered Code or - portions thereof with code not governed by the terms of this License. - - 1.8. "License" means this document. - - 1.8.1. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed herein. - - 1.9. "Modifications" means any addition to or deletion from the - substance or structure of either the Original Code or any previous - Modifications. When Covered Code is released as a series of files, a - Modification is: - A. Any addition to or deletion from the contents of a file - containing Original Code or previous Modifications. - - B. Any new file that contains any part of the Original Code or - previous Modifications. - - 1.10. "Original Code" means Source Code of computer software code - which is described in the Source Code notice required by Exhibit A as - Original Code, and which, at the time of its release under this - License is not already Covered Code governed by this License. - - 1.10.1. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, process, - and apparatus claims, in any patent Licensable by grantor. - - 1.11. "Source Code" means the preferred form of the Covered Code for - making modifications to it, including all modules it contains, plus - any associated interface definition files, scripts used to control - compilation and installation of an Executable, or source code - differential comparisons against either the Original Code or another - well known, available Covered Code of the Contributor's choice. The - Source Code can be in a compressed or archival form, provided the - appropriate decompression or de-archiving software is widely available - for no charge. - - 1.12. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms of, this - License or a future version of this License issued under Section 6.1. - For legal entities, "You" includes any entity which controls, is - controlled by, or is under common control with You. For purposes of - this definition, "control" means (a) the power, direct or indirect, - to cause the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty percent - (50%) of the outstanding shares or beneficial ownership of such - entity. - -2. Source Code License. - - 2.1. The Initial Developer Grant. - The Initial Developer hereby grants You a world-wide, royalty-free, - non-exclusive license, subject to third party intellectual property - claims: - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer to use, reproduce, - modify, display, perform, sublicense and distribute the Original - Code (or portions thereof) with or without Modifications, and/or - as part of a Larger Work; and - - (b) under Patents Claims infringed by the making, using or - selling of Original Code, to make, have made, use, practice, - sell, and offer for sale, and/or otherwise dispose of the - Original Code (or portions thereof). - - (c) the licenses granted in this Section 2.1(a) and (b) are - effective on the date Initial Developer first distributes - Original Code under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: 1) for code that You delete from the Original Code; 2) - separate from the Original Code; or 3) for infringements caused - by: i) the modification of the Original Code or ii) the - combination of the Original Code with other software or devices. - - 2.2. Contributor Grant. - Subject to third party intellectual property claims, each Contributor - hereby grants You a world-wide, royalty-free, non-exclusive license - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor, to use, reproduce, modify, - display, perform, sublicense and distribute the Modifications - created by such Contributor (or portions thereof) either on an - unmodified basis, with other Modifications, as Covered Code - and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either alone - and/or in combination with its Contributor Version (or portions - of such combination), to make, use, sell, offer for sale, have - made, and/or otherwise dispose of: 1) Modifications made by that - Contributor (or portions thereof); and 2) the combination of - Modifications made by that Contributor with its Contributor - Version (or portions of such combination). - - (c) the licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first makes Commercial Use of - the Covered Code. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: 1) for any code that Contributor has deleted from the - Contributor Version; 2) separate from the Contributor Version; - 3) for infringements caused by: i) third party modifications of - Contributor Version or ii) the combination of Modifications made - by that Contributor with other software (except as part of the - Contributor Version) or other devices; or 4) under Patent Claims - infringed by Covered Code in the absence of Modifications made by - that Contributor. - -3. Distribution Obligations. - - 3.1. Application of License. - The Modifications which You create or to which You contribute are - governed by the terms of this License, including without limitation - Section 2.2. The Source Code version of Covered Code may be - distributed only under the terms of this License or a future version - of this License released under Section 6.1, and You must include a - copy of this License with every copy of the Source Code You - distribute. You may not offer or impose any terms on any Source Code - version that alters or restricts the applicable version of this - License or the recipients' rights hereunder. However, You may include - an additional document offering the additional rights described in - Section 3.5. - - 3.2. Availability of Source Code. - Any Modification which You create or to which You contribute must be - made available in Source Code form under the terms of this License - either on the same media as an Executable version or via an accepted - Electronic Distribution Mechanism to anyone to whom you made an - Executable version available; and if made available via Electronic - Distribution Mechanism, must remain available for at least twelve (12) - months after the date it initially became available, or at least six - (6) months after a subsequent version of that particular Modification - has been made available to such recipients. You are responsible for - ensuring that the Source Code version remains available even if the - Electronic Distribution Mechanism is maintained by a third party. - - 3.3. Description of Modifications. - You must cause all Covered Code to which You contribute to contain a - file documenting the changes You made to create that Covered Code and - the date of any change. You must include a prominent statement that - the Modification is derived, directly or indirectly, from Original - Code provided by the Initial Developer and including the name of the - Initial Developer in (a) the Source Code, and (b) in any notice in an - Executable version or related documentation in which You describe the - origin or ownership of the Covered Code. - - 3.4. Intellectual Property Matters - (a) Third Party Claims. - If Contributor has knowledge that a license under a third party's - intellectual property rights is required to exercise the rights - granted by such Contributor under Sections 2.1 or 2.2, - Contributor must include a text file with the Source Code - distribution titled "LEGAL" which describes the claim and the - party making the claim in sufficient detail that a recipient will - know whom to contact. If Contributor obtains such knowledge after - the Modification is made available as described in Section 3.2, - Contributor shall promptly modify the LEGAL file in all copies - Contributor makes available thereafter and shall take other steps - (such as notifying appropriate mailing lists or newsgroups) - reasonably calculated to inform those who received the Covered - Code that new knowledge has been obtained. - - (b) Contributor APIs. - If Contributor's Modifications include an application programming - interface and Contributor has knowledge of patent licenses which - are reasonably necessary to implement that API, Contributor must - also include this information in the LEGAL file. - - (c) Representations. - Contributor represents that, except as disclosed pursuant to - Section 3.4(a) above, Contributor believes that Contributor's - Modifications are Contributor's original creation(s) and/or - Contributor has sufficient rights to grant the rights conveyed by - this License. - - 3.5. Required Notices. - You must duplicate the notice in Exhibit A in each file of the Source - Code. If it is not possible to put such notice in a particular Source - Code file due to its structure, then You must include such notice in a - location (such as a relevant directory) where a user would be likely - to look for such a notice. If You created one or more Modification(s) - You may add your name as a Contributor to the notice described in - Exhibit A. You must also duplicate this License in any documentation - for the Source Code where You describe recipients' rights or ownership - rights relating to Covered Code. You may choose to offer, and to - charge a fee for, warranty, support, indemnity or liability - obligations to one or more recipients of Covered Code. However, You - may do so only on Your own behalf, and not on behalf of the Initial - Developer or any Contributor. You must make it absolutely clear than - any such warranty, support, indemnity or liability obligation is - offered by You alone, and You hereby agree to indemnify the Initial - Developer and every Contributor for any liability incurred by the - Initial Developer or such Contributor as a result of warranty, - support, indemnity or liability terms You offer. - - 3.6. Distribution of Executable Versions. - You may distribute Covered Code in Executable form only if the - requirements of Section 3.1-3.5 have been met for that Covered Code, - and if You include a notice stating that the Source Code version of - the Covered Code is available under the terms of this License, - including a description of how and where You have fulfilled the - obligations of Section 3.2. The notice must be conspicuously included - in any notice in an Executable version, related documentation or - collateral in which You describe recipients' rights relating to the - Covered Code. You may distribute the Executable version of Covered - Code or ownership rights under a license of Your choice, which may - contain terms different from this License, provided that You are in - compliance with the terms of this License and that the license for the - Executable version does not attempt to limit or alter the recipient's - rights in the Source Code version from the rights set forth in this - License. If You distribute the Executable version under a different - license You must make it absolutely clear that any terms which differ - from this License are offered by You alone, not by the Initial - Developer or any Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred by - the Initial Developer or such Contributor as a result of any such - terms You offer. - - 3.7. Larger Works. - You may create a Larger Work by combining Covered Code with other code - not governed by the terms of this License and distribute the Larger - Work as a single product. In such a case, You must make sure the - requirements of this License are fulfilled for the Covered Code. - -4. Inability to Comply Due to Statute or Regulation. - - If it is impossible for You to comply with any of the terms of this - License with respect to some or all of the Covered Code due to - statute, judicial order, or regulation then You must: (a) comply with - the terms of this License to the maximum extent possible; and (b) - describe the limitations and the code they affect. Such description - must be included in the LEGAL file described in Section 3.4 and must - be included with all distributions of the Source Code. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Application of this License. - - This License applies to code to which the Initial Developer has - attached the notice in Exhibit A and to related Covered Code. - -6. Versions of the License. - - 6.1. New Versions. - Netscape Communications Corporation ("Netscape") may publish revised - and/or new versions of the License from time to time. Each version - will be given a distinguishing version number. - - 6.2. Effect of New Versions. - Once Covered Code has been published under a particular version of the - License, You may always continue to use it under the terms of that - version. You may also choose to use such Covered Code under the terms - of any subsequent version of the License published by Netscape. No one - other than Netscape has the right to modify the terms applicable to - Covered Code created under this License. - - 6.3. Derivative Works. - If You create or use a modified version of this License (which you may - only do in order to apply it to code which is not already Covered Code - governed by this License), You must (a) rename Your license so that - the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", - "MPL", "NPL" or any confusingly similar phrase do not appear in your - license (except to note that your license differs from this License) - and (b) otherwise make it clear that Your version of the license - contains terms which differ from the Mozilla Public License and - Netscape Public License. (Filling in the name of the Initial - Developer, Original Code or Contributor in the notice described in - Exhibit A shall not of themselves be deemed to be modifications of - this License.) - -7. DISCLAIMER OF WARRANTY. - - COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF - DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. - THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE - IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, - YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE - COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER - OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -8. TERMINATION. - - 8.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to cure - such breach within 30 days of becoming aware of the breach. All - sublicenses to the Covered Code which are properly granted shall - survive any termination of this License. Provisions which, by their - nature, must remain in effect beyond the termination of this License - shall survive. - - 8.2. If You initiate litigation by asserting a patent infringement - claim (excluding declatory judgment actions) against Initial Developer - or a Contributor (the Initial Developer or Contributor against whom - You file such action is referred to as "Participant") alleging that: - - (a) such Participant's Contributor Version directly or indirectly - infringes any patent, then any and all rights granted by such - Participant to You under Sections 2.1 and/or 2.2 of this License - shall, upon 60 days notice from Participant terminate prospectively, - unless if within 60 days after receipt of notice You either: (i) - agree in writing to pay Participant a mutually agreeable reasonable - royalty for Your past and future use of Modifications made by such - Participant, or (ii) withdraw Your litigation claim with respect to - the Contributor Version against such Participant. If within 60 days - of notice, a reasonable royalty and payment arrangement are not - mutually agreed upon in writing by the parties or the litigation claim - is not withdrawn, the rights granted by Participant to You under - Sections 2.1 and/or 2.2 automatically terminate at the expiration of - the 60 day notice period specified above. - - (b) any software, hardware, or device, other than such Participant's - Contributor Version, directly or indirectly infringes any patent, then - any rights granted to You by such Participant under Sections 2.1(b) - and 2.2(b) are revoked effective as of the date You first made, used, - sold, distributed, or had made, Modifications made by that - Participant. - - 8.3. If You assert a patent infringement claim against Participant - alleging that such Participant's Contributor Version directly or - indirectly infringes any patent where such claim is resolved (such as - by license or settlement) prior to the initiation of patent - infringement litigation, then the reasonable value of the licenses - granted by such Participant under Sections 2.1 or 2.2 shall be taken - into account in determining the amount or value of any payment or - license. - - 8.4. In the event of termination under Sections 8.1 or 8.2 above, - all end user license agreements (excluding distributors and resellers) - which have been validly granted by You or any distributor hereunder - prior to termination shall survive termination. - -9. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL - DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, - OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR - ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY - CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, - WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY - RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW - PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE - EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO - THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -10. U.S. GOVERNMENT END USERS. - - The Covered Code is a "commercial item," as that term is defined in - 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer - software" and "commercial computer software documentation," as such - terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 - C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), - all U.S. Government End Users acquire Covered Code with only those - rights set forth herein. - -11. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed by - California law provisions (except to the extent applicable law, if - any, provides otherwise), excluding its conflict-of-law provisions. - With respect to disputes in which at least one party is a citizen of, - or an entity chartered or registered to do business in the United - States of America, any litigation relating to this License shall be - subject to the jurisdiction of the Federal Courts of the Northern - District of California, with venue lying in Santa Clara County, - California, with the losing party responsible for costs, including - without limitation, court costs and reasonable attorneys' fees and - expenses. The application of the United Nations Convention on - Contracts for the International Sale of Goods is expressly excluded. - Any law or regulation which provides that the language of a contract - shall be construed against the drafter shall not apply to this - License. - -12. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or indirectly, - out of its utilization of rights under this License and You agree to - work with Initial Developer and Contributors to distribute such - responsibility on an equitable basis. Nothing herein is intended or - shall be deemed to constitute any admission of liability. - -13. MULTIPLE-LICENSED CODE. - - Initial Developer may designate portions of the Covered Code as - "Multiple-Licensed". "Multiple-Licensed" means that the Initial - Developer permits you to utilize portions of the Covered Code under - Your choice of the NPL or the alternative licenses, if any, specified - by the Initial Developer in the file described in Exhibit A. - -EXHIBIT A -Mozilla Public License. - - ``The contents of this file are subject to the Mozilla Public License - Version 1.1 (the "License"); you may not use this file except in - compliance with the License. You may obtain a copy of the License at - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - License for the specific language governing rights and limitations - under the License. - - The Original Code is ______________________________________. - - The Initial Developer of the Original Code is ________________________. - Portions created by ______________________ are Copyright (C) ______ - _______________________. All Rights Reserved. - - Contributor(s): ______________________________________. - - Alternatively, the contents of this file may be used under the terms - of the _____ license (the "[___] License"), in which case the - provisions of [______] License are applicable instead of those - above. If you wish to allow use of your version of this file only - under the terms of the [____] License and not to allow others to use - your version of this file under the MPL, indicate your decision by - deleting the provisions above and replace them with the notice and - other provisions required by the [___] License. If you do not delete - the provisions above, a recipient may use your version of this file - under either the MPL or the [___] License." - - [NOTE: The text of this Exhibit A may differ slightly from the text of - the notices in the Source Code files of the Original Code. You should - use the text of this Exhibit A rather than the text found in the - Original Code Source Code for Your Modifications.] -============================================================================ - - - The MD5 generator used for authentication in some modules is written by Aladdin Enterprises: -- cgit v1.2.3 From 3b6eadc990664f9929bceb4f7d14498cf672f0d1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sat, 7 Jul 2007 19:19:28 +0200 Subject: Fix some warnings in storage.c. --- lib/base64.c | 4 ++-- lib/base64.h | 2 +- lib/rc4.c | 8 ++++---- lib/rc4.h | 4 ++-- protocols/jabber/sasl.c | 7 ++++--- storage_xml.c | 15 +++++++++------ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/base64.c b/lib/base64.c index 69069dae..64e9692a 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -30,10 +30,10 @@ static const char real_b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv char *tobase64(const char *text) { - return base64_encode(text, strlen(text)); + return base64_encode((const unsigned char *)text, strlen(text)); } -char *base64_encode(const char *in, int len) +char *base64_encode(const unsigned char *in, int len) { char *out; diff --git a/lib/base64.h b/lib/base64.h index 570f2b14..ebd74bf1 100644 --- a/lib/base64.h +++ b/lib/base64.h @@ -26,7 +26,7 @@ #include <gmodule.h> G_MODULE_EXPORT char *tobase64( const char *text ); -G_MODULE_EXPORT char *base64_encode( const char *in, int len ); +G_MODULE_EXPORT char *base64_encode( const unsigned char *in, int len ); G_MODULE_EXPORT int base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, const char *b64digits ); G_MODULE_EXPORT char *frombase64( const char *in ); G_MODULE_EXPORT int base64_decode( const char *in, unsigned char **out ); diff --git a/lib/rc4.c b/lib/rc4.c index f2c76f54..635b802a 100644 --- a/lib/rc4.c +++ b/lib/rc4.c @@ -121,7 +121,7 @@ unsigned char rc4_getbyte( struct rc4_state *st ) Both functions return the number of bytes in the result string. */ -int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ) +int rc4_encode( char *clear, int clear_len, unsigned char **crypt, char *password ) { struct rc4_state *st; unsigned char *key; @@ -129,7 +129,7 @@ int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char key_len = strlen( password ) + RC4_IV_LEN; if( clear_len <= 0 ) - clear_len = strlen( (char*) clear ); + clear_len = strlen( clear ); /* Prepare buffers and the key + IV */ *crypt = g_malloc( clear_len + RC4_IV_LEN ); @@ -153,7 +153,7 @@ int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char return clear_len + RC4_IV_LEN; } -int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ) +int rc4_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ) { struct rc4_state *st; unsigned char *key; @@ -164,7 +164,7 @@ int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char if( clear_len < 0 ) { - *clear = (unsigned char*) g_strdup( "" ); + *clear = g_strdup( "" ); return 0; } diff --git a/lib/rc4.h b/lib/rc4.h index 2d4d3cc8..52de06b1 100644 --- a/lib/rc4.h +++ b/lib/rc4.h @@ -32,5 +32,5 @@ struct rc4_state struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ); unsigned char rc4_getbyte( struct rc4_state *st ); -int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ); -int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ); +int rc4_encode( char *clear, int clear_len, unsigned char **crypt, char *password ); +int rc4_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ); diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 69199a8b..6eee37b3 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -88,7 +88,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) s[0] = 0; strcpy( s + 1, jd->username ); strcpy( s + 2 + strlen( jd->username ), ic->acc->pass ); - reply->text = base64_encode( s, len ); + reply->text = base64_encode( (unsigned char *)s, len ); reply->text_len = strlen( reply->text ); g_free( s ); } @@ -184,7 +184,8 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *reply = NULL; - char *nonce = NULL, *realm = NULL, *cnonce = NULL, cnonce_bin[30]; + char *nonce = NULL, *realm = NULL, *cnonce = NULL; + unsigned char cnonce_bin[30]; char *digest_uri = NULL; char *dec = NULL; char *s = NULL; @@ -215,7 +216,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) if( !realm ) realm = g_strdup( jd->server ); - random_bytes( (unsigned char *) cnonce_bin, sizeof( cnonce_bin ) ); + random_bytes( cnonce_bin, sizeof( cnonce_bin ) ); cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) ); digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server ); diff --git a/storage_xml.c b/storage_xml.c index 00fca425..97379b29 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -131,7 +131,8 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na else if( g_strcasecmp( element_name, "account" ) == 0 ) { char *protocol, *handle, *server, *password = NULL, *autoconnect; - char *pass_b64 = NULL, *pass_rc4 = NULL; + char *pass_b64 = NULL; + unsigned char *pass_rc4 = NULL; int pass_len; struct prpl *prpl = NULL; @@ -151,8 +152,9 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown protocol: %s", protocol ); else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_rc4 ) ) && - rc4_decode( (unsigned char*) pass_rc4, pass_len, - (unsigned char**) &password, xd->given_pass ) ) + rc4_decode( pass_rc4, pass_len, + &password, + xd->given_pass ) ) { xd->current_account = account_add( irc, prpl, handle, password ); if( server ) @@ -409,7 +411,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ md5_finish( &md5_state, pass_md5 ); /* Save the hash in base64-encoded form. */ - pass_buf = base64_encode( (char*) pass_md5, 21 ); + pass_buf = base64_encode( pass_md5, 21 ); if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) ) goto write_error; @@ -423,10 +425,11 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) for( acc = irc->accounts; acc; acc = acc->next ) { - char *pass_rc4, *pass_b64; + unsigned char *pass_rc4; + char *pass_b64; int pass_len; - pass_len = rc4_encode( (unsigned char*) acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); + pass_len = rc4_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); pass_b64 = base64_encode( pass_rc4, pass_len ); g_free( pass_rc4 ); -- cgit v1.2.3 From b9e4ab55dff62611e825de013b32fadab782362f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sat, 7 Jul 2007 19:21:12 +0200 Subject: Fix ssl_bogus. --- lib/ssl_bogus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c index 00aaa7c4..5bae3496 100644 --- a/lib/ssl_bogus.c +++ b/lib/ssl_bogus.c @@ -51,6 +51,11 @@ int ssl_getfd( void *conn ) return( -1 ); } +void *ssl_starttls( int fd, ssl_input_function func, gpointer data ) +{ + return NULL; +} + b_input_condition ssl_getdirection( void *conn ) { return GAIM_INPUT_READ; -- cgit v1.2.3 From c9c7ca771d3b06ab448a72bdcddfdacd5be815c0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 11 Jul 2007 15:22:00 +0100 Subject: Fixed imc_logout() (assigning u too early). Stupid me. --- protocols/nogaim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 22d82ecb..7dc777ef 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -288,7 +288,7 @@ void cancel_auto_reconnect( account_t *a ) void imc_logout( struct im_connection *ic, int allow_reconnect ) { irc_t *irc = ic->irc; - user_t *t, *u = irc->users; + user_t *t, *u; account_t *a; /* Nested calls might happen sometimes, this is probably the best @@ -305,6 +305,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect ) ic->acc->prpl->logout( ic ); b_event_remove( ic->inpa ); + u = irc->users; while( u ) { if( u->ic == ic ) -- cgit v1.2.3 From cbaac62b34403c8bb2bd207e7d91da3d7884f4f7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 14 Jul 2007 18:20:18 +0100 Subject: Adding an epoch to "spoofed" version numbers to make sure apt doesn't stick with distro packages. --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index eb0417db..8d6bd4fa 100755 --- a/debian/rules +++ b/debian/rules @@ -66,7 +66,7 @@ binary-arch: build-arch install-arch find usr -type f -exec md5sum {} \; > DEBIAN/md5sums dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee ifdef BITLBEE_VERSION - dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' + dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v1:$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' else dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' endif -- cgit v1.2.3 From 1ffb46f027f501da45951428e097f69ced1c80e0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Jul 2007 00:45:30 +0100 Subject: Added join_chat command to the "help groupchat" information. --- doc/user-guide/misc.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/user-guide/misc.xml b/doc/user-guide/misc.xml index f90ce538..d387d4b3 100644 --- a/doc/user-guide/misc.xml +++ b/doc/user-guide/misc.xml @@ -79,6 +79,10 @@ If you want to start a groupchat with the person <emphasis>jim_msn</emphasis> in Of course a channel with only two people isn't really exciting yet. So the next step is to invite some other people to the channel. For this, you can use the <emphasis>/invite</emphasis> command of your IRC client. Please do keep in mind that all the people have to be on the same network and contact list! You can't invite Yahoo! buddies into an MSN groupchat. </para> +<para> +Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information. +</para> + <para> This is all you'll probably need to know. If you have any problems, please read <emphasis>help groupchats3</emphasis>. </para> -- cgit v1.2.3 From 1da00b12d498951219141000947927120b2fdbcc Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Jul 2007 00:47:38 +0100 Subject: Hiding LDAP support because it doesn't actually work at all ATM. --- configure | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure b/configure index bb7ddd7d..fec7544e 100755 --- a/configure +++ b/configure @@ -71,8 +71,6 @@ Option Description Default --ipv6=0/1 IPv6 socket support $ipv6 ---ldap=0/1/auto LDAP support $ldap - --events=... Event handler (glib, libevent) $events --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl -- cgit v1.2.3 From 85023c65b697d2dab932acbda31258ae5270dbe6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 15 Jul 2007 16:47:34 +0100 Subject: Added imcb_clean_handle() to sanitize handles properly (without putting IRC-specific stuff into the Jabber module). Only using this in the MUC code for now because this only works if the IM module can somehow convert the cleaned up handle back to the original one. --- protocols/jabber/conference.c | 3 +++ protocols/nogaim.c | 33 ++++++++++++++++++++++++++++++++- protocols/nogaim.h | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index f49dbd1c..3fc9ee70 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -179,6 +179,9 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu for( i = 0; bud->resource[i]; i ++ ) if( bud->ext_jid[i] == '=' || bud->ext_jid[i] == '@' ) bud->ext_jid[i] = '_'; + + /* Some program-specific restrictions. */ + imcb_clean_handle( ic, bud->ext_jid ); } bud->flags |= JBFLAG_IS_ANONYMOUS; } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 7dc777ef..4b0b738b 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -98,7 +98,6 @@ void register_protocol (struct prpl *p) protocols = g_list_append(protocols, p); } - struct prpl *find_protocol(const char *name) { GList *gl; @@ -1113,3 +1112,35 @@ void imc_rem_block( struct im_connection *ic, char *handle ) ic->acc->prpl->rem_deny( ic, handle ); } + +void imcb_clean_handle( struct im_connection *ic, char *handle ) +{ + /* Accepts a handle and does whatever is necessary to make it + BitlBee-friendly. Currently this means removing everything + outside 33-127 (ASCII printable excl spaces), @ (only one + is allowed) and ! and : */ + char out[strlen(handle)+1]; + int s, d; + + s = d = 0; + while( handle[s] ) + { + if( handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' && + ( handle[s] & 0x80 ) == 0 ) + { + if( handle[s] == '@' ) + { + /* See if we got an @ already? */ + out[d] = 0; + if( strchr( out, '@' ) ) + continue; + } + + out[d++] = handle[s]; + } + s ++; + } + out[d] = handle[s]; + + strcpy( handle, out ); +} diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 74a63306..6aa057ff 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -200,6 +200,7 @@ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *ha /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); +G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); /* Groupchats */ G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); -- cgit v1.2.3 From 1baaef858136cd3a4799b3ccf1d9961534e0017c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 30 Jul 2007 20:12:06 +0100 Subject: Added jabber_error_parse() and using it for both stream- and stanza (only presence so far) errors. --- protocols/jabber/io.c | 31 ++++++++----------------------- protocols/jabber/jabber.h | 7 +++++++ protocols/jabber/jabber_util.c | 35 +++++++++++++++++++++++++++++++++++ protocols/jabber/presence.c | 12 +++++++++++- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index edde5a8d..cf71ff87 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -435,50 +435,35 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) { struct im_connection *ic = data; - struct xt_node *c; - char *s, *type = NULL, *text = NULL; int allow_reconnect = TRUE; + struct jabber_error *err; - for( c = node->children; c; c = c->next ) - { - if( !( s = xt_find_attr( c, "xmlns" ) ) || - strcmp( s, XMLNS_STREAM_ERROR ) != 0 ) - continue; - - if( strcmp( c->name, "text" ) != 0 ) - { - type = c->name; - } - /* Only use the text if it doesn't have an xml:lang attribute, - if it's empty or if it's set to something English. */ - else if( !( s = xt_find_attr( c, "xml:lang" ) ) || - !*s || strncmp( s, "en", 2 ) == 0 ) - { - text = c->text; - } - } + err = jabber_error_parse( node, XMLNS_STREAM_ERROR ); /* Tssk... */ - if( type == NULL ) + if( err->code == NULL ) { imcb_error( ic, "Unknown stream error reported by server" ); imc_logout( ic, allow_reconnect ); + jabber_error_free( err ); return XT_ABORT; } /* We know that this is a fatal error. If it's a "conflict" error, we should turn off auto-reconnect to make sure we won't get some nasty infinite loop! */ - if( strcmp( type, "conflict" ) == 0 ) + if( strcmp( err->code, "conflict" ) == 0 ) { imcb_error( ic, "Account and resource used from a different location" ); allow_reconnect = FALSE; } else { - imcb_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" ); + imcb_error( ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "", + err->text ? err->text : "" ); } + jabber_error_free( err ); imc_logout( ic, allow_reconnect ); return XT_ABORT; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 90c1e9f6..7af7f98e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -193,6 +193,11 @@ typedef enum GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */ } get_buddy_flags_t; +struct jabber_error +{ + char *code, *text, *type; +}; + struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); @@ -200,6 +205,8 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ); time_t jabber_get_timestamp( struct xt_node *xt ); +struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ); +void jabber_error_free( struct jabber_error *err ); extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 5b91c5ed..56491c4f 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -647,3 +647,38 @@ time_t jabber_get_timestamp( struct xt_node *xt ) return res; } + +struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ) +{ + struct jabber_error *err = g_new0( struct jabber_error, 1 ); + struct xt_node *c; + char *s; + + err->type = xt_find_attr( node, "type" ); + + for( c = node->children; c; c = c->next ) + { + if( !( s = xt_find_attr( c, "xmlns" ) ) || + strcmp( s, xmlns ) != 0 ) + continue; + + if( strcmp( c->name, "text" ) != 0 ) + { + err->code = c->name; + } + /* Only use the text if it doesn't have an xml:lang attribute, + if it's empty or if it's set to something English. */ + else if( !( s = xt_find_attr( c, "xml:lang" ) ) || + !*s || strncmp( s, "en", 2 ) == 0 ) + { + err->text = c->text; + } + } + + return err; +} + +void jabber_error_free( struct jabber_error *err ) +{ + g_free( err ); +} diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index e53978ea..cbfcedae 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -157,7 +157,17 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) } else if( strcmp( type, "error" ) == 0 ) { - /* What to do with it? */ + struct jabber_error *err; + + if( ( c = xt_find_node( node->children, "error" ) ) ) + { + err = jabber_error_parse( c, XMLNS_STANZA_ERROR ); + imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name, + err->code, err->text ? ": " : "", + err->text ? err->text : "" ); + jabber_error_free( err ); + } + /* What else to do with it? */ } else { -- cgit v1.2.3 From 82135c7178b6379f35741991f6c06bb308143194 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 8 Aug 2007 10:20:57 +0100 Subject: Not trying to handle typing notifications from unknown buddies anymore (NULL pointer dereference). --- protocols/jabber/message.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 52ee3a53..fab62a91 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -89,7 +89,11 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) g_string_free( fullmsg, TRUE ); /* Handling of incoming typing notifications. */ - if( xt_find_node( node->children, "composing" ) ) + if( bud == NULL ) + { + /* Can't handle these for unknown buddies. */ + } + else if( xt_find_node( node->children, "composing" ) ) { bud->flags |= JBFLAG_DOES_XEP85; imcb_buddy_typing( ic, from, OPT_TYPING ); -- cgit v1.2.3 From 2abfbc5e9ef942937f9ef662262d00fa5e47301f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 30 Aug 2007 23:17:51 +0100 Subject: From vmiklos: Added --plugins= option to configure script. --- configure | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure b/configure index fec7544e..ca7e0268 100755 --- a/configure +++ b/configure @@ -28,6 +28,7 @@ yahoo=1 debug=0 strip=1 gcov=0 +plugins=1 ipv6=1 events=glib @@ -68,6 +69,7 @@ Option Description Default --debug=0/1 Disable/enable debugging $debug --strip=0/1 Disable/enable binary stripping $strip --gcov=0/1 Disable/enable test coverage reporting $gcov +--plugins=0/1 Disable/enable plugins support $plugins --ipv6=0/1 IPv6 socket support $ipv6 @@ -382,6 +384,12 @@ if [ "$gcov" = "1" ]; then echo "EFLAGS+=-lgcov" >> Makefile.settings fi +if [ "$plugins" = 0 ]; then + echo '#undef WITH_PLUGINS' >> config.h +else + echo '#define WITH_PLUGINS' >> config.h +fi + echo if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then nick=`bzr nick` -- cgit v1.2.3 From f2b171d39a6e93e7d05e421f81cd120276906e3e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 30 Aug 2007 23:22:43 +0100 Subject: From vmiklos: Fixed list of header files in Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f32dae84..039c202a 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # Program variables objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o -headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h +headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha.h lib/ssl_client.h lib/url.h protocols/nogaim.h subdirs = lib protocols # Expansion of variables -- cgit v1.2.3 From 8ad90fbd65d544ac207d52780499df76db9adc6f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 30 Aug 2007 23:23:07 +0100 Subject: From vmiklos: More verbose error message on plugin load failures. --- protocols/nogaim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index a70d6eca..9ebd048e 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -47,7 +47,7 @@ gboolean load_plugin(char *path) GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY); if(!mod) { - log_message(LOGLVL_ERROR, "Can't find `%s', not loading", path); + log_message(LOGLVL_ERROR, "Can't find `%s', not loading (%s)\n", path, g_module_error()); return FALSE; } -- cgit v1.2.3 From 60c1a4e76a343c0dbc19690b486190681265db4c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 30 Aug 2007 23:30:27 +0100 Subject: Changed the order in which things are loaded a little bit so global.conf->plugindir is actually filled in before we call nogaim_init(). --- unix.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/unix.c b/unix.c index 2be16b2b..0abf43ea 100644 --- a/unix.c +++ b/unix.c @@ -46,19 +46,18 @@ int main( int argc, char *argv[], char **envp ) memset( &global, 0, sizeof( global_t ) ); - b_main_init(); log_init(); - nogaim_init(); - - srand( time( NULL ) ^ getpid() ); - CONF_FILE = g_strdup( CONF_FILE_DEF ); - global.helpfile = g_strdup( HELP_FILE ); - global.conf = conf_load( argc, argv ); if( global.conf == NULL ) return( 1 ); + b_main_init(); + nogaim_init(); + + srand( time( NULL ) ^ getpid() ); + global.helpfile = g_strdup( HELP_FILE ); + if( global.conf->runmode == RUNMODE_INETD ) { i = bitlbee_inetd_init(); -- cgit v1.2.3 From 8d32b9e8328605bb52c87b53f1f27028e68336e5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 1 Sep 2007 22:57:22 +0100 Subject: Made UTF-8 the new default charset. This is the default on pretty much every recent machin. --- irc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irc.c b/irc.c index e953bfad..254bdbdc 100644 --- a/irc.c +++ b/irc.c @@ -131,7 +131,7 @@ irc_t *irc_new( int fd ) set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc ); set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); - set_add( &irc->set, "charset", "iso8859-1", set_eval_charset, irc ); + set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); set_add( &irc->set, "debug", "false", set_eval_bool, irc ); set_add( &irc->set, "default_target", "root", NULL, irc ); set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); -- cgit v1.2.3 From 9334cc280474ae55f67e058797e214d30251973a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 25 Sep 2007 09:08:56 +0100 Subject: Fixed NULL pointer dereference in "account set" command. That command indeed does have a slightly confusing syntax. --- root_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/root_commands.c b/root_commands.c index a7582936..baaf3354 100644 --- a/root_commands.c +++ b/root_commands.c @@ -382,7 +382,7 @@ static void cmd_account( irc_t *irc, char **cmd ) return; } - if( cmd[3] ) + if( cmd[3] && set_name ) { set_t *s = set_find( &a->set, set_name ); -- cgit v1.2.3 From a7b59252ddd85810c3b14357fd43602c800b9cb6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 7 Oct 2007 21:42:37 +0100 Subject: Renaming RC4 to ArcFour (possible trademark issues). --- lib/Makefile | 2 +- lib/arc.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/arc.h | 36 +++++++++++ lib/rc4.c | 189 --------------------------------------------------------- lib/rc4.h | 36 ----------- storage_xml.c | 18 +++--- 6 files changed, 238 insertions(+), 235 deletions(-) create mode 100644 lib/arc.c create mode 100644 lib/arc.h delete mode 100644 lib/rc4.c delete mode 100644 lib/rc4.h diff --git a/lib/Makefile b/lib/Makefile index a9038987..bc1966d9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o +objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha.o $(SSL_CLIENT) url.o CFLAGS += -Wall LFLAGS += -r diff --git a/lib/arc.c b/lib/arc.c new file mode 100644 index 00000000..a8e863f2 --- /dev/null +++ b/lib/arc.c @@ -0,0 +1,192 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple (but secure) ArcFour implementation for safer password storage. * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* 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, version * +* 2.1. * +* * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +\***************************************************************************/ + +/* + This file implements ArcFour-encryption, which will mainly be used to + save IM passwords safely in the new XML-format. Possibly other uses will + come up later. It's supposed to be quite reliable (thanks to the use of a + 6-byte IV/seed), certainly compared to the old format. The only realistic + way to crack BitlBee passwords now is to use a sniffer to get your hands + on the user's password. + + If you see that something's wrong in this implementation (I asked a + couple of people to look at it already, but who knows), please tell me. + + The reason I picked ArcFour is because it's pretty simple but effective, + so it will work without adding several KBs or an extra library dependency. + + (ArcFour is an RC4-compatible cipher. See for details: + http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt) +*/ + + +#include <glib.h> +#include <gmodule.h> +#include <stdlib.h> +#include <string.h> +#include "misc.h" +#include "arc.h" + +/* Add some seed to the password, to make sure we *never* use the same key. + This defines how many bytes we use as a seed. */ +#define ARC_IV_LEN 6 + +/* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended + to shuffle S[] just a bit more before you start to use it. This defines how + many bytes we'll request before we'll really use them for encryption. */ +#define ARC_CYCLES 1024 + +struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) +{ + struct arc_state *st; + int i, j, tmp; + + st = g_malloc( sizeof( struct arc_state ) ); + st->i = st->j = 0; + for( i = 0; i < 256; i ++ ) + st->S[i] = i; + + if( kl <= 0 ) + kl = strlen( (char*) key ); + + for( i = j = 0; i < 256; i ++ ) + { + j = ( j + st->S[i] + key[i%kl] ) & 0xff; + tmp = st->S[i]; + st->S[i] = st->S[j]; + st->S[j] = tmp; + } + + for( i = 0; i < cycles; i ++ ) + arc_getbyte( st ); + + return st; +} + +/* + For those who don't know, ArcFour is basically an algorithm that generates + a stream of bytes after you give it a key. Just get a byte from it and + xor it with your cleartext. To decrypt, just give it the same key again + and start xorring. + + The function above initializes the byte generator, the next function can + be used to get bytes from the generator (and shuffle things a bit). +*/ + +unsigned char arc_getbyte( struct arc_state *st ) +{ + unsigned char tmp; + + /* Unfortunately the st-> stuff doesn't really improve readability here... */ + st->i ++; + st->j += st->S[st->i]; + tmp = st->S[st->i]; + st->S[st->i] = st->S[st->j]; + st->S[st->j] = tmp; + + return st->S[(st->S[st->i] + st->S[st->j]) & 0xff]; +} + +/* + The following two functions can be used for reliable encryption and + decryption. Known plaintext attacks are prevented by adding some (6, + by default) random bytes to the password before setting up the state + structures. These 6 bytes are also saved in the results, because of + course we'll need them in arc_decode(). + + Because the length of the resulting string is unknown to the caller, + it should pass a char**. Since the encode/decode functions allocate + memory for the string, make sure the char** points at a NULL-pointer + (or at least to something you already free()d), or you'll leak + memory. And of course, don't forget to free() the result when you + don't need it anymore. + + Both functions return the number of bytes in the result string. +*/ + +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password ) +{ + struct arc_state *st; + unsigned char *key; + int key_len, i; + + key_len = strlen( password ) + ARC_IV_LEN; + if( clear_len <= 0 ) + clear_len = strlen( clear ); + + /* Prepare buffers and the key + IV */ + *crypt = g_malloc( clear_len + ARC_IV_LEN ); + key = g_malloc( key_len ); + strcpy( (char*) key, password ); + + /* Add the salt. Save it for later (when decrypting) and, of course, + add it to the encryption key. */ + random_bytes( crypt[0], ARC_IV_LEN ); + memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN ); + + /* Generate the initial S[] from the IVed key. */ + st = arc_keymaker( key, key_len, ARC_CYCLES ); + g_free( key ); + + for( i = 0; i < clear_len; i ++ ) + crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st ); + + g_free( st ); + + return clear_len + ARC_IV_LEN; +} + +int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ) +{ + struct arc_state *st; + unsigned char *key; + int key_len, clear_len, i; + + key_len = strlen( password ) + ARC_IV_LEN; + clear_len = crypt_len - ARC_IV_LEN; + + if( clear_len < 0 ) + { + *clear = g_strdup( "" ); + return 0; + } + + /* Prepare buffers and the key + IV */ + *clear = g_malloc( clear_len + 1 ); + key = g_malloc( key_len ); + strcpy( (char*) key, password ); + for( i = 0; i < ARC_IV_LEN; i ++ ) + key[key_len-ARC_IV_LEN+i] = crypt[i]; + + /* Generate the initial S[] from the IVed key. */ + st = arc_keymaker( key, key_len, ARC_CYCLES ); + g_free( key ); + + for( i = 0; i < clear_len; i ++ ) + clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st ); + clear[0][i] = 0; /* Nice to have for plaintexts. */ + + g_free( st ); + + return clear_len; +} diff --git a/lib/arc.h b/lib/arc.h new file mode 100644 index 00000000..882372ed --- /dev/null +++ b/lib/arc.h @@ -0,0 +1,36 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple (but secure) ArcFour implementation for safer password storage. * +* * +* Copyright 2007 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * +* * +\***************************************************************************/ + + +/* See arc.c for more information. */ + +struct arc_state +{ + unsigned char S[256]; + unsigned char i, j; +}; + +struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ); +unsigned char arc_getbyte( struct arc_state *st ); +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password ); +int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ); diff --git a/lib/rc4.c b/lib/rc4.c deleted file mode 100644 index 635b802a..00000000 --- a/lib/rc4.c +++ /dev/null @@ -1,189 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple (but secure) RC4 implementation for safer password storage. * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * -* * -* 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, version * -* 2.1. * -* * -* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * -* * -\***************************************************************************/ - -/* - This file implements RC4-encryption, which will mainly be used to save IM - passwords safely in the new XML-format. Possibly other uses will come up - later. It's supposed to be quite reliable (thanks to the use of a 6-byte - IV/seed), certainly compared to the old format. The only realistic way to - crack BitlBee passwords now is to use a sniffer to get your hands on the - user's password. - - If you see that something's wrong in this implementation (I asked a - couple of people to look at it already, but who knows), please tell me. - - The reason I chose for RC4 is because it's pretty simple but effective, - so it will work without adding several KBs or an extra library dependency. -*/ - - -#include <glib.h> -#include <gmodule.h> -#include <stdlib.h> -#include <string.h> -#include "misc.h" -#include "rc4.h" - -/* Add some seed to the password, to make sure we *never* use the same key. - This defines how many bytes we use as a seed. */ -#define RC4_IV_LEN 6 - -/* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended - to shuffle S[] just a bit more before you start to use it. This defines how - many bytes we'll request before we'll really use them for encryption. */ -#define RC4_CYCLES 1024 - -struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ) -{ - struct rc4_state *st; - int i, j, tmp; - - st = g_malloc( sizeof( struct rc4_state ) ); - st->i = st->j = 0; - for( i = 0; i < 256; i ++ ) - st->S[i] = i; - - if( kl <= 0 ) - kl = strlen( (char*) key ); - - for( i = j = 0; i < 256; i ++ ) - { - j = ( j + st->S[i] + key[i%kl] ) & 0xff; - tmp = st->S[i]; - st->S[i] = st->S[j]; - st->S[j] = tmp; - } - - for( i = 0; i < cycles; i ++ ) - rc4_getbyte( st ); - - return st; -} - -/* - For those who don't know, RC4 is basically an algorithm that generates a - stream of bytes after you give it a key. Just get a byte from it and xor - it with your cleartext. To decrypt, just give it the same key again and - start xorring. - - The function above initializes the RC4 byte generator, the next function - can be used to get bytes from the generator (and shuffle things a bit). -*/ - -unsigned char rc4_getbyte( struct rc4_state *st ) -{ - unsigned char tmp; - - /* Unfortunately the st-> stuff doesn't really improve readability here... */ - st->i ++; - st->j += st->S[st->i]; - tmp = st->S[st->i]; - st->S[st->i] = st->S[st->j]; - st->S[st->j] = tmp; - - return st->S[(st->S[st->i] + st->S[st->j]) & 0xff]; -} - -/* - The following two functions can be used for reliable encryption and - decryption. Known plaintext attacks are prevented by adding some (6, - by default) random bytes to the password before setting up the RC4 - structures. These 6 bytes are also saved in the results, because of - course we'll need them in rc4_decode(). - - Because the length of the resulting string is unknown to the caller, - it should pass a char**. Since the encode/decode functions allocate - memory for the string, make sure the char** points at a NULL-pointer - (or at least to something you already free()d), or you'll leak - memory. And of course, don't forget to free() the result when you - don't need it anymore. - - Both functions return the number of bytes in the result string. -*/ - -int rc4_encode( char *clear, int clear_len, unsigned char **crypt, char *password ) -{ - struct rc4_state *st; - unsigned char *key; - int key_len, i; - - key_len = strlen( password ) + RC4_IV_LEN; - if( clear_len <= 0 ) - clear_len = strlen( clear ); - - /* Prepare buffers and the key + IV */ - *crypt = g_malloc( clear_len + RC4_IV_LEN ); - key = g_malloc( key_len ); - strcpy( (char*) key, password ); - - /* Add the salt. Save it for later (when decrypting) and, of course, - add it to the encryption key. */ - random_bytes( crypt[0], RC4_IV_LEN ); - memcpy( key + key_len - RC4_IV_LEN, crypt[0], RC4_IV_LEN ); - - /* Generate the initial S[] from the IVed key. */ - st = rc4_keymaker( key, key_len, RC4_CYCLES ); - g_free( key ); - - for( i = 0; i < clear_len; i ++ ) - crypt[0][i+RC4_IV_LEN] = clear[i] ^ rc4_getbyte( st ); - - g_free( st ); - - return clear_len + RC4_IV_LEN; -} - -int rc4_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ) -{ - struct rc4_state *st; - unsigned char *key; - int key_len, clear_len, i; - - key_len = strlen( password ) + RC4_IV_LEN; - clear_len = crypt_len - RC4_IV_LEN; - - if( clear_len < 0 ) - { - *clear = g_strdup( "" ); - return 0; - } - - /* Prepare buffers and the key + IV */ - *clear = g_malloc( clear_len + 1 ); - key = g_malloc( key_len ); - strcpy( (char*) key, password ); - for( i = 0; i < RC4_IV_LEN; i ++ ) - key[key_len-RC4_IV_LEN+i] = crypt[i]; - - /* Generate the initial S[] from the IVed key. */ - st = rc4_keymaker( key, key_len, RC4_CYCLES ); - g_free( key ); - - for( i = 0; i < clear_len; i ++ ) - clear[0][i] = crypt[i+RC4_IV_LEN] ^ rc4_getbyte( st ); - clear[0][i] = 0; /* Nice to have for plaintexts. */ - - g_free( st ); - - return clear_len; -} diff --git a/lib/rc4.h b/lib/rc4.h deleted file mode 100644 index 52de06b1..00000000 --- a/lib/rc4.h +++ /dev/null @@ -1,36 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple (but secure) RC4 implementation for safer password storage. * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.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 02110-1301 USA. * -* * -\***************************************************************************/ - - -/* See rc4.c for more information. */ - -struct rc4_state -{ - unsigned char S[256]; - unsigned char i, j; -}; - -struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ); -unsigned char rc4_getbyte( struct rc4_state *st ); -int rc4_encode( char *clear, int clear_len, unsigned char **crypt, char *password ); -int rc4_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ); diff --git a/storage_xml.c b/storage_xml.c index e45c4252..8618c5fe 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -26,7 +26,7 @@ #define BITLBEE_CORE #include "bitlbee.h" #include "base64.h" -#include "rc4.h" +#include "arc.h" #include "md5.h" typedef enum @@ -132,7 +132,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { char *protocol, *handle, *server, *password = NULL, *autoconnect; char *pass_b64 = NULL; - unsigned char *pass_rc4 = NULL; + unsigned char *pass_cr = NULL; int pass_len; struct prpl *prpl = NULL; @@ -151,8 +151,8 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na else if( !prpl ) g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Unknown protocol: %s", protocol ); - else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_rc4 ) ) && - rc4_decode( pass_rc4, pass_len, &password, xd->given_pass ) ) + else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_cr ) ) && + arc_decode( pass_cr, pass_len, &password, xd->given_pass ) ) { xd->current_account = account_add( irc, prpl, handle, password ); if( server ) @@ -168,7 +168,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na "Error while decrypting account password" ); } - g_free( pass_rc4 ); + g_free( pass_cr ); g_free( password ); } else if( g_strcasecmp( element_name, "setting" ) == 0 ) @@ -423,13 +423,13 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) for( acc = irc->accounts; acc; acc = acc->next ) { - unsigned char *pass_rc4; + unsigned char *pass_cr; char *pass_b64; int pass_len; - pass_len = rc4_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); - pass_b64 = base64_encode( pass_rc4, pass_len ); - g_free( pass_rc4 ); + pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password ); + pass_b64 = base64_encode( pass_cr, pass_len ); + g_free( pass_cr ); if( !xml_printf( fd, 1, "<account protocol=\"%s\" handle=\"%s\" password=\"%s\" autoconnect=\"%d\"", acc->prpl->name, acc->user, pass_b64, acc->auto_connect ) ) { -- cgit v1.2.3 From 2305488d0a81193648dec7304f5a6a768e0c926b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 7 Oct 2007 22:45:41 +0100 Subject: Adding test for arc.c so that I can now safely replace the RC4 code with a (compatible) ArcFour implementation. --- tests/Makefile | 2 +- tests/check.c | 4 +++ tests/check_arc.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 tests/check_arc.c diff --git a/tests/Makefile b/tests/Makefile index 4d4ed8d3..5bc3fbde 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -12,7 +12,7 @@ distclean: clean main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 488d9608..043889d6 100644 --- a/tests/check.c +++ b/tests/check.c @@ -47,6 +47,9 @@ Suite *nick_suite(void); /* From check_md5.c */ Suite *md5_suite(void); +/* From check_arc.c */ +Suite *arc_suite(void); + /* From check_irc.c */ Suite *irc_suite(void); @@ -101,6 +104,7 @@ int main (int argc, char **argv) sr = srunner_create(util_suite()); srunner_add_suite(sr, nick_suite()); srunner_add_suite(sr, md5_suite()); + srunner_add_suite(sr, arc_suite()); srunner_add_suite(sr, irc_suite()); srunner_add_suite(sr, help_suite()); srunner_add_suite(sr, user_suite()); diff --git a/tests/check_arc.c b/tests/check_arc.c new file mode 100644 index 00000000..a9bc2770 --- /dev/null +++ b/tests/check_arc.c @@ -0,0 +1,95 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "arc.h" + +char *password = "TotT"; + +char *clear_tests[] = +{ + "Wie dit leest is gek :-)", + "ItllBeBitlBee", + "One more boring password", + NULL +}; + +static void check_codec(int l) +{ + int i; + + for( i = 0; clear_tests[i]; i++ ) + { + tcase_fn_start (clear_tests[i], __FILE__, __LINE__); + unsigned char *crypted; + char *decrypted; + int len; + + len = arc_encode( clear_tests[i], 0, &crypted, password ); + len = arc_decode( crypted, len, &decrypted, password ); + + fail_if( strcmp( clear_tests[i], decrypted ) != 0, + "%s didn't decrypt back properly", clear_tests[i] ); + + g_free( crypted ); + g_free( decrypted ); + } +} + +struct +{ + const unsigned char crypted[24]; + int len; + char *decrypted; +} decrypt_tests[] = { + { + { + 0xc3, 0x0d, 0x43, 0xc3, 0xee, 0x80, 0xe2, 0x8c, 0x0b, 0x29, 0x32, 0x7e, + 0x38, 0x05, 0x82, 0x10, 0x21, 0x1c, 0x4a, 0x00, 0x2c + }, 21, "Debugging sucks" + }, + { + { + 0xb0, 0x00, 0x57, 0x0d, 0x0d, 0x0d, 0x70, 0xe1, 0xc0, 0x00, 0xa4, 0x25, + 0x7d, 0xbe, 0x03, 0xcc, 0x24, 0xd1, 0x0c + }, 19, "Testing rocks" + }, + { + { + 0xb6, 0x92, 0x59, 0xe4, 0xf9, 0xc1, 0x7a, 0xf6, 0xf3, 0x18, 0xea, 0x28, + 0x73, 0x6d, 0xb3, 0x0a, 0x6f, 0x0a, 0x2b, 0x43, 0x57, 0xe9, 0x3e, 0x63 + }, 24, "OSCAR is creepy..." + } +}; + +static void check_decod(int l) +{ + int i; + + for( i = 0; clear_tests[i]; i++ ) + { + tcase_fn_start (decrypt_tests[i].decrypted, __FILE__, __LINE__); + char *decrypted; + int len; + + len = arc_decode( decrypt_tests[i].crypted, decrypt_tests[i].len, + &decrypted, password ); + + fail_if( strcmp( decrypt_tests[i].decrypted, decrypted ) != 0, + "%s didn't decrypt properly", clear_tests[i] ); + + g_free( decrypted ); + } +} + +Suite *arc_suite (void) +{ + Suite *s = suite_create("ArcFour"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, check_codec); + tcase_add_test (tc_core, check_decod); + return s; +} -- cgit v1.2.3 From e2869bf14ee7aca93d29edd142d60a7184b4d449 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 7 Oct 2007 23:07:25 +0100 Subject: "Changed" the ArcFour implementation. I'm afraid this was a waste of time, but at least I added a neat unittest... --- lib/arc.c | 18 +++++++++++++----- tests/check_arc.c | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/arc.c b/lib/arc.c index a8e863f2..617f6b96 100644 --- a/lib/arc.c +++ b/lib/arc.c @@ -60,23 +60,30 @@ struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) { struct arc_state *st; int i, j, tmp; + unsigned char S2[256]; st = g_malloc( sizeof( struct arc_state ) ); st->i = st->j = 0; - for( i = 0; i < 256; i ++ ) - st->S[i] = i; - if( kl <= 0 ) kl = strlen( (char*) key ); + for( i = 0; i < 256; i ++ ) + { + st->S[i] = i; + S2[i] = key[i%kl]; + } + for( i = j = 0; i < 256; i ++ ) { - j = ( j + st->S[i] + key[i%kl] ) & 0xff; + j = ( j + st->S[i] + S2[i] ) & 0xff; tmp = st->S[i]; st->S[i] = st->S[j]; st->S[j] = tmp; } + memset( S2, 0, 256 ); + i = j = 0; + for( i = 0; i < cycles; i ++ ) arc_getbyte( st ); @@ -103,8 +110,9 @@ unsigned char arc_getbyte( struct arc_state *st ) tmp = st->S[st->i]; st->S[st->i] = st->S[st->j]; st->S[st->j] = tmp; + tmp = (st->S[st->i] + st->S[st->j]) & 0xff; - return st->S[(st->S[st->i] + st->S[st->j]) & 0xff]; + return st->S[tmp]; } /* diff --git a/tests/check_arc.c b/tests/check_arc.c index a9bc2770..989a0a66 100644 --- a/tests/check_arc.c +++ b/tests/check_arc.c @@ -40,7 +40,7 @@ static void check_codec(int l) struct { - const unsigned char crypted[24]; + unsigned char crypted[24]; int len; char *decrypted; } decrypt_tests[] = { -- cgit v1.2.3 From acd61b90ac5da7bcc15506194994116a9378fb14 Mon Sep 17 00:00:00 2001 From: Miklos Vajna <vmiklos@frugalware.org> Date: Mon, 8 Oct 2007 02:04:33 +0200 Subject: Improve comments in nogaim.h so that writing support for new protocols will be easier. --- protocols/nogaim.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 6 deletions(-) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 59f9e870..26a6cc01 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -97,14 +97,21 @@ struct groupchat { struct im_connection *ic; /* stuff used just for chat */ + /* The in_room variable is a list of handles (not nicks!), kind of + * "nick list". This is how you can check who is in the group chat + * already, for example to avoid adding somebody two times. */ GList *in_room; GList *ignored; /* BitlBee */ struct groupchat *next; char *channel; + /* The title variable contains the ID you gave when you created the + * chat using imcb_chat_new(). */ char *title; char joined; + /* This is for you, you can add your own structure here to extend this + * structure for your protocol's needs. */ void *data; }; @@ -123,26 +130,52 @@ struct buddy { struct prpl { int options; + /* You should set this to the name of your protocol. + * - The user sees this name ie. when imcb_log() is used. */ const char *name; /* Added this one to be able to add per-account settings, don't think - it should be used for anything else. */ + * it should be used for anything else. You are supposed to use the + * set_add() function to add new settings. */ void (* init) (account_t *); - /* These should all be pretty obvious. */ + /* The typical usage of the login() function: + * - Create an im_connection using imcb_new() from the account_t parameter. + * - Initialize your myproto_data struct - you should store all your protocol-specific data there. + * - Save your custom structure to im_connection->proto_data. + * - Use proxy_connect() to connect to the server. + */ void (* login) (account_t *); + /* Implementing this function is optional. */ void (* keepalive) (struct im_connection *); + /* In this function you should: + * - Tell the server about you are logging out. + * - g_free() your myproto_data struct as BitlBee does not know how to + * properly do so. + */ void (* logout) (struct im_connection *); + /* This function is called when the user wants to send a message to a handle. + * - 'to' is a handle, not a nick + * - 'flags' may be ignored + */ int (* buddy_msg) (struct im_connection *, char *to, char *message, int flags); + /* This function is called then the user uses the /away IRC command. + * - 'state' contains the away reason. + * - 'message' may be ignored if your protocol does not support it. + */ void (* set_away) (struct im_connection *, char *state, char *message); + /* Implementing this function is optional. */ void (* get_away) (struct im_connection *, char *who); + /* Implementing this function is optional. */ int (* send_typing) (struct im_connection *, char *who, int flags); - /* For now BitlBee doesn't really handle groups, just set it to NULL. */ + /* 'name' is a handle to add/remove. For now BitlBee doesn't really + * handle groups, just set it to NULL, so you can ignore that + * parameter. */ void (* add_buddy) (struct im_connection *, char *name, char *group); void (* remove_buddy) (struct im_connection *, char *name, char *group); - /* Block list stuff. */ + /* Block list stuff. Implementing these are optional. */ void (* add_permit) (struct im_connection *, char *who); void (* add_deny) (struct im_connection *, char *who); void (* rem_permit) (struct im_connection *, char *who); @@ -151,23 +184,41 @@ struct prpl { void (* set_permit_deny)(struct im_connection *); /* Request profile info. Free-formatted stuff, the IM module gives back - this info via imcb_log(). */ + this info via imcb_log(). Implementing these are optional. */ void (* get_info) (struct im_connection *, char *who); void (* set_my_name) (struct im_connection *, char *name); void (* set_name) (struct im_connection *, char *who, char *name); /* Group chat stuff. */ + /* This is called when the user uses the /invite IRC command. + * - 'who' may be ignored + * - 'message' is a handle to invite + */ void (* chat_invite) (struct groupchat *, char *who, char *message); + /* This is called when the user uses the /part IRC command in a group + * chat. You just should tell the user about it, nothing more. */ void (* chat_leave) (struct groupchat *); + /* This is called when the user sends a message to the groupchat. + * 'flags' may be ignored. */ void (* chat_msg) (struct groupchat *, char *message, int flags); + /* This is called when the user uses the /join #nick IRC command. + * - 'who' is the handle of the nick + */ struct groupchat * (* chat_with) (struct im_connection *, char *who); + /* This is used when the user uses the /join #channel IRC command. If + * your protocol does not support publicly named group chats, then do + * not implement this. */ struct groupchat * (* chat_join) (struct im_connection *, char *room, char *nick, char *password); + /* You can tell what away states your protocol supports, so that + * BitlBee will try to map the IRC away reasons to them, or use + * GAIM_AWAY_CUSTOM when calling skype_set_away(). */ GList *(* away_states)(struct im_connection *ic); - /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ + /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* + * - Most protocols will just want to set this to g_strcasecmp().*/ int (* handle_cmp) (const char *who1, const char *who2); }; @@ -175,37 +226,68 @@ struct prpl { void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); G_MODULE_EXPORT struct prpl *find_protocol( const char *name ); +/* When registering a new protocol, you should allocate space for a new prpl + * struct, initialize it (set the function pointers to point to your + * functions), finally call this function. */ G_MODULE_EXPORT void register_protocol( struct prpl * ); /* Connection management. */ +/* You will need this function in prpl->login() to get an im_connection from + * the account_t parameter. */ G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc ); G_MODULE_EXPORT void imcb_free( struct im_connection *ic ); +/* Once you're connected, you should call this function, so that the user will + * see the success. */ G_MODULE_EXPORT void imcb_connected( struct im_connection *ic ); +/* This can be used to disconnect when something went wrong (ie. read error + * from the server). You probably want to set the second parameter to TRUE. */ G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect ); /* Communicating with the user. */ +/* A printf()-like function to tell the user anything you want. */ G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +/* To tell the user an error, ie. before logging out when an error occurs. */ G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +/* To ask a your about something. + * - 'msg' is the question. + * - 'data' can be your custom struct - it will be passed to the callbacks. + * - 'doit' or 'dont' will be called depending of the answer of the user. + */ G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont ); G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname ); /* Buddy management */ +/* This function should be called for each handle which are visible to the + * user, usually after a login. */ G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ); G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ); G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname ); /* Buddy activity */ +/* To manipulate the status of a handle. + * - flags can be |='d with OPT_* constants. You will need at least: + * OPT_LOGGED_IN and OPT_AWAY. + * - 'state' and 'message' can be NULL */ G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); +/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); /* Groupchats */ G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); +/* These two functions are to create a group chat. + * - imcb_chat_new(): the 'handle' parameter identifies the chat, like the + * channel name on IRC. + * - After you have a groupchat pointer, you should add the handles, finally + * the user her/himself. At that point the group chat will be visible to the + * user, too. */ G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ); G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); +/* To remove a handle from a group chat. Reason can be NULL. */ G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); +/* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c ); struct groupchat *chat_by_channel( char *channel ); -- cgit v1.2.3 From 8c2008ec2944c3eee13a25656cbd715f352ba4ed Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 10 Oct 2007 22:56:32 +0100 Subject: Added 1.0.4 changes to doc/CHANGES. --- doc/CHANGES | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/CHANGES b/doc/CHANGES index 3f509c46..6c109f25 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,4 @@ -Version 1.1dev: +Version 1.2: - First BitlBee development/testing RELEASE. This should be quite stable though (and for most people more stable than 1.0.x). It just has a couple of rough edges and needs a bit more testing. @@ -65,6 +65,21 @@ Version 1.1dev: resources available for that buddy. (Of course this only works if the buddy is in your contact list.) +Finished ??? + +Version 1.0.4: +- Removed sethostent(), which causes problems for many people, especially on + *BSD. This is basically the reason for this release. +- "allow" command actually displays the allow list, not the block list. +- Yahoo away state/msg fix. +- Don't display "Gender: Male" by default if nothing's filled in (OSCAR + "info" command) +- Fixed account cleanup (possible infinite loop) in irc_free(). +- Fixed configdir error message to not always display the compile-time + setting. + +Finished 20 Aug 2007 + Version 1.0.3: - Fixed ugliness in block/allow list commands (still not perfect though, the list is empty or not up-to-date for most protocols). -- cgit v1.2.3 From 118638279f7a39422d9e07365b380fa773c5243e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 10 Oct 2007 23:15:59 +0100 Subject: Made the netsplit-like quit messages optional. --- doc/user-guide/commands.xml | 10 ++++++++++ irc.c | 3 ++- protocols/nogaim.c | 16 ++++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 6646d0db..cf40782f 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -595,6 +595,16 @@ </description> </bitlbee-setting> + <bitlbee-setting name="simulate_netsplit" type="boolean" scope="global"> + <default>true</default> + + <description> + <para> + Some IRC clients parse quit messages sent by the IRC server to see if someone really left or just disappeared because of a netsplit. By default, BitlBee tries to simulate netsplit-like quit messages to keep the control channel window clean. If you don't like this (or if your IRC client doesn't support this) you can disable this setting. + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="ssl" type="boolean" scope="account"> <default>false</default> diff --git a/irc.c b/irc.c index 254bdbdc..e1928497 100644 --- a/irc.c +++ b/irc.c @@ -142,6 +142,7 @@ irc_t *irc_new( int fd ) set_add( &irc->set, "private", "true", set_eval_bool, irc ); set_add( &irc->set, "query_order", "lifo", NULL, irc ); set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); + set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); set_add( &irc->set, "strip_html", "true", NULL, irc ); set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); @@ -909,7 +910,7 @@ void irc_kill( irc_t *irc, user_t *u ) char *nick, *s; char reason[128]; - if( u->ic && u->ic->flags & OPT_LOGGING_OUT ) + if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) ) { if( u->ic->acc->server ) g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 9ebd048e..d7b26b74 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -585,8 +585,20 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, ( ( ( u->online != oo ) && !u->away ) || /* Voice joining people */ ( ( u->online == oo ) && ( oa == !u->away ) ) ) ) /* (De)voice people changing state */ { - irc_write( ic->irc, ":%s MODE %s %cv %s", ic->irc->myhost, - ic->irc->channel, u->away?'-':'+', u->nick ); + char *from; + + if( set_getbool( &ic->irc->set, "simulate_netsplit" ) ) + { + from = g_strdup( ic->irc->myhost ); + } + else + { + from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick, + ic->irc->myhost ); + } + irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, + u->away?'-':'+', u->nick ); + g_free( from ); } } -- cgit v1.2.3 From 285b55d3b38d6e1c8b3fc4a64945f2bb9ace07f4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 10 Oct 2007 23:45:19 +0100 Subject: configure script now allows one to override CFLAGS. (Bug #171) --- configure | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/configure b/configure index ca7e0268..ffa0e2f2 100755 --- a/configure +++ b/configure @@ -139,13 +139,14 @@ if [ "$ipv6" = "1" ]; then fi if [ "$debug" = "1" ]; then - echo 'CFLAGS=-g' >> Makefile.settings + [ -z "$CFLAGS" ] && CFLAGS=-g echo 'DEBUG=1' >> Makefile.settings echo '#define DEBUG' >> config.h else - echo 'CFLAGS=-O3' >> Makefile.settings + [ -z "$CFLAGS" ] && CFLAGS=-O3 fi +echo CFLAGS=$CFLAGS >> Makefile.settings echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings -- cgit v1.2.3 From d444c09e6c7ac6fc3c1686af0e63c09805d8cd00 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 12 Oct 2007 01:06:50 +0100 Subject: Added word_wrap() function to misc.c and using it at the right places so that long messages in groupchats also get wrapped properly (instead of truncated). --- lib/misc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ lib/misc.h | 2 ++ protocols/nogaim.c | 46 ++++++++++++------------------------------- tests/check_util.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 33 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 9061af39..5e385d4a 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -544,3 +544,51 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) return reply; } + +/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */ +char *word_wrap( char *msg, int line_len ) +{ + GString *ret = g_string_sized_new( strlen( msg ) + 16 ); + + while( strlen( msg ) > line_len ) + { + int i; + + /* First try to find out if there's a newline already. Don't + want to add more splits than necessary. */ + for( i = line_len; i > 0 && msg[i] != '\n'; i -- ); + if( msg[i] == '\n' ) + { + g_string_append_len( ret, msg, i + 1 ); + msg += i + 1; + continue; + } + + for( i = line_len; i > 0; i -- ) + { + if( msg[i] == '-' ) + { + g_string_append_len( ret, msg, i + 1 ); + g_string_append_c( ret, '\n' ); + msg += i + 1; + break; + } + else if( msg[i] == ' ' ) + { + g_string_append_len( ret, msg, i ); + g_string_append_c( ret, '\n' ); + msg += i + 1; + break; + } + } + if( i == 0 ) + { + g_string_append_len( ret, msg, line_len ); + g_string_append_c( ret, '\n' ); + msg += line_len; + } + } + g_string_append( ret, msg ); + + return g_string_free( ret, FALSE ); +} diff --git a/lib/misc.h b/lib/misc.h index 55dabfc4..1d76f7f2 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -63,4 +63,6 @@ G_MODULE_EXPORT int bool2int( char *value ); G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT char *word_wrap( char *msg, int line_len ); + #endif diff --git a/protocols/nogaim.c b/protocols/nogaim.c index d7b26b74..d90870ad 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -605,6 +605,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ) { irc_t *irc = ic->irc; + char *wrapped; user_t *u; u = user_findhandle( ic, handle ); @@ -647,37 +648,9 @@ void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_ ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); - while( strlen( msg ) > 425 ) - { - char tmp, *nl; - - tmp = msg[425]; - msg[425] = 0; - - /* If there's a newline/space in this string, split up there, - looks a bit prettier. */ - if( ( nl = strrchr( msg, '\n' ) ) || ( nl = strrchr( msg, ' ' ) ) ) - { - msg[425] = tmp; - tmp = *nl; - *nl = 0; - } - - irc_msgfrom( irc, u->nick, msg ); - - /* Move on. */ - if( nl ) - { - *nl = tmp; - msg = nl + 1; - } - else - { - msg[425] = tmp; - msg += 425; - } - } - irc_msgfrom( irc, u->nick, msg ); + wrapped = word_wrap( msg, 425 ); + irc_msgfrom( irc, u->nick, wrapped ); + g_free( wrapped ); } void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ) @@ -736,6 +709,7 @@ void imcb_chat_removed( struct groupchat *c ) void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ) { struct im_connection *ic = c->ic; + char *wrapped; user_t *u; /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ @@ -748,10 +722,16 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) strip_html( msg ); + wrapped = word_wrap( msg, 425 ); if( c && u ) - irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", msg ); + { + irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped ); + } else - imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); + { + imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, wrapped ); + } + g_free( wrapped ); } struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) diff --git a/tests/check_util.c b/tests/check_util.c index 284ddba3..b00d645b 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -103,6 +103,63 @@ START_TEST(test_set_url_username_pwd) fail_unless (url.port == 1080); END_TEST +struct +{ + char *orig; + int line_len; + char *wrapped; +} word_wrap_tests[] = { + { + "Line-wrapping is not as easy as it seems?", + 16, + "Line-wrapping is\nnot as easy as\nit seems?" + }, + { + "Line-wrapping is not as easy as it seems?", + 8, + "Line-\nwrapping\nis not\nas easy\nas it\nseems?" + }, + { + "Line-wrapping is\nnot as easy as it seems?", + 8, + "Line-\nwrapping\nis\nnot as\neasy as\nit\nseems?" + }, + { + "a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa", + 5, + "a aa\naaa\naaaa\naaaaa\naaaaa\na\naaaaa\naa\naaaaa\naaa", + }, + { + "aaaaaaaa aaaaaaa aaaaaa aaaaa aaaa aaa aa a", + 5, + "aaaaa\naaa\naaaaa\naa\naaaaa\na\naaaaa\naaaa\naaa\naa a", + }, + { + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + 5, + "aaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\na", + }, + { + NULL + } +}; + +START_TEST(test_word_wrap) + int i; + + for( i = 0; word_wrap_tests[i].orig && *word_wrap_tests[i].orig; i ++ ) + { + char *wrapped = word_wrap( word_wrap_tests[i].orig, word_wrap_tests[i].line_len ); + + fail_unless( strcmp( word_wrap_tests[i].wrapped, wrapped ) == 0, + "%s (line_len = %d) should wrap to `%s', not to `%s'", + word_wrap_tests[i].orig, word_wrap_tests[i].line_len, + word_wrap_tests[i].wrapped, wrapped ); + + g_free( wrapped ); + } +END_TEST + Suite *util_suite (void) { Suite *s = suite_create("Util"); @@ -115,5 +172,6 @@ Suite *util_suite (void) tcase_add_test (tc_core, test_set_url_port); tcase_add_test (tc_core, test_set_url_username); tcase_add_test (tc_core, test_set_url_username_pwd); + tcase_add_test (tc_core, test_word_wrap); return s; } -- cgit v1.2.3 From c78c03298b5fd99999dcafeb1e1c377a62d03019 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Fri, 12 Oct 2007 14:11:32 +0200 Subject: Add GCC attributes. --- conf.h | 2 +- crypting.h | 6 +++--- help.h | 2 +- storage.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/conf.h b/conf.h index e852dbef..f4c6a397 100644 --- a/conf.h +++ b/conf.h @@ -50,7 +50,7 @@ typedef struct conf int ping_timeout; } conf_t; -conf_t *conf_load( int argc, char *argv[] ); +G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] ); void conf_loaddefaults( irc_t *irc ); #endif diff --git a/crypting.h b/crypting.h index fbaa7dcc..e13b0433 100644 --- a/crypting.h +++ b/crypting.h @@ -24,6 +24,6 @@ */ int checkpass (const char *password, const char *md5sum); -char *hashpass (const char *password); -char *obfucrypt (char *line, const char *password); -char *deobfucrypt (char *line, const char *password); +G_GNUC_MALLOC char *hashpass (const char *password); +G_GNUC_MALLOC char *obfucrypt (char *line, const char *password); +G_GNUC_MALLOC char *deobfucrypt (char *line, const char *password); diff --git a/help.h b/help.h index 07182e9c..32aba723 100644 --- a/help.h +++ b/help.h @@ -42,7 +42,7 @@ typedef struct help struct help *next; } help_t; -help_t *help_init( help_t **help, const char *helpfile ); +G_GNUC_MALLOC help_t *help_init( help_t **help, const char *helpfile ); char *help_get( help_t **help, char *string ); #endif diff --git a/storage.h b/storage.h index 3c641088..d114dec4 100644 --- a/storage.h +++ b/storage.h @@ -61,6 +61,6 @@ storage_status_t storage_remove (const char *nick, const char *password); storage_status_t storage_rename (const char *onick, const char *nnick, const char *password); void register_storage_backend(storage_t *); -GList *storage_init(const char *primary, char **migrate); +G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); #endif /* __STORAGE_H__ */ -- cgit v1.2.3 From f618a4a446d9de22298f45edba53eadf87129efc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Fri, 12 Oct 2007 14:11:57 +0200 Subject: Fix GCC warning. --- lib/proxy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/proxy.c b/lib/proxy.c index 7911b06f..dff5d0a4 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -210,7 +210,7 @@ static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond return FALSE; } - if (proxyuser && *proxyuser) { + if (strlen(proxyuser) > 0) { char *t1, *t2; t1 = g_strdup_printf("%s:%s", proxyuser, proxypass); t2 = tobase64(t1); @@ -538,7 +538,7 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat phb->func = func; phb->data = data; - if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1)) + if ((proxytype == PROXY_NONE) || strlen(proxyhost) > 0 || !proxyport || (proxyport == -1)) return proxy_connect_none(host, port, phb); else if (proxytype == PROXY_HTTP) return proxy_connect_http(host, port, phb); -- cgit v1.2.3 From 764b163d6bc0587498c14de8023d70aea076e646 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Fri, 12 Oct 2007 14:18:16 +0200 Subject: Fix another warning. --- protocols/nogaim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index d90870ad..d0395fa9 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -35,7 +35,7 @@ #include "nogaim.h" #include <ctype.h> -static int remove_chat_buddy_silent( struct groupchat *b, char *handle ); +static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ); GSList *connections; @@ -555,7 +555,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */ for( c = ic->conversations; c; c = c->next ) - remove_chat_buddy_silent( c, (char*) handle ); + remove_chat_buddy_silent( c, handle ); } if( flags & OPT_AWAY ) @@ -820,7 +820,7 @@ void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) irc_part( b->ic->irc, u, b->channel ); } -static int remove_chat_buddy_silent( struct groupchat *b, char *handle ) +static int remove_chat_buddy_silent( struct groupchat *b, const char *handle ) { GList *i; -- cgit v1.2.3 From 3933853e12f9f4271c33e68425c3cc4d0aa53728 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 14 Oct 2007 23:57:42 +0100 Subject: Fixed a typo in "help join_chat". --- doc/user-guide/commands.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index cf40782f..b7af2027 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -822,7 +822,7 @@ <bitlbee-command name="join_chat"> <short-description>Join a named groupchat/conference room</short-description> - <syntax>import_buddies <connection> <room name> [<channel name>] [<room nickname>] [<password>]</syntax> + <syntax>join_chat <connection> <room name> [<channel name>] [<room nickname>] [<password>]</syntax> <description> <para> -- cgit v1.2.3 From e9b755e3726fa41ac2d4ed1c3a6192d1af68edbc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Thu, 18 Oct 2007 18:44:25 +0200 Subject: Use standard functions for dealing with both IPv6 and IPv4. --- bitlbee.c | 95 ++++++++++++++++++++++++-------------------------------------- conf.c | 23 ++++----------- conf.h | 2 +- configure | 7 ----- irc.c | 66 ++++++++++++------------------------------- lib/misc.c | 40 -------------------------- lib/misc.h | 3 -- 7 files changed, 61 insertions(+), 175 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 6a3625ee..3065aa9d 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -37,72 +37,51 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition int bitlbee_daemon_init() { -#ifdef IPV6 - int use_ipv6 = 1; - struct sockaddr_in6 listen_addr6; -#endif - struct sockaddr_in listen_addr; + struct addrinfo *res, hints, *addrinfo_bind; int i; FILE *fp; log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG ); log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG ); -#ifdef IPV6 - if( ( global.listen_socket = socket( AF_INET6, SOCK_STREAM, 0 ) ) == -1 ) - { - use_ipv6 = 0; -#endif - global.listen_socket = socket( AF_INET, SOCK_STREAM, 0 ); -#ifdef IPV6 - } -#endif - if( global.listen_socket == -1 ) - { - log_error( "socket" ); - return( -1 ); - } - - /* TIME_WAIT (?) sucks.. */ - i = 1; - setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); - -#ifdef IPV6 - memset( &listen_addr6, 0, sizeof( listen_addr6 ) ); - listen_addr6.sin6_family = AF_INET6; - listen_addr6.sin6_port = htons( global.conf->port ); - if( ( i = inet_pton( AF_INET6, ipv6_wrap( global.conf->iface ), &listen_addr6.sin6_addr ) ) != 1 ) - { - /* Forget about IPv6 in this function. */ - use_ipv6 = 0; -#endif - memset( &listen_addr, 0, sizeof( listen_addr ) ); - listen_addr.sin_family = AF_INET; - listen_addr.sin_port = htons( global.conf->port ); - if( strcmp( global.conf->iface, "::" ) == 0 ) - i = inet_pton( AF_INET, "0.0.0.0", &listen_addr.sin_addr ); - else - i = inet_pton( AF_INET, global.conf->iface, &listen_addr.sin_addr ); -#ifdef IPV6 - } -#endif - - if( i != 1 ) - { - log_message( LOGLVL_ERROR, "Couldn't parse address `%s'", global.conf->iface ); - return( -1 ); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; + + i = getaddrinfo(global.conf->iface, global.conf->port, &hints, + &addrinfo_bind); + if (i) { + log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s", + global.conf->iface, gai_strerror(i) ); + return -1; } - -#ifdef IPV6 - if( !use_ipv6 || ( i = bind( global.listen_socket, (struct sockaddr *) &listen_addr6, sizeof( listen_addr6 ) ) ) == -1 ) -#endif - i = bind( global.listen_socket, (struct sockaddr *) &listen_addr, sizeof( listen_addr ) ); - if( i == -1 ) - { - log_error( "bind" ); - return( -1 ); + + global.listen_socket = -1; + + for (res = addrinfo_bind; res; res = res->ai_next) { + global.listen_socket = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (global.listen_socket < 0) + continue; + + /* TIME_WAIT (?) sucks.. */ + i = 1; + setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, + sizeof( i ) ); + + i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen); + if( i == -1 ) + { + log_error( "bind" ); + return( -1 ); + } + + break; } - + + freeaddrinfo(addrinfo_bind); + i = listen( global.listen_socket, 10 ); if( i == -1 ) { diff --git a/conf.c b/conf.c index 09fd08e1..551e8f5e 100644 --- a/conf.c +++ b/conf.c @@ -46,12 +46,8 @@ conf_t *conf_load( int argc, char *argv[] ) conf = g_new0( conf_t, 1 ); -#ifdef IPV6 - conf->iface = "::"; -#else - conf->iface = "0.0.0.0"; -#endif - conf->port = 6667; + conf->iface = NULL; + conf->port = "6667"; conf->nofork = 0; conf->verbose = 0; conf->primary_storage = "xml"; @@ -88,12 +84,8 @@ conf_t *conf_load( int argc, char *argv[] ) } else if( opt == 'p' ) { - if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) ) - { - fprintf( stderr, "Invalid port number: %s\n", optarg ); - return( NULL ); - } - conf->port = i; + g_free( conf->port ); + conf->port = g_strdup( optarg ); } else if( opt == 'P' ) { @@ -203,12 +195,7 @@ static int conf_loadini( conf_t *conf, char *file ) } else if( g_strcasecmp( ini->key, "daemonport" ) == 0 ) { - if( ( sscanf( ini->value, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) ) - { - fprintf( stderr, "Invalid port number: %s\n", ini->value ); - return( 0 ); - } - conf->port = i; + conf->port = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "authmode" ) == 0 ) { diff --git a/conf.h b/conf.h index f4c6a397..5138ce11 100644 --- a/conf.h +++ b/conf.h @@ -32,7 +32,7 @@ typedef enum authmode { AUTHMODE_OPEN, AUTHMODE_CLOSED, AUTHMODE_REGISTERED } au typedef struct conf { char *iface; - signed int port; + char *port; int nofork; int verbose; runmode_t runmode; diff --git a/configure b/configure index ffa0e2f2..bc9960a9 100755 --- a/configure +++ b/configure @@ -29,7 +29,6 @@ debug=0 strip=1 gcov=0 plugins=1 -ipv6=1 events=glib ldap=0 @@ -71,8 +70,6 @@ Option Description Default --gcov=0/1 Disable/enable test coverage reporting $gcov --plugins=0/1 Disable/enable plugins support $plugins ---ipv6=0/1 IPv6 socket support $ipv6 - --events=... Event handler (glib, libevent) $events --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl @@ -134,10 +131,6 @@ cat<<EOF>config.h #define CPU "$cpu" EOF -if [ "$ipv6" = "1" ]; then - echo '#define IPV6' >> config.h -fi - if [ "$debug" = "1" ]; then [ -z "$CFLAGS" ] && CFLAGS=-g echo 'DEBUG=1' >> Makefile.settings diff --git a/irc.c b/irc.c index e1928497..0f8f1b82 100644 --- a/irc.c +++ b/irc.c @@ -44,14 +44,8 @@ static char *passchange( set_t *set, char *value ) irc_t *irc_new( int fd ) { irc_t *irc; - struct hostent *peer; - unsigned int i; - char buf[128]; -#ifdef IPV6 - struct sockaddr_in6 sock6[1]; - unsigned int i6; -#endif - struct sockaddr_in sock[1]; + struct sockaddr_storage sock; + socklen_t socklen = sizeof(sock); irc = g_new0( irc_t, 1 ); @@ -70,54 +64,30 @@ irc_t *irc_new( int fd ) irc->mynick = g_strdup( ROOT_NICK ); irc->channel = g_strdup( ROOT_CHAN ); - i = sizeof( *sock ); -#ifdef IPV6 - i6 = sizeof( *sock6 ); -#endif - if( global.conf->hostname ) irc->myhost = g_strdup( global.conf->hostname ); -#ifdef IPV6 - else if( getsockname( irc->fd, (struct sockaddr*) sock6, &i6 ) == 0 && sock6->sin6_family == AF_INET6 ) - { - if( ( peer = gethostbyaddr( (char*) &sock6->sin6_addr, sizeof( sock6->sin6_addr ), AF_INET6 ) ) ) - irc->myhost = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INET6, &sock6->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) - irc->myhost = g_strdup( ipv6_unwrap( buf ) ); - } -#endif - else if( getsockname( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INET ) + else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0) { - if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INET ) ) ) - irc->myhost = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INET, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) - irc->myhost = g_strdup( buf ); + irc->myhost = g_new0(char, NI_MAXHOST); + + if (getnameinfo((struct sockaddr *)&sock, socklen, irc->myhost, + NI_MAXHOST, NULL, -1, 0)) { + /* Rare, but possible. */ + strncpy(irc->myhost, "localhost.", NI_MAXHOST); + } } - i = sizeof( *sock ); -#ifdef IPV6 - i6 = sizeof( *sock6 ); - if( getpeername( irc->fd, (struct sockaddr*) sock6, &i6 ) == 0 && sock6->sin6_family == AF_INET6 ) + if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0) { - if( ( peer = gethostbyaddr( (char*) &sock6->sin6_addr, sizeof( sock6->sin6_addr ), AF_INET6 ) ) ) - irc->host = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INET6, &sock6->sin6_addr, buf, sizeof( buf ) - 1 ) != NULL ) - irc->host = g_strdup( ipv6_unwrap( buf ) ); - } - else -#endif - if( getpeername( irc->fd, (struct sockaddr*) sock, &i ) == 0 && sock->sin_family == AF_INET ) - { - if( ( peer = gethostbyaddr( (char*) &sock->sin_addr, sizeof( sock->sin_addr ), AF_INET ) ) ) - irc->host = g_strdup( peer->h_name ); - else if( inet_ntop( AF_INET, &sock->sin_addr, buf, sizeof( buf ) - 1 ) != NULL ) - irc->host = g_strdup( buf ); + irc->host = g_new0(char, NI_MAXHOST); + + if (getnameinfo((struct sockaddr *)&sock, socklen, irc->host, + NI_MAXHOST, NULL, -1, 0)) { + /* Rare, but possible. */ + strncpy(irc->myhost, "localhost.", NI_MAXHOST); + } } - /* Rare, but possible. */ - if( !irc->host ) irc->host = g_strdup( "localhost." ); - if( !irc->myhost ) irc->myhost = g_strdup( "localhost." ); - if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); diff --git a/lib/misc.c b/lib/misc.c index 5e385d4a..ceba9d95 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -321,46 +321,6 @@ char *strip_newlines( char *source ) return source; } -#ifdef IPV6 -/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */ -char *ipv6_wrap( char *src ) -{ - static char dst[64]; - int i; - - for( i = 0; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) - break; - - /* Hmm, it's not even an IP... */ - if( src[i] ) - return src; - - g_snprintf( dst, sizeof( dst ), "::ffff:%s", src ); - - return dst; -} - -/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */ -char *ipv6_unwrap( char *src ) -{ - int i; - - if( g_strncasecmp( src, "::ffff:", 7 ) != 0 ) - return src; - - for( i = 7; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) - break; - - /* Hmm, it's not even an IP... */ - if( src[i] ) - return src; - - return ( src + 7 ); -} -#endif - /* Convert from one charset to another. from_cs, to_cs: Source and destination charsets diff --git a/lib/misc.h b/lib/misc.h index 1d76f7f2..e32b5f12 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -51,9 +51,6 @@ G_MODULE_EXPORT char *escape_html( const char *html ); G_MODULE_EXPORT void http_decode( char *s ); G_MODULE_EXPORT void http_encode( char *s ); -G_MODULE_EXPORT char *ipv6_wrap( char *src ); -G_MODULE_EXPORT char *ipv6_unwrap( char *src ); - G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ); G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); -- cgit v1.2.3 From 7435ccf486eee2f60d6a8b2ab0029b8f4ce17ab7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Thu, 18 Oct 2007 21:03:02 +0200 Subject: Fix indentation. --- bitlbee.c | 20 ++++++++++---------- irc.c | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 3065aa9d..625ea214 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -44,14 +44,14 @@ int bitlbee_daemon_init() log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG ); log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG ); - memset(&hints, 0, sizeof(hints)); + memset( &hints, 0, sizeof( hints ) ); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; - i = getaddrinfo(global.conf->iface, global.conf->port, &hints, - &addrinfo_bind); - if (i) { + i = getaddrinfo( global.conf->iface, global.conf->port, &hints, + &addrinfo_bind ); + if ( i ) { log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s", global.conf->iface, gai_strerror(i) ); return -1; @@ -59,10 +59,10 @@ int bitlbee_daemon_init() global.listen_socket = -1; - for (res = addrinfo_bind; res; res = res->ai_next) { - global.listen_socket = socket(res->ai_family, res->ai_socktype, - res->ai_protocol); - if (global.listen_socket < 0) + for ( res = addrinfo_bind; res; res = res->ai_next ) { + global.listen_socket = socket( res->ai_family, res->ai_socktype, + res->ai_protocol ); + if ( global.listen_socket < 0 ) continue; /* TIME_WAIT (?) sucks.. */ @@ -70,7 +70,7 @@ int bitlbee_daemon_init() setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); - i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen); + i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen ); if( i == -1 ) { log_error( "bind" ); @@ -80,7 +80,7 @@ int bitlbee_daemon_init() break; } - freeaddrinfo(addrinfo_bind); + freeaddrinfo( addrinfo_bind ); i = listen( global.listen_socket, 10 ); if( i == -1 ) diff --git a/irc.c b/irc.c index 0f8f1b82..1a1f511e 100644 --- a/irc.c +++ b/irc.c @@ -45,7 +45,7 @@ irc_t *irc_new( int fd ) { irc_t *irc; struct sockaddr_storage sock; - socklen_t socklen = sizeof(sock); + socklen_t socklen = sizeof( sock ); irc = g_new0( irc_t, 1 ); @@ -66,25 +66,25 @@ irc_t *irc_new( int fd ) if( global.conf->hostname ) irc->myhost = g_strdup( global.conf->hostname ); - else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0) + else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) { - irc->myhost = g_new0(char, NI_MAXHOST); + irc->myhost = g_new0( char, NI_MAXHOST ); - if (getnameinfo((struct sockaddr *)&sock, socklen, irc->myhost, - NI_MAXHOST, NULL, -1, 0)) { + if (getnameinfo( (struct sockaddr *) &sock, socklen, irc->myhost, + NI_MAXHOST, NULL, -1, 0) ) { /* Rare, but possible. */ - strncpy(irc->myhost, "localhost.", NI_MAXHOST); + strncpy( irc->myhost, "localhost.", NI_MAXHOST ); } } - if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0) + if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) { - irc->host = g_new0(char, NI_MAXHOST); + irc->host = g_new0( char, NI_MAXHOST ); - if (getnameinfo((struct sockaddr *)&sock, socklen, irc->host, - NI_MAXHOST, NULL, -1, 0)) { + if ( getnameinfo( (struct sockaddr *)&sock, socklen, irc->host, + NI_MAXHOST, NULL, -1, 0 ) ) { /* Rare, but possible. */ - strncpy(irc->myhost, "localhost.", NI_MAXHOST); + strncpy( irc->myhost, "localhost.", NI_MAXHOST ); } } -- cgit v1.2.3 From 7448e1bdb7ea75ed8a845816bd2f6bc76ce43785 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 22 Oct 2007 23:39:46 +0100 Subject: debian/ specific: Changed "rm help.txt at upgrade" hack to not remove the file but rename it and rename it back in postinst in case we were doing a dpkg-reconfigure instead of an upgrade. --- debian/postinst | 9 +++++++++ debian/prerm | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/debian/postinst b/debian/postinst index 6c99c40d..37608e47 100755 --- a/debian/postinst +++ b/debian/postinst @@ -45,6 +45,15 @@ EOF ## Bye-bye DebConf, we don't need you anymore. db_stop +## Restore the helpfile in case we weren't upgrading but just reconfiguring: +if [ -e /usr/share/bitlbee/help.upgrading ]; then + if [ -e /usr/share/bitlbee/help.txt ]; then + rm -f /usr/share/bitlbee/help.upgrading + else + mv /usr/share/bitlbee/help.upgrading /usr/share/bitlbee/help.txt + fi +fi + if [ -n "$2" -a "$BITLBEE_UPGRADE_DONT_RESTART" != "1" ]; then /etc/init.d/bitlbee restart fi diff --git a/debian/prerm b/debian/prerm index c02b13f4..5272e273 100755 --- a/debian/prerm +++ b/debian/prerm @@ -1,8 +1,13 @@ #!/bin/sh -e if [ "$1" = "upgrade" ]; then - ## To prevent the help function from breaking in currently running BitlBee processes - rm -f /usr/share/bitlbee/help.txt + ## To prevent the help function from breaking in currently running + ## BitlBee processes. Have to do it like this because dpkg-reconfigure + ## looks a lot like an upgrade and we don't want to lose help.txt... + if [ -e /usr/share/bitlbee/help.txt ]; then + rm -f /usr/share/bitlbee/help.upgrading + mv /usr/share/bitlbee/help.txt /usr/share/bitlbee/help.upgrading + fi else /etc/init.d/bitlbee stop || exit 0 fi -- cgit v1.2.3 From 5e2615a2d8a5ae64161727f8a32f6f0949f3fee4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 30 Oct 2007 23:44:39 +0000 Subject: s/FAQ's/FAQs/ --- irc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/irc.c b/irc.c index e1928497..1a936d47 100644 --- a/irc.c +++ b/irc.c @@ -743,7 +743,7 @@ void irc_login( irc_t *irc ) u->online = 1; irc_spawn( irc, u ); - irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQ's are answered there." ); + irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQs are answered there." ); if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); -- cgit v1.2.3 From be68d99a58721768033c83d2f0a8f26e1af9bd73 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 10 Nov 2007 09:25:50 +0000 Subject: Handing of multipart messages in OSCAR (usually from mobiles), this fixes bug #88, at last. --- protocols/oscar/oscar.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 426dd4a2..2b8b4853 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1065,8 +1065,17 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } else { g_snprintf(tmp, BUF_LONG, "%s", args->msg); } - } else + } else if (args->mpmsg.numparts == 0) { g_snprintf(tmp, BUF_LONG, "%s", args->msg); + } else { + int i; + + *tmp = 0; + for (i = 0; i < args->mpmsg.numparts; i ++) { + g_strlcat(tmp, (char*) args->mpmsg.parts[i].data, BUF_LONG); + g_strlcat(tmp, "\n", BUF_LONG); + } + } strip_linefeed(tmp); imcb_buddy_msg(ic, userinfo->sn, tmp, flags, 0); -- cgit v1.2.3 From 1bf1ae6f25ff56894d67999791802aa864eaa02b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 14 Nov 2007 23:09:22 +0000 Subject: Removed some debugging stuff that shouldn't have been here for a long time already. --- protocols/jabber/io.c | 9 --------- protocols/jabber/presence.c | 5 ----- protocols/jabber/xmltree.c | 2 ++ 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 67deb3a6..925463a4 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -475,14 +475,6 @@ static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) return XT_ABORT; } -static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data ) -{ - printf( "Received unknown packet:\n" ); - xt_print( node ); - - return XT_HANDLED; -} - static const struct xt_handler_entry jabber_handlers[] = { { "stream:stream", "<root>", jabber_end_of_stream }, { "message", "stream:stream", jabber_pkt_message }, @@ -494,7 +486,6 @@ static const struct xt_handler_entry jabber_handlers[] = { { "challenge", "stream:stream", sasl_pkt_challenge }, { "success", "stream:stream", sasl_pkt_result }, { "failure", "stream:stream", sasl_pkt_result }, - { NULL, "stream:stream", jabber_pkt_misc }, { NULL, NULL, NULL } }; diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index ef92740a..49c66a3d 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -127,11 +127,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) { /* What to do with it? */ } - else - { - printf( "Received PRES from %s:\n", from ); - xt_print( node ); - } return XT_HANDLED; } diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c index 7a165a1e..7e74cccb 100644 --- a/protocols/jabber/xmltree.c +++ b/protocols/jabber/xmltree.c @@ -304,6 +304,7 @@ char *xt_to_string( struct xt_node *node ) return real; } +#ifdef DEBUG void xt_print( struct xt_node *node ) { int i; @@ -354,6 +355,7 @@ void xt_print( struct xt_node *node ) /* Non-empty tag is now finished. */ printf( "</%s>\n", node->name ); } +#endif struct xt_node *xt_dup( struct xt_node *node ) { -- cgit v1.2.3 From a6df0b5d21370549328c7929a008abb68f2ed4db Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 14 Nov 2007 23:29:43 +0000 Subject: Added "xmlconsole" setting so it can be enabled at login time already. --- doc/user-guide/commands.xml | 13 +++++++++++++ protocols/jabber/jabber.c | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index cf40782f..8f97558f 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -680,6 +680,19 @@ </description> </bitlbee-setting> + <bitlbee-setting name="xmlconsole" type="boolean" scope="account"> + <default>false</default> + + <description> + <para> + The Jabber module allows you to add a buddy <emphasis>xmlconsole</emphasis> to your contact list, which will then show you the raw XMPP stream between you and the server. You can also send XMPP packets to this buddy, which will then be sent to the server. + </para> + <para> + If you want to enable this XML console permanently (and at login time already), you can set this setting. + </para> + </description> + </bitlbee-setting> + <bitlbee-command name="rename"> <short-description>Rename (renick) a buddy</short-description> <syntax>rename <oldnick> <newnick></syntax> diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 9176cd68..ab26efc9 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -54,6 +54,9 @@ static void jabber_init( account_t *acc ) s = set_add( &acc->set, "tls", "try", set_eval_tls, acc ); s->flags |= ACC_SET_OFFLINE_ONLY; + + s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc ); + s->flags |= ACC_SET_OFFLINE_ONLY; } static void jabber_login( account_t *acc ) @@ -188,6 +191,14 @@ static void jabber_login( account_t *acc ) imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); } + + if( set_getbool( &acc->set, "xmlconsole" ) ) + { + jd->flags |= JFLAG_XMLCONSOLE; + /* Shouldn't really do this at this stage already, maybe. But + I think this shouldn't break anything. */ + imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); + } } static void jabber_logout( struct im_connection *ic ) -- cgit v1.2.3 From cd428e473fe4428041722fd373badef890edebd9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 17 Nov 2007 12:20:51 +0000 Subject: Added (account) set -del. --- doc/user-guide/commands.xml | 10 +++++++--- root_commands.c | 44 +++++++++++++++++++++++++++++++------------- set.c | 9 +++++++++ set.h | 1 + 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index b7af2027..05b9abea 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -133,6 +133,7 @@ <syntax>account set <account id></syntax> <syntax>account set <account id>/<setting></syntax> <syntax>account set <account id>/<setting> <value></syntax> + <syntax>account set -del <account id>/<setting></syntax> <description> <para> @@ -140,7 +141,7 @@ </para> <para> - For more infomation about a setting, see <emphasis>help set <setting></emphasis>. + For more infomation about a setting, see <emphasis>help set <setting></emphasis>. For details about the syntax of this command, see <emphasis>help set</emphasis>. </para> <para> @@ -245,12 +246,15 @@ <bitlbee-command name="set"> <short-description>Miscellaneous settings</short-description> - <syntax>set [<variable> [<value>]]</syntax> + <syntax>set</syntax> + <syntax>set <variable></syntax> + <syntax>set <variable> <value></syntax> + <syntax>set -del <variable></syntax> <description> <para> - Without any arguments, this command lists all the set variables. You can also specify a single argument, a variable name, to get that variable's value. To change this value, specify the new value as the second argument. + Without any arguments, this command lists all the set variables. You can also specify a single argument, a variable name, to get that variable's value. To change this value, specify the new value as the second argument. With <emphasis>-del</emphasis> you can reset a setting to its default value. </para> <para> diff --git a/root_commands.c b/root_commands.c index baaf3354..59852de6 100644 --- a/root_commands.c +++ b/root_commands.c @@ -367,15 +367,18 @@ static void cmd_account( irc_t *irc, char **cmd ) return; } - acc_handle = g_strdup( cmd[2] ); + if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 ) + acc_handle = g_strdup( cmd[3] ); + else + acc_handle = g_strdup( cmd[2] ); + if( ( tmp = strchr( acc_handle, '/' ) ) ) { *tmp = 0; set_name = tmp + 1; } - a = account_get( irc, acc_handle ); - if( a == NULL ) + if( ( a = account_get( irc, acc_handle ) ) == NULL ) { g_free( acc_handle ); irc_usermsg( irc, "Invalid account" ); @@ -399,10 +402,12 @@ static void cmd_account( irc_t *irc, char **cmd ) return; } - set_setstr( &a->set, set_name, cmd[3] ); - if( ( strcmp( cmd[3], "=" ) ) == 0 && cmd[4] ) irc_usermsg( irc, "Warning: Correct syntax: \002account set <variable> <value>\002 (without =)" ); + else if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 ) + set_reset( &a->set, set_name ); + else + set_setstr( &a->set, set_name, cmd[3] ); } if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ { @@ -418,7 +423,7 @@ static void cmd_account( irc_t *irc, char **cmd ) while( s ) { if( s->value || s->def ) - irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); + irc_usermsg( irc, "%s = `%s'", s->key, s->value ? s->value : s->def ); else irc_usermsg( irc, "%s is empty", s->key ); s = s->next; @@ -739,20 +744,33 @@ static void cmd_yesno( irc_t *irc, char **cmd ) static void cmd_set( irc_t *irc, char **cmd ) { + char *set_name; + if( cmd[1] && cmd[2] ) { - set_setstr( &irc->set, cmd[1], cmd[2] ); - if( ( strcmp( cmd[2], "=" ) ) == 0 && cmd[3] ) + { irc_usermsg( irc, "Warning: Correct syntax: \002set <variable> <value>\002 (without =)" ); + return; + } + else if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 ) + { + set_reset( &irc->set, cmd[2] ); + set_name = cmd[2]; + } + else + { + set_setstr( &irc->set, cmd[1], cmd[2] ); + set_name = cmd[1]; + } } if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ { - char *s = set_getstr( &irc->set, cmd[1] ); - if( s ) - irc_usermsg( irc, "%s = `%s'", cmd[1], s ); + char *s = set_getstr( &irc->set, set_name ); + if( s ) + irc_usermsg( irc, "%s = `%s'", set_name, s ); else - irc_usermsg( irc, "%s is empty", cmd[1] ); + irc_usermsg( irc, "%s is empty", set_name ); } else { @@ -760,7 +778,7 @@ static void cmd_set( irc_t *irc, char **cmd ) while( s ) { if( s->value || s->def ) - irc_usermsg( irc, "%s = `%s'", s->key, s->value?s->value:s->def ); + irc_usermsg( irc, "%s = `%s'", s->key, s->value ? s->value : s->def ); else irc_usermsg( irc, "%s is empty", s->key ); s = s->next; diff --git a/set.c b/set.c index 184c3243..6f09843b 100644 --- a/set.c +++ b/set.c @@ -167,6 +167,15 @@ void set_del( set_t **head, char *key ) } } +void set_reset( set_t **head, char *key ) +{ + set_t *s; + + s = set_find( head, key ); + if( s ) + set_setstr( head, key, s->def ); +} + char *set_eval_int( set_t *set, char *value ) { char *s = value; diff --git a/set.h b/set.h index b6fffed9..7dcbb869 100644 --- a/set.h +++ b/set.h @@ -87,6 +87,7 @@ G_MODULE_EXPORT int set_getbool( set_t **head, char *key ); int set_setstr( set_t **head, char *key, char *value ); int set_setint( set_t **head, char *key, int value ); void set_del( set_t **head, char *key ); +void set_reset( set_t **head, char *key ); /* Two very useful generic evaluators. */ char *set_eval_int( set_t *set, char *value ); -- cgit v1.2.3 From 50e1776cb0c76b3328d458dd8a1bfb379b6b0e43 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 19 Nov 2007 22:23:58 +0000 Subject: Merging /TOPIC code from Miklos Vajna. Untested, because I still have to implement the Jabber hooks. --- irc.c | 17 ++++++----------- irc_commands.c | 17 ++++++++++++++--- protocols/nogaim.c | 24 ++++++++++++++++++++++++ protocols/nogaim.h | 10 ++++++++++ 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/irc.c b/irc.c index 72bc5d92..ebb2876b 100644 --- a/irc.c +++ b/irc.c @@ -787,19 +787,14 @@ void irc_motd( irc_t *irc ) void irc_topic( irc_t *irc, char *channel ) { - if( g_strcasecmp( channel, irc->channel ) == 0 ) - { + struct groupchat *c = irc_chat_by_channel( irc, channel ); + + if( c && c->topic ) + irc_reply( irc, 332, "%s :%s", channel, c->topic ); + else if( g_strcasecmp( channel, irc->channel ) == 0 ) irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC ); - } else - { - struct groupchat *c = irc_chat_by_channel( irc, channel ); - - if( c ) - irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title ); - else - irc_reply( irc, 331, "%s :No topic for this channel", channel ); - } + irc_reply( irc, 331, "%s :No topic for this channel", channel ); } void irc_umode_set( irc_t *irc, char *s, int allow_priv ) diff --git a/irc_commands.c b/irc_commands.c index 266d9732..287a126f 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -420,10 +420,21 @@ static void irc_cmd_watch( irc_t *irc, char **cmd ) static void irc_cmd_topic( irc_t *irc, char **cmd ) { - if( cmd[2] ) - irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] ); + char *channel = cmd[1]; + char *topic = cmd[2]; + + if( topic ) + { + /* Send the topic */ + struct groupchat *c = irc_chat_by_channel( irc, channel ); + if( c && c->ic && c->ic->acc->prpl->chat_topic ) + c->ic->acc->prpl->chat_topic( c, topic ); + } else - irc_topic( irc, cmd[1] ); + { + /* Get the topic */ + irc_topic( irc, channel ); + } } static void irc_cmd_away( irc_t *irc, char **cmd ) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index d1aceb1a..2ad8a049 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -759,6 +759,29 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, g_free( wrapped ); } +void imcb_chat_topic( struct groupchat *c, char *who, char *topic ) +{ + struct im_connection *ic = c->ic; + user_t *u = NULL; + + if( who == NULL) + u = user_find( ic, ic->irc->mynick ); + else if( g_strcasecmp( who, ic->acc->user ) == 0 ) + u = user_find( ic, ic->irc->nick ); + else + u = user_findhandle( ic, who ); + + if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) || + ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) ) + strip_html( topic ); + + g_free( c->topic ); + c->topic = g_strdup( topic ); + + if( c->joined && u ) + irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); +} + struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) { struct groupchat *c; @@ -776,6 +799,7 @@ struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) c->ic = ic; c->title = g_strdup( handle ); c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); + c->topic = g_strdup_printf( "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->channel, c->title ); if( set_getbool( &ic->irc->set, "debug" ) ) imcb_log( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 5bf6d922..7c643cd3 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -109,6 +109,9 @@ struct groupchat { /* The title variable contains the ID you gave when you created the * chat using imcb_chat_new(). */ char *title; + /* Use imcb_chat_topic() to change this variable otherwise the user + * won't notice the topic change. */ + char *topic; char joined; /* This is for you, you can add your own structure here to extend this * structure for your protocol's needs. */ @@ -211,6 +214,11 @@ struct prpl { * not implement this. */ struct groupchat * (* chat_join) (struct im_connection *, char *room, char *nick, char *password); + /* Change the topic, if supported. Note that BitlBee expects the IM + server to confirm the topic change with a regular topic change + event. If it doesn't do that, you have to fake it to make it + visible to the user. */ + void (* chat_topic) (struct groupchat *, char *message); /* You can tell what away states your protocol supports, so that * BitlBee will try to map the IRC away reasons to them, or use @@ -292,6 +300,8 @@ G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); +/* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ +G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic ); G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); /* Actions, or whatever. */ -- cgit v1.2.3 From ef5c1855b406e462fb8b90b517f1672a47bcc4b5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 19 Nov 2007 23:14:39 +0000 Subject: Added Jabber groupchat topic support. --- protocols/jabber/conference.c | 28 ++++++++++++++++++++++++++++ protocols/jabber/jabber.c | 7 +++++++ protocols/jabber/jabber.h | 1 + protocols/jabber/sasl.c | 2 +- protocols/nogaim.c | 6 +++--- protocols/nogaim.h | 4 ++-- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 3fc9ee70..008bbe63 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -96,6 +96,25 @@ int jabber_chat_msg( struct groupchat *c, char *message, int flags ) return 1; } +int jabber_chat_topic( struct groupchat *c, char *topic ) +{ + struct im_connection *ic = c->ic; + struct jabber_chat *jc = c->data; + struct xt_node *node; + + node = xt_new_node( "subject", topic, NULL ); + node = jabber_make_packet( "message", "groupchat", jc->name, node ); + + if( !jabber_write_packet( ic, node ) ) + { + xt_free_node( node ); + return 0; + } + xt_free_node( node ); + + return 1; +} + int jabber_chat_leave( struct groupchat *c, const char *reason ) { struct im_connection *ic = c->ic; @@ -213,6 +232,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) { + struct xt_node *subject = xt_find_node( node->children, "subject" ); struct xt_node *body = xt_find_node( node->children, "body" ); struct groupchat *chat; char *s; @@ -236,6 +256,14 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud return; } + if( subject ) + { + s = strchr( bud->ext_jid, '/' ); + if( s ) *s = 0; + imcb_chat_topic( chat, bud->ext_jid, subject->text_len > 0 ? + subject->text : NULL, jabber_get_timestamp( node ) ); + if( s ) *s = '/'; + } if( body && body->text_len > 0 ) { s = strchr( bud->ext_jid, '/' ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index ab26efc9..e7be63fd 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -384,6 +384,12 @@ static void jabber_chat_msg_( struct groupchat *c, char *message, int flags ) jabber_chat_msg( c, message, flags ); } +static void jabber_chat_topic_( struct groupchat *c, char *topic ) +{ + if( c && topic ) + jabber_chat_topic( c, topic ); +} + static void jabber_chat_leave_( struct groupchat *c ) { if( c ) @@ -460,6 +466,7 @@ void jabber_initmodule() ret->add_buddy = jabber_add_buddy; ret->remove_buddy = jabber_remove_buddy; ret->chat_msg = jabber_chat_msg_; + ret->chat_topic = jabber_chat_topic_; // ret->chat_invite = jabber_chat_invite; ret->chat_leave = jabber_chat_leave_; ret->chat_join = jabber_chat_join_; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 7af7f98e..e26c3899 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -228,6 +228,7 @@ gboolean sasl_supported( struct im_connection *ic ); struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ); void jabber_chat_free( struct groupchat *c ); int jabber_chat_msg( struct groupchat *ic, char *message, int flags ); +int jabber_chat_topic( struct groupchat *c, char *topic ); int jabber_chat_leave( struct groupchat *c, const char *reason ); void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 6eee37b3..87059051 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -331,5 +331,5 @@ gboolean sasl_supported( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; - return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL; + return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != 0; } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 2ad8a049..e0f04c0b 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -759,15 +759,15 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, g_free( wrapped ); } -void imcb_chat_topic( struct groupchat *c, char *who, char *topic ) +void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) { struct im_connection *ic = c->ic; user_t *u = NULL; if( who == NULL) - u = user_find( ic, ic->irc->mynick ); + u = user_find( ic->irc, ic->irc->mynick ); else if( g_strcasecmp( who, ic->acc->user ) == 0 ) - u = user_find( ic, ic->irc->nick ); + u = user_find( ic->irc, ic->irc->nick ); else u = user_findhandle( ic, who ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 7c643cd3..adee5e33 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -218,7 +218,7 @@ struct prpl { server to confirm the topic change with a regular topic change event. If it doesn't do that, you have to fake it to make it visible to the user. */ - void (* chat_topic) (struct groupchat *, char *message); + void (* chat_topic) (struct groupchat *, char *topic); /* You can tell what away states your protocol supports, so that * BitlBee will try to map the IRC away reasons to them, or use @@ -301,7 +301,7 @@ G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ -G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic ); +G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ); G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); /* Actions, or whatever. */ -- cgit v1.2.3 From 7df5a087131d3b1bbe7add0907cd72217692ffd0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 19 Nov 2007 23:36:57 +0000 Subject: Changelog update. --- doc/CHANGES | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/CHANGES b/doc/CHANGES index 6c109f25..b8dbe86f 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -15,6 +15,7 @@ Version 1.2: the one-process daemon mode is not reliable enough. - BitlBee now makes the buddy quits when doing "account off" look like a netsplit. Modern IRC clients show this in a different, more compact way. + (This can be disabled if your client doesn't support this.) - GLib 1.x compatibility was dropped. BitlBee now requires GLib 2.4 or newer. This allows us to use more GLib features (like the XML parser). By now GLib 1.x is so old that supporting it really isn't necessary anymore. @@ -47,13 +48,14 @@ Version 1.2: - A brand new Jabber module. Besides the major code cleanup, it also has has these new features: * Pretty complete XMPP support: RFC3920, RFC3921 plus a number of XEPs - including XEP73 and XEP85. (See http://www.xmpp.org/ for what all these - things mean exactly.) Privacy lists are not supported for obvious + including XEP45, XEP73 and XEP85. (See http://www.xmpp.org/ for what all + these things mean exactly.) Privacy lists are not supported for obvious reasons. * This complete support also includes TLS and SASL support and SRV record lookup. This means that specifying a server tag for connections should (almost) never be necessary anymore, BitlBee can find the server and can automatically convert plaintext connections to TLS-encrypted ones. + * XEP45: Jabber chatroom support! * XEP85 means typing notifications. The older XEP22 (still used by some clients including Gaim <2.0) is not supported. * Better handling of buddies who have more than one resource on-line. As -- cgit v1.2.3 From 3e1e11afc869238d5cfca899d4814fea8a877687 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 19 Nov 2007 23:41:42 +0000 Subject: Fixed NULL pointer dereference (in printf) when connected to a non-socket (which I do quite often when testing stuff). --- bitlbee.c | 16 ++++++---------- irc.c | 15 +++++---------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 7a9a89d9..3d8a0310 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -49,12 +49,11 @@ int bitlbee_daemon_init() hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; - i = getaddrinfo( global.conf->iface, global.conf->port, &hints, - &addrinfo_bind ); + i = getaddrinfo( global.conf->iface, global.conf->port, &hints, &addrinfo_bind ); if( i ) { - log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s", - global.conf->iface, gai_strerror(i) ); + log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s", + global.conf->iface, gai_strerror(i) ); return -1; } @@ -62,15 +61,13 @@ int bitlbee_daemon_init() for( res = addrinfo_bind; res; res = res->ai_next ) { - global.listen_socket = socket( res->ai_family, res->ai_socktype, - res->ai_protocol ); + global.listen_socket = socket( res->ai_family, res->ai_socktype, res->ai_protocol ); if( global.listen_socket < 0 ) continue; /* TIME_WAIT (?) sucks.. */ i = 1; - setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, - sizeof( i ) ); + setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen ); if( i == -1 ) @@ -118,8 +115,7 @@ int bitlbee_daemon_init() if( global.conf->runmode == RUNMODE_FORKDAEMON ) ipc_master_load_state(); - if( global.conf->runmode == RUNMODE_DAEMON || - global.conf->runmode == RUNMODE_FORKDAEMON ) + if( global.conf->runmode == RUNMODE_DAEMON || global.conf->runmode == RUNMODE_FORKDAEMON ) ipc_master_listen_socket(); if( ( fp = fopen( global.conf->pidfile, "w" ) ) ) diff --git a/irc.c b/irc.c index ebb2876b..5531addb 100644 --- a/irc.c +++ b/irc.c @@ -77,11 +77,6 @@ irc_t *irc_new( int fd ) { irc->myhost = g_strdup( ipv6_unwrap( buf ) ); } - else - { - /* Rare, but possible. */ - strncpy( irc->myhost, "localhost.localdomain", NI_MAXHOST ); - } } if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) @@ -93,13 +88,13 @@ irc_t *irc_new( int fd ) { irc->host = g_strdup( ipv6_unwrap( buf ) ); } - else - { - /* Rare, but possible. */ - strncpy( irc->host, "localhost.localdomain", NI_MAXHOST ); - } } + if( irc->host == NULL ) + irc->host = g_strdup( "localhost.localdomain" ); + if( irc->myhost == NULL ) + irc->myhost = g_strdup( "localhost.localdomain" ); + if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); -- cgit v1.2.3 From d75597b0b31f8aa8ca523a3cfa4869e20fca8466 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 20 Nov 2007 00:13:58 +0000 Subject: Fixed memory management issues introduced by at least the getaddrinfo() change. (Patch from arnau) --- conf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.c b/conf.c index 551e8f5e..82487ddf 100644 --- a/conf.c +++ b/conf.c @@ -47,10 +47,10 @@ conf_t *conf_load( int argc, char *argv[] ) conf = g_new0( conf_t, 1 ); conf->iface = NULL; - conf->port = "6667"; + conf->port = g_strdup( "6667" ); conf->nofork = 0; conf->verbose = 0; - conf->primary_storage = "xml"; + conf->primary_storage = g_strdup( "xml" ); conf->migrate_storage = g_strsplit( "text", ",", -1 ); conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; -- cgit v1.2.3 From 56f260affd91651cb0c44ee14713f7dfa0717ad4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 22 Nov 2007 22:56:52 +0000 Subject: Some changes to get rid of compiler warnings. (And disabling strict aliasing because there are too many warnings about it. :-P) --- configure | 2 +- lib/ssl_gnutls.c | 10 +++++++++- protocols/nogaim.c | 10 +++++----- root_commands.c | 4 ++-- storage_xml.c | 4 ++-- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/configure b/configure index bc9960a9..b84f3947 100755 --- a/configure +++ b/configure @@ -136,7 +136,7 @@ if [ "$debug" = "1" ]; then echo 'DEBUG=1' >> Makefile.settings echo '#define DEBUG' >> config.h else - [ -z "$CFLAGS" ] && CFLAGS=-O3 + [ -z "$CFLAGS" ] && CFLAGS="-O2 -fno-strict-aliasing" fi echo CFLAGS=$CFLAGS >> Makefile.settings diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index fbd1d0c0..221a2862 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -35,6 +35,14 @@ int ssl_errno = 0; static gboolean initialized = FALSE; +#include <limits.h> + +#if defined(ULONG_MAX) && ULONG_MAX > 4294967295UL +#define GNUTLS_STUPID_CAST (long) +#else +#define GNUTLS_STUPID_CAST (int) +#endif + struct scd { ssl_input_function func; @@ -124,7 +132,7 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred ); sock_make_nonblocking( conn->fd ); - gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd ); + gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) GNUTLS_STUPID_CAST conn->fd ); return ssl_handshake( data, source, cond ); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index e0f04c0b..5e698902 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -698,7 +698,7 @@ void imcb_chat_free( struct groupchat *c ) GList *ir; if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "You were removed from conversation 0x%x", (int) c ); + imcb_log( ic, "You were removed from conversation %p", c ); if( c ) { @@ -754,7 +754,7 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, } else { - imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, wrapped ); + imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped ); } g_free( wrapped ); } @@ -802,7 +802,7 @@ struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) c->topic = g_strdup_printf( "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->channel, c->title ); if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "Creating new conversation: (id=0x%x,handle=%s)", (int) c, handle ); + imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); return c; } @@ -816,7 +816,7 @@ void imcb_chat_add_buddy( struct groupchat *b, char *handle ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - imcb_log( b->ic, "User %s added to conversation 0x%x", handle, (int) b ); + imcb_log( b->ic, "User %s added to conversation %p", handle, b ); /* It might be yourself! */ if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 ) @@ -851,7 +851,7 @@ void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ) int me = 0; if( set_getbool( &b->ic->irc->set, "debug" ) ) - imcb_log( b->ic, "User %s removed from conversation 0x%x (%s)", handle, (int) b, reason ? reason : "" ); + imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" ); /* It might be yourself! */ if( g_strcasecmp( handle, b->ic->acc->user ) == 0 ) diff --git a/root_commands.c b/root_commands.c index e9c71f04..642f5374 100644 --- a/root_commands.c +++ b/root_commands.c @@ -744,7 +744,7 @@ static void cmd_yesno( irc_t *irc, char **cmd ) static void cmd_set( irc_t *irc, char **cmd ) { - char *set_name; + char *set_name = NULL; if( cmd[1] && cmd[2] ) { @@ -764,7 +764,7 @@ static void cmd_set( irc_t *irc, char **cmd ) set_name = cmd[1]; } } - if( cmd[1] ) /* else 'forgotten' on purpose.. Must show new value after changing */ + if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ { char *s = set_getstr( &irc->set, set_name ); if( s ) diff --git a/storage_xml.c b/storage_xml.c index 8618c5fe..4c372cde 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -455,7 +455,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) errors, so instead let's use the _find function and return TRUE on write errors. Which means, if we found something, there was an error. :-) */ - if( g_hash_table_find( acc->nicks, xml_save_nick, (gpointer) fd ) ) + if( g_hash_table_find( acc->nicks, xml_save_nick, & fd ) ) goto write_error; if( !xml_printf( fd, 1, "</account>\n" ) ) @@ -493,7 +493,7 @@ write_error: static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data ) { - return !xml_printf( (int) data, 2, "<buddy handle=\"%s\" nick=\"%s\" />\n", key, value ); + return !xml_printf( *( (int*) data ), 2, "<buddy handle=\"%s\" nick=\"%s\" />\n", key, value ); } static storage_status_t xml_remove( const char *nick, const char *password ) -- cgit v1.2.3 From df6d1da013f42caa5f11dbcbb0d54710682811f7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 23 Nov 2007 22:25:04 +0000 Subject: Replaced GPL-incompatible MD5 hashing code. --- crypting.c | 5 +- debian/copyright | 25 --- lib/md5.c | 577 ++++++++++++++++++++----------------------------------- lib/md5.h | 102 +++------- 4 files changed, 242 insertions(+), 467 deletions(-) diff --git a/crypting.c b/crypting.c index 5ba47e5b..2a17a913 100644 --- a/crypting.c +++ b/crypting.c @@ -28,11 +28,12 @@ included if CRYPTING_MAIN is defined. Or just do "make decode" and the programs will be built. */ -#include "md5.h" -#include "crypting.h" #include <string.h> #include <stdio.h> #include <stdlib.h> +#include <glib.h> +#include "md5.h" +#include "crypting.h" /*\ * [SH] Do _not_ call this if it's not entirely sure that it will not cause diff --git a/debian/copyright b/debian/copyright index 3f2ecc8e..40a777a9 100644 --- a/debian/copyright +++ b/debian/copyright @@ -31,31 +31,6 @@ BitlBee License: -The MD5 generator used for authentication in some modules is written by -Aladdin Enterprises: - -============================================================================ - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -============================================================================ - - - The SGML-formatted documentation is written by Jelmer Vernooij <jelmer@nl.linux.org> under the GNU Free Documentation License: diff --git a/lib/md5.c b/lib/md5.c index e6273585..08c298a2 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -1,392 +1,235 @@ /* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - + * MD5 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.c is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. */ +#include <sys/types.h> +#include <string.h> /* for memcpy() */ #include "md5.h" -#include <string.h> -#ifdef TEST +static void md5_transform(u_int32_t buf[4], u_int32_t const in[16]); + /* - * Compile with -DTEST to create a self-contained executable test program. - * The test program should print out the same values as given in section - * A.5 of RFC 1321, reproduced below. + * Wrapper function for all-in-one MD5 + * + * Bernardo Reino, aka Lepton. + * 20021120 */ -#include <string.h> -main() + +void md5_init(struct MD5Context *ctx) { - static const char *const test[7] = { - "", /*d41d8cd98f00b204e9800998ecf8427e*/ - "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ - "abc", /*900150983cd24fb0d6963f7d28e17f72*/ - "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ - "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - /*d174ab98d277d9f5a5611c2c9f419d9f*/ - "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ - }; - int i; - - for (i = 0; i < 7; ++i) { - md5_state_t state; - md5_byte_t digest[16]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); - md5_finish(&state, digest); - printf("MD5 (\"%s\") = ", test[i]); - for (di = 0; di < 16; ++di) - printf("%02x", digest[di]); - printf("\n"); - } - return 0; -} -#endif /* TEST */ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} /* - * For reference, here is the program that computed the T values. + * Update context to reflect the concatenation of another buffer full + * of bytes. */ -#if 0 -#include <math.h> -main() +void md5_append(struct MD5Context *ctx, const md5_byte_t *buf, + unsigned int len) { - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - printf("#define T%d 0x%08lx\n", i, v); - } - return 0; + u_int32_t t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((u_int32_t) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + md5_transform(ctx->buf, (u_int32_t *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + md5_transform(ctx->buf, (u_int32_t *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); } -#endif + /* - * End of T computation program. + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) */ -#define T1 0xd76aa478 -#define T2 0xe8c7b756 -#define T3 0x242070db -#define T4 0xc1bdceee -#define T5 0xf57c0faf -#define T6 0x4787c62a -#define T7 0xa8304613 -#define T8 0xfd469501 -#define T9 0x698098d8 -#define T10 0x8b44f7af -#define T11 0xffff5bb1 -#define T12 0x895cd7be -#define T13 0x6b901122 -#define T14 0xfd987193 -#define T15 0xa679438e -#define T16 0x49b40821 -#define T17 0xf61e2562 -#define T18 0xc040b340 -#define T19 0x265e5a51 -#define T20 0xe9b6c7aa -#define T21 0xd62f105d -#define T22 0x02441453 -#define T23 0xd8a1e681 -#define T24 0xe7d3fbc8 -#define T25 0x21e1cde6 -#define T26 0xc33707d6 -#define T27 0xf4d50d87 -#define T28 0x455a14ed -#define T29 0xa9e3e905 -#define T30 0xfcefa3f8 -#define T31 0x676f02d9 -#define T32 0x8d2a4c8a -#define T33 0xfffa3942 -#define T34 0x8771f681 -#define T35 0x6d9d6122 -#define T36 0xfde5380c -#define T37 0xa4beea44 -#define T38 0x4bdecfa9 -#define T39 0xf6bb4b60 -#define T40 0xbebfbc70 -#define T41 0x289b7ec6 -#define T42 0xeaa127fa -#define T43 0xd4ef3085 -#define T44 0x04881d05 -#define T45 0xd9d4d039 -#define T46 0xe6db99e5 -#define T47 0x1fa27cf8 -#define T48 0xc4ac5665 -#define T49 0xf4292244 -#define T50 0x432aff97 -#define T51 0xab9423a7 -#define T52 0xfc93a039 -#define T53 0x655b59c3 -#define T54 0x8f0ccc92 -#define T55 0xffeff47d -#define T56 0x85845dd1 -#define T57 0x6fa87e4f -#define T58 0xfe2ce6e0 -#define T59 0xa3014314 -#define T60 0x4e0811a1 -#define T61 0xf7537e82 -#define T62 0xbd3af235 -#define T63 0x2ad7d2bb -#define T64 0xeb86d391 - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +void md5_finish(struct MD5Context *ctx, md5_byte_t digest[16]) { - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - -#ifndef ARCH_IS_BIG_ENDIAN -# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ -#endif -#if ARCH_IS_BIG_ENDIAN - - /* - * On big-endian machines, we must arrange the bytes in the right - * order. (This also works on machines of unknown byte order.) - */ - md5_word_t X[16]; - const md5_byte_t *xp = data; - int i; - - for (i = 0; i < 16; ++i, xp += 4) - X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - -#else /* !ARCH_IS_BIG_ENDIAN */ - - /* - * On little-endian machines, we can process properly aligned data - * without copying it. - */ - md5_word_t xbuf[16]; - const md5_word_t *X; - - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } -#endif - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + md5_transform(ctx->buf, (u_int32_t *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + + /* Append length in bits and transform */ + ((u_int32_t *) ctx->in)[14] = ctx->bits[0]; + ((u_int32_t *) ctx->in)[15] = ctx->bits[1]; + + md5_transform(ctx->buf, (u_int32_t *) ctx->in); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = 0xefcdab89; - pms->abcd[2] = 0x98badcfe; - pms->abcd[3] = 0x10325476; -} +/* The four core functions - F1 is optimized somewhat */ -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void md5_transform(u_int32_t buf[4], u_int32_t const in[16]) { - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + register u_int32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; } diff --git a/lib/md5.h b/lib/md5.h index f24f2ff1..86568b7a 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -1,85 +1,41 @@ /* - Copyright (C) 1999 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - + * MD5 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. */ -/* - Independent implementation of MD5 (RFC 1321). - This code implements the MD5 Algorithm defined in RFC 1321. - It is derived directly from the text of the RFC and not from the - reference implementation. - - The original and principal author of md5.h is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2004-03-09 Jelmer Vernooij add G_MODULE_EXPORT for Bitlbee - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke <purschke@bnl.gov>. - 1999-05-03 lpd Original version. +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. */ -#ifndef md5_INCLUDED -# define md5_INCLUDED +#ifndef _MD5_H +#define _MD5_H -#include <glib.h> +#include <sys/types.h> #include <gmodule.h> -/* - * This code has some adaptations for the Ghostscript environment, but it - * will compile and run correctly in any environment with 8-bit chars and - * 32-bit ints. Specifically, it assumes that if the following are - * defined, they have the same meaning as in Ghostscript: P1, P2, P3, - * ARCH_IS_BIG_ENDIAN. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ +typedef u_int8_t md5_byte_t; +typedef struct MD5Context { + u_int32_t buf[4]; + u_int32_t bits[2]; + unsigned char in[64]; } md5_state_t; -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -G_MODULE_EXPORT void md5_init(md5_state_t *pms); - -/* Append a string to the message. */ -G_MODULE_EXPORT void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +G_MODULE_EXPORT void md5_init(struct MD5Context *context); +G_MODULE_EXPORT void md5_append(struct MD5Context *context, const md5_byte_t *buf, unsigned int len); +G_MODULE_EXPORT void md5_finish(struct MD5Context *context, md5_byte_t digest[16]); -/* Finish the message and return the digest. */ -G_MODULE_EXPORT void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ #endif - -#endif /* md5_INCLUDED */ -- cgit v1.2.3 From 77bfd077778c30c70f791752ce3a13d537aedd3b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 23 Nov 2007 23:07:44 +0000 Subject: Replaced GPL-incompatible SHA1 hashing code (and renamed the files in case I ever need SHA256 ;-)). --- lib/Makefile | 2 +- lib/sha.c | 173 -------------------- lib/sha.h | 21 --- lib/sha1.c | 375 ++++++++++++++++++++++++++++++++++++++++++++ lib/sha1.h | 66 ++++++++ protocols/jabber/iq.c | 11 +- protocols/nogaim.h | 1 - protocols/yahoo/libyahoo2.c | 44 +++--- 8 files changed, 470 insertions(+), 223 deletions(-) delete mode 100644 lib/sha.c delete mode 100644 lib/sha.h create mode 100644 lib/sha1.c create mode 100644 lib/sha1.h diff --git a/lib/Makefile b/lib/Makefile index bc1966d9..a79f7c4c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha.o $(SSL_CLIENT) url.o +objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o CFLAGS += -Wall LFLAGS += -r diff --git a/lib/sha.c b/lib/sha.c deleted file mode 100644 index 895505a1..00000000 --- a/lib/sha.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * - * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are - * Copyright (C) 1995-9 by Cryptography Research, Inc. All - * Rights Reserved. - * - * Contributor(s): - * - */ - -#define BITLBEE_CORE -#include "nogaim.h" - -static void shaHashBlock(SHA_CTX *ctx); - -void shaInit(SHA_CTX *ctx) { - int i; - - ctx->lenW = 0; - ctx->sizeHi = ctx->sizeLo = 0; - - /* Initialize H with the magic constants (see FIPS180 for constants) - */ - ctx->H[0] = 0x67452301L; - ctx->H[1] = 0xefcdab89L; - ctx->H[2] = 0x98badcfeL; - ctx->H[3] = 0x10325476L; - ctx->H[4] = 0xc3d2e1f0L; - - for (i = 0; i < 80; i++) - ctx->W[i] = 0; -} - - -void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) { - int i; - - /* Read the data into W and process blocks as they get full - */ - for (i = 0; i < len; i++) { - ctx->W[ctx->lenW / 4] <<= 8; - ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i]; - if ((++ctx->lenW) % 64 == 0) { - shaHashBlock(ctx); - ctx->lenW = 0; - } - ctx->sizeLo += 8; - ctx->sizeHi += (ctx->sizeLo < 8); - } -} - - -void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) { - unsigned char pad0x80 = 0x80; - unsigned char pad0x00 = 0x00; - unsigned char padlen[8]; - int i; - - /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length - */ - padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255); - padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255); - padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255); - padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255); - padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255); - padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); - padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); - padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - shaUpdate(ctx, &pad0x80, 1); - while (ctx->lenW != 56) - shaUpdate(ctx, &pad0x00, 1); - shaUpdate(ctx, padlen, 8); - - /* Output hash - */ - for (i = 0; i < 20; i++) { - hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24); - ctx->H[i / 4] <<= 8; - } - - /* - * Re-initialize the context (also zeroizes contents) - */ - shaInit(ctx); -} - - -void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) { - SHA_CTX ctx; - - shaInit(&ctx); - shaUpdate(&ctx, dataIn, len); - shaFinal(&ctx, hashout); -} - - -#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL) - -static void shaHashBlock(SHA_CTX *ctx) { - int t; - guint32 A,B,C,D,E,TEMP; - - for (t = 16; t <= 79; t++) - ctx->W[t] = - SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - for (t = 0; t <= 19; t++) { - TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 20; t <= 39; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 40; t <= 59; t++) { - TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - for (t = 60; t <= 79; t++) { - TEMP = (SHA_ROTL(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL; - E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP; - } - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; -} - -/*---------------------------------------------------------------------------- - * - * This code added by Thomas "temas" Muldowney for Jabber compatability - * - *---------------------------------------------------------------------------*/ -char *shahash(char *str) -{ - static char final[41]; - char *pos; - unsigned char hashval[20]; - int x; - - if(!str || strlen(str) == 0) - return NULL; - - shaBlock((unsigned char *)str, strlen(str), hashval); - - pos = final; - for(x=0;x<20;x++) - { - g_snprintf(pos, 3, "%02x", hashval[x]); - pos += 2; - } - return (char *)final; -} diff --git a/lib/sha.h b/lib/sha.h deleted file mode 100644 index e8152b1b..00000000 --- a/lib/sha.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SHA_H__ -#define __SHA_H__ - -#include <gmodule.h> - -G_MODULE_EXPORT int strprintsha(char *dest, int *hashval); - -typedef struct { - guint32 H[5]; - guint32 W[80]; - int lenW; - guint32 sizeHi,sizeLo; -} SHA_CTX; - -G_MODULE_EXPORT void shaInit(SHA_CTX *ctx); -G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); -G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); -G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); -G_MODULE_EXPORT char *shahash(char *str); - -#endif diff --git a/lib/sha1.c b/lib/sha1.c new file mode 100644 index 00000000..ee4fcc19 --- /dev/null +++ b/lib/sha1.c @@ -0,0 +1,375 @@ +/* + * SHA1 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. + */ + +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses <stdint.h> (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +static void sha1_pad(sha1_state_t *); +static void sha1_process_block(sha1_state_t *); + +/* + * sha1_init + * + * Description: + * This function will initialize the sha1_state_t in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int sha1_init(sha1_state_t * context) +{ + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * sha1_finish + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int sha1_finish(sha1_state_t * context, uint8_t Message_Digest[sha1_hash_size]) +{ + int i; + + if (!context || !Message_Digest) { + return shaNull; + } + + if (context->Corrupted) { + return context->Corrupted; + } + + if (!context->Computed) { + sha1_pad(context); + for (i = 0; i < 64; ++i) { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for (i = 0; i < sha1_hash_size; ++i) { + Message_Digest[i] = context->Intermediate_Hash[i >> 2] + >> 8 * (3 - (i & 0x03)); + } + + return shaSuccess; +} + +/* + * sha1_append + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int +sha1_append(sha1_state_t * context, + const uint8_t * message_array, unsigned length) +{ + if (!length) { + return shaSuccess; + } + + if (!context || !message_array) { + return shaNull; + } + + if (context->Computed) { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) { + return context->Corrupted; + } + while (length-- && !context->Corrupted) { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) { + context->Length_High++; + if (context->Length_High == 0) { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) { + sha1_process_block(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * sha1_process_block + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +static void sha1_process_block(sha1_state_t * context) +{ + const uint32_t K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for (t = 0; t < 16; t++) { + W[t] = context->Message_Block[t * 4] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for (t = 16; t < 80; t++) { + W[t] = + SHA1CircularShift(1, + W[t - 3] ^ W[t - 8] ^ W[t - + 14] ^ W[t - + 16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for (t = 0; t < 20; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + + B = A; + A = temp; + } + + for (t = 20; t < 40; t++) { + temp = + SHA1CircularShift(5, + A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 40; t < 60; t++) { + temp = SHA1CircularShift(5, A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + for (t = 60; t < 80; t++) { + temp = + SHA1CircularShift(5, + A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30, B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * sha1_pad + * + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +static void sha1_pad(sha1_state_t * context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) { + context->Message_Block[context->Message_Block_Index++] = + 0x80; + while (context->Message_Block_Index < 64) { + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + + sha1_process_block(context); + + while (context->Message_Block_Index < 56) { + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + } else { + context->Message_Block[context->Message_Block_Index++] = + 0x80; + while (context->Message_Block_Index < 56) { + + context->Message_Block[context-> + Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = context->Length_High >> 24; + context->Message_Block[57] = context->Length_High >> 16; + context->Message_Block[58] = context->Length_High >> 8; + context->Message_Block[59] = context->Length_High; + context->Message_Block[60] = context->Length_Low >> 24; + context->Message_Block[61] = context->Length_Low >> 16; + context->Message_Block[62] = context->Length_Low >> 8; + context->Message_Block[63] = context->Length_Low; + + sha1_process_block(context); +} diff --git a/lib/sha1.h b/lib/sha1.h new file mode 100644 index 00000000..368c0669 --- /dev/null +++ b/lib/sha1.h @@ -0,0 +1,66 @@ +/* + * SHA1 hashing code copied from Lepton's crack <http://usuarios.lycos.es/reinob/> + * + * Adapted to be API-compatible with the previous (GPL-incompatible) code. + */ + +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#include <stdint.h> +#include <gmodule.h> + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif +#define sha1_hash_size 20 + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context { + uint32_t Intermediate_Hash[sha1_hash_size/4]; /* Message Digest */ + + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ + + /* Index into message block array */ + int_least16_t Message_Block_Index; + uint8_t Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} sha1_state_t; + +/* + * Function Prototypes + */ + +G_MODULE_EXPORT int sha1_init(sha1_state_t *); +G_MODULE_EXPORT int sha1_append(sha1_state_t *, const uint8_t *, unsigned int); +G_MODULE_EXPORT int sha1_finish(sha1_state_t *, uint8_t Message_Digest[sha1_hash_size]); + +#endif diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 4738817a..40897639 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -22,6 +22,7 @@ \***************************************************************************/ #include "jabber.h" +#include "sha1.h" static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); @@ -232,15 +233,15 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no { /* We can do digest authentication, it seems, and of course we prefer that. */ - SHA_CTX sha; + sha1_state_t sha; char hash_hex[41]; unsigned char hash[20]; int i; - shaInit( &sha ); - shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); - shaUpdate( &sha, (unsigned char*) ic->acc->pass, strlen( ic->acc->pass ) ); - shaFinal( &sha, hash ); + sha1_init( &sha ); + sha1_append( &sha, (unsigned char*) s, strlen( s ) ); + sha1_append( &sha, (unsigned char*) ic->acc->pass, strlen( ic->acc->pass ) ); + sha1_finish( &sha, hash ); for( i = 0; i < 20; i ++ ) sprintf( hash_hex + i * 2, "%02x", hash[i] ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index adee5e33..0e890464 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -42,7 +42,6 @@ #include "account.h" #include "proxy.h" #include "md5.h" -#include "sha.h" #define BUF_LEN MSG_LEN #define BUF_LONG ( BUF_LEN * 2 ) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 5beae687..ce38bc73 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -75,7 +75,7 @@ char *strchr (), *strrchr (); #include <stdlib.h> #include <ctype.h> -#include "sha.h" +#include "sha1.h" #include "md5.h" #include "yahoo2.h" #include "yahoo_httplib.h" @@ -1819,8 +1819,8 @@ static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *se md5_byte_t result[16]; md5_state_t ctx; - SHA_CTX ctx1; - SHA_CTX ctx2; + sha1_state_t ctx1; + sha1_state_t ctx2; char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ"; char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop"; @@ -1876,7 +1876,7 @@ static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *se magic_ptr = (unsigned char *)seed; - while (*magic_ptr != (int)NULL) { + while (*magic_ptr != 0) { char *loc; /* Ignore parentheses. */ @@ -2055,27 +2055,27 @@ static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *se if (cnt < 64) memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt); - shaInit(&ctx1); - shaInit(&ctx2); + sha1_init(&ctx1); + sha1_init(&ctx2); /* The first context gets the password hash XORed * with 0x36 plus a magic value * which we previously extrapolated from our * challenge. */ - shaUpdate(&ctx1, pass_hash_xor1, 64); + sha1_append(&ctx1, pass_hash_xor1, 64); if (j >= 3 ) - ctx1.sizeLo = 0x1ff; - shaUpdate(&ctx1, magic_key_char, 4); - shaFinal(&ctx1, digest1); + ctx1.Length_Low = 0x1ff; + sha1_append(&ctx1, magic_key_char, 4); + sha1_finish(&ctx1, digest1); /* The second context gets the password hash XORed * with 0x5c plus the SHA-1 digest * of the first context. */ - shaUpdate(&ctx2, pass_hash_xor2, 64); - shaUpdate(&ctx2, digest1, 20); - shaFinal(&ctx2, digest2); + sha1_append(&ctx2, pass_hash_xor2, 64); + sha1_append(&ctx2, digest1, 20); + sha1_finish(&ctx2, digest2); /* Now that we have digest2, use it to fetch * characters from an alphabet to construct @@ -2146,27 +2146,27 @@ static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *se if (cnt < 64) memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt); - shaInit(&ctx1); - shaInit(&ctx2); + sha1_init(&ctx1); + sha1_init(&ctx2); /* The first context gets the password hash XORed * with 0x36 plus a magic value * which we previously extrapolated from our * challenge. */ - shaUpdate(&ctx1, crypt_hash_xor1, 64); + sha1_append(&ctx1, crypt_hash_xor1, 64); if (j >= 3 ) - ctx1.sizeLo = 0x1ff; - shaUpdate(&ctx1, magic_key_char, 4); - shaFinal(&ctx1, digest1); + ctx1.Length_Low = 0x1ff; + sha1_append(&ctx1, magic_key_char, 4); + sha1_finish(&ctx1, digest1); /* The second context gets the password hash XORed * with 0x5c plus the SHA-1 digest * of the first context. */ - shaUpdate(&ctx2, crypt_hash_xor2, 64); - shaUpdate(&ctx2, digest1, 20); - shaFinal(&ctx2, digest2); + sha1_append(&ctx2, crypt_hash_xor2, 64); + sha1_append(&ctx2, digest1, 20); + sha1_finish(&ctx2, digest2); /* Now that we have digest2, use it to fetch * characters from an alphabet to construct -- cgit v1.2.3 From 3a80471931642374f323e284ce3a5a04b5635a96 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 24 Nov 2007 01:13:15 +0000 Subject: (Hopefully) fixing one case where the Jabber module doesn't understand a <presence type=unavailable> tag properly and keeps showing the buddy as on-line. (When the tag comes from a bare JID.) --- protocols/jabber/presence.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 71a044b5..5abdc449 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -87,7 +87,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) } else if( strcmp( type, "unavailable" ) == 0 ) { - if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) == NULL ) + if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); @@ -100,7 +100,13 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) jabber_chat_pkt_presence( ic, bud, node ); } - jabber_buddy_remove( ic, from ); + if( strchr( from, '/' ) == NULL ) + /* Sometimes servers send a type="unavailable" from a + bare JID, which should mean that suddenly all + resources for this JID disappeared. */ + jabber_buddy_remove_bare( ic, from ); + else + jabber_buddy_remove( ic, from ); if( is_chat ) { -- cgit v1.2.3 From 608f8cf652d0c443ef551ac979bd46096b361663 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 24 Nov 2007 18:02:39 +0000 Subject: Added some random hash to the id= for cached XMPP packets so that packets from other BitlBees won't be picked up accidentally. Might also want to randomize the per-packet IDs because they're still predictable. --- protocols/jabber/iq.c | 2 +- protocols/jabber/jabber.c | 28 ++++++++++++++++++++++++++++ protocols/jabber/jabber.h | 5 ++++- protocols/jabber/jabber_util.c | 3 ++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 40897639..595718fb 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -49,7 +49,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) struct jabber_cache_entry *entry; if( ( s = xt_find_attr( node, "id" ) ) == NULL || - strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 ) + strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 ) { /* Silently ignore it, without an ID (or a non-cache ID) we don't know how to handle the packet and we diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e7be63fd..b0651a59 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -31,6 +31,8 @@ #include "xmltree.h" #include "bitlbee.h" #include "jabber.h" +#include "md5.h" +#include "base64.h" static void jabber_init( account_t *acc ) { @@ -59,6 +61,8 @@ static void jabber_init( account_t *acc ) s->flags |= ACC_SET_OFFLINE_ONLY; } +static void jabber_generate_id_hash( struct jabber_data *jd ); + static void jabber_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); @@ -199,6 +203,30 @@ static void jabber_login( account_t *acc ) I think this shouldn't break anything. */ imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); } + + jabber_generate_id_hash( jd ); +} + +static void jabber_generate_id_hash( struct jabber_data *jd ) +{ + md5_state_t id_hash; + md5_byte_t binbuf[16]; + char *s; + + md5_init( &id_hash ); + md5_append( &id_hash, (unsigned char *) jd->username, strlen( jd->username ) ); + md5_append( &id_hash, (unsigned char *) jd->server, strlen( jd->server ) ); + s = set_getstr( &jd->ic->acc->set, "resource" ); + md5_append( &id_hash, (unsigned char *) s, strlen( s ) ); + random_bytes( binbuf, 16 ); + md5_append( &id_hash, binbuf, 16 ); + md5_finish( &id_hash, binbuf ); + + s = base64_encode( binbuf, 9 ); + jd->cached_id_prefix = g_strdup_printf( "%s%s", JABBER_CACHED_ID, s ); + g_free( s ); + + printf( "%s\n", jd->cached_id_prefix ); } static void jabber_logout( struct im_connection *ic ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index e26c3899..fc9d2fc4 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -77,6 +77,7 @@ struct jabber_data struct jabber_away_state *away_state; char *away_message; + char *cached_id_prefix; GHashTable *node_cache; GHashTable *buddies; }; @@ -131,7 +132,9 @@ struct jabber_chat /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the first one should be used, but when storing a packet in the cache, a "special" kind of ID is assigned to make it easier later to figure out - if we have to do call an event handler for the response packet. */ + if we have to do call an event handler for the response packet. Also + we'll append a hash to make sure we won't trigger on cached packets from + other BitlBee users. :-) */ #define JABBER_PACKET_ID "BeeP" #define JABBER_CACHED_ID "BeeC" diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 56491c4f..43b91fe3 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -132,9 +132,10 @@ struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) { struct jabber_data *jd = ic->proto_data; - char *id = g_strdup_printf( "%s%05x", JABBER_CACHED_ID, ( next_id++ ) & 0xfffff ); struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); + char *id; + id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff ); xt_add_attr( node, "id", id ); g_free( id ); -- cgit v1.2.3 From 221a27346f768b9626f2a0281ff774790858a0c2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 24 Nov 2007 19:07:22 +0000 Subject: 1.1.1dev (Although the CHANGES change isn't in there). --- Makefile | 2 +- bitlbee.h | 2 +- doc/CHANGES | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 039c202a..a9dd2e17 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # Program variables objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o -headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha.h lib/ssl_client.h lib/url.h protocols/nogaim.h +headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h subdirs = lib protocols # Expansion of variables diff --git a/bitlbee.h b/bitlbee.h index f82f763a..23ec64b1 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -29,7 +29,7 @@ #define _GNU_SOURCE /* Stupid GNU :-P */ #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "1.1dev" +#define BITLBEE_VERSION "1.1.1dev" #define VERSION BITLBEE_VERSION #define MAX_STRING 128 diff --git a/doc/CHANGES b/doc/CHANGES index b8dbe86f..ee4cde69 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -66,6 +66,8 @@ Version 1.2: * The info command now gives away state/message information for all resources available for that buddy. (Of course this only works if the buddy is in your contact list.) + * An XML console (add xmlconsole to your contact list or see "help set + xmlconsole" if you want it permanently). Finished ??? -- cgit v1.2.3 From b6a2373c2c9a98594a87c54a4644f3c0e985e420 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 28 Nov 2007 23:24:26 +0000 Subject: Fixed the epoll+ForkDaemon combination. The libevent event handling didn't work very well on Linux 2.6 (and possibly others) in ForkDaemon mode. --- bitlbee.c | 2 ++ lib/events_libevent.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 3d8a0310..3f488b46 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -292,6 +292,8 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition get the same random numbers as the parent/siblings. */ srand( time( NULL ) ^ getpid() ); + b_main_init(); + /* Close the listening socket, we're a client. */ close( global.listen_socket ); b_event_remove( global.listen_watch_source_id ); diff --git a/lib/events_libevent.c b/lib/events_libevent.c index f2b4d15c..d02ad6a6 100644 --- a/lib/events_libevent.c +++ b/lib/events_libevent.c @@ -36,7 +36,9 @@ #include <sys/time.h> #include <event.h> -static guint id_next; +static void b_main_restart(); + +static guint id_next = 1; static GHashTable *id_hash; static int quitting = 0; @@ -47,6 +49,9 @@ static int quitting = 0; static GHashTable *read_hash; static GHashTable *write_hash; +struct event_base *leh; +struct event_base *old_leh; + struct b_event_data { guint id; @@ -58,9 +63,16 @@ struct b_event_data void b_main_init() { - event_init(); + if( leh != NULL ) + { + /* Clean up the hash tables? */ + + b_main_restart(); + old_leh = leh; + } + + leh = event_init(); - id_next = 1; id_hash = g_hash_table_new( g_int_hash, g_int_equal ); read_hash = g_hash_table_new( g_int_hash, g_int_equal ); write_hash = g_hash_table_new( g_int_hash, g_int_equal ); @@ -68,19 +80,40 @@ void b_main_init() void b_main_run() { - event_dispatch(); + /* This while loop is necessary to exit the event loop and start a + different one (necessary for ForkDaemon mode). */ + while( event_base_dispatch( leh ) == 0 && !quitting ) + { + if( old_leh != NULL ) + { + /* For some reason this just isn't allowed... + Possibly a bug in older versions, will see later. + event_base_free( old_leh ); */ + old_leh = NULL; + } + + printf( "New event loop.\n" ); + } } -void b_main_quit() +static void b_main_restart() { struct timeval tv; - /* libevent sometimes generates events before really quitting, + memset( &tv, 0, sizeof( struct timeval ) ); + event_base_loopexit( leh, &tv ); + + printf( "b_main_restart()\n" ); +} + +void b_main_quit() +{ + /* Tell b_main_run() that it shouldn't restart the loop. Also, + libevent sometimes generates events before really quitting, we want to stop them. */ quitting = 1; - memset( &tv, 0, sizeof( struct timeval ) ); - event_loopexit( &tv ); + b_main_restart(); } static void b_event_passthrough( int fd, short event, void *data ) -- cgit v1.2.3 From 9ff5737ec53cca2ba295b58fb74a8b97f496cd19 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 29 Nov 2007 21:55:14 +0000 Subject: printf() in daemons considered harmful. --- lib/events.h | 4 ++-- lib/events_libevent.c | 8 +++----- protocols/oscar/msgcookie.c | 15 --------------- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/lib/events.h b/lib/events.h index 0588547f..4baea7b6 100644 --- a/lib/events.h +++ b/lib/events.h @@ -44,7 +44,7 @@ #include <glib.h> #include <gmodule.h> -/* The conditions you can pass to gaim_input_add()/that will be passed to +/* The conditions you can pass to b_input_add()/that will be passed to the given callback function. */ typedef enum { GAIM_INPUT_READ = 1 << 1, @@ -57,7 +57,7 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL) #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) -// #define event_debug( x... ) printf( x ) +/* #define event_debug( x... ) printf( x ) */ #define event_debug( x... ) /* Call this once when the program starts. It'll initialize the event handler diff --git a/lib/events_libevent.c b/lib/events_libevent.c index d02ad6a6..d3403152 100644 --- a/lib/events_libevent.c +++ b/lib/events_libevent.c @@ -31,13 +31,11 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> -#include "proxy.h" - #include <sys/time.h> #include <event.h> +#include "proxy.h" static void b_main_restart(); - static guint id_next = 1; static GHashTable *id_hash; static int quitting = 0; @@ -92,7 +90,7 @@ void b_main_run() old_leh = NULL; } - printf( "New event loop.\n" ); + event_debug( "New event loop.\n" ); } } @@ -103,7 +101,7 @@ static void b_main_restart() memset( &tv, 0, sizeof( struct timeval ) ); event_base_loopexit( leh, &tv ); - printf( "b_main_restart()\n" ); + event_debug( "b_main_restart()\n" ); } void b_main_quit() diff --git a/protocols/oscar/msgcookie.c b/protocols/oscar/msgcookie.c index d3c91a94..efeb8cbf 100644 --- a/protocols/oscar/msgcookie.c +++ b/protocols/oscar/msgcookie.c @@ -130,21 +130,6 @@ aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const guint8 *cookie, int return NULL; } -#if 0 /* debugging feature */ -int aim_dumpcookie(aim_msgcookie_t *cookie) -{ - - if (!cookie) - return -EINVAL; - - printf("\tCookie at %p: %d/%s with %p, next %p\n", - cookie, cookie->type, cookie->cookie, - cookie->data, cookie->next); - - return 0; -} -#endif - /** * aim_cookie_free - free an aim_msgcookie_t struct * @sess: session to remove the cookie from -- cgit v1.2.3 From 94d52d64c1ad3d55f210e1fc8e6345d54c4e46d5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 11:00:15 +0000 Subject: Added charset checks on incoming msgs (from the IRC side) to prevent possible crashes/other odd behaviour in IM modules (or a GLib function that crashes on non-UTF-8 strings). --- irc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/irc.c b/irc.c index 5531addb..01d4c47e 100644 --- a/irc.c +++ b/irc.c @@ -319,11 +319,22 @@ void irc_process( irc_t *irc ) break; } - if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) + if( ( cs = set_getstr( &irc->set, "charset" ) ) ) { conv[IRC_MAX_LINE] = 0; - if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) != -1 ) - lines[i] = conv; + if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) + { + if( irc->status & USTATUS_LOGGED_IN ) + irc_usermsg( irc, "ERROR: Charset mismatch detected. The charset " + "setting is currently set to %s, so please make " + "sure your IRC client will send and accept text in " + "that charset, or tell BitlBee which charset to " + "expect by changing the charset setting. See " + "`help set charset' for more information. Your " + "message was ignored.", cs ); + *conv = 0; + } + lines[i] = conv; } if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) -- cgit v1.2.3 From 4306d8b066d335cb6667414bdd6c5b2e78ccbfd5 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 16:43:57 +0000 Subject: Removed retarded printf() (ARGH) and moved the event handling handling of IQ packets to jabber_util so I can reuse it for certain presence packets. --- protocols/jabber/iq.c | 19 +------------------ protocols/jabber/jabber.c | 2 -- protocols/jabber/jabber.h | 1 + protocols/jabber/jabber_util.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 595718fb..3dae39f6 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -30,7 +30,6 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) { struct im_connection *ic = data; - struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *type, *s; int st, pack = 1; @@ -46,23 +45,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) { - struct jabber_cache_entry *entry; - - if( ( s = xt_find_attr( node, "id" ) ) == NULL || - strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 ) - { - /* Silently ignore it, without an ID (or a non-cache - ID) we don't know how to handle the packet and we - probably don't have to. */ - return XT_HANDLED; - } - - entry = g_hash_table_lookup( jd->node_cache, s ); - - if( entry == NULL ) - imcb_log( ic, "WARNING: Received IQ-%s packet with unknown/expired ID %s!", type, s ); - else if( entry->func ) - return entry->func( ic, node, entry->node ); + return jabber_cache_handle_packet( ic, node ); } else if( strcmp( type, "get" ) == 0 ) { diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b0651a59..6ee10a38 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -225,8 +225,6 @@ static void jabber_generate_id_hash( struct jabber_data *jd ) s = base64_encode( binbuf, 9 ); jd->cached_id_prefix = g_strdup_printf( "%s%s", JABBER_CACHED_ID, s ); g_free( s ); - - printf( "%s\n", jd->cached_id_prefix ); } static void jabber_logout( struct im_connection *ic ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index fc9d2fc4..bee5cb73 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -184,6 +184,7 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); void jabber_cache_entry_free( gpointer entry ); void jabber_cache_clean( struct im_connection *ic ); +xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ); const struct jabber_away_state *jabber_away_state_by_code( char *code ); const struct jabber_away_state *jabber_away_state_by_name( char *name ); void jabber_buddy_ask( struct im_connection *ic, char *handle ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 43b91fe3..453e5930 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -180,6 +180,36 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullp } } +xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ) +{ + struct jabber_data *jd = ic->proto_data; + struct jabber_cache_entry *entry; + char *s; + + if( ( s = xt_find_attr( node, "id" ) ) == NULL || + strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 ) + { + /* Silently ignore it, without an ID (or a non-cache + ID) we don't know how to handle the packet and we + probably don't have to. */ + return XT_HANDLED; + } + + entry = g_hash_table_lookup( jd->node_cache, s ); + + if( entry == NULL ) + { + imcb_log( ic, "WARNING: Received %s-%s packet with unknown/expired ID %s!", + node->name, xt_find_attr( node, "type" ) ? : "(no type)", s ); + } + else if( entry->func ) + { + return entry->func( ic, node, entry->node ); + } + + return XT_HANDLED; +} + const struct jabber_away_state jabber_away_state_list[] = { { "away", "Away" }, -- cgit v1.2.3 From 911cc4f16e96c1ea9027bb12b024531a4b588038 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 17:24:46 +0000 Subject: Defining DEBUG via CFLAGS so that it'll always be there, even when a file doesn't include config.h. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index b84f3947..15e22623 100755 --- a/configure +++ b/configure @@ -134,7 +134,7 @@ EOF if [ "$debug" = "1" ]; then [ -z "$CFLAGS" ] && CFLAGS=-g echo 'DEBUG=1' >> Makefile.settings - echo '#define DEBUG' >> config.h + CFLAGS="$CFLAGS -DDEBUG" else [ -z "$CFLAGS" ] && CFLAGS="-O2 -fno-strict-aliasing" fi -- cgit v1.2.3 From 5bd21df87b195af211c2280ca00391493a669895 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 17:25:57 +0000 Subject: Handling of presence-error packets (only useful for groupchats now), moved jabber_chat_by_jid() (with the right name) to conference.c, I don't know what it was doing in jabber_util.c. --- protocols/jabber/conference.c | 48 ++++++++++++++++++++++++++++++++++++++---- protocols/jabber/jabber.c | 4 ++-- protocols/jabber/jabber.h | 2 +- protocols/jabber/jabber_util.c | 23 +++++--------------- protocols/jabber/presence.c | 9 ++++---- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 008bbe63..72d7b5d8 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -23,6 +23,8 @@ #include "jabber.h" +static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); + struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ) { struct jabber_chat *jc; @@ -34,14 +36,13 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * node = xt_new_node( "x", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_MUC ); node = jabber_make_packet( "presence", NULL, roomjid, node ); + jabber_cache_add( ic, node, jabber_chat_join_failed ); if( !jabber_write_packet( ic, node ) ) { g_free( roomjid ); - xt_free_node( node ); return NULL; } - xt_free_node( node ); jc = g_new0( struct jabber_chat, 1 ); jc->name = jabber_normalize( room ); @@ -64,6 +65,45 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * return c; } +static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +{ + struct jabber_error *err; + struct jabber_buddy *bud; + char *room; + + room = xt_find_attr( orig, "to" ); + bud = jabber_buddy_by_jid( ic, room, 0 ); + + err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR ); + if( err ) + { + imcb_error( ic, "Error joining groupchat %s: %s%s%s", + bud->bare_jid, err->code, err->text ? ": " : "", + err->text ? err->text : "" ); + jabber_error_free( err ); + } + + if( bud ) + jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); +} + +struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name ) +{ + char *normalized = jabber_normalize( name ); + struct groupchat *ret; + struct jabber_chat *jc; + + for( ret = ic->groupchats; ret; ret = ret->next ) + { + jc = ret->data; + if( strcmp( normalized, jc->name ) == 0 ) + break; + } + g_free( normalized ); + + return ret; +} + void jabber_chat_free( struct groupchat *c ) { struct jabber_chat *jc = c->data; @@ -147,7 +187,7 @@ void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bu struct jabber_chat *jc; char *s; - if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL ) + if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL ) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ @@ -249,7 +289,7 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud return; } - else if( ( chat = jabber_chat_by_name( ic, bud->bare_jid ) ) == NULL ) + else if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL ) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 6ee10a38..817d1487 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -269,7 +269,7 @@ static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) return jabber_write( ic, message, strlen( message ) ); - if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) ) + if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) ) bud = jabber_buddy_by_ext_jid( ic, who, 0 ); else bud = jabber_buddy_by_jid( ic, who, 0 ); @@ -396,7 +396,7 @@ static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room { if( strchr( room, '@' ) == NULL ) imcb_error( ic, "Invalid room name: %s", room ); - else if( jabber_chat_by_name( ic, room ) ) + else if( jabber_chat_by_jid( ic, room ) ) imcb_error( ic, "Already present in chat `%s'", room ); else return jabber_chat_join( ic, room, nick, password ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index bee5cb73..94d017d6 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -207,7 +207,6 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, g struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); -struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ); time_t jabber_get_timestamp( struct xt_node *xt ); struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ); void jabber_error_free( struct jabber_error *err ); @@ -230,6 +229,7 @@ gboolean sasl_supported( struct im_connection *ic ); /* conference.c */ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password ); +struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name ); void jabber_chat_free( struct groupchat *c ); int jabber_chat_msg( struct groupchat *ic, char *message, int flags ); int jabber_chat_topic( struct groupchat *c, char *topic ); diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 453e5930..9d84e099 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -613,23 +613,6 @@ int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ) } } -struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name ) -{ - char *normalized = jabber_normalize( name ); - struct groupchat *ret; - struct jabber_chat *jc; - - for( ret = ic->groupchats; ret; ret = ret->next ) - { - jc = ret->data; - if( strcmp( normalized, jc->name ) == 0 ) - break; - } - g_free( normalized ); - - return ret; -} - time_t jabber_get_timestamp( struct xt_node *xt ) { struct tm tp, utc; @@ -681,10 +664,14 @@ time_t jabber_get_timestamp( struct xt_node *xt ) struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ) { - struct jabber_error *err = g_new0( struct jabber_error, 1 ); + struct jabber_error *err; struct xt_node *c; char *s; + if( node == NULL ) + return NULL; + + err = g_new0( struct jabber_error, 1 ); err->type = xt_find_attr( node, "type" ); for( c = node->children; c; c = c->next ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 5abdc449..c3d7dced 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -39,7 +39,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( s = strchr( from, '/' ) ) ) { *s = 0; - if( jabber_chat_by_name( ic, from ) ) + if( jabber_chat_by_jid( ic, from ) ) is_chat = 1; *s = '/'; } @@ -163,8 +163,10 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) } else if( strcmp( type, "error" ) == 0 ) { - struct jabber_error *err; + return jabber_cache_handle_packet( ic, node ); + /* + struct jabber_error *err; if( ( c = xt_find_node( node->children, "error" ) ) ) { err = jabber_error_parse( c, XMLNS_STANZA_ERROR ); @@ -172,8 +174,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) err->code, err->text ? ": " : "", err->text ? err->text : "" ); jabber_error_free( err ); - } - /* What else to do with it? */ + } */ } return XT_HANDLED; -- cgit v1.2.3 From 80e9db97776bfd6c6192135d65027abd8f50887c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 23:14:49 +0000 Subject: Forgot to return something in jabber_chat_join_failed(). --- protocols/jabber/conference.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 72d7b5d8..c5bc0e68 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -72,7 +72,8 @@ static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_no char *room; room = xt_find_attr( orig, "to" ); - bud = jabber_buddy_by_jid( ic, room, 0 ); + if( ( bud = jabber_buddy_by_jid( ic, room, 0 ) ) ) + jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR ); if( err ) @@ -83,8 +84,7 @@ static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_no jabber_error_free( err ); } - if( bud ) - jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); + return XT_HANDLED; } struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name ) -- cgit v1.2.3 From aaf92a9eb64327892e39fdbd7113d797d1d68cec Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Dec 2007 23:18:25 +0000 Subject: Imported setuid() patch from Simo Leone <simo@archlinux...> with some modifications. Also adding some missing g_free()s to conf.c. --- bitlbee.conf | 7 +++++++ conf.c | 19 ++++++++++++++++++- conf.h | 1 + unix.c | 21 +++++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/bitlbee.conf b/bitlbee.conf index e5e0f7de..d9f878c8 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -19,6 +19,13 @@ ## # RunMode = Inetd +## User: +## +## If BitlBee is started by root as a daemon, it can drop root privileges, +## and change to the specified user. +## +# User = bitlbee + ## DaemonPort/DaemonInterface: ## ## For daemon mode, you can specify on what interface and port the daemon diff --git a/conf.c b/conf.c index 82487ddf..94c673cc 100644 --- a/conf.c +++ b/conf.c @@ -62,6 +62,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->motdfile = g_strdup( ETCDIR "/motd.txt" ); conf->ping_interval = 180; conf->ping_timeout = 300; + conf->user = NULL; proxytype = 0; i = conf_loadini( conf, CONF_FILE ); @@ -75,7 +76,7 @@ conf_t *conf_load( int argc, char *argv[] ) fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE ); } - while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:" ) ) >= 0 ) + while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 ) /* ^^^^ Just to make sure we skip this step from the REHASH handler. */ { if( opt == 'i' ) @@ -131,6 +132,7 @@ conf_t *conf_load( int argc, char *argv[] ) " -I Classic/InetD mode. (Default)\n" " -D Daemon mode. (Still EXPERIMENTAL!)\n" " -F Forking daemon. (one process per client)\n" + " -u Run daemon as specified user.\n" " -P Specify PID-file (not for inetd mode)\n" " -i Specify the interface (by IP address) to listen on.\n" " (Default: 0.0.0.0 (any interface))\n" @@ -150,6 +152,11 @@ conf_t *conf_load( int argc, char *argv[] ) mode anyway!) */ ipc_master_set_statefile( optarg ); } + else if( opt == 'u' ) + { + g_free( conf->user ); + conf->user = g_strdup( optarg ); + } } if( conf->configdir[strlen(conf->configdir)-1] != '/' ) @@ -191,10 +198,12 @@ static int conf_loadini( conf_t *conf, char *file ) } else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 ) { + g_free( conf->iface ); conf->iface = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "daemonport" ) == 0 ) { + g_free( conf->port ); conf->port = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "authmode" ) == 0 ) @@ -208,14 +217,17 @@ static int conf_loadini( conf_t *conf, char *file ) } else if( g_strcasecmp( ini->key, "authpassword" ) == 0 ) { + g_free( conf->auth_pass ); conf->auth_pass = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "operpassword" ) == 0 ) { + g_free( conf->oper_pass ); conf->oper_pass = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "hostname" ) == 0 ) { + g_free( conf->hostname ); conf->hostname = g_strdup( ini->value ); } else if( g_strcasecmp( ini->key, "configdir" ) == 0 ) @@ -280,6 +292,11 @@ static int conf_loadini( conf_t *conf, char *file ) g_free( url ); } + else if( g_strcasecmp( ini->key, "user" ) == 0 ) + { + g_free( conf->user ); + conf->user = g_strdup( ini->value ); + } else { fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key ); diff --git a/conf.h b/conf.h index 5138ce11..d21ec577 100644 --- a/conf.h +++ b/conf.h @@ -48,6 +48,7 @@ typedef struct conf char **migrate_storage; int ping_interval; int ping_timeout; + char *user; } conf_t; G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] ); diff --git a/unix.c b/unix.c index 0abf43ea..75ffcf95 100644 --- a/unix.c +++ b/unix.c @@ -33,6 +33,7 @@ #include <unistd.h> #include <sys/time.h> #include <sys/wait.h> +#include <pwd.h> global_t global; /* Against global namespace pollution */ @@ -44,8 +45,6 @@ int main( int argc, char *argv[], char **envp ) char *old_cwd = NULL; struct sigaction sig, old; - memset( &global, 0, sizeof( global_t ) ); - log_init(); CONF_FILE = g_strdup( CONF_FILE_DEF ); global.conf = conf_load( argc, argv ); @@ -86,12 +85,26 @@ int main( int argc, char *argv[], char **envp ) if( i != 0 ) return( i ); + if( ( global.conf->user && *global.conf->user ) && + ( global.conf->runmode == RUNMODE_DAEMON || + global.conf->runmode == RUNMODE_FORKDAEMON ) && + ( !getuid() || !geteuid() ) ) + { + struct passwd *pw = NULL; + pw = getpwnam( global.conf->user ); + if( pw ) + { + setgid( pw->pw_gid ); + setuid( pw->pw_uid ); + } + } + global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage ); - if ( global.storage == NULL) { + if( global.storage == NULL ) + { log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage ); return( 1 ); } - /* Catch some signals to tell the user what's happening before quitting */ memset( &sig, 0, sizeof( sig ) ); -- cgit v1.2.3 From de0337481fca3894c406a2724da30af8cc8bae2f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Tue, 4 Dec 2007 22:59:59 +0000 Subject: Fixing jabber_login/_logout for better (non-crashing) cleanup on early connect failure. --- protocols/jabber/jabber.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 817d1487..e2a3a27a 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -76,6 +76,8 @@ static void jabber_login( account_t *acc ) jd->username = g_strdup( acc->user ); jd->server = strchr( jd->username, '@' ); + jd->fd = jd->r_inpa = jd->w_inpa = -1; + if( jd->server == NULL ) { imcb_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); @@ -231,7 +233,8 @@ static void jabber_logout( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; - jabber_end_stream( ic ); + if( jd->fd >= 0 ) + jabber_end_stream( ic ); while( ic->groupchats ) jabber_chat_free( ic->groupchats ); @@ -249,7 +252,8 @@ static void jabber_logout( struct im_connection *ic ) if( jd->tx_len ) g_free( jd->txq ); - g_hash_table_destroy( jd->node_cache ); + if( jd->node_cache ) + g_hash_table_destroy( jd->node_cache ); xt_free( jd->xt ); -- cgit v1.2.3 From c058ff976bbbbf43ef11c262f21440e61244f73e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 9 Dec 2007 23:19:35 +0000 Subject: Added /invite support for Jabber chatrooms (and fixed the argument order to chat_invite). --- irc_commands.c | 2 +- protocols/jabber/conference.c | 21 +++++++++++++++++++++ protocols/jabber/jabber.c | 16 +++++++++++++++- protocols/jabber/jabber.h | 1 + protocols/msn/msn.c | 2 +- protocols/oscar/oscar.c | 2 +- protocols/yahoo/yahoo.c | 2 +- 7 files changed, 41 insertions(+), 5 deletions(-) diff --git a/irc_commands.c b/irc_commands.c index 287a126f..65f0d6c6 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -206,7 +206,7 @@ static void irc_cmd_invite( irc_t *irc, char **cmd ) if( u && c && ( u->ic == c->ic ) ) if( c->ic && c->ic->acc->prpl->chat_invite ) { - c->ic->acc->prpl->chat_invite( c, "", u->handle ); + c->ic->acc->prpl->chat_invite( c, u->handle, NULL ); irc_reply( irc, 341, "%s %s", nick, channel ); return; } diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index c5bc0e68..074412ec 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -175,6 +175,27 @@ int jabber_chat_leave( struct groupchat *c, const char *reason ) return 1; } +void jabber_chat_invite( struct groupchat *c, char *who, char *message ) +{ + struct xt_node *node; + struct im_connection *ic = c->ic; + struct jabber_chat *jc = c->data; + + node = xt_new_node( "reason", message, NULL ); + + node = xt_new_node( "invite", NULL, node ); + xt_add_attr( node, "to", who ); + + node = xt_new_node( "x", NULL, node ); + xt_add_attr( node, "xmlns", XMLNS_MUC_USER ); + + node = jabber_make_packet( "message", NULL, jc->name, node ); + + jabber_write_packet( ic, node ); + + xt_free_node( node ); +} + /* Not really the same syntax as the normal pkt_ functions, but this isn't called by the xmltree parser directly and this way I can add some extra parameters so we won't have to repeat too many things done by the caller diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e2a3a27a..4c89ab5c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -426,6 +426,20 @@ static void jabber_chat_leave_( struct groupchat *c ) jabber_chat_leave( c, NULL ); } +static void jabber_chat_invite_( struct groupchat *c, char *who, char *msg ) +{ + struct jabber_chat *jc = c->data; + gchar *msg_alt = NULL; + + if( msg == NULL ) + msg_alt = g_strdup_printf( "%s invited you to %s", c->ic->acc->user, jc->name ); + + if( c && who ) + jabber_chat_invite( c, who, msg ? msg : msg_alt ); + + g_free( msg_alt ); +} + static void jabber_keepalive( struct im_connection *ic ) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ @@ -497,7 +511,7 @@ void jabber_initmodule() ret->remove_buddy = jabber_remove_buddy; ret->chat_msg = jabber_chat_msg_; ret->chat_topic = jabber_chat_topic_; -// ret->chat_invite = jabber_chat_invite; + ret->chat_invite = jabber_chat_invite_; ret->chat_leave = jabber_chat_leave_; ret->chat_join = jabber_chat_join_; ret->keepalive = jabber_keepalive; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 94d017d6..56056534 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -236,5 +236,6 @@ int jabber_chat_topic( struct groupchat *c, char *topic ); int jabber_chat_leave( struct groupchat *c, const char *reason ); void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); +void jabber_chat_invite( struct groupchat *c, char *who, char *message ); #endif diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index df04e30d..aa05dbdd 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -240,7 +240,7 @@ static void msn_chat_msg( struct groupchat *c, char *message, int flags ) already severely broken) disappeared here! */ } -static void msn_chat_invite( struct groupchat *c, char *msg, char *who ) +static void msn_chat_invite( struct groupchat *c, char *who, char *message ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); char buf[1024]; diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 96983738..8d45acf0 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2508,7 +2508,7 @@ void oscar_chat_msg(struct groupchat *c, char *message, int msgflags) /* return (ret >= 0); */ } -void oscar_chat_invite(struct groupchat *c, char *message, char *who) +void oscar_chat_invite(struct groupchat *c, char *who, char *message) { struct im_connection *ic = c->ic; struct oscar_data * od = (struct oscar_data *)ic->proto_data; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 28a72877..625f3d1c 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -305,7 +305,7 @@ static void byahoo_chat_msg( struct groupchat *c, char *message, int flags ) yahoo_conference_message( yd->y2_id, NULL, c->data, c->title, message, 1 ); } -static void byahoo_chat_invite( struct groupchat *c, char *msg, char *who ) +static void byahoo_chat_invite( struct groupchat *c, char *who, char *msg ) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; -- cgit v1.2.3 From 3f2bc2d721c1ac3d6c11a88a350041c2166f71e7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 9 Dec 2007 23:23:03 +0000 Subject: If I keep forgetting to credit people in commit msgs I should probably add them to doc/CREDITS. Shouldn't be using bzr uncommit all the time. ;-( --- doc/CREDITS | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/CREDITS b/doc/CREDITS index f805c251..d53f6de0 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -54,6 +54,7 @@ The authors thank the following people: - Ed Schouten, for reporting bugs. - Greg (gropeep.org), for updating the Yahoo! module to fix some issues that were there for quite some time already. +- misc@mandriva.org for lots of Jabber contributions. - And all other users who help us by sending useful bug reports, positive feedback, nice patches and cool addons. Mentioning you all would make -- cgit v1.2.3 From 71dc8543dc4eeafabbe28bae52ec1d05ce9f5fea Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 10 Dec 2007 22:33:08 +0000 Subject: Fixed "set xxx" syntax (it showed all settings instead of just xxx). --- root_commands.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/root_commands.c b/root_commands.c index 642f5374..2a5938e7 100644 --- a/root_commands.c +++ b/root_commands.c @@ -402,9 +402,7 @@ static void cmd_account( irc_t *irc, char **cmd ) return; } - if( ( strcmp( cmd[3], "=" ) ) == 0 && cmd[4] ) - irc_usermsg( irc, "Warning: Correct syntax: \002account set <variable> <value>\002 (without =)" ); - else if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 ) + if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 ) set_reset( &a->set, set_name ); else set_setstr( &a->set, set_name, cmd[3] ); @@ -744,16 +742,11 @@ static void cmd_yesno( irc_t *irc, char **cmd ) static void cmd_set( irc_t *irc, char **cmd ) { - char *set_name = NULL; + char *set_name = cmd[1]; if( cmd[1] && cmd[2] ) { - if( ( strcmp( cmd[2], "=" ) ) == 0 && cmd[3] ) - { - irc_usermsg( irc, "Warning: Correct syntax: \002set <variable> <value>\002 (without =)" ); - return; - } - else if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 ) + if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 ) { set_reset( &irc->set, cmd[2] ); set_name = cmd[2]; @@ -761,7 +754,6 @@ static void cmd_set( irc_t *irc, char **cmd ) else { set_setstr( &irc->set, cmd[1], cmd[2] ); - set_name = cmd[1]; } } if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ -- cgit v1.2.3 From 0f47613a39ad1b5d22d187e63c80c2f70702c217 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 10 Dec 2007 22:57:13 +0000 Subject: Don't allow nicks that start with a number. --- nick.c | 19 ++++++++++++++----- tests/check_nick.c | 12 +++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/nick.c b/nick.c index 88c3faea..4b05f4a7 100644 --- a/nick.c +++ b/nick.c @@ -153,10 +153,10 @@ void nick_del( account_t *acc, const char *handle ) /* Character maps, _lc_[x] == _uc_[x] (but uppercase), according to the RFC's. With one difference, we allow dashes. */ -static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^-_|"; -static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~-_\\"; +static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^`-_|"; +static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~`-_\\"; -void nick_strip( char * nick ) +void nick_strip( char *nick ) { int i, j; @@ -169,6 +169,15 @@ void nick_strip( char * nick ) j++; } } + if( isdigit( nick[0] ) ) + { + char *orig; + + orig = g_strdup( nick ); + g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig ); + g_free( orig ); + j ++; + } while( j <= MAX_NICK_LENGTH ) nick[j++] = '\0'; } @@ -177,8 +186,8 @@ int nick_ok( const char *nick ) { const char *s; - /* Empty/long nicks are not allowed */ - if( !*nick || strlen( nick ) > MAX_NICK_LENGTH ) + /* Empty/long nicks are not allowed, nor numbers at [0] */ + if( !*nick || isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH ) return( 0 ); for( s = nick; *s; s ++ ) diff --git a/tests/check_nick.c b/tests/check_nick.c index 714c4fdc..6c4267cd 100644 --- a/tests/check_nick.c +++ b/tests/check_nick.c @@ -14,11 +14,17 @@ START_TEST(test_nick_strip) "thisisaveryveryveryverylongnick", "thisisave:ryveryveryverylongnick", "t::::est", + "test123", + "123test", + "123", NULL }; const char *expected[] = { "test", "test", "test", "thisisaveryveryveryveryl", "thisisaveryveryveryveryl", "test", + "test123", + "_123test", + "_123", NULL }; for (i = 0; get[i]; i++) { @@ -34,8 +40,8 @@ END_TEST START_TEST(test_nick_ok_ok) { - const char *nicks[] = { "foo", "bar", "bla[", "blie]", - "BreEZaH", "\\od^~", NULL }; + const char *nicks[] = { "foo", "bar123", "bla[", "blie]", "BreEZaH", + "\\od^~", "_123", "_123test", NULL }; int i; for (i = 0; nicks[i]; i++) { @@ -48,7 +54,7 @@ END_TEST START_TEST(test_nick_ok_notok) { const char *nicks[] = { "thisisaveryveryveryveryveryveryverylongnick", - "\nillegalchar", "", "nick%", NULL }; + "\nillegalchar", "", "nick%", "123test", NULL }; int i; for (i = 0; nicks[i]; i++) { -- cgit v1.2.3 From d52111a7b05657e4a4fa8417e6655389a50769cf Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 12 Dec 2007 21:36:33 +0000 Subject: Fixed sockerr_again() usage in Jabber module to (hopefully) fix a 100% CPU usage bug. --- lib/misc.c | 10 ++++++++++ lib/misc.h | 2 ++ protocols/jabber/io.c | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index c977029f..d6795ec9 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -44,6 +44,8 @@ #include <resolv.h> #endif +#include "ssl_client.h" + void strip_linefeed(gchar *text) { int i, j; @@ -590,3 +592,11 @@ char *word_wrap( char *msg, int line_len ) return g_string_free( ret, FALSE ); } + +gboolean ssl_sockerr_again( void *ssl ) +{ + if( ssl ) + return ssl_errno == SSL_AGAIN; + else + return sockerr_again(); +} diff --git a/lib/misc.h b/lib/misc.h index 1d76f7f2..e0468d73 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -65,4 +65,6 @@ G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, G_MODULE_EXPORT char *word_wrap( char *msg, int line_len ); +G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl ); + #endif diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 61cd142e..29561b86 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -119,7 +119,7 @@ static gboolean jabber_write_queue( struct im_connection *ic ) return TRUE; } - else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) { /* Set fd to -1 to make sure we won't write to it anymore. */ closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ @@ -230,7 +230,7 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition } } } - else if( st == 0 || ( st < 0 && !sockerr_again() ) ) + else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) { closesocket( jd->fd ); jd->fd = -1; -- cgit v1.2.3 From 30ce1ced040c44c528d0a6e6e9c6b10a1caf1052 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 12 Dec 2007 23:30:51 +0000 Subject: Killed the <server> parameter to "account add" and changed the default server for OSCAR to what both login.icq.com and login.oscar.aol.com resolve to these days. There's no need to specify a server anymore so why bother. And cleaned up the docs (removed all references to those OSCAR servers). --- account.c | 7 ++++++- doc/user-guide/commands.xml | 12 ++++++------ doc/user-guide/quickstart.xml | 4 ++-- protocols/oscar/aim.h | 2 +- protocols/oscar/oscar.c | 26 ++++---------------------- root_commands.c | 8 ++++++-- 6 files changed, 25 insertions(+), 34 deletions(-) diff --git a/account.c b/account.c index 388d04d0..4eb78faa 100644 --- a/account.c +++ b/account.c @@ -94,10 +94,15 @@ char *set_eval_account( set_t *set, char *value ) { g_free( acc->server ); if( *value ) + { acc->server = g_strdup( value ); + return value; + } else + { acc->server = NULL; - return value; + return g_strdup( set->def ); + } } else if( strcmp( set->key, "auto_connect" ) == 0 ) { diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index ac9bdf11..b4efd967 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -16,7 +16,7 @@ </description> <bitlbee-command name="add"> - <syntax>account add <protocol> <username> <password> [<server>]</syntax> + <syntax>account add <protocol> <username> <password></syntax> <description> <para> @@ -25,7 +25,7 @@ </description> <bitlbee-command name="jabber"> - <syntax>account add jabber <handle@server.tld> <password> [<servertag>]</syntax> + <syntax>account add jabber <handle@server.tld> <password></syntax> <description> <para> @@ -49,16 +49,16 @@ </bitlbee-command> <bitlbee-command name="oscar"> - <syntax>account add oscar <handle> <password> [<servername>]</syntax> + <syntax>account add oscar <handle> <password></syntax> <description> <para> - Specifying a server is required for OSCAR, since OSCAR can be used for both ICQ- and AIM-connections. Although these days it's supposed to be possible to connect to ICQ via AIM-servers and vice versa, we like to stick with this separation for now. For ICQ connections, the servername is <emphasis>login.icq.com</emphasis>, for AIM connections it's <emphasis>login.oscar.aol.com</emphasis>. + OSCAR is the protocol used to connect to AIM and/or ICQ. The servers will automatically detect if you're using a numeric or non-numeric username so there's no need to tell which network you want to connect to. </para> </description> <ircexample> - <ircline nick="wilmer">account add oscar 72696705 hobbelmeeuw login.icq.com</ircline> + <ircline nick="wilmer">account add oscar 72696705 hobbelmeeuw</ircline> <ircline nick="root">Account successfully added</ircline> </ircexample> </bitlbee-command> @@ -594,7 +594,7 @@ <bitlbee-setting name="server" type="string" scope="account"> <description> <para> - Can be set for Jabber- and OSCAR-connections. For OSCAR, this must be set to <emphasis>login.icq.com</emphasis> if it's an ICQ connection, or <emphasis>login.oscar.aol.com</emphasis> if it's an AIM connection. For Jabber, you have to set this if the servername isn't equal to the part after the @ in the Jabber handle. + Can be set for Jabber- and OSCAR-connections. For Jabber, you might have to set this if the servername isn't equal to the part after the @ in the Jabber handle. For OSCAR this shouldn't be necessary anymore in recent BitlBee versions. </para> </description> </bitlbee-setting> diff --git a/doc/user-guide/quickstart.xml b/doc/user-guide/quickstart.xml index 520f240f..fcb06c6b 100644 --- a/doc/user-guide/quickstart.xml +++ b/doc/user-guide/quickstart.xml @@ -37,12 +37,12 @@ For instance, suppose you have an ICQ account with UIN <emphasis>72696705</empha </para> <ircexample> - <ircline nick="you">account add oscar 72696705 QuickStart login.icq.com</ircline> + <ircline nick="you">account add jabber bitlbee@jabber.org QuickStart</ircline> <ircline nick="root">Account successfully added</ircline> </ircexample> <para> -Other available IM protocols are jabber, msn, and yahoo. Oscar is the protocol used by ICQ and AOL. For oscar, you need to specify the IM-server as a fourth argument (for msn and yahoo there is no fourth argument). For AOL Instant Messenger, the server name is <emphasis>login.oscar.aol.com</emphasis>. For ICQ, the server name is <emphasis>login.icq.com</emphasis>. +Other available IM protocols are msn, oscar, and yahoo. Oscar is the protocol used by ICQ and AOL. </para> <para> diff --git a/protocols/oscar/aim.h b/protocols/oscar/aim.h index 81ea5f9e..9516996c 100644 --- a/protocols/oscar/aim.h +++ b/protocols/oscar/aim.h @@ -93,7 +93,7 @@ typedef guint16 flap_seqnum_t; * the client to connect to it. * */ -#define AIM_DEFAULT_LOGIN_SERVER "login.oscar.aol.com" +#define AIM_DEFAULT_LOGIN_SERVER "login.messaging.aol.com" #define AIM_LOGIN_PORT 5190 /* diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 8d45acf0..c4683046 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -340,7 +340,7 @@ static void oscar_init(account_t *acc) { set_t *s; - s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); + s = set_add( &acc->set, "server", AIM_DEFAULT_LOGIN_SERVER, set_eval_account, acc ); s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; if (isdigit(acc->user[0])) { @@ -355,15 +355,7 @@ static void oscar_login(account_t *acc) { struct im_connection *ic = imcb_new(acc); struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); - if (isdigit(acc->user[0])) { - odata->icq = TRUE; - /* This is odd but it's necessary for a proper do_import and do_export. - We don't do those anymore, but let's stick with it, just in case - it accidentally fixes something else too... </bitlbee> */ - /* ic->acc->pass[8] = 0; - Not touching this anymore now that it belongs to account_t! - Let's hope nothing will break. ;-) */ - } else { + if (!isdigit(acc->user[0])) { ic->flags |= OPT_DOES_HTML; } @@ -384,24 +376,14 @@ static void oscar_login(account_t *acc) { return; } - if (acc->server == NULL) { - imcb_error(ic, "No servername specified"); - imc_logout(ic, FALSE); - return; - } - - if (g_strcasecmp(acc->server, "login.icq.com") != 0 && - g_strcasecmp(acc->server, "login.oscar.aol.com") != 0) { - imcb_log(ic, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",acc->server); - } - imcb_log(ic, _("Signon: %s"), ic->acc->user); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); conn->status |= AIM_CONN_STATUS_INPROGRESS; - conn->fd = proxy_connect(acc->server, AIM_LOGIN_PORT, oscar_login_connect, ic); + conn->fd = proxy_connect(set_getstr(&acc->set, "server"), + AIM_LOGIN_PORT, oscar_login_connect, ic); if (conn->fd < 0) { imcb_error(ic, _("Couldn't connect to host")); imc_logout(ic, TRUE); diff --git a/root_commands.c b/root_commands.c index 2a5938e7..dc70feb4 100644 --- a/root_commands.c +++ b/root_commands.c @@ -198,7 +198,7 @@ static void cmd_drop( irc_t *irc, char **cmd ) irc_usermsg( irc, "Account `%s' removed", irc->nick ); break; default: - irc_usermsg( irc, "Error: '%d'", status ); + irc_usermsg( irc, "Error: `%d'", status ); break; } } @@ -233,7 +233,11 @@ static void cmd_account( irc_t *irc, char **cmd ) a = account_add( irc, prpl, cmd[3], cmd[4] ); if( cmd[5] ) + { + irc_usermsg( irc, "Warning: Passing a servername/other flags to `account add' " + "is now deprecated. Use `account set' instead." ); set_setstr( &a->set, "server", cmd[5] ); + } irc_usermsg( irc, "Account successfully added" ); } @@ -316,7 +320,7 @@ static void cmd_account( irc_t *irc, char **cmd ) } else { - irc_usermsg( irc, "No accounts known. Use 'account add' to add one." ); + irc_usermsg( irc, "No accounts known. Use `account add' to add one." ); } } } -- cgit v1.2.3 From 3e79889dceeac1432156dc5fb6ae4a1f20b86d69 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 12 Dec 2007 23:57:49 +0000 Subject: Checking conn->xcred before trying to clean it up since GnuTLS doesn't seem to check for NULL pointers here. (Closes #257) --- lib/ssl_gnutls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index 221a2862..b964ab49 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -222,8 +222,10 @@ void ssl_disconnect( void *conn_ ) closesocket( conn->fd ); - gnutls_deinit( conn->session ); - gnutls_certificate_free_credentials( conn->xcred ); + if( conn->session ) + gnutls_deinit( conn->session ); + if( conn->xcred ) + gnutls_certificate_free_credentials( conn->xcred ); g_free( conn ); } -- cgit v1.2.3 From 529078a3e7f701c7b85201380b2d2097ac676ec6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 16 Dec 2007 16:35:38 +0000 Subject: Implemented XEP-0199 (patch from misc@mandriva.org). --- protocols/jabber/iq.c | 12 +++++++++++- protocols/jabber/jabber.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 3dae39f6..069e3af3 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -49,7 +49,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( type, "get" ) == 0 ) { - if( !( c = xt_find_node( node->children, "query" ) ) || + if( !( ( c = xt_find_node( node->children, "query" ) ) || + ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just <query/> ????? */ !( s = xt_find_attr( c, "xmlns" ) ) ) { imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); @@ -80,12 +81,21 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); } + else if( strcmp( s, XMLNS_PING ) == 0 ) + { + xt_free_node( reply ); + reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), NULL ); + if( ( s = xt_find_attr( node, "id" ) ) ) + xt_add_attr( reply, "id", s ); + pack = 0; + } else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { const char *features[] = { XMLNS_VERSION, XMLNS_TIME, XMLNS_CHATSTATES, XMLNS_MUC, + XMLNS_PING, NULL }; const char **f; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 56056534..f673ee0d 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -151,6 +151,7 @@ struct jabber_chat #define XMLNS_AUTH "jabber:iq:auth" /* XEP-0078 */ #define XMLNS_VERSION "jabber:iq:version" /* XEP-0092 */ #define XMLNS_TIME "jabber:iq:time" /* XEP-0090 */ +#define XMLNS_PING "urn:xmpp:ping" /* XEP-0199 */ #define XMLNS_VCARD "vcard-temp" /* XEP-0054 */ #define XMLNS_DELAY "jabber:x:delay" /* XEP-0091 */ #define XMLNS_CHATSTATES "http://jabber.org/protocol/chatstates" /* 0085 */ -- cgit v1.2.3 From fb4ebcc5e3cffc4683cd3f38d7aba6cd86dbcd50 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 28 Dec 2007 23:26:44 +0000 Subject: Added missing return in jabber_login(). --- protocols/jabber/jabber.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 4c89ab5c..264a0308 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -196,6 +196,8 @@ static void jabber_login( account_t *acc ) { imcb_error( ic, "Could not connect to server" ); imc_logout( ic, TRUE ); + + return; } if( set_getbool( &acc->set, "xmlconsole" ) ) -- cgit v1.2.3 From 6f7ac174bb8fbde5e07e1c7da3cf691ecb4e172b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 28 Dec 2007 23:27:45 +0000 Subject: Fixed return value check in proxy_connect(), since on some systems a non-blocking connect() can return immediately (when connecting to localhost, for example). Closes bug #233 and #340. --- lib/proxy.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/proxy.c b/lib/proxy.c index dff5d0a4..0e1c8f07 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -129,18 +129,17 @@ static int proxy_connect_none(const char *host, unsigned short port, struct PHB event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); - if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) { - if (sockerr_again()) { - phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); - phb->fd = fd; - } else { - closesocket(fd); - g_free(phb); - return -1; - } + if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) { + closesocket(fd); + g_free(phb); + + return -1; + } else { + phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb); + phb->fd = fd; + + return fd; } - - return fd; } -- cgit v1.2.3 From debc281b8f35015c0491c3a34465f82289a0e919 Mon Sep 17 00:00:00 2001 From: Miklos Vajna <vmiklos@frugalware.org> Date: Mon, 31 Dec 2007 00:40:59 +0100 Subject: encode: md5.c is no longer in protocols/, it's in lib/ Fix build failure. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a9dd2e17..0a988feb 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ ifndef DEBUG endif encode: crypting.c - $(CC) crypting.c protocols/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS) + $(CC) crypting.c lib/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS) decode: encode cp encode decode -- cgit v1.2.3 From f394500c46003237373a47c5a1dcb4af16029e4d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 5 Jan 2008 15:00:15 +0000 Subject: Removed closure->result. I was planning to add some more stuff, but will do that later. --- lib/events_glib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/events_glib.c b/lib/events_glib.c index 38938380..1198dba6 100644 --- a/lib/events_glib.c +++ b/lib/events_glib.c @@ -47,7 +47,6 @@ typedef struct _GaimIOClosure { b_event_handler function; - guint result; gpointer data; } GaimIOClosure; @@ -100,6 +99,7 @@ gint b_input_add(gint source, b_input_condition condition, b_event_handler funct GaimIOClosure *closure = g_new0(GaimIOClosure, 1); GIOChannel *channel; GIOCondition cond = 0; + int st; closure->function = function; closure->data = data; @@ -110,13 +110,13 @@ gint b_input_add(gint source, b_input_condition condition, b_event_handler funct cond |= GAIM_WRITE_COND; channel = g_io_channel_unix_new(source); - closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, - gaim_io_invoke, closure, gaim_io_destroy); + st = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, + gaim_io_invoke, closure, gaim_io_destroy); - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure ); + event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (%p)\n", source, condition, function, data, st, closure ); g_io_channel_unref(channel); - return closure->result; + return st; } gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) -- cgit v1.2.3 From 3585c5aa1770147dd4a75a5283793d7908573011 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 5 Jan 2008 19:03:02 +0000 Subject: Added handling of MSN switchboard NAK messages. Untested, but hey, it compiles! (And it's pretty trivial...) --- protocols/msn/sb.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index cb9e2cab..557f4f16 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -490,6 +490,17 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } } + else if( strcmp( cmd[0], "NAK" ) == 0 ) + { + if( sb->who ) + { + imcb_log( ic, "The MSN servers could not deliver one of your messages to %s.", sb->who ); + } + else + { + imcb_log( ic, "The MSN servers could not deliver one of your groupchat messages to all participants." ); + } + } else if( strcmp( cmd[0], "BYE" ) == 0 ) { if( num_parts < 2 ) -- cgit v1.2.3 From 1febf5c93b231942cd9cac8ac6a5a0d830c581cc Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 5 Jan 2008 21:15:32 +0000 Subject: Added "mail_notifications" setting. Who needs those notifications anyway? Closes: #338. --- doc/user-guide/commands.xml | 11 +++++++++++ protocols/msn/msn.c | 2 ++ protocols/msn/ns.c | 4 ++-- protocols/yahoo/yahoo.c | 10 +++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index b4efd967..5a1e398c 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -474,6 +474,17 @@ </bitlbee-setting> + <bitlbee-setting name="mail_notifications" type="boolean" scope="account"> + <default>false</default> + + <description> + <para> + Some protocols (MSN, Yahoo!) can notify via IM about new e-mail. Since most people use their Hotmail/Yahoo! addresses as a spam-box, this is disabled default. If you want these notifications, you can enable this setting. + </para> + </description> + + </bitlbee-setting> + <bitlbee-setting name="ops" type="string" scope="global"> <default>both</default> <possible-values>both, root, user, none</possible-values> diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index aa05dbdd..192dda0a 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -34,6 +34,8 @@ static void msn_init( account_t *acc ) s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc ); s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; + + s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); } static void msn_login( account_t *acc ) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 9bd7f152..3735aad6 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -642,7 +642,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int char *inbox = msn_findheader( body, "Inbox-Unread:", blen ); char *folders = msn_findheader( body, "Folders-Unread:", blen ); - if( inbox && folders ) + if( inbox && folders && set_getbool( &ic->acc->set, "mail_notifications" ) ) { imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); } @@ -652,7 +652,7 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int char *from = msn_findheader( body, "From-Addr:", blen ); char *fromname = msn_findheader( body, "From:", blen ); - if( from && fromname ) + if( from && fromname && set_getbool( &ic->acc->set, "mail_notifications" ) ) { imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 625f3d1c..d413597a 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -126,6 +126,11 @@ static char *byahoo_strip( const char *in ) return( g_strndup( in, len ) ); } +static void byahoo_init( account_t *acc ) +{ + set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); +} + static void byahoo_login( account_t *acc ) { struct im_connection *ic = imcb_new( acc ); @@ -348,6 +353,7 @@ void byahoo_initmodule( ) { struct prpl *ret = g_new0(struct prpl, 1); ret->name = "yahoo"; + ret->init = byahoo_init; ret->login = byahoo_login; ret->keepalive = byahoo_keepalive; @@ -922,7 +928,9 @@ void ext_yahoo_mail_notify( int id, const char *from, const char *subj, int cnt { struct im_connection *ic = byahoo_get_ic_by_id( id ); - if( from && subj ) + if( !set_getbool( &ic->acc->set, "mail_notifications" ) ) + ; /* The user doesn't care. */ + else if( from && subj ) imcb_log( ic, "Received e-mail message from %s with subject `%s'", from, subj ); else if( cnt > 0 ) imcb_log( ic, "Received %d new e-mails", cnt ); -- cgit v1.2.3 From 46dca11bfad72bb9365b85b433f1e812733f31ec Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 6 Jan 2008 12:32:27 +0000 Subject: Changed warning message about unsent MSN messages. It should show the actual message(s) now. --- protocols/msn/msn.c | 16 +--------------- protocols/msn/msn.h | 1 + protocols/msn/msn_util.c | 34 ++++++++++++++++++++++++++++++++++ protocols/msn/sb.c | 41 ++++++----------------------------------- 4 files changed, 42 insertions(+), 50 deletions(-) diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 192dda0a..a2e8519a 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -89,21 +89,7 @@ static void msn_logout( struct im_connection *ic ) while( md->switchboards ) msn_sb_destroy( md->switchboards->data ); - if( md->msgq ) - { - struct msn_message *m; - - for( l = md->msgq; l; l = l->next ) - { - m = l->data; - - imcb_log( ic, "Warning: Closing down MSN connection with unsent message to %s, you'll have to resend it.", m->who ); - g_free( m->who ); - g_free( m->text ); - g_free( m ); - } - g_slist_free( md->msgq ); - } + msn_msgq_purge( ic, &md->msgq ); while( md->groupcount > 0 ) g_free( md->grouplist[--md->groupcount] ); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 721466d6..746606a0 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -157,6 +157,7 @@ char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); char *msn_http_encode( const char *input ); +void msn_msgq_purge( struct im_connection *ic, GSList **list ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index c9eb5ee2..04ee799d 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -338,3 +338,37 @@ char *msn_http_encode( const char *input ) return ret; } + +void msn_msgq_purge( struct im_connection *ic, GSList **list ) +{ + struct msn_message *m; + GString *ret; + GSList *l; + + l = *list; + if( l == NULL ) + return; + + m = l->data; + ret = g_string_sized_new( 1024 ); + g_string_printf( ret, "WARNING: Cleaning up MSN (switchboard) connection with unsent " + "messages to %s:", m->who ? m->who : "unknown recipient" ); + + while( l ) + { + m = l->data; + + g_string_append_printf( ret, "\n%s", m->text ); + + g_free( m->who ); + g_free( m->text ); + g_free( m ); + + l = l->next; + } + g_slist_free( *list ); + *list = NULL; + + imcb_log( ic, ret->str ); + g_string_free( ret, TRUE ); +} diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 557f4f16..8c0afca6 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -127,7 +127,7 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) /* Build the message. Convert LF to CR-LF for normal messages. */ if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 ) { - buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 ); + buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 ); i = strlen( MSN_MESSAGE_HEADERS ); strcpy( buf, MSN_MESSAGE_HEADERS ); @@ -206,25 +206,7 @@ void msn_sb_destroy( struct msn_switchboard *sb ) debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" ); - if( sb->msgq ) - { - struct msn_message *m; - GSList *l; - - for( l = sb->msgq; l; l = l->next ) - { - m = l->data; - - g_free( m->who ); - g_free( m->text ); - g_free( m ); - } - g_slist_free( sb->msgq ); - - imcb_log( ic, "Warning: Closing down MSN switchboard connection with " - "unsent message to %s, you'll have to resend it.", - sb->who ? sb->who : "(unknown)" ); - } + msn_msgq_purge( ic, &sb->msgq ); if( sb->key ) g_free( sb->key ); if( sb->who ) g_free( sb->who ); @@ -265,7 +247,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) if( source != sb->fd ) { - debug( "ERROR %d while connecting to switchboard server", 1 ); + debug( "Error %d while connecting to switchboard server", 1 ); msn_sb_destroy( sb ); return FALSE; } @@ -286,7 +268,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) if( msn_sb_write( sb, buf, strlen( buf ) ) ) sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb ); else - debug( "ERROR %d while connecting to switchboard server", 2 ); + debug( "Error %d while connecting to switchboard server", 2 ); return FALSE; } @@ -297,7 +279,7 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c if( msn_handler( sb->handler ) == -1 ) { - debug( "ERROR: Switchboard died" ); + debug( "Error: Switchboard died" ); msn_sb_destroy( sb ); return FALSE; @@ -554,24 +536,13 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) { if( sb->who ) { - struct msn_message *m; - GSList *l; - /* Apparently some invitation failed. We might want to use this board later, so keep it as a spare. */ g_free( sb->who ); sb->who = NULL; /* Also clear the msgq, otherwise someone else might get them. */ - for( l = sb->msgq; l; l = l->next ) - { - m = l->data; - g_free( m->who ); - g_free( m->text ); - g_free( m ); - } - g_slist_free( sb->msgq ); - sb->msgq = NULL; + msn_msgq_purge( ic, &sb->msgq ); } /* Do NOT return 0 here, we want to keep this sb. */ -- cgit v1.2.3 From 434627083613f016d432462fce73f728dd77172e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 6 Jan 2008 12:37:55 +0000 Subject: More consistency in error/warning errors. Until now "WARNING:" was usually in upper case while "Error:" wasn't .... that doesn't really make sense. --- configure | 2 +- irc.c | 2 +- nick.c | 2 +- protocols/jabber/iq.c | 12 ++++++------ protocols/jabber/jabber_util.c | 2 +- protocols/jabber/presence.c | 4 ++-- protocols/msn/msn_util.c | 2 +- protocols/oscar/service.c | 2 +- protocols/oscar/txqueue.c | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 15e22623..6f8d8ea6 100755 --- a/configure +++ b/configure @@ -453,7 +453,7 @@ else fi if [ "$protocols" = "PROTOCOLS = " ]; then - echo "WARNING: You haven't selected any communication protocol to compile!" + echo "Warning: You haven't selected any communication protocol to compile!" echo " BitlBee will run, but you will be unable to connect to IM servers!" fi diff --git a/irc.c b/irc.c index 01d4c47e..2b86aebb 100644 --- a/irc.c +++ b/irc.c @@ -325,7 +325,7 @@ void irc_process( irc_t *irc ) if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) { if( irc->status & USTATUS_LOGGED_IN ) - irc_usermsg( irc, "ERROR: Charset mismatch detected. The charset " + irc_usermsg( irc, "Error: Charset mismatch detected. The charset " "setting is currently set to %s, so please make " "sure your IRC client will send and accept text in " "that charset, or tell BitlBee which charset to " diff --git a/nick.c b/nick.c index 4b05f4a7..52f9e5ad 100644 --- a/nick.c +++ b/nick.c @@ -110,7 +110,7 @@ void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+ { int i; - irc_usermsg( acc->irc, "WARNING: Almost had an infinite loop in nick_get()! " + irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! " "This used to be a fatal BitlBee bug, but we tried to fix it. " "This message should *never* appear anymore. " "If it does, please *do* send us a bug report! " diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 069e3af3..e1bab29e 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -53,7 +53,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) ( c = xt_find_node( node->children, "ping" ) ) ) || /* O_o WHAT is wrong with just <query/> ????? */ !( s = xt_find_attr( c, "xmlns" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -124,7 +124,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ-%s packet", type ); + imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } @@ -146,7 +146,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else { - imcb_log( ic, "WARNING: %s tried to fake a roster push!", s ? s : "(unknown)" ); + imcb_log( ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)" ); xt_free_node( reply ); reply = jabber_make_error_packet( node, "not-allowed", "cancel" ); @@ -211,7 +211,7 @@ static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *no if( !( query = xt_find_node( node->children, "query" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -269,7 +269,7 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node if( !( type = xt_find_attr( node, "type" ) ) ) { - imcb_log( ic, "WARNING: Received incomplete IQ packet while authenticating" ); + imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); imc_logout( ic, FALSE ); return XT_HANDLED; } @@ -345,7 +345,7 @@ static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node * if( !( query = xt_find_node( node->children, "query" ) ) ) { - imcb_log( ic, "WARNING: Received NULL roster packet" ); + imcb_log( ic, "Warning: Received NULL roster packet" ); return XT_HANDLED; } diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 9d84e099..b84be49b 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -199,7 +199,7 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node * if( entry == NULL ) { - imcb_log( ic, "WARNING: Received %s-%s packet with unknown/expired ID %s!", + imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!", node->name, xt_find_attr( node, "type" ) ? : "(no type)", s ); } else if( entry->func ) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index c3d7dced..f2dca26c 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -49,7 +49,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); + imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from ); return XT_HANDLED; } @@ -90,7 +90,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) { if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); + imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from ); return XT_HANDLED; } diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 04ee799d..fae2877d 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -351,7 +351,7 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) m = l->data; ret = g_string_sized_new( 1024 ); - g_string_printf( ret, "WARNING: Cleaning up MSN (switchboard) connection with unsent " + g_string_printf( ret, "Warning: Cleaning up MSN (switchboard) connection with unsent " "messages to %s:", m->who ? m->who : "unknown recipient" ); while( l ) diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index 3a180780..acd09150 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -893,7 +893,7 @@ int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guin aimbs_put32(&fr->data, 0xecf8427e); */ } else - imcb_error(sess->aux_data, "WARNING: unknown hash request"); + imcb_error(sess->aux_data, "Warning: unknown hash request"); } diff --git a/protocols/oscar/txqueue.c b/protocols/oscar/txqueue.c index 4416025a..d38986d0 100644 --- a/protocols/oscar/txqueue.c +++ b/protocols/oscar/txqueue.c @@ -79,7 +79,7 @@ static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr) { if (!fr->conn) { - imcb_error(sess->aux_data, "WARNING: enqueueing packet with no connection"); + imcb_error(sess->aux_data, "Warning: enqueueing packet with no connection"); fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); } -- cgit v1.2.3 From fc82be67d1f785218273e6269ed9d089a89b2bfd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sun, 6 Jan 2008 21:01:25 +0100 Subject: Add Debian watch file. --- debian/watch | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 debian/watch diff --git a/debian/watch b/debian/watch new file mode 100644 index 00000000..66ab4504 --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=2 +http://get.bitlbee.org/src/bitlbee-(.*).tar.gz -- cgit v1.2.3 From 181e47a9693d56e4bc0cec65ec05fce6086aebe8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 10 Jan 2008 00:31:38 +0000 Subject: Now setting odata->icq properly again, this got lost some time ago, which broke the info command and probably more things. --- protocols/oscar/oscar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index c4683046..980beaca 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -355,9 +355,10 @@ static void oscar_login(account_t *acc) { struct im_connection *ic = imcb_new(acc); struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); - if (!isdigit(acc->user[0])) { + if (isdigit(acc->user[0])) + odata->icq = TRUE; + else ic->flags |= OPT_DOES_HTML; - } sess = g_new0(aim_session_t, 1); -- cgit v1.2.3 From e7311208511c391b4f55161b6be93dbffb381c5e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 11 Jan 2008 00:45:18 +0000 Subject: Adding own handle to protocol name in blist output for people with multiple accounts on the same IM network. --- root_commands.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/root_commands.c b/root_commands.c index dc70feb4..26a42a25 100644 --- a/root_commands.c +++ b/root_commands.c @@ -820,7 +820,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( online == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user ); irc_usermsg( irc, format, u->nick, s, "Online" ); } @@ -831,7 +831,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( away == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user ); irc_usermsg( irc, format, u->nick, s, u->away ); } n_away ++; @@ -841,7 +841,7 @@ static void cmd_blist( irc_t *irc, char **cmd ) { if( offline == 1 ) { - g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->ic->acc->prpl->name ); + g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user ); irc_usermsg( irc, format, u->nick, s, "Offline" ); } n_offline ++; -- cgit v1.2.3 From e7f8838951c81ba7edf6c6567cf68075de42be6e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 11 Jan 2008 13:17:11 +0000 Subject: Fixing bug #344, now away states should always be correct, even when people do complicated things with multiple resources. (There were two bugs and some duplicated code, so I moved things around a bit.) --- protocols/jabber/presence.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index f2dca26c..3bfc83ff 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -29,8 +29,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ struct xt_node *c; - struct jabber_buddy *bud; - int is_chat = 0, is_away = 0; + struct jabber_buddy *bud, *send_presence = NULL; + int is_chat = 0; char *s; if( !from ) @@ -62,8 +62,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) { bud->away_state = (void*) jabber_away_state_by_code( c->text ); - if( strcmp( c->text, "chat" ) != 0 ) - is_away = OPT_AWAY; } else { @@ -80,10 +78,8 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( is_chat ) jabber_chat_pkt_presence( ic, bud, node ); - else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) - imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, - bud->away_message ); + else + send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 ); } else if( strcmp( type, "unavailable" ) == 0 ) { @@ -118,17 +114,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) /* If another resource is still available, send its presence information. */ - if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) ) - { - if( bud->away_state && ( *bud->away_state->code == 0 || - strcmp( bud->away_state->code, "chat" ) == 0 ) ) - is_away = OPT_AWAY; - - imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, - ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, - bud->away_message ); - } - else + if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) { /* Otherwise, count him/her as offline now. */ imcb_buddy_status( ic, from, 0, NULL, NULL ); @@ -176,6 +162,20 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) jabber_error_free( err ); } */ } + + if( send_presence ) + { + int is_away; + + if( send_presence->away_state && !( *send_presence->away_state->code == 0 || + strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) + is_away = OPT_AWAY; + + imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, + ( is_away && send_presence->away_state ) ? + send_presence->away_state->full_name : NULL, + send_presence->away_message ); + } return XT_HANDLED; } -- cgit v1.2.3 From e64de00bf2d99962182243983e8c09decaa36eb4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 12 Jan 2008 00:24:46 +0000 Subject: Killed info_string_append() and now showing the IP address of ICQ users in the "info" command response. --- lib/misc.c | 6 -- lib/misc.h | 1 - protocols/oscar/oscar.c | 184 +++++++++++++++++++++++++++--------------------- 3 files changed, 102 insertions(+), 89 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index d6795ec9..c2dd966e 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -244,12 +244,6 @@ char *escape_html( const char *html ) return( str ); } -void info_string_append(GString *str, char *newline, char *name, char *value) -{ - if( value && value[0] ) - g_string_sprintfa( str, "%s%s: %s", newline, name, value ); -} - /* Decode%20a%20file%20name */ void http_decode( char *s ) { diff --git a/lib/misc.h b/lib/misc.h index e0468d73..7804bfb1 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -41,7 +41,6 @@ G_MODULE_EXPORT void strip_linefeed( gchar *text ); G_MODULE_EXPORT char *add_cr( char *text ); G_MODULE_EXPORT char *strip_newlines(char *source); G_MODULE_EXPORT char *normalize( const char *s ); -G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value ); G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec ); double gettime( void ); diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 980beaca..c96e342e 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -90,6 +90,8 @@ struct oscar_data { gboolean killme; gboolean icq; GSList *evilhack; + + GHashTable *ips; struct { guint maxbuddies; /* max users you can watch */ @@ -411,6 +413,8 @@ static void oscar_logout(struct im_connection *ic) { odata->create_rooms = g_slist_remove(odata->create_rooms, cr); g_free(cr); } + if (odata->ips) + g_hash_table_destroy(odata->ips); if (odata->email) g_free(odata->email); if (odata->newp) @@ -987,6 +991,16 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) signon = time(NULL) - info->sessionlen; + if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR) { + uint32_t *uin = g_new0(uint32_t, 1); + + if (od->ips == NULL) + od->ips = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL); + + if (sscanf(info->sn, "%d", uin) == 1) + g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr); + } + tmp = g_strdup(normalize(ic->acc->user)); if (!strcmp(tmp, normalize(info->sn))) g_snprintf(ic->displayname, sizeof(ic->displayname), "%s", info->sn); @@ -2219,87 +2233,93 @@ static GList *oscar_away_states(struct im_connection *ic) static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) { - struct im_connection *ic = sess->aux_data; - gchar who[16]; - GString *str; - va_list ap; - struct aim_icq_info *info; - - va_start(ap, fr); - info = va_arg(ap, struct aim_icq_info *); - va_end(ap); - - if (!info->uin) - return 0; - - str = g_string_sized_new(100); - g_snprintf(who, sizeof(who), "%u", info->uin); - - g_string_sprintfa(str, "%s: %s - %s: %s", _("UIN"), who, _("Nick"), - info->nick ? info->nick : "-"); - info_string_append(str, "\n", _("First Name"), info->first); - info_string_append(str, "\n", _("Last Name"), info->last); - info_string_append(str, "\n", _("Email Address"), info->email); - if (info->numaddresses && info->email2) { - int i; - for (i = 0; i < info->numaddresses; i++) { - info_string_append(str, "\n", _("Email Address"), info->email2[i]); - } - } - info_string_append(str, "\n", _("Mobile Phone"), info->mobile); - if (info->gender != 0) - info_string_append(str, "\n", _("Gender"), info->gender==1 ? _("Female") : _("Male")); - if (info->birthyear || info->birthmonth || info->birthday) { - char date[30]; - struct tm tm; - tm.tm_mday = (int)info->birthday; - tm.tm_mon = (int)info->birthmonth-1; - tm.tm_year = (int)info->birthyear%100; - strftime(date, sizeof(date), "%Y-%m-%d", &tm); - info_string_append(str, "\n", _("Birthday"), date); - } - if (info->age) { - char age[5]; - g_snprintf(age, sizeof(age), "%hhd", info->age); - info_string_append(str, "\n", _("Age"), age); - } - info_string_append(str, "\n", _("Personal Web Page"), info->personalwebpage); - if (info->info && info->info[0]) { - g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Additional Information"), - info->info, _("End of Additional Information")); - } - g_string_sprintfa(str, "\n"); - if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { - g_string_sprintfa(str, "%s:", _("Home Address")); - info_string_append(str, "\n", _("Address"), info->homeaddr); - info_string_append(str, "\n", _("City"), info->homecity); - info_string_append(str, "\n", _("State"), info->homestate); - info_string_append(str, "\n", _("Zip Code"), info->homezip); - g_string_sprintfa(str, "\n"); - } - if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { - g_string_sprintfa(str, "%s:", _("Work Address")); - info_string_append(str, "\n", _("Address"), info->workaddr); - info_string_append(str, "\n", _("City"), info->workcity); - info_string_append(str, "\n", _("State"), info->workstate); - info_string_append(str, "\n", _("Zip Code"), info->workzip); - g_string_sprintfa(str, "\n"); - } - if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { - g_string_sprintfa(str, "%s:", _("Work Information")); - info_string_append(str, "\n", _("Company"), info->workcompany); - info_string_append(str, "\n", _("Division"), info->workdivision); - info_string_append(str, "\n", _("Position"), info->workposition); - if (info->workwebpage && info->workwebpage[0]) { - info_string_append(str, "\n", _("Web Page"), info->workwebpage); - } - g_string_sprintfa(str, "\n"); - } - - imcb_log(ic, "%s\n%s", _("User Info"), str->str); - g_string_free(str, TRUE); - - return 1; + struct im_connection *ic = sess->aux_data; + struct oscar_data *od = ic->proto_data; + gchar who[16]; + GString *str; + va_list ap; + struct aim_icq_info *info; + uint32_t ip; + + va_start(ap, fr); + info = va_arg(ap, struct aim_icq_info *); + va_end(ap); + + if (!info->uin) + return 0; + + str = g_string_sized_new(512); + g_snprintf(who, sizeof(who), "%u", info->uin); + + g_string_printf(str, "%s: %s - %s: %s", _("UIN"), who, _("Nick"), + info->nick ? info->nick : "-"); + g_string_append_printf(str, "\n%s: %s", _("First Name"), info->first); + g_string_append_printf(str, "\n%s: %s", _("Last Name"), info->last); + g_string_append_printf(str, "\n%s: %s", _("Email Address"), info->email); + if (info->numaddresses && info->email2) { + int i; + for (i = 0; i < info->numaddresses; i++) { + g_string_append_printf(str, "\n%s: %s", _("Email Address"), info->email2[i]); + } + } + if ((ip = (long) g_hash_table_lookup(od->ips, &info->uin)) != 0) { + g_string_append_printf(str, "\n%s: %d.%d.%d.%d", _("Last used IP address"), + (ip >> 24), (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + } + g_string_append_printf(str, "\n%s: %s", _("Mobile Phone"), info->mobile); + if (info->gender != 0) + g_string_append_printf(str, "\n%s: %s", _("Gender"), info->gender==1 ? _("Female") : _("Male")); + if (info->birthyear || info->birthmonth || info->birthday) { + char date[30]; + struct tm tm; + tm.tm_mday = (int)info->birthday; + tm.tm_mon = (int)info->birthmonth-1; + tm.tm_year = (int)info->birthyear%100; + strftime(date, sizeof(date), "%Y-%m-%d", &tm); + g_string_append_printf(str, "\n%s: %s", _("Birthday"), date); + } + if (info->age) { + char age[5]; + g_snprintf(age, sizeof(age), "%hhd", info->age); + g_string_append_printf(str, "\n%s: %s", _("Age"), age); + } + g_string_append_printf(str, "\n%s: %s", _("Personal Web Page"), info->personalwebpage); + if (info->info && info->info[0]) { + g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Additional Information"), + info->info, _("End of Additional Information")); + } + g_string_append_c(str, '\n'); + if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { + g_string_append_printf(str, "%s:", _("Home Address")); + g_string_append_printf(str, "\n%s: %s", _("Address"), info->homeaddr); + g_string_append_printf(str, "\n%s: %s", _("City"), info->homecity); + g_string_append_printf(str, "\n%s: %s", _("State"), info->homestate); + g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->homezip); + g_string_append_c(str, '\n'); + } + if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { + g_string_append_printf(str, "%s:", _("Work Address")); + g_string_append_printf(str, "\n%s: %s", _("Address"), info->workaddr); + g_string_append_printf(str, "\n%s: %s", _("City"), info->workcity); + g_string_append_printf(str, "\n%s: %s", _("State"), info->workstate); + g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->workzip); + g_string_append_c(str, '\n'); + } + if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { + g_string_append_printf(str, "%s:", _("Work Information")); + g_string_append_printf(str, "\n%s: %s", _("Company"), info->workcompany); + g_string_append_printf(str, "\n%s: %s", _("Division"), info->workdivision); + g_string_append_printf(str, "\n%s: %s", _("Position"), info->workposition); + if (info->workwebpage && info->workwebpage[0]) { + g_string_append_printf(str, "\n%s: %s", _("Web Page"), info->workwebpage); + } + g_string_append_c(str, '\n'); + } + + imcb_log(ic, "%s\n%s", _("User Info"), str->str); + g_string_free(str, TRUE); + + return 1; } @@ -2433,7 +2453,7 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) else { /* User has stopped typing */ imcb_buddy_typing(ic, sn, 0); - } + } return 1; } -- cgit v1.2.3 From 59f527b6eefaae452533170f52a96903ef63a209 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 12 Jan 2008 17:24:38 +0000 Subject: When a switchboard connection dies (at the TCP level) and there are still queued messages, they will now be moved back to the main queue and a new sb will be created to try to send the messages again. I hope this will solve some/most/all of the "Closing switchboard with unsent messages" problems, but can't be sure since this problem isn't very easy to reproduce. At least it should solve the ones caused by keeping spare switchboards around. Also enabling switchboard debugging output if configured with --debug=1, at least for now this will be useful. --- protocols/msn/msn.h | 10 +++++----- protocols/msn/sb.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 746606a0..c8f4f4c6 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -28,11 +28,9 @@ #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r" #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r" -#ifdef _WIN32 -#define debug +#ifdef DEBUG +#define debug( text... ) imcb_log( ic, text ); #else -#define debug( text... ) irc_usermsg( IRC, text ); -#undef debug #define debug( text... ) #endif @@ -65,8 +63,10 @@ struct msn_data GSList *msgq; GSList *switchboards; - const struct msn_away_state *away_state; + int sb_failures; + time_t first_sb_failure; + const struct msn_away_state *away_state; int buddycount; int groupcount; char **grouplist; diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 8c0afca6..cdf2e8ad 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -276,16 +276,59 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; + struct im_connection *ic = sb->ic; + struct msn_data *md = ic->proto_data; if( msn_handler( sb->handler ) == -1 ) { + time_t now = time( NULL ); + + if( now - md->first_sb_failure > 600 ) + { + /* It's not really the first one, but the start of this "series". + With this, the warning below will be shown only if this happens + at least three times in ten minutes. This algorithm isn't + perfect, but for this purpose it will do. */ + md->first_sb_failure = now; + md->sb_failures = 0; + } + debug( "Error: Switchboard died" ); + if( ++ md->sb_failures >= 3 ) + imcb_log( ic, "Warning: Many switchboard failures on MSN connection. " + "There might be problems delivering your messages." ); + + if( sb->msgq != NULL ) + { + char buf[1024]; + + if( md->msgq == NULL ) + { + md->msgq = sb->msgq; + } + else + { + GSList *l; + + for( l = md->msgq; l->next; l = l->next ); + l->next = sb->msgq; + } + sb->msgq = NULL; + + debug( "Moved queued messages back to the main queue, creating a new switchboard to retry." ); + g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); + if( !msn_write( ic, buf, strlen( buf ) ) ) + return FALSE; + } + msn_sb_destroy( sb ); return FALSE; } else + { return TRUE; + } } static int msn_sb_command( gpointer data, char **cmd, int num_parts ) -- cgit v1.2.3 From fc0cf92a81086903914056b32663479909a6fbff Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 13 Jan 2008 00:15:12 +0000 Subject: Different handling of charset mismatches before login time. Ignoring a USER command because of encoding issues isn't too great, so let's simply replace them. The information isn't really used anywhere anyway. --- irc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/irc.c b/irc.c index 2b86aebb..972e030e 100644 --- a/irc.c +++ b/irc.c @@ -324,7 +324,10 @@ void irc_process( irc_t *irc ) conv[IRC_MAX_LINE] = 0; if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) { + /* GLib can do strange things if things are not in the expected charset, + so let's be a little bit paranoid here: */ if( irc->status & USTATUS_LOGGED_IN ) + { irc_usermsg( irc, "Error: Charset mismatch detected. The charset " "setting is currently set to %s, so please make " "sure your IRC client will send and accept text in " @@ -332,7 +335,18 @@ void irc_process( irc_t *irc ) "expect by changing the charset setting. See " "`help set charset' for more information. Your " "message was ignored.", cs ); - *conv = 0; + *conv = 0; + } + else + { + irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, + "Warning: invalid (non-UTF8) characters received at login time." ); + + strncpy( conv, lines[i], IRC_MAX_LINE ); + for( temp = conv; *temp; temp ++ ) + if( *temp & 0x80 ) + *temp = '?'; + } } lines[i] = conv; } -- cgit v1.2.3 From 07ff8a2c5af9b281fa6cdf6f1273f7c55c83bdb2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 13 Jan 2008 14:45:51 +0000 Subject: Fixed quickstart2. (Bug #349.) --- doc/user-guide/quickstart.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user-guide/quickstart.xml b/doc/user-guide/quickstart.xml index fcb06c6b..7735a8d7 100644 --- a/doc/user-guide/quickstart.xml +++ b/doc/user-guide/quickstart.xml @@ -33,7 +33,7 @@ To add an account to the account list you will need to use the <emphasis>account </para> <para> -For instance, suppose you have an ICQ account with UIN <emphasis>72696705</emphasis> with password <emphasis>QuickStart</emphasis>, you would: +For instance, suppose you have a Jabber account at jabber.org with handle <emphasis>bitlbee@jabber.org</emphasis> with password <emphasis>QuickStart</emphasis>, you would: </para> <ircexample> @@ -42,7 +42,7 @@ For instance, suppose you have an ICQ account with UIN <emphasis>72696705</empha </ircexample> <para> -Other available IM protocols are msn, oscar, and yahoo. Oscar is the protocol used by ICQ and AOL. +Other available IM protocols are msn, oscar, and yahoo. OSCAR is the protocol used by ICQ and AOL. For more information about the <emphasis>account add</emphasis> command, see <emphasis>help account add</emphasis>. </para> <para> -- cgit v1.2.3 From dded27d9a58237036b23f152eb6dfeaad3ae762d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 13 Jan 2008 14:48:32 +0000 Subject: Fixed "Conditional jump or move depends on uninitialised value(s)" at jabber_pkt_presence (presence.c:174). Valgrind-Wilmer: 1-0. --- protocols/jabber/presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 3bfc83ff..2c49b800 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -165,7 +165,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) if( send_presence ) { - int is_away; + int is_away = 0; if( send_presence->away_state && !( *send_presence->away_state->code == 0 || strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) -- cgit v1.2.3 From 13857c648210a16448619c65e33f9918bfe27cbe Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 13 Jan 2008 17:13:45 +0000 Subject: Fixed handing of failed groupchat joins. --- protocols/jabber/conference.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 074412ec..466cb323 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -72,17 +72,16 @@ static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_no char *room; room = xt_find_attr( orig, "to" ); - if( ( bud = jabber_buddy_by_jid( ic, room, 0 ) ) ) - jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); - + bud = jabber_buddy_by_jid( ic, room, 0 ); err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR ); if( err ) { - imcb_error( ic, "Error joining groupchat %s: %s%s%s", - bud->bare_jid, err->code, err->text ? ": " : "", - err->text ? err->text : "" ); + imcb_error( ic, "Error joining groupchat %s: %s%s%s", room, err->code, + err->text ? ": " : "", err->text ? err->text : "" ); jabber_error_free( err ); } + if( bud ) + jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); return XT_HANDLED; } -- cgit v1.2.3 From 52744f8f65a278a59a8903d5c594e057d63c7006 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 17 Jan 2008 22:06:55 +0000 Subject: Fixing some Solaris compiler warnings (u_int->uint, adding some typecasts for pid_t variables). --- bitlbee.c | 2 +- ipc.c | 6 +++--- lib/md5.c | 22 +++++++++++----------- lib/md5.h | 7 ++++--- protocols/nogaim.c | 6 +++--- protocols/nogaim.h | 8 ++++---- unix.c | 4 ++-- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/bitlbee.c b/bitlbee.c index 3f488b46..c4b5abb3 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -278,7 +278,7 @@ static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child ); child_list = g_slist_append( child_list, child ); - log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid ); + log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", (int) client_pid ); /* Close some things we don't need in the parent process. */ close( new_socket ); diff --git a/ipc.c b/ipc.c index d0d2dff3..384a9c33 100644 --- a/ipc.c +++ b/ipc.c @@ -51,7 +51,7 @@ static void ipc_master_cmd_client( irc_t *data, char **cmd ) if( g_strcasecmp( cmd[0], "CLIENT" ) == 0 ) ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n", - child ? child->pid : -1, cmd[2], cmd[1], cmd[3] ); + (int) ( child ? child->pid : -1 ), cmd[2], cmd[1], cmd[3] ); } static void ipc_master_cmd_die( irc_t *data, char **cmd ) @@ -445,7 +445,7 @@ char *ipc_master_save_state() fprintf( fp, "%d\n", i ); for( l = child_list; l; l = l->next ) - fprintf( fp, "%d %d\n", ((struct bitlbee_child*)l->data)->pid, + fprintf( fp, "%d %d\n", (int) ((struct bitlbee_child*)l->data)->pid, ((struct bitlbee_child*)l->data)->ipc_fd ); if( fclose( fp ) == 0 ) @@ -550,7 +550,7 @@ int ipc_master_load_state() { child = g_new0( struct bitlbee_child, 1 ); - if( fscanf( fp, "%d %d", &child->pid, &child->ipc_fd ) != 2 ) + if( fscanf( fp, "%d %d", (int *) &child->pid, &child->ipc_fd ) != 2 ) { log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i ); g_free( child ); diff --git a/lib/md5.c b/lib/md5.c index 08c298a2..f1779794 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -25,7 +25,7 @@ #include <string.h> /* for memcpy() */ #include "md5.h" -static void md5_transform(u_int32_t buf[4], u_int32_t const in[16]); +static void md5_transform(uint32_t buf[4], uint32_t const in[16]); /* * Wrapper function for all-in-one MD5 @@ -52,12 +52,12 @@ void md5_init(struct MD5Context *ctx) void md5_append(struct MD5Context *ctx, const md5_byte_t *buf, unsigned int len) { - u_int32_t t; + uint32_t t; /* Update bitcount */ t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((u_int32_t) len << 3)) < t) + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; @@ -74,7 +74,7 @@ void md5_append(struct MD5Context *ctx, const md5_byte_t *buf, return; } memcpy(p, buf, t); - md5_transform(ctx->buf, (u_int32_t *) ctx->in); + md5_transform(ctx->buf, (uint32_t *) ctx->in); buf += t; len -= t; } @@ -82,7 +82,7 @@ void md5_append(struct MD5Context *ctx, const md5_byte_t *buf, while (len >= 64) { memcpy(ctx->in, buf, 64); - md5_transform(ctx->buf, (u_int32_t *) ctx->in); + md5_transform(ctx->buf, (uint32_t *) ctx->in); buf += 64; len -= 64; } @@ -116,7 +116,7 @@ void md5_finish(struct MD5Context *ctx, md5_byte_t digest[16]) if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); - md5_transform(ctx->buf, (u_int32_t *) ctx->in); + md5_transform(ctx->buf, (uint32_t *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -126,10 +126,10 @@ void md5_finish(struct MD5Context *ctx, md5_byte_t digest[16]) } /* Append length in bits and transform */ - ((u_int32_t *) ctx->in)[14] = ctx->bits[0]; - ((u_int32_t *) ctx->in)[15] = ctx->bits[1]; + ((uint32_t *) ctx->in)[14] = ctx->bits[0]; + ((uint32_t *) ctx->in)[15] = ctx->bits[1]; - md5_transform(ctx->buf, (u_int32_t *) ctx->in); + md5_transform(ctx->buf, (uint32_t *) ctx->in); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } @@ -151,9 +151,9 @@ void md5_finish(struct MD5Context *ctx, md5_byte_t digest[16]) * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ -static void md5_transform(u_int32_t buf[4], u_int32_t const in[16]) +static void md5_transform(uint32_t buf[4], uint32_t const in[16]) { - register u_int32_t a, b, c, d; + register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; diff --git a/lib/md5.h b/lib/md5.h index 86568b7a..094507b2 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -26,11 +26,12 @@ #include <sys/types.h> #include <gmodule.h> +#include <stdint.h> -typedef u_int8_t md5_byte_t; +typedef uint8_t md5_byte_t; typedef struct MD5Context { - u_int32_t buf[4]; - u_int32_t bits[2]; + uint32_t buf[4]; + uint32_t bits[2]; unsigned char in[64]; } md5_state_t; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 5e698902..b9008af1 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -624,7 +624,7 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, } } -void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ) +void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at ) { irc_t *irc = ic->irc; char *wrapped; @@ -675,7 +675,7 @@ void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_ g_free( wrapped ); } -void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ) +void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ) { user_t *u; @@ -731,7 +731,7 @@ void imcb_chat_free( struct groupchat *c ) } } -void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ) +void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ) { struct im_connection *ic = c->ic; char *wrapped; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 0e890464..8ba8fd9e 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -67,7 +67,7 @@ struct im_connection { account_t *acc; - u_int32_t flags; + uint32_t flags; /* each connection then can have its own protocol-specific data */ void *proto_data; @@ -281,8 +281,8 @@ G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handl G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ -G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at ); -G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ); +G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ); G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); /* Groupchats */ @@ -298,7 +298,7 @@ G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); /* To remove a handle from a group chat. Reason can be NULL. */ G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ -G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ); /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ); G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); diff --git a/unix.c b/unix.c index 75ffcf95..0aaf505a 100644 --- a/unix.c +++ b/unix.c @@ -196,9 +196,9 @@ static void sighandler( int signal ) while( ( pid = waitpid( 0, &st, WNOHANG ) ) > 0 ) { if( WIFSIGNALED( st ) ) - log_message( LOGLVL_INFO, "Client %d terminated normally. (status = %d)", pid, WEXITSTATUS( st ) ); + log_message( LOGLVL_INFO, "Client %d terminated normally. (status = %d)", (int) pid, WEXITSTATUS( st ) ); else if( WIFEXITED( st ) ) - log_message( LOGLVL_INFO, "Client %d killed by signal %d.", pid, WTERMSIG( st ) ); + log_message( LOGLVL_INFO, "Client %d killed by signal %d.", (int) pid, WTERMSIG( st ) ); } } else if( signal != SIGPIPE ) -- cgit v1.2.3 From ac4adf9a546c2e9b247b9de4b753177e6bd479e4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 17 Jan 2008 22:48:32 +0000 Subject: Apparently ext_yahoo_got_im can be called with msg=NULL, so it should be handled. Let's just ignore those packets. --- protocols/yahoo/yahoo.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index d413597a..9f9ffcf7 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -623,10 +623,14 @@ void ext_yahoo_status_changed( int id, const char *who, int stat, const char *ms void ext_yahoo_got_im( int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8 ) { struct im_connection *ic = byahoo_get_ic_by_id( id ); - char *m = byahoo_strip( msg ); + char *m; - imcb_buddy_msg( ic, (char*) who, (char*) m, 0, 0 ); - g_free( m ); + if( msg ) + { + m = byahoo_strip( msg ); + imcb_buddy_msg( ic, (char*) who, (char*) m, 0, 0 ); + g_free( m ); + } } void ext_yahoo_got_file( int id, -- cgit v1.2.3 From 83ba3e541acc3c29616fbf982b57633d303d941a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Fri, 18 Jan 2008 13:20:37 +0000 Subject: Moving imcb_chat_new() to a saner location (no code changes) and fixing default channel topic. --- protocols/nogaim.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index b9008af1..cfdaa454 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -691,6 +691,31 @@ void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags ) } } +struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) +{ + struct groupchat *c; + + /* This one just creates the conversation structure, user won't see anything yet */ + + if( ic->groupchats ) + { + for( c = ic->groupchats; c->next; c = c->next ); + c = c->next = g_new0( struct groupchat, 1 ); + } + else + ic->groupchats = c = g_new0( struct groupchat, 1 ); + + c->ic = ic; + c->title = g_strdup( handle ); + c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); + c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); + + if( set_getbool( &ic->irc->set, "debug" ) ) + imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); + + return c; +} + void imcb_chat_free( struct groupchat *c ) { struct im_connection *ic = c->ic; @@ -727,6 +752,7 @@ void imcb_chat_free( struct groupchat *c ) g_list_free( c->in_room ); g_free( c->channel ); g_free( c->title ); + g_free( c->topic ); g_free( c ); } } @@ -782,31 +808,6 @@ void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic ); } -struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) -{ - struct groupchat *c; - - /* This one just creates the conversation structure, user won't see anything yet */ - - if( ic->groupchats ) - { - for( c = ic->groupchats; c->next; c = c->next ); - c = c->next = g_new0( struct groupchat, 1 ); - } - else - ic->groupchats = c = g_new0( struct groupchat, 1 ); - - c->ic = ic; - c->title = g_strdup( handle ); - c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ ); - c->topic = g_strdup_printf( "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->channel, c->title ); - - if( set_getbool( &ic->irc->set, "debug" ) ) - imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); - - return c; -} - /* buddy_chat.c */ -- cgit v1.2.3 From bea13052bf43e34b043d868dfdaa84241a8b163a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 19 Jan 2008 12:36:30 +0000 Subject: Added byte swapping code to the new MD5 checksumming code to make it work on big-endian machines. (If someone thinks BitlBee should work on PDPs, send me the fix. I don't care. :-P) This fixes bug #351 (MSN challenge- response failure) but might break backward compatibility if the broken MD5 code was used to save settings. (Somewhere between rev 266 and now.) --- lib/md5.c | 165 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 69 deletions(-) diff --git a/lib/md5.c b/lib/md5.c index f1779794..3c39eccd 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -34,6 +34,29 @@ static void md5_transform(uint32_t buf[4], uint32_t const in[16]); * 20021120 */ +/* Turns out MD5 was designed for little-endian machines. If we're running + on a big-endian machines, we have to swap some bytes. Since detecting + endianness at compile time reliably seems pretty hard, let's do it at + run-time. It's not like we're going to checksum megabytes of data... */ +static uint32_t cvt32(uint32_t val) +{ + static int little_endian = -1; + + if (little_endian == -1) + { + little_endian = 1; + little_endian = *((char*) &little_endian); + } + + if (little_endian) + return val; + else + return (val >> 24) | + ((val >> 8) & 0xff00) | + ((val << 8) & 0xff0000) | + (val << 24); +} + void md5_init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; @@ -126,10 +149,14 @@ void md5_finish(struct MD5Context *ctx, md5_byte_t digest[16]) } /* Append length in bits and transform */ - ((uint32_t *) ctx->in)[14] = ctx->bits[0]; - ((uint32_t *) ctx->in)[15] = ctx->bits[1]; + ((uint32_t *) ctx->in)[14] = cvt32(ctx->bits[0]); + ((uint32_t *) ctx->in)[15] = cvt32(ctx->bits[1]); md5_transform(ctx->buf, (uint32_t *) ctx->in); + ctx->buf[0] = cvt32(ctx->buf[0]); + ctx->buf[1] = cvt32(ctx->buf[1]); + ctx->buf[2] = cvt32(ctx->buf[2]); + ctx->buf[3] = cvt32(ctx->buf[3]); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } @@ -160,73 +187,73 @@ static void md5_transform(uint32_t buf[4], uint32_t const in[16]) c = buf[2]; d = buf[3]; - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + MD5STEP(F1, a, b, c, d, cvt32(in[0]) + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, cvt32(in[1]) + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, cvt32(in[2]) + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, cvt32(in[3]) + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, cvt32(in[4]) + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, cvt32(in[5]) + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, cvt32(in[6]) + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, cvt32(in[7]) + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, cvt32(in[8]) + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, cvt32(in[9]) + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, cvt32(in[10]) + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, cvt32(in[11]) + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, cvt32(in[12]) + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, cvt32(in[13]) + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, cvt32(in[14]) + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, cvt32(in[15]) + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, cvt32(in[1]) + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, cvt32(in[6]) + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, cvt32(in[11]) + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, cvt32(in[0]) + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, cvt32(in[5]) + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, cvt32(in[10]) + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, cvt32(in[15]) + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, cvt32(in[4]) + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, cvt32(in[9]) + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, cvt32(in[14]) + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, cvt32(in[3]) + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, cvt32(in[8]) + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, cvt32(in[13]) + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, cvt32(in[2]) + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, cvt32(in[7]) + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, cvt32(in[12]) + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, cvt32(in[5]) + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, cvt32(in[8]) + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, cvt32(in[11]) + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, cvt32(in[14]) + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, cvt32(in[1]) + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, cvt32(in[4]) + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, cvt32(in[7]) + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, cvt32(in[10]) + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, cvt32(in[13]) + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, cvt32(in[0]) + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, cvt32(in[3]) + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, cvt32(in[6]) + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, cvt32(in[9]) + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, cvt32(in[12]) + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, cvt32(in[15]) + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, cvt32(in[2]) + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, cvt32(in[0]) + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, cvt32(in[7]) + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, cvt32(in[14]) + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, cvt32(in[5]) + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, cvt32(in[12]) + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, cvt32(in[3]) + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, cvt32(in[10]) + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, cvt32(in[1]) + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, cvt32(in[8]) + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, cvt32(in[15]) + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, cvt32(in[6]) + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, cvt32(in[13]) + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, cvt32(in[4]) + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, cvt32(in[11]) + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, cvt32(in[2]) + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, cvt32(in[9]) + 0xeb86d391, 21); buf[0] += a; buf[1] += b; -- cgit v1.2.3 From 003553b6ac35ce3d9caa44ebe301e0eeb2125ed0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 19 Jan 2008 18:23:56 +0000 Subject: Using test -f instead of test -e. This breaks if the include files are symlinks, but I guess that's less common than people trying to run BitlBee on Solaris machines... (Bug #350) --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 6f8d8ea6..22989f60 100755 --- a/configure +++ b/configure @@ -188,7 +188,7 @@ else fi if [ "$events" = "libevent" ]; then - if ! [ -e "${libevent}include/event.h" ]; then + if ! [ -f "${libevent}include/event.h" ]; then echo echo 'Warning: Could not find event.h, you might have to install it and/or specify' echo 'its location using the --libevent= argument. (Example: If event.h is in' @@ -323,7 +323,7 @@ fi; echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings for i in /lib /usr/lib /usr/local/lib; do - if [ -e $i/libresolv.a ]; then + if [ -f $i/libresolv.a ]; then echo '#define HAVE_RESOLV_A' >> config.h echo 'EFLAGS+='$i'/libresolv.a' >> Makefile.settings break -- cgit v1.2.3 From 0adce2151fc2a4f517e558663e5afe010b86a39a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 20 Jan 2008 00:01:31 +0000 Subject: GET_BUDDY_FIRST wasn't actually implemented, even though it was in use already. I don't want to know how long it took me to find out... --- protocols/jabber/jabber_util.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index b84be49b..794a1040 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -391,19 +391,26 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, *s = 0; if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) { + /* Just return the first one for this bare JID. */ + if( flags & GET_BUDDY_FIRST ) + { + *s = '/'; + g_free( jid ); + return bud; + } + /* Is this one of those no-resource buddies? */ if( bud->resource == NULL ) { + *s = '/'; g_free( jid ); return NULL; } - else - { - /* See if there's an exact match. */ - for( ; bud; bud = bud->next ) - if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) - break; - } + + /* See if there's an exact match. */ + for( ; bud; bud = bud->next ) + if( g_strcasecmp( bud->resource, s + 1 ) == 0 ) + break; } else { @@ -412,6 +419,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, for this JID, even if it's an unknown buddy. This is done to handle conferences properly. */ none_found = 1; + /* TODO(wilmer): Find out what I was thinking when I + wrote this??? And then fix it. This makes me sad... */ } if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) ) @@ -442,6 +451,9 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, else if( ( bud->resource == NULL || bud->next == NULL ) ) /* No need for selection if there's only one option. */ return bud; + else if( flags & GET_BUDDY_FIRST ) + /* Looks like the caller doesn't care about details. */ + return bud; best_prio = best_time = bud; for( ; bud; bud = bud->next ) -- cgit v1.2.3 From 31e584652a5543b87e0953525a742fb067c28e6f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 20 Jan 2008 00:17:57 +0000 Subject: Added imcb_chat_log() for chatroom system messages, so they can be displayed inside the right channel. --- protocols/nogaim.c | 18 ++++++++++++++++++ protocols/nogaim.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/protocols/nogaim.c b/protocols/nogaim.c index cfdaa454..3ce15166 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -785,6 +785,24 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, t g_free( wrapped ); } +void imcb_chat_log( struct groupchat *c, char *format, ... ) +{ + irc_t *irc = c->ic->irc; + va_list params; + char *text; + user_t *u; + + va_start( params, format ); + text = g_strdup_vprintf( format, params ); + va_end( params ); + + u = user_find( irc, irc->mynick ); + + irc_privmsg( irc, u, "PRIVMSG", c->channel, "System message: ", text ); + + g_free( text ); +} + void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) { struct im_connection *ic = c->ic; diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 8ba8fd9e..7d391edd 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -299,6 +299,8 @@ G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ); +/* System messages specific to a groupchat, so they can be displayed in the right context. */ +G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ); G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); -- cgit v1.2.3 From a882d6c1eec55fb9a00ce61acd6d776884d0c84a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 20 Jan 2008 11:15:40 +0000 Subject: The Jabber module now uses imcb_chat_log() instead of imcb_log() where possible. --- protocols/jabber/conference.c | 46 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 466cb323..515194fc 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -294,18 +294,54 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud { struct xt_node *subject = xt_find_node( node->children, "subject" ); struct xt_node *body = xt_find_node( node->children, "body" ); - struct groupchat *chat; + struct groupchat *chat = NULL; char *s; if( bud == NULL ) { + char *nick; + + if( body == NULL || body->text_len == 0 ) + /* Meh. Empty messages aren't very interesting, no matter + how much some servers love to send them. */ + return; + s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */ - if( strchr( s, '/' ) == NULL ) + nick = strchr( s, '/' ); + if( nick ) + { + /* If this message included a resource/nick we don't know, + we might still know the groupchat itself. */ + *nick = 0; + chat = jabber_chat_by_jid( ic, s ); + *nick = '/'; + + nick ++; + } + else + { + /* message.c uses the EXACT_JID option, so bud should + always be NULL here for bare JIDs. */ + chat = jabber_chat_by_jid( ic, s ); + } + + if( nick == NULL ) + { /* This is fine, the groupchat itself isn't in jd->buddies. */ - imcb_log( ic, "System message from groupchat %s: %s", s, body? body->text : "NULL" ); + if( chat ) + imcb_chat_log( chat, "From conference server: %s", body->text ); + else + imcb_log( ic, "System message from unknown groupchat %s: %s", s, body->text ); + } else - /* This, however, isn't fine! */ - imcb_log( ic, "Groupchat message from unknown participant %s: %s", s, body ? body->text : "NULL" ); + { + /* This can happen too, at least when receiving a backlog when + just joining a channel. */ + if( chat ) + imcb_chat_log( chat, "Message from unknown participant %s: %s", nick, body->text ); + else + imcb_log( ic, "Groupchat message from unknown JID %s: %s", s, body->text ); + } return; } -- cgit v1.2.3 From 613cc5583465b2fa35288a2f28d0e408904c4fd9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 24 Jan 2008 22:22:46 +0000 Subject: Fixed two valgrind warnings (partially uninitialized "struct tm" vars.) --- lib/misc.c | 2 ++ protocols/oscar/oscar.c | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/misc.c b/lib/misc.c index c2dd966e..18d98f9e 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -89,12 +89,14 @@ time_t get_time(int year, int month, int day, int hour, int min, int sec) { struct tm tm; + memset(&tm, 0, sizeof(struct tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; + return mktime(&tm); } diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index c96e342e..30ad4b68 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2272,6 +2272,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) if (info->birthyear || info->birthmonth || info->birthday) { char date[30]; struct tm tm; + memset(&tm, 0, sizeof(struct tm)); tm.tm_mday = (int)info->birthday; tm.tm_mon = (int)info->birthmonth-1; tm.tm_year = (int)info->birthyear%100; -- cgit v1.2.3 From b5c8a34aeff244ffe7a9f4bd5edf827495d0deea Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 24 Jan 2008 22:49:47 +0000 Subject: Keeping track of valid Jabber connections so _connected() events will be ignored if the connection's dead already. Necessary if using GLib for event handling for now. :-/ --- protocols/jabber/io.c | 10 +++++++++- protocols/jabber/jabber.c | 9 +++++++++ protocols/jabber/jabber.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 29561b86..86c216ef 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -248,6 +248,9 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c { struct im_connection *ic = data; + if( g_slist_find( jabber_connections, ic ) == NULL ) + return FALSE; + if( source == -1 ) { imcb_error( ic, "Could not connect to server" ); @@ -263,7 +266,12 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond ) { struct im_connection *ic = data; - struct jabber_data *jd = ic->proto_data; + struct jabber_data *jd; + + if( g_slist_find( jabber_connections, ic ) == NULL ) + return FALSE; + + jd = ic->proto_data; if( source == NULL ) { diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 264a0308..243ed7fd 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -34,6 +34,8 @@ #include "md5.h" #include "base64.h" +GSList *jabber_connections; + static void jabber_init( account_t *acc ) { set_t *s; @@ -70,6 +72,11 @@ static void jabber_login( account_t *acc ) struct ns_srv_reply *srv = NULL; char *connect_to, *s; + /* For now this is needed in the _connected() handlers if using + GLib event handling, to make sure we're not handling events + on dead connections. */ + jabber_connections = g_slist_prepend( jabber_connections, ic ); + jd->ic = ic; ic->proto_data = jd; @@ -262,6 +269,8 @@ static void jabber_logout( struct im_connection *ic ) g_free( jd->away_message ); g_free( jd->username ); g_free( jd ); + + jabber_connections = g_slist_remove( jabber_connections, ic ); } static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index f673ee0d..cf0f8e6a 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -29,6 +29,8 @@ #include "xmltree.h" #include "bitlbee.h" +extern GSList *jabber_connections; + typedef enum { JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream -- cgit v1.2.3 From f774e01cdb34e339455671f51413ecdc6de3208d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Wed, 30 Jan 2008 23:05:52 +0000 Subject: Fixed handling of OSCAR multi-part messages... They're not arrays, they're linked lists! --- protocols/oscar/oscar.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 30ad4b68..9e5de70a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -1065,12 +1065,14 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ } else if (args->mpmsg.numparts == 0) { g_snprintf(tmp, BUF_LONG, "%s", args->msg); } else { - int i; + aim_mpmsg_section_t *part; *tmp = 0; - for (i = 0; i < args->mpmsg.numparts; i ++) { - g_strlcat(tmp, (char*) args->mpmsg.parts[i].data, BUF_LONG); - g_strlcat(tmp, "\n", BUF_LONG); + for (part = args->mpmsg.parts; part; part = part->next) { + if (part->data) { + g_strlcat(tmp, (char*) part->data, BUF_LONG); + g_strlcat(tmp, "\n", BUF_LONG); + } } } -- cgit v1.2.3 From 0fbda19314c806e3e677847f3c977eb5a1bc2b61 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 2 Feb 2008 21:48:09 +0000 Subject: Added help_free() and cleaned up some very stale help-related stuff I wasn't even aware of. This closes bug #352. --- help.c | 66 +++++++++++++++++++++++++++++++++++++++------------------- help.h | 5 +++-- irc.c | 11 ---------- irc.h | 1 - irc_commands.c | 2 +- unix.c | 5 ++++- 6 files changed, 53 insertions(+), 37 deletions(-) diff --git a/help.c b/help.c index 756eb12a..587b9940 100644 --- a/help.c +++ b/help.c @@ -70,21 +70,20 @@ help_t *help_init( help_t **help, const char *helpfile ) if( !( t = strstr( s, "\n%\n" ) ) || s[0] != '?' ) { /* FIXME: Clean up */ -// help_close( *help ); - *help = NULL; + help_free( help ); g_free( s ); - return( NULL ); + return NULL; } i = strchr( s, '\n' ) - s; - if( h->string ) + if( h->title ) { h = h->next = g_new0( help_t, 1 ); } - h->string = g_new ( char, i ); + h->title = g_new ( char, i ); - strncpy( h->string, s + 1, i - 1 ); - h->string[i-1] = 0; + strncpy( h->title, s + 1, i - 1 ); + h->title[i-1] = 0; h->fd = (*help)->fd; h->offset.file_offset = lseek( h->fd, 0, SEEK_CUR ) - buflen + i + 1; h->length = t - s - i - 1; @@ -102,7 +101,31 @@ help_t *help_init( help_t **help, const char *helpfile ) return( *help ); } -char *help_get( help_t **help, char *string ) +void help_free( help_t **help ) +{ + help_t *h, *oh; + int last_fd = -1; /* Weak de-dupe */ + + if( help == NULL || *help == NULL ) + return; + + h = *help; + while( h ) + { + if( h->fd != last_fd ) + { + close( h->fd ); + last_fd = h->fd; + } + g_free( h->title ); + h = (oh=h)->next; + g_free( oh ); + } + + *help = NULL; +} + +char *help_get( help_t **help, char *title ) { time_t mtime; struct stat stat[1]; @@ -110,28 +133,29 @@ char *help_get( help_t **help, char *string ) for( h = *help; h; h = h->next ) { - if( h->string != NULL && - g_strcasecmp( h->string, string ) == 0 ) + if( h->title != NULL && g_strcasecmp( h->title, title ) == 0 ) break; } if( h && h->length > 0 ) { char *s = g_new( char, h->length + 1 ); - if( fstat( h->fd, stat ) != 0 ) - { - g_free( h ); - *help = NULL; - return NULL; - } - mtime = stat->st_mtime; - - if( mtime > h->mtime ) - return NULL; - s[h->length] = 0; if( h->fd >= 0 ) { + if( fstat( h->fd, stat ) != 0 ) + { + g_free( s ); + return NULL; + } + mtime = stat->st_mtime; + + if( mtime > h->mtime ) + { + g_free( s ); + return NULL; + } + lseek( h->fd, h->offset.file_offset, SEEK_SET ); read( h->fd, s, h->length ); } diff --git a/help.h b/help.h index 32aba723..5421220c 100644 --- a/help.h +++ b/help.h @@ -36,13 +36,14 @@ typedef struct help { int fd; time_t mtime; - char *string; + char *title; help_off_t offset; int length; struct help *next; } help_t; G_GNUC_MALLOC help_t *help_init( help_t **help, const char *helpfile ); -char *help_get( help_t **help, char *string ); +void help_free( help_t **help ); +char *help_get( help_t **help, char *title ); #endif diff --git a/irc.c b/irc.c index 972e030e..2510e3d9 100644 --- a/irc.c +++ b/irc.c @@ -188,7 +188,6 @@ void irc_free(irc_t * irc) { account_t *account; user_t *user, *usertmp; - help_t *helpnode, *helpnodetmp; log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); @@ -265,16 +264,6 @@ void irc_free(irc_t * irc) g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); g_hash_table_destroy(irc->watches); - if (irc->help != NULL) { - helpnode = irc->help; - while (helpnode != NULL) { - g_free(helpnode->string); - - helpnodetmp = helpnode; - helpnode = helpnode->next; - g_free(helpnodetmp); - } - } g_free(irc); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) diff --git a/irc.h b/irc.h index 8be3579e..eb70ad1c 100644 --- a/irc.h +++ b/irc.h @@ -88,7 +88,6 @@ typedef struct irc GHashTable *userhash; GHashTable *watches; struct __NICK *nicks; - struct help *help; struct set *set; gint r_watch_source_id; diff --git a/irc_commands.c b/irc_commands.c index 65f0d6c6..4b431027 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -555,7 +555,7 @@ static void irc_cmd_completions( irc_t *irc, char **cmd ) irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command ); for( h = global.help; h; h = h->next ) - irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string ); + irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->title ); for( s = irc->set; s; s = s->next ) irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key ); diff --git a/unix.c b/unix.c index 0aaf505a..9b670d78 100644 --- a/unix.c +++ b/unix.c @@ -123,11 +123,14 @@ int main( int argc, char *argv[], char **envp ) if( !getuid() || !geteuid() ) log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" ); - if( help_init( &(global.help), global.helpfile ) == NULL ) + if( help_init( &global.help, global.helpfile ) == NULL ) log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE ); b_main_run(); + /* Mainly good for restarting, to make sure we close the help.txt fd. */ + help_free( &global.help ); + if( global.restart ) { char *fn = ipc_master_save_state(); -- cgit v1.2.3 From 979cfb448cc233e29ceb6cd43f99fb4104728be6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Feb 2008 13:54:19 +0000 Subject: Saner garbage collection of cached packets in the Jabber module. Now cached packets are removed after about ten minues instead of something between one and two minutes. Closes one issue in #354. --- protocols/jabber/jabber.h | 5 +++++ protocols/jabber/jabber_util.c | 16 ++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index cf0f8e6a..5132d45f 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -94,6 +94,7 @@ typedef xt_status (*jabber_cache_event) ( struct im_connection *ic, struct xt_no struct jabber_cache_entry { + time_t saved_at; struct xt_node *node; jabber_cache_event func; }; @@ -140,6 +141,10 @@ struct jabber_chat #define JABBER_PACKET_ID "BeeP" #define JABBER_CACHED_ID "BeeC" +/* The number of seconds to keep cached packets before garbage collecting + them. This gc is done on every keepalive (every minute). */ +#define JABBER_CACHE_MAX_AGE 600 + /* RFC 392[01] stuff */ #define XMLNS_TLS "urn:ietf:params:xml:ns:xmpp-tls" #define XMLNS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 794a1040..6e872040 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -141,6 +141,7 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca entry->node = node; entry->func = func; + entry->saved_at = time( NULL ); g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); } @@ -162,22 +163,17 @@ gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpo void jabber_cache_clean( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; + time_t threshold = time( NULL ) - JABBER_CACHE_MAX_AGE; - g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, NULL ); + g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, &threshold ); } -gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer nullpointer ) +gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer threshold_ ) { struct jabber_cache_entry *entry = entry_; - struct xt_node *node = entry->node; + time_t *threshold = threshold_; - if( node->flags & XT_SEEN ) - return TRUE; - else - { - node->flags |= XT_SEEN; - return FALSE; - } + return entry->saved_at < *threshold; } xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ) -- cgit v1.2.3 From 8c1eb8025f493ce22b4cc58da1ecfd4afa416816 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Feb 2008 16:59:39 +0000 Subject: Implemented XEP-0115. This adds some info to the <presence/> tags so clients interested in capabilities can cache discovery info, so they don't have to ask about it every time you/they log in. --- protocols/jabber/iq.c | 3 ++- protocols/jabber/jabber.h | 1 + protocols/jabber/presence.c | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index e1bab29e..c88bc0b0 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -91,7 +91,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) } else if( strcmp( s, XMLNS_DISCOVER ) == 0 ) { - const char *features[] = { XMLNS_VERSION, + const char *features[] = { XMLNS_DISCOVER, + XMLNS_VERSION, XMLNS_TIME, XMLNS_CHATSTATES, XMLNS_MUC, diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 5132d45f..44655409 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -165,6 +165,7 @@ struct jabber_chat #define XMLNS_DISCOVER "http://jabber.org/protocol/disco#info" /* 0030 */ #define XMLNS_MUC "http://jabber.org/protocol/muc" /* XEP-0045 */ #define XMLNS_MUC_USER "http://jabber.org/protocol/muc#user"/* XEP-0045 */ +#define XMLNS_CAPS "http://jabber.org/protocol/caps" /* XEP-0115 */ /* iq.c */ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 2c49b800..6fc360b7 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -28,7 +28,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) struct im_connection *ic = data; char *from = xt_find_attr( node, "from" ); char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ - struct xt_node *c; + struct xt_node *c, *cap; struct jabber_buddy *bud, *send_presence = NULL; int is_chat = 0; char *s; @@ -76,6 +76,26 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) else bud->priority = 0; + if( bud && ( cap = xt_find_node( node->children, "c" ) ) && + ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 ) + { + /* This <presence> stanza includes an XEP-0115 + capabilities part. Not too interesting, but we can + see if it has an ext= attribute. */ + s = xt_find_attr( cap, "ext" ); + if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) ) + bud->flags |= JBFLAG_DOES_XEP85; + + /* This field can contain more information like xhtml + support, but we don't support that ourselves. + Officially the ext= tag was deprecated, but enough + clients do send it. + + (I'm aware that this is not the right way to use + this field.) See for an explanation of ext=: + http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/ + } + if( is_chat ) jabber_chat_pkt_presence( ic, bud, node ); else @@ -185,7 +205,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) int presence_send_update( struct im_connection *ic ) { struct jabber_data *jd = ic->proto_data; - struct xt_node *node; + struct xt_node *node, *cap; char *show = jd->away_state->code; char *status = jd->away_message; struct groupchat *c; @@ -198,6 +218,16 @@ int presence_send_update( struct im_connection *ic ) if( status ) xt_add_child( node, xt_new_node( "status", status, NULL ) ); + /* This makes the packet slightly bigger, but clients interested in + capabilities can now cache the discovery info. This reduces the + usual post-login iq-flood. See XEP-0115. At least libpurple and + Trillian seem to do this right. */ + cap = xt_new_node( "c", NULL, NULL ); + xt_add_attr( cap, "xmlns", XMLNS_CAPS ); + xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" ); + xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */ + xt_add_child( node, cap ); + st = jabber_write_packet( ic, node ); /* Have to send this update to all groupchats too, the server won't -- cgit v1.2.3 From 8ff0a61e7389db201ff4534f267225af6f66736b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Feb 2008 17:11:15 +0000 Subject: Disabling "Unknown command" warnings since they're very noisy and pretty pointless. --- protocols/msn/ns.c | 2 +- protocols/msn/sb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 3735aad6..0bb84a74 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -583,7 +583,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) } else { - debug( "Received unknown command from main server: %s", cmd[0] ); + /* debug( "Received unknown command from main server: %s", cmd[0] ); */ } return( 1 ); diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index cdf2e8ad..18c41ef5 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -593,7 +593,7 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) } else { - debug( "Received unknown command from switchboard server: %s", cmd[0] ); + /* debug( "Received unknown command from switchboard server: %s", cmd[0] ); */ } return( 1 ); -- cgit v1.2.3 From 63075d7345355dde6e490ad00a886a1b165dbe17 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 3 Feb 2008 23:33:18 +0000 Subject: Messages from the user are also included in backlogs when joining a Jabber chatroom. Until now they were ignored, which might make backlogs a little bit confusing. --- protocols/jabber/conference.c | 9 ++++++--- protocols/jabber/jabber.h | 14 ++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 515194fc..f206e084 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -122,6 +122,8 @@ int jabber_chat_msg( struct groupchat *c, char *message, int flags ) struct jabber_chat *jc = c->data; struct xt_node *node; + jc->flags |= JCFLAG_MESSAGE_SENT; + node = xt_new_node( "body", message, NULL ); node = jabber_make_packet( "message", "groupchat", jc->name, node ); @@ -294,10 +296,11 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud { struct xt_node *subject = xt_find_node( node->children, "subject" ); struct xt_node *body = xt_find_node( node->children, "body" ); - struct groupchat *chat = NULL; + struct groupchat *chat = bud ? jabber_chat_by_jid( ic, bud->bare_jid ) : NULL; + struct jabber_chat *jc = chat ? chat->data : NULL; char *s; - if( bud == NULL ) + if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) ) { char *nick; @@ -345,7 +348,7 @@ void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud return; } - else if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL ) + else if( chat == NULL ) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 44655409..1ff0e8dd 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -48,16 +48,22 @@ typedef enum typedef enum { - JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make + JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make sure it gets sent only once. */ - JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support + JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support XEP85 (typing notification shite). */ - JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for + JBFLAG_IS_CHATROOM = 4, /* It's convenient to use this JID thingy for groupchat state info too. */ - JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have + JBFLAG_IS_ANONYMOUS = 8, /* For anonymous chatrooms, when we don't have have a real JID. */ } jabber_buddy_flags_t; +typedef enum +{ + JCFLAG_MESSAGE_SENT = 1, /* Set this after sending the first message, so + we can detect echoes/backlogs. */ +} jabber_chat_flags_t; + struct jabber_data { struct im_connection *ic; -- cgit v1.2.3 From 69ac78cef9505f334cf61d13825371ce0c67ca16 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 4 Feb 2008 23:54:08 +0000 Subject: Added bogus G_GNUC_MALLOC to restore GLib 2.4 compatibility (hopefully). --- bitlbee.h | 6 ++++++ crypting.c | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index 23ec64b1..55687e3b 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -98,6 +98,12 @@ #define F_OK 0 #endif +#ifndef G_GNUC_MALLOC +/* Doesn't exist in GLib <=2.4 while everything else in BitlBee should + work with it, so let's fake this one. */ +#define G_GNUC_MALLOC +#endif + #define _( x ) x #define ROOT_NICK "root" diff --git a/crypting.c b/crypting.c index 2a17a913..34b99034 100644 --- a/crypting.c +++ b/crypting.c @@ -28,10 +28,7 @@ included if CRYPTING_MAIN is defined. Or just do "make decode" and the programs will be built. */ -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <glib.h> +#include <bitlbee.h> #include "md5.h" #include "crypting.h" -- cgit v1.2.3 From c84e31ae1e972a327b103ada52cae6a2e2335767 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 7 Feb 2008 21:25:18 +0000 Subject: Fixed getnameinfo() calls, this fixes Solaris stability issues. Thanks to Logan O'Sullivan Bruns for the report. --- irc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/irc.c b/irc.c index 2510e3d9..3a09f684 100644 --- a/irc.c +++ b/irc.c @@ -73,7 +73,7 @@ irc_t *irc_new( int fd ) char buf[NI_MAXHOST+1]; if( getnameinfo( (struct sockaddr *) &sock, socklen, buf, - NI_MAXHOST, NULL, -1, 0 ) == 0 ) + NI_MAXHOST, NULL, 0, 0 ) == 0 ) { irc->myhost = g_strdup( ipv6_unwrap( buf ) ); } @@ -84,7 +84,7 @@ irc_t *irc_new( int fd ) char buf[NI_MAXHOST+1]; if( getnameinfo( (struct sockaddr *)&sock, socklen, buf, - NI_MAXHOST, NULL, -1, 0 ) == 0 ) + NI_MAXHOST, NULL, 0, 0 ) == 0 ) { irc->host = g_strdup( ipv6_unwrap( buf ) ); } -- cgit v1.2.3 From 7adc657830fe76df344bf718df45ca05cc015d4e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 9 Feb 2008 23:54:09 +0000 Subject: Restored "add -tmp". A bit hackish, but it will do for now. --- root_commands.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/root_commands.c b/root_commands.c index 26a42a25..8e315bd4 100644 --- a/root_commands.c +++ b/root_commands.c @@ -448,7 +448,7 @@ static void cmd_add( irc_t *irc, char **cmd ) if( g_strcasecmp( cmd[1], "-tmp" ) == 0 ) { add_on_server = 0; - cmd ++; /* So evil... :-D */ + cmd ++; } if( !( a = account_get( irc, cmd[1] ) ) ) @@ -480,12 +480,13 @@ static void cmd_add( irc_t *irc, char **cmd ) } } - /* By making this optional, you can talk to people without having to - add them to your *real* (server-side) contact list. */ if( add_on_server ) a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL ); - - /* add_buddy( a->ic, NULL, cmd[2], cmd[2] ); */ + else + /* Yeah, officially this is a call-*back*... So if we just + called add_buddy, we'll wait for the IM server to respond + before we do this. */ + imcb_add_buddy( a->ic, cmd[2], NULL ); irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2] ); } -- cgit v1.2.3 From 1ecff5ee9ab540584a8b15814dcc15f706a26d4c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 10 Feb 2008 11:12:35 +0000 Subject: Making AI_ADDRCONFIG optional, it doesn't exist on at least NetBSD and (IIRC) OpenBSD systems. --- bitlbee.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bitlbee.c b/bitlbee.c index c4b5abb3..59a417f0 100644 --- a/bitlbee.c +++ b/bitlbee.c @@ -47,7 +47,11 @@ int bitlbee_daemon_init() memset( &hints, 0, sizeof( hints ) ); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; + hints.ai_flags = AI_PASSIVE +#ifdef AI_ADDRCONFIG + | AI_ADDRCONFIG +#endif + ; i = getaddrinfo( global.conf->iface, global.conf->port, &hints, &addrinfo_bind ); if( i ) -- cgit v1.2.3 From 3038e476a93b2be057581b831749eac931a06559 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 10 Feb 2008 17:11:06 +0000 Subject: Added support for password-protected Jabber chatrooms. --- protocols/jabber/conference.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index f206e084..79fdd053 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -36,6 +36,8 @@ struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char * node = xt_new_node( "x", NULL, NULL ); xt_add_attr( node, "xmlns", XMLNS_MUC ); node = jabber_make_packet( "presence", NULL, roomjid, node ); + if( password ) + xt_add_child( node, xt_new_node( "password", password, NULL ) ); jabber_cache_add( ic, node, jabber_chat_join_failed ); if( !jabber_write_packet( ic, node ) ) -- cgit v1.2.3 From eeb85a8a880fefe655eb31b6322136b61ee969e2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Mon, 11 Feb 2008 12:35:01 +0000 Subject: Got rid of some noise at startup: complaining when the default configuration file couldn't be found while the user specified an alternative location with the -c option, and double complaints about /var/lib/bitlbee/ permissions. --- bitlbee.h | 3 +-- conf.c | 45 ++++++++++++++++++++++++--------------------- irc_commands.c | 2 +- storage_text.c | 8 ++++---- storage_xml.c | 4 ++-- unix.c | 2 +- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index 55687e3b..c118d7fc 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -121,8 +121,6 @@ #define HELP_FILE VARDIR "help.txt" #define CONF_FILE_DEF ETCDIR "bitlbee.conf" -extern char *CONF_FILE; - #include "irc.h" #include "storage.h" #include "set.h" @@ -144,6 +142,7 @@ typedef struct global { int listen_socket; gint listen_watch_source_id; help_t *help; + char *conf_file; conf_t *conf; GList *storage; /* The first backend in the list will be used for saving */ char *helpfile; diff --git a/conf.c b/conf.c index 94c673cc..57902826 100644 --- a/conf.c +++ b/conf.c @@ -35,14 +35,12 @@ #include "proxy.h" -char *CONF_FILE; - static int conf_loadini( conf_t *conf, char *file ); conf_t *conf_load( int argc, char *argv[] ) { conf_t *conf; - int opt, i; + int opt, i, config_missing = 0; conf = g_new0( conf_t, 1 ); @@ -65,15 +63,17 @@ conf_t *conf_load( int argc, char *argv[] ) conf->user = NULL; proxytype = 0; - i = conf_loadini( conf, CONF_FILE ); + i = conf_loadini( conf, global.conf_file ); if( i == 0 ) { - fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", CONF_FILE ); - return( NULL ); + fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file ); + return NULL; } else if( i == -1 ) { - fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", CONF_FILE ); + config_missing ++; + /* Whine after parsing the options if there was no -c pointing + at a *valid* configuration file. */ } while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 ) @@ -105,16 +105,16 @@ conf_t *conf_load( int argc, char *argv[] ) conf->runmode = RUNMODE_FORKDAEMON; else if( opt == 'c' ) { - if( strcmp( CONF_FILE, optarg ) != 0 ) + if( strcmp( global.conf_file, optarg ) != 0 ) { - g_free( CONF_FILE ); - CONF_FILE = g_strdup( optarg ); + g_free( global.conf_file ); + global.conf_file = g_strdup( optarg ); g_free( conf ); /* Re-evaluate arguments. Don't use this option twice, you'll end up in an infinite loop! Hope this trick works with all libcs BTW.. */ optind = 1; - return( conf_load( argc, argv ) ); + return conf_load( argc, argv ); } } else if( opt == 'd' ) @@ -142,7 +142,7 @@ conf_t *conf_load( int argc, char *argv[] ) " -c Load alternative configuration file\n" " -d Specify alternative user configuration directory\n" " -h Show this help page.\n" ); - return( NULL ); + return NULL; } else if( opt == 'R' ) { @@ -168,7 +168,10 @@ conf_t *conf_load( int argc, char *argv[] ) conf->configdir = s; } - return( conf ); + if( config_missing ) + fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file ); + + return conf; } static int conf_loadini( conf_t *conf, char *file ) @@ -177,7 +180,7 @@ static int conf_loadini( conf_t *conf, char *file ) int i; ini = ini_open( file ); - if( ini == NULL ) return( -1 ); + if( ini == NULL ) return -1; while( ini_read( ini ) ) { if( g_strcasecmp( ini->section, "settings" ) == 0 ) @@ -255,7 +258,7 @@ static int conf_loadini( conf_t *conf, char *file ) if( sscanf( ini->value, "%d", &i ) != 1 ) { fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); - return( 0 ); + return 0; } conf->ping_interval = i; } @@ -264,7 +267,7 @@ static int conf_loadini( conf_t *conf, char *file ) if( sscanf( ini->value, "%d", &i ) != 1 ) { fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); - return( 0 ); + return 0; } conf->ping_timeout = i; } @@ -276,7 +279,7 @@ static int conf_loadini( conf_t *conf, char *file ) { fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); g_free( url ); - return( 0 ); + return 0; } strncpy( proxyhost, url->host, sizeof( proxyhost ) ); @@ -300,7 +303,7 @@ static int conf_loadini( conf_t *conf, char *file ) else { fprintf( stderr, "Error: Unknown setting `%s` in configuration file.\n", ini->key ); - return( 0 ); + return 0; /* For now just ignore unknown keys... */ } } @@ -308,19 +311,19 @@ static int conf_loadini( conf_t *conf, char *file ) { fprintf( stderr, "Error: Unknown section [%s] in configuration file. " "BitlBee configuration must be put in a [settings] section!\n", ini->section ); - return( 0 ); + return 0; } } ini_close( ini ); - return( 1 ); + return 1; } void conf_loaddefaults( irc_t *irc ) { ini_t *ini; - ini = ini_open( CONF_FILE ); + ini = ini_open( global.conf_file ); if( ini == NULL ) return; while( ini_read( ini ) ) { diff --git a/irc_commands.c b/irc_commands.c index 4b431027..68db4617 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -570,7 +570,7 @@ static void irc_cmd_rehash( irc_t *irc, char **cmd ) else ipc_to_master( cmd ); - irc_reply( irc, 382, "%s :Rehashing", CONF_FILE ); + irc_reply( irc, 382, "%s :Rehashing", global.conf_file ); } static const command_t irc_commands[] = { diff --git a/storage_text.c b/storage_text.c index 7c29d95a..5ee6438d 100644 --- a/storage_text.c +++ b/storage_text.c @@ -29,10 +29,10 @@ static void text_init (void) { - if( access( global.conf->configdir, F_OK ) != 0 ) - log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir ); - else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 ) - log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); + /* Don't complain about the configuration directory anymore, leave it + up to the XML storage module, which uses the same directory for it + anyway. Nobody should be using just the text plugin anymore since + it's read only! */ } static storage_status_t text_load ( const char *my_nick, const char* password, irc_t *irc ) diff --git a/storage_xml.c b/storage_xml.c index 4c372cde..19070a74 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -262,9 +262,9 @@ GMarkupParser xml_parser = static void xml_init( void ) { if( access( global.conf->configdir, F_OK ) != 0 ) - log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", global.conf->configdir ); + log_message( LOGLVL_WARNING, "The configuration directory `%s' does not exist. Configuration won't be saved.", global.conf->configdir ); else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 ) - log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir ); + log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", global.conf->configdir ); } static storage_status_t xml_load_real( const char *my_nick, const char *password, irc_t *irc, xml_pass_st action ) diff --git a/unix.c b/unix.c index 9b670d78..d25aeb2e 100644 --- a/unix.c +++ b/unix.c @@ -46,7 +46,7 @@ int main( int argc, char *argv[], char **envp ) struct sigaction sig, old; log_init(); - CONF_FILE = g_strdup( CONF_FILE_DEF ); + global.conf_file = g_strdup( CONF_FILE_DEF ); global.conf = conf_load( argc, argv ); if( global.conf == NULL ) return( 1 ); -- cgit v1.2.3 From 2799ff94059f496b59420d04ec4f41f67aab2b9d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 12:20:03 +0000 Subject: Fixed broken check in check_arc.c --- tests/check_arc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/check_arc.c b/tests/check_arc.c index 989a0a66..a430f899 100644 --- a/tests/check_arc.c +++ b/tests/check_arc.c @@ -61,14 +61,15 @@ struct 0xb6, 0x92, 0x59, 0xe4, 0xf9, 0xc1, 0x7a, 0xf6, 0xf3, 0x18, 0xea, 0x28, 0x73, 0x6d, 0xb3, 0x0a, 0x6f, 0x0a, 0x2b, 0x43, 0x57, 0xe9, 0x3e, 0x63 }, 24, "OSCAR is creepy..." - } + }, + { "", 0, NULL } }; static void check_decod(int l) { int i; - for( i = 0; clear_tests[i]; i++ ) + for( i = 0; decrypt_tests[i].len; i++ ) { tcase_fn_start (decrypt_tests[i].decrypted, __FILE__, __LINE__); char *decrypted; -- cgit v1.2.3 From af97b234ad86fb9d69aa744af426591e4b1eaf97 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 13:17:52 +0000 Subject: Improved sasl_get_part() to deal with whitespace in challenge strings, as described in RFC 2831 secion 7.1 (the #rule description). Closes bug #362. --- protocols/jabber/sasl.c | 27 ++++++++--- tests/Makefile | 4 +- tests/check.c | 4 ++ tests/check_jabber_sasl.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 tests/check_jabber_sasl.c diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 87059051..53248ef3 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -21,6 +21,8 @@ * * \***************************************************************************/ +#include <ctype.h> + #include "jabber.h" #include "base64.h" @@ -106,12 +108,17 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) return XT_HANDLED; } -static char *sasl_get_part( char *data, char *field ) +/* Non-static function, but not mentioned in jabber.h because it's for internal + use, just that the unittest should be able to reach it... */ +char *sasl_get_part( char *data, char *field ) { int i, len; len = strlen( field ); + while( isspace( *data ) || *data == ',' ) + data ++; + if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' ) { i = strlen( field ) + 1; @@ -128,13 +135,19 @@ static char *sasl_get_part( char *data, char *field ) i ++; } - /* If we got a comma, we got a new field. Check it. */ - if( data[i] == ',' && - g_strncasecmp( data + i + 1, field, len ) == 0 && - data[i+len+1] == '=' ) + /* If we got a comma, we got a new field. Check it, + find the next key after it. */ + if( data[i] == ',' ) { - i += len + 2; - break; + while( isspace( data[i] ) || data[i] == ',' ) + i ++; + + if( g_strncasecmp( data + i, field, len ) == 0 && + data[i+len] == '=' ) + { + i += len + 1; + break; + } } } } diff --git a/tests/Makefile b/tests/Makefile index 5bc3fbde..ae76fef5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -10,9 +10,9 @@ clean: distclean: clean -main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o +main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o -test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o check_jabber_sasl.o check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o @echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 043889d6..b3ffb957 100644 --- a/tests/check.c +++ b/tests/check.c @@ -65,6 +65,9 @@ Suite *crypting_suite(void); /* From check_set.c */ Suite *set_suite(void); +/* From check_jabber_sasl.c */ +Suite *jabber_sasl_suite(void); + int main (int argc, char **argv) { int nf; @@ -110,6 +113,7 @@ int main (int argc, char **argv) srunner_add_suite(sr, user_suite()); srunner_add_suite(sr, crypting_suite()); srunner_add_suite(sr, set_suite()); + srunner_add_suite(sr, jabber_sasl_suite()); if (no_fork) srunner_set_fork_status(sr, CK_NOFORK); srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); diff --git a/tests/check_jabber_sasl.c b/tests/check_jabber_sasl.c new file mode 100644 index 00000000..96c05837 --- /dev/null +++ b/tests/check_jabber_sasl.c @@ -0,0 +1,117 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "arc.h" + +char *sasl_get_part( char *data, char *field ); + +#define challenge1 "nonce=\"1669585310\",qop=\"auth\",charset=utf-8,algorithm=md5-sess," \ + "something=\"Not \\\"standardized\\\"\"" +#define challenge2 "realm=\"quadpoint.org\", nonce=\"NPotlQpQf9RNYodOwierkQ==\", " \ + "qop=\"auth, auth-int\", charset=utf-8, algorithm=md5-sess" +#define challenge3 ", realm=\"localhost\", nonce=\"LlBV2txnO8RbB5hgs3KgiQ==\", " \ + "qop=\"auth, auth-int, \", ,\n, charset=utf-8, algorithm=md5-sess," + +struct +{ + const char *challenge; + char *key; + char *value; +} get_part_tests[] = { + { + challenge1, + "nonce", + "1669585310" + }, + { + challenge1, + "charset", + "utf-8" + }, + { + challenge1, + "harset", + NULL + }, + { + challenge1, + "something", + "Not \"standardized\"" + }, + { + challenge1, + "something_else", + NULL + }, + { + challenge2, + "realm", + "quadpoint.org", + }, + { + challenge2, + "real", + NULL + }, + { + challenge2, + "qop", + "auth, auth-int" + }, + { + challenge3, + "realm", + "localhost" + }, + { + challenge3, + "qop", + "auth, auth-int, " + }, + { + challenge3, + "charset", + "utf-8" + }, + { NULL, NULL, NULL } +}; + +static void check_get_part(int l) +{ + int i; + + for( i = 0; get_part_tests[i].key; i++ ) + { + tcase_fn_start( get_part_tests[i].key, __FILE__, i ); + char *res; + int len; + + res = sasl_get_part( get_part_tests[i].challenge, + get_part_tests[i].key ); + + if( get_part_tests[i].value == NULL ) + fail_if( res != NULL, "Found key %s in %s while it shouldn't be there!", + get_part_tests[i].key, get_part_tests[i].challenge ); + else if( res ) + fail_unless( strcmp( res, get_part_tests[i].value ) == 0, + "Incorrect value for key %s in %s: %s", + get_part_tests[i].key, get_part_tests[i].challenge, res ); + else + fail( "Could not find key %s in %s", + get_part_tests[i].key, get_part_tests[i].challenge ); + + g_free( res ); + } +} + +Suite *jabber_sasl_suite (void) +{ + Suite *s = suite_create("jabber/sasl"); + TCase *tc_core = tcase_create("Core"); + suite_add_tcase (s, tc_core); + tcase_add_test (tc_core, check_get_part); + return s; +} -- cgit v1.2.3 From fc5cf88448d4337d1a5fde418df1c6206a9b0ea2 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij <jelmer@samba.org> Date: Sat, 16 Feb 2008 16:45:12 +0100 Subject: Fix lcov dependencies. --- Makefile | 1 - lib/Makefile | 2 +- protocols/Makefile | 2 +- protocols/jabber/Makefile | 2 +- protocols/msn/Makefile | 2 +- protocols/oscar/Makefile | 2 +- protocols/yahoo/Makefile | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 0a988feb..49fc924a 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,6 @@ distclean: clean $(subdirs) check: all $(MAKE) -C tests -lcov: gcov: check gcov *.c diff --git a/lib/Makefile b/lib/Makefile index a79f7c4c..975deceb 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: lib.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/Makefile b/protocols/Makefile index f7d76e0f..18d79e8d 100644 --- a/protocols/Makefile +++ b/protocols/Makefile @@ -26,7 +26,7 @@ LFLAGS += -r # [SH] Phony targets all: protocols.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index e042f812..3ce78127 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: jabber_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index 3440658d..6a588613 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: msn_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/oscar/Makefile b/protocols/oscar/Makefile index 95e85ec2..2792f22a 100644 --- a/protocols/oscar/Makefile +++ b/protocols/oscar/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: oscar_mod.o check: all -lcov: +lcov: check gcov: gcov *.c diff --git a/protocols/yahoo/Makefile b/protocols/yahoo/Makefile index 2cfd147b..b4fe56e2 100644 --- a/protocols/yahoo/Makefile +++ b/protocols/yahoo/Makefile @@ -17,7 +17,7 @@ LFLAGS += -r # [SH] Phony targets all: yahoo_mod.o check: all -lcov: +lcov: check gcov: gcov *.c -- cgit v1.2.3 From a73e91a40ac1110e772214a3401105aeb86d35e4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 17:38:30 +0000 Subject: Added callback on Jabber add-to-roster requests so buddies get added to the internal buddy list a little bit earlier. This should deal better with Jabber servers that send presence information of a new buddy before the roster push. --- protocols/jabber/iq.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index c88bc0b0..38c5a5a9 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -525,6 +525,8 @@ static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_no return XT_HANDLED; } +static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); + int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ) { struct xt_node *node; @@ -540,13 +542,36 @@ int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name ) node = xt_new_node( "query", NULL, node ); xt_add_attr( node, "xmlns", XMLNS_ROSTER ); node = jabber_make_packet( "iq", "set", NULL, node ); + jabber_cache_add( ic, node, jabber_add_to_roster_callback ); st = jabber_write_packet( ic, node ); - xt_free_node( node ); return st; } +static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +{ + char *s, *jid = NULL; + struct xt_node *c; + + if( ( c = xt_find_node( orig->children, "query" ) ) && + ( c = xt_find_node( c->children, "item" ) ) && + ( jid = xt_find_attr( c, "jid" ) ) && + ( s = xt_find_attr( node, "type" ) ) && + strcmp( s, "result" ) == 0 ) + { + if( imcb_find_buddy( ic, jid ) == NULL ) + imcb_add_buddy( ic, jid, NULL ); + } + else + { + imcb_log( ic, "Error while adding `%s' to your contact list.", + jid ? jid : "(unknown handle)" ); + } + + return XT_HANDLED; +} + int jabber_remove_from_roster( struct im_connection *ic, char *handle ) { struct xt_node *node; -- cgit v1.2.3 From 2d88d25aeb62d90e4288f8b83979baaff96cb7f2 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 19:38:17 +0000 Subject: Added help_free() test, and fixed compiler warning in SASL test. --- tests/check_help.c | 7 +++++-- tests/check_jabber_sasl.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/check_help.c b/tests/check_help.c index 7e5283e3..5a2f28d9 100644 --- a/tests/check_help.c +++ b/tests/check_help.c @@ -6,11 +6,14 @@ #include <stdio.h> #include "help.h" -START_TEST(test_help_none) +START_TEST(test_help_initfree) help_t *h, *r; r = help_init(&h, "/dev/null"); fail_if(r == NULL); fail_if(r != h); + + help_free(&h); + fail_if(h != NULL); END_TEST START_TEST(test_help_nonexistent) @@ -24,7 +27,7 @@ Suite *help_suite (void) Suite *s = suite_create("Help"); TCase *tc_core = tcase_create("Core"); suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_help_none); + tcase_add_test (tc_core, test_help_initfree); tcase_add_test (tc_core, test_help_nonexistent); return s; } diff --git a/tests/check_jabber_sasl.c b/tests/check_jabber_sasl.c index 96c05837..6bceeb88 100644 --- a/tests/check_jabber_sasl.c +++ b/tests/check_jabber_sasl.c @@ -17,7 +17,7 @@ char *sasl_get_part( char *data, char *field ); struct { - const char *challenge; + char *challenge; char *key; char *value; } get_part_tests[] = { -- cgit v1.2.3 From add23a26034a7368f4fdc0707488719048322e89 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 22:07:14 +0000 Subject: Moved xmltree to lib/ because I want to use it from more than just the Jabber module. --- lib/Makefile | 2 +- lib/xmltree.c | 589 +++++++++++++++++++++++++++++++++++++++++++++ lib/xmltree.h | 97 ++++++++ protocols/jabber/Makefile | 2 +- protocols/jabber/xmltree.c | 589 --------------------------------------------- protocols/jabber/xmltree.h | 97 -------- 6 files changed, 688 insertions(+), 688 deletions(-) create mode 100644 lib/xmltree.c create mode 100644 lib/xmltree.h delete mode 100644 protocols/jabber/xmltree.c delete mode 100644 protocols/jabber/xmltree.h diff --git a/lib/Makefile b/lib/Makefile index 975deceb..03fef1ab 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@ -include ../Makefile.settings # [SH] Program variables -objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o +objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o CFLAGS += -Wall LFLAGS += -r diff --git a/lib/xmltree.c b/lib/xmltree.c new file mode 100644 index 00000000..62549eb5 --- /dev/null +++ b/lib/xmltree.c @@ -0,0 +1,589 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* 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, version * +* 2.1. * +* * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +#include <glib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <stdio.h> + +#include "xmltree.h" + +static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; + int i; + + node->parent = xt->cur; + node->name = g_strdup( element_name ); + + /* First count the number of attributes */ + for( i = 0; attr_names[i]; i ++ ); + + /* Then allocate a NULL-terminated array. */ + node->attr = g_new0( struct xt_attr, i + 1 ); + + /* And fill it, saving one variable by starting at the end. */ + for( i --; i >= 0; i -- ) + { + node->attr[i].key = g_strdup( attr_names[i] ); + node->attr[i].value = g_strdup( attr_values[i] ); + } + + /* Add it to the linked list of children nodes, if we have a current + node yet. */ + if( xt->cur ) + { + if( xt->cur->children ) + { + for( nt = xt->cur->children; nt->next; nt = nt->next ); + nt->next = node; + } + else + { + xt->cur->children = node; + } + } + else if( xt->root ) + { + /* ERROR situation: A second root-element??? */ + } + + /* Now this node will be the new current node. */ + xt->cur = node; + /* And maybe this is the root? */ + if( xt->root == NULL ) + xt->root = node; +} + +static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + struct xt_node *node = xt->cur; + + if( node == NULL ) + return; + + /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ + node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); + memcpy( node->text + node->text_len, text, text_len ); + node->text_len += text_len; + /* Zero termination is always nice to have. */ + node->text[node->text_len] = 0; +} + +static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) +{ + struct xt_parser *xt = data; + + xt->cur->flags |= XT_COMPLETE; + xt->cur = xt->cur->parent; +} + +GMarkupParser xt_parser_funcs = +{ + xt_start_element, + xt_end_element, + xt_text, + NULL, + NULL +}; + +struct xt_parser *xt_new( gpointer data ) +{ + struct xt_parser *xt = g_new0( struct xt_parser, 1 ); + + xt->data = data; + xt_reset( xt ); + + return xt; +} + +/* Reset the parser, flush everything we have so far. For example, we need + this for XMPP when doing TLS/SASL to restart the stream. */ +void xt_reset( struct xt_parser *xt ) +{ + if( xt->parser ) + g_markup_parse_context_free( xt->parser ); + + xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); + + if( xt->root ) + { + xt_free_node( xt->root ); + xt->root = NULL; + xt->cur = NULL; + } +} + +/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on + end-of-stream and 1 otherwise. */ +int xt_feed( struct xt_parser *xt, char *text, int text_len ) +{ + if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) + { + return -1; + } + + return !( xt->root && xt->root->flags & XT_COMPLETE ); +} + +/* Find completed nodes and see if a handler has to be called. Passing + a node isn't necessary if you want to start at the root, just pass + NULL. This second argument is needed for recursive calls. */ +int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) +{ + struct xt_node *c; + xt_status st; + int i; + + /* Just in case someone likes infinite loops... */ + if( xt->root == NULL ) + return 0; + + if( node == NULL ) + return xt_handle( xt, xt->root, depth ); + + if( depth != 0 ) + for( c = node->children; c; c = c->next ) + if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) + return 0; + + if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) + { + for( i = 0; xt->handlers[i].func; i ++ ) + { + /* This one is fun! \o/ */ + + /* If handler.name == NULL it means it should always match. */ + if( ( xt->handlers[i].name == NULL || + /* If it's not, compare. There should always be a name. */ + g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && + /* If handler.parent == NULL, it's a match. */ + ( xt->handlers[i].parent == NULL || + /* If there's a parent node, see if the name matches. */ + ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : + /* If there's no parent, the handler should mention <root> as a parent. */ + g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) + { + st = xt->handlers[i].func( node, xt->data ); + + if( st == XT_ABORT ) + return 0; + else if( st != XT_NEXT ) + break; + } + } + + node->flags |= XT_SEEN; + } + + return 1; +} + +/* Garbage collection: Cleans up all nodes that are handled. Useful for + streams because there's no reason to keep a complete packet history + in memory. */ +void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) +{ + struct xt_node *c, *prev; + + if( !xt || !xt->root ) + return; + + if( node == NULL ) + return xt_cleanup( xt, xt->root, depth ); + + if( node->flags & XT_SEEN && node == xt->root ) + { + xt_free_node( xt->root ); + xt->root = xt->cur = NULL; + /* xt->cur should be NULL already, BTW... */ + + return; + } + + /* c contains the current node, prev the previous node (or NULL). + I admit, this one's pretty horrible. */ + for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) + { + if( c->flags & XT_SEEN ) + { + /* Remove the node from the linked list. */ + if( prev ) + prev->next = c->next; + else + node->children = c->next; + + xt_free_node( c ); + + /* Since the for loop wants to get c->next, make sure + c points at something that exists (and that c->next + will actually be the next item we should check). c + can be NULL now, if we just removed the first item. + That explains the ? thing in for(). */ + c = prev; + } + else + { + /* This node can't be cleaned up yet, but maybe a + subnode can. */ + if( depth != 0 ) + xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); + } + } +} + +static void xt_to_string_real( struct xt_node *node, GString *str ) +{ + char *buf; + struct xt_node *c; + int i; + + g_string_append_printf( str, "<%s", node->name ); + + for( i = 0; node->attr[i].key; i ++ ) + { + buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); + g_string_append( str, buf ); + g_free( buf ); + } + + if( node->text == NULL && node->children == NULL ) + { + g_string_append( str, "/>" ); + return; + } + + g_string_append( str, ">" ); + if( node->text_len > 0 ) + { + buf = g_markup_escape_text( node->text, node->text_len ); + g_string_append( str, buf ); + g_free( buf ); + } + + for( c = node->children; c; c = c->next ) + xt_to_string_real( c, str ); + + g_string_append_printf( str, "</%s>", node->name ); +} + +char *xt_to_string( struct xt_node *node ) +{ + GString *ret; + char *real; + + ret = g_string_new( "" ); + xt_to_string_real( node, ret ); + + real = ret->str; + g_string_free( ret, FALSE ); + + return real; +} + +#ifdef DEBUG +void xt_print( struct xt_node *node ) +{ + int i; + struct xt_node *c; + + /* Indentation */ + for( c = node; c->parent; c = c->parent ) + printf( "\t" ); + + /* Start the tag */ + printf( "<%s", node->name ); + + /* Print the attributes */ + for( i = 0; node->attr[i].key; i ++ ) + printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); + + /* /> in case there's really *nothing* inside this tag, otherwise + just >. */ + /* If this tag doesn't have any content at all... */ + if( node->text == NULL && node->children == NULL ) + { + printf( "/>\n" ); + return; + /* Then we're finished! */ + } + + /* Otherwise... */ + printf( ">" ); + + /* Only print the text if it contains more than whitespace (TEST). */ + if( node->text_len > 0 ) + { + for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); + if( node->text[i] ) + printf( "%s", g_markup_escape_text( node->text, -1 ) ); + } + + if( node->children ) + printf( "\n" ); + + for( c = node->children; c; c = c->next ) + xt_print( c ); + + if( node->children ) + for( c = node; c->parent; c = c->parent ) + printf( "\t" ); + + /* Non-empty tag is now finished. */ + printf( "</%s>\n", node->name ); +} +#endif + +struct xt_node *xt_dup( struct xt_node *node ) +{ + struct xt_node *dup = g_new0( struct xt_node, 1 ); + struct xt_node *c, *dc = NULL; + int i; + + /* Let's NOT copy the parent element here BTW! Only do it for children. */ + + dup->name = g_strdup( node->name ); + dup->flags = node->flags; + if( node->text ) + { + dup->text = g_memdup( node->text, node->text_len + 1 ); + dup->text_len = node->text_len; + } + + /* Count the number of attributes and allocate the new array. */ + for( i = 0; node->attr[i].key; i ++ ); + dup->attr = g_new0( struct xt_attr, i + 1 ); + + /* Copy them all! */ + for( i --; i >= 0; i -- ) + { + dup->attr[i].key = g_strdup( node->attr[i].key ); + dup->attr[i].value = g_strdup( node->attr[i].value ); + } + + /* This nice mysterious loop takes care of the children. */ + for( c = node->children; c; c = c->next ) + { + if( dc == NULL ) + dc = dup->children = xt_dup( c ); + else + dc = ( dc->next = xt_dup( c ) ); + + dc->parent = dup; + } + + return dup; +} + +/* Frees a node. This doesn't clean up references to itself from parents! */ +void xt_free_node( struct xt_node *node ) +{ + int i; + + if( !node ) + return; + + g_free( node->name ); + g_free( node->text ); + + for( i = 0; node->attr[i].key; i ++ ) + { + g_free( node->attr[i].key ); + g_free( node->attr[i].value ); + } + g_free( node->attr ); + + while( node->children ) + { + struct xt_node *next = node->children->next; + + xt_free_node( node->children ); + node->children = next; + } + + g_free( node ); +} + +void xt_free( struct xt_parser *xt ) +{ + if( !xt ) + return; + + if( xt->root ) + xt_free_node( xt->root ); + + g_markup_parse_context_free( xt->parser ); + + g_free( xt ); +} + +/* To find a node's child with a specific name, pass the node's children + list, not the node itself! The reason you have to do this by hand: So + that you can also use this function as a find-next. */ +struct xt_node *xt_find_node( struct xt_node *node, const char *name ) +{ + while( node ) + { + if( g_strcasecmp( node->name, name ) == 0 ) + break; + + node = node->next; + } + + return node; +} + +char *xt_find_attr( struct xt_node *node, const char *key ) +{ + int i; + + if( !node ) + return NULL; + + for( i = 0; node->attr[i].key; i ++ ) + if( g_strcasecmp( node->attr[i].key, key ) == 0 ) + break; + + return node->attr[i].value; +} + +struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) +{ + struct xt_node *node, *c; + + node = g_new0( struct xt_node, 1 ); + node->name = g_strdup( name ); + node->children = children; + node->attr = g_new0( struct xt_attr, 1 ); + + if( text ) + { + node->text_len = strlen( text ); + node->text = g_memdup( text, node->text_len + 1 ); + } + + for( c = children; c; c = c->next ) + { + if( c->parent != NULL ) + { + /* ERROR CONDITION: They seem to have a parent already??? */ + } + + c->parent = node; + } + + return node; +} + +void xt_add_child( struct xt_node *parent, struct xt_node *child ) +{ + struct xt_node *node; + + /* This function can actually be used to add more than one child, so + do handle this properly. */ + for( node = child; node; node = node->next ) + { + if( node->parent != NULL ) + { + /* ERROR CONDITION: They seem to have a parent already??? */ + } + + node->parent = parent; + } + + if( parent->children == NULL ) + { + parent->children = child; + } + else + { + for( node = parent->children; node->next; node = node->next ); + node->next = child; + } +} + +void xt_add_attr( struct xt_node *node, const char *key, const char *value ) +{ + int i; + + /* Now actually it'd be nice if we can also change existing attributes + (which actually means this function doesn't have the right name). + So let's find out if we have this attribute already... */ + for( i = 0; node->attr[i].key; i ++ ) + if( strcmp( node->attr[i].key, key ) == 0 ) + break; + + if( node->attr[i].key == NULL ) + { + /* If not, allocate space for a new attribute. */ + node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); + node->attr[i].key = g_strdup( key ); + node->attr[i+1].key = NULL; + } + else + { + /* Otherwise, free the old value before setting the new one. */ + g_free( node->attr[i].value ); + } + + node->attr[i].value = g_strdup( value ); +} + +int xt_remove_attr( struct xt_node *node, const char *key ) +{ + int i, last; + + for( i = 0; node->attr[i].key; i ++ ) + if( strcmp( node->attr[i].key, key ) == 0 ) + break; + + /* If we didn't find the attribute... */ + if( node->attr[i].key == NULL ) + return 0; + + g_free( node->attr[i].key ); + g_free( node->attr[i].value ); + + /* If it's the last, this is easy: */ + if( node->attr[i+1].key == NULL ) + { + node->attr[i].key = node->attr[i].value = NULL; + } + else /* It's also pretty easy, actually. */ + { + /* Find the last item. */ + for( last = i + 1; node->attr[last+1].key; last ++ ); + + node->attr[i] = node->attr[last]; + node->attr[last].key = NULL; + node->attr[last].value = NULL; + } + + /* Let's not bother with reallocating memory here. It takes time and + most packets don't stay in memory for long anyway. */ + + return 1; +} diff --git a/lib/xmltree.h b/lib/xmltree.h new file mode 100644 index 00000000..b8b61641 --- /dev/null +++ b/lib/xmltree.h @@ -0,0 +1,97 @@ +/***************************************************************************\ +* * +* BitlBee - An IRC to IM gateway * +* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * +* * +* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * +* * +* 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, version * +* 2.1. * +* * +* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * +* * +****************************************************************************/ + +#ifndef _XMLTREE_H +#define _XMLTREE_H + +typedef enum +{ + XT_COMPLETE = 1, /* </tag> reached */ + XT_SEEN = 2, /* Handler called (or not defined) */ +} xt_flags; + +typedef enum +{ + XT_ABORT, /* Abort, don't handle the rest anymore */ + XT_HANDLED, /* Handled this tag properly, go to the next one */ + XT_NEXT /* Try if there's another matching handler */ +} xt_status; + +struct xt_attr +{ + char *key, *value; +}; + +struct xt_node +{ + struct xt_node *parent; + struct xt_node *children; + + char *name; + struct xt_attr *attr; + char *text; + int text_len; + + struct xt_node *next; + xt_flags flags; +}; + +typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); + +struct xt_handler_entry +{ + char *name, *parent; + xt_handler_func func; +}; + +struct xt_parser +{ + GMarkupParseContext *parser; + struct xt_node *root; + struct xt_node *cur; + + struct xt_handler_entry *handlers; + gpointer data; + + GError *gerr; +}; + +struct xt_parser *xt_new( gpointer data ); +void xt_reset( struct xt_parser *xt ); +int xt_feed( struct xt_parser *xt, char *text, int text_len ); +int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); +void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); +char *xt_to_string( struct xt_node *node ); +void xt_print( struct xt_node *node ); +struct xt_node *xt_dup( struct xt_node *node ); +void xt_free_node( struct xt_node *node ); +void xt_free( struct xt_parser *xt ); +struct xt_node *xt_find_node( struct xt_node *node, const char *name ); +char *xt_find_attr( struct xt_node *node, const char *key ); + +struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); +void xt_add_child( struct xt_node *parent, struct xt_node *child ); +void xt_add_attr( struct xt_node *node, const char *key, const char *value ); +int xt_remove_attr( struct xt_node *node, const char *key ); + +#endif diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index 3ce78127..e7a505ba 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@ -include ../../Makefile.settings # [SH] Program variables -objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o +objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o CFLAGS += -Wall LFLAGS += -r diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c deleted file mode 100644 index 62549eb5..00000000 --- a/protocols/jabber/xmltree.c +++ /dev/null @@ -1,589 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * -* * -* 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, version * -* 2.1. * -* * -* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * -* * -****************************************************************************/ - -#include <glib.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <stdio.h> - -#include "xmltree.h" - -static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; - int i; - - node->parent = xt->cur; - node->name = g_strdup( element_name ); - - /* First count the number of attributes */ - for( i = 0; attr_names[i]; i ++ ); - - /* Then allocate a NULL-terminated array. */ - node->attr = g_new0( struct xt_attr, i + 1 ); - - /* And fill it, saving one variable by starting at the end. */ - for( i --; i >= 0; i -- ) - { - node->attr[i].key = g_strdup( attr_names[i] ); - node->attr[i].value = g_strdup( attr_values[i] ); - } - - /* Add it to the linked list of children nodes, if we have a current - node yet. */ - if( xt->cur ) - { - if( xt->cur->children ) - { - for( nt = xt->cur->children; nt->next; nt = nt->next ); - nt->next = node; - } - else - { - xt->cur->children = node; - } - } - else if( xt->root ) - { - /* ERROR situation: A second root-element??? */ - } - - /* Now this node will be the new current node. */ - xt->cur = node; - /* And maybe this is the root? */ - if( xt->root == NULL ) - xt->root = node; -} - -static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - struct xt_node *node = xt->cur; - - if( node == NULL ) - return; - - /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ - node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); - memcpy( node->text + node->text_len, text, text_len ); - node->text_len += text_len; - /* Zero termination is always nice to have. */ - node->text[node->text_len] = 0; -} - -static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) -{ - struct xt_parser *xt = data; - - xt->cur->flags |= XT_COMPLETE; - xt->cur = xt->cur->parent; -} - -GMarkupParser xt_parser_funcs = -{ - xt_start_element, - xt_end_element, - xt_text, - NULL, - NULL -}; - -struct xt_parser *xt_new( gpointer data ) -{ - struct xt_parser *xt = g_new0( struct xt_parser, 1 ); - - xt->data = data; - xt_reset( xt ); - - return xt; -} - -/* Reset the parser, flush everything we have so far. For example, we need - this for XMPP when doing TLS/SASL to restart the stream. */ -void xt_reset( struct xt_parser *xt ) -{ - if( xt->parser ) - g_markup_parse_context_free( xt->parser ); - - xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); - - if( xt->root ) - { - xt_free_node( xt->root ); - xt->root = NULL; - xt->cur = NULL; - } -} - -/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on - end-of-stream and 1 otherwise. */ -int xt_feed( struct xt_parser *xt, char *text, int text_len ) -{ - if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) - { - return -1; - } - - return !( xt->root && xt->root->flags & XT_COMPLETE ); -} - -/* Find completed nodes and see if a handler has to be called. Passing - a node isn't necessary if you want to start at the root, just pass - NULL. This second argument is needed for recursive calls. */ -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) -{ - struct xt_node *c; - xt_status st; - int i; - - /* Just in case someone likes infinite loops... */ - if( xt->root == NULL ) - return 0; - - if( node == NULL ) - return xt_handle( xt, xt->root, depth ); - - if( depth != 0 ) - for( c = node->children; c; c = c->next ) - if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) - return 0; - - if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) - { - for( i = 0; xt->handlers[i].func; i ++ ) - { - /* This one is fun! \o/ */ - - /* If handler.name == NULL it means it should always match. */ - if( ( xt->handlers[i].name == NULL || - /* If it's not, compare. There should always be a name. */ - g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && - /* If handler.parent == NULL, it's a match. */ - ( xt->handlers[i].parent == NULL || - /* If there's a parent node, see if the name matches. */ - ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : - /* If there's no parent, the handler should mention <root> as a parent. */ - g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) - { - st = xt->handlers[i].func( node, xt->data ); - - if( st == XT_ABORT ) - return 0; - else if( st != XT_NEXT ) - break; - } - } - - node->flags |= XT_SEEN; - } - - return 1; -} - -/* Garbage collection: Cleans up all nodes that are handled. Useful for - streams because there's no reason to keep a complete packet history - in memory. */ -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) -{ - struct xt_node *c, *prev; - - if( !xt || !xt->root ) - return; - - if( node == NULL ) - return xt_cleanup( xt, xt->root, depth ); - - if( node->flags & XT_SEEN && node == xt->root ) - { - xt_free_node( xt->root ); - xt->root = xt->cur = NULL; - /* xt->cur should be NULL already, BTW... */ - - return; - } - - /* c contains the current node, prev the previous node (or NULL). - I admit, this one's pretty horrible. */ - for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) - { - if( c->flags & XT_SEEN ) - { - /* Remove the node from the linked list. */ - if( prev ) - prev->next = c->next; - else - node->children = c->next; - - xt_free_node( c ); - - /* Since the for loop wants to get c->next, make sure - c points at something that exists (and that c->next - will actually be the next item we should check). c - can be NULL now, if we just removed the first item. - That explains the ? thing in for(). */ - c = prev; - } - else - { - /* This node can't be cleaned up yet, but maybe a - subnode can. */ - if( depth != 0 ) - xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); - } - } -} - -static void xt_to_string_real( struct xt_node *node, GString *str ) -{ - char *buf; - struct xt_node *c; - int i; - - g_string_append_printf( str, "<%s", node->name ); - - for( i = 0; node->attr[i].key; i ++ ) - { - buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); - g_string_append( str, buf ); - g_free( buf ); - } - - if( node->text == NULL && node->children == NULL ) - { - g_string_append( str, "/>" ); - return; - } - - g_string_append( str, ">" ); - if( node->text_len > 0 ) - { - buf = g_markup_escape_text( node->text, node->text_len ); - g_string_append( str, buf ); - g_free( buf ); - } - - for( c = node->children; c; c = c->next ) - xt_to_string_real( c, str ); - - g_string_append_printf( str, "</%s>", node->name ); -} - -char *xt_to_string( struct xt_node *node ) -{ - GString *ret; - char *real; - - ret = g_string_new( "" ); - xt_to_string_real( node, ret ); - - real = ret->str; - g_string_free( ret, FALSE ); - - return real; -} - -#ifdef DEBUG -void xt_print( struct xt_node *node ) -{ - int i; - struct xt_node *c; - - /* Indentation */ - for( c = node; c->parent; c = c->parent ) - printf( "\t" ); - - /* Start the tag */ - printf( "<%s", node->name ); - - /* Print the attributes */ - for( i = 0; node->attr[i].key; i ++ ) - printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); - - /* /> in case there's really *nothing* inside this tag, otherwise - just >. */ - /* If this tag doesn't have any content at all... */ - if( node->text == NULL && node->children == NULL ) - { - printf( "/>\n" ); - return; - /* Then we're finished! */ - } - - /* Otherwise... */ - printf( ">" ); - - /* Only print the text if it contains more than whitespace (TEST). */ - if( node->text_len > 0 ) - { - for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); - if( node->text[i] ) - printf( "%s", g_markup_escape_text( node->text, -1 ) ); - } - - if( node->children ) - printf( "\n" ); - - for( c = node->children; c; c = c->next ) - xt_print( c ); - - if( node->children ) - for( c = node; c->parent; c = c->parent ) - printf( "\t" ); - - /* Non-empty tag is now finished. */ - printf( "</%s>\n", node->name ); -} -#endif - -struct xt_node *xt_dup( struct xt_node *node ) -{ - struct xt_node *dup = g_new0( struct xt_node, 1 ); - struct xt_node *c, *dc = NULL; - int i; - - /* Let's NOT copy the parent element here BTW! Only do it for children. */ - - dup->name = g_strdup( node->name ); - dup->flags = node->flags; - if( node->text ) - { - dup->text = g_memdup( node->text, node->text_len + 1 ); - dup->text_len = node->text_len; - } - - /* Count the number of attributes and allocate the new array. */ - for( i = 0; node->attr[i].key; i ++ ); - dup->attr = g_new0( struct xt_attr, i + 1 ); - - /* Copy them all! */ - for( i --; i >= 0; i -- ) - { - dup->attr[i].key = g_strdup( node->attr[i].key ); - dup->attr[i].value = g_strdup( node->attr[i].value ); - } - - /* This nice mysterious loop takes care of the children. */ - for( c = node->children; c; c = c->next ) - { - if( dc == NULL ) - dc = dup->children = xt_dup( c ); - else - dc = ( dc->next = xt_dup( c ) ); - - dc->parent = dup; - } - - return dup; -} - -/* Frees a node. This doesn't clean up references to itself from parents! */ -void xt_free_node( struct xt_node *node ) -{ - int i; - - if( !node ) - return; - - g_free( node->name ); - g_free( node->text ); - - for( i = 0; node->attr[i].key; i ++ ) - { - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - } - g_free( node->attr ); - - while( node->children ) - { - struct xt_node *next = node->children->next; - - xt_free_node( node->children ); - node->children = next; - } - - g_free( node ); -} - -void xt_free( struct xt_parser *xt ) -{ - if( !xt ) - return; - - if( xt->root ) - xt_free_node( xt->root ); - - g_markup_parse_context_free( xt->parser ); - - g_free( xt ); -} - -/* To find a node's child with a specific name, pass the node's children - list, not the node itself! The reason you have to do this by hand: So - that you can also use this function as a find-next. */ -struct xt_node *xt_find_node( struct xt_node *node, const char *name ) -{ - while( node ) - { - if( g_strcasecmp( node->name, name ) == 0 ) - break; - - node = node->next; - } - - return node; -} - -char *xt_find_attr( struct xt_node *node, const char *key ) -{ - int i; - - if( !node ) - return NULL; - - for( i = 0; node->attr[i].key; i ++ ) - if( g_strcasecmp( node->attr[i].key, key ) == 0 ) - break; - - return node->attr[i].value; -} - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ) -{ - struct xt_node *node, *c; - - node = g_new0( struct xt_node, 1 ); - node->name = g_strdup( name ); - node->children = children; - node->attr = g_new0( struct xt_attr, 1 ); - - if( text ) - { - node->text_len = strlen( text ); - node->text = g_memdup( text, node->text_len + 1 ); - } - - for( c = children; c; c = c->next ) - { - if( c->parent != NULL ) - { - /* ERROR CONDITION: They seem to have a parent already??? */ - } - - c->parent = node; - } - - return node; -} - -void xt_add_child( struct xt_node *parent, struct xt_node *child ) -{ - struct xt_node *node; - - /* This function can actually be used to add more than one child, so - do handle this properly. */ - for( node = child; node; node = node->next ) - { - if( node->parent != NULL ) - { - /* ERROR CONDITION: They seem to have a parent already??? */ - } - - node->parent = parent; - } - - if( parent->children == NULL ) - { - parent->children = child; - } - else - { - for( node = parent->children; node->next; node = node->next ); - node->next = child; - } -} - -void xt_add_attr( struct xt_node *node, const char *key, const char *value ) -{ - int i; - - /* Now actually it'd be nice if we can also change existing attributes - (which actually means this function doesn't have the right name). - So let's find out if we have this attribute already... */ - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) - break; - - if( node->attr[i].key == NULL ) - { - /* If not, allocate space for a new attribute. */ - node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); - node->attr[i].key = g_strdup( key ); - node->attr[i+1].key = NULL; - } - else - { - /* Otherwise, free the old value before setting the new one. */ - g_free( node->attr[i].value ); - } - - node->attr[i].value = g_strdup( value ); -} - -int xt_remove_attr( struct xt_node *node, const char *key ) -{ - int i, last; - - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) - break; - - /* If we didn't find the attribute... */ - if( node->attr[i].key == NULL ) - return 0; - - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - - /* If it's the last, this is easy: */ - if( node->attr[i+1].key == NULL ) - { - node->attr[i].key = node->attr[i].value = NULL; - } - else /* It's also pretty easy, actually. */ - { - /* Find the last item. */ - for( last = i + 1; node->attr[last+1].key; last ++ ); - - node->attr[i] = node->attr[last]; - node->attr[last].key = NULL; - node->attr[last].value = NULL; - } - - /* Let's not bother with reallocating memory here. It takes time and - most packets don't stay in memory for long anyway. */ - - return 1; -} diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h deleted file mode 100644 index b8b61641..00000000 --- a/protocols/jabber/xmltree.h +++ /dev/null @@ -1,97 +0,0 @@ -/***************************************************************************\ -* * -* BitlBee - An IRC to IM gateway * -* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) * -* * -* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> * -* * -* 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, version * -* 2.1. * -* * -* 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 St, Fifth Floor, Boston, MA 02110-1301 USA * -* * -****************************************************************************/ - -#ifndef _XMLTREE_H -#define _XMLTREE_H - -typedef enum -{ - XT_COMPLETE = 1, /* </tag> reached */ - XT_SEEN = 2, /* Handler called (or not defined) */ -} xt_flags; - -typedef enum -{ - XT_ABORT, /* Abort, don't handle the rest anymore */ - XT_HANDLED, /* Handled this tag properly, go to the next one */ - XT_NEXT /* Try if there's another matching handler */ -} xt_status; - -struct xt_attr -{ - char *key, *value; -}; - -struct xt_node -{ - struct xt_node *parent; - struct xt_node *children; - - char *name; - struct xt_attr *attr; - char *text; - int text_len; - - struct xt_node *next; - xt_flags flags; -}; - -typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); - -struct xt_handler_entry -{ - char *name, *parent; - xt_handler_func func; -}; - -struct xt_parser -{ - GMarkupParseContext *parser; - struct xt_node *root; - struct xt_node *cur; - - struct xt_handler_entry *handlers; - gpointer data; - - GError *gerr; -}; - -struct xt_parser *xt_new( gpointer data ); -void xt_reset( struct xt_parser *xt ); -int xt_feed( struct xt_parser *xt, char *text, int text_len ); -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); -char *xt_to_string( struct xt_node *node ); -void xt_print( struct xt_node *node ); -struct xt_node *xt_dup( struct xt_node *node ); -void xt_free_node( struct xt_node *node ); -void xt_free( struct xt_parser *xt ); -struct xt_node *xt_find_node( struct xt_node *node, const char *name ); -char *xt_find_attr( struct xt_node *node, const char *key ); - -struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children ); -void xt_add_child( struct xt_node *parent, struct xt_node *child ); -void xt_add_attr( struct xt_node *node, const char *key, const char *value ); -int xt_remove_attr( struct xt_node *node, const char *key ); - -#endif -- cgit v1.2.3 From 4bbcba32aca2948f66c484ab074264fdb67609ae Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sat, 16 Feb 2008 22:40:38 +0000 Subject: Moved xmltree handlers initialization to xt_new(). --- lib/xmltree.c | 3 ++- lib/xmltree.h | 4 ++-- protocols/jabber/io.c | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/xmltree.c b/lib/xmltree.c index 62549eb5..e65b4f41 100644 --- a/lib/xmltree.c +++ b/lib/xmltree.c @@ -110,11 +110,12 @@ GMarkupParser xt_parser_funcs = NULL }; -struct xt_parser *xt_new( gpointer data ) +struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data ) { struct xt_parser *xt = g_new0( struct xt_parser, 1 ); xt->data = data; + xt->handlers = handlers; xt_reset( xt ); return xt; diff --git a/lib/xmltree.h b/lib/xmltree.h index b8b61641..10677412 100644 --- a/lib/xmltree.h +++ b/lib/xmltree.h @@ -70,13 +70,13 @@ struct xt_parser struct xt_node *root; struct xt_node *cur; - struct xt_handler_entry *handlers; + const struct xt_handler_entry *handlers; gpointer data; GError *gerr; }; -struct xt_parser *xt_new( gpointer data ); +struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data ); void xt_reset( struct xt_parser *xt ); int xt_feed( struct xt_parser *xt, char *text, int text_len ); int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 86c216ef..9980dc8e 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -520,8 +520,7 @@ gboolean jabber_start_stream( struct im_connection *ic ) /* We'll start our stream now, so prepare everything to receive one from the server too. */ xt_free( jd->xt ); /* In case we're RE-starting. */ - jd->xt = xt_new( ic ); - jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers; + jd->xt = xt_new( jabber_handlers, ic ); if( jd->r_inpa <= 0 ) jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic ); -- cgit v1.2.3 From e6648bf3b821ae40c0640857aae069bc0f5d90c4 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 17 Feb 2008 11:16:01 +0000 Subject: Replaced old MSN Passport (v1.4) authentication code with what's described on http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener . This was an attempt to fix bug #360, but it didn't. However, this change may make BitlBee a little bit more future-proof. Plus, the code is tidier and sometimes faster than the old mechanism. --- protocols/msn/ns.c | 30 +++--- protocols/msn/passport.c | 275 ++++++++++++++++++----------------------------- protocols/msn/passport.h | 91 +++++++++++++--- 3 files changed, 200 insertions(+), 196 deletions(-) diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 0bb84a74..ff7da6ed 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -33,7 +33,7 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -static void msn_auth_got_passport_id( struct passport_reply *rep ); +static void msn_auth_got_passport_token( struct msn_auth_data *mad ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) { @@ -213,7 +213,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* Time for some Passport black magic... */ - if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) + if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) { imcb_error( ic, "Error while contacting Passport server" ); imc_logout( ic, TRUE ); @@ -673,22 +673,26 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int return( 1 ); } -static void msn_auth_got_passport_id( struct passport_reply *rep ) +static void msn_auth_got_passport_token( struct msn_auth_data *mad ) { - struct im_connection *ic = rep->data; - struct msn_data *md = ic->proto_data; - char *key = rep->result; - char buf[1024]; + struct im_connection *ic = mad->data; + struct msn_data *md; - if( key == NULL ) + /* Dead connection? */ + if( g_slist_find( msn_connections, ic ) == NULL ) + return; + + md = ic->proto_data; + if( mad->token ) { - imcb_error( ic, "Error during Passport authentication (%s)", - rep->error_string ? rep->error_string : "Unknown error" ); - imc_logout( ic, TRUE ); + char buf[1024]; + + g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); + msn_write( ic, buf, strlen( buf ) ); } else { - g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key ); - msn_write( ic, buf, strlen( buf ) ); + imcb_error( ic, "Error during Passport authentication: %s", mad->error ); + imc_logout( ic, TRUE ); } } diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 9fe6a174..7a15c3fe 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -1,8 +1,7 @@ -/* passport.c +/** passport.c * - * Functions to login to microsoft passport service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be> - * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -23,208 +22,144 @@ #include "passport.h" #include "msn.h" #include "bitlbee.h" +#include "url.h" +#include "misc.h" +#include "xmltree.h" #include <ctype.h> #include <errno.h> -#define MSN_BUF_LEN 8192 +static int passport_get_token_real( struct msn_auth_data *mad ); +static void passport_get_token_ready( struct http_request *req ); -static char *prd_cached = NULL; - -static int passport_get_id_real( gpointer func, gpointer data, char *header ); -static void passport_get_id_ready( struct http_request *req ); - -static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ); -static void passport_retrieve_dalogin_ready( struct http_request *req ); - -static char *passport_create_header( char *cookie, char *email, char *pwd ); -static void destroy_reply( struct passport_reply *rep ); - -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ) +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ) { - char *header = passport_create_header( cookie, username, password ); + struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 ); + int i; - if( prd_cached == NULL ) - return passport_retrieve_dalogin( func, data, header ); - else - return passport_get_id_real( func, data, header ); + mad->username = g_strdup( username ); + mad->password = g_strdup( password ); + mad->cookie = g_strdup( cookie ); + + mad->callback = func; + mad->data = data; + + mad->url = g_strdup( SOAP_AUTHENTICATION_URL ); + mad->ttl = 3; /* Max. # of redirects. */ + + /* HTTP-escape stuff and s/,/&/ */ + http_decode( mad->cookie ); + for( i = 0; mad->cookie[i]; i ++ ) + if( mad->cookie[i] == ',' ) + mad->cookie[i] = '&'; + + return passport_get_token_real( mad ); } -static int passport_get_id_real( gpointer func, gpointer data, char *header ) +static int passport_get_token_real( struct msn_auth_data *mad ) { - struct passport_reply *rep; - char *server, *dummy, *reqs; + char *post_payload, *post_request; struct http_request *req; + url_t url; - rep = g_new0( struct passport_reply, 1 ); - rep->data = data; - rep->func = func; - rep->header = header; - - server = g_strdup( prd_cached ); - dummy = strchr( server, '/' ); - - if( dummy == NULL ) - { - destroy_reply( rep ); - return( 0 ); - } - - reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header ); + url_set( &url, mad->url ); - *dummy = 0; - req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep ); + post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD, + mad->username, + mad->password, + mad->cookie ); - g_free( server ); - g_free( reqs ); + post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST, + url.file, url.host, + (int) strlen( post_payload ), + post_payload ); + + req = http_dorequest( url.host, url.port, 1, post_request, + passport_get_token_ready, mad ); - if( req == NULL ) - destroy_reply( rep ); + g_free( post_request ); + g_free( post_payload ); - return( req != NULL ); + return req != NULL; } -static void passport_get_id_ready( struct http_request *req ) +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ); +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ); + +static const struct xt_handler_entry passport_xt_handlers[] = { + { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token }, + { "S:Fault", "S:Envelope", passport_xt_handle_fault }, + { NULL, NULL, NULL } +}; + +static void passport_get_token_ready( struct http_request *req ) { - struct passport_reply *rep = req->data; + struct msn_auth_data *mad = req->data; + struct xt_parser *parser; - if( !g_slist_find( msn_connections, rep->data ) ) - { - destroy_reply( rep ); - return; - } + g_free( mad->url ); + g_free( mad->error ); + mad->url = mad->error = NULL; - if( req->finished && req->reply_headers && req->status_code == 200 ) + if( req->status_code == 200 ) { - char *dummy; - - if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) ) - { - char *responseend; - - dummy += strlen( "from-PP='" ); - responseend = strchr( dummy, '\'' ); - if( responseend ) - *responseend = 0; - - rep->result = g_strdup( dummy ); - } - else - { - rep->error_string = g_strdup( "Could not parse Passport server response" ); - } + parser = xt_new( passport_xt_handlers, mad ); + xt_feed( parser, req->reply_body, req->body_size ); + xt_handle( parser, NULL, -1 ); + xt_free( parser ); } else { - rep->error_string = g_strdup_printf( "HTTP error: %s", - req->status_string ? req->status_string : "Unknown error" ); + mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code, + req->status_string ? req->status_string : "unknown" ); } - rep->func( rep ); - destroy_reply( rep ); -} - -static char *passport_create_header( char *cookie, char *email, char *pwd ) -{ - char *buffer; - char *currenttoken; - char *email_enc, *pwd_enc; - - currenttoken = strstr( cookie, "lc=" ); - if( currenttoken == NULL ) - return NULL; - - email_enc = g_new0( char, strlen( email ) * 3 + 1 ); - strcpy( email_enc, email ); - http_encode( email_enc ); - - pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 ); - strcpy( pwd_enc, pwd ); - http_encode( pwd_enc ); - - buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET," - "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," - "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, - currenttoken ); - - g_free( email_enc ); - g_free( pwd_enc ); + if( mad->error == NULL && mad->token == NULL ) + mad->error = g_strdup( "Could not parse Passport server response" ); - return buffer; + if( mad->url && mad->token == NULL ) + { + passport_get_token_real( mad ); + } + else + { + mad->callback( mad ); + + g_free( mad->url ); + g_free( mad->username ); + g_free( mad->password ); + g_free( mad->cookie ); + g_free( mad->token ); + g_free( mad->error ); + g_free( mad ); + } } -static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header ) +static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data ) { - struct passport_reply *rep = g_new0( struct passport_reply, 1 ); - struct http_request *req; + struct msn_auth_data *mad = data; + char *s; - rep->data = data; - rep->func = func; - rep->header = header; + if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 ) + mad->token = g_memdup( node->text, node->text_len + 1 ); - req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep ); - - if( !req ) - destroy_reply( rep ); - - return( req != NULL ); + return XT_HANDLED; } -static void passport_retrieve_dalogin_ready( struct http_request *req ) +static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data ) { - struct passport_reply *rep = req->data; - char *dalogin; - char *urlend; + struct msn_auth_data *mad = data; + struct xt_node *code = xt_find_node( node->children, "faultcode" ); + struct xt_node *string = xt_find_node( node->children, "faultstring" ); + struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" ); - if( !g_slist_find( msn_connections, rep->data ) ) - { - destroy_reply( rep ); - return; - } - - if( !req->finished || !req->reply_headers || req->status_code != 200 ) - { - rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s", - req->status_string ? req->status_string : "Unknown error" ); - goto failure; - } + if( redirect && redirect->text_len && mad->ttl-- > 0 ) + mad->url = g_memdup( redirect->text, redirect->text_len + 1 ); - dalogin = strstr( req->reply_headers, "DALogin=" ); - - if( !dalogin ) - { - rep->error_string = g_strdup( "Parse error while fetching DALogin" ); - goto failure; - } - - dalogin += strlen( "DALogin=" ); - urlend = strchr( dalogin, ',' ); - if( urlend ) - *urlend = 0; - - /* strip the http(s):// part from the url */ - urlend = strstr( urlend, "://" ); - if( urlend ) - dalogin = urlend + strlen( "://" ); - - if( prd_cached == NULL ) - prd_cached = g_strdup( dalogin ); - - if( passport_get_id_real( rep->func, rep->data, rep->header ) ) - { - rep->header = NULL; - destroy_reply( rep ); - return; - } + if( code == NULL || code->text_len == 0 ) + mad->error = g_strdup( "Unknown error" ); + else + mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? + string->text : "no description available" ); -failure: - rep->func( rep ); - destroy_reply( rep ); -} - -static void destroy_reply( struct passport_reply *rep ) -{ - g_free( rep->result ); - g_free( rep->header ); - g_free( rep->error_string ); - g_free( rep ); + return XT_HANDLED; } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 9fd81a82..1d0c6edc 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -1,10 +1,7 @@ -#ifndef __PASSPORT_H__ -#define __PASSPORT_H__ /* passport.h * - * Functions to login to Microsoft Passport Service for Messenger - * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>, - * Wilmer van der Gaast <wilmer@gaast.net> + * Functions to login to Microsoft Passport service for Messenger + * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -17,9 +14,15 @@ * * You should have received a copy of the GNU 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener + for the specs! */ + +#ifndef __PASSPORT_H__ +#define __PASSPORT_H__ + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -32,15 +35,77 @@ #endif #include "nogaim.h" -struct passport_reply +struct msn_auth_data { - void (*func)( struct passport_reply * ); - void *data; - char *result; - char *header; - char *error_string; + char *url; + int ttl; + + char *username; + char *password; + char *cookie; + + /* The end result, the only thing we'll really be interested in + once finished. */ + char *token; + char *error; /* Yeah, or that... */ + + void (*callback)( struct msn_auth_data *mad ); + gpointer data; }; -int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie ); +#define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf" + +#define SOAP_AUTHENTICATION_REQUEST \ +"POST %s HTTP/1.0\r\n" \ +"Accept: text/*\r\n" \ +"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ +"Host: %s\r\n" \ +"Content-Length: %d\r\n" \ +"Cache-Control: no-cache\r\n" \ +"\r\n" \ +"%s" + +#define SOAP_AUTHENTICATION_PAYLOAD \ +"<?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>AQAAAAIAAABsYwQAAAAzMDg0</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>" \ + "<wst:RequestSecurityToken Id=\"RST1\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>messenger.msn.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "</ps:RequestMultipleSecurityTokens>" \ + "</Body>" \ +"</Envelope>" + +int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie ); #endif /* __PASSPORT_H__ */ -- cgit v1.2.3 From 9186d15356a46576fb5b306f49a6acdb64fb7622 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 17 Feb 2008 11:26:44 +0000 Subject: Automatically truncate MSN passports to 16 characters because that's the maximum supported by MSN and giving a longer password will make the authentication fail. --- protocols/msn/passport.c | 5 +++++ protocols/msn/passport.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 7a15c3fe..565d15f3 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -52,6 +52,11 @@ int passport_get_token( gpointer func, gpointer data, char *username, char *pass if( mad->cookie[i] == ',' ) mad->cookie[i] = '&'; + /* Microsoft doesn't allow password longer than 16 chars and silently + fails authentication if you give the "full version" of your passwd. */ + if( strlen( mad->password ) > MAX_PASSPORT_PWLEN ) + mad->password[MAX_PASSPORT_PWLEN] = 0; + return passport_get_token_real( mad ); } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 1d0c6edc..517d2e91 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -35,6 +35,8 @@ #endif #include "nogaim.h" +#define MAX_PASSPORT_PWLEN 16 + struct msn_auth_data { char *url; -- cgit v1.2.3 From d5bd9c078ae2fb4d2e9354e943e06e017e878776 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Thu, 28 Feb 2008 22:39:37 +0000 Subject: My fix for semi-PEBKAC bug #353: Add a warning if someone seems to be using the wrong command, and fixing "help nick" example to show how it should be done now. --- doc/user-guide/commands.xml | 4 ++-- root_commands.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 5a1e398c..3402cfd7 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -842,8 +842,8 @@ </description> <ircexample> - <ircline nick="wouter">nick 1 "Wouter Paesen"</ircline> - <ircline nick="root">Setting your name on connection 1 to `Wouter Paesen'</ircline> + <ircline nick="wouter">account set 1/display_name "The majestik mรธรธse"</ircline> + <ircline nick="root">display_name = `The majestik mรธรธse'</ircline> </ircexample> </bitlbee-command> diff --git a/root_commands.c b/root_commands.c index 8e315bd4..2f542826 100644 --- a/root_commands.c +++ b/root_commands.c @@ -768,6 +768,9 @@ static void cmd_set( irc_t *irc, char **cmd ) irc_usermsg( irc, "%s = `%s'", set_name, s ); else irc_usermsg( irc, "%s is empty", set_name ); + + if( strchr( set_name, '/' ) ) + irc_usermsg( irc, "Warning: / found in setting name, you're probably looking for the `account set' command." ); } else { -- cgit v1.2.3 From 7bb3afbf24aaae0df9cd2e0e0cc9ebaf8e19f228 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast <wilmer@gaast.net> Date: Sun, 2 Mar 2008 17:13:32 +0000 Subject: Oops, even GMail got out of beta quicker than this. ;-) --- doc/user-guide/Support.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/user-guide/Support.xml b/doc/user-guide/Support.xml index 401a4295..c9f50a5f 100644 --- a/doc/user-guide/Support.xml +++ b/doc/user-guide/Support.xml @@ -3,12 +3,13 @@ <title>Support -BitlBee is beta software +Disclaimer -Although BitlBee has quite some functionality it is still beta. That means it -can crash at any time, corrupt your data or whatever. Don't use it in -any production environment and don't rely on it. +BitlBee doesn't come with a warranty and is still (and will probably always +be) under development. That means it can crash at any time, corrupt your +data or whatever. Don't use it in any production environment and don't rely +on it, or at least don't blame us if things blow up. :-) -- cgit v1.2.3 From 064e47c5927e1711fc45263d971998a7afca547b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Mar 2008 17:58:21 +0000 Subject: Some very late quickstart updates: ICQ supports server-side contact lists for ages already and private is set to true by default for quite some time as well. --- doc/user-guide/quickstart.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/user-guide/quickstart.xml b/doc/user-guide/quickstart.xml index 7735a8d7..0539a7c7 100644 --- a/doc/user-guide/quickstart.xml +++ b/doc/user-guide/quickstart.xml @@ -60,11 +60,11 @@ When you are finished adding your account(s) use the account on -For most protocols (currently MSN, Jabber, Yahoo and AOL) BitlBee can download the contact list automatically from the IM server and all the on-line users should appear in the control channel when you log in. +Now BitlBee logs in and downloads the contact list from the IM server. In a few seconds, all your on-line buddies should show up in the control channel. -BitlBee will convert names into irc-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo. +BitlBee will convert names into IRC-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo. @@ -126,11 +126,15 @@ First of all, a person must be on your contact list for you to chat with them (u tux: hey, how's the weather down there? - you: a bit chilly! + you: a bit chilly! -If you'd rather chat with them in a separate window use the /msg or /query command, just like you would for a private message in IRC. If you want to have messages automatically come up in private messages rather than in the &bitlbee channel, use the set private command: set private true (set private false to change back). +Note that, although all contacts are in the &bitlbee channel, only tux will actually receive this message. The &bitlbee channel shouldn't be confused with a real IRC channel. + + + +If you prefer chatting in a separate window, use the /msg or /query command, just like on real IRC. BitlBee will remember how you talk to someone and show his/her responses the same way. If you want to change the default behaviour (for people you haven't talked to yet), see help set private. -- cgit v1.2.3 From b27557b2d23f3cbc0801bc628de24a2a6adcfca9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Mar 2008 22:12:06 +0000 Subject: More documentation fixes: Cleaned up dead links, removed more outdated information (like the "set charset" default, which is UTF-8 for ages already). --- doc/user-guide/commands.xml | 22 +++++++--------------- doc/user-guide/misc.xml | 28 ++++------------------------ 2 files changed, 11 insertions(+), 39 deletions(-) diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 3402cfd7..c45727b9 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -162,11 +162,7 @@ - If you want, you can also tell BitlBee what nick to give the new contact. Of course you can also use the rename command for that, but sometimes this might be more convenient. - - - - Adding -tmp adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by set handle_unknown add). This allows you to talk to people who are not in your contact list. + If you want, you can also tell BitlBee what nick to give the new contact. The -tmp option adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by set handle_unknown add). This allows you to talk to people who are not in your contact list. This normally won't show you any presence notifications. @@ -382,16 +378,16 @@
- iso8859-1 + utf-8 you can get a list of all possible values by doing 'iconv -l' in a shell - The charset setting enables you to use different character sets in BitlBee. These get converted to UTF-8 before sending and from UTF-8 when receiving. + This setting tells BitlBee what your IRC client sends and expects. It should be equal to the charset setting of your IRC client if you want to be able to send and receive non-ASCII text properly. - If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://czyborra.com/charsets/iso8859.html + Most systems use UTF-8 these days. On older systems, an iso8859 charset may work better. For example, iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://www.unicodecharacter.com/charsets/iso8859.html @@ -676,7 +672,7 @@ - Sends you a /notice when a user starts typing a message (if the protocol supports it, MSN for example). This is a bug, not a feature. (But please don't report it.. ;-) You don't want to use it. Really. In fact the typing-notification is just one of the least useful 'innovations' ever. It's just there because some guy will probably ask me about it anyway. ;-) + Sends you a /notice when a user starts typing a message (if supported by the IM protocol and the user's client). To use this, you most likely want to use a script in your IRC client to show this information in a more sensible way. @@ -829,15 +825,11 @@ Change friendly name, nick nick <connection> [<new nick>] - nick + nick <connection> - This command allows to set the friendly name of an im account. If no new name is specified the command will report the current name. When the name contains spaces, don't forget to quote the whole nick in double quotes. Currently this command is only supported by the MSN protocol. - - - - It is recommended to use the per-account display_name setting to read and change this information. The nick command is deprecated. + Deprecated: Use the per-account display_name setting to read and change this information. diff --git a/doc/user-guide/misc.xml b/doc/user-guide/misc.xml index d387d4b3..b55a8915 100644 --- a/doc/user-guide/misc.xml +++ b/doc/user-guide/misc.xml @@ -46,16 +46,12 @@ All MSN smileys (except one) are case insensitive and work without the nose too. (O)Clock - -This list was extracted from http://help.msn.com/!data/en_us/data/messengerv50.its51/$content$/EMOTICONS.HTM?H_APP=. - - Groupchats -Since version 0.8x, BitlBee supports groupchats on the MSN and Yahoo! networks. This text will try to explain you how they work. +BitlBee now supports groupchats on all IM networks. This text will try to explain you how they work. @@ -72,7 +68,7 @@ Of course you can also create your own groupchats. Type help groupchat Creating groupchats -If you want to start a groupchat with the person jim_msn in it, just join the channel #jim_msn. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and jim_msn in it. +If you want to start a groupchat with the person lisa_msn in it, just join the channel #lisa_msn. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and lisa_msn in it. @@ -83,23 +79,6 @@ Of course a channel with only two people isn't really exciting yet. So the next Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the join_chat command to join them. See help join_chat for more information. - -This is all you'll probably need to know. If you have any problems, please read help groupchats3. - - - - - -Groupchat channel names - - -Obviously the (numbered) channel names don't make a lot of sense. Problem is that groupchats usually don't have names at all in the IM-world, while IRC insists on a name. So BitlBee just generates something random, just don't pay attention to it. :-) - - - -Please also note that BitlBee doesn't support groupchats for all protocols yet. BitlBee will tell you so. Support for other protocols will hopefully come later. - - @@ -120,6 +99,7 @@ Not all away states are supported by all protocols, and some protocols have diff Be right back, BRB On the phone, Phone, On phone Out to lunch, Lunch, Food + Invisible, Hidden @@ -127,7 +107,7 @@ So /away Food will set your state to "Out to lunch" on your -You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Protocols like Yahoo! and Jabber will also show this complete away message to your buddies. +You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Most IM-protocols can also show this additional information to your buddies. -- cgit v1.2.3 From 171ef85781e08ccbd8a6a018e88b1ad3cb802f78 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 2 Mar 2008 23:17:15 +0000 Subject: Some saner error handling in ipc.c. One of the things I wanted to do for 1.2. --- ipc.c | 60 +++++++++++++++++++++++++++++++++++++++--------------------- ipc.h | 3 +++ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/ipc.c b/ipc.c index 384a9c33..54f026ac 100644 --- a/ipc.c +++ b/ipc.c @@ -257,19 +257,7 @@ gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ) } else { - GSList *l; - struct bitlbee_child *c; - - for( l = child_list; l; l = l->next ) - { - c = l->data; - if( c->ipc_fd == source ) - { - ipc_master_free_one( c ); - child_list = g_slist_remove( child_list, c ); - break; - } - } + ipc_master_free_fd( source ); } return TRUE; @@ -287,10 +275,7 @@ gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ) } else { - b_event_remove( global.listen_watch_source_id ); - close( global.listen_socket ); - - global.listen_socket = -1; + ipc_child_disable(); } return TRUE; @@ -325,7 +310,9 @@ void ipc_to_master_str( char *format, ... ) } else if( global.conf->runmode == RUNMODE_FORKDAEMON ) { - write( global.listen_socket, msg_buf, strlen( msg_buf ) ); + if( global.listen_socket >= 0 ) + if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 ) + ipc_child_disable(); } else if( global.conf->runmode == RUNMODE_DAEMON ) { @@ -375,12 +362,18 @@ void ipc_to_children_str( char *format, ... ) else if( global.conf->runmode == RUNMODE_FORKDAEMON ) { int msg_len = strlen( msg_buf ); - GSList *l; + GSList *l, *next; - for( l = child_list; l; l = l->next ) + for( l = child_list; l; l = next ) { struct bitlbee_child *c = l->data; - write( c->ipc_fd, msg_buf, msg_len ); + + next = l->next; + if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 ) + { + ipc_master_free_one( c ); + child_list = g_slist_remove( child_list, c ); + } } } else if( global.conf->runmode == RUNMODE_DAEMON ) @@ -409,6 +402,23 @@ void ipc_master_free_one( struct bitlbee_child *c ) g_free( c ); } +void ipc_master_free_fd( int fd ) +{ + GSList *l; + struct bitlbee_child *c; + + for( l = child_list; l; l = l->next ) + { + c = l->data; + if( c->ipc_fd == fd ) + { + ipc_master_free_one( c ); + child_list = g_slist_remove( child_list, c ); + break; + } + } +} + void ipc_master_free_all() { GSList *l; @@ -420,6 +430,14 @@ void ipc_master_free_all() child_list = NULL; } +void ipc_child_disable() +{ + b_event_remove( global.listen_watch_source_id ); + close( global.listen_socket ); + + global.listen_socket = -1; +} + char *ipc_master_save_state() { char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" ); diff --git a/ipc.h b/ipc.h index 68926dfd..f3d24614 100644 --- a/ipc.h +++ b/ipc.h @@ -43,8 +43,11 @@ gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ); gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ); void ipc_master_free_one( struct bitlbee_child *child ); +void ipc_master_free_fd( int fd ); void ipc_master_free_all(); +void ipc_child_disable(); + void ipc_to_master( char **cmd ); void ipc_to_master_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 ); void ipc_to_children( char **cmd ); -- cgit v1.2.3 From ed3ae7e7d41f91917fc2ae92051c7c77c357fbab Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 3 Mar 2008 00:08:49 +0000 Subject: Added note about daemon mode to doc/README --- doc/README | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/README b/doc/README index bb6596ba..ca392573 100644 --- a/doc/README +++ b/doc/README @@ -41,6 +41,20 @@ Also, don't forget to create the configuration directory (/var/lib/bitlbee/ by default) and chown it to the UID BitlBee is running as. Make sure this directory is read-/writable by this user only. +--- (Fork)Daemon mode + +If you don't want to run any inetd daemon, you can run BitlBee in Daemon +mode. Right now, daemon mode may be a bad idea on servers with multiple +users, since possible fatal BitlBee bugs will crash the BitlBee process and +disconnect all connected users at once. Instead, you can use ForkDaemon +mode, which serves every user from a separate process, without depending on +an inetd daemon. + +To use BitlBee in daemon mode, just start it with the right flags or enable +it in bitlbee.conf. You probably want to write an init script to start +BitlBee automatically after a reboot. (This is where you realise using +a package from your distro would've been a better idea. :-P) + DEPENDENCIES ============ -- cgit v1.2.3 From 7f421d6b922837857d6aca342da314225023eb46 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 3 Mar 2008 23:18:36 +0000 Subject: BitlBee <= 1.0 didn't have "account set" and allowed one to delete an account and re-create it with new login settings if necessary, without losing custom nicknames. Now, nicknames are connected to an account instead of just the protocol, and they're flushed together with the account. So I added a warning to make sure nobody accidentally loses any settings while just changing the password. This will probably go after a few releases, since it's slightly annoying. --- query.c | 10 ++++++++-- root_commands.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/query.c b/query.c index 99be2bee..6f9eb77f 100644 --- a/query.c +++ b/query.c @@ -139,12 +139,18 @@ void query_answer( irc_t *irc, query_t *q, int ans ) } if( ans ) { - imcb_log( q->ic, "Accepted: %s", q->question ); + if( q->ic ) + imcb_log( q->ic, "Accepted: %s", q->question ); + else + irc_usermsg( irc, "Accepted: %s", q->question ); q->yes( NULL, q->data ); } else { - imcb_log( q->ic, "Rejected: %s", q->question ); + if( q->ic ) + imcb_log( q->ic, "Rejected: %s", q->question ); + else + irc_usermsg( irc, "Rejected: %s", q->question ); q->no( NULL, q->data ); } q->data = NULL; diff --git a/root_commands.c b/root_commands.c index 2f542826..9a60b5af 100644 --- a/root_commands.c +++ b/root_commands.c @@ -203,6 +203,26 @@ static void cmd_drop( irc_t *irc, char **cmd ) } } +void cmd_account_del_yes( gpointer w, void *data ) +{ + account_t *a = data; + irc_t *irc = a->irc; + + if( a->ic ) + { + irc_usermsg( irc, "Account is still logged in, can't delete" ); + } + else + { + account_del( irc, a ); + irc_usermsg( irc, "Account deleted" ); + } +} + +void cmd_account_del_no( gpointer w, void *data ) +{ +} + static void cmd_account( irc_t *irc, char **cmd ) { account_t *a; @@ -257,8 +277,15 @@ static void cmd_account( irc_t *irc, char **cmd ) } else { - account_del( irc, a ); - irc_usermsg( irc, "Account deleted" ); + char *msg; + + msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will " + "also forget all your saved nicknames. If you want " + "to change your username/password, use the `account " + "set' command. Are you sure you want to delete this " + "account?", a->prpl->name, a->user ); + query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, a ); + g_free( msg ); } } else if( g_strcasecmp( cmd[1], "list" ) == 0 ) -- cgit v1.2.3 From 9ad86bb22e53a40b3ad5bbc57f33d819d2748b0c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 15 Mar 2008 16:09:50 +0000 Subject: Fixed issues with "long" URLs in url.c. Reusing code from 2001 wasn't a good idea... --- bitlbee.h | 2 +- lib/url.c | 24 +++++++++++++----------- lib/url.h | 18 +++++++++--------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index c118d7fc..4a1c8b6d 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -32,7 +32,7 @@ #define BITLBEE_VERSION "1.1.1dev" #define VERSION BITLBEE_VERSION -#define MAX_STRING 128 +#define MAX_STRING 511 #if HAVE_CONFIG_H #include "config.h" diff --git a/lib/url.c b/lib/url.c index c6fdc4c8..de9966b4 100644 --- a/lib/url.c +++ b/lib/url.c @@ -25,13 +25,16 @@ #include "url.h" -/* Convert an URL to a url_t structure */ +/* Convert an URL to a url_t structure */ int url_set( url_t *url, char *set_url ) { - char s[MAX_STRING]; + char s[MAX_STRING+1]; char *i; - /* protocol:// */ + memset( url, 0, sizeof( url_t ) ); + memset( s, 0, sizeof( s ) ); + + /* protocol:// */ if( ( i = strstr( set_url, "://" ) ) == NULL ) { url->proto = PROTO_DEFAULT; @@ -48,13 +51,12 @@ int url_set( url_t *url, char *set_url ) else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 ) url->proto = PROTO_SOCKS5; else - { - return( 0 ); - } + return 0; + strncpy( s, i + 3, MAX_STRING ); } - /* Split */ + /* Split */ if( ( i = strchr( s, '/' ) ) == NULL ) { strcpy( url->file, "/" ); @@ -66,7 +68,7 @@ int url_set( url_t *url, char *set_url ) } strncpy( url->host, s, MAX_STRING ); - /* Check for username in host field */ + /* Check for username in host field */ if( strrchr( url->host, '@' ) != NULL ) { strncpy( url->user, url->host, MAX_STRING ); @@ -75,19 +77,19 @@ int url_set( url_t *url, char *set_url ) strcpy( url->host, i + 1 ); *url->pass = 0; } - /* If not: Fill in defaults */ + /* If not: Fill in defaults */ else { *url->user = *url->pass = 0; } - /* Password? */ + /* Password? */ if( ( i = strchr( url->user, ':' ) ) != NULL ) { *i = 0; strcpy( url->pass, i + 1 ); } - /* Port number? */ + /* Port number? */ if( ( i = strchr( url->host, ':' ) ) != NULL ) { *i = 0; diff --git a/lib/url.h b/lib/url.h index e9e1ecfe..8c038c91 100644 --- a/lib/url.h +++ b/lib/url.h @@ -25,20 +25,20 @@ #include "bitlbee.h" -#define PROTO_HTTP 2 -#define PROTO_HTTPS 5 -#define PROTO_SOCKS4 3 -#define PROTO_SOCKS5 4 -#define PROTO_DEFAULT PROTO_HTTP +#define PROTO_HTTP 2 +#define PROTO_HTTPS 5 +#define PROTO_SOCKS4 3 +#define PROTO_SOCKS5 4 +#define PROTO_DEFAULT PROTO_HTTP typedef struct url { int proto; int port; - char host[MAX_STRING]; - char file[MAX_STRING]; - char user[MAX_STRING]; - char pass[MAX_STRING]; + char host[MAX_STRING+1]; + char file[MAX_STRING+1]; + char user[MAX_STRING+1]; + char pass[MAX_STRING+1]; } url_t; int url_set( url_t *url, char *set_url ); -- cgit v1.2.3 From a869d9147584de96a0ac341416e551953167800f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 15 Mar 2008 17:44:21 +0000 Subject: Indicate that we support YMSG protocol version 12, this should hopefully keep BitlBee working after 2008-04-02 . --- protocols/yahoo/libyahoo2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index ce38bc73..4e93449e 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -736,7 +736,7 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet data = y_new0(unsigned char, len + 1); memcpy(data + pos, "YMSG", 4); pos += 4; - pos += yahoo_put16(data + pos, 0x0a00); + pos += yahoo_put16(data + pos, 0x000c); pos += yahoo_put16(data + pos, 0x0000); pos += yahoo_put16(data + pos, pktlen + extra_pad); pos += yahoo_put16(data + pos, pkt->service); -- cgit v1.2.3 From 79eae4a9edb343eaad30425289f7737467a535bb Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 15 Mar 2008 21:05:39 +0000 Subject: Inviting someone to a Yahoo! chatroom with msg=NULL is bad. I wonder if /invite ever worked in the Yahoo! module... --- protocols/yahoo/yahoo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 9f9ffcf7..36579d66 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -314,7 +314,7 @@ static void byahoo_chat_invite( struct groupchat *c, char *who, char *msg ) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; - yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ); + yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ? msg : "" ); } static void byahoo_chat_leave( struct groupchat *c ) -- cgit v1.2.3 From 4bb50efd1015a04d44c301961710fa08e0eda162 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 15 Mar 2008 23:53:54 +0000 Subject: Although I have no idea what the author meant with code like `if(cp != "\005")', I'm sure he feels homesick to QuickBasic. Since BitlBee doesn't use this function anyway, it doesn't really matter if my fix works. As long as it keeps the compiler quiet. --- protocols/yahoo/libyahoo2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 4e93449e..80d88a85 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -3350,7 +3350,7 @@ static void yahoo_process_search_connection(struct yahoo_input_data *yid, int ov yct->age = atoi(cp); break; case 5: - if(cp != "\005") + if(strcmp(cp, "5") != 0) yct->location = cp; k = 0; break; -- cgit v1.2.3 From d07c3a8cde47096ad69db7139d410dfee29e509b Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 00:40:20 +0000 Subject: No idea what's holding back 1.2 anymore so at least I'll make sure bitlbee.h is correct. Also updated the changelog. Just remembered 1 or 2 things left to do before 1.2, maybe do them tomorrow? --- bitlbee.h | 2 +- doc/CHANGES | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/bitlbee.h b/bitlbee.h index 4a1c8b6d..420ab70a 100644 --- a/bitlbee.h +++ b/bitlbee.h @@ -29,7 +29,7 @@ #define _GNU_SOURCE /* Stupid GNU :-P */ #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "1.1.1dev" +#define BITLBEE_VERSION "1.2" #define VERSION BITLBEE_VERSION #define MAX_STRING 511 diff --git a/doc/CHANGES b/doc/CHANGES index ee4cde69..959c11fd 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,7 +1,4 @@ Version 1.2: -- First BitlBee development/testing RELEASE. This should be quite stable - though (and for most people more stable than 1.0.x). It just has a couple - of rough edges and needs a bit more testing. - Added ForkDaemon mode next to the existing Daemon- and inetd modes. With ForkDaemon you can run BitlBee as a stand-alone daemon and every connection will run in its own process. No more need to configure inetd, and still you @@ -20,9 +17,16 @@ Version 1.2: This allows us to use more GLib features (like the XML parser). By now GLib 1.x is so old that supporting it really isn't necessary anymore. - Many, many, MANY little changes, improvements, fixes. Using non-blocking - I/O as much as possible, fixed lots of little bugs (including bugs that - affected daemon mode stability). See the bzr logs for more information. -- Added units tests, will have to add some more before the real release. + I/O as much as possible, replaced the Gaim (0.59, IOW heavily outdated) + API, fixed lots of little bugs (including bugs that affected daemon mode + stability). See the bzr logs for more information. +- One of the user-visible changes from the API change: You can finally see + all away states/messages properly. +- Added units tests. Test coverage is very minimal for now. +- Better charset handling: Everything is just converted from/to UTF-8 right + in the IRC core, and charset mismatches are detected (if possible) and the + user is asked to resolve this before continuing. Also, UTF-8 is the default + setting now, since that's how the world seems to work these days. - Most important change: New file format for user data (accounts, nicks and settings). Migration to the new format should happen transparently, BitlBee will read the old files and once you quit/save it will save in the @@ -68,6 +72,11 @@ Version 1.2: buddy is in your contact list.) * An XML console (add xmlconsole to your contact list or see "help set xmlconsole" if you want it permanently). +- The Yahoo! module now says it supports YMSG protocol version 12, which will + hopefully keep the Yahoo module working after 2008-04-02 (when Yahoo! is + dropping support for version 6.x of their client). +- MSN switchboard handling changes. Hopefully less messages will get lost now, + although things are still not perfect. Finished ??? -- cgit v1.2.3 From ddcf491fa460fea612c240589c50da864dad6668 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 14:18:22 +0000 Subject: Adding padding to encrypted IM-passwords so the exact password length can't be guessed from the encrypted data anymore. --- lib/arc.c | 27 +++++++++++++++++++++++++-- lib/arc.h | 4 ++-- storage_xml.c | 2 +- tests/check_arc.c | 35 ++++++++++++++++++++++------------- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/lib/arc.c b/lib/arc.c index 617f6b96..fd498454 100644 --- a/lib/arc.c +++ b/lib/arc.c @@ -130,18 +130,40 @@ unsigned char arc_getbyte( struct arc_state *st ) don't need it anymore. Both functions return the number of bytes in the result string. + + Note that if you use the pad_to argument, you will need zero-termi- + nation to find back the original string length after decryption. So + it shouldn't be used if your string contains \0s by itself! */ -int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password ) +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ) { struct arc_state *st; unsigned char *key; - int key_len, i; + char *padded = NULL; + int key_len, i, padded_len; key_len = strlen( password ) + ARC_IV_LEN; if( clear_len <= 0 ) clear_len = strlen( clear ); + /* Pad the string to the closest multiple of pad_to. This makes it + impossible to see the exact length of the password. */ + if( pad_to > 0 && ( clear_len % pad_to ) > 0 ) + { + padded_len = clear_len + pad_to - ( clear_len % pad_to ); + padded = g_malloc( padded_len ); + memcpy( padded, clear, clear_len ); + + /* First a \0 and then random data, so we don't have to do + anything special when decrypting. */ + padded[clear_len] = 0; + random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 ); + + clear = padded; + clear_len = padded_len; + } + /* Prepare buffers and the key + IV */ *crypt = g_malloc( clear_len + ARC_IV_LEN ); key = g_malloc( key_len ); @@ -160,6 +182,7 @@ int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *passwor crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st ); g_free( st ); + g_free( padded ); return clear_len + ARC_IV_LEN; } diff --git a/lib/arc.h b/lib/arc.h index 882372ed..58f30d3d 100644 --- a/lib/arc.h +++ b/lib/arc.h @@ -30,7 +30,7 @@ struct arc_state unsigned char i, j; }; -struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ); +G_GNUC_MALLOC struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ); unsigned char arc_getbyte( struct arc_state *st ); -int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password ); +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ); int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ); diff --git a/storage_xml.c b/storage_xml.c index 19070a74..6ea4d442 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -427,7 +427,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) char *pass_b64; int pass_len; - pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password ); + pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password, 12 ); pass_b64 = base64_encode( pass_cr, pass_len ); g_free( pass_cr ); diff --git a/tests/check_arc.c b/tests/check_arc.c index a430f899..9d913dcd 100644 --- a/tests/check_arc.c +++ b/tests/check_arc.c @@ -6,13 +6,14 @@ #include #include "arc.h" -char *password = "TotT"; +char *password = "ArcVier"; char *clear_tests[] = { "Wie dit leest is gek :-)", "ItllBeBitlBee", "One more boring password", + "Hoi hoi", NULL }; @@ -27,7 +28,7 @@ static void check_codec(int l) char *decrypted; int len; - len = arc_encode( clear_tests[i], 0, &crypted, password ); + len = arc_encode( clear_tests[i], 0, &crypted, password, 12 ); len = arc_decode( crypted, len, &decrypted, password ); fail_if( strcmp( clear_tests[i], decrypted ) != 0, @@ -40,27 +41,35 @@ static void check_codec(int l) struct { - unsigned char crypted[24]; + unsigned char crypted[30]; int len; char *decrypted; } decrypt_tests[] = { + /* One block with padding. */ { { - 0xc3, 0x0d, 0x43, 0xc3, 0xee, 0x80, 0xe2, 0x8c, 0x0b, 0x29, 0x32, 0x7e, - 0x38, 0x05, 0x82, 0x10, 0x21, 0x1c, 0x4a, 0x00, 0x2c - }, 21, "Debugging sucks" + 0x3f, 0x79, 0xb0, 0xf5, 0x91, 0x56, 0xd2, 0x1b, 0xd1, 0x4b, 0x67, 0xac, + 0xb1, 0x31, 0xc9, 0xdb, 0xf9, 0xaa + }, 18, "short pass" }, + + /* Two blocks with padding. */ { { - 0xb0, 0x00, 0x57, 0x0d, 0x0d, 0x0d, 0x70, 0xe1, 0xc0, 0x00, 0xa4, 0x25, - 0x7d, 0xbe, 0x03, 0xcc, 0x24, 0xd1, 0x0c - }, 19, "Testing rocks" + 0xf9, 0xa6, 0xec, 0x5d, 0xc7, 0x06, 0xb8, 0x6b, 0x63, 0x9f, 0x2d, 0xb5, + 0x7d, 0xaa, 0x32, 0xbb, 0xd8, 0x08, 0xfd, 0x81, 0x2e, 0xca, 0xb4, 0xd7, + 0x2f, 0x36, 0x9c, 0xac, 0xa0, 0xbc + }, 30, "longer password" }, + + /* This string is exactly two "blocks" long, to make sure unpadded strings also decrypt + properly. */ { { - 0xb6, 0x92, 0x59, 0xe4, 0xf9, 0xc1, 0x7a, 0xf6, 0xf3, 0x18, 0xea, 0x28, - 0x73, 0x6d, 0xb3, 0x0a, 0x6f, 0x0a, 0x2b, 0x43, 0x57, 0xe9, 0x3e, 0x63 - }, 24, "OSCAR is creepy..." + 0x95, 0x4d, 0xcf, 0x4d, 0x5e, 0x6c, 0xcf, 0xef, 0xb9, 0x80, 0x00, 0xef, + 0x25, 0xe9, 0x17, 0xf6, 0x29, 0x6a, 0x82, 0x79, 0x1c, 0xca, 0x68, 0xb5, + 0x4e, 0xd0, 0xc1, 0x41, 0x8e, 0xe6 + }, 30, "OSCAR is really creepy.." }, { "", 0, NULL } }; @@ -79,7 +88,7 @@ static void check_decod(int l) &decrypted, password ); fail_if( strcmp( decrypt_tests[i].decrypted, decrypted ) != 0, - "%s didn't decrypt properly", clear_tests[i] ); + "`%s' didn't decrypt properly", decrypt_tests[i].decrypted ); g_free( decrypted ); } -- cgit v1.2.3 From e960a523f587a83bd22d000b4451c5a21b2951e8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 14:39:34 +0000 Subject: Fixed cached_id_prefix memory leak. --- protocols/jabber/jabber.c | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 243ed7fd..0e23b4d4 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -266,6 +266,7 @@ static void jabber_logout( struct im_connection *ic ) xt_free( jd->xt ); + g_free( jd->cached_id_prefix ); g_free( jd->away_message ); g_free( jd->username ); g_free( jd ); -- cgit v1.2.3 From 50d26f33935aadc556dd3e79829b1ca01bbceab9 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 15:28:37 +0000 Subject: Fixed base64_decode() to not barf on corrupted Base64 strings. --- lib/base64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base64.c b/lib/base64.c index 64e9692a..ea0db6b9 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -117,7 +117,7 @@ int base64_decode_real(const unsigned char *in, unsigned char *out, char *b64rev { int i, outlen = 0; - for( i = 0; in[i]; i += 4 ) + for( i = 0; in[i] && in[i+1] && in[i+2] && in[i+3]; i += 4 ) { int sx; -- cgit v1.2.3 From 4e8db1c0141f74dc6156a57739613483344b358d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 16:03:52 +0000 Subject: Moved password hash verification to md5_verify_password() so this can be reused for IRC/OPER passwords (to have encrypted in bitlbee.conf). --- lib/misc.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/misc.h | 2 ++ storage_xml.c | 41 +++++++++++------------------------------ 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 18d98f9e..ccf208b5 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -32,6 +32,7 @@ #define BITLBEE_CORE #include "nogaim.h" +#include "base64.h" #include #include #include @@ -596,3 +597,43 @@ gboolean ssl_sockerr_again( void *ssl ) else return sockerr_again(); } + +/* Returns values: -1 == Failure (base64-decoded to something unexpected) + 0 == Okay + 1 == Password doesn't match the hash. */ +int md5_verify_password( char *password, char *hash ) +{ + md5_byte_t *pass_dec = NULL; + md5_byte_t pass_md5[16]; + md5_state_t md5_state; + int ret, i; + + if( base64_decode( hash, &pass_dec ) != 21 ) + { + ret = -1; + } + else + { + md5_init( &md5_state ); + md5_append( &md5_state, (md5_byte_t*) password, strlen( password ) ); + md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */ + md5_finish( &md5_state, pass_md5 ); + + for( i = 0; i < 16; i ++ ) + { + if( pass_dec[i] != pass_md5[i] ) + { + ret = 1; + break; + } + } + + /* If we reached the end of the loop, it was a match! */ + if( i == 16 ) + ret = 0; + } + + g_free( pass_dec ); + + return ret; +} diff --git a/lib/misc.h b/lib/misc.h index 7804bfb1..a2acada6 100644 --- a/lib/misc.h +++ b/lib/misc.h @@ -66,4 +66,6 @@ G_MODULE_EXPORT char *word_wrap( char *msg, int line_len ); G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl ); +G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); + #endif diff --git a/storage_xml.c b/storage_xml.c index 6ea4d442..f37fce44 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -79,49 +79,30 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na { char *nick = xml_attr( attr_names, attr_values, "nick" ); char *pass = xml_attr( attr_names, attr_values, "password" ); - md5_byte_t *pass_dec = NULL; + int st; if( !nick || !pass ) { g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Missing attributes for %s element", element_name ); } - else if( base64_decode( pass, &pass_dec ) != 21 ) + else if( ( st = md5_verify_password( xd->given_pass, pass ) ) == -1 ) { + xd->pass_st = XML_PASS_WRONG; g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Error while decoding password attribute" ); } + else if( st == 0 ) + { + if( xd->pass_st != XML_PASS_CHECK_ONLY ) + xd->pass_st = XML_PASS_OK; + } else { - md5_byte_t pass_md5[16]; - md5_state_t md5_state; - int i; - - md5_init( &md5_state ); - md5_append( &md5_state, (md5_byte_t*) xd->given_pass, strlen( xd->given_pass ) ); - md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */ - md5_finish( &md5_state, pass_md5 ); - - for( i = 0; i < 16; i ++ ) - { - if( pass_dec[i] != pass_md5[i] ) - { - xd->pass_st = XML_PASS_WRONG; - g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Password mismatch" ); - break; - } - } - - /* If we reached the end of the loop, it was a match! */ - if( i == 16 ) - { - if( xd->pass_st != XML_PASS_CHECK_ONLY ) - xd->pass_st = XML_PASS_OK; - } + xd->pass_st = XML_PASS_WRONG; + g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Password mismatch" ); } - - g_free( pass_dec ); } else if( xd->pass_st < XML_PASS_OK ) { -- cgit v1.2.3 From ec0355f6998eb5dee254e4bc60a3207bb661c854 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 16:31:27 +0000 Subject: Passwords in bitlbee.conf can now be (properly salted) MD5 hashes, for just that little bit extra security. --- bitlbee.conf | 7 +++++++ doc/CHANGES | 2 ++ irc_commands.c | 10 ++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/bitlbee.conf b/bitlbee.conf index d9f878c8..99e8106d 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -48,14 +48,21 @@ ## AuthPassword ## ## Password the user should enter when logging into a closed BitlBee server. +## You can also have an MD5-encrypted password here. Format: "md5:", followed +## by a hash as generated for the attribute in a BitlBee +## XML file (for now there's no easier way to generate the hash). ## # AuthPassword = ItllBeBitlBee ## Heh.. Our slogan. ;-) +## or +# AuthPassword = md5:gzkK0Ox/1xh+1XTsQjXxBJ571Vgl ## OperPassword ## ## Password that unlocks access to special operator commands. ## # OperPassword = ChangeMe! +## or +# OperPassword = md5:I0mnZbn1t4R731zzRdDN2/pK7lRX ## HostName ## diff --git a/doc/CHANGES b/doc/CHANGES index 959c11fd..b3c3b711 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -27,6 +27,8 @@ Version 1.2: in the IRC core, and charset mismatches are detected (if possible) and the user is asked to resolve this before continuing. Also, UTF-8 is the default setting now, since that's how the world seems to work these days. +- One can now keep hashed passwords in bitlbee.conf instead of the cleartext + version. - Most important change: New file format for user data (accounts, nicks and settings). Migration to the new format should happen transparently, BitlBee will read the old files and once you quit/save it will save in the diff --git a/irc_commands.c b/irc_commands.c index 68db4617..14209732 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -29,7 +29,10 @@ static void irc_cmd_pass( irc_t *irc, char **cmd ) { - if( global.conf->auth_pass && strcmp( cmd[1], global.conf->auth_pass ) == 0 ) + if( global.conf->auth_pass && + strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? + md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : + strcmp( cmd[1], global.conf->auth_pass ) == 0 ) { irc->status |= USTATUS_AUTHORIZED; irc_check_login( irc ); @@ -87,7 +90,10 @@ static void irc_cmd_ping( irc_t *irc, char **cmd ) static void irc_cmd_oper( irc_t *irc, char **cmd ) { - if( global.conf->oper_pass && strcmp( cmd[2], global.conf->oper_pass ) == 0 ) + if( global.conf->oper_pass && + strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? + md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : + strcmp( cmd[2], global.conf->oper_pass ) == 0 ) { irc_umode_set( irc, "+o", 1 ); irc_reply( irc, 381, ":Password accepted" ); -- cgit v1.2.3 From c029350d962d95c2d5e9854ca4d82e597addf76d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Mar 2008 17:17:23 +0000 Subject: Added some brackets in irc_cmd_(pass|oper) to prevent crashes when no passwords were set. --- irc_commands.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/irc_commands.c b/irc_commands.c index 14209732..b8bae541 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -30,9 +30,9 @@ static void irc_cmd_pass( irc_t *irc, char **cmd ) { if( global.conf->auth_pass && - strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? - md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : - strcmp( cmd[1], global.conf->auth_pass ) == 0 ) + ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? + md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : + strcmp( cmd[1], global.conf->auth_pass ) == 0 ) ) { irc->status |= USTATUS_AUTHORIZED; irc_check_login( irc ); @@ -91,9 +91,9 @@ static void irc_cmd_ping( irc_t *irc, char **cmd ) static void irc_cmd_oper( irc_t *irc, char **cmd ) { if( global.conf->oper_pass && - strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? - md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : - strcmp( cmd[2], global.conf->oper_pass ) == 0 ) + ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? + md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : + strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) { irc_umode_set( irc, "+o", 1 ); irc_reply( irc, 381, ":Password accepted" ); -- cgit v1.2.3 From 6612cc9dd32475569875030f5acc7cc4b0374ba6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 17 Mar 2008 22:35:24 +0000 Subject: Release 1.2 should now be ready. --- doc/CHANGES | 2 +- doc/RELEASE-SPEECH-1.2 | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 doc/RELEASE-SPEECH-1.2 diff --git a/doc/CHANGES b/doc/CHANGES index b3c3b711..65947617 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -80,7 +80,7 @@ Version 1.2: - MSN switchboard handling changes. Hopefully less messages will get lost now, although things are still not perfect. -Finished ??? +Finished 17 Mar 2008 Version 1.0.4: - Removed sethostent(), which causes problems for many people, especially on diff --git a/doc/RELEASE-SPEECH-1.2 b/doc/RELEASE-SPEECH-1.2 new file mode 100644 index 00000000..ec7c48b4 --- /dev/null +++ b/doc/RELEASE-SPEECH-1.2 @@ -0,0 +1,57 @@ +BitlBee ... is Bitl +------------------- + +"I CAN HAS SPEEECH?" This is how Wilmer announced to me that he was going to do +another BitlBee release. I was as surprised as you are. I thought he had given +up on this whole releasing business. + +There is some humor in using a LOLcats reference to announce a new Bee +release. The last major BitlBee release (1.0) was done a long time before the +hype even begun. Between then and now we've celebrated BitlBee's fifth birthday +and had a handful of releases, but nothing big happened. As a user this lax +release planning worries me. What if this means that later releases will take +even longer? I don't think we should fear this. Let us explore why this release +took so long. + +Personally, I blame Google. + +There, I've said it. Google. The guys who are so big on "Do No Evil" and all +that jazz. They caused this release to be so late. Let me explain why. + +They made Wilmer an offer. Wilmer, being the sillily naive guy he is, couldn't +refuse. There were no decapitated horses involved, but he couldn't refuse +nonetheless. That's not a big problem of course. Lots of guys (and gals, sure) +work for Google. It wouldn't have become a problem if they hadn't shipped him of +to Ireland. That's where the trouble starts. + +Ireland. Home of the leprechauns. These rascals joined forces with aliens and +LOLcats to abduct Wilmer. The aliens had been trying for years to kidnap him, +but they were on his turf and his trusty sidekicks Jelmer and Maurits were there +to help him. All that changed when he moved to Ireland. + +But it wasn't just that Wilmer was all alone in some strange place. It was also +that the aliens had created the LOLcats and made an alliance with the +leprechauns--the real rulers of Ireland. Wilmer is cool, but he's not that +cool. So they abducted him for a few years. When he finally came back, he +regathered his mad coding skills and hacked a new release together. + +By now you're thinking, what has happened to Jelmer and Maurits? Well, they're +still here and they worked on the Bee while Wilmer was absent. But, like open +source, they are very Bitl--they're cool, but they're ready when they're +ready. + +Well, whatever you may think of my little theory, they did take forever to +launch this release. We're not mad at them, because it shows. They have +added some cool new features and made plenty of changes under the hood. Let me +give you a sneak preview of some of the new features: Jabber groupchats are +supported. Configuration files are stored encrypted. You can now use +ForkDaemon mode, which gives better stability over normal daemon mode, but +doesn't require inetd. Also, server owners can now use the /OPER command to +spy on their users. And--as I was specifically asked to mention--this is the +first stable release that supports plugins. That's some Bitl changes for ya. + +BitlBee is cool, but ready when it's ready. Very Bitl. + +Sjoerd. LOL. + +(LOLBee by Erik Bosman.) -- cgit v1.2.3 From 379c08a27e637dbcbbe3f39a8723daa765ad0e48 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 21 Mar 2008 00:27:24 +0000 Subject: Updated/Fixed Debian package. --- debian/README.Debian | 4 ++-- debian/changelog | 25 +++++++++++++++++++++++-- debian/control | 2 +- debian/po/it.po | 36 ++++++++++++++++++++++++++++++++++++ debian/postinst | 9 ++++++++- debian/postrm | 3 ++- debian/rules | 9 ++++++--- 7 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 debian/po/it.po diff --git a/debian/README.Debian b/debian/README.Debian index e2102fc8..6056f488 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -1,6 +1,6 @@ - *** NEWS (Version 1.1 and later) *** + *** NEWS (Version 1.2 and later) *** -Starting from version 1.1, BitlBee has a forking daemon mode. The Debian +Starting from version 1.2, BitlBee has a forking daemon mode. The Debian package now uses this mode by default, instead of inetd mode. If you don't want to use this, you can disable the init scripts (best way to do this is by editing /etc/default/bitlbee) and restore the inetd.conf entry. This diff --git a/debian/changelog b/debian/changelog index ae524f73..2cf6510c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,12 +1,33 @@ -bitlbee (1.1.1dev-0pre) unstable; urgency=low +bitlbee (1.2-1) unstable; urgency=low + * New upstream release. (Closes: #325017, #386914, #437515) + * With hopefully completely sane charset handling (Closes: #296145) * Switched to the new forking daemon mode. Added /etc/default/bitlbee file, an init script. People who want to stick with inetd can do so, see the defaults file. + (Closes: #460741, #466171, #294585, #345038, #306452, #392682) * Got rid of debconf Woody compatibility stuff. * No more MPL code in BitlBee, thanks to the Jabber module rewrite! + * Added Italian translation, sorry for taking so long! (Closes: #448238) + * Added libevent dependency (more reliable event handling). + * Removed GLib 1.x dependency because BitlBee really requires GLib >=2.4. - -- Wilmer van der Gaast Fri, 06 Jul 2007 09:09:36 +0100 + -- Wilmer van der Gaast Tue, 18 Mar 2008 23:44:19 +0000 + +bitlbee (1.0.4-2) unstable; urgency=low + + * Removed $DEB_BUILD_OPTIONS because apparently buildds fill it with crap. + (Closes: #458717) + + -- Wilmer van der Gaast Mon, 11 Feb 2008 19:15:33 +0000 + +bitlbee (1.0.4-1) unstable; urgency=low + + * New upstream release. + * Changed libnss-dev dependency. (Closes: #370442) + * Added build-indep rule to debian/rules. (Closes: #395673) + + -- Wilmer van der Gaast Wed, 29 Aug 2007 20:24:28 +0100 bitlbee (1.0.3-1.3) unstable; urgency=low diff --git a/debian/control b/debian/control index 139174a6..8383391b 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: net Priority: optional Maintainer: Wilmer van der Gaast Standards-Version: 3.5.9 -Build-Depends: libglib2.0-dev | libglib-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf +Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf Package: bitlbee Architecture: any diff --git a/debian/po/it.po b/debian/po/it.po new file mode 100644 index 00000000..e149e61a --- /dev/null +++ b/debian/po/it.po @@ -0,0 +1,36 @@ +# Italian translation of the bitlbee debconf template +# This file is distributed under the same license as the bitlbee package +# Copyright (C) 2007 Free Software Foundation, Inc. +# Luca Monducci , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: bitlbee\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-30 04:31+0200\n" +"PO-Revision-Date: 2007-10-27 11:52+0200\n" +"Last-Translator: Luca Monducci \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:1001 +msgid "On what TCP port should BitlBee listen for connections?" +msgstr "Su quale porta TCP si deve mettere in ascolto BitlBee?" + +#. Type: string +#. Description +#: ../bitlbee.templates.master:1001 +msgid "" +"BitlBee normally listens on the regular IRC port, 6667. This might not be a " +"very good idea when you're running a real IRC daemon as well. 6668 might be " +"a good alternative. Leaving this value blank means that BitlBee will not be " +"run automatically." +msgstr "" +"Normalmente BitlBee si mette in ascolto sulla consueta porta IRC, la 6667. " +"Questa potrebbe non essere una buona idea se รจ in esecuzione anche un reale " +"demone IRC. La porta 6668 potrebbe essere una valida alternativa. Lasciando " +"vuoto questo valore BitlBee non viene avviato automaticamente." diff --git a/debian/postinst b/debian/postinst index 37608e47..c4edb8e8 100755 --- a/debian/postinst +++ b/debian/postinst @@ -15,9 +15,16 @@ BITLBEE_DISABLED=0 BITLBEE_UPGRADE_DONT_RESTART=0 [ -r /etc/default/bitlbee ] && source /etc/default/bitlbee -if [ "$BITLBEE_DISABLED" = "0" ]; then +if [ "$BITLBEE_DISABLED" = "0" ] && expr "$2" : '0\..*' > /dev/null || expr "$2" : '1\.0\..*' > /dev/null; then ## In case it's still there (if we're upgrading right now) update-inetd --remove '.*/usr/sbin/bitlbee' + if grep -q /usr/sbin/bitlbee /etc/inetd.conf 2> /dev/null; then + # Thanks for breaking update-inetd! (bugs.debian.org/311111) + # I hope that it works at least with xinetd, because this + # emergency hack doesn't: + perl -pi -e 's:^[^#].*/usr/sbin/bitlbee$:## Now using daemon mode\: # $&:' /etc/inetd.conf + killall -HUP inetd + fi fi cat</etc/default/bitlbee diff --git a/debian/postrm b/debian/postrm index cef99f13..f7686e7b 100755 --- a/debian/postrm +++ b/debian/postrm @@ -8,4 +8,5 @@ if [ -e /usr/share/debconf/confmodule ]; then fi update-rc.d bitlbee remove > /dev/null 2>&1 || true -deluser --remove-home bitlbee || true +deluser --system --remove-home bitlbee || true +rm -f /etc/default/bitlbee diff --git a/debian/rules b/debian/rules index 8d6bd4fa..0c757899 100755 --- a/debian/rules +++ b/debian/rules @@ -2,15 +2,18 @@ DEBUG ?= 0 +ifdef BITLBEE_VERSION +BITLBEE_FORCE_VERSION=1 +else # Want to use the full package version number instead of just the release. BITLBEE_VERSION ?= "$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')" export BITLBEE_VERSION - +endif build-arch: build-arch-stamp build-arch-stamp: if [ ! -d debian ]; then exit 1; fi - ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee $(DEB_BUILD_OPTIONS) + ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(DEB_BUILD_OPTIONS) $(MAKE) # $(MAKE) -C doc/ all touch build-arch-stamp @@ -65,7 +68,7 @@ binary-arch: build-arch install-arch cd debian/bitlbee; \ find usr -type f -exec md5sum {} \; > DEBIAN/md5sums dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee -ifdef BITLBEE_VERSION +ifdef BITLBEE_FORCE_VERSION dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v1:$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' else dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0' -- cgit v1.2.3 From a83442a7c4dbf99937e9e5397e5665c671694161 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 21 Mar 2008 00:39:16 +0000 Subject: Fixed handling of "set charset none". Fixes bug #373. --- irc.c | 7 ++++--- set.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/irc.c b/irc.c index 3a09f684..3589256e 100644 --- a/irc.c +++ b/irc.c @@ -308,7 +308,7 @@ void irc_process( irc_t *irc ) break; } - if( ( cs = set_getstr( &irc->set, "charset" ) ) ) + if( ( cs = set_getstr( &irc->set, "charset" ) ) && g_strcasecmp( cs, "none" ) != 0 ) { conv[IRC_MAX_LINE] = 0; if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) @@ -329,7 +329,7 @@ void irc_process( irc_t *irc ) else { irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, - "Warning: invalid (non-UTF8) characters received at login time." ); + "Warning: invalid characters received at login time." ); strncpy( conv, lines[i], IRC_MAX_LINE ); for( temp = conv; *temp; temp ++ ) @@ -553,7 +553,8 @@ void irc_vawrite( irc_t *irc, char *format, va_list params ) g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); strip_newlines( line ); - if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) ) + if( ( cs = set_getstr( &irc->set, "charset" ) ) && + g_strcasecmp( cs, "none" ) != 0 && g_strcasecmp( cs, "utf-8" ) != 0 ) { char conv[IRC_MAX_LINE+1]; diff --git a/set.c b/set.c index 6f09843b..90b29f91 100644 --- a/set.c +++ b/set.c @@ -234,7 +234,7 @@ char *set_eval_charset( set_t *set, char *value ) { GIConv cd; - if ( g_strncasecmp( value, "none", 4 ) == 0 ) + if( g_strcasecmp( value, "none" ) == 0 ) return value; cd = g_iconv_open( "UTF-8", value ); -- cgit v1.2.3 From 851a8c29c681cdc3c9838ed99486822cba927f60 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 Mar 2008 12:02:50 +0000 Subject: Taught GLib-mode subprocesses how to die. (Closes: #374) --- lib/events_glib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/events_glib.c b/lib/events_glib.c index 1198dba6..3e194e98 100644 --- a/lib/events_glib.c +++ b/lib/events_glib.c @@ -50,11 +50,12 @@ typedef struct _GaimIOClosure { gpointer data; } GaimIOClosure; -static GMainLoop *loop; +static GMainLoop *loop = NULL; void b_main_init() { - loop = g_main_new( FALSE ); + if( loop == NULL ) + loop = g_main_new( FALSE ); } void b_main_run() -- cgit v1.2.3 From 8a2221a79b177a5c6d0b55dafebd39414d7fe10a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 23 Mar 2008 14:29:19 +0000 Subject: Fixed stalling issue with OpenSSL and Jabber (#368). --- lib/ssl_client.h | 3 +++ lib/ssl_gnutls.c | 6 ++++++ lib/ssl_nss.c | 6 ++++++ lib/ssl_openssl.c | 23 +++++++++++++++++++---- protocols/jabber/io.c | 9 +++++++-- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/lib/ssl_client.h b/lib/ssl_client.h index dcbf9a01..f91d0d70 100644 --- a/lib/ssl_client.h +++ b/lib/ssl_client.h @@ -59,6 +59,9 @@ G_MODULE_EXPORT void *ssl_starttls( int fd, ssl_input_function func, gpointer da G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); +/* See ssl_openssl.c for an explanation. */ +G_MODULE_EXPORT int ssl_pending( void *conn ); + /* Abort the SSL connection and disconnect the socket. Do not use close() directly, both the SSL library and the peer will be unhappy! */ G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index b964ab49..f5945442 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -210,6 +210,12 @@ int ssl_write( void *conn, const char *buf, int len ) return st; } +/* See ssl_openssl.c for an explanation. */ +int ssl_pending( void *conn ) +{ + return 0; +} + void ssl_disconnect( void *conn_ ) { struct scd *conn = conn_; diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c index 218b3a80..eba3c441 100644 --- a/lib/ssl_nss.c +++ b/lib/ssl_nss.c @@ -168,6 +168,12 @@ int ssl_write( void *conn, const char *buf, int len ) return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) ); } +/* See ssl_openssl.c for an explanation. */ +int ssl_pending( void *conn ) +{ + return 0; +} + void ssl_disconnect( void *conn_ ) { struct scd *conn = conn_; diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c index b1ba1db9..fc6d433e 100644 --- a/lib/ssl_openssl.c +++ b/lib/ssl_openssl.c @@ -61,16 +61,16 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data struct scd *conn = g_new0( struct scd, 1 ); conn->fd = proxy_connect( host, port, ssl_connected, conn ); - conn->func = func; - conn->data = data; - conn->inpa = -1; - if( conn->fd < 0 ) { g_free( conn ); return NULL; } + conn->func = func; + conn->data = data; + conn->inpa = -1; + return conn; } @@ -230,6 +230,21 @@ int ssl_write( void *conn, const char *buf, int len ) return st; } +/* Only OpenSSL *really* needs this (and well, maybe NSS). See for more info: + http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209 + http://www.openssl.org/docs/ssl/SSL_pending.html + + Required because OpenSSL empties the TCP buffer completely but doesn't + necessarily give us all the unencrypted data. + + Returns 0 if there's nothing left or if we don't have to care (GnuTLS), + 1 if there's more data. */ +int ssl_pending( void *conn ) +{ + return ( ((struct scd*)conn) && ((struct scd*)conn)->established ) ? + SSL_pending( ((struct scd*)conn)->ssl ) > 0 : 0; +} + void ssl_disconnect( void *conn_ ) { struct scd *conn = conn_; diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 9980dc8e..10efad37 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -240,8 +240,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition return FALSE; } - /* EAGAIN/etc or a successful read. */ - return TRUE; + if( ssl_pending( jd->ssl ) ) + /* OpenSSL empties the TCP buffers completely but may keep some + data in its internap buffers. select() won't see that, but + ssl_pending() does. */ + return jabber_read_callback( data, fd, cond ); + else + return TRUE; } gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) -- cgit v1.2.3 From dd14ecc29b87b9aefa97b6838f5a8595557d46d1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 23 Mar 2008 15:02:42 +0000 Subject: s/g_strsplit/g_strsplit_set/, thanks to misc@mandriva.org (Bug #380). --- conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.c b/conf.c index 57902826..339af618 100644 --- a/conf.c +++ b/conf.c @@ -251,7 +251,7 @@ static int conf_loadini( conf_t *conf, char *file ) else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 ) { g_strfreev( conf->migrate_storage ); - conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 ); + conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 ); } else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 ) { -- cgit v1.2.3 From fcd5003bd6c10f176f63df459e8ca479c5292dc1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 23 Mar 2008 21:53:53 +0000 Subject: Some Debian package fixes. If nothing else comes up, this will be 1.2-2. (Not sure if I will roll back the non-Debian changes...) --- debian/README.Debian | 16 +++++++++++++++- debian/changelog | 7 +++++++ debian/conffiles | 1 + debian/postinst | 10 ++++++---- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/debian/README.Debian b/debian/README.Debian index 6056f488..b5a514c0 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -6,7 +6,21 @@ want to use this, you can disable the init scripts (best way to do this is by editing /etc/default/bitlbee) and restore the inetd.conf entry. This should be necessary only once, it won't be touched during upgrades. --------------------------------------------------------------------------- +Another important change in BitlBee 1.2 is the file format used for your +personal settings. Everything's now saved in a single .xml (per account, +of course) file instead of $nick.accounts and $nick.nicks. One advantage +of this new format is that the passwords are actually encrypted instead of +just vaguely obfuscated. BitlBee can still read the old files, and will +save things in the new format when you save/disconnect. After that, you +can safely remove the old-style files (this is recommended). + +I tried making this transition (the new file format but especially, in this +case, the inetd->forkdaemon mode change) as smooth as possible, but I'm +aware that many BitlBee users will have their own hacks already to run the +program. I hope the package won't break any of this for anyone. 1.2-2 +should fix at least some of the issues. + +--------------------------------------------------------------------------- Debconf should have asked you on what port you want BitlBee to run. If it did not, the port number should be 6667 or 6668. (6668 if you already got diff --git a/debian/changelog b/debian/changelog index 2cf6510c..0eb05525 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +bitlbee (1.2-2) unstable; urgency=low + + * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373) + * Not ready yet. + + -- Wilmer van der Gaast Sun, 23 Mar 2008 21:51:57 +0000 + bitlbee (1.2-1) unstable; urgency=low * New upstream release. (Closes: #325017, #386914, #437515) diff --git a/debian/conffiles b/debian/conffiles index 2ccc958d..dcb4078e 100644 --- a/debian/conffiles +++ b/debian/conffiles @@ -1,2 +1,3 @@ /etc/bitlbee/motd.txt /etc/bitlbee/bitlbee.conf +/etc/init.d/bitlbee diff --git a/debian/postinst b/debian/postinst index c4edb8e8..1a906474 100755 --- a/debian/postinst +++ b/debian/postinst @@ -13,17 +13,19 @@ update-rc.d bitlbee defaults > /dev/null 2>&1 BITLBEE_OPTS=-F BITLBEE_DISABLED=0 BITLBEE_UPGRADE_DONT_RESTART=0 -[ -r /etc/default/bitlbee ] && source /etc/default/bitlbee +[ -r /etc/default/bitlbee ] && . /etc/default/bitlbee -if [ "$BITLBEE_DISABLED" = "0" ] && expr "$2" : '0\..*' > /dev/null || expr "$2" : '1\.0\..*' > /dev/null; then - ## In case it's still there (if we're upgrading right now) +if [ "$BITLBEE_DISABLED" = "0" ] && type update-inetd > /dev/null 2> /dev/null && + ( expr "$2" : '0\..*' > /dev/null || expr "$2" : '1\.0\..*' > /dev/null ); then + ## Make sure the inetd entry is gone (can still be there from a + ## previous version. update-inetd --remove '.*/usr/sbin/bitlbee' if grep -q /usr/sbin/bitlbee /etc/inetd.conf 2> /dev/null; then # Thanks for breaking update-inetd! (bugs.debian.org/311111) # I hope that it works at least with xinetd, because this # emergency hack doesn't: perl -pi -e 's:^[^#].*/usr/sbin/bitlbee$:## Now using daemon mode\: # $&:' /etc/inetd.conf - killall -HUP inetd + killall -HUP inetd || true fi fi -- cgit v1.2.3 From 58a1449166ebc9c2913bf47a4bf05c4cf3e258b0 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 Mar 2008 11:01:02 +0000 Subject: Fixed a broken check in lib/proxy.c, this restores proxy support. Thanks to Miles Bader for reporting this in the Debian BTS. Apparently not many people use this functionality, it was broken in bzr for more than a year already... --- debian/changelog | 1 + lib/proxy.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0eb05525..6c725964 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ bitlbee (1.2-2) unstable; urgency=low * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373) + * Fixed proxy support. (Closes: #472395) * Not ready yet. -- Wilmer van der Gaast Sun, 23 Mar 2008 21:51:57 +0000 diff --git a/lib/proxy.c b/lib/proxy.c index 0e1c8f07..53b89d64 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -529,7 +529,7 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat { struct PHB *phb; - if (!host || !port || (port == -1) || !func || strlen(host) > 128) { + if (!host || port <= 0 || !func || strlen(host) > 128) { return -1; } @@ -537,7 +537,7 @@ int proxy_connect(const char *host, int port, b_event_handler func, gpointer dat phb->func = func; phb->data = data; - if ((proxytype == PROXY_NONE) || strlen(proxyhost) > 0 || !proxyport || (proxyport == -1)) + if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) return proxy_connect_none(host, port, phb); else if (proxytype == PROXY_HTTP) return proxy_connect_http(host, port, phb); -- cgit v1.2.3 From bfe7caaa8f7ec37506668b375bfa026b3349a6a6 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 Mar 2008 13:55:25 +0000 Subject: Updated doc/CHANGES. --- doc/CHANGES | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/CHANGES b/doc/CHANGES index 65947617..4e9f72ab 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,3 +1,14 @@ +Version 1.2.1: +- Fixed proxy support. +- Fixed stalling issues while connecting to Jabber when using the OpenSSL + module. +- Fixed problem with GLib and ForkDaemon where processes didn't die when + the client disconnects. +- Fixed handling of "set charset none". (Which pretty much breaks the account + completely in 1.2.) + +Finished ... + Version 1.2: - Added ForkDaemon mode next to the existing Daemon- and inetd modes. With ForkDaemon you can run BitlBee as a stand-alone daemon and every connection -- cgit v1.2.3 From 66c51bbf19a599e3fffd2e3dbb5aae829e15af59 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 Mar 2008 19:11:29 +0000 Subject: Updated debian/changelog, I hope this will be a good 1.2-2 package. --- debian/changelog | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 6c725964..ba68e0e4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,9 +2,8 @@ bitlbee (1.2-2) unstable; urgency=low * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373) * Fixed proxy support. (Closes: #472395) - * Not ready yet. - -- Wilmer van der Gaast Sun, 23 Mar 2008 21:51:57 +0000 + -- Wilmer van der Gaast Mon, 24 Mar 2008 19:10:46 +0000 bitlbee (1.2-1) unstable; urgency=low -- cgit v1.2.3 From 628e6018a8387603e67f4ce1c8b3b67126408726 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 Mar 2008 19:48:36 +0000 Subject: Some more changes for 1.2-2: Adding a bitlbee group for extra security and small stuff. --- debian/bitlbee.init | 2 +- debian/changelog | 6 +++++- debian/postinst | 16 ++++++++++++---- debian/postrm | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/debian/bitlbee.init b/debian/bitlbee.init index baf1a0c6..51b807f5 100755 --- a/debian/bitlbee.init +++ b/debian/bitlbee.init @@ -36,7 +36,7 @@ d_start() { chown bitlbee /var/run/bitlbee.pid start-stop-daemon --start --quiet --pidfile $PIDFILE \ - -c bitlbee -g nogroup \ + -c bitlbee: \ --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $DAEMON_OPT } diff --git a/debian/changelog b/debian/changelog index ba68e0e4..b043c13a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,8 +2,12 @@ bitlbee (1.2-2) unstable; urgency=low * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373) * Fixed proxy support. (Closes: #472395) + * Added a BitlBee group so only root can edit the configs and BitlBee can + just *read* it. + * Manually deleting /var/lib/bitlbee/ when purging, deluser doesn't want to + do it. - -- Wilmer van der Gaast Mon, 24 Mar 2008 19:10:46 +0000 + -- Wilmer van der Gaast Mon, 24 Mar 2008 19:48:24 +0000 bitlbee (1.2-1) unstable; urgency=low diff --git a/debian/postinst b/debian/postinst index 1a906474..80249bfe 100755 --- a/debian/postinst +++ b/debian/postinst @@ -73,13 +73,21 @@ if [ -d $CONFDIR ] && chown -R bitlbee $CONFDIR; then exit 0 fi -adduser --system --home /var/lib/bitlbee/ --disabled-login --disabled-password bitlbee +adduser --system --group --disabled-login --disabled-password --home /var/lib/bitlbee/ bitlbee chmod 700 /var/lib/bitlbee/ ## Can't do this in packaging phase: Don't know the UID yet. Access to -## the file should be limited, now that it stores passwords. -chmod 600 /etc/bitlbee/bitlbee.conf -chown bitlbee /etc/bitlbee/bitlbee.conf +## the file should be limited, now that it stores passwords. Added +## --group later for a little more security, but have to see if I can +## apply this change to existing installations on upgrades. Will think +## about that later. +if getent group bitlbee > /dev/null; then + chmod 640 /etc/bitlbee/bitlbee.conf + chown root:bitlbee /etc/bitlbee/bitlbee.conf +else + chmod 600 /etc/bitlbee/bitlbee.conf + chown bitlbee /etc/bitlbee/bitlbee.conf +fi if [ -z "$2" ]; then /etc/init.d/bitlbee start diff --git a/debian/postrm b/debian/postrm index f7686e7b..5c3b4b2e 100755 --- a/debian/postrm +++ b/debian/postrm @@ -8,5 +8,7 @@ if [ -e /usr/share/debconf/confmodule ]; then fi update-rc.d bitlbee remove > /dev/null 2>&1 || true -deluser --system --remove-home bitlbee || true rm -f /etc/default/bitlbee + +deluser --system --remove-home bitlbee || true +rm -rf /var/lib/bitlbee ## deluser doesn't seem to do this for homedirs in /var -- cgit v1.2.3 From 483f8dd1042e89e02a0eb736f65885e9f74a344d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 24 Mar 2008 21:13:23 +0000 Subject: Removed DEB_BUILD_OPTIONS because it turns out this isn't just some string I can pass through to configure, there's an official policy on what can be in there exactly. (Or at least I found a suggested policy on the debian- policy mailing list.) 1.2-3, because I just uploaded -2 already. :-( --- debian/changelog | 8 ++++++++ debian/rules | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index b043c13a..1d266c0c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +bitlbee (1.2-3) unstable; urgency=low + + * Removed DEB_BUILD_OPTIONS again (forgot to apply that change to the 1.2 + branch when I finished 1.0.4-2, things diverged too much anyway.) + Closes: #472540. + + -- Wilmer van der Gaast Mon, 24 Mar 2008 21:10:14 +0000 + bitlbee (1.2-2) unstable; urgency=low * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373) diff --git a/debian/rules b/debian/rules index 0c757899..252fb742 100755 --- a/debian/rules +++ b/debian/rules @@ -13,7 +13,7 @@ endif build-arch: build-arch-stamp build-arch-stamp: if [ ! -d debian ]; then exit 1; fi - ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(DEB_BUILD_OPTIONS) + ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(MAKE) # $(MAKE) -C doc/ all touch build-arch-stamp -- cgit v1.2.3 From 0281c4598b396e837342c6fa6465bc709fc068a3 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Mar 2008 21:01:09 +0000 Subject: s/DAEMON_OPT/BITLBEE_OPTS/ so the init script will actually pick up flags from /etc/default/bitlbee. --- debian/bitlbee.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/bitlbee.init b/debian/bitlbee.init index 51b807f5..62b57b13 100755 --- a/debian/bitlbee.init +++ b/debian/bitlbee.init @@ -17,7 +17,7 @@ SCRIPTNAME=/etc/init.d/$NAME # Default value BITLBEE_PORT=6667 -DAEMON_OPT=-F +BITLBEE_OPTS=-F # Read config file if it is present. if [ -r /etc/default/$NAME ]; then @@ -37,7 +37,7 @@ d_start() { start-stop-daemon --start --quiet --pidfile $PIDFILE \ -c bitlbee: \ - --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $DAEMON_OPT + --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $BITLBEE_OPTS } # -- cgit v1.2.3 From e74c7fe11099e45da9a17b4d791162d57d2768f8 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Mar 2008 21:11:23 +0000 Subject: Added dependency information to the init script, and updated changelog. --- debian/bitlbee.init | 7 +++++++ debian/changelog | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/debian/bitlbee.init b/debian/bitlbee.init index 62b57b13..904ae5ea 100755 --- a/debian/bitlbee.init +++ b/debian/bitlbee.init @@ -1,4 +1,11 @@ #! /bin/sh +### BEGIN INIT INFO +# Provides: bitlbee +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 1 +### END INIT INFO # # Init script for BitlBee Debian package. Based on skeleton init script: # diff --git a/debian/changelog b/debian/changelog index 1d266c0c..b964ee0e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +bitlbee (1.2-4) unstable; urgency=low + + * Not a real release, just a placeholder for the changelog. + * Fixed init script to use the BITLBEE_OPTS variable, not an undefined + DAEMON_OPT. + * Added dependency information to the init script. (Closes: #472567) + + -- Wilmer van der Gaast Sat, 29 Mar 2008 21:10:33 +0000 + bitlbee (1.2-3) unstable; urgency=low * Removed DEB_BUILD_OPTIONS again (forgot to apply that change to the 1.2 -- cgit v1.2.3 From a199d33ed818820ffba328f718799bbd77392f6a Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Mar 2008 22:19:17 +0000 Subject: Closing bug #209: The PASS command can now be used to identify yourself to BitlBee. The advantage: No more messing with NickServ hooks. Just set a server password. --- irc.c | 17 ++++++++++++++++- irc.h | 4 +++- irc_commands.c | 24 +++++++++++++++++++++--- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/irc.c b/irc.c index 3589256e..fa0c03fe 100644 --- a/irc.c +++ b/irc.c @@ -735,12 +735,27 @@ void irc_login( irc_t *irc ) u->online = 1; irc_spawn( irc, u ); - irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQs are answered there." ); + irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n" + "If you've never used BitlBee before, please do read the help " + "information using the \x02help\x02 command. Lots of FAQs are " + "answered there.\n" + "If you already have an account on this server, just use the " + "\x02identify\x02 command to identify yourself." ); if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname ); irc->status |= USTATUS_LOGGED_IN; + + /* This is for bug #209 (use PASS to identify to NickServ). */ + if( irc->password != NULL ) + { + char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; + + irc_setpass( irc, NULL ); + root_command( irc, send_cmd ); + g_free( send_cmd[1] ); + } } void irc_motd( irc_t *irc ) diff --git a/irc.h b/irc.h index eb70ad1c..eaf531b7 100644 --- a/irc.h +++ b/irc.h @@ -68,7 +68,9 @@ typedef struct irc char *user; char *host; char *realname; - char *password; + char *password; /* HACK: Used to save the user's password, but before + logging in, this may contain a password we should + send to identify after USER/NICK are received. */ char umode[8]; diff --git a/irc_commands.c b/irc_commands.c index b8bae541..61517614 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -29,7 +29,19 @@ static void irc_cmd_pass( irc_t *irc, char **cmd ) { - if( global.conf->auth_pass && + if( irc->status & USTATUS_LOGGED_IN ) + { + char *send_cmd[] = { "identify", cmd[1], NULL }; + + /* We're already logged in, this client seems to send the PASS + command last. (Possibly it won't send it at all if it turns + out we don't require it, which will break this feature.) + Try to identify using the given password. */ + return root_command( irc, send_cmd ); + } + /* Handling in pre-logged-in state, first see if this server is + password-protected: */ + else if( global.conf->auth_pass && ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : strcmp( cmd[1], global.conf->auth_pass ) == 0 ) ) @@ -37,10 +49,16 @@ static void irc_cmd_pass( irc_t *irc, char **cmd ) irc->status |= USTATUS_AUTHORIZED; irc_check_login( irc ); } - else + else if( global.conf->auth_pass ) { irc_reply( irc, 464, ":Incorrect password" ); } + else + { + /* Remember the password and try to identify after USER/NICK. */ + irc_setpass( irc, cmd[1] ); + irc_check_login( irc ); + } } static void irc_cmd_user( irc_t *irc, char **cmd ) @@ -580,7 +598,7 @@ static void irc_cmd_rehash( irc_t *irc, char **cmd ) } static const command_t irc_commands[] = { - { "pass", 1, irc_cmd_pass, IRC_CMD_PRE_LOGIN }, + { "pass", 1, irc_cmd_pass, 0 }, { "user", 4, irc_cmd_user, IRC_CMD_PRE_LOGIN }, { "nick", 1, irc_cmd_nick, 0 }, { "quit", 0, irc_cmd_quit, 0 }, -- cgit v1.2.3 From 18ff38fad0d6d47853fb43ec5a99b29ba031a8ca Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Mar 2008 23:15:04 +0000 Subject: Be more liberal with accepted line endings. ERC on Windows likes to use "\r\r\n", for example, and until now BitlBee only chopped off the \r\n, leaving the first \r as part of the command, which means it couldn't log in to BitlBee at all. (Bad character in nickname.) --- irc.c | 54 ++++++++++++++++++++++++++---------------------------- tests/check_irc.c | 4 ++-- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/irc.c b/irc.c index fa0c03fe..99f0de9a 100644 --- a/irc.c +++ b/irc.c @@ -296,9 +296,8 @@ void irc_process( irc_t *irc ) { char conv[IRC_MAX_LINE+1]; - /* [WvG] Because irc_tokenize splits at every newline, the lines[] list - should end with an empty string. This is why this actually works. - Took me a while to figure out, Maurits. :-P */ + /* [WvG] If the last line isn't empty, it's an incomplete line and we + should wait for the rest to come in before processing it. */ if( lines[i+1] == NULL ) { temp = g_strdup( lines[i] ); @@ -368,42 +367,41 @@ void irc_process( irc_t *irc ) contains an incomplete line at the end, ends with an empty string. */ char **irc_tokenize( char *buffer ) { - int i, j; + int i, j, n = 3; char **lines; - /* Count the number of elements we're gonna need. */ - for( i = 0, j = 1; buffer[i] != '\0'; i ++ ) - { - if( buffer[i] == '\n' ) - if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) - j ++; - } - - /* Allocate j+1 elements. */ - lines = g_new( char *, j + 1 ); - - /* NULL terminate our list. */ - lines[j] = NULL; + /* Allocate n+1 elements. */ + lines = g_new( char *, n + 1 ); lines[0] = buffer; - /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional. - * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too. - */ - for( i = 0, j = 0; buffer[i] != '\0'; i ++) + /* Split the buffer in several strings, and accept any kind of line endings, + * knowing that ERC on Windows may send something interesting like \r\r\n, + * and surely there must be clients that think just \n is enough... */ + for( i = 0, j = 0; buffer[i] != '\0'; i ++ ) { - if( buffer[i] == '\n' ) + if( buffer[i] == '\r' || buffer[i] == '\n' ) { - buffer[i] = '\0'; + while( buffer[i] == '\r' || buffer[i] == '\n' ) + buffer[i++] = '\0'; - if( i > 0 && buffer[i-1] == '\r' ) - buffer[i-1] = '\0'; - if( buffer[i+1] != '\r' && buffer[i+1] != '\n' ) - lines[++j] = buffer + i + 1; + lines[++j] = buffer + i; + + if( j >= n ) + { + n *= 2; + lines = g_renew( char *, lines, n + 1 ); + } + + if( buffer[i] == '\0' ) + break; } } - return( lines ); + /* NULL terminate our list. */ + lines[++j] = NULL; + + return lines; } /* Split an IRC-style line into little parts/arguments. */ diff --git a/tests/check_irc.c b/tests/check_irc.c index c1cf05a5..66fe0021 100644 --- a/tests/check_irc.c +++ b/tests/check_irc.c @@ -36,8 +36,8 @@ START_TEST(test_login) irc = irc_new(g_io_channel_unix_get_fd(ch1)); - fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\n" - "USER a a a a\r\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL); + fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\r\n" + "USER a a a a\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL); fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL); g_main_iteration(FALSE); -- cgit v1.2.3 From 5ecf96b935c6f6c0fba00d84cf7616ee04b06aed Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 30 Mar 2008 17:15:15 +0100 Subject: Updated doc/CHANGES again. --- doc/CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/CHANGES b/doc/CHANGES index 4e9f72ab..93ad35e2 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -6,6 +6,9 @@ Version 1.2.1: the client disconnects. - Fixed handling of "set charset none". (Which pretty much breaks the account completely in 1.2.) +- You can now automatically identify yourself to BitlBee by setting a server + password in your IRC client. +- Compatible with all crazy kinds of line endings that clients can send. Finished ... -- cgit v1.2.3 From f9756bd2e2711d58e06ad2a33ad3292ff10fc6da Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 30 Mar 2008 22:26:16 +0100 Subject: Changed charset handling: irc_t keeps two iconv structures, which are just used for every line sent and received, so now there's no need to use g_iconv_open() every time a message comes in/out. Also, fixed a small memory leak that was there for a long time but somehow never caught my attention. --- irc.c | 102 ++++++++++++++++++++++++++++++++++++++++++++------------- irc.h | 1 + irc_commands.c | 3 +- set.c | 15 --------- set.h | 1 - 5 files changed, 81 insertions(+), 41 deletions(-) diff --git a/irc.c b/irc.c index 99f0de9a..2faa2bc1 100644 --- a/irc.c +++ b/irc.c @@ -41,6 +41,35 @@ static char *passchange( set_t *set, char *value ) return NULL; } +static char *set_eval_charset( set_t *set, char *value ) +{ + irc_t *irc = set->data; + GIConv ic, oc; + + if( g_strcasecmp( value, "none" ) == 0 ) + value = g_strdup( "utf-8" ); + + if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) + { + return NULL; + } + if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) + { + g_iconv_close( ic ); + return NULL; + } + + if( irc->iconv != (GIConv) -1 ) + g_iconv_close( irc->iconv ); + if( irc->oconv != (GIConv) -1 ) + g_iconv_close( irc->oconv ); + + irc->iconv = ic; + irc->oconv = oc; + + return value; +} + irc_t *irc_new( int fd ) { irc_t *irc; @@ -64,6 +93,9 @@ irc_t *irc_new( int fd ) irc->mynick = g_strdup( ROOT_NICK ); irc->channel = g_strdup( ROOT_CHAN ); + irc->iconv = (GIConv) -1; + irc->oconv = (GIConv) -1; + if( global.conf->hostname ) { irc->myhost = g_strdup( global.conf->hostname ); @@ -126,6 +158,9 @@ irc_t *irc_new( int fd ) conf_loaddefaults( irc ); + /* Evaluator sets the iconv/oconv structures. */ + set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); + return( irc ); } @@ -264,6 +299,13 @@ void irc_free(irc_t * irc) g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); g_hash_table_destroy(irc->watches); + if( irc->iconv != (GIConv) -1 ) + g_iconv_close( irc->iconv ); + if( irc->oconv != (GIConv) -1 ) + g_iconv_close( irc->oconv ); + + g_free( irc->last_target ); + g_free(irc); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -285,7 +327,7 @@ void irc_setpass (irc_t *irc, const char *pass) void irc_process( irc_t *irc ) { - char **lines, *temp, **cmd, *cs; + char **lines, *temp, **cmd; int i; if( irc->readbuffer != NULL ) @@ -294,7 +336,7 @@ void irc_process( irc_t *irc ) for( i = 0; *lines[i] != '\0'; i ++ ) { - char conv[IRC_MAX_LINE+1]; + char *conv = NULL; /* [WvG] If the last line isn't empty, it's an incomplete line and we should wait for the rest to come in before processing it. */ @@ -307,10 +349,14 @@ void irc_process( irc_t *irc ) break; } - if( ( cs = set_getstr( &irc->set, "charset" ) ) && g_strcasecmp( cs, "none" ) != 0 ) + if( irc->iconv != (GIConv) -1 ) { - conv[IRC_MAX_LINE] = 0; - if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 ) + gsize bytes_read, bytes_written; + + conv = g_convert_with_iconv( lines[i], -1, irc->iconv, + &bytes_read, &bytes_written, NULL ); + + if( conv == NULL || bytes_read != strlen( lines[i] ) ) { /* GLib can do strange things if things are not in the expected charset, so let's be a little bit paranoid here: */ @@ -322,15 +368,18 @@ void irc_process( irc_t *irc ) "that charset, or tell BitlBee which charset to " "expect by changing the charset setting. See " "`help set charset' for more information. Your " - "message was ignored.", cs ); - *conv = 0; + "message was ignored.", + set_getstr( &irc->set, "charset" ) ); + + g_free( conv ); + conv = NULL; } else { irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "Warning: invalid characters received at login time." ); - strncpy( conv, lines[i], IRC_MAX_LINE ); + conv = g_strdup( lines[i] ); for( temp = conv; *temp; temp ++ ) if( *temp & 0x80 ) *temp = '?'; @@ -339,11 +388,15 @@ void irc_process( irc_t *irc ) lines[i] = conv; } - if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) - continue; - irc_exec( irc, cmd ); + if( lines[i] ) + { + if( ( cmd = irc_parse_line( lines[i] ) ) == NULL ) + continue; + irc_exec( irc, cmd ); + g_free( cmd ); + } - g_free( cmd ); + g_free( conv ); /* Shouldn't really happen, but just in case... */ if( !g_slist_find( irc_connection_list, irc ) ) @@ -535,32 +588,35 @@ void irc_write( irc_t *irc, char *format, ... ) va_end( params ); return; - } void irc_vawrite( irc_t *irc, char *format, va_list params ) { int size; - char line[IRC_MAX_LINE+1], *cs; + char line[IRC_MAX_LINE+1]; /* Don't try to write anything new anymore when shutting down. */ if( irc->status & USTATUS_SHUTDOWN ) return; - line[IRC_MAX_LINE] = 0; + memset( line, 0, sizeof( line ) ); g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); - strip_newlines( line ); - if( ( cs = set_getstr( &irc->set, "charset" ) ) && - g_strcasecmp( cs, "none" ) != 0 && g_strcasecmp( cs, "utf-8" ) != 0 ) + + if( irc->oconv != (GIConv) -1 ) { - char conv[IRC_MAX_LINE+1]; + gsize bytes_read, bytes_written; + char *conv; + + conv = g_convert_with_iconv( line, -1, irc->oconv, + &bytes_read, &bytes_written, NULL ); + + if( bytes_read == strlen( line ) ) + strncpy( line, conv, IRC_MAX_LINE - 2 ); - conv[IRC_MAX_LINE] = 0; - if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 ) - strcpy( line, conv ); + g_free( conv ); } - strcat( line, "\r\n" ); + g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 ); if( irc->sendbuffer != NULL ) { diff --git a/irc.h b/irc.h index eaf531b7..b8c52925 100644 --- a/irc.h +++ b/irc.h @@ -60,6 +60,7 @@ typedef struct irc int pinging; char *sendbuffer; char *readbuffer; + GIConv iconv, oconv; int sentbytes; time_t oldtime; diff --git a/irc_commands.c b/irc_commands.c index 61517614..6a47007a 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -277,8 +277,7 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd ) if( cmd[1] != irc->last_target ) { - if( irc->last_target ) - g_free( irc->last_target ); + g_free( irc->last_target ); irc->last_target = g_strdup( cmd[1] ); } } diff --git a/set.c b/set.c index 90b29f91..112e6937 100644 --- a/set.c +++ b/set.c @@ -229,18 +229,3 @@ char *set_eval_ops( set_t *set, char *value ) return value; } - -char *set_eval_charset( set_t *set, char *value ) -{ - GIConv cd; - - if( g_strcasecmp( value, "none" ) == 0 ) - return value; - - cd = g_iconv_open( "UTF-8", value ); - if( cd == (GIConv) -1 ) - return NULL; - - g_iconv_close( cd ); - return value; -} diff --git a/set.h b/set.h index 7dcbb869..8c722877 100644 --- a/set.h +++ b/set.h @@ -96,6 +96,5 @@ char *set_eval_bool( set_t *set, char *value ); /* Some not very generic evaluators that really shouldn't be here... */ char *set_eval_to_char( set_t *set, char *value ); char *set_eval_ops( set_t *set, char *value ); -char *set_eval_charset( set_t *set, char *value ); #endif /* __SET_H__ */ -- cgit v1.2.3 From ddba0aea68f90b06bb6278cada982eb88889c31c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 30 Mar 2008 22:28:39 +0100 Subject: Removing speech, in case I forget before 1.2.1. --- doc/RELEASE-SPEECH-1.2 | 57 -------------------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 doc/RELEASE-SPEECH-1.2 diff --git a/doc/RELEASE-SPEECH-1.2 b/doc/RELEASE-SPEECH-1.2 deleted file mode 100644 index ec7c48b4..00000000 --- a/doc/RELEASE-SPEECH-1.2 +++ /dev/null @@ -1,57 +0,0 @@ -BitlBee ... is Bitl -------------------- - -"I CAN HAS SPEEECH?" This is how Wilmer announced to me that he was going to do -another BitlBee release. I was as surprised as you are. I thought he had given -up on this whole releasing business. - -There is some humor in using a LOLcats reference to announce a new Bee -release. The last major BitlBee release (1.0) was done a long time before the -hype even begun. Between then and now we've celebrated BitlBee's fifth birthday -and had a handful of releases, but nothing big happened. As a user this lax -release planning worries me. What if this means that later releases will take -even longer? I don't think we should fear this. Let us explore why this release -took so long. - -Personally, I blame Google. - -There, I've said it. Google. The guys who are so big on "Do No Evil" and all -that jazz. They caused this release to be so late. Let me explain why. - -They made Wilmer an offer. Wilmer, being the sillily naive guy he is, couldn't -refuse. There were no decapitated horses involved, but he couldn't refuse -nonetheless. That's not a big problem of course. Lots of guys (and gals, sure) -work for Google. It wouldn't have become a problem if they hadn't shipped him of -to Ireland. That's where the trouble starts. - -Ireland. Home of the leprechauns. These rascals joined forces with aliens and -LOLcats to abduct Wilmer. The aliens had been trying for years to kidnap him, -but they were on his turf and his trusty sidekicks Jelmer and Maurits were there -to help him. All that changed when he moved to Ireland. - -But it wasn't just that Wilmer was all alone in some strange place. It was also -that the aliens had created the LOLcats and made an alliance with the -leprechauns--the real rulers of Ireland. Wilmer is cool, but he's not that -cool. So they abducted him for a few years. When he finally came back, he -regathered his mad coding skills and hacked a new release together. - -By now you're thinking, what has happened to Jelmer and Maurits? Well, they're -still here and they worked on the Bee while Wilmer was absent. But, like open -source, they are very Bitl--they're cool, but they're ready when they're -ready. - -Well, whatever you may think of my little theory, they did take forever to -launch this release. We're not mad at them, because it shows. They have -added some cool new features and made plenty of changes under the hood. Let me -give you a sneak preview of some of the new features: Jabber groupchats are -supported. Configuration files are stored encrypted. You can now use -ForkDaemon mode, which gives better stability over normal daemon mode, but -doesn't require inetd. Also, server owners can now use the /OPER command to -spy on their users. And--as I was specifically asked to mention--this is the -first stable release that supports plugins. That's some Bitl changes for ya. - -BitlBee is cool, but ready when it's ready. Very Bitl. - -Sjoerd. LOL. - -(LOLBee by Erik Bosman.) -- cgit v1.2.3 From fa75134008bd9206ca02380927c27581feb65c3e Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Wed, 2 Apr 2008 00:07:21 +0100 Subject: Reordered irc_free() a little bit, hoping that this will fix a crash-on-quit bug I can't figure out. The previous order wasn't optimal. --- account.c | 12 +++---- irc.c | 111 +++++++++++++++++++++++++++++++------------------------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/account.c b/account.c index 4eb78faa..2c6e1069 100644 --- a/account.c +++ b/account.c @@ -181,19 +181,17 @@ void account_del( irc_t *irc, account_t *acc ) { account_t *a, *l = NULL; + if( acc->ic ) + /* Caller should have checked, accounts still in use can't be deleted. */ + return; + for( a = irc->accounts; a; a = (l=a)->next ) if( a == acc ) { - if( a->ic ) return; /* Caller should have checked, accounts still in use can't be deleted. */ - if( l ) - { l->next = a->next; - } else - { irc->accounts = a->next; - } while( a->set ) set_del( &a->set, a->set->key ); @@ -202,7 +200,7 @@ void account_del( irc_t *irc, account_t *acc ) g_free( a->user ); g_free( a->pass ); - if( a->server ) g_free( a->server ); + g_free( a->server ); if( a->reconnect ) /* This prevents any reconnect still queued to happen */ cancel_auto_reconnect( a ); g_free( a ); diff --git a/irc.c b/irc.c index 2faa2bc1..585cf232 100644 --- a/irc.c +++ b/irc.c @@ -219,9 +219,8 @@ static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) } /* Because we have no garbage collection, this is quite annoying */ -void irc_free(irc_t * irc) +void irc_free( irc_t * irc ) { - account_t *account; user_t *user, *usertmp; log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); @@ -230,83 +229,85 @@ void irc_free(irc_t * irc) if( storage_save( irc, TRUE ) != STORAGE_OK ) irc_usermsg( irc, "Error while saving settings!" ); - closesocket( irc->fd ); - - if( irc->ping_source_id > 0 ) - b_event_remove( irc->ping_source_id ); - b_event_remove( irc->r_watch_source_id ); - if( irc->w_watch_source_id > 0 ) - b_event_remove( irc->w_watch_source_id ); - irc_connection_list = g_slist_remove( irc_connection_list, irc ); - for (account = irc->accounts; account; account = account->next) { - if (account->ic) { - imc_logout(account->ic, TRUE); - } else if (account->reconnect) { - cancel_auto_reconnect(account); - } - } - - g_free(irc->sendbuffer); - g_free(irc->readbuffer); - - g_free(irc->nick); - g_free(irc->user); - g_free(irc->host); - g_free(irc->realname); - g_free(irc->password); - - g_free(irc->myhost); - g_free(irc->mynick); - - g_free(irc->channel); - - while (irc->queries != NULL) - query_del(irc, irc->queries); - - while (irc->accounts) - if (irc->accounts->ic == NULL) - account_del(irc, irc->accounts); + while( irc->accounts ) + { + if( irc->accounts->ic ) + imc_logout( irc->accounts->ic, FALSE ); + else if( irc->accounts->reconnect ) + cancel_auto_reconnect( irc->accounts ); + + if( irc->accounts->ic == NULL ) + account_del( irc, irc->accounts ); else /* Nasty hack, but account_del() doesn't work in this case and we don't want infinite loops, do we? ;-) */ irc->accounts = irc->accounts->next; + } + + while( irc->queries != NULL ) + query_del( irc, irc->queries ); - while (irc->set) - set_del(&irc->set, irc->set->key); + while( irc->set ) + set_del( &irc->set, irc->set->key ); - if (irc->users != NULL) { + if (irc->users != NULL) + { user = irc->users; - while (user != NULL) { - g_free(user->nick); - g_free(user->away); - g_free(user->handle); - if(user->user!=user->nick) g_free(user->user); - if(user->host!=user->nick) g_free(user->host); - if(user->realname!=user->nick) g_free(user->realname); - b_event_remove(user->sendbuf_timer); + while( user != NULL ) + { + g_free( user->nick ); + g_free( user->away ); + g_free( user->handle ); + if( user->user != user->nick ) g_free( user->user ); + if( user->host != user->nick ) g_free( user->host ); + if( user->realname != user->nick ) g_free( user->realname ); + b_event_remove( user->sendbuf_timer ); usertmp = user; user = user->next; - g_free(usertmp); + g_free( usertmp ); } } - g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL); - g_hash_table_destroy(irc->userhash); + if( irc->ping_source_id > 0 ) + b_event_remove( irc->ping_source_id ); + b_event_remove( irc->r_watch_source_id ); + if( irc->w_watch_source_id > 0 ) + b_event_remove( irc->w_watch_source_id ); + + closesocket( irc->fd ); + irc->fd = -1; + + g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL ); + g_hash_table_destroy( irc->userhash ); - g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); - g_hash_table_destroy(irc->watches); + g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); + g_hash_table_destroy( irc->watches ); if( irc->iconv != (GIConv) -1 ) g_iconv_close( irc->iconv ); if( irc->oconv != (GIConv) -1 ) g_iconv_close( irc->oconv ); + g_free( irc->sendbuffer ); + g_free( irc->readbuffer ); + + g_free( irc->nick ); + g_free( irc->user ); + g_free( irc->host ); + g_free( irc->realname ); + g_free( irc->password ); + + g_free( irc->myhost ); + g_free( irc->mynick ); + + g_free( irc->channel ); + g_free( irc->last_target ); - g_free(irc); + g_free( irc ); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) b_main_quit(); -- cgit v1.2.3 From 31fc3970e53409f71ed7d09e277e0e33461ad571 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Dec 2025 03:21:03 +0100 Subject: Use simpler flags for gcov. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 22989f60..02f01225 100755 --- a/configure +++ b/configure @@ -374,8 +374,8 @@ else fi if [ "$gcov" = "1" ]; then - echo "CFLAGS+=-ftest-coverage -fprofile-arcs" >> Makefile.settings - echo "EFLAGS+=-lgcov" >> Makefile.settings + echo "CFLAGS+=--coverage" >> Makefile.settings + echo "EFLAGS+=--coverage" >> Makefile.settings fi if [ "$plugins" = 0 ]; then -- cgit v1.2.3 From e942df125bf47b2cb0f20bed2d5cd6c18b330118 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Dec 2025 03:22:45 +0100 Subject: Ignore coverage output dir. --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 12dd9c10..7f9796b9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -16,3 +16,4 @@ tests/check *.gcov *.gcno *.o +coverage -- cgit v1.2.3 From 0db75ad966458610427dacdd31ecbaddbca18935 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 27 Dec 2025 03:25:31 +0100 Subject: Ignore lcov output data. --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 7f9796b9..7d0ad548 100644 --- a/.bzrignore +++ b/.bzrignore @@ -17,3 +17,4 @@ tests/check *.gcno *.o coverage +bitlbee.info -- cgit v1.2.3