Crossfire Server, Trunk
account.cpp File Reference
#include <set>
#include <string>
#include "global.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "object.h"
#include "sproto.h"
#include "output_file.h"
+ Include dependency graph for account.cpp:

Go to the source code of this file.

Data Structures

struct  account_struct
 

Macros

#define ACCOUNT_FILE   "accounts"
 
#define NUM_ACCOUNT_FIELDS   6
 

Functions

static account_structaccount_alloc ()
 
int account_change_password (const char *account_name, const char *current_password, const char *new_password)
 
int account_check_string (const char *str)
 
const char * account_exists (const char *account_name)
 
const char * account_get_account_for_char (const char *charname)
 
linked_characcount_get_additional_chars (const char *account_name, const Account_Chars *chars, int *count)
 
char ** account_get_players_for_account (const char *account_name)
 
int account_is_logged_in (const char *name)
 
int account_link (const char *account_name, const char *player_name)
 
int account_login (const char *account_name, const char *account_password)
 
void account_logout (const char *account_name)
 
int account_new (const char *account_name, const char *account_password)
 
int account_remove_player (const char *account_name, const char *player_name)
 
static void account_write_entry (FILE *fp, account_struct *ac)
 
void accounts_clear (void)
 
void accounts_load (void)
 
void accounts_save (void)
 
static int char_in_list (const char *name, const std::vector< Account_Char * > chars)
 
static void ensure_available_characters (account_struct *account, int count)
 

Variables

static std::vector< account_struct * > accounts
 
static int accounts_loaded = 0
 
static std::set< std::string > accounts_logged_in = std::set<std::string>()
 

Detailed Description

This file contains account management logic - creation, deletion, log in verification, as well as associating player files with the account.

The code in this file mostly assumes that the number of account operations will be low - for example, we load up all acounts in a linked list, and save them all out. If we have 10,000 accounts, this would be very slow. But for a few hundred accounts, should be plenty fast on most any hardware.

Likewise, the account structure is not exposed outside this file - this means that account access/updates is done through the account name. This adds some extra overhead in that code has to search the linked list, but for a relatively low number of entries, and relatively infrequent updates, this should not be much of an issue.

Since the accounts file is updated in several places in this file, it is documented here. The file is a list of accounts, one line per account, with fields separted by colons, eg:

Account name:Password:Account last used:Characters (semicolon separated):expansion mwede.nosp@m.l@so.nosp@m.nic.n.nosp@m.et:mypassword:1260686494:Mark;MarkW;:

none of the the fields listed could contain colons, and player names can not contain semicolon, as that is used to separate those. In addition, everything is limited to printable characters. The accounts file is designed to be human readable, even if it is not expected that a human will read it. Passwords are hashed using crypt(3) in traditional mode, unless you're on FreeBSD or Windows in which case passwords are stored in plaintext due to legacy reasons. expansion (last field) is there for possible expansion. There may be desire to store bits of information there. An example might be dm=1. But it is there for expansion.

Definition in file account.cpp.

Macro Definition Documentation

◆ ACCOUNT_FILE

#define ACCOUNT_FILE   "accounts"

Name of the accounts file. I can not ever see a reason why this name would not work, but may as well still make it easy to change it.

Definition at line 109 of file account.cpp.

◆ NUM_ACCOUNT_FIELDS

#define NUM_ACCOUNT_FIELDS   6

Number of fields in the accounts file. These are colon separated

Definition at line 68 of file account.cpp.

Function Documentation

◆ account_alloc()

static account_struct* account_alloc ( )
static

Allocate a new account_struct item. Will fatal() if memory error.

Returns
item, never NULL.

Definition at line 136 of file account.cpp.

References curse_on_apply::ac, ensure_available_characters(), fatal(), llevError, LOG(), and OUT_OF_MEMORY.

Referenced by account_new(), and accounts_load().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_change_password()

int account_change_password ( const char *  account_name,
const char *  current_password,
const char *  new_password 
)

Change an account password. It does error checking, but the caller might want to do checking before getting here.

Parameters
account_nameaccount name we are changing
current_passwordcurrent password for the account or NULL. This is the unencrypted password (password as entered by user). If NULL, the current password is not checked, suitable for resetting lost passwords.
new_passwordnew password to set, unencrypted.
Return values
0password changed successfully.
1account name, old or new password has invalid character.
2account does not exist.
3current password is invalid.

Definition at line 628 of file account.cpp.

References curse_on_apply::ac, account_check_string(), accounts, check_password(), newhash(), strcasecmp(), and strdup_local.

Referenced by account_password(), and command_accountpasswd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_check_string()

int account_check_string ( const char *  str)

