aboutsummaryrefslogtreecommitdiffstats
path: root/storage_xml.c
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2012-06-04 14:55:58 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2012-06-04 14:55:58 +0100
commita338faa2e8262c62b3c871c547e91654c5d206ef (patch)
tree54c47844cf33ca4b95bbca089ecf4924bb9cbc2b /storage_xml.c
parent0153ba9a0dbed83fa98281f4d1ad34ad08e379b5 (diff)
Use xmltree to save user settings, in preparation for allowing other storage
media than local fs.
Diffstat (limited to 'storage_xml.c')
-rw-r--r--storage_xml.c148
1 files changed, 73 insertions, 75 deletions
diff --git a/storage_xml.c b/storage_xml.c
index 566d0021..57bc464c 100644
--- a/storage_xml.c
+++ b/storage_xml.c
@@ -1,7 +1,7 @@
/********************************************************************\
* BitlBee -- An IRC to other IM-networks gateway *
* *
- * Copyright 2002-2006 Wilmer van der Gaast and others *
+ * Copyright 2002-2012 Wilmer van der Gaast and others *
\********************************************************************/
/* Storage backend that uses an XMLish format for all data. */
@@ -28,6 +28,7 @@
#include "base64.h"
#include "arc.h"
#include "md5.h"
+#include "xmltree.h"
#include <glib/gstdio.h>
@@ -40,7 +41,7 @@ typedef enum
} xml_pass_st;
/* To make it easier later when extending the format: */
-#define XML_FORMAT_VERSION 1
+#define XML_FORMAT_VERSION "1"
struct xml_parsedata
{
@@ -421,54 +422,17 @@ static storage_status_t xml_check_pass( const char *my_nick, const char *passwor
return xml_load_real( NULL, my_nick, password, XML_PASS_CHECK_ONLY );
}
-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 );
-
- len = strlen( out );
- len -= write( fd, out, len );
- g_free( out );
-
- return len == 0;
-}
-
static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data );
-static storage_status_t xml_save( irc_t *irc, int overwrite )
+struct xt_node *xml_generate( irc_t *irc )
{
- char path[512], *path2, *pass_buf = NULL;
+ char *pass_buf = NULL;
set_t *set;
account_t *acc;
- int fd;
md5_byte_t pass_md5[21];
md5_state_t md5_state;
GSList *l;
-
- path2 = g_strdup( irc->user->nick );
- nick_lc( path2 );
- g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" );
- g_free( path2 );
-
- if( !overwrite && g_access( path, F_OK ) == 0 )
- return STORAGE_ALREADY_EXISTS;
-
- strcat( path, ".XXXXXX" );
- if( ( fd = mkstemp( path ) ) < 0 )
- {
- irc_rootmsg( irc, "Error while opening configuration file." );
- return STORAGE_OTHER_ERROR;
- }
+ struct xt_node *root, *cur;
/* Generate a salted md5sum of the password. Use 5 bytes for the salt
(to prevent dictionary lookups of passwords) to end up with a 21-
@@ -481,15 +445,20 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
/* Save the hash in base64-encoded form. */
pass_buf = base64_encode( pass_md5, 21 );
- if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->user->nick, pass_buf, XML_FORMAT_VERSION ) )
- goto write_error;
+ root = cur = xt_new_node( "user", NULL, NULL );
+ xt_add_attr( cur, "nick", irc->user->nick );
+ xt_add_attr( cur, "password", pass_buf );
+ xt_add_attr( cur, "version", XML_FORMAT_VERSION );
g_free( pass_buf );
for( set = irc->b->set; set; set = set->next )
if( set->value && !( set->flags & SET_NOSAVE ) )
- if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
- goto write_error;
+ {
+ struct xt_node *xset;
+ xt_add_child( cur, xset = xt_new_node( "setting", set->value, NULL ) );
+ xt_add_attr( xset, "name", set->key );
+ }
for( acc = irc->b->accounts; acc; acc = acc->next )
{
@@ -501,24 +470,24 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
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\" tag=\"%s\"", acc->prpl->name, acc->user,
- pass_b64, acc->auto_connect, acc->tag ) )
- {
- g_free( pass_b64 );
- goto write_error;
- }
- g_free( pass_b64 );
+ cur = xt_new_node( "account", NULL, NULL );
+ xt_add_attr( cur, "protocol", acc->prpl->name );
+ xt_add_attr( cur, "handle", acc->user );
+ xt_add_attr( cur, "password", pass_b64 );
+ xt_add_attr( cur, "autoconnect", acc->auto_connect ? "true" : "false" );
+ xt_add_attr( cur, "tag", acc->tag );
+ if( acc->server && acc->server[0] )
+ xt_add_attr( cur, "server", acc->server );
- if( acc->server && acc->server[0] && !xml_printf( fd, 0, " server=\"%s\"", acc->server ) )
- goto write_error;
- if( !xml_printf( fd, 0, ">\n" ) )
- goto write_error;
+ g_free( pass_b64 );
for( set = acc->set; set; set = set->next )
if( set->value && !( set->flags & ACC_SET_NOSAVE ) )
- if( !xml_printf( fd, 2, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
- goto write_error;
+ {
+ struct xt_node *xset;
+ xt_add_child( cur, xset = xt_new_node( "setting", set->value, NULL ) );
+ xt_add_attr( xset, "name", set->key );
+ }
/* This probably looks pretty strange. g_hash_table_foreach
is quite a PITA already (but it can't get much better in
@@ -527,11 +496,9 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
errors, so instead let's use the _find function and
return TRUE on write errors. Which means, if we found
something, there was an error. :-) */
- if( g_hash_table_find( acc->nicks, xml_save_nick, & fd ) )
- goto write_error;
+ g_hash_table_find( acc->nicks, xml_save_nick, cur );
- if( !xml_printf( fd, 1, "</account>\n" ) )
- goto write_error;
+ xt_add_child( root, cur );
}
for( l = irc->channels; l; l = l->next )
@@ -541,21 +508,48 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
if( ic->flags & IRC_CHANNEL_TEMP )
continue;
- if( !xml_printf( fd, 1, "<channel name=\"%s\" type=\"%s\">\n",
- ic->name, set_getstr( &ic->set, "type" ) ) )
- goto write_error;
+ cur = xt_new_node( "channel", NULL, NULL );
+ xt_add_attr( cur, "name", ic->name );
+ xt_add_attr( cur, "type", set_getstr( &ic->set, "type" ) );
for( set = ic->set; set; set = set->next )
if( set->value && strcmp( set->key, "type" ) != 0 )
- if( !xml_printf( fd, 2, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
- goto write_error;
+ {
+ struct xt_node *xset;
+ xt_add_child( cur, xset = xt_new_node( "setting", set->value, NULL ) );
+ xt_add_attr( xset, "name", set->key );
+ }
- if( !xml_printf( fd, 1, "</channel>\n" ) )
- goto write_error;
+ xt_add_child( root, cur );
+ }
+
+ return root;
+}
+
+static storage_status_t xml_save( irc_t *irc, int overwrite )
+{
+ char path[512], *path2, *xml;
+ struct xt_node *tree;
+ int fd;
+
+ path2 = g_strdup( irc->user->nick );
+ nick_lc( path2 );
+ g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" );
+ g_free( path2 );
+
+ if( !overwrite && g_access( path, F_OK ) == 0 )
+ return STORAGE_ALREADY_EXISTS;
+
+ strcat( path, ".XXXXXX" );
+ if( ( fd = mkstemp( path ) ) < 0 )
+ {
+ irc_rootmsg( irc, "Error while opening configuration file." );
+ return STORAGE_OTHER_ERROR;
}
- if( !xml_printf( fd, 0, "</user>\n" ) )
- goto write_error;
+ tree = xml_generate( irc );
+ xml = xt_to_string( tree );
+ write( fd, xml, strlen( xml ) );
fsync( fd );
close( fd );
@@ -576,7 +570,6 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
return STORAGE_OK;
write_error:
- g_free( pass_buf );
irc_rootmsg( irc, "Write error. Disk full?" );
close( fd );
@@ -586,7 +579,12 @@ write_error:
static gboolean xml_save_nick( gpointer key, gpointer value, gpointer data )
{
- return !xml_printf( *( (int*) data ), 2, "<buddy handle=\"%s\" nick=\"%s\" />\n", key, value );
+ struct xt_node *node = xt_new_node( "buddy", NULL, NULL );
+ xt_add_attr( node, "handle", key );
+ xt_add_attr( node, "nick", value );
+ xt_add_child( (struct xt_node *) data, node );
+
+ return FALSE;
}
static storage_status_t xml_remove( const char *nick, const char *password )