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 );  } - - | 
