diff options
| author | Sven Moritz Hallberg <pesco@khjk.org> | 2009-03-12 20:10:06 +0100 | 
|---|---|---|
| committer | Sven Moritz Hallberg <pesco@khjk.org> | 2009-03-12 20:10:06 +0100 | 
| commit | 823de9d44f262ea2364ac8ec6a1e18e0f7dab658 (patch) | |
| tree | bfe64e4fafbcd13aaef6a436cab6ad91619e2821 | |
| parent | 9b55485a6f9d72334b372e6fb6b60bbde943170d (diff) | |
commit updates by ashish shukla <wahjava@gmail.com>
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | account.c | 123 | ||||
| -rw-r--r-- | account.h | 9 | ||||
| -rw-r--r-- | bitlbee.h | 5 | ||||
| -rw-r--r-- | conf.c | 7 | ||||
| -rwxr-xr-x | configure | 2 | ||||
| -rw-r--r-- | doc/CHANGES | 21 | ||||
| -rw-r--r-- | doc/user-guide/commands.xml | 10 | ||||
| -rw-r--r-- | ipc.c | 35 | ||||
| -rw-r--r-- | ipc.h | 3 | ||||
| -rw-r--r-- | irc.c | 79 | ||||
| -rw-r--r-- | irc_commands.c | 1 | ||||
| -rw-r--r-- | lib/ssl_bogus.c | 5 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 2 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 4 | ||||
| -rw-r--r-- | protocols/msn/msn.c | 61 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 6 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 23 | ||||
| -rw-r--r-- | protocols/msn/sb.c | 42 | ||||
| -rw-r--r-- | protocols/nogaim.c | 10 | ||||
| -rw-r--r-- | protocols/yahoo/libyahoo2.c | 2 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo.c | 3 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo_httplib.c | 2 | ||||
| -rw-r--r-- | root_commands.c | 91 | ||||
| -rw-r--r-- | set.c | 55 | ||||
| -rw-r--r-- | set.h | 10 | ||||
| -rw-r--r-- | sock.h | 8 | ||||
| -rw-r--r-- | storage.c | 37 | ||||
| -rw-r--r-- | storage.h | 8 | ||||
| -rw-r--r-- | storage_text.c | 21 | ||||
| -rw-r--r-- | storage_xml.c | 26 | ||||
| -rw-r--r-- | unix.c | 16 | 
32 files changed, 445 insertions, 284 deletions
| @@ -106,7 +106,7 @@ tar:  	fakeroot debian/rules clean || make distclean  	x=$$(basename $$(pwd)); \  	cd ..; \ -	tar czf $$x.tar.gz --exclude=debian --exclude=.bzr $$x +	tar czf $$x.tar.gz --exclude=debian --exclude=.bzr* $$x  $(subdirs):  	@$(MAKE) -C $@ $(MAKECMDGOALS) @@ -54,7 +54,7 @@ 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, "password", NULL, set_eval_account, a ); -	s->flags |= ACC_SET_NOSAVE; +	s->flags |= ACC_SET_NOSAVE | SET_NULL_OK;  	s = set_add( &a->set, "username", NULL, set_eval_account, a );  	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; @@ -76,9 +76,23 @@ char *set_eval_account( set_t *set, char *value )  	/* Double-check: We refuse to edit on-line accounts. */  	if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic ) -		return NULL; +		return SET_INVALID; -	if( strcmp( set->key, "username" ) == 0 ) +	if( strcmp( set->key, "server" ) == 0 ) +	{ +		g_free( acc->server ); +		if( value && *value ) +		{ +			acc->server = g_strdup( value ); +			return value; +		} +		else +		{ +			acc->server = g_strdup( set->def ); +			return g_strdup( set->def ); +		} +	} +	else if( strcmp( set->key, "username" ) == 0 )  	{  		g_free( acc->user );  		acc->user = g_strdup( value ); @@ -86,34 +100,29 @@ char *set_eval_account( set_t *set, char *value )  	}  	else if( strcmp( set->key, "password" ) == 0 )  	{ -		g_free( acc->pass ); -		acc->pass = g_strdup( value ); -		return NULL;	/* password shouldn't be visible in plaintext! */ -	} -	else if( strcmp( set->key, "server" ) == 0 ) -	{ -		g_free( acc->server ); -		if( *value ) +		if( value )  		{ -			acc->server = g_strdup( value ); -			return value; +			g_free( acc->pass ); +			acc->pass = g_strdup( value ); +			return NULL;	/* password shouldn't be visible in plaintext! */  		}  		else  		{ -			acc->server = NULL; -			return g_strdup( set->def ); +			/* NULL can (should) be stored in the set_t +			   variable, but is otherwise not correct. */ +			return SET_INVALID;  		}  	}  	else if( strcmp( set->key, "auto_connect" ) == 0 )  	{  		if( !is_bool( value ) ) -			return NULL; +			return SET_INVALID;  		acc->auto_connect = bool2int( value );  		return value;  	} -	return NULL; +	return SET_INVALID;  }  account_t *account_get( irc_t *irc, char *id ) @@ -233,3 +242,83 @@ void account_off( irc_t *irc, account_t *a )  		cancel_auto_reconnect( a );  	}  } + +struct account_reconnect_delay +{ +	int start; +	char op; +	int step; +	int max; +}; + +int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p ) +{ +	memset( p, 0, sizeof( *p ) ); +	/* A whole day seems like a sane "maximum maximum". */ +	p->max = 86400; +	 +	/* Format: /[0-9]+([*+][0-9]+(<[0-9+]))/ */ +	while( *value && isdigit( *value ) ) +		p->start = p->start * 10 + *value++ - '0'; +	 +	/* Sure, call me evil for implementing my own fscanf here, but it's +	   dead simple and I immediately know where to continue parsing. */ +	 +	if( *value == 0 ) +		/* If the string ends now, the delay is constant. */ +		return 1; +	else if( *value != '+' && *value != '*' ) +		/* Otherwise allow either a + or a * */ +		return 0; +	 +	p->op = *value++; +	 +	/* + or * the delay by this number every time. */ +	while( *value && isdigit( *value ) ) +		p->step = p->step * 10 + *value++ - '0'; +	 +	if( *value == 0 ) +		/* Use the default maximum (one day). */ +		return 1; +	else if( *value != '<' ) +		return 0; +	 +	p->max = 0; +	value ++; +	while( *value && isdigit( *value ) ) +		p->max = p->max * 10 + *value++ - '0'; +	 +	return p->max > 0; +} + +char *set_eval_account_reconnect_delay( set_t *set, char *value ) +{ +	struct account_reconnect_delay p; +	 +	return account_reconnect_delay_parse( value, &p ) ? value : SET_INVALID; +} + +int account_reconnect_delay( account_t *a ) +{ +	char *setting = set_getstr( &a->irc->set, "auto_reconnect_delay" ); +	struct account_reconnect_delay p; +	 +	if( account_reconnect_delay_parse( setting, &p ) ) +	{ +		if( a->auto_reconnect_delay == 0 ) +			a->auto_reconnect_delay = p.start; +		else if( p.op == '+' ) +			a->auto_reconnect_delay += p.step; +		else if( p.op == '*' ) +			a->auto_reconnect_delay *= p.step; +		 +		if( a->auto_reconnect_delay > p.max ) +			a->auto_reconnect_delay = p.max; +	} +	else +	{ +		a->auto_reconnect_delay = 0; +	} +	 +	return a->auto_reconnect_delay; +} @@ -34,6 +34,7 @@ typedef struct account  	char *server;  	int auto_connect; +	int auto_reconnect_delay;  	int reconnect;  	set_t *set; @@ -51,9 +52,11 @@ void account_on( irc_t *irc, account_t *a );  void account_off( irc_t *irc, account_t *a );  char *set_eval_account( set_t *set, char *value ); +char *set_eval_account_reconnect_delay( set_t *set, char *value ); +int account_reconnect_delay( account_t *a ); -#define ACC_SET_NOSAVE		1 -#define ACC_SET_OFFLINE_ONLY	2 -#define ACC_SET_ONLINE_ONLY	4 +#define ACC_SET_NOSAVE		0x01 +#define ACC_SET_OFFLINE_ONLY	0x02 +#define ACC_SET_ONLINE_ONLY	0x04  #endif @@ -31,8 +31,11 @@  /* Depend on Windows 2000 for now since we need getaddrinfo() */  #define _WIN32_WINNT 0x0501 +/* Depend on Windows 2000 for now since we need getaddrinfo() */ +#define _WIN32_WINNT 0x0501 +  #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "1.2.1" +#define BITLBEE_VERSION "1.2.3"  #define VERSION BITLBEE_VERSION  #define MAX_STRING 511 @@ -146,6 +146,13 @@ conf_t *conf_load( int argc, char *argv[] )  			        "  -h  Show this help page.\n" );  			return NULL;  		} +		else if( opt == 'R' ) +		{ +			/* Backward compatibility; older BitlBees passed this +			   info using a command-line flag. Allow people to +			   upgrade from such a version for now. */ +			setenv( "_BITLBEE_RESTART_STATE", optarg, 0 ); +		}  		else if( opt == 'u' )  		{  			g_free( conf->user ); @@ -71,7 +71,7 @@ Option		Description				Default  --strip=0/1	Disable/enable binary stripping		$strip  --gcov=0/1	Disable/enable test coverage reporting	$gcov  --plugins=0/1	Disable/enable plugins support		$plugins ---otr=0/1/auto	Disable/enable OTR encryption support	$otr +--otr=0/1	Disable/enable OTR encryption support	$otr  --events=...	Event handler (glib, libevent)		$events  --ssl=...	SSL library to use (gnutls, nss, openssl, bogus, auto) diff --git a/doc/CHANGES b/doc/CHANGES index ac1f1f02..84dbe162 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -3,6 +3,27 @@ found in the bzr commit logs, for example you can try:  http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on +Version 1.2.3: +- Fixed one more flaw similar to the previous hijacking bug, caused by incon- +  sistent handling of the USTATUS_IDENTIFIED state. All code touching these +  variables was reviewed and should be correct now. + +Finished 7 Sep 2008  + +Version 1.2.2: +- Security bugfix: It was possible to hijack accounts (without gaining access +  to the old account, it's simply an overwrite) +- Some more stability improvements. +- Fixed bug where people with non-lowercase nicks couldn't drop their account. +- Easier upgrades of non-forking daemon mode servers (using the DEAF +  command). +- Can be cross-compiled for Win32 now! (No support for SSL yet though, which +  makes it less useful for now.) +- Exponential backoff on auto-reconnect. +- Changing passwords gives less confusing feedback ("password is empty") now. + +Finished 26 Aug 2008 +  Version 1.2.1:  - Fixed proxy support.  - Fixed stalling issues while connecting to Jabber when using the OpenSSL diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index f0653232..3a7bd5a8 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -469,12 +469,16 @@  		</description>  	</bitlbee-setting> -	<bitlbee-setting name="auto_reconnect_delay" type="integer" scope="global"> -		<default>300</default> +	<bitlbee-setting name="auto_reconnect_delay" type="string" scope="global"> +		<default>5*3<900</default>  		<description>  			<para> -				Tell BitlBee after how many seconds it should attempt to bring an IM-connection back up after a crash. It's not a good idea to set this value very low, it will cause too much useless traffic when an IM-server is down for a few hours. +				Tell BitlBee after how many seconds it should attempt to bring a broken IM-connection back up. +			</para> + +			<para> +				This can be one integer, for a constant delay. One can also set it to something like "10*10", which means wait for ten seconds on the first reconnect, multiply it by ten on every failure. Once successfully connected, this delay is re-set to the initial value. With < you can give a maximum delay.  			</para>  			<para> @@ -32,6 +32,7 @@  #endif  GSList *child_list = NULL; +static char *statefile = NULL;  static void ipc_master_cmd_client( irc_t *data, char **cmd )  { @@ -61,25 +62,6 @@ static void ipc_master_cmd_die( irc_t *data, char **cmd )  	bitlbee_shutdown( NULL, -1, 0 );  } -static void ipc_master_cmd_deaf( irc_t *data, char **cmd ) -{ -	if( global.conf->runmode == RUNMODE_DAEMON ) -	{ -		b_event_remove( global.listen_watch_source_id ); -		close( global.listen_socket ); -		 -		global.listen_socket = global.listen_watch_source_id = -1; -	 -		ipc_to_children_str( "OPERMSG :Closed listening socket, waiting " -		                     "for all users to disconnect." ); -	} -	else -	{ -		ipc_to_children_str( "OPERMSG :The DEAF command only works in " -		                     "normal daemon mode. Try DIE instead." ); -	} -} -  void ipc_master_cmd_rehash( irc_t *data, char **cmd )  {  	runmode_t oldmode; @@ -115,7 +97,6 @@ static const command_t ipc_master_commands[] = {  	{ "client",     3, ipc_master_cmd_client,     0 },  	{ "hello",      0, ipc_master_cmd_client,     0 },  	{ "die",        0, ipc_master_cmd_die,        0 }, -	{ "deaf",       0, ipc_master_cmd_deaf,       0 },  	{ "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },  	{ "wall",       1, NULL,                      IPC_CMD_TO_CHILDREN },  	{ "opermsg",    1, NULL,                      IPC_CMD_TO_CHILDREN }, @@ -459,7 +440,6 @@ void ipc_child_disable()  	global.listen_socket = -1;  } -#ifndef _WIN32  char *ipc_master_save_state()  {  	char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" ); @@ -500,6 +480,11 @@ char *ipc_master_save_state()  	}  } +void ipc_master_set_statefile( char *fn ) +{ +	statefile = g_strdup( fn ); +} +  static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )  { @@ -520,6 +505,7 @@ static gboolean new_ipc_client( gpointer data, gint serversock, b_input_conditio  	return TRUE;  } +#ifndef _WIN32  int ipc_master_listen_socket()  {  	struct sockaddr_un un_addr; @@ -556,14 +542,10 @@ int ipc_master_listen_socket()  	return 1;  }  #else -int ipc_master_listen_socket() -{  	/* FIXME: Open named pipe \\.\BITLBEE */ -	return 0; -}  #endif -int ipc_master_load_state( char *statefile ) +int ipc_master_load_state()  {  	struct bitlbee_child *child;  	FILE *fp; @@ -571,7 +553,6 @@ int ipc_master_load_state( char *statefile )  	if( statefile == NULL )  		return 0; -	  	fp = fopen( statefile, "r" );  	unlink( statefile );	/* Why do it later? :-) */  	if( fp == NULL ) @@ -57,7 +57,8 @@ void ipc_to_children_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 );  void ipc_master_cmd_rehash( irc_t *data, char **cmd );  char *ipc_master_save_state(); -int ipc_master_load_state( char *statefile ); +void ipc_master_set_statefile( char *fn ); +int ipc_master_load_state();  int ipc_master_listen_socket();  extern GSList *child_list; @@ -32,17 +32,23 @@  #include <sys/wait.h>  static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond ); -static void irc_welcome( irc_t *irc ); +static void irc_welcome( irc_t* irc );  GSList *irc_connection_list = NULL; -static char *passchange( set_t *set, char *value ) +static char *set_eval_password( set_t *set, char *value )  {  	irc_t *irc = set->data; -	irc_setpass( irc, value ); -	irc_usermsg( irc, "Password successfully changed" ); -	return NULL; +	if( irc->status & USTATUS_IDENTIFIED && value ) +	{ +		irc_setpass( irc, value ); +		return NULL; +	} +	else +	{ +		return SET_INVALID; +	}  }  static char *set_eval_charset( set_t *set, char *value ) @@ -79,6 +85,7 @@ irc_t *irc_new( int fd )  	irc_t *irc;  	struct sockaddr_storage sock;  	socklen_t socklen = sizeof( sock ); +	set_t *s;  	irc = g_new0( irc_t, 1 ); @@ -138,38 +145,38 @@ irc_t *irc_new( int fd )  	irc_connection_list = g_slist_append( irc_connection_list, irc ); -	set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc ); -	set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc ); -	set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc ); -	set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc ); -	set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); -	set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); -	set_add( &irc->set, "color_encrypted", "true", set_eval_bool, irc ); -	set_add( &irc->set, "debug", "false", set_eval_bool, irc ); -	set_add( &irc->set, "default_target", "root", NULL, irc ); -	set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); -	set_add( &irc->set, "handle_unknown", "root", NULL, irc ); -	set_add( &irc->set, "halfop_buddies", "encrypted", set_eval_halfop_buddies, irc ); -	set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); -	set_add( &irc->set, "op_buddies", "trusted", set_eval_op_buddies, irc ); -	set_add( &irc->set, "op_root", "true", set_eval_op_root, irc ); -	set_add( &irc->set, "op_user", "true", set_eval_op_user, irc ); -	set_add( &irc->set, "otr_policy", "opportunistic", set_eval_otr_policy, irc ); -	set_add( &irc->set, "password", NULL, passchange, irc ); -	set_add( &irc->set, "private", "true", set_eval_bool, irc ); -	set_add( &irc->set, "query_order", "lifo", NULL, irc ); -	set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); -	set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); -	set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); -	set_add( &irc->set, "strip_html", "true", NULL, irc ); -	set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); -	set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); -	set_add( &irc->set, "voice_buddies", "notaway",  set_eval_voice_buddies, 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_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 ); +	s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc ); +	s = set_add( &irc->set, "color_encrypted", "true", set_eval_bool, irc ); +	s = set_add( &irc->set, "debug", "false", set_eval_bool, irc ); +	s = set_add( &irc->set, "default_target", "root", NULL, irc ); +	s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); +	s = set_add( &irc->set, "handle_unknown", "root", NULL, irc ); +	s = set_add( &irc->set, "halfop_buddies", "encrypted", set_eval_halfop_buddies, irc ); +	s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); +	s = set_add( &irc->set, "op_buddies", "trusted", set_eval_op_buddies, irc ); +	s = set_add( &irc->set, "op_root", "true", set_eval_op_root, irc ); +	s = set_add( &irc->set, "otr_policy", "oppurtunistic", set_eval_otr_policy, irc ); +	s = set_add( &irc->set, "password", NULL, set_eval_password, irc ); +	s->flags |= SET_NULL_OK; +	s = set_add( &irc->set, "private", "true", set_eval_bool, irc ); +	s = set_add( &irc->set, "query_order", "lifo", NULL, irc ); +	s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc ); +	s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); +	s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc ); +	s = set_add( &irc->set, "strip_html", "true", NULL, irc ); +	s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc ); +	s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); +	s = set_add( &irc->set, "voice_buddies", "notaway", set_eval_voice_buddies, irc);  	conf_loaddefaults( irc );  	irc->otr = otr_new(); -	 +  	/* Evaluator sets the iconv/oconv structures. */  	set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) ); @@ -240,7 +247,7 @@ void irc_free( irc_t * irc )  	log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );  	if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )  -		if( storage_save( irc, TRUE ) != STORAGE_OK ) +		if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )  			irc_usermsg( irc, "Error while saving settings!" );  	irc_connection_list = g_slist_remove( irc_connection_list, irc ); @@ -321,11 +328,11 @@ void irc_free( irc_t * irc )  	g_free( irc->channel );  	g_free( irc->last_target ); -	 +  	otr_free(irc->otr);  	g_free( irc ); -	 +  	if( global.conf->runmode == RUNMODE_INETD ||  	    global.conf->runmode == RUNMODE_FORKDAEMON ||  	    ( global.conf->runmode == RUNMODE_DAEMON && diff --git a/irc_commands.c b/irc_commands.c index fb2bc7cf..6a47007a 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -625,7 +625,6 @@ static const command_t irc_commands[] = {  	{ "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },  	{ "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },  	{ "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER }, -	{ "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },  	{ "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },  	{ "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },  	{ "rehash",      0, irc_cmd_rehash,      IRC_CMD_OPER_ONLY }, diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c index 6eea18c7..22226592 100644 --- a/lib/ssl_bogus.c +++ b/lib/ssl_bogus.c @@ -69,3 +69,8 @@ int ssl_pending( void *conn )  {  	return 0;  } + +int ssl_pending( void *conn ) +{ +	return 0; +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 5fb2c4fc..518c9506 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -69,7 +69,7 @@ static void jabber_init( account_t *acc )  	s = set_add( &acc->set, "resource_select", "priority", NULL, acc );  	s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); -	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; +	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK;  	s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 1bee5009..19a73b6a 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -36,10 +36,10 @@ char *set_eval_priority( set_t *set, char *value )  	{  		/* Priority is a signed 8-bit integer, according to RFC 3921. */  		if( i < -128 || i > 127 ) -			return NULL; +			return SET_INVALID;  	}  	else -		return NULL; +		return SET_INVALID;  	/* Only run this stuff if the account is online ATM,  	   and if the setting seems to be acceptable. */ diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 335ae894..05eae541 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -112,7 +112,6 @@ static void msn_logout( struct im_connection *ic )  static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away )  {  	struct msn_switchboard *sb; -	struct msn_data *md = ic->proto_data;  	if( ( sb = msn_sb_by_handle( ic, who ) ) )  	{ @@ -121,47 +120,13 @@ static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, in  	else  	{  		struct msn_message *m; -		char buf[1024];  		/* Create a message. We have to arrange a usable switchboard, and send the message later. */  		m = g_new0( struct msn_message, 1 );  		m->who = g_strdup( who );  		m->text = g_strdup( message ); -		/* FIXME: *CHECK* the reliability of using spare sb's! */ -		if( ( sb = msn_sb_spare( ic ) ) ) -		{ -			debug( "Trying to use a spare switchboard to message %s", who ); -			 -			sb->who = g_strdup( who ); -			g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); -			if( msn_sb_write( sb, buf, strlen( buf ) ) ) -			{ -				/* He/She should join the switchboard soon, let's queue the message. */ -				sb->msgq = g_slist_append( sb->msgq, m ); -				return( 1 ); -			} -		} -		 -		debug( "Creating a new switchboard to message %s", who ); -		 -		/* If we reach this line, there was no spare switchboard, so let's make one. */ -		g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); -		if( !msn_write( ic, buf, strlen( buf ) ) ) -		{ -			g_free( m->who ); -			g_free( m->text ); -			g_free( m ); -			 -			return( 0 ); -		} -		 -		/* And queue the message to md. We'll pick it up when the switchboard comes up. */ -		md->msgq = g_slist_append( md->msgq, m ); -		 -		/* FIXME: If the switchboard creation fails, the message will not be sent. */ -		 -		return( 1 ); +		return msn_sb_write_msg( ic, m );  	}  	return( 0 ); @@ -251,8 +216,6 @@ static void msn_chat_leave( struct groupchat *c )  static struct groupchat *msn_chat_with( struct im_connection *ic, char *who )  {  	struct msn_switchboard *sb; -	struct msn_data *md = ic->proto_data; -	char buf[1024];  	if( ( sb = msn_sb_by_handle( ic, who ) ) )  	{ @@ -263,31 +226,13 @@ static struct groupchat *msn_chat_with( struct im_connection *ic, char *who )  	{  		struct msn_message *m; -		if( ( sb = msn_sb_spare( ic ) ) ) -		{ -			debug( "Trying to reuse an existing switchboard as a groupchat with %s", who ); -			g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); -			if( msn_sb_write( sb, buf, strlen( buf ) ) ) -				return msn_sb_to_chat( sb ); -		} -		 -		/* If the stuff above failed for some reason: */ -		debug( "Creating a new switchboard to groupchat with %s", who ); -		 -		/* Request a new switchboard. */ -		g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); -		if( !msn_write( ic, buf, strlen( buf ) ) ) -			return( 0 ); -		  		/* Create a magic message. This is quite hackish, but who cares? :-P */  		m = g_new0( struct msn_message, 1 );  		m->who = g_strdup( who );  		m->text = g_strdup( GROUPCHAT_SWITCHBOARD_MESSAGE ); -		/* Queue the magic message and cross your fingers. */ -		md->msgq = g_slist_append( md->msgq, m ); -		 -		/* FIXME: Can I try to return something here already? */ +		msn_sb_write_msg( ic, m ); +  		return NULL;  	} diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 63759303..7c849acf 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -23,6 +23,9 @@    Suite 330, Boston, MA  02111-1307  USA  */ +#ifndef _MSN_H +#define _MSN_H +  /* Some hackish magicstrings to make special-purpose messages/switchboards.   */  #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r" @@ -175,3 +178,6 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text );  struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb );  void msn_sb_destroy( struct msn_switchboard *sb );  gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); +int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); + +#endif //_MSN_H diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index fe48f96d..ffaa90a7 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -277,25 +277,11 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  	{  		if( num_parts == 5 )  		{ -			int i, groupcount; -			 -			groupcount = atoi( cmd[4] ); -			if( groupcount > 0 ) -			{ -				/* valgrind says this is leaking memory, I'm guessing -				   that this happens during server redirects. */ -				if( md->grouplist ) -				{ -					for( i = 0; i < md->groupcount; i ++ ) -						g_free( md->grouplist[i] ); -					g_free( md->grouplist ); -				} -				 -				md->groupcount = groupcount; +			md->buddycount = atoi( cmd[3] ); +			md->groupcount = atoi( cmd[4] ); +			if( md->groupcount > 0 )  				md->grouplist = g_new0( char *, md->groupcount ); -			} -			md->buddycount = atoi( cmd[3] );  			if( !*cmd[3] || md->buddycount == 0 )  				msn_logged_in( ic );  		} @@ -678,9 +664,6 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int  				{  					imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );  				} -				 -				g_free( inbox ); -				g_free( folders );  			}  			else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )  			{ diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 18c41ef5..e9526234 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -47,6 +47,48 @@ int msn_sb_write( struct msn_switchboard *sb, char *s, int len )  	return( 1 );  } +int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ) +{ +	struct msn_data *md = ic->proto_data; +	struct msn_switchboard *sb; +	char buf[1024]; + +	/* FIXME: *CHECK* the reliability of using spare sb's! */ +	if( ( sb = msn_sb_spare( ic ) ) ) +	{ +		debug( "Trying to use a spare switchboard to message %s", m->who ); +		 +		sb->who = g_strdup( m->who ); +		g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, m->who ); +		if( msn_sb_write( sb, buf, strlen( buf ) ) ) +		{ +			/* He/She should join the switchboard soon, let's queue the message. */ +			sb->msgq = g_slist_append( sb->msgq, m ); +			return( 1 ); +		} +	} +	 +	debug( "Creating a new switchboard to message %s", m->who ); +	 +	/* If we reach this line, there was no spare switchboard, so let's make one. */ +	g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId ); +	if( !msn_write( ic, buf, strlen( buf ) ) ) +	{ +		g_free( m->who ); +		g_free( m->text ); +		g_free( m ); +		 +		return( 0 ); +	} +	 +	/* And queue the message to md. We'll pick it up when the switchboard comes up. */ +	md->msgq = g_slist_append( md->msgq, m ); +	 +	/* FIXME: If the switchboard creation fails, the message will not be sent. */ +	 +	return( 1 ); +} +  struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session )  {  	struct msn_data *md = ic->proto_data; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 95d950ca..e6a89dfd 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -266,6 +266,10 @@ void imcb_connected( struct im_connection *ic )  	/* Also necessary when we're not away, at least for some of the  	   protocols. */  	imc_set_away( ic, u->away ); +	 +	/* Apparently we're connected successfully, so reset the +	   exponential backoff timer. */ +	ic->acc->auto_reconnect_delay = 0;  }  gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) @@ -289,6 +293,7 @@ void imc_logout( struct im_connection *ic, int allow_reconnect )  	irc_t *irc = ic->irc;  	user_t *t, *u;  	account_t *a; +	int delay;  	/* Nested calls might happen sometimes, this is probably the best  	   place to catch them. */ @@ -328,10 +333,9 @@ void imc_logout( struct im_connection *ic, int allow_reconnect )  		/* Uhm... This is very sick. */  	}  	else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) && -	         set_getbool( &a->set, "auto_reconnect" ) ) +	         set_getbool( &a->set, "auto_reconnect" ) && +	         ( delay = account_reconnect_delay( a ) ) > 0 )  	{ -		int delay = set_getint( &irc->set, "auto_reconnect_delay" ); -		  		imcb_log( ic, "Reconnecting in %d seconds..", delay );  		a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a );  	} diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index a61955c4..897ba27b 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -68,6 +68,8 @@ char *strchr (), *strrchr ();  #ifdef __MINGW32__  # include <winsock2.h> +# define write(a,b,c) send(a,b,c,0) +# define read(a,b,c)  recv(a,b,c,0)  #endif  #include <stdlib.h> diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 0db6e27a..8feb6639 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -665,9 +665,6 @@ void ext_yahoo_error( int id, const char *err, int fatal, int num )  	struct im_connection *ic = byahoo_get_ic_by_id( id );  	imcb_error( ic, "%s", err ); -	 -	if( fatal ) -		imc_logout( ic, TRUE );  }  /* TODO: Clear up the mess of inp and d structures */ diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c index 1b084992..dbbe2a84 100644 --- a/protocols/yahoo/yahoo_httplib.c +++ b/protocols/yahoo/yahoo_httplib.c @@ -50,6 +50,8 @@ char *strchr (), *strrchr ();  #include "yahoo_debug.h"  #ifdef __MINGW32__  # include <winsock2.h> +# define write(a,b,c) send(a,b,c,0) +# define read(a,b,c)  recv(a,b,c,0)  # define snprintf _snprintf  #endif diff --git a/root_commands.c b/root_commands.c index 2f00eca8..ffa163bb 100644 --- a/root_commands.c +++ b/root_commands.c @@ -131,7 +131,7 @@ static void cmd_account( irc_t *irc, char **cmd );  static void cmd_identify( irc_t *irc, char **cmd )  { -	storage_status_t status = storage_load( irc->nick, cmd[1], irc ); +	storage_status_t status = storage_load( irc, cmd[1] );  	char *account_on[] = { "account", "on", NULL };  	switch (status) { @@ -143,6 +143,8 @@ static void cmd_identify( irc_t *irc, char **cmd )  		break;  	case STORAGE_OK:  		irc_usermsg( irc, "Password accepted, settings and accounts loaded" ); +		irc_setpass( irc, cmd[1] ); +		irc->status |= USTATUS_IDENTIFIED;  		irc_umode_set( irc, "+R", 1 );  		if( set_getbool( &irc->set, "auto_connect" ) )  			cmd_account( irc, account_on ); @@ -162,14 +164,14 @@ static void cmd_register( irc_t *irc, char **cmd )  		return;  	} -	irc_setpass( irc, cmd[1] ); -	switch( storage_save( irc, FALSE )) { +	switch( storage_save( irc, cmd[1], FALSE ) ) {  		case STORAGE_ALREADY_EXISTS:  			irc_usermsg( irc, "Nick is already registered" );  			break;  		case STORAGE_OK:  			irc_usermsg( irc, "Account successfully created" ); +			irc_setpass( irc, cmd[1] );  			irc->status |= USTATUS_IDENTIFIED;  			irc_umode_set( irc, "+R", 1 );  			break; @@ -238,6 +240,16 @@ void cmd_account_del_no( void *data )  	g_free( data );  } +static void cmd_showset( irc_t *irc, set_t **head, char *key ) +{ +	char *val; +	 +	if( ( val = set_getstr( head, key ) ) ) +		irc_usermsg( irc, "%s = `%s'", key, val ); +	else +		irc_usermsg( irc, "%s is empty", key ); +} +  static void cmd_account( irc_t *irc, char **cmd )  {  	account_t *a; @@ -449,6 +461,7 @@ static void cmd_account( irc_t *irc, char **cmd )  		if( cmd[3] && set_name )  		{  			set_t *s = set_find( &a->set, set_name ); +			int st;  			if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY )  			{ @@ -464,27 +477,32 @@ static void cmd_account( irc_t *irc, char **cmd )  			}  			if( g_strncasecmp( cmd[2], "-del", 4 ) == 0 ) -				set_reset( &a->set, set_name ); +				st = set_reset( &a->set, set_name ); +			else +				st = set_setstr( &a->set, set_name, cmd[3] ); +			 +			if( set_getstr( &a->set, set_name ) == NULL ) +			{ +				if( st ) +					irc_usermsg( irc, "Setting changed successfully" ); +				else +					irc_usermsg( irc, "Failed to change setting" ); +			}  			else -				set_setstr( &a->set, set_name, cmd[3] ); +			{ +				cmd_showset( irc, &a->set, set_name ); +			}  		} -		if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ +		else if( set_name )  		{ -			char *s = set_getstr( &a->set, set_name ); -			if( s ) -				irc_usermsg( irc, "%s = `%s'", set_name, s ); -			else -				irc_usermsg( irc, "%s is empty", set_name ); +			cmd_showset( irc, &a->set, set_name );  		}  		else  		{  			set_t *s = a->set;  			while( s )  			{ -				if( s->value || s->def ) -					irc_usermsg( irc, "%s = `%s'", s->key, s->value ? s->value : s->def ); -				else -					irc_usermsg( irc, "%s is empty", s->key ); +				cmd_showset( irc, &s, s->key );  				s = s->next;  			}  		} @@ -614,6 +632,8 @@ static void cmd_rename( irc_t *irc, char **cmd )  			g_free( irc->mynick );  			irc->mynick = g_strdup( cmd[2] ); +			/* If we're called internally (user did "set root_nick"), +			   let's not go O(INF). :-) */  			if( strcmp( cmd[0], "set_rename" ) != 0 )  				set_setstr( &irc->set, "root_nick", cmd[2] );  		} @@ -637,7 +657,7 @@ char *set_eval_root_nick( set_t *set, char *new_nick )  		cmd_rename( irc, cmd );  	} -	return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : NULL; +	return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;  }  static void cmd_remove( irc_t *irc, char **cmd ) @@ -825,23 +845,37 @@ static void cmd_set( irc_t *irc, char **cmd )  	if( cmd[1] && cmd[2] )  	{ +		int st; +		  		if( g_strncasecmp( cmd[1], "-del", 4 ) == 0 )  		{ -			set_reset( &irc->set, cmd[2] ); +			st = set_reset( &irc->set, cmd[2] );  			set_name = cmd[2];  		}  		else  		{ -			set_setstr( &irc->set, cmd[1], cmd[2] ); +			st = set_setstr( &irc->set, cmd[1], cmd[2] ); +		} +		 +		/* Normally we just show the variable's new/unchanged +		   value as feedback to the user, but this has always +		   caused confusion when changing the password. Give +		   other feedback instead: */ +		if( set_getstr( &irc->set, set_name ) == NULL ) +		{ +			if( st ) +				irc_usermsg( irc, "Setting changed successfully" ); +			else +				irc_usermsg( irc, "Failed to change setting" ); +		} +		else +		{ +			cmd_showset( irc, &irc->set, set_name );  		}  	} -	if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */ +	else if( set_name )  	{ -		char *s = set_getstr( &irc->set, set_name ); - 		if( s ) -			irc_usermsg( irc, "%s = `%s'", set_name, s ); -		else -			irc_usermsg( irc, "%s is empty", set_name ); +		cmd_showset( irc, &irc->set, set_name );  		if( strchr( set_name, '/' ) )  			irc_usermsg( irc, "Warning: / found in setting name, you're probably looking for the `account set' command." ); @@ -851,10 +885,7 @@ static void cmd_set( irc_t *irc, char **cmd )  		set_t *s = irc->set;  		while( s )  		{ -			if( s->value || s->def ) -				irc_usermsg( irc, "%s = `%s'", s->key, s->value ? s->value : s->def ); -			else -				irc_usermsg( irc, "%s is empty", s->key ); +			cmd_showset( irc, &s, s->key );  			s = s->next;  		}  	} @@ -862,7 +893,9 @@ static void cmd_set( irc_t *irc, char **cmd )  static void cmd_save( irc_t *irc, char **cmd )  { -	if( storage_save( irc, TRUE ) == STORAGE_OK ) +	if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) +		irc_usermsg( irc, "Please create an account first" ); +	else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )  		irc_usermsg( irc, "Configuration saved" );  	else  		irc_usermsg( irc, "Configuration could not be saved!" ); @@ -25,6 +25,9 @@  #define BITLBEE_CORE  #include "bitlbee.h" +/* Used to use NULL for this, but NULL is actually a "valid" value. */ +char *SET_INVALID = "nee"; +  set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data )  {  	set_t *s = set_find( head, key ); @@ -113,9 +116,20 @@ int set_setstr( set_t **head, char *key, char *value )  	char *nv = value;  	if( !s ) +		/* +		Used to do this, but it never really made sense.  		s = set_add( head, key, NULL, NULL, NULL ); +		*/ +		return 0; -	if( s->eval && !( nv = s->eval( s, value ) ) ) +	if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 ) +		return 0; +	 +	/* Call the evaluator. For invalid values, evaluators should now +	   return SET_INVALID, but previously this was NULL. Try to handle +	   that too if NULL is not an allowed value for this setting. */ +	if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID || +	                 ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) )  		return 0;  	if( s->value ) @@ -167,13 +181,15 @@ void set_del( set_t **head, char *key )  	}  } -void set_reset( set_t **head, char *key ) +int set_reset( set_t **head, char *key )  {  	set_t *s;  	s = set_find( head, key );  	if( s ) -		set_setstr( head, key, s->def ); +		return set_setstr( head, key, s->def ); +	 +	return 0;  }  char *set_eval_int( set_t *set, char *value ) @@ -186,14 +202,14 @@ char *set_eval_int( set_t *set, char *value )  	for( ; *s; s ++ )  		if( !isdigit( *s ) ) -			return NULL; +			return SET_INVALID;  	return value;  }  char *set_eval_bool( set_t *set, char *value )  { -	return is_bool( value ) ? value : NULL; +	return is_bool( value ) ? value : SET_INVALID;  }  char *set_eval_to_char( set_t *set, char *value ) @@ -208,25 +224,27 @@ char *set_eval_to_char( set_t *set, char *value )  	return s;  } -char *set_eval_op_root( set_t *set, char *value ) +char* set_eval_op_root( set_t *set, char* value )  {  	irc_t *irc = set->data; -	char *ret = set_eval_bool(set, value); +	char* ret = set_eval_bool(set, value);  	int b = bool2int(ret); -	 +  	irc_write( irc, ":%s!%s@%s MODE %s %s %s", irc->mynick, irc->mynick, irc->myhost, -	                                           irc->channel, b?"+o":"-o", irc->mynick ); +                                               irc->channel, b?"+o":"-o", irc->mynick); +  	return ret;  } -char *set_eval_op_user( set_t *set, char *value ) +char* set_eval_op_user( set_t *set, char* value )  {  	irc_t *irc = set->data; -	char *ret = set_eval_bool(set, value); +	char* ret = set_eval_bool(set, value);  	int b = bool2int(ret); -	 +  	irc_write( irc, ":%s!%s@%s MODE %s %s %s", irc->mynick, irc->mynick, irc->myhost, -	                                           irc->channel, b?"+o":"-o", irc->nick ); +                                               irc->channel, b?"+o":"-o", irc->nick); +  	return ret;  } @@ -249,7 +267,7 @@ char *set_eval_mode_buddies( set_t *set, char *value, char modeflag )  		mode=3;  	else  		return NULL; -	 +  	/* sorry for calling them op/deop - too lazy for search+replace :P */  	op[0]='\0';  	deop[0]='\0'; @@ -334,10 +352,10 @@ char *set_eval_mode_buddies( set_t *set, char *value, char modeflag )  	if(*deop) {  		char *flags = g_strnfill(ndeop, modeflag);  		irc_write( irc, ":%s!%s@%s MODE %s -%s%s", irc->mynick, irc->mynick, irc->myhost, -	                                               irc->channel, flags, deop ); -		g_free(flags); -	} -	 +                                                   irc->channel, flags, deop ); +        g_free(flags); +    } +  	return value;  } @@ -369,3 +387,4 @@ char *set_eval_otr_policy( set_t *set, char *value )  		return value;  	return NULL;  } + @@ -43,6 +43,10 @@ struct set;  typedef char *(*set_eval) ( struct set *set, char *value ); +extern char *SET_INVALID; + +#define SET_NULL_OK        0x0100 +  typedef struct set  {  	void *data;     /* Here you can save a pointer to the @@ -60,8 +64,8 @@ typedef struct set  	int flags;      /* See account.h, for example. set.c doesn't use  	                   this (yet?). */ -	/* Eval: Returns NULL if the value is incorrect or exactly the -	   passed value variable. When returning a corrected value, +	/* Eval: Returns SET_INVALID if the value is incorrect or exactly +	   the passed value variable. When returning a corrected value,  	   set_setstr() should be able to free() the returned string! */  	set_eval eval;  	struct set *next; @@ -87,7 +91,7 @@ G_MODULE_EXPORT int set_getbool( set_t **head, char *key );  int set_setstr( set_t **head, char *key, char *value );  int set_setint( set_t **head, char *key, int value );  void set_del( set_t **head, char *key ); -void set_reset( set_t **head, char *key ); +int set_reset( set_t **head, char *key );  /* Two very useful generic evaluators. */  char *set_eval_int( set_t *set, char *value ); @@ -15,11 +15,17 @@  #endif  #else  # include <winsock2.h> -# include <ws2tcpip.h> +# ifndef _MSC_VER +#  include <ws2tcpip.h> +# endif  # if !defined(BITLBEE_CORE) && defined(_MSC_VER)  #   pragma comment(lib,"bitlbee.lib")  # endif  # include <io.h> +# define read(a,b,c) recv(a,b,c,0) +# define write(a,b,c) send(a,b,c,0) +# define umask _umask +# define mode_t int  # define sock_make_nonblocking(fd) { int non_block = 1; ioctlsocket(fd, FIONBIO, &non_block); }  # define sock_make_blocking(fd) { int non_block = 0; ioctlsocket(fd, FIONBIO, &non_block); }  # define sockerr_again() (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK) @@ -103,36 +103,52 @@ storage_status_t storage_check_pass (const char *nick, const char *password)  	return STORAGE_NO_SUCH_USER;  } -storage_status_t storage_load (const char *nick, const char *password, irc_t * irc) +storage_status_t storage_load (irc_t * irc, const char *password)  {  	GList *gl; +	if (irc && irc->status & USTATUS_IDENTIFIED) +		return STORAGE_OTHER_ERROR; +	  	/* Loop until we don't get NO_SUCH_USER */  	for (gl = global.storage; gl; gl = gl->next) {  		storage_t *st = gl->data;  		storage_status_t status; -		status = st->load(nick, password, irc); +		status = st->load(irc, password);  		if (status == STORAGE_OK) { -			irc_setpass(irc, password); -			otr_load(irc);		/* load our OTR userstate */ +			otr_load(irc);  			return status;  		} -		if (status != STORAGE_NO_SUCH_USER) { +		if (status != STORAGE_NO_SUCH_USER)   			return status; -		}  	}  	return STORAGE_NO_SUCH_USER;  } -storage_status_t storage_save (irc_t *irc, int overwrite) +storage_status_t storage_save (irc_t *irc, char *password, int overwrite)  {  	storage_status_t st; +	if (password != NULL) { +		/* Should only use this in the "register" command. */ +		if (irc->password || overwrite) +			return STORAGE_OTHER_ERROR; +		 +		irc_setpass(irc, password); +	} else if ((irc->status & USTATUS_IDENTIFIED) == 0) { +		return STORAGE_NO_SUCH_USER; +	} +  	otr_save(irc);  	st = ((storage_t *)global.storage->data)->save(irc, overwrite); +	 +	if (password != NULL) { +		irc_setpass(irc, NULL); +	} +	  	return st;  } @@ -149,8 +165,7 @@ storage_status_t storage_remove (const char *nick, const char *password)  		storage_status_t status;  		status = st->remove(nick, password); -		if (status != STORAGE_NO_SUCH_USER &&  -			status != STORAGE_OK) +		if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK)  			ret = status;  	}  	if (ret == STORAGE_OK) { @@ -160,6 +175,9 @@ storage_status_t storage_remove (const char *nick, const char *password)  	return ret;  } +#if 0 +Not using this yet. Test thoroughly before adding UI hooks to this function. +  storage_status_t storage_rename (const char *onick, const char *nnick, const char *password)  {  	storage_status_t status; @@ -201,3 +219,4 @@ storage_status_t storage_rename (const char *onick, const char *nnick, const cha  	return STORAGE_OK;  } +#endif @@ -44,7 +44,7 @@ typedef struct {  	storage_status_t (*check_pass) (const char *nick, const char *password); -	storage_status_t (*load) (const char *nick, const char *password, irc_t * irc); +	storage_status_t (*load) (irc_t *irc, const char *password);  	storage_status_t (*save) (irc_t *irc, int overwrite);  	storage_status_t (*remove) (const char *nick, const char *password); @@ -54,11 +54,11 @@ typedef struct {  storage_status_t storage_check_pass (const char *nick, const char *password); -storage_status_t storage_load (const char *nick, const char *password, irc_t * irc); -storage_status_t storage_save (irc_t *irc, int overwrite); +storage_status_t storage_load (irc_t * irc, const char *password); +storage_status_t storage_save (irc_t *irc, char *password, int overwrite);  storage_status_t storage_remove (const char *nick, const char *password); -storage_status_t storage_rename (const char *onick, const char *nnick, const char *password); +/* storage_status_t storage_rename (const char *onick, const char *nnick, const char *password); */  void register_storage_backend(storage_t *);  G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); diff --git a/storage_text.c b/storage_text.c index 78f7e3bd..003bde44 100644 --- a/storage_text.c +++ b/storage_text.c @@ -26,14 +26,6 @@  #define BITLBEE_CORE  #include "bitlbee.h"  #include "crypting.h" -#ifdef _WIN32 -# define umask _umask -# define mode_t int -#endif - -#ifndef F_OK -#define F_OK 0 -#endif  static void text_init (void)  { @@ -43,7 +35,7 @@ static void text_init (void)  	   it's read only! */  } -static storage_status_t text_load ( const char *my_nick, const char* password, irc_t *irc ) +static storage_status_t text_load( irc_t *irc, const char* password )  {  	char s[512];  	char *line; @@ -53,10 +45,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i  	user_t *ru = user_find( irc, ROOT_NICK );  	account_t *acc, *acc_lookup[9]; -	if( irc->status & USTATUS_IDENTIFIED ) -		return( 1 ); -	 -	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" ); +	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );     	fp = fopen( s, "r" );     	if( !fp ) return STORAGE_NO_SUCH_USER; @@ -68,10 +57,6 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i  		return STORAGE_INVALID_PASSWORD;  	} -	/* Do this now. If the user runs with AuthMode = Registered, the -	   account command will not work otherwise. */ -	irc->status |= USTATUS_IDENTIFIED; -	  	while( fscanf( fp, "%511[^\n]s", s ) > 0 )  	{  		fgetc( fp ); @@ -100,7 +85,7 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i  			acc_lookup[8] = acc;  	} -	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" ); +	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );  	fp = fopen( s, "r" );  	if( !fp ) return STORAGE_NO_SUCH_USER;  	while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 ) diff --git a/storage_xml.c b/storage_xml.c index 240206f1..09e2f328 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -28,7 +28,14 @@  #include "base64.h"  #include "arc.h"  #include "md5.h" + +#if GLIB_CHECK_VERSION(2,8,0)  #include <glib/gstdio.h> +#else +/* GLib < 2.8.0 doesn't have g_access, so just use the system access(). */ +#include <unistd.h> +#define g_access access +#endif  #if !GLIB_CHECK_VERSION(2,8,0)  /* GLib < 2.8.0 doesn't have g_access, so just use the system access(). */ @@ -255,7 +262,7 @@ static void xml_init( void )  		log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", global.conf->configdir );  } -static storage_status_t xml_load_real( const char *my_nick, const char *password, irc_t *irc, xml_pass_st action ) +static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const char *password, xml_pass_st action )  {  	GMarkupParseContext *ctx;  	struct xml_parsedata *xd; @@ -263,9 +270,6 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password  	GError *gerr = NULL;  	int fd, st; -	if( irc && irc->status & USTATUS_IDENTIFIED ) -		return( 1 ); -	  	xd = g_new0( struct xml_parsedata, 1 );  	xd->irc = irc;  	xd->given_nick = g_strdup( my_nick ); @@ -317,21 +321,19 @@ static storage_status_t xml_load_real( const char *my_nick, const char *password  	if( action == XML_PASS_CHECK_ONLY )  		return STORAGE_OK; -	irc->status |= USTATUS_IDENTIFIED; -	  	return STORAGE_OK;  } -static storage_status_t xml_load( const char *my_nick, const char *password, irc_t *irc ) +static storage_status_t xml_load( irc_t *irc, const char *password )  { -	return xml_load_real( my_nick, password, irc, XML_PASS_UNKNOWN ); +	return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN );  }  static storage_status_t xml_check_pass( const char *my_nick, const char *password )  {  	/* This is a little bit risky because we have to pass NULL for the  	   irc_t argument. This *should* be fine, if I didn't miss anything... */ -	return xml_load_real( my_nick, password, NULL, XML_PASS_CHECK_ONLY ); +	return xml_load_real( NULL, my_nick, password, XML_PASS_CHECK_ONLY );  }  static int xml_printf( int fd, int indent, char *fmt, ... ) @@ -367,12 +369,6 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )  	md5_byte_t pass_md5[21];  	md5_state_t md5_state; -	if( irc->password == NULL ) -	{ -		irc_usermsg( irc, "Please register yourself if you want to save your settings." ); -		return STORAGE_OTHER_ERROR; -	} -	  	path2 = g_strdup( irc->nick );  	nick_lc( path2 );  	g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" ); @@ -55,13 +55,13 @@ int main( int argc, char *argv[] )  	b_main_init();  	nogaim_init(); -	/* Ugly Note: libotr and gnutls both use libgcrypt. libgcrypt -	   has a process-global config state whose initialization happpens -	   twice if libotr and gnutls are used together. libotr installs custom -	   memory management functions for libgcrypt while our gnutls module -	   uses the defaults. Therefore we initialize OTR after SSL. *sigh* */ -	ssl_init(); -	otr_init(); + 	/* Ugly Note: libotr and gnutls both use libgcrypt. libgcrypt + 	   has a process-global config state whose initialization happpens + 	   twice if libotr and gnutls are used together. libotr installs custom + 	   memory management functions for libgcrypt while our gnutls module + 	   uses the defaults. Therefore we initialize OTR after SSL. *sigh* */ + 	ssl_init(); + 	otr_init();  	srand( time( NULL ) ^ getpid() );  	global.helpfile = g_strdup( HELP_FILE ); @@ -222,5 +222,3 @@ double gettime()  	gettimeofday( time, 0 );  	return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );  } - - | 
