📄 account.c
字号:
/* * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu) * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net) * Copyright (C) 2002,2003,2004 Dizzy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define ACCOUNT_INTERNAL_ACCESS#include "common/setup_before.h"#include <stdio.h>#ifdef HAVE_STDDEF_H# include <stddef.h>#else# ifndef NULL# define NULL ((void *)0)# endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif#endif#include "compat/strchr.h"#include "compat/strdup.h"#include "compat/strcasecmp.h"#include "compat/strncasecmp.h"#include <ctype.h>#ifdef HAVE_LIMITS_H# include <limits.h>#endif#include "compat/char_bit.h"#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#include <errno.h>#include "compat/strerror.h"#ifdef HAVE_SYS_TYPES_H# include <sys/types.h>#endif#include "compat/pdir.h"#include "common/list.h"#include "common/elist.h"#include "common/eventlog.h"#include "prefs.h"#include "common/util.h"#include "common/field_sizes.h"#include "common/bnethash.h"#include "common/introtate.h"#include "account.h"#include "account_wrap.h"#include "common/hashtable.h"#include "connection.h"#include "watch.h"#include "friends.h"#include "team.h"#include "common/tag.h"#include "ladder.h"#include "clan.h"#include "server.h"#include "attrgroup.h"#include "attrlayer.h"#include "storage.h"#include "common/flags.h"#include "common/xalloc.h"#ifdef HAVE_ASSERT_H# include <assert.h>#endif#include "common/setup_after.h"static t_hashtable * accountlist_head=NULL;static t_hashtable * accountlist_uid_head=NULL;unsigned int maxuserid=0;/* This is to force the creation of all accounts when we initially load the accountlist. */static int force_account_add=0;static unsigned int account_hash(char const * username);static t_account * account_load(t_attrgroup *);static int account_load_friends(t_account * account);static int account_unload_friends(t_account * account);static void account_destroy(t_account * account);static t_account * accountlist_add_account(t_account * account);static unsigned int account_hash(char const *username){ register unsigned int h; register unsigned int len = strlen(username); for (h = 5381; len > 0; --len, ++username) { h += h << 5; if (isupper((int) *username) == 0) h ^= *username; else h ^= tolower((int) *username); } return h;}static t_account * account_create(char const * username, char const * passhash1){ t_account * account; if (username && !passhash1) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL passhash1"); return NULL; } if (username && account_check_name(username)) { eventlog(eventlog_level_error,__FUNCTION__,"got invalid chars in username"); return NULL; } account = xmalloc(sizeof(t_account)); account->name = NULL; account->clanmember = NULL; account->attrgroup = NULL; account->friends = NULL; account->teams = NULL; account->conn = NULL; FLAG_ZERO(&account->flags); account->namehash = 0; /* hash it later before inserting */ account->uid = 0; /* hash it later before inserting */ if (username) { /* actually making a new account */ /* first check if such a username already owns an account. * we search in the memory hash mainly for non-indexed storage types. * indexed storage types check themselves if the username exists already * in the storage (see storage_sql.c) */ if (accountlist_find_account(username)) { eventlog(eventlog_level_debug,__FUNCTION__,"user \"%s\" already has an account",username); goto err; } account->attrgroup = attrgroup_create_newuser(username); if(!account->attrgroup) { eventlog(eventlog_level_error,__FUNCTION__,"failed to add user"); goto err; } account->name = xstrdup(username); if (account_set_strattr(account,"BNET\\acct\\username",username)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set username"); goto err; } if (account_set_numattr(account,"BNET\\acct\\userid",maxuserid+1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set userid"); goto err; } if (account_set_strattr(account,"BNET\\acct\\passhash1",passhash1)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set passhash1"); goto err; } if (account_set_numattr(account,"BNET\\acct\\ctime",(unsigned int)now)) { eventlog(eventlog_level_error,__FUNCTION__,"could not set ctime"); goto err; } } return account;err: account_destroy(account); return NULL;}static void account_destroy(t_account * account){ assert(account); friendlist_close(account->friends); teams_destroy(account->teams); if (account->attrgroup) attrgroup_destroy(account->attrgroup); if (account->name) xfree(account->name); xfree(account);}extern unsigned int account_get_uid(t_account const * account){ if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return 0; } return account->uid;}extern int account_match(t_account * account, char const * username){ unsigned int userid=0; unsigned int namehash; char const * tname; if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!username) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); return -1; } if (username[0]=='#') if (str_to_uint(&username[1],&userid)<0) userid = 0; if (userid) { if (account->uid==userid) return 1; } else { namehash = account_hash(username); if (account->namehash==namehash && (tname = account_get_name(account))) { if (strcasecmp(tname,username)==0) return 1; } } return 0;}extern int account_save(t_account * account, unsigned flags){ assert(account); return attrgroup_save(account->attrgroup, flags);}extern int account_flush(t_account * account, unsigned flags){ int res; assert(account); res = attrgroup_flush(account->attrgroup, flags); if (res<0) return res; account_unload_friends(account); return res;}extern char const * account_get_strattr_real(t_account * account, char const * key, char const * fn, unsigned int ln){ if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account (from %s:%u)",fn,ln); return NULL; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key (from %s:%u)",fn,ln); return NULL; } return attrgroup_get_attr(account->attrgroup, key);}extern int account_set_strattr(t_account * account, char const * key, char const * val){ if (!account) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return -1; } if (!key) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL key"); return -1; } return attrgroup_set_attr(account->attrgroup, key, val);}static t_account * account_load(t_attrgroup *attrgroup){ t_account * account; assert(attrgroup); if (!(account = account_create(NULL,NULL))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create account"); return NULL; } account->attrgroup = attrgroup; return account;}static t_account * account_load_new(char const * name, unsigned uid){ t_account *account; t_attrgroup *attrgroup; if (name && account_check_name(name)) return NULL; force_account_add = 1; /* disable the protection */ attrgroup = attrgroup_create_nameuid(name, uid); if (!attrgroup) { force_account_add = 0; return NULL; } if (!(account = account_load(attrgroup))) { eventlog(eventlog_level_error, __FUNCTION__,"could not load account"); attrgroup_destroy(attrgroup); force_account_add = 0; return NULL; } if (!accountlist_add_account(account)) { eventlog(eventlog_level_error, __FUNCTION__,"could not add account to list"); account_destroy(account); force_account_add = 0; return NULL; } force_account_add = 0; return account;}static int _cb_read_accounts(t_attrgroup *attrgroup, void *data){ unsigned int *count = (unsigned int *)data; t_account *account; if (!(account = account_load(attrgroup))) { eventlog(eventlog_level_error, __FUNCTION__,"could not load account"); attrgroup_destroy(attrgroup); return -1; } if (!accountlist_add_account(account)) { eventlog(eventlog_level_error, __FUNCTION__,"could not add account to list"); account_destroy(account); return -1; } /* might as well free up the memory since we probably won't need it */ account_flush(account,FS_FORCE); /* force unload */ (*count)++; return 0;}extern int accountlist_load_all(int flag){ unsigned int count; int starttime = time(NULL); static int loaded = 0; /* all accounts already loaded ? */ int res; if (loaded) return 0; count = 0; res = 0; force_account_add = 1; /* disable the protection */ switch(attrgroup_read_accounts(flag, _cb_read_accounts, &count)) { case -1: eventlog(eventlog_level_error, __FUNCTION__,"got error reading users"); res = -1; break; case 0: loaded = 1; eventlog(eventlog_level_info, __FUNCTION__, "loaded %u user accounts in %ld seconds",count,time(NULL) - starttime); break; default: break; } force_account_add = 0; /* enable the protection */ return res;}extern int accountlist_create(void){ eventlog(eventlog_level_info, __FUNCTION__, "started creating accountlist"); if (!(accountlist_head = hashtable_create(prefs_get_hashtable_size()))) { eventlog(eventlog_level_error, __FUNCTION__, "could not create accountlist_head"); return -1; } if (!(accountlist_uid_head = hashtable_create(prefs_get_hashtable_size()))) { eventlog(eventlog_level_error, __FUNCTION__, "could not create accountlist_uid_head"); return -1; } /* load accounts without force, indexed storage types wont be loading */ accountlist_load_all(ST_NONE); maxuserid = storage->read_maxuserid(); return 0;}extern int accountlist_destroy(void){ t_entry * curr; t_account * account; HASHTABLE_TRAVERSE(accountlist_head,curr) { if (!(account = entry_get_data(curr))) eventlog(eventlog_level_error,__FUNCTION__,"found NULL account in list"); else { if (account_flush(account, FS_FORCE)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not save account"); account_destroy(account); } hashtable_remove_entry(accountlist_head,curr); } HASHTABLE_TRAVERSE(accountlist_uid_head,curr) { hashtable_remove_entry(accountlist_head,curr); } if (hashtable_destroy(accountlist_head)<0) return -1; accountlist_head = NULL; if (hashtable_destroy(accountlist_uid_head)<0) return -1; accountlist_uid_head = NULL; return 0;}extern t_hashtable * accountlist(void){ return accountlist_head;}extern t_hashtable * accountlist_uid(void){ return accountlist_uid_head;}extern unsigned int accountlist_get_length(void){ return hashtable_get_length(accountlist_head);}extern int accountlist_save(unsigned flags){ return attrlayer_save(flags);}extern int accountlist_flush(unsigned flags){ return attrlayer_flush(flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -