diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2006-07-03 23:22:45 +0200 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2006-07-03 23:22:45 +0200 |
commit | 5b52a4895e5a59ff6509f7771f4d8665737688c3 (patch) | |
tree | 32c13033b127804864507d8ff90c0c274f8b07e5 | |
parent | 911f2eb7060f6af6fe8e4e02144cfb7c4bb4cc8b (diff) |
Implemented per-account nick lists instead of per-protocol nick lists.
nick_t is dead, instead nicks are just saves in a per-account_t GLib
hash table. While doing this, the import_buddies command finally died
and text_save() disappeared, because the old file format can't handle
most of the new features in this branch anyway.
Still have to implement support for the new nick lists in text_load()!
-rw-r--r-- | account.c | 6 | ||||
-rw-r--r-- | account.h | 1 | ||||
-rw-r--r-- | bitlbee.h | 1 | ||||
-rw-r--r-- | irc.c | 43 | ||||
-rw-r--r-- | irc.h | 2 | ||||
-rw-r--r-- | irc_commands.c | 3 | ||||
-rw-r--r-- | nick.c | 111 | ||||
-rw-r--r-- | nick.h | 14 | ||||
-rw-r--r-- | protocols/jabber/jabber.c | 2 | ||||
-rw-r--r-- | protocols/msn/msn.c | 2 | ||||
-rw-r--r-- | protocols/nogaim.c | 14 | ||||
-rw-r--r-- | protocols/nogaim.h | 2 | ||||
-rw-r--r-- | protocols/oscar/oscar.c | 3 | ||||
-rw-r--r-- | protocols/yahoo/yahoo.c | 3 | ||||
-rw-r--r-- | root_commands.c | 59 | ||||
-rw-r--r-- | storage_text.c | 178 | ||||
-rw-r--r-- | storage_xml.c | 23 | ||||
-rw-r--r-- | user.c | 26 |
18 files changed, 118 insertions, 375 deletions
@@ -58,6 +58,8 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass ) s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY; set_setstr( &a->set, "username", user ); + a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); + /* This function adds some more settings (and might want to do more things that have to be done now, although I can't think of anything. */ if( prpl->acc_init ) @@ -125,7 +127,7 @@ account_t *account_get( irc_t *irc, char *id ) { for( a = irc->accounts; a; a = a->next ) if( a->prpl == proto && - a->prpl->cmp_buddynames( handle, a->user ) == 0 ) + a->prpl->handle_cmp( handle, a->user ) == 0 ) ret = a; } @@ -189,6 +191,8 @@ void account_del( irc_t *irc, account_t *acc ) while( a->set ) set_del( &a->set, a->set->key ); + g_hash_table_destroy( a->nicks ); + g_free( a->user ); g_free( a->pass ); if( a->server ) g_free( a->server ); @@ -37,6 +37,7 @@ typedef struct account int reconnect; set_t *set; + GHashTable *nicks; struct irc *irc; struct gaim_connection *gc; @@ -123,6 +123,7 @@ extern char *CONF_FILE; #include "nogaim.h" #include "commands.h" #include "account.h" +#include "nick.h" #include "conf.h" #include "log.h" #include "ini.h" @@ -203,11 +203,9 @@ static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) /* Because we have no garbage collection, this is quite annoying */ void irc_free(irc_t * irc) { - account_t *account, *accounttmp; + account_t *account; user_t *user, *usertmp; - nick_t *nick, *nicktmp; help_t *helpnode, *helpnodetmp; - set_t *setnode, *setnodetmp; log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); @@ -251,17 +249,11 @@ void irc_free(irc_t * irc) while (irc->queries != NULL) query_del(irc, irc->queries); - if (irc->accounts != NULL) { - account = irc->accounts; - while (account != NULL) { - g_free(account->user); - g_free(account->pass); - g_free(account->server); - accounttmp = account; - account = account->next; - g_free(accounttmp); - } - } + while (irc->accounts) + account_del(irc, irc->accounts); + + while (irc->set) + set_del(&irc->set, irc->set->key); if (irc->users != NULL) { user = irc->users; @@ -286,17 +278,6 @@ void irc_free(irc_t * irc) g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); g_hash_table_destroy(irc->watches); - if (irc->nicks != NULL) { - nick = irc->nicks; - while (nick != NULL) { - g_free(nick->nick); - g_free(nick->handle); - - nicktmp = nick; - nick = nick->next; - g_free(nicktmp); - } - } if (irc->help != NULL) { helpnode = irc->help; while (helpnode != NULL) { @@ -307,18 +288,6 @@ void irc_free(irc_t * irc) g_free(helpnodetmp); } } - if (irc->set != NULL) { - setnode = irc->set; - while (setnode != NULL) { - g_free(setnode->key); - g_free(setnode->def); - g_free(setnode->value); - - setnodetmp = setnode; - setnode = setnode->next; - g_free(setnodetmp); - } - } g_free(irc); if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON ) @@ -97,7 +97,7 @@ typedef struct irc } irc_t; #include "user.h" -#include "nick.h" +// #include "nick.h" extern GSList *irc_connection_list; diff --git a/irc_commands.c b/irc_commands.c index 889de9da..47d9e8cb 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -477,7 +477,8 @@ static void irc_cmd_whois( irc_t *irc, char **cmd ) if( u->gc ) irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->acc->user, - *u->gc->acc->server ? u->gc->acc->server : "", u->gc->acc->prpl->name ); + u->gc->acc->server && *u->gc->acc->server ? u->gc->acc->server : "", + u->gc->acc->prpl->name ); else irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO ); @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2006 Wilmer van der Gaast and others * \********************************************************************/ /* Some stuff to fetch, save and handle nicknames for your buddies */ @@ -26,50 +26,48 @@ #define BITLBEE_CORE #include "bitlbee.h" -void nick_set( irc_t *irc, const char *handle, struct prpl *proto, const char *nick ) +/* Store handles in lower case and strip spaces, because AIM is braindead. */ +static char *clean_handle( const char *orig ) { - nick_t *m = NULL, *n = irc->nicks; + char *new = g_malloc( strlen( orig ) + 1 ); + int i = 0; - while( n ) - { - if( ( g_strcasecmp( n->handle, handle ) == 0 ) && n->proto == proto ) - { - g_free( n->nick ); - n->nick = nick_dup( nick ); - nick_strip( n->nick ); - - return; - } - n = ( m = n )->next; // :-P + do { + if (*orig != ' ') + new[i++] = tolower( *orig ); } + while (*(orig++)); - if( m ) - n = m->next = g_new0( nick_t, 1 ); - else - n = irc->nicks = g_new0( nick_t, 1 ); + return new; +} + +void nick_set( account_t *acc, const char *handle, const char *nick ) +{ + char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 ); - n->handle = g_strdup( handle ); - n->proto = proto; - n->nick = nick_dup( nick ); + store_handle = clean_handle( handle ); + strncpy( store_nick, nick, MAX_NICK_LENGTH ); + nick_strip( store_nick ); - nick_strip( n->nick ); + g_hash_table_replace( acc->nicks, store_handle, store_nick ); } -char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *realname ) +char *nick_get( account_t *acc, const char *handle, const char *realname ) { static char nick[MAX_NICK_LENGTH+1]; - nick_t *n = irc->nicks; + char *store_handle, *found_nick; int inf_protection = 256; memset( nick, 0, MAX_NICK_LENGTH + 1 ); - while( n && !*nick ) - if( ( n->proto == proto ) && ( g_strcasecmp( n->handle, handle ) == 0 ) ) - strcpy( nick, n->nick ); - else - n = n->next; - - if( !n ) + store_handle = clean_handle( handle ); + /* Find out if we stored a nick for this person already. If not, try + to generate a sane nick automatically. */ + if( ( found_nick = g_hash_table_lookup( acc->nicks, store_handle ) ) ) + { + strncpy( nick, found_nick, MAX_NICK_LENGTH ); + } + else { char *s; @@ -85,11 +83,14 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * g_snprintf( nick, MAX_NICK_LENGTH, "%s", realname ); nick_strip( nick ); - if( set_getint( &irc->set, "lcnicks" ) ) + if( set_getbool( &acc->irc->set, "lcnicks" ) ) nick_lc( nick ); } + g_free( store_handle ); - while( !nick_ok( nick ) || user_find( irc, nick ) ) + /* Now, find out if the nick is already in use at the moment, and make + subtle changes to make it unique. */ + while( !nick_ok( nick ) || user_find( acc->irc, nick ) ) { if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) { @@ -105,19 +106,19 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * { int i; - irc_usermsg( irc, "WARNING: Almost had an infinite loop in nick_get()! " - "This used to be a fatal BitlBee bug, but we tried to fix it. " - "This message should *never* appear anymore. " - "If it does, please *do* send us a bug report! " - "Please send all the following lines in your report:" ); + irc_usermsg( acc->irc, "WARNING: Almost had an infinite loop in nick_get()! " + "This used to be a fatal BitlBee bug, but we tried to fix it. " + "This message should *never* appear anymore. " + "If it does, please *do* send us a bug report! " + "Please send all the following lines in your report:" ); - irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle ); + irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle ); for( i = 0; i < MAX_NICK_LENGTH; i ++ ) - irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] ); + irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] ); - irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. " - "Good luck, and please don't forget to paste the lines up here " - "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); + irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. " + "Good luck, and please don't forget to paste the lines up here " + "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" ); g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); @@ -125,30 +126,12 @@ char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char * } } - return( nick ); + return nick; } -void nick_del( irc_t *irc, const char *nick ) +void nick_del( account_t *acc, const char *handle ) { - nick_t *l = NULL, *n = irc->nicks; - - while( n ) - { - if( g_strcasecmp( n->nick, nick ) == 0 ) - { - if( l ) - l->next = n->next; - else - irc->nicks = n->next; - - g_free( n->handle ); - g_free( n->nick ); - g_free( n ); - - break; - } - n = (l=n)->next; - } + g_hash_table_remove( acc->nicks, handle ); } @@ -23,17 +23,9 @@ Suite 330, Boston, MA 02111-1307 USA */ -typedef struct __NICK -{ - char *handle; - struct prpl *proto; - char *nick; - struct __NICK *next; -} nick_t; - -void nick_set( irc_t *irc, const char *handle, struct prpl *proto, const char *nick ); -char *nick_get( irc_t *irc, const char *handle, struct prpl *proto, const char *realname ); -void nick_del( irc_t *irc, const char *nick ); +void nick_set( account_t *acc, const char *handle, const char *nick ); +char *nick_get( account_t *acc, const char *handle, const char *realname ); +void nick_del( account_t *acc, const char *handle ); void nick_strip( char *nick ); int nick_ok( const char *nick ); diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index e7f4534e..7147a78c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -2379,7 +2379,7 @@ void jabber_init() ret->keepalive = jabber_keepalive; ret->alias_buddy = jabber_roster_update; ret->group_buddy = jabber_group_change; - ret->cmp_buddynames = g_strcasecmp; + ret->handle_cmp = g_strcasecmp; register_protocol (ret); } diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 790b372a..db4563dc 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -431,7 +431,7 @@ void msn_init() ret->add_deny = msn_add_deny; ret->rem_deny = msn_rem_deny; ret->send_typing = msn_send_typing; - ret->cmp_buddynames = g_strcasecmp; + ret->handle_cmp = g_strcasecmp; register_protocol(ret); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 8346f5fa..54965b84 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -365,7 +365,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea } memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( gc->irc, handle, gc->acc->prpl, realname ) ); + strcpy( nick, nick_get( gc->acc, handle, realname ) ); u = user_add( gc->irc, nick ); @@ -377,7 +377,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea u->host = g_strdup( s + 1 ); u->user = g_strndup( handle, s - handle ); } - else if( *gc->acc->server ) + else if( gc->acc->server ) { char *colon; @@ -777,7 +777,7 @@ void add_chat_buddy( struct conversation *b, char *handle ) serv_got_crap( b->gc, "User %s added to conversation %d", handle, b->id ); /* It might be yourself! */ - if( b->gc->acc->prpl->cmp_buddynames( handle, b->gc->username ) == 0 ) + if( b->gc->acc->prpl->handle_cmp( handle, b->gc->username ) == 0 ) { u = user_find( b->gc->irc, b->gc->irc->nick ); if( !b->joined ) @@ -1061,7 +1061,7 @@ static char *bim_away_alias_find( GList *gcm, char *away ) void bim_add_allow( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) { gc->permit = g_slist_prepend( gc->permit, g_strdup( handle ) ); } @@ -1073,7 +1073,7 @@ void bim_rem_allow( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); gc->permit = g_slist_delete_link( gc->permit, l ); @@ -1084,7 +1084,7 @@ void bim_rem_allow( struct gaim_connection *gc, char *handle ) void bim_add_block( struct gaim_connection *gc, char *handle ) { - if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) == NULL ) + if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) == NULL ) { gc->deny = g_slist_prepend( gc->deny, g_strdup( handle ) ); } @@ -1096,7 +1096,7 @@ void bim_rem_block( struct gaim_connection *gc, char *handle ) { GSList *l; - if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->cmp_buddynames ) ) ) + if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->acc->prpl->handle_cmp ) ) ) { g_free( l->data ); gc->deny = g_slist_delete_link( gc->deny, l ); diff --git a/protocols/nogaim.h b/protocols/nogaim.h index c0a867d6..bae4489f 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -164,7 +164,7 @@ struct prpl { GList *(* away_states)(struct gaim_connection *gc); /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */ - int (* cmp_buddynames) (const char *who1, const char *who2); + int (* handle_cmp) (const char *who1, const char *who2); }; #define UC_UNAVAILABLE 1 diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 28239812..f65332dc 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2680,9 +2680,10 @@ void oscar_init() ret->rem_deny = oscar_rem_deny; ret->set_permit_deny = oscar_set_permit_deny; ret->keepalive = oscar_keepalive; - ret->cmp_buddynames = aim_sncmp; ret->get_status_string = oscar_get_status_string; ret->send_typing = oscar_send_typing; + + ret->handle_cmp = aim_sncmp; register_protocol(ret); } diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index c21779ba..23c6f813 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -408,7 +408,8 @@ void byahoo_init( ) ret->chat_invite = byahoo_chat_invite; ret->chat_leave = byahoo_chat_leave; ret->chat_open = byahoo_chat_open; - ret->cmp_buddynames = g_strcasecmp; + + ret->handle_cmp = g_strcasecmp; register_protocol(ret); } diff --git a/root_commands.c b/root_commands.c index 42e113ed..2cf67134 100644 --- a/root_commands.c +++ b/root_commands.c @@ -465,7 +465,7 @@ static void cmd_add( irc_t *irc, char **cmd ) } else { - nick_set( irc, cmd[2], a->gc->acc->prpl, cmd[3] ); + nick_set( a, cmd[2], cmd[3] ); } } @@ -547,7 +547,7 @@ static void cmd_rename( irc_t *irc, char **cmd ) } else if( u->send_handler == buddy_send_handler ) { - nick_set( irc, u->handle, u->gc->acc->prpl, cmd[2] ); + nick_set( u->gc->acc, u->handle, cmd[2] ); } irc_usermsg( irc, "Nick successfully changed" ); @@ -568,7 +568,7 @@ static void cmd_remove( irc_t *irc, char **cmd ) u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); user_del( irc, cmd[1] ); - nick_del( irc, cmd[1] ); + nick_del( u->gc->acc, u->handle ); irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); g_free( s ); @@ -880,58 +880,6 @@ static void cmd_qlist( irc_t *irc, char **cmd ) irc_usermsg( irc, "%d, BitlBee: %s", num, q->question ); } -static void cmd_import_buddies( irc_t *irc, char **cmd ) -{ - struct gaim_connection *gc; - account_t *a; - nick_t *n; - - if( !( a = account_get( irc, cmd[1] ) ) ) - { - irc_usermsg( irc, "Invalid account" ); - return; - } - else if( !( ( gc = a->gc ) && ( a->gc->flags & OPT_LOGGED_IN ) ) ) - { - irc_usermsg( irc, "That account is not on-line" ); - return; - } - - if( cmd[2] ) - { - if( g_strcasecmp( cmd[2], "clear" ) == 0 ) - { - user_t *u; - - /* FIXME: Hmmm, this is actually pretty dangerous code... REMOVEME? :-) */ - for( u = irc->users; u; u = u->next ) - if( u->gc == gc ) - { - u->gc->acc->prpl->remove_buddy( u->gc, u->handle, NULL ); - user_del( irc, u->nick ); - } - - irc_usermsg( irc, "Old buddy list cleared." ); - } - else - { - irc_usermsg( irc, "Invalid argument: %s", cmd[2] ); - return; - } - } - - for( n = gc->irc->nicks; n; n = n->next ) - { - if( n->proto == gc->acc->prpl && !user_findhandle( gc, n->handle ) ) - { - gc->acc->prpl->add_buddy( gc, n->handle ); - add_buddy( gc, NULL, n->handle, NULL ); - } - } - - irc_usermsg( irc, "Sent all add requests. Please wait for a while, the server needs some time to handle all the adds." ); -} - const command_t commands[] = { { "help", 0, cmd_help, 0 }, { "identify", 1, cmd_identify, 0 }, @@ -950,7 +898,6 @@ const command_t commands[] = { { "no", 0, cmd_yesno, 0 }, { "blist", 0, cmd_blist, 0 }, { "nick", 1, cmd_nick, 0 }, - { "import_buddies", 1, cmd_import_buddies, 0 }, { "qlist", 0, cmd_qlist, 0 }, { NULL } }; diff --git a/storage_text.c b/storage_text.c index 06d278aa..ac197685 100644 --- a/storage_text.c +++ b/storage_text.c @@ -112,186 +112,13 @@ static storage_status_t text_load ( const char *my_nick, const char* password, i continue; http_decode( s ); - nick_set( irc, s, prpl, nick ); + // FIXME!!!! nick_set( irc, s, prpl, nick ); } fclose( fp ); return STORAGE_OK; } -static storage_status_t text_save( irc_t *irc, int overwrite ) -{ - char s[512]; - char path[512], new_path[512]; - char *line; - nick_t *n; - set_t *set; - mode_t ou = umask( 0077 ); - account_t *a; - FILE *fp; - char *hash; - - if (!overwrite) { - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); - if (access( path, F_OK ) != -1) - return STORAGE_ALREADY_EXISTS; - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); - if (access( path, F_OK ) != -1) - return STORAGE_ALREADY_EXISTS; - } - - /*\ - * [SH] Nothing should be saved if no password is set, because the - * password is not set if it was wrong, or if one is not identified - * yet. This means that a malicious user could easily overwrite - * files owned by someone else: - * a Bad Thing, methinks - \*/ - - /* [WVG] No? Really? */ - - /*\ - * [SH] Okay, okay, it wasn't really Wilmer who said that, it was - * me. I just thought it was funny. - \*/ - - hash = hashpass( irc->password ); - if( hash == NULL ) - { - irc_usermsg( irc, "Please register yourself if you want to save your settings." ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - for( n = irc->nicks; n; n = n->next ) - { - strcpy( s, n->handle ); - s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */ - http_encode( s ); - g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", find_protocol_id(n->proto->name), n->nick ); - if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .nicks file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .nicks file" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" ); - fp = fopen( path, "w" ); - if( !fp ) return STORAGE_OTHER_ERROR; - if( fprintf( fp, "%s", hash ) != strlen( hash ) ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - g_free( hash ); - - for( a = irc->accounts; a; a = a->next ) - { - if( !strcmp(a->prpl->name, "oscar") ) - g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server ); - else - g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"", - a->prpl->name, a->user, a->pass, a->server ? a->server : "" ); - - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - - for( set = irc->set; set; set = set->next ) - { - if( set->value && set->def ) - { - g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - } - - if( strcmp( irc->mynick, ROOT_NICK ) != 0 ) - { - g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick ); - line = obfucrypt( s, irc->password ); - if( *line ) - { - if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 ) - { - irc_usermsg( irc, "fprintf() wrote too little. Disk full?" ); - fclose( fp ); - return STORAGE_OTHER_ERROR; - } - } - g_free( line ); - } - if( fclose( fp ) != 0 ) - { - irc_usermsg( irc, "fclose() reported an error. Disk full?" ); - return STORAGE_OTHER_ERROR; - } - - g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" ); - if( unlink( new_path ) != 0 ) - { - if( errno != ENOENT ) - { - irc_usermsg( irc, "Error while removing old .accounts file" ); - return STORAGE_OTHER_ERROR; - } - } - if( rename( path, new_path ) != 0 ) - { - irc_usermsg( irc, "Error while renaming new .accounts file" ); - return STORAGE_OTHER_ERROR; - } - - umask( ou ); - - return STORAGE_OK; -} - static storage_status_t text_check_pass( const char *nick, const char *password ) { char s[512]; @@ -336,6 +163,5 @@ storage_t storage_text = { .init = text_init, .check_pass = text_check_pass, .remove = text_remove, - .load = text_load, - .save = text_save + .load = text_load }; diff --git a/storage_xml.c b/storage_xml.c index 701d5144..b01f35d6 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -196,7 +196,7 @@ static void xml_start_element( GMarkupParseContext *ctx, const gchar *element_na if( xd->current_account && handle && nick ) { - nick_set( irc, handle, xd->current_account->prpl, nick ); + nick_set( xd->current_account, handle, nick ); } else { @@ -364,11 +364,12 @@ static int xml_printf( int fd, int indent, char *fmt, ... ) 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 ) { char path[512], *path2, *pass_buf = NULL; set_t *set; - nick_t *nick; account_t *acc; int fd; md5_byte_t pass_md5[21]; @@ -439,10 +440,15 @@ static storage_status_t xml_save( irc_t *irc, int overwrite ) 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, 2, "<buddy handle=\"%s\" nick=\"%s\" />\n", nick->handle, nick->nick ) ) - goto write_error; + /* This probably looks pretty strange. g_hash_table_foreach + is quite a PITA already (but it can't get much better in + C without using #define, I'm afraid), and since it + doesn't seem to be possible to abort the foreach on write + 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, (gpointer) fd ) ) + goto write_error; if( !xml_printf( fd, 1, "</account>\n" ) ) goto write_error; @@ -477,6 +483,11 @@ write_error: return STORAGE_OTHER_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 ); +} + static storage_status_t xml_remove( const char *nick, const char *password ) { char s[512]; @@ -142,16 +142,22 @@ user_t *user_find( irc_t *irc, char *nick ) user_t *user_findhandle( struct gaim_connection *gc, char *handle ) { - user_t *u = gc->irc->users; - - while( u ) - { - if( u->gc == gc && u->handle && gc->acc->prpl->cmp_buddynames ( u->handle, handle ) == 0 ) - break; - u = u->next; - } - - return( u ); + user_t *u; + char *nick; + + /* First, let's try a hash lookup. If it works, it's probably faster. */ + if( ( nick = g_hash_table_lookup( gc->acc->nicks, handle ) ) && + ( u = user_find( gc->irc, nick ) ) && + ( gc->acc->prpl->handle_cmp( handle, u->handle ) == 0 ) ) + return u; + + /* However, it doesn't always work, so in that case we'll have to dig + through the whole userlist. :-( */ + for( u = gc->irc->users; u; u = u->next ) + if( u->gc == gc && u->handle && gc->acc->prpl->handle_cmp( u->handle, handle ) == 0 ) + return u; + + return NULL; } void user_rename( irc_t *irc, char *oldnick, char *newnick ) |