diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | account.c | 2 | ||||
-rw-r--r-- | bitlbee.c | 16 | ||||
-rw-r--r-- | bitlbee.conf | 13 | ||||
-rw-r--r-- | bitlbee.h | 4 | ||||
-rw-r--r-- | conf.c | 9 | ||||
-rw-r--r-- | conf.h | 1 | ||||
-rwxr-xr-x | configure | 9 | ||||
-rw-r--r-- | crypting.c | 60 | ||||
-rw-r--r-- | doc/CHANGES | 15 | ||||
-rw-r--r-- | doc/user-guide/commands.xml | 15 | ||||
-rw-r--r-- | irc.c | 2 | ||||
-rw-r--r-- | lib/misc.c | 3 | ||||
-rw-r--r-- | lib/misc.h | 2 | ||||
-rw-r--r-- | protocols/jabber/io.c | 38 | ||||
-rw-r--r-- | protocols/jabber/iq.c | 31 | ||||
-rw-r--r-- | protocols/jabber/jabber.h | 5 | ||||
-rw-r--r-- | protocols/msn/msn.c | 4 | ||||
-rw-r--r-- | protocols/msn/msn.h | 6 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 6 | ||||
-rw-r--r-- | protocols/msn/ns.c | 25 | ||||
-rw-r--r-- | protocols/nogaim.c | 50 | ||||
-rw-r--r-- | protocols/nogaim.h | 16 | ||||
-rw-r--r-- | protocols/yahoo/libyahoo2.c | 332 | ||||
-rw-r--r-- | protocols/yahoo/yahoo2_types.h | 23 | ||||
-rw-r--r-- | root_commands.c | 79 | ||||
-rw-r--r-- | unix.c | 71 |
27 files changed, 424 insertions, 421 deletions
@@ -48,7 +48,7 @@ Makefile.settings: @echo clean: $(subdirs) - rm -f *.o $(OUTFILE) core utils/bitlbeed encode decode + rm -f *.o $(OUTFILE) core utils/bitlbeed $(MAKE) -C tests clean distclean: clean $(subdirs) @@ -123,11 +123,5 @@ ifndef DEBUG @-$(STRIP) $(OUTFILE) endif -encode: crypting.c - $(CC) crypting.c lib/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS) - -decode: encode - cp encode decode - ctags: ctags `find . -name "*.c"` `find . -name "*.h"` @@ -54,6 +54,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); + s = set_add( &a->set, "nick_source", "handle", NULL, a ); + s = set_add( &a->set, "password", NULL, set_eval_account, a ); s->flags |= ACC_SET_NOSAVE | SET_NULL_OK; @@ -108,11 +108,17 @@ int bitlbee_daemon_init() chdir( "/" ); - /* Sometimes std* are already closed (for example when we're in a RESTARTed - BitlBee process. So let's only close TTY-fds. */ - if( isatty( 0 ) ) close( 0 ); - if( isatty( 1 ) ) close( 1 ); - if( isatty( 2 ) ) close( 2 ); + i = close( 0 ) == 0; + i += close( 1 ) == 0; + i += close( 2 ) == 0; + /* To avoid that something important ends up on one of those + fd's, open them for something bogus. Otherwise RESTART + may cause troubles. */ + while( i > 0 ) + { + open( "/dev/null", O_WRONLY ); + i --; + } } #endif diff --git a/bitlbee.conf b/bitlbee.conf index 5fce2820..c5dafd9f 100644 --- a/bitlbee.conf +++ b/bitlbee.conf @@ -54,9 +54,8 @@ ## 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 <user password=""> attribute in a BitlBee -## XML file (for now there's no easier way to generate the hash). +## You can also have a BitlBee-style MD5 hash here. Format: "md5:", followed +## by a hash as generated by "bitlbee -x hash <password>". ## # AuthPassword = ItllBeBitlBee ## Heh.. Our slogan. ;-) ## or @@ -120,6 +119,14 @@ ## Proxy = socks4://socksproxy.localnet.com ## Proxy = socks5://socksproxy.localnet.com +## Protocols offered by bitlbee +## +## As recompiling may be quite unpractical for some people, this option +## allows to remove the support of protocol, even if compiled in. If +## nothing is given, there are no restrictions. +## +## Protocols = jabber yahoo + [defaults] @@ -26,13 +26,15 @@ #ifndef _BITLBEE_H #define _BITLBEE_H +#ifndef _GNU_SOURCE #define _GNU_SOURCE /* Stupid GNU :-P */ +#endif /* Depend on Windows 2000 for now since we need getaddrinfo() */ #define _WIN32_WINNT 0x0501 #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "1.2.4" +#define BITLBEE_VERSION "1.2.5" #define VERSION BITLBEE_VERSION #define MAX_STRING 511 @@ -62,6 +62,7 @@ conf_t *conf_load( int argc, char *argv[] ) conf->ping_interval = 180; conf->ping_timeout = 300; conf->user = NULL; + conf->protocols = NULL; proxytype = 0; i = conf_loadini( conf, global.conf_file ); @@ -126,7 +127,7 @@ conf_t *conf_load( int argc, char *argv[] ) else if( opt == 'h' ) { printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n" - " [-c <file>] [-d <dir>] [-h]\n" + " [-c <file>] [-d <dir>] [-x] [-h]\n" "\n" "An IRC-to-other-chat-networks gateway\n" "\n" @@ -142,6 +143,7 @@ conf_t *conf_load( int argc, char *argv[] ) " -v Be verbose (only works in combination with -n)\n" " -c Load alternative configuration file\n" " -d Specify alternative user configuration directory\n" + " -x Command-line interface to password encryption/hashing\n" " -h Show this help page.\n" ); return NULL; } @@ -305,6 +307,11 @@ static int conf_loadini( conf_t *conf, char *file ) g_free( conf->user ); conf->user = g_strdup( ini->value ); } + else if( g_strcasecmp( ini->key, "protocols" ) == 0 ) + { + g_strfreev( conf->protocols ); + conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 ); + } else { fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line ); @@ -49,6 +49,7 @@ typedef struct conf int ping_interval; int ping_timeout; char *user; + char **protocols; } conf_t; G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] ); @@ -158,7 +158,7 @@ else fi echo CFLAGS=$CFLAGS >> Makefile.settings -echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings +echo CFLAGS+=-I`pwd` -iquote`pwd`/lib -iquote`pwd`/protocols -I. >> Makefile.settings echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings @@ -446,6 +446,12 @@ else echo '#define WITH_PLUGINS' >> config.h fi +if [ ! -e doc/user-guide/help.txt ] && ! type xmlto > /dev/null 2> /dev/null; then + echo + echo 'WARNING: Building from an unreleased source tree without prebuilt helpfile.' + echo 'Install xmlto if you want online help to work.' +fi + echo if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then nick=`bzr nick` @@ -555,6 +561,7 @@ GNU/* ) *BSD ) ;; Darwin ) + echo 'STRIP=\# skip strip' >> Makefile.settings ;; IRIX ) ;; @@ -131,63 +131,3 @@ char *deobfucrypt (char *line, const char *password) return (rv); } - -#ifdef CRYPTING_MAIN - -/* A little main() function for people who want a stand-alone program to - encode/decode BitlCrypted files. */ - -int main( int argc, char *argv[] ) -{ - char *hash, *action, line[256]; - char* (*func)( char *, const char * ); - - if( argc < 2 ) - { - fprintf( stderr, "Usage: %s <password>\n\n" - "Reads from stdin, writes to stdout.\n" - "Call as \"encode\" to encode, \"decode\" to decode.\n", argv[0] ); - return( 1 ); - } - - hash = hashpass( argv[1] ); - action = argv[0] + strlen( argv[0] ) - strlen( "encode" ); - - if( strcmp( action, "encode" ) == 0 ) - { - fwrite( hash, 32, 1, stdout ); - func = obfucrypt; - } - else if( strcmp( action, "decode" ) == 0 ) - { - char hash2[32]; - - fread( hash2, 32, 1, stdin ); - if( memcmp( hash, hash2, 32 ) != 0 ) - { - fprintf( stderr, "Passwords don't match. Can't decode.\n" ); - return( 1 ); - } - func = deobfucrypt; - } - else - { - return( main( 0, NULL ) ); - } - - while( fscanf( stdin, "%[^\n]255s", line ) > 0 ) - { - char *out; - - /* Flush the newline */ - fgetc( stdin ); - - out = func( line, argv[1] ); - printf( "%s\n", out ); - g_free( out ); - } - - return( 0 ); -} - -#endif diff --git a/doc/CHANGES b/doc/CHANGES index 1bfd71d4..a0e9b30b 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -3,6 +3,21 @@ found in the bzr commit logs, for example you can try: http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on +Version 1.2.5: +- Many bug fixes, including a fix for MSN login issues, Jabber login timing + issues, Yahoo! crashes at login time with huge contact lists, +- Avoid linking in a static version of libresolv now that glibc has all + relevant functions available in the dynamic version. +- Improved away state code and added the ability to set (non-away) status + messages using "set status" (also possible per account). +- Added a post-1.2 equivalent of encode/decode to quickly encrypt/decrypt + passwords in a way that BitlBee can read them. +- Allow using the full name for generating nicknames, instead of just the + handle. This is especially useful when using the Facebook XMPP server. +- Auto reconnect is now enabled by default since all protocols can properly + detect cases where auto reconnect should be avoided (i.e. concurrent + logins). + Version 1.2.4: - Most important change (and main reason for releasing now): Upgraded Yahoo! module to a newer version to get it working again. diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index a7d06cf1..931608ee 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -607,6 +607,21 @@ </description> </bitlbee-setting> + <bitlbee-setting name="nick_source" type="string" scope="account"> + <default>handle</default> + <possible-values>handle, full_name, first_name</possible-values> + + <description> + <para> + By default, BitlBee generates a nickname for every contact by taking its handle and chopping off everything after the @. In some cases, this gives very inconvenient nicknames. The Facebook XMPP server is a good example, as all Facebook XMPP handles are numeric. + </para> + + <para> + With this setting set to <emphasis>full_name</emphasis>, the person's full name is used to generate a nickname. Or if you don't like long nicknames, set this setting to <emphasis>first_name</emphasis> instead and only the first word will be used. Note that the full name can be full of non-ASCII characters which will be stripped off. + </para> + </description> + </bitlbee-setting> + <bitlbee-setting name="ops" type="string" scope="global"> <default>both</default> <possible-values>both, root, user, none</possible-values> @@ -165,7 +165,7 @@ irc_t *irc_new( int fd ) s->flags |= SET_NULL_OK; s = set_add( &irc->set, "away_devoice", "true", set_eval_away_devoice, irc ); s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); - s = set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc ); + s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc ); s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc ); s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); @@ -33,6 +33,7 @@ #define BITLBEE_CORE #include "nogaim.h" #include "base64.h" +#include "md5.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -522,7 +523,7 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ) } /* 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 ) +char *word_wrap( const char *msg, int line_len ) { GString *ret = g_string_sized_new( strlen( msg ) + 16 ); @@ -61,7 +61,7 @@ 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 ); +G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len ); G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl ); diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 3b0ef3ef..bff4e6c8 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -374,39 +374,23 @@ 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( &ic->acc->set, "resource" ), NULL ) ); - xt_add_attr( reply, "xmlns", XMLNS_BIND ); - reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); - - if( !jabber_write_packet( ic, reply ) ) - return XT_ABORT; - - jd->flags |= JFLAG_WAIT_BIND; - } + jd->flags |= JFLAG_WANT_BIND; if( ( c = xt_find_node( node->children, "session" ) ) ) - { - 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( ic, reply, jabber_pkt_bind_sess ); - - if( !jabber_write_packet( ic, reply ) ) - return XT_ABORT; - - jd->flags |= JFLAG_WAIT_SESSION; - } + jd->flags |= JFLAG_WANT_SESSION; /* This flag is already set if we authenticated via SASL, so now 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( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 ) { if( !jabber_get_roster( ic ) ) return XT_ABORT; } + else if( jd->flags & JFLAG_AUTHENTICATED ) + { + return jabber_pkt_bind_sess( ic, NULL, NULL ); + } return XT_HANDLED; } @@ -440,6 +424,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) imcb_log( ic, "Converting stream to TLS" ); + jd->flags |= JFLAG_STARTTLS_DONE; jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic ); return XT_HANDLED; @@ -530,9 +515,10 @@ gboolean jabber_start_stream( struct im_connection *ic ) if( jd->r_inpa <= 0 ) jd->r_inpa = b_input_add( jd->fd, B_EV_IO_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 ); + greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " + "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", + ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>", + jd->server ); st = jabber_write( ic, greet, strlen( greet ) ); diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index 875b5c81..21e52da6 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -297,24 +297,43 @@ static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { struct jabber_data *jd = ic->proto_data; - struct xt_node *c; + struct xt_node *c, *reply = NULL; char *s; - if( ( c = xt_find_node( node->children, "bind" ) ) ) + if( node && ( 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( &ic->acc->set, "resource" ) ) != 0 ) imcb_log( ic, "Server changed session resource string to `%s'", s + 1 ); - jd->flags &= ~JFLAG_WAIT_BIND; + jd->flags &= ~JFLAG_WANT_BIND; } - else + else if( node && ( c = xt_find_node( node->children, "session" ) ) ) + { + jd->flags &= ~JFLAG_WANT_SESSION; + } + + if( jd->flags & JFLAG_WANT_BIND ) { - jd->flags &= ~JFLAG_WAIT_SESSION; + reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); + xt_add_attr( reply, "xmlns", XMLNS_BIND ); + } + else if( jd->flags & JFLAG_WANT_SESSION ) + { + reply = xt_new_node( "session", NULL, NULL ); + xt_add_attr( reply, "xmlns", XMLNS_SESSION ); } - if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) + if( reply != NULL ) + { + reply = jabber_make_packet( "iq", "set", NULL, reply ); + jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); + + if( !jabber_write_packet( ic, reply ) ) + return XT_ABORT; + } + else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 ) { if( !jabber_get_roster( ic ) ) return XT_ABORT; diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 7bb66e0e..8e3bf036 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -39,12 +39,13 @@ typedef enum 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_WANT_SESSION = 8, /* Set if the server wants a <session/> tag before we continue. */ - JFLAG_WAIT_BIND = 16, /* ... for <bind> tag. */ + JFLAG_WANT_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. */ + JFLAG_STARTTLS_DONE = 128, /* If a plaintext session was converted to TLS. */ } jabber_flags_t; typedef enum diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index e12fb3a9..8930847d 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -26,6 +26,10 @@ #include "nogaim.h" #include "msn.h" +int msn_chat_id; +GSList *msn_connections; +GSList *msn_switchboards; + static char *msn_set_display_name( set_t *set, char *value ); static void msn_init( account_t *acc ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 333ae7f0..84914bc3 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -134,7 +134,7 @@ struct msn_handler_data #define STATUS_SB_IM_SPARE 4 /* Make one-to-one conversation switchboard available again, invite failed. */ #define STATUS_SB_CHAT_SPARE 8 /* Same, but also for groupchats (not used yet). */ -int msn_chat_id; +extern int msn_chat_id; extern const struct msn_away_state msn_away_state_list[]; extern const struct msn_status_code msn_status_code_list[]; @@ -143,8 +143,8 @@ extern const struct msn_status_code msn_status_code_list[]; is down already (for example, when an impatient user disabled the connection), the callback should check whether it's still listed here before doing *anything* else. */ -GSList *msn_connections; -GSList *msn_switchboards; +extern GSList *msn_connections; +extern GSList *msn_switchboards; /* ns.c */ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 6b12217b..668a8b8a 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -170,9 +170,9 @@ char *msn_findheader( char *text, char *header, int len ) while( i < len && ( text[i] == '\r' || text[i] == '\n' ) ) i ++; /* End of headers? */ - if( strncmp( text + i - 2, "\n\n", 2 ) == 0 || - strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 || - strncmp( text + i - 2, "\r\r", 2 ) == 0 ) + if( ( i >= 4 && strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ) || + ( i >= 2 && ( strncmp( text + i - 2, "\n\n", 2 ) == 0 || + strncmp( text + i - 2, "\r\r", 2 ) == 0 ) ) ) { break; } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index b2b9cf81..9c4e1357 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -228,19 +228,26 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) return( 0 ); } } - else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 ) + else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 ) { set_t *s; - http_decode( cmd[4] ); - - strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); - ic->displayname[sizeof(ic->displayname)-1] = 0; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) + if( num_parts == 7 ) { - g_free( s->value ); - s->value = g_strdup( cmd[4] ); + http_decode( cmd[4] ); + + strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); + ic->displayname[sizeof(ic->displayname)-1] = 0; + + if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) + { + g_free( s->value ); + s->value = g_strdup( cmd[4] ); + } + } + else + { + imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); } imcb_log( ic, "Authenticated, getting buddy list" ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 1f46926a..96c2f512 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -97,7 +97,19 @@ GList *protocols = NULL; void register_protocol (struct prpl *p) { - protocols = g_list_append(protocols, p); + int i; + gboolean refused = global.conf->protocols != NULL; + + for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++) + { + if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0) + refused = FALSE; + } + + if (refused) + log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name); + else + protocols = g_list_append(protocols, p); } struct prpl *find_protocol(const char *name) @@ -378,7 +390,7 @@ void imcb_ask( struct im_connection *ic, char *msg, void *data, /* list.c */ -void imcb_add_buddy( struct im_connection *ic, char *handle, char *group ) +void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) { user_t *u; char nick[MAX_NICK_LENGTH+1], *s; @@ -452,9 +464,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 ) +void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ) { user_t *u = user_findhandle( ic, handle ); + char *set; if( !u || !realname ) return; @@ -467,9 +480,26 @@ 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 ); } + + set = set_getstr( &ic->acc->set, "nick_source" ); + if( strcmp( set, "handle" ) != 0 ) + { + char *name = g_strdup( realname ); + + if( strcmp( set, "first_name" ) == 0 ) + { + int i; + for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {} + name[i] = '\0'; + } + + imcb_buddy_nick_hint( ic, handle, name ); + + g_free( name ); + } } -void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ) +void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) { user_t *u; @@ -479,7 +509,7 @@ void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group ) /* 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 ) +void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) { user_t *u = user_findhandle( ic, handle ); char newnick[MAX_NICK_LENGTH+1], *orig_nick; @@ -691,7 +721,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, uint32_t flags, time_t sent_at ) +void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at ) { irc_t *irc = ic->irc; char *wrapped; @@ -824,7 +854,7 @@ void imcb_chat_free( struct groupchat *c ) } } -void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at ) +void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at ) { struct im_connection *ic = c->ic; char *wrapped; @@ -896,7 +926,7 @@ void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at /* buddy_chat.c */ -void imcb_chat_add_buddy( struct groupchat *b, char *handle ) +void imcb_chat_add_buddy( struct groupchat *b, const char *handle ) { user_t *u = user_findhandle( b->ic, handle ); int me = 0; @@ -931,7 +961,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 ) +void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason ) { user_t *u; int me = 0; @@ -1080,7 +1110,7 @@ static char *imc_away_state_find( GList *gcm, char *away, char **message ); int imc_away_send_update( struct im_connection *ic ) { - char *away, *msg; + char *away, *msg = NULL; away = set_getstr( &ic->acc->set, "away" ) ? : set_getstr( &ic->irc->set, "away" ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 54761039..ff24acc2 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -275,11 +275,11 @@ G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, const char *handle, /* This function should be called for each handle which are visible to the * user, usually after a login, or if the user added a buddy and the IM * server confirms that the add was successful. Don't forget to do this! */ -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 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ); +G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const 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 ); +G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ); +G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ); /* Buddy activity */ /* To manipulate the status of a handle. @@ -289,7 +289,7 @@ 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, uint32_t flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const 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 ); @@ -302,11 +302,11 @@ G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle, * 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, const char *handle ); -G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); +G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const 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 ); +G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const 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 ); +G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const 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'. */ diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 721f4b7c..5b2ff44e 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -854,55 +854,6 @@ static int is_same_bud(const void * a, const void * b) { return strcmp(subject->id, object->id); } -static YList * bud_str2list(char *rawlist) -{ - YList * l = NULL; - - char **lines; - char **split; - char **buddies; - char **tmp, **bud; - - lines = y_strsplit(rawlist, "\n", -1); - for (tmp = lines; *tmp; tmp++) { - struct yahoo_buddy *newbud; - - split = y_strsplit(*tmp, ":", 2); - if (!split) - continue; - if (!split[0] || !split[1]) { - y_strfreev(split); - continue; - } - buddies = y_strsplit(split[1], ",", -1); - - for (bud = buddies; bud && *bud; bud++) { - newbud = y_new0(struct yahoo_buddy, 1); - newbud->id = strdup(*bud); - newbud->group = strdup(split[0]); - - if(y_list_find_custom(l, newbud, is_same_bud)) { - FREE(newbud->id); - FREE(newbud->group); - FREE(newbud); - continue; - } - - newbud->real_name = NULL; - - l = y_list_append(l, newbud); - - NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group)); - } - - y_strfreev(buddies); - y_strfreev(split); - } - y_strfreev(lines); - - return l; -} - static char * getcookie(char *rawcookie) { char * cookie=NULL; @@ -1359,140 +1310,150 @@ static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_pac y_list_free(messages); } - -static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_status(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) { YList *l; struct yahoo_data *yd = yid->yd; - 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; + struct yahoo_process_status_entry *u; YList *users = 0; - + if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { - YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_DUPL, NULL); return; } + /* Status updates may be spread accross multiple packets and not + even on buddy boundaries, so keeping some state is important. + So, continue where we left off, and only add a user entry to + the list once it's complete (301-315 End buddy). */ + u = yd->half_user; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; switch (pair->key) { - case 0: /* we won't actually do anything with this */ + case 300: /* Begin buddy */ + if (!strcmp(pair->value, "315") && !u) { + u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1); + } + break; + case 301: /* End buddy */ + if (!strcmp(pair->value, "315") && u) { + users = y_list_prepend(users, u); + u = yd->half_user = NULL; + } + break; + case 0: /* we won't actually do anything with this */ NOTICE(("key %d:%s", pair->key, pair->value)); break; - case 1: /* we don't get the full buddy list here. */ + case 1: /* we don't get the full buddy list here. */ if (!yd->logged_in) { - yd->logged_in = TRUE; - if(yd->current_status < 0) + yd->logged_in = 1; + if (yd->current_status < 0) yd->current_status = yd->initial_status; - YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd-> + client_id, YAHOO_LOGIN_OK, NULL); } break; - case 8: /* how many online buddies we have */ + case 8: /* how many online buddies we have */ NOTICE(("key %d:%s", pair->key, pair->value)); break; - case 7: /* the current buddy */ - u = y_new0(struct user, 1); + case 7: /* the current buddy */ + if (!u) { + /* This will only happen in case of a single level message */ + u = y_new0(struct yahoo_process_status_entry, 1); + users = y_list_prepend(users, u); + } u->name = pair->value; - users = y_list_prepend(users, u); break; - case 10: /* state */ - ((struct user*)users->data)->state = strtol(pair->value, NULL, 10); + case 10: /* state */ + u->state = strtol(pair->value, NULL, 10); break; - case 19: /* custom status message */ - ((struct user*)users->data)->msg = pair->value; + case 19: /* custom status message */ + u->msg = pair->value; break; - case 47: /* is it an away message or not */ - ((struct user*)users->data)->away = atoi(pair->value); + case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */ + u->away = atoi(pair->value); break; - case 137: /* seconds idle */ - ((struct user*)users->data)->idle = atoi(pair->value); + case 137: /* seconds idle */ + u->idle = atoi(pair->value); break; - case 11: /* this is the buddy's session id */ - ((struct user*)users->data)->buddy_session = atoi(pair->value); + case 11: /* this is the buddy's session id */ + u->buddy_session = atoi(pair->value); break; - case 17: /* in chat? */ - ((struct user*)users->data)->f17 = atoi(pair->value); + case 17: /* in chat? */ + u->f17 = atoi(pair->value); break; - case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ - ((struct user*)users->data)->flags = atoi(pair->value); + case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ + u->flags = atoi(pair->value); break; - case 60: /* SMS -> 1 MOBILE USER */ + case 60: /* SMS -> 1 MOBILE USER */ /* sometimes going offline makes this 2, but invisible never sends it */ - ((struct user*)users->data)->mobile = atoi(pair->value); + u->mobile = atoi(pair->value); break; case 138: - ((struct user*)users->data)->f138 = atoi(pair->value); + u->f138 = atoi(pair->value); break; case 184: - ((struct user*)users->data)->f184 = pair->value; + u->f184 = pair->value; break; case 192: - ((struct user*)users->data)->f192 = atoi(pair->value); + u->f192 = atoi(pair->value); break; case 10001: - ((struct user*)users->data)->f10001 = atoi(pair->value); + u->f10001 = atoi(pair->value); break; case 10002: - ((struct user*)users->data)->f10002 = atoi(pair->value); + u->f10002 = atoi(pair->value); break; case 198: - ((struct user*)users->data)->f198 = atoi(pair->value); + u->f198 = atoi(pair->value); break; case 197: - ((struct user*)users->data)->f197 = pair->value; + u->f197 = pair->value; break; case 205: - ((struct user*)users->data)->f205 = pair->value; + u->f205 = pair->value; break; case 213: - ((struct user*)users->data)->f213 = atoi(pair->value); + u->f213 = atoi(pair->value); break; - case 16: /* Custom error message */ - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM); + case 16: /* Custom error message */ + 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)); + WARNING(("unknown status key %d:%s", pair->key, + pair->value)); break; } } - + while (users) { YList *t = users; - struct user *u = users->data; + struct yahoo_process_status_entry *u = users->data; if (u->name != NULL) { - if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */ - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); + if (pkt->service == + YAHOO_SERVICE_LOGOFF + /*|| u->flags == 0 No flags for YMSG16 */ ) { + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> + client_id, u->name, + YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); } else { /* Key 47 always seems to be 1 for YMSG16 */ - if(!u->state) + if (!u->state) u->away = 0; else u->away = 1; - YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile); + YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> + client_id, u->name, u->state, u->msg, + u->away, u->idle, u->mobile); } } @@ -1502,7 +1463,8 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack } } -static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_buddy_list(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; @@ -1514,141 +1476,117 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_ for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - switch(pair->key) { + switch (pair->key) { case 300: case 301: case 302: + break; /* Separators. Our logic does not need them */ case 303: - if ( 315 == atoi(pair->value) ) + if (318 == atoi(pair->value)) last_packet = 1; break; case 65: - g_free(cur_group); cur_group = strdup(pair->value); break; case 7: newbud = y_new0(struct yahoo_buddy, 1); newbud->id = strdup(pair->value); - if (cur_group) { + if (cur_group) newbud->group = strdup(cur_group); - } else { - YList *last; - struct yahoo_buddy *lastbud; - - for (last = yd->buddies; last && last->next; last = last->next); - if (last) { - lastbud = last->data; - newbud->group = strdup(lastbud->group); - } else { - newbud->group = strdup("Buddies"); - } - } + else if (yd->buddies) { + struct yahoo_buddy *lastbud = + (struct yahoo_buddy *)y_list_nth(yd-> + buddies, + y_list_length(yd->buddies) - 1)->data; + newbud->group = strdup(lastbud->group); + } else + newbud->group = strdup("Buddies"); yd->buddies = y_list_append(yd->buddies, newbud); break; } } - - g_free(cur_group); /* we could be getting multiple packets here */ - if (last_packet) + if (pkt->hash && !last_packet) return; - YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies); + YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies); - /*** We login at the very end of the packet communication */ + /* Logged in */ if (!yd->logged_in) { - yd->logged_in = TRUE; - if(yd->current_status < 0) + yd->logged_in = 1; + if (yd->current_status < 0) yd->current_status = yd->initial_status; - YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); + YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_OK, NULL); + + /* + yahoo_set_away(yd->client_id, yd->initial_status, NULL, + (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); + + yahoo_get_yab(yd->client_id); + */ } + } -static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_list(struct yahoo_input_data *yid, + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; - if (!yd->logged_in) { - yd->logged_in = TRUE; - if(yd->current_status < 0) - yd->current_status = yd->initial_status; - YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL); - } - + /* we could be getting multiple packets here */ for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - switch(pair->key) { - case 87: /* buddies */ - if(!yd->rawbuddylist) - yd->rawbuddylist = strdup(pair->value); - else { - yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value); - } - break; - - case 88: /* ignore list */ - if(!yd->ignorelist) - yd->ignorelist = strdup("Ignore:"); - yd->ignorelist = y_string_append(yd->ignorelist, pair->value); - break; - - case 89: /* identities */ + switch (pair->key) { + case 89: /* identities */ { - char **identities = y_strsplit(pair->value, ",", -1); - int i; - for(i=0; identities[i]; i++) - yd->identities = y_list_append(yd->identities, + char **identities = + y_strsplit(pair->value, ",", -1); + int i; + for (i = 0; identities[i]; i++) + yd->identities = + y_list_append(yd->identities, strdup(identities[i])); - y_strfreev(identities); + y_strfreev(identities); } - YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities); + YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id, + yd->identities); break; - case 59: /* cookies */ - if(yd->ignorelist) { - yd->ignore = bud_str2list(yd->ignorelist); - FREE(yd->ignorelist); - YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore); - } - if(yd->rawbuddylist) { - yd->buddies = bud_str2list(yd->rawbuddylist); - FREE(yd->rawbuddylist); - YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies); - } - - if(pair->value[0]=='Y') { + case 59: /* cookies */ + if (pair->value[0] == 'Y') { FREE(yd->cookie_y); FREE(yd->login_cookie); yd->cookie_y = getcookie(pair->value); yd->login_cookie = getlcookie(yd->cookie_y); - } else if(pair->value[0]=='T') { + } else if (pair->value[0] == 'T') { FREE(yd->cookie_t); yd->cookie_t = getcookie(pair->value); - } else if(pair->value[0]=='C') { + } else if (pair->value[0] == 'C') { FREE(yd->cookie_c); yd->cookie_c = getcookie(pair->value); - } - - if(yd->cookie_y && yd->cookie_t) - YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id); + } break; - case 3: /* my id */ - case 90: /* 1 */ - case 100: /* 0 */ - case 101: /* NULL */ - case 102: /* NULL */ - case 93: /* 86400/1440 */ + case 3: /* my id */ + case 90: /* 1 */ + case 100: /* 0 */ + case 101: /* NULL */ + case 102: /* NULL */ + case 93: /* 86400/1440 */ break; } } + + if (yd->cookie_y && yd->cookie_t) /* We don't get cookie_c anymore */ + YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id); } static void yahoo_process_verify(struct yahoo_input_data *yid, struct yahoo_packet *pkt) diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h index 3507e13a..f05acb3c 100644 --- a/protocols/yahoo/yahoo2_types.h +++ b/protocols/yahoo/yahoo2_types.h @@ -195,6 +195,8 @@ struct yahoo_data { char *ignorelist; void *server_settings; + + struct yahoo_process_status_entry *half_user; }; struct yab { @@ -260,6 +262,27 @@ struct yahoo_chat_member { char *location; }; +struct yahoo_process_status_entry { + 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 */ +}; + #ifdef __cplusplus } #endif diff --git a/root_commands.c b/root_commands.c index 5de616fb..b3432b9b 100644 --- a/root_commands.c +++ b/root_commands.c @@ -143,6 +143,12 @@ static void cmd_identify( irc_t *irc, char **cmd ) storage_status_t status = storage_load( irc, cmd[1] ); char *account_on[] = { "account", "on", NULL }; + if( strchr( irc->umode, 'R' ) != NULL ) + { + irc_usermsg( irc, "You're already logged in." ); + return; + } + switch (status) { case STORAGE_INVALID_PASSWORD: irc_usermsg( irc, "Incorrect password" ); @@ -1114,79 +1120,6 @@ static void cmd_chat( irc_t *irc, char **cmd ) { irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] ); } - - - -#if 0 - account_t *a; - struct im_connection *ic; - char *chat, *channel, *nick = NULL, *password = NULL; - struct groupchat *c; - - if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return; - } - else if( !( a->ic && ( a->ic->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; - } - ic = a->ic; - - chat = cmd[2]; - if( cmd[3] ) - { - if( strchr( CTYPES, cmd[3][0] ) == NULL ) - channel = g_strdup_printf( "&%s", cmd[3] ); - else - channel = g_strdup( cmd[3] ); - } - else - { - char *s; - - channel = g_strdup_printf( "&%s", chat ); - if( ( s = strchr( channel, '@' ) ) ) - *s = 0; - } - if( cmd[3] && cmd[4] ) - nick = cmd[4]; - else - nick = irc->nick; - if( cmd[3] && cmd[4] && cmd[5] ) - password = cmd[5]; - - if( !nick_ok( channel + 1 ) ) - { - 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 ); - c->channel = channel; - } - else - { - irc_usermsg( irc, "Tried to join chat, not sure if this was successful" ); - g_free( channel ); - } -#endif } const command_t commands[] = { @@ -24,11 +24,15 @@ */ #include "bitlbee.h" + +#include "arc.h" +#include "base64.h" #include "commands.h" -#include "crypting.h" #include "protocols/nogaim.h" #include "help.h" #include "ipc.h" +#include "md5.h" +#include "misc.h" #include <signal.h> #include <unistd.h> #include <sys/time.h> @@ -39,12 +43,17 @@ global_t global; /* Against global namespace pollution */ static void sighandler( int signal ); +static int crypt_main( int argc, char *argv[] ); + int main( int argc, char *argv[] ) { int i = 0; char *old_cwd = NULL; struct sigaction sig, old; + if( argc > 1 && strcmp( argv[1], "-x" ) == 0 ) + return crypt_main( argc, argv ); + log_init(); global.conf_file = g_strdup( CONF_FILE_DEF ); @@ -159,6 +168,64 @@ int main( int argc, char *argv[] ) return( 0 ); } +static int crypt_main( int argc, char *argv[] ) +{ + int pass_len; + unsigned char *pass_cr, *pass_cl; + + if( argc < 4 || ( strcmp( argv[2], "hash" ) != 0 && + strcmp( argv[2], "unhash" ) != 0 && argc < 5 ) ) + { + printf( "Supported:\n" + " %s -x enc <key> <cleartext password>\n" + " %s -x dec <key> <encrypted password>\n" + " %s -x hash <cleartext password>\n" + " %s -x unhash <hashed password>\n" + " %s -x chkhash <hashed password> <cleartext password>\n", + argv[0], argv[0], argv[0], argv[0], argv[0] ); + } + else if( strcmp( argv[2], "enc" ) == 0 ) + { + pass_len = arc_encode( argv[4], strlen( argv[4] ), (unsigned char**) &pass_cr, argv[3], 12 ); + printf( "%s\n", base64_encode( pass_cr, pass_len ) ); + } + else if( strcmp( argv[2], "dec" ) == 0 ) + { + pass_len = base64_decode( argv[4], (unsigned char**) &pass_cr ); + arc_decode( pass_cr, pass_len, (char**) &pass_cl, argv[3] ); + printf( "%s\n", pass_cl ); + } + else if( strcmp( argv[2], "hash" ) == 0 ) + { + md5_byte_t pass_md5[21]; + md5_state_t md5_state; + + random_bytes( pass_md5 + 16, 5 ); + md5_init( &md5_state ); + md5_append( &md5_state, (md5_byte_t*) argv[3], strlen( argv[3] ) ); + md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ + md5_finish( &md5_state, pass_md5 ); + + printf( "%s\n", base64_encode( pass_md5, 21 ) ); + } + else if( strcmp( argv[2], "unhash" ) == 0 ) + { + printf( "Hash %s submitted to a massive Beowulf cluster of\n" + "overclocked 486s. Expect your answer next year somewhere around this time. :-)\n", argv[3] ); + } + else if( strcmp( argv[2], "chkhash" ) == 0 ) + { + char *hash = strncmp( argv[3], "md5:", 4 ) == 0 ? argv[3] + 4 : argv[3]; + int st = md5_verify_password( argv[4], hash ); + + printf( "Hash %s given password.\n", st == 0 ? "matches" : "does not match" ); + + return st; + } + + return 0; +} + static void sighandler( int signal ) { /* FIXME: Calling log_message() here is not a very good idea! */ @@ -214,5 +281,3 @@ double gettime() gettimeofday( time, 0 ); return( (double) time->tv_sec + (double) time->tv_usec / 1000000 ); } - - |