aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2006-07-01 17:52:05 +0200
committerWilmer van der Gaast <wilmer@gaast.net>2006-07-01 17:52:05 +0200
commit5100caa16bb707d89f1873aca99b5f87abc1dd56 (patch)
treecb07ef3e313f9d6f4f5feb2231176c5e9a2a7a2a
parent0a3c243b6659dc10efb227e507f324c2711d6dcd (diff)
Added "account set" command.
-rw-r--r--account.c60
-rw-r--r--account.h5
-rw-r--r--lib/misc.c34
-rw-r--r--lib/misc.h3
-rw-r--r--lib/rc4.c2
-rw-r--r--root_commands.c69
-rw-r--r--set.c18
-rw-r--r--set.h4
-rw-r--r--storage_xml.c65
9 files changed, 220 insertions, 40 deletions
diff --git a/account.c b/account.c
index ced62e25..4e399e8a 100644
--- a/account.c
+++ b/account.c
@@ -27,9 +27,12 @@
#include "bitlbee.h"
#include "account.h"
+char *set_eval_account( set_t *set, char *value );
+
account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass )
{
account_t *a;
+ set_t *s;
if( irc->accounts )
{
@@ -47,9 +50,63 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass )
a->auto_connect = 1;
a->irc = irc;
+ s = set_add( &a->set, "auto_connect", NULL, set_eval_account, a );
+ s->flags |= ACC_SET_NOSAVE;
+
+ s = set_add( &a->set, "password", NULL, set_eval_account, a );
+ s->flags |= ACC_SET_NOSAVE;
+
+ s = set_add( &a->set, "server", NULL, set_eval_account, a );
+ s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
+
+ s = set_add( &a->set, "username", NULL, set_eval_account, a );
+ s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
+ set_setstr( &a->set, "username", user );
+
return( a );
}
+char *set_eval_account( set_t *set, char *value )
+{
+ account_t *acc = set->data;
+
+ /* Double-check: We refuse to edit on-line accounts. */
+ if( acc->gc )
+ return NULL;
+
+ if( strcmp( set->key, "username" ) == 0 )
+ {
+ g_free( acc->user );
+ acc->user = g_strdup( value );
+ return 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 )
+ acc->server = g_strdup( value );
+ else
+ acc->server = NULL;
+ return value;
+ }
+ else if( strcmp( set->key, "auto_connect" ) == 0 )
+ {
+ if( !is_bool( value ) )
+ return NULL;
+
+ acc->auto_connect = bool2int( value );
+ return value;
+ }
+
+ return NULL;
+}
+
account_t *account_get( irc_t *irc, char *id )
{
account_t *a, *ret = NULL;
@@ -129,6 +186,9 @@ void account_del( irc_t *irc, account_t *acc )
irc->accounts = a->next;
}
+ while( a->set )
+ set_del( &a->set, a->set->key );
+
g_free( a->user );
g_free( a->pass );
if( a->server ) g_free( a->server );
diff --git a/account.h b/account.h
index 40efb101..9fed399e 100644
--- a/account.h
+++ b/account.h
@@ -36,6 +36,8 @@ typedef struct account
int auto_connect;
int reconnect;
+ set_t *set;
+
struct irc *irc;
struct gaim_connection *gc;
struct account *next;
@@ -47,4 +49,7 @@ void account_del( irc_t *irc, account_t *acc );
void account_on( irc_t *irc, account_t *a );
void account_off( irc_t *irc, account_t *a );
+#define ACC_SET_NOSAVE 1
+#define ACC_SET_OFFLINE_ONLY 2
+
#endif
diff --git a/lib/misc.c b/lib/misc.c
index 784d80d6..17599946 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -485,3 +485,37 @@ void random_bytes( unsigned char *buf, int count )
buf[i] = rand() & 0xff;
}
}
+
+int is_bool( char *value )
+{
+ if( *value == 0 )
+ return 0;
+
+ if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) )
+ return 1;
+ if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) )
+ return 1;
+
+ while( *value )
+ if( !isdigit( *value ) )
+ return 0;
+ else
+ value ++;
+
+ return 1;
+}
+
+int bool2int( char *value )
+{
+ int i;
+
+ if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) )
+ return 1;
+ if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) )
+ return 0;
+
+ if( sscanf( value, "%d", &i ) == 1 )
+ return i;
+
+ return 0;
+}
diff --git a/lib/misc.h b/lib/misc.h
index 57ff3e37..b021e642 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -50,4 +50,7 @@ G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char
G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count );
+G_MODULE_EXPORT int is_bool( char *value );
+G_MODULE_EXPORT int bool2int( char *value );
+
#endif
diff --git a/lib/rc4.c b/lib/rc4.c
index 86b74ef5..5e334507 100644
--- a/lib/rc4.c
+++ b/lib/rc4.c
@@ -164,7 +164,7 @@ int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char
if( clear_len < 0 )
{
- *clear = g_strdup( "" );
+ *clear = (unsigned char*) g_strdup( "" );
return 0;
}
diff --git a/root_commands.c b/root_commands.c
index 3bd80e5e..b975b0f4 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -231,9 +231,8 @@ static void cmd_account( irc_t *irc, char **cmd )
}
a = account_add( irc, prpl, cmd[3], cmd[4] );
-
if( cmd[5] )
- a->server = g_strdup( cmd[5] );
+ set_setstr( &a->set, "server", cmd[5] );
irc_usermsg( irc, "Account successfully added" );
}
@@ -357,6 +356,68 @@ static void cmd_account( irc_t *irc, char **cmd )
return;
}
}
+ else if( g_strcasecmp( cmd[1], "set" ) == 0 )
+ {
+ char *acc_handle, *set_name = NULL, *tmp;
+
+ if( !cmd[2] )
+ {
+ irc_usermsg( irc, "Not enough parameters given (need %d)", 2 );
+ return;
+ }
+
+ acc_handle = g_strdup( cmd[2] );
+ if( ( tmp = strchr( acc_handle, '/' ) ) )
+ {
+ *tmp = 0;
+ set_name = tmp + 1;
+ }
+ a = account_get( irc, acc_handle );
+
+ if( a == NULL )
+ {
+ irc_usermsg( irc, "Invalid account" );
+ return;
+ }
+
+ if( cmd[3] )
+ {
+ set_t *s = set_find( &a->set, set_name );
+
+ if( a->gc && s && s->flags & ACC_SET_OFFLINE_ONLY )
+ {
+ irc_usermsg( irc, "This setting can only be changed when the account is off-line" );
+ return;
+ }
+
+ set_setstr( &a->set, set_name, cmd[3] );
+
+ if( ( strcmp( cmd[3], "=" ) ) == 0 && cmd[4] )
+ irc_usermsg( irc, "Warning: Correct syntax: \002account set <variable> <value>\002 (without =)" );
+ }
+ if( set_name ) /* else 'forgotten' on purpose.. Must show new value after changing */
+ {
+ 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 );
+ }
+ 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 );
+ s = s->next;
+ }
+ }
+
+ g_free( acc_handle );
+ }
else
{
irc_usermsg( irc, "Unknown command: account %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[1] );
@@ -681,6 +742,8 @@ static void cmd_set( irc_t *irc, char **cmd )
char *s = set_getstr( &irc->set, cmd[1] );
if( s )
irc_usermsg( irc, "%s = `%s'", cmd[1], s );
+ else
+ irc_usermsg( irc, "%s is empty", cmd[1] );
}
else
{
@@ -689,6 +752,8 @@ static void cmd_set( irc_t *irc, char **cmd )
{
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 );
s = s->next;
}
}
diff --git a/set.c b/set.c
index b511a358..4620264f 100644
--- a/set.c
+++ b/set.c
@@ -100,6 +100,16 @@ int set_getint( set_t **head, char *key )
return i;
}
+int set_getbool( set_t **head, char *key )
+{
+ char *s = set_getstr( head, key );
+
+ if( !s )
+ return 0;
+
+ return bool2int( s );
+}
+
int set_setstr( set_t **head, char *key, char *value )
{
set_t *s = set_find( head, key );
@@ -165,7 +175,7 @@ char *set_eval_int( set_t *set, char *value )
char *s;
for( s = value; *s; s ++ )
- if( *s < '0' || *s > '9' )
+ if( !isdigit( *s ) )
return NULL;
return value;
@@ -173,11 +183,7 @@ char *set_eval_int( set_t *set, char *value )
char *set_eval_bool( set_t *set, char *value )
{
- if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) )
- return( value );
- if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) )
- return( value );
- return( set_eval_int( set, value ) );
+ return is_bool( value ) ? value : NULL;
}
char *set_eval_to_char( set_t *set, char *value )
diff --git a/set.h b/set.h
index 15e97b5d..4731f80a 100644
--- a/set.h
+++ b/set.h
@@ -31,6 +31,8 @@ typedef struct set
char *value;
char *def; /* Default */
+ int flags;
+
/* Eval: Returns NULL 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! */
@@ -39,7 +41,7 @@ typedef struct set
} set_t;
set_t *set_add( set_t **head, char *key, char *def, void *eval, void *data );
-G_MODULE_EXPORT set_t *set_find( set_t **head, char *key );
+set_t *set_find( set_t **head, char *key );
G_MODULE_EXPORT char *set_getstr( set_t **head, char *key );
G_MODULE_EXPORT int set_getint( set_t **head, char *key );
int set_setstr( set_t **head, char *key, char *value );
diff --git a/storage_xml.c b/storage_xml.c
index e0ffc481..701d5144 100644
--- a/storage_xml.c
+++ b/storage_xml.c
@@ -156,11 +156,9 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na
{
xd->current_account = account_add( irc, prpl, handle, password );
if( server )
- xd->current_account->server = g_strdup( server );
+ set_setstr( &xd->current_account->set, "server", server );
if( autoconnect )
- /* Return value doesn't matter, since account_add() already sets
- a default! */
- sscanf( autoconnect, "%d", &xd->current_account->auto_connect );
+ set_setstr( &xd->current_account->set, "auto_connect", autoconnect );
}
else
{
@@ -175,22 +173,19 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na
}
else if( g_strcasecmp( element_name, "setting" ) == 0 )
{
- if( xd->current_account == NULL )
+ char *setting;
+
+ if( xd->current_setting )
{
- char *setting;
-
- if( xd->current_setting )
- {
- g_free( xd->current_setting );
- xd->current_setting = NULL;
- }
-
- if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) )
- xd->current_setting = g_strdup( setting );
- else
- g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
- "Missing attributes for %s element", element_name );
+ g_free( xd->current_setting );
+ xd->current_setting = NULL;
}
+
+ if( ( setting = xml_attr( attr_names, attr_values, "name" ) ) )
+ xd->current_setting = g_strdup( setting );
+ else
+ g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "Missing attributes for %s element", element_name );
}
else if( g_strcasecmp( element_name, "buddy" ) == 0 )
{
@@ -242,10 +237,10 @@ static void xml_text( GMarkupParseContext *ctx, const gchar *text, gsize text_le
the password, or if we didn't get the chance to check it
yet. */
}
- else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 &&
- xd->current_setting && xd->current_account == NULL )
+ else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting )
{
- set_setstr( &irc->set, xd->current_setting, (char*) text );
+ set_setstr( xd->current_account ? &xd->current_account->set : &irc->set,
+ xd->current_setting, (char*) text );
g_free( xd->current_setting );
xd->current_setting = NULL;
}
@@ -347,12 +342,17 @@ static storage_status_t xml_check_pass( const char *my_nick, const char *passwor
return xml_load_real( my_nick, password, NULL, XML_PASS_CHECK_ONLY );
}
-static int xml_printf( int fd, char *fmt, ... )
+static int xml_printf( int fd, int indent, char *fmt, ... )
{
va_list params;
char *out;
+ char tabs[9] = "\t\t\t\t\t\t\t\t";
int len;
+ /* Maybe not very clean, but who needs more than 8 levels of indentation anyway? */
+ if( write( fd, tabs, indent <= 8 ? indent : 8 ) != indent )
+ return 0;
+
va_start( params, fmt );
out = g_markup_vprintf_escaped( fmt, params );
va_end( params );
@@ -403,14 +403,14 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
/* Save the hash in base64-encoded form. */
pass_buf = base64_encode( (char*) pass_md5, 21 );
- if( !xml_printf( fd, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )
+ if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )
goto write_error;
g_free( pass_buf );
for( set = irc->set; set; set = set->next )
if( set->value && set->def )
- if( !xml_printf( fd, "\t<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
+ if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
goto write_error;
for( acc = irc->accounts; acc; acc = acc->next )
@@ -422,28 +422,33 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
pass_b64 = base64_encode( pass_rc4, pass_len );
g_free( pass_rc4 );
- if( !xml_printf( fd, "\t<account protocol=\"%s\" handle=\"%s\" password=\"%s\" autoconnect=\"%d\"", acc->prpl->name, acc->user, pass_b64, acc->auto_connect ) )
+ if( !xml_printf( fd, 1, "<account protocol=\"%s\" handle=\"%s\" password=\"%s\" autoconnect=\"%d\"", acc->prpl->name, acc->user, pass_b64, acc->auto_connect ) )
{
g_free( pass_b64 );
goto write_error;
}
g_free( pass_b64 );
- if( acc->server && acc->server[0] && !xml_printf( fd, " server=\"%s\"", acc->server ) )
+ if( acc->server && acc->server[0] && !xml_printf( fd, 0, " server=\"%s\"", acc->server ) )
goto write_error;
- if( !xml_printf( fd, ">\n" ) )
+ if( !xml_printf( fd, 0, ">\n" ) )
goto write_error;
+ for( set = acc->set; set; set = set->next )
+ if( set->value && set->def && !( set->flags & ACC_SET_NOSAVE ) )
+ if( !xml_printf( fd, 2, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
+ goto write_error;
+
for( nick = irc->nicks; nick; nick = nick->next )
if( nick->proto == acc->prpl )
- if( !xml_printf( fd, "\t\t<buddy handle=\"%s\" nick=\"%s\" />\n", nick->handle, nick->nick ) )
+ if( !xml_printf( fd, 2, "<buddy handle=\"%s\" nick=\"%s\" />\n", nick->handle, nick->nick ) )
goto write_error;
- if( !xml_printf( fd, "\t</account>\n" ) )
+ if( !xml_printf( fd, 1, "</account>\n" ) )
goto write_error;
}
- if( !xml_printf( fd, "</user>\n" ) )
+ if( !xml_printf( fd, 0, "</user>\n" ) )
goto write_error;
close( fd );