aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--account.c123
-rw-r--r--account.h9
-rw-r--r--bitlbee.h5
-rw-r--r--conf.c7
-rwxr-xr-xconfigure2
-rw-r--r--doc/CHANGES21
-rw-r--r--doc/user-guide/commands.xml10
-rw-r--r--ipc.c35
-rw-r--r--ipc.h3
-rw-r--r--irc.c79
-rw-r--r--irc_commands.c1
-rw-r--r--lib/ssl_bogus.c5
-rw-r--r--protocols/jabber/jabber.c2
-rw-r--r--protocols/jabber/jabber_util.c4
-rw-r--r--protocols/msn/msn.c61
-rw-r--r--protocols/msn/msn.h6
-rw-r--r--protocols/msn/ns.c23
-rw-r--r--protocols/msn/sb.c42
-rw-r--r--protocols/nogaim.c10
-rw-r--r--protocols/yahoo/libyahoo2.c2
-rw-r--r--protocols/yahoo/yahoo.c3
-rw-r--r--protocols/yahoo/yahoo_httplib.c2
-rw-r--r--root_commands.c91
-rw-r--r--set.c55
-rw-r--r--set.h10
-rw-r--r--sock.h8
-rw-r--r--storage.c37
-rw-r--r--storage.h8
-rw-r--r--storage_text.c21
-rw-r--r--storage_xml.c26
-rw-r--r--unix.c16
32 files changed, 445 insertions, 284 deletions
diff --git a/Makefile b/Makefile
index 6c8e289f..9a495283 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/account.c b/account.c
index 2c6e1069..f3e15d7e 100644
--- a/account.c
+++ b/account.c
@@ -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;
+}
diff --git a/account.h b/account.h
index a81ca928..cf22482c 100644
--- a/account.h
+++ b/account.h
@@ -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
diff --git a/bitlbee.h b/bitlbee.h
index f11d275d..5543b501 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -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
diff --git a/conf.c b/conf.c
index bd7d5b6a..d930b26d 100644
--- a/conf.c
+++ b/conf.c
@@ -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 );
diff --git a/configure b/configure
index bb22c4cc..2287b2ad 100755
--- a/configure
+++ b/configure
@@ -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&lt;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 &quot;10*10&quot;, 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 &lt; you can give a maximum delay.
</para>
<para>
diff --git a/ipc.c b/ipc.c
index d6b850f1..f853a18f 100644
--- a/ipc.c
+++ b/ipc.c
@@ -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 )
diff --git a/ipc.h b/ipc.h
index 0e71c520..f3d24614 100644
--- a/ipc.h
+++ b/ipc.h
@@ -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;
diff --git a/irc.c b/irc.c
index d0b184fc..f32ae21a 100644
--- a/irc.c
+++ b/irc.c
@@ -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!" );
diff --git a/set.c b/set.c
index b18d7cc8..764ca8b7 100644
--- a/set.c
+++ b/set.c
@@ -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;
}
+
diff --git a/set.h b/set.h
index 988429ff..05f879c0 100644
--- a/set.h
+++ b/set.h
@@ -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 );
diff --git a/sock.h b/sock.h
index 848dc466..c3c0428e 100644
--- a/sock.h
+++ b/sock.h
@@ -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)
diff --git a/storage.c b/storage.c
index 6a62af83..0ff2d34d 100644
--- a/storage.c
+++ b/storage.c
@@ -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
diff --git a/storage.h b/storage.h
index d114dec4..f2e9afce 100644
--- a/storage.h
+++ b/storage.h
@@ -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" );
diff --git a/unix.c b/unix.c
index 6fc85dbb..8a828eec 100644
--- a/unix.c
+++ b/unix.c
@@ -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 );
}
-
-