#include <stdio.h> #include <arpa/telnet.h> #include "db.h" #include "net.h" #include "externs.h" STATE state_list[] = { { STATE_WAITCONNECT, do_state_waitconnect }, { STATE_WAITLOGIN, do_state_waitlogin }, { STATE_WAITPASS, do_state_waitpass }, { STATE_CONNECTED, NULL }, { STATE_RELOADCONNECT, NULL }, { STATE_WAITINPUT, NULL }, { STATE_WAITPLAYERNAME, do_state_waitplayername }, { STATE_WAITPLAYERPASS, do_state_waitplayerpass }, { STATE_WAITPASSVERIFY, do_state_waitpassverify }, { STATE_WAITPLAYEREMAIL, do_state_waitplayeremail }, { -1, NULL } }; static void do_login_screen(DDATA *d) { queue_string(d, tprintf("Welcome to %s!\n", config.maze_name), 1); show_file(d, "msgs/welcome.txt"); queue_string(d, tprintf("Server: %s\n", get_version()), 1); queue_string(d, "Login with your player name or type 'guest' to login as a guest.", 1); if(config.auto_create) queue_string(d, "Login as 'new' to create a character.\n", 1); } static OBJ *make_guest(DDATA *d) { int i; OBJ *player; char *name = NULL; if(config.max_guests < 1) { queue_string(d, "Guest logins are not currently allowed. Sorry.", 1); return(NULL); } for(i = 1;i <= config.max_guests;i++) { name = tprintf("%s%d", config.guest_prefix, i); if(!(player = match_player(NULL, name))) break; /* See if this guest is 'stale' */ if(!is_connected_raw(player)) { log_guest(tprintf("Destroying stale guest '%s'", unparse_object(player, player))); destroy_guest(player); break; } } if(i-1 == config.max_guests) { queue_string(d, "All guest ID's are busy; please try again later.", 1); return(NULL); } player = create_guest(name, tprintf("%c%d", *name, i), create_random_password()); if(!player) { queue_string(d, "Error creating guest ID, please try again later.", 1); log_error(tprintf("Error creating guest ID. '%s' already exists.", name)); return(NULL); } queue_string(d, tprintf("You are guest %d of %d.", i, config.max_guests), 1); return(player); } static void echo_on(DDATA *d) { char echo_on_str[] = { IAC, WONT, TELOPT_ECHO, '\0' }; queue_string(d, echo_on_str, 0); } static void echo_off(DDATA *d) { char echo_off_str[] = { IAC, WILL, TELOPT_ECHO, '\0' }; queue_string(d, echo_off_str, 0); } STATE *find_state(int state) { STATE *s; for(s = state_list;s->num != -1;s++) if(s->num == state) break; return(s); } void set_state(DDATA *des, int state) { STATE *s; if(!(s = find_state(state))) { log_error(tprintf("Unable to set state for descriptor %d to %d.", des->descriptor, state)); return; } des->state = s; } int check_state(DDATA *des, int state) { return((des->state->num == state)); } int do_state_waitlogin(DDATA *d, char *str) { char *login_msg = tprintf("%s Login: ", config.maze_name); if(!string_compare(str, "guest")) { if(!(d->player = make_guest(d))) { queue_string(d, login_msg, 0); return(0); } return(1); } if(!string_compare(str, "new")) { if(!config.auto_create) { queue_string(d, "Automatic player creation is disabled.", 1); queue_string(d, login_msg, 0); return(0); } queue_string(d, "Please enter desired name: ", 0); set_state(d, STATE_WAITPLAYERNAME); return(0); } if(!(d->player = match_player(NULL, str))) { queue_string(d, tprintf("Player '%s' doesn't exist.", str), 1); queue_string(d, login_msg, 0); return(0); } queue_string(d, tprintf("Password for %s: ", d->player->name), 0); echo_off(d); set_state(d, STATE_WAITPASS); return(0); } static void add_bad_login(DDATA *d) { ATTR *attr = find_attr("BADLOGINS"); char *msg = tprintf("%s@%s", d->user, d->addr); if(*atr_get_a(d->player, attr)) atr_add_a(d->player, attr, tprintf("%s %s", atr_get_a(d->player, attr), msg)); else atr_add_a(d->player, attr, msg); } int do_state_waitpass(DDATA *d, char *str) { echo_on(d); if(!check_password(d->player, str)) { log_io(tprintf("FAILED CONNECT '%s' on descriptor %d", name(d->player), d->descriptor)); queue_string(d, "Invalid password.", 1); queue_string(d, tprintf("%s Login: ", config.maze_name), 0); set_state(d, STATE_WAITLOGIN); add_bad_login(d); d->player = NULL; return(0); } queue_string(d, "", 1); return(1); } int do_state_waitconnect(DDATA *d, char *str) { do_login_screen(d); queue_string(d, tprintf("%s Login: ", config.maze_name), 0); set_state(d, STATE_WAITLOGIN); return(0); } int do_state_waitplayername(DDATA *d, char *str) { if(!*str || !ok_player_name(NULL, strip_color(str), "") || string_prefix(str, config.guest_prefix) || match_player(NULL, str)) { queue_string(d, tprintf("Sorry, '%s' is not a valid player name.", str), 1); queue_string(d, "Please enter desired name: ", 0); return(0); } d->create_info = (struct create_info *)stack_alloc(sizeof(struct create_info), 1, 0); SET(d->create_info->name, str); d->create_info->password = NULL; echo_off(d); queue_string(d, "Please enter desired password: ", 0); set_state(d, STATE_WAITPLAYERPASS); return(0); } int do_state_waitplayerpass(DDATA *d, char *str) { if(!ok_password(str)) { queue_string(d, tprintf("Sorry, '%s' is not a valid password.", str), 1); queue_string(d, "Please enter desired password: ", 0); return(0); } SET(d->create_info->password, str); echo_off(d); queue_string(d, "Please re-enter password for verification: ", 0); set_state(d, STATE_WAITPASSVERIFY); return(0); } int do_state_waitpassverify(DDATA *d, char *str) { if(strcmp(d->create_info->password, str)) { queue_string(d, "Passwords don't match.", 1); queue_string(d, "Please enter desired password: ", 0); set_state(d, STATE_WAITPLAYERPASS); return(0); } SET(d->create_info->passverify, str); echo_on(d); queue_string(d, "Please enter your email address: ", 0); set_state(d, STATE_WAITPLAYEREMAIL); return(0); } int do_state_waitplayeremail(DDATA *d, char *str) { if(!is_valid_email(str)) { queue_string(d, tprintf("Sorry, '%s' is not a valid email address.", str), 1); queue_string(d, "Please enter your email address: ", 0); return(0); } if(!(d->player = create_player(d->create_info->name, d->create_info->password, CLASS_CITIZEN, player_start_obj))) { log_error(tprintf("Failure creating '%s'", d->create_info->name)); queue_string(d, "Sorry, I couldn't create your character!", 1); shutdownsock(d); return(0); } d->player->creator = root_obj; atr_add(d->player, "EMAIL", str); stack_free(d->create_info->name); stack_free(d->create_info->password); stack_free(d->create_info->passverify); stack_free(d->create_info); queue_string(d, tprintf("\nWelcome to %s!\n", config.maze_name), 1); return(1); }