Checks a string to make sure it does not have any invalid characters. We are fairly permissive on character here. String must start with alphanumeric String must not contain :;/'[ String can not end if a space This string will get used for file/directory names, but so long as as characters are not included that are not illegal, one can still manipulate the file/directory by putting it in quotes. If one starts to block all characters that may get interperted by shells, a large number of characters now get blocked (|*]()!, etc), and deciding which should be allowed and not just becomes a judgement call, so easier to just allow all and have the user put it in quotes.

Parameters
strstring to check
Returns
0 if ok, 1 if we have an invalid character, 2 if string is too long.

Definition at line 361 of file account.cpp.

References MAX_NAME, and make_face_from_files::str.

Referenced by account_change_password(), account_new(), account_new_cmd(), account_password(), create_player_cmd(), and START_TEST().

+ Here is the caller graph for this function:

◆ account_exists()

const char* account_exists ( const char *  account_name)

Checks the existing accounts, and see if this account exists. This can also be used to get the official name for the account (eg, as user first entered, so Mark instead of mARk)

Parameters
account_nameaccount name we are looking for.
Returns
returns official name on match, NULL on no match.

Definition at line 297 of file account.cpp.

References curse_on_apply::ac, accounts, and strcasecmp().

Referenced by account_login_cmd(), account_new(), account_new_cmd(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_get_account_for_char()

const char* account_get_account_for_char ( const char *  charname)

This looks at all the accounts and sees if charname is associated with any of them.

Parameters
charnamecharacter name to check for.
Returns
Account name the character is associated with, NULL if none.

Definition at line 580 of file account.cpp.

References curse_on_apply::ac, accounts, and guildjoin::charname.

Referenced by account_add_player_cmd(), and save_player().

+ Here is the caller graph for this function:

◆ account_get_additional_chars()

linked_char* account_get_additional_chars ( const char *  account_name,
const Account_Chars chars,
int *  count 
)

Get a list of character names linked to the specified account which are not listed in chars.

Parameters
account_nameaccount name.
charsknown character names.
[out]countwill be incremented by the number of items returned. Not initialized before use.
Returns
list of character names not in chars, the caller should free it after use.

Definition at line 551 of file account.cpp.

References curse_on_apply::ac, accounts, char_in_list(), Account_Chars::chars, linked_char::name, linked_char::next, and strcasecmp().

Referenced by send_account_players().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_get_players_for_account()

char** account_get_players_for_account ( const char *  account_name)

Returns an array of strings for the characters on this account - the array is null terminated. In fact, it just returns the ac->character_names.

Parameters
account_namename of the account to get the players for.
Returns
array of character names for this account. This will return NULL in the case where we can not find the account. It will return an array with the first entry being NULL in the case of a valid account with no characters added. This returned data should not be altered in any way.

Definition at line 520 of file account.cpp.

References curse_on_apply::ac, accounts, and strcasecmp().

Referenced by account_play_cmd(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_is_logged_in()

int account_is_logged_in ( const char *  name)

This checkes if an account is logged in. It is mainly used because some operations should not be done on logged in accounts (keeping everything synchronized is harder.)

Parameters
namename to look for.
Returns
0 if not logged in, 1 if logged in.

Definition at line 605 of file account.cpp.

References accounts_logged_in, and give::name.

Referenced by account_add_player_cmd().

+ Here is the caller graph for this function:

◆ account_link()

int account_link ( const char *  account_name,
const char *  player_name 
)

Adds a player name to an account. Player corresponds to the names used in the pl object, not the person sitting at the computer. This function presumes that the caller has done the work to verify that the player does in fact exist, and does any related work to update the player. What this function does is simply update the account structure.

Parameters
account_namename of the account we are adding this player to.
player_namename of this player.
Return values
0player name added successfully.
1could not find account of that name.

Definition at line 445 of file account.cpp.

References curse_on_apply::ac, accounts, ensure_available_characters(), strcasecmp(), and strdup_local.

Referenced by account_add_player_cmd(), save_player(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_login()

int account_login ( const char *  account_name,
const char *  account_password 
)

Check if the given account exists, and whether the password is correct.

Note - if we do get a match, we update the last_login value - it is presumed that if someone knows the right accountname/password, that the account is effectively getting logged in.

Parameters
account_nameaccount name we are looking for.
account_passwordpassword for the account. This is the unencrypted password (password as entered by user)
Returns
0 if no match/wrong password, 1 if a match is found and password matches.

Definition at line 319 of file account.cpp.

References curse_on_apply::ac, account_password(), accounts, accounts_logged_in, check_password(), and strcasecmp().

Referenced by account_login_cmd().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_logout()

void account_logout ( const char *  account_name)

Remove 'account_name' from the list of logged in accounts.

Definition at line 338 of file account.cpp.

References accounts_logged_in.

◆ account_new()

int account_new ( const char *  account_name,
const char *  account_password 
)

Adds an account. It does error checking, but the caller might want to do checking before getting here.

Parameters
account_nameaccount name we are adding
account_passwordpassword for the account. This is the unencrypted password (password as entered by user)
Return values
0account added successfully.
1name or password has invalid character.
2account already exists.

Definition at line 400 of file account.cpp.

References curse_on_apply::ac, account_alloc(), account_check_string(), account_exists(), account_password(), accounts, accounts_loaded, newhash(), and strdup_local.

Referenced by account_new_cmd(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_remove_player()

int account_remove_player ( const char *  account_name,
const char *  player_name 
)

Removes a player name from an account. Player corresponds to the names used in the pl object, not the person sitting at the computer. This function presumes that the caller has done the work to verify that the player does in fact exist, and does any related work to update the player. What this function does is simply update the account structure.

Parameters
account_namename of the account we are removing this player from.
player_namename of this player.
Return values
0player name removed successfully.
1could not find account of that name.
2player of this name not on account.

Definition at line 475 of file account.cpp.

References curse_on_apply::ac, accounts, push::match, and strcasecmp().

Referenced by account_add_player_cmd(), key_confirm_quit(), kill_player_permadeath(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ account_write_entry()

static void account_write_entry ( FILE *  fp,
account_struct ac 
)
static

This writes a single account entry to the given filepointer. it is used both when saving all accounts, or if we just need to append a new account to the end of the file.

Parameters
fpfile pointer to write to.
acaccount structure to write out.

Definition at line 235 of file account.cpp.

References curse_on_apply::ac.

Referenced by accounts_save().

+ Here is the caller graph for this function:

◆ accounts_clear()

void accounts_clear ( void  )

This is used purely by the test harness - by clearing the accounts, it can then verify that the data is added is loaded back into memory properly. As such, we don't worry about memory cleanup, etc.

Definition at line 153 of file account.cpp.

References accounts, and accounts_loaded.

Referenced by START_TEST().

+ Here is the caller graph for this function:

◆ accounts_load()

void accounts_load ( void  )

This loads all the account entries into memory. It is presumed to only be called once during the program startup.

Definition at line 162 of file account.cpp.

References curse_on_apply::ac, account_alloc(), ACCOUNT_FILE, accounts, accounts_loaded, buf, bufferreader_destroy(), bufferreader_init_from_file(), bufferreader_next_line(), ensure_available_characters(), llevError, llevInfo, Settings::localdir, LOG(), MAX_BUF, NUM_ACCOUNT_FIELDS, settings, split_string(), strdup_local, and Ice::tmp.

Referenced by init(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ accounts_save()

void accounts_save ( void  )

Save all the account information. Since the data is stored in a flat file, if an update is needed for an account, the only way to save updates is to save all the data - there isn't an easy way to just add another player name for an account.

Definition at line 256 of file account.cpp.

References curse_on_apply::ac, ACCOUNT_FILE, account_write_entry(), accounts, accounts_loaded, Settings::localdir, MAX_BUF, of_close(), of_open(), and settings.

Referenced by account_new_cmd(), cleanup(), do_specials(), and START_TEST().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ char_in_list()

static int char_in_list ( const char *  name,
const std::vector< Account_Char * >  chars 
)
static

Check if a character name is in a list or not.

Parameters
namecharacter name to check.
charslist of names to check.
Returns
0 if not in the list, non-zero else.

Definition at line 534 of file account.cpp.

References give::name.

Referenced by account_get_additional_chars().

+ Here is the caller graph for this function:

◆ ensure_available_characters()

static void ensure_available_characters ( account_struct account,
int  count 
)
static

Ensure an account can handle at least the specified count of character names.

Parameters
accountaccount to check.
countnumber of names to handle.

Definition at line 116 of file account.cpp.

References account_struct::allocated_characters, account_struct::character_names, disinfect::count, fatal(), llevError, LOG(), and OUT_OF_MEMORY.

Referenced by account_alloc(), account_link(), and accounts_load().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ accounts

◆ accounts_loaded

int accounts_loaded = 0
static

Whether the account information was loaded or not. Because accounts_save() is called in cleanup(), we don't want programs using this library to erase the server's account information, since it is NOT loaded by default.

Definition at line 103 of file account.cpp.

Referenced by account_new(), accounts_clear(), accounts_load(), and accounts_save().

◆ accounts_logged_in

std::set<std::string> accounts_logged_in = std::set<std::string>()
static

Set of accounts names that are currently logged in.

Definition at line 54 of file account.cpp.

Referenced by account_is_logged_in(), account_login(), and account_logout().