diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2007-10-12 01:08:58 +0100 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2007-10-12 01:08:58 +0100 | 
| commit | eda54e40d04c83028d84e91c895a550c1929b436 (patch) | |
| tree | 878f985af2ab5d2b9c59e8c955448bc4e9ddec17 | |
| parent | 82135c7178b6379f35741991f6c06bb308143194 (diff) | |
| parent | d444c09e6c7ac6fc3c1686af0e63c09805d8cd00 (diff) | |
Merge from devel.
| -rw-r--r-- | Makefile | 2 | ||||
| -rwxr-xr-x | configure | 15 | ||||
| -rw-r--r-- | doc/CHANGES | 17 | ||||
| -rw-r--r-- | doc/user-guide/commands.xml | 10 | ||||
| -rw-r--r-- | irc.c | 5 | ||||
| -rw-r--r-- | lib/Makefile | 2 | ||||
| -rw-r--r-- | lib/arc.c (renamed from lib/rc4.c) | 107 | ||||
| -rw-r--r-- | lib/arc.h (renamed from lib/rc4.h) | 16 | ||||
| -rw-r--r-- | lib/base64.c | 4 | ||||
| -rw-r--r-- | lib/base64.h | 2 | ||||
| -rw-r--r-- | lib/misc.c | 48 | ||||
| -rw-r--r-- | lib/misc.h | 2 | ||||
| -rw-r--r-- | lib/ssl_bogus.c | 5 | ||||
| -rw-r--r-- | protocols/jabber/sasl.c | 7 | ||||
| -rw-r--r-- | protocols/nogaim.c | 64 | ||||
| -rw-r--r-- | protocols/nogaim.h | 96 | ||||
| -rw-r--r-- | root_commands.c | 2 | ||||
| -rw-r--r-- | storage_xml.c | 23 | ||||
| -rw-r--r-- | tests/Makefile | 2 | ||||
| -rw-r--r-- | tests/check.c | 4 | ||||
| -rw-r--r-- | tests/check_arc.c | 95 | ||||
| -rw-r--r-- | tests/check_util.c | 58 | ||||
| -rw-r--r-- | unix.c | 13 | 
23 files changed, 466 insertions, 133 deletions
| @@ -10,7 +10,7 @@  # Program variables  objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o user.o -headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h +headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha.h lib/ssl_client.h lib/url.h protocols/nogaim.h  subdirs = lib protocols  # Expansion of variables @@ -28,6 +28,7 @@ yahoo=1  debug=0  strip=1  gcov=0 +plugins=1  ipv6=1  events=glib @@ -68,11 +69,10 @@ Option		Description				Default  --debug=0/1	Disable/enable debugging		$debug  --strip=0/1	Disable/enable binary stripping		$strip  --gcov=0/1	Disable/enable test coverage reporting	$gcov +--plugins=0/1	Disable/enable plugins support		$plugins  --ipv6=0/1	IPv6 socket support			$ipv6 ---ldap=0/1/auto	LDAP support				$ldap -  --events=...	Event handler (glib, libevent)		$events  --ssl=...	SSL library to use (gnutls, nss, openssl, bogus, auto)  							$ssl @@ -139,13 +139,14 @@ if [ "$ipv6" = "1" ]; then  fi  if [ "$debug" = "1" ]; then -	echo 'CFLAGS=-g' >> Makefile.settings +	[ -z "$CFLAGS" ] && CFLAGS=-g  	echo 'DEBUG=1' >> Makefile.settings  	echo '#define DEBUG' >> config.h  else -	echo 'CFLAGS=-O3' >> Makefile.settings +	[ -z "$CFLAGS" ] && CFLAGS=-O3  fi +echo CFLAGS=$CFLAGS >> Makefile.settings  echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings  echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings @@ -384,6 +385,12 @@ if [ "$gcov" = "1" ]; then  	echo "EFLAGS+=-lgcov" >> Makefile.settings  fi +if [ "$plugins" = 0 ]; then +	echo '#undef WITH_PLUGINS' >> config.h +else +	echo '#define WITH_PLUGINS' >> config.h +fi +  echo  if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then  	nick=`bzr nick` diff --git a/doc/CHANGES b/doc/CHANGES index 3f509c46..6c109f25 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,4 +1,4 @@ -Version 1.1dev: +Version 1.2:  - First BitlBee development/testing RELEASE. This should be quite stable    though (and for most people more stable than 1.0.x). It just has a couple    of rough edges and needs a bit more testing. @@ -65,6 +65,21 @@ Version 1.1dev:      resources available for that buddy. (Of course this only works if the      buddy is in your contact list.) +Finished ??? + +Version 1.0.4: +- Removed sethostent(), which causes problems for many people, especially on +  *BSD. This is basically the reason for this release. +- "allow" command actually displays the allow list, not the block list. +- Yahoo away state/msg fix. +- Don't display "Gender: Male" by default if nothing's filled in (OSCAR +  "info" command) +- Fixed account cleanup (possible infinite loop) in irc_free(). +- Fixed configdir error message to not always display the compile-time +  setting. + +Finished 20 Aug 2007 +  Version 1.0.3:  - Fixed ugliness in block/allow list commands (still not perfect though, the    list is empty or not up-to-date for most protocols). diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index 6646d0db..cf40782f 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -595,6 +595,16 @@  		</description>  	</bitlbee-setting> +	<bitlbee-setting name="simulate_netsplit" type="boolean" scope="global"> +		<default>true</default> + +		<description> +			<para> +				Some IRC clients parse quit messages sent by the IRC server to see if someone really left or just disappeared because of a netsplit. By default, BitlBee tries to simulate netsplit-like quit messages to keep the control channel window clean. If you don't like this (or if your IRC client doesn't support this) you can disable this setting. +			</para> +		</description> +	</bitlbee-setting> +  	<bitlbee-setting name="ssl" type="boolean" scope="account">  		<default>false</default> @@ -131,7 +131,7 @@ irc_t *irc_new( int fd )  	set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc );  	set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );  	set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc ); -	set_add( &irc->set, "charset", "iso8859-1", set_eval_charset, irc ); +	set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );  	set_add( &irc->set, "debug", "false", set_eval_bool, irc );  	set_add( &irc->set, "default_target", "root", NULL, irc );  	set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc ); @@ -142,6 +142,7 @@ irc_t *irc_new( int fd )  	set_add( &irc->set, "private", "true", set_eval_bool, irc );  	set_add( &irc->set, "query_order", "lifo", NULL, irc );  	set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc ); +	set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );  	set_add( &irc->set, "strip_html", "true", NULL, irc );  	set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );  	set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); @@ -909,7 +910,7 @@ void irc_kill( irc_t *irc, user_t *u )  	char *nick, *s;  	char reason[128]; -	if( u->ic && u->ic->flags & OPT_LOGGING_OUT ) +	if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) )  	{  		if( u->ic->acc->server )  			g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost, diff --git a/lib/Makefile b/lib/Makefile index a9038987..bc1966d9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,7 +9,7 @@  -include ../Makefile.settings  # [SH] Program variables -objects = base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o +objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha.o $(SSL_CLIENT) url.o  CFLAGS += -Wall  LFLAGS += -r @@ -1,7 +1,7 @@  /***************************************************************************\  *                                                                           *  *  BitlBee - An IRC to IM gateway                                           * -*  Simple (but secure) RC4 implementation for safer password storage.       * +*  Simple (but secure) ArcFour implementation for safer password storage.   *  *                                                                           *  *  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *  *                                                                           * @@ -22,18 +22,21 @@  \***************************************************************************/  /*  -   This file implements RC4-encryption, which will mainly be used to save IM -   passwords safely in the new XML-format. Possibly other uses will come up -   later. It's supposed to be quite reliable (thanks to the use of a 6-byte -   IV/seed), certainly compared to the old format. The only realistic way to -   crack BitlBee passwords now is to use a sniffer to get your hands on the -   user's password. +   This file implements ArcFour-encryption, which will mainly be used to +   save IM passwords safely in the new XML-format. Possibly other uses will +   come up later. It's supposed to be quite reliable (thanks to the use of a +   6-byte IV/seed), certainly compared to the old format. The only realistic +   way to crack BitlBee passwords now is to use a sniffer to get your hands +   on the user's password.     If you see that something's wrong in this implementation (I asked a     couple of people to look at it already, but who knows), please tell me. -   The reason I chose for RC4 is because it's pretty simple but effective, +   The reason I picked ArcFour is because it's pretty simple but effective,     so it will work without adding several KBs or an extra library dependency. +    +   (ArcFour is an RC4-compatible cipher. See for details: +   http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt)  */ @@ -42,55 +45,62 @@  #include <stdlib.h>  #include <string.h>  #include "misc.h" -#include "rc4.h" +#include "arc.h"  /* Add some seed to the password, to make sure we *never* use the same key.     This defines how many bytes we use as a seed. */ -#define RC4_IV_LEN 6 +#define ARC_IV_LEN 6  /* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended     to shuffle S[] just a bit more before you start to use it. This defines how     many bytes we'll request before we'll really use them for encryption. */ -#define RC4_CYCLES 1024 +#define ARC_CYCLES 1024 -struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ) +struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles )  { -	struct rc4_state *st; +	struct arc_state *st;  	int i, j, tmp; +	unsigned char S2[256]; -	st = g_malloc( sizeof( struct rc4_state ) ); +	st = g_malloc( sizeof( struct arc_state ) );  	st->i = st->j = 0; -	for( i = 0; i < 256; i ++ ) -		st->S[i] = i; -	  	if( kl <= 0 )  		kl = strlen( (char*) key ); +	for( i = 0; i < 256; i ++ ) +	{ +		st->S[i] = i; +		S2[i] = key[i%kl]; +	} +	  	for( i = j = 0; i < 256; i ++ )  	{ -		j = ( j + st->S[i] + key[i%kl] ) & 0xff; +		j = ( j + st->S[i] + S2[i] ) & 0xff;  		tmp = st->S[i];  		st->S[i] = st->S[j];  		st->S[j] = tmp;  	} +	memset( S2, 0, 256 ); +	i = j = 0; +	  	for( i = 0; i < cycles; i ++ ) -		rc4_getbyte( st ); +		arc_getbyte( st );  	return st;  }  /* -   For those who don't know, RC4 is basically an algorithm that generates a -   stream of bytes after you give it a key. Just get a byte from it and xor -   it with your cleartext. To decrypt, just give it the same key again and -   start xorring. +   For those who don't know, ArcFour is basically an algorithm that generates +   a stream of bytes after you give it a key. Just get a byte from it and +   xor it with your cleartext. To decrypt, just give it the same key again +   and start xorring. -   The function above initializes the RC4 byte generator, the next function -   can be used to get bytes from the generator (and shuffle things a bit). +   The function above initializes the byte generator, the next function can +   be used to get bytes from the generator (and shuffle things a bit).  */ -unsigned char rc4_getbyte( struct rc4_state *st ) +unsigned char arc_getbyte( struct arc_state *st )  {  	unsigned char tmp; @@ -100,16 +110,17 @@ unsigned char rc4_getbyte( struct rc4_state *st )  	tmp = st->S[st->i];  	st->S[st->i] = st->S[st->j];  	st->S[st->j] = tmp; +	tmp = (st->S[st->i] + st->S[st->j]) & 0xff; -	return st->S[(st->S[st->i] + st->S[st->j]) & 0xff]; +	return st->S[tmp];  }  /*     The following two functions can be used for reliable encryption and     decryption. Known plaintext attacks are prevented by adding some (6, -   by default) random bytes to the password before setting up the RC4 +   by default) random bytes to the password before setting up the state     structures. These 6 bytes are also saved in the results, because of -   course we'll need them in rc4_decode(). +   course we'll need them in arc_decode().     Because the length of the resulting string is unknown to the caller,     it should pass a char**. Since the encode/decode functions allocate @@ -121,50 +132,50 @@ unsigned char rc4_getbyte( struct rc4_state *st )     Both functions return the number of bytes in the result string.  */ -int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ) +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password )  { -	struct rc4_state *st; +	struct arc_state *st;  	unsigned char *key;  	int key_len, i; -	key_len = strlen( password ) + RC4_IV_LEN; +	key_len = strlen( password ) + ARC_IV_LEN;  	if( clear_len <= 0 ) -		clear_len = strlen( (char*) clear ); +		clear_len = strlen( clear );  	/* Prepare buffers and the key + IV */ -	*crypt = g_malloc( clear_len + RC4_IV_LEN ); +	*crypt = g_malloc( clear_len + ARC_IV_LEN );  	key = g_malloc( key_len );  	strcpy( (char*) key, password );  	/* Add the salt. Save it for later (when decrypting) and, of course,  	   add it to the encryption key. */ -	random_bytes( crypt[0], RC4_IV_LEN ); -	memcpy( key + key_len - RC4_IV_LEN, crypt[0], RC4_IV_LEN ); +	random_bytes( crypt[0], ARC_IV_LEN ); +	memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN );  	/* Generate the initial S[] from the IVed key. */ -	st = rc4_keymaker( key, key_len, RC4_CYCLES ); +	st = arc_keymaker( key, key_len, ARC_CYCLES );  	g_free( key );  	for( i = 0; i < clear_len; i ++ ) -		crypt[0][i+RC4_IV_LEN] = clear[i] ^ rc4_getbyte( st ); +		crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st );  	g_free( st ); -	return clear_len + RC4_IV_LEN; +	return clear_len + ARC_IV_LEN;  } -int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ) +int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password )  { -	struct rc4_state *st; +	struct arc_state *st;  	unsigned char *key;  	int key_len, clear_len, i; -	key_len = strlen( password ) + RC4_IV_LEN; -	clear_len = crypt_len - RC4_IV_LEN; +	key_len = strlen( password ) + ARC_IV_LEN; +	clear_len = crypt_len - ARC_IV_LEN;  	if( clear_len < 0 )  	{ -		*clear = (unsigned char*) g_strdup( "" ); +		*clear = g_strdup( "" );  		return 0;  	} @@ -172,15 +183,15 @@ int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char  	*clear = g_malloc( clear_len + 1 );  	key = g_malloc( key_len );  	strcpy( (char*) key, password ); -	for( i = 0; i < RC4_IV_LEN; i ++ ) -		key[key_len-RC4_IV_LEN+i] = crypt[i]; +	for( i = 0; i < ARC_IV_LEN; i ++ ) +		key[key_len-ARC_IV_LEN+i] = crypt[i];  	/* Generate the initial S[] from the IVed key. */ -	st = rc4_keymaker( key, key_len, RC4_CYCLES ); +	st = arc_keymaker( key, key_len, ARC_CYCLES );  	g_free( key );  	for( i = 0; i < clear_len; i ++ ) -		clear[0][i] = crypt[i+RC4_IV_LEN] ^ rc4_getbyte( st ); +		clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st );  	clear[0][i] = 0; /* Nice to have for plaintexts. */  	g_free( st ); @@ -1,9 +1,9 @@  /***************************************************************************\  *                                                                           *  *  BitlBee - An IRC to IM gateway                                           * -*  Simple (but secure) RC4 implementation for safer password storage.       * +*  Simple (but secure) ArcFour implementation for safer password storage.   *  *                                                                           * -*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   * +*  Copyright 2007 Wilmer van der Gaast <wilmer@gaast.net>                   *  *                                                                           *  *  This program is free software; you can redistribute it and/or modify     *  *  it under the terms of the GNU General Public License as published by     * @@ -22,15 +22,15 @@  \***************************************************************************/ -/* See rc4.c for more information. */ +/* See arc.c for more information. */ -struct rc4_state +struct arc_state  {  	unsigned char S[256];  	unsigned char i, j;  }; -struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles ); -unsigned char rc4_getbyte( struct rc4_state *st ); -int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password ); -int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password ); +struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ); +unsigned char arc_getbyte( struct arc_state *st ); +int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password ); +int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ); diff --git a/lib/base64.c b/lib/base64.c index 69069dae..64e9692a 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -30,10 +30,10 @@ static const char real_b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv  char *tobase64(const char *text)  { -	return base64_encode(text, strlen(text)); +	return base64_encode((const unsigned char *)text, strlen(text));  } -char *base64_encode(const char *in, int len) +char *base64_encode(const unsigned char *in, int len)  {  	char *out; diff --git a/lib/base64.h b/lib/base64.h index 570f2b14..ebd74bf1 100644 --- a/lib/base64.h +++ b/lib/base64.h @@ -26,7 +26,7 @@  #include <gmodule.h>  G_MODULE_EXPORT char *tobase64( const char *text ); -G_MODULE_EXPORT char *base64_encode( const char *in, int len ); +G_MODULE_EXPORT char *base64_encode( const unsigned char *in, int len );  G_MODULE_EXPORT int base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, const char *b64digits );  G_MODULE_EXPORT char *frombase64( const char *in );  G_MODULE_EXPORT int base64_decode( const char *in, unsigned char **out ); @@ -544,3 +544,51 @@ struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain )  	return reply;  } + +/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */ +char *word_wrap( char *msg, int line_len ) +{ +	GString *ret = g_string_sized_new( strlen( msg ) + 16 ); +	 +	while( strlen( msg ) > line_len ) +	{ +		int i; +		 +		/* First try to find out if there's a newline already. Don't +		   want to add more splits than necessary. */ +		for( i = line_len; i > 0 && msg[i] != '\n'; i -- ); +		if( msg[i] == '\n' ) +		{ +			g_string_append_len( ret, msg, i + 1 ); +			msg += i + 1; +			continue; +		} +		 +		for( i = line_len; i > 0; i -- ) +		{ +			if( msg[i] == '-' ) +			{ +				g_string_append_len( ret, msg, i + 1 ); +				g_string_append_c( ret, '\n' ); +				msg += i + 1; +				break; +			} +			else if( msg[i] == ' ' ) +			{ +				g_string_append_len( ret, msg, i ); +				g_string_append_c( ret, '\n' ); +				msg += i + 1; +				break; +			} +		} +		if( i == 0 ) +		{ +			g_string_append_len( ret, msg, line_len ); +			g_string_append_c( ret, '\n' ); +			msg += line_len; +		} +	} +	g_string_append( ret, msg ); +	 +	return g_string_free( ret, FALSE ); +} @@ -63,4 +63,6 @@ G_MODULE_EXPORT int bool2int( char *value );  G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain ); +G_MODULE_EXPORT char *word_wrap( char *msg, int line_len ); +  #endif diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c index 00aaa7c4..5bae3496 100644 --- a/lib/ssl_bogus.c +++ b/lib/ssl_bogus.c @@ -51,6 +51,11 @@ int ssl_getfd( void *conn )  	return( -1 );  } +void *ssl_starttls( int fd, ssl_input_function func, gpointer data )  +{ +	return NULL; +} +  b_input_condition ssl_getdirection( void *conn )  {  	return GAIM_INPUT_READ; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 69199a8b..6eee37b3 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -88,7 +88,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )  		s[0] = 0;  		strcpy( s + 1, jd->username );  		strcpy( s + 2 + strlen( jd->username ), ic->acc->pass ); -		reply->text = base64_encode( s, len ); +		reply->text = base64_encode( (unsigned char *)s, len );  		reply->text_len = strlen( reply->text );  		g_free( s );  	} @@ -184,7 +184,8 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data )  	struct im_connection *ic = data;  	struct jabber_data *jd = ic->proto_data;  	struct xt_node *reply = NULL; -	char *nonce = NULL, *realm = NULL, *cnonce = NULL, cnonce_bin[30]; +	char *nonce = NULL, *realm = NULL, *cnonce = NULL; +	unsigned char cnonce_bin[30];  	char *digest_uri = NULL;  	char *dec = NULL;  	char *s = NULL; @@ -215,7 +216,7 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data )  		if( !realm )  			realm = g_strdup( jd->server ); -		random_bytes( (unsigned char *) cnonce_bin, sizeof( cnonce_bin ) ); +		random_bytes( cnonce_bin, sizeof( cnonce_bin ) );  		cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) );  		digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server ); diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 4b0b738b..3307b0f5 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -47,7 +47,7 @@ gboolean load_plugin(char *path)  	GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);  	if(!mod) { -		log_message(LOGLVL_ERROR, "Can't find `%s', not loading", path); +		log_message(LOGLVL_ERROR, "Can't find `%s', not loading (%s)\n", path, g_module_error());  		return FALSE;  	} @@ -607,14 +607,27 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  	    ( ( ( u->online != oo ) && !u->away ) ||			/* Voice joining people */  	      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )		/* (De)voice people changing state */  	{ -		irc_write( ic->irc, ":%s MODE %s %cv %s", ic->irc->myhost, -		                                          ic->irc->channel, u->away?'-':'+', u->nick ); +		char *from; +		 +		if( set_getbool( &ic->irc->set, "simulate_netsplit" ) ) +		{ +			from = g_strdup( ic->irc->myhost ); +		} +		else +		{ +			from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick, +			                                    ic->irc->myhost ); +		} +		irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, +		                                          u->away?'-':'+', u->nick ); +		g_free( from );  	}  }  void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at )  {  	irc_t *irc = ic->irc; +	char *wrapped;  	user_t *u;  	u = user_findhandle( ic, handle ); @@ -657,37 +670,9 @@ void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_  	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )  		strip_html( msg ); -	while( strlen( msg ) > 425 ) -	{ -		char tmp, *nl; -		 -		tmp = msg[425]; -		msg[425] = 0; -		 -		/* If there's a newline/space in this string, split up there, -		   looks a bit prettier. */ -		if( ( nl = strrchr( msg, '\n' ) ) || ( nl = strrchr( msg, ' ' ) ) ) -		{ -			msg[425] = tmp; -			tmp = *nl; -			*nl = 0; -		} -		 -		irc_msgfrom( irc, u->nick, msg ); -		 -		/* Move on. */ -		if( nl ) -		{ -			*nl = tmp; -			msg = nl + 1; -		} -		else -		{ -			msg[425] = tmp; -			msg += 425; -		} -	} -	irc_msgfrom( irc, u->nick, msg ); +	wrapped = word_wrap( msg, 425 ); +	irc_msgfrom( irc, u->nick, wrapped ); +	g_free( wrapped );  }  void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags ) @@ -749,6 +734,7 @@ void imcb_chat_free( struct groupchat *c )  void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at )  {  	struct im_connection *ic = c->ic; +	char *wrapped;  	user_t *u;  	/* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ @@ -761,10 +747,16 @@ void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags,  	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )  		strip_html( msg ); +	wrapped = word_wrap( msg, 425 );  	if( c && u ) -		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", msg ); +	{ +		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped ); +	}  	else -		imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, msg ); +	{ +		imcb_log( ic, "Message from/to conversation %s@0x%x (unknown conv/user): %s", who, (int) c, wrapped ); +	} +	g_free( wrapped );  }  struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle ) diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 6aa057ff..5bf6d922 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -97,13 +97,21 @@ struct im_connection  struct groupchat {  	struct im_connection *ic; +	/* stuff used just for chat */ +	/* The in_room variable is a list of handles (not nicks!), kind of +	 * "nick list". This is how you can check who is in the group chat +	 * already, for example to avoid adding somebody two times. */  	GList *in_room;  	GList *ignored;  	struct groupchat *next;  	char *channel; +	/* The title variable contains the ID you gave when you created the +	 * chat using imcb_chat_new(). */  	char *title;  	char joined; +	/* This is for you, you can add your own structure here to extend this +	 * structure for your protocol's needs. */  	void *data;  }; @@ -122,26 +130,52 @@ struct buddy {  struct prpl {  	int options; +	/* You should set this to the name of your protocol. +	 * - The user sees this name ie. when imcb_log() is used. */  	const char *name;  	/* Added this one to be able to add per-account settings, don't think -	   it should be used for anything else. */ +	 * it should be used for anything else. You are supposed to use the +	 * set_add() function to add new settings. */  	void (* init)		(account_t *); -	/* These should all be pretty obvious. */ +	/* The typical usage of the login() function: +	 * - Create an im_connection using imcb_new() from the account_t parameter. +	 * - Initialize your myproto_data struct - you should store all your protocol-specific data there. +	 * - Save your custom structure to im_connection->proto_data. +	 * - Use proxy_connect() to connect to the server. +	 */  	void (* login)		(account_t *); +	/* Implementing this function is optional. */  	void (* keepalive)	(struct im_connection *); +	/* In this function you should: +	 * - Tell the server about you are logging out. +	 * - g_free() your myproto_data struct as BitlBee does not know how to +	 *   properly do so. +	 */  	void (* logout)		(struct im_connection *); +	/* This function is called when the user wants to send a message to a handle. +	 * - 'to' is a handle, not a nick +	 * - 'flags' may be ignored +	 */  	int  (* buddy_msg)	(struct im_connection *, char *to, char *message, int flags); +	/* This function is called then the user uses the /away IRC command. +	 * - 'state' contains the away reason. +	 * - 'message' may be ignored if your protocol does not support it. +	 */  	void (* set_away)	(struct im_connection *, char *state, char *message); +	/* Implementing this function is optional. */  	void (* get_away)       (struct im_connection *, char *who); +	/* Implementing this function is optional. */  	int  (* send_typing)	(struct im_connection *, char *who, int flags); -	/* For now BitlBee doesn't really handle groups, just set it to NULL. */ +	/* 'name' is a handle to add/remove. For now BitlBee doesn't really +	 * handle groups, just set it to NULL, so you can ignore that +	 * parameter. */  	void (* add_buddy)	(struct im_connection *, char *name, char *group);  	void (* remove_buddy)	(struct im_connection *, char *name, char *group); -	/* Block list stuff. */ +	/* Block list stuff. Implementing these are optional. */  	void (* add_permit)	(struct im_connection *, char *who);  	void (* add_deny)	(struct im_connection *, char *who);  	void (* rem_permit)	(struct im_connection *, char *who); @@ -150,23 +184,41 @@ struct prpl {  	void (* set_permit_deny)(struct im_connection *);  	/* Request profile info. Free-formatted stuff, the IM module gives back -	   this info via imcb_log(). */ +	   this info via imcb_log(). Implementing these are optional. */  	void (* get_info)	(struct im_connection *, char *who);  	void (* set_my_name)	(struct im_connection *, char *name);  	void (* set_name)	(struct im_connection *, char *who, char *name);  	/* Group chat stuff. */ +	/* This is called when the user uses the /invite IRC command. +	 * - 'who' may be ignored +	 * - 'message' is a handle to invite +	 */  	void (* chat_invite)	(struct groupchat *, char *who, char *message); +	/* This is called when the user uses the /part IRC command in a group +	 * chat. You just should tell the user about it, nothing more. */  	void (* chat_leave)	(struct groupchat *); +	/* This is called when the user sends a message to the groupchat. +	 * 'flags' may be ignored. */  	void (* chat_msg)	(struct groupchat *, char *message, int flags); +	/* This is called when the user uses the /join #nick IRC command. +	 * - 'who' is the handle of the nick +	 */  	struct groupchat *  	     (* chat_with)	(struct im_connection *, char *who); +	/* This is used when the user uses the /join #channel IRC command.  If +	 * your protocol does not support publicly named group chats, then do +	 * not implement this. */  	struct groupchat *  	     (* chat_join)	(struct im_connection *, char *room, char *nick, char *password); +	/* You can tell what away states your protocol supports, so that +	 * BitlBee will try to map the IRC away reasons to them, or use +	 * GAIM_AWAY_CUSTOM when calling skype_set_away(). */  	GList *(* away_states)(struct im_connection *ic); -	/* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ +	/* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* +	 * - Most protocols will just want to set this to g_strcasecmp().*/  	int (* handle_cmp) (const char *who1, const char *who2);  }; @@ -174,21 +226,40 @@ struct prpl {  void nogaim_init();  G_MODULE_EXPORT GSList *get_connections();  G_MODULE_EXPORT struct prpl *find_protocol( const char *name ); +/* When registering a new protocol, you should allocate space for a new prpl + * struct, initialize it (set the function pointers to point to your + * functions), finally call this function. */  G_MODULE_EXPORT void register_protocol( struct prpl * );  /* Connection management. */ +/* You will need this function in prpl->login() to get an im_connection from + * the account_t parameter. */  G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc );  G_MODULE_EXPORT void imcb_free( struct im_connection *ic ); +/* Once you're connected, you should call this function, so that the user will + * see the success. */  G_MODULE_EXPORT void imcb_connected( struct im_connection *ic ); +/* This can be used to disconnect when something went wrong (ie. read error + * from the server). You probably want to set the second parameter to TRUE. */  G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect );  /* Communicating with the user. */ +/* A printf()-like function to tell the user anything you want. */  G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +/* To tell the user an error, ie. before logging out when an error occurs. */  G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +/* To ask a your about something. + * - 'msg' is the question. + * - 'data' can be your custom struct - it will be passed to the callbacks. + * - 'doit' or 'dont' will be called depending of the answer of the user. + */  G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont );  G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname );  /* Buddy management */ +/* This function should be called for each handle which are visible to the + * user, usually after a login, 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 struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); @@ -196,17 +267,30 @@ G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle,  G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );  /* Buddy activity */ +/* To manipulate the status of a handle. + * - flags can be |='d with OPT_* constants. You will need at least: + *   OPT_LOGGED_IN and OPT_AWAY. + * - 'state' and 'message' can be NULL */  G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );  /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); +/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */  G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at );  G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags );  G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );  /* Groupchats */  G_MODULE_EXPORT void imcb_chat_invited( struct im_connection *ic, char *handle, char *who, char *msg, GList *data ); +/* These two functions are to create a group chat. + * - imcb_chat_new(): the 'handle' parameter identifies the chat, like the + *   channel name on IRC. + * - After you have a groupchat pointer, you should add the handles, finally + *   the user her/himself. At that point the group chat will be visible to the + *   user, too. */  G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, char *handle );  G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle ); +/* To remove a handle from a group chat. Reason can be NULL. */  G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason ); +/* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */  G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at );  G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); diff --git a/root_commands.c b/root_commands.c index 0f9f776c..e8c796d3 100644 --- a/root_commands.c +++ b/root_commands.c @@ -382,7 +382,7 @@ static void cmd_account( irc_t *irc, char **cmd )  			return;  		} -		if( cmd[3] ) +		if( cmd[3] && set_name )  		{  			set_t *s = set_find( &a->set, set_name ); diff --git a/storage_xml.c b/storage_xml.c index 00fca425..8618c5fe 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -26,7 +26,7 @@  #define BITLBEE_CORE  #include "bitlbee.h"  #include "base64.h" -#include "rc4.h" +#include "arc.h"  #include "md5.h"  typedef enum @@ -131,7 +131,8 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na  	else if( g_strcasecmp( element_name, "account" ) == 0 )  	{  		char *protocol, *handle, *server, *password = NULL, *autoconnect; -		char *pass_b64 = NULL, *pass_rc4 = NULL; +		char *pass_b64 = NULL; +		unsigned char *pass_cr = NULL;  		int pass_len;  		struct prpl *prpl = NULL; @@ -150,9 +151,8 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na  		else if( !prpl )  			g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,  			             "Unknown protocol: %s", protocol ); -		else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_rc4 ) ) && -		                rc4_decode( (unsigned char*) pass_rc4, pass_len, -		                            (unsigned char**) &password, xd->given_pass ) ) +		else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_cr ) ) && +		                         arc_decode( pass_cr, pass_len, &password, xd->given_pass ) )  		{  			xd->current_account = account_add( irc, prpl, handle, password );  			if( server ) @@ -168,7 +168,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na  			             "Error while decrypting account password" );  		} -		g_free( pass_rc4 ); +		g_free( pass_cr );  		g_free( password );  	}  	else if( g_strcasecmp( element_name, "setting" ) == 0 ) @@ -409,7 +409,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )  	md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */  	md5_finish( &md5_state, pass_md5 );  	/* Save the hash in base64-encoded form. */ -	pass_buf = base64_encode( (char*) pass_md5, 21 ); +	pass_buf = base64_encode( pass_md5, 21 );  	if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )  		goto write_error; @@ -423,12 +423,13 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )  	for( acc = irc->accounts; acc; acc = acc->next )  	{ -		char *pass_rc4, *pass_b64; +		unsigned char *pass_cr; +		char *pass_b64;  		int pass_len; -		pass_len = rc4_encode( (unsigned char*) acc->pass, strlen( acc->pass ), (unsigned char**) &pass_rc4, irc->password ); -		pass_b64 = base64_encode( pass_rc4, pass_len ); -		g_free( pass_rc4 ); +		pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password ); +		pass_b64 = base64_encode( pass_cr, pass_len ); +		g_free( pass_cr );  		if( !xml_printf( fd, 1, "<account protocol=\"%s\" handle=\"%s\" password=\"%s\" autoconnect=\"%d\"", acc->prpl->name, acc->user, pass_b64, acc->auto_connect ) )  		{ diff --git a/tests/Makefile b/tests/Makefile index 4d4ed8d3..5bc3fbde 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -12,7 +12,7 @@ distclean: clean  main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o  -test_objs = check.o check_util.o check_nick.o check_md5.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o +test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_crypting.o check_set.o  check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o  	@echo '*' Linking $@ diff --git a/tests/check.c b/tests/check.c index 488d9608..043889d6 100644 --- a/tests/check.c +++ b/tests/check.c @@ -47,6 +47,9 @@ Suite *nick_suite(void);  /* From check_md5.c */  Suite *md5_suite(void); +/* From check_arc.c */ +Suite *arc_suite(void); +  /* From check_irc.c */  Suite *irc_suite(void); @@ -101,6 +104,7 @@ int main (int argc, char **argv)  	sr = srunner_create(util_suite());  	srunner_add_suite(sr, nick_suite());  	srunner_add_suite(sr, md5_suite()); +	srunner_add_suite(sr, arc_suite());  	srunner_add_suite(sr, irc_suite());  	srunner_add_suite(sr, help_suite());  	srunner_add_suite(sr, user_suite()); diff --git a/tests/check_arc.c b/tests/check_arc.c new file mode 100644 index 00000000..989a0a66 --- /dev/null +++ b/tests/check_arc.c @@ -0,0 +1,95 @@ +#include <stdlib.h> +#include <glib.h> +#include <gmodule.h> +#include <check.h> +#include <string.h> +#include <stdio.h> +#include "arc.h" + +char *password = "TotT"; + +char *clear_tests[] = +{ +	"Wie dit leest is gek :-)", +	"ItllBeBitlBee", +	"One more boring password", +	NULL +}; + +static void check_codec(int l) +{ +	int i; +	 +	for( i = 0; clear_tests[i]; i++ ) +	{ +  		tcase_fn_start (clear_tests[i], __FILE__, __LINE__); +		unsigned char *crypted; +		char *decrypted; +		int len; +		 +		len = arc_encode( clear_tests[i], 0, &crypted, password ); +		len = arc_decode( crypted, len, &decrypted, password ); +		 +		fail_if( strcmp( clear_tests[i], decrypted ) != 0, +		         "%s didn't decrypt back properly", clear_tests[i] ); +		 +		g_free( crypted ); +		g_free( decrypted ); +	} +} + +struct +{ +	unsigned char crypted[24]; +	int len; +	char *decrypted; +} decrypt_tests[] = { +	{ +		{ +			0xc3, 0x0d, 0x43, 0xc3, 0xee, 0x80, 0xe2, 0x8c, 0x0b, 0x29, 0x32, 0x7e, +			0x38, 0x05, 0x82, 0x10, 0x21, 0x1c, 0x4a, 0x00, 0x2c +		}, 21, "Debugging sucks" +	}, +	{ +		{ +			0xb0, 0x00, 0x57, 0x0d, 0x0d, 0x0d, 0x70, 0xe1, 0xc0, 0x00, 0xa4, 0x25, +			0x7d, 0xbe, 0x03, 0xcc, 0x24, 0xd1, 0x0c +		}, 19, "Testing rocks" +	}, +	{ +		{ +			0xb6, 0x92, 0x59, 0xe4, 0xf9, 0xc1, 0x7a, 0xf6, 0xf3, 0x18, 0xea, 0x28, +			0x73, 0x6d, 0xb3, 0x0a, 0x6f, 0x0a, 0x2b, 0x43, 0x57, 0xe9, 0x3e, 0x63 +		}, 24, "OSCAR is creepy..." +	} +}; + +static void check_decod(int l) +{ +	int i; +	 +	for( i = 0; clear_tests[i]; i++ ) +	{ +  		tcase_fn_start (decrypt_tests[i].decrypted, __FILE__, __LINE__); +		char *decrypted; +		int len; +		 +		len = arc_decode( decrypt_tests[i].crypted, decrypt_tests[i].len, +		                  &decrypted, password ); +		 +		fail_if( strcmp( decrypt_tests[i].decrypted, decrypted ) != 0, +		         "%s didn't decrypt properly", clear_tests[i] ); +		 +		g_free( decrypted ); +	} +} + +Suite *arc_suite (void) +{ +	Suite *s = suite_create("ArcFour"); +	TCase *tc_core = tcase_create("Core"); +	suite_add_tcase (s, tc_core); +	tcase_add_test (tc_core, check_codec); +	tcase_add_test (tc_core, check_decod); +	return s; +} diff --git a/tests/check_util.c b/tests/check_util.c index 284ddba3..b00d645b 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -103,6 +103,63 @@ START_TEST(test_set_url_username_pwd)  	fail_unless (url.port == 1080);  END_TEST +struct +{ +	char *orig; +	int line_len; +	char *wrapped; +} word_wrap_tests[] = { +	{ +		"Line-wrapping is not as easy as it seems?", +		16, +		"Line-wrapping is\nnot as easy as\nit seems?" +	}, +	{ +		"Line-wrapping is not as easy as it seems?", +		8, +		"Line-\nwrapping\nis not\nas easy\nas it\nseems?" +	}, +	{ +		"Line-wrapping is\nnot as easy as it seems?", +		8, +		"Line-\nwrapping\nis\nnot as\neasy as\nit\nseems?" +	}, +	{ +		"a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa", +		5, +		"a aa\naaa\naaaa\naaaaa\naaaaa\na\naaaaa\naa\naaaaa\naaa", +	}, +	{ +		"aaaaaaaa aaaaaaa aaaaaa aaaaa aaaa aaa aa a", +		5, +		"aaaaa\naaa\naaaaa\naa\naaaaa\na\naaaaa\naaaa\naaa\naa a", +	}, +	{ +		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +		5, +		"aaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\naaaaa\na", +	}, +	{ +		NULL +	} +}; + +START_TEST(test_word_wrap) +	int i; +	 +	for( i = 0; word_wrap_tests[i].orig && *word_wrap_tests[i].orig; i ++ ) +	{ +		char *wrapped = word_wrap( word_wrap_tests[i].orig, word_wrap_tests[i].line_len ); +		 +		fail_unless( strcmp( word_wrap_tests[i].wrapped, wrapped ) == 0, +		             "%s (line_len = %d) should wrap to `%s', not to `%s'", +		             word_wrap_tests[i].orig, word_wrap_tests[i].line_len, +		             word_wrap_tests[i].wrapped, wrapped ); +		 +		g_free( wrapped ); +	} +END_TEST +  Suite *util_suite (void)  {  	Suite *s = suite_create("Util"); @@ -115,5 +172,6 @@ Suite *util_suite (void)  	tcase_add_test (tc_core, test_set_url_port);  	tcase_add_test (tc_core, test_set_url_username);  	tcase_add_test (tc_core, test_set_url_username_pwd); +	tcase_add_test (tc_core, test_word_wrap);  	return s;  } @@ -46,19 +46,18 @@ int main( int argc, char *argv[], char **envp )  	memset( &global, 0, sizeof( global_t ) ); -	b_main_init();  	log_init(); -	nogaim_init(); -	 -	srand( time( NULL ) ^ getpid() ); -	  	CONF_FILE = g_strdup( CONF_FILE_DEF ); -	global.helpfile = g_strdup( HELP_FILE ); -	  	global.conf = conf_load( argc, argv );  	if( global.conf == NULL )  		return( 1 ); +	b_main_init(); +	nogaim_init(); +	 +	srand( time( NULL ) ^ getpid() ); +	global.helpfile = g_strdup( HELP_FILE ); +	  	if( global.conf->runmode == RUNMODE_INETD )  	{  		i = bitlbee_inetd_init(); | 
