foundation2_fluffos_v1/
foundation2_fluffos_v1/bin/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/ChangeLog.old/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/Win32/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/compat/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/compat/simuls/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/include/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/clone/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/command/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/data/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/etc/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/include/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/inherit/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/inherit/master/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/log/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/compiler/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/efuns/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/single/tests/operators/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/testsuite/u/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/tmp/
foundation2_fluffos_v1/fluffos-2.9-ds2.13/windows/
foundation2_fluffos_v1/lib/cfg/
foundation2_fluffos_v1/lib/cmds/adm/
foundation2_fluffos_v1/lib/daemon/save/
foundation2_fluffos_v1/lib/daemon/services/
foundation2_fluffos_v1/lib/daemon/soul/
foundation2_fluffos_v1/lib/doc/build/
foundation2_fluffos_v1/lib/doc/classes/
foundation2_fluffos_v1/lib/doc/driver/
foundation2_fluffos_v1/lib/doc/driver/applies/
foundation2_fluffos_v1/lib/doc/driver/applies/interactive/
foundation2_fluffos_v1/lib/doc/driver/concepts/
foundation2_fluffos_v1/lib/doc/driver/driver/
foundation2_fluffos_v1/lib/doc/driver/efuns/arrays/
foundation2_fluffos_v1/lib/doc/driver/efuns/buffers/
foundation2_fluffos_v1/lib/doc/driver/efuns/calls/
foundation2_fluffos_v1/lib/doc/driver/efuns/compile/
foundation2_fluffos_v1/lib/doc/driver/efuns/filesystem/
foundation2_fluffos_v1/lib/doc/driver/efuns/floats/
foundation2_fluffos_v1/lib/doc/driver/efuns/functions/
foundation2_fluffos_v1/lib/doc/driver/efuns/general/
foundation2_fluffos_v1/lib/doc/driver/efuns/mappings/
foundation2_fluffos_v1/lib/doc/driver/efuns/numbers/
foundation2_fluffos_v1/lib/doc/driver/efuns/parsing/
foundation2_fluffos_v1/lib/doc/driver/lpc/constructs/
foundation2_fluffos_v1/lib/doc/driver/lpc/types/
foundation2_fluffos_v1/lib/doc/driver/platforms/
foundation2_fluffos_v1/lib/doc/efun/
foundation2_fluffos_v1/lib/doc/etc/
foundation2_fluffos_v1/lib/doc/faq/
foundation2_fluffos_v1/lib/doc/help/creator/
foundation2_fluffos_v1/lib/doc/help/player/
foundation2_fluffos_v1/lib/doc/lpc/basic/
foundation2_fluffos_v1/lib/doc/lpc/data_types/
foundation2_fluffos_v1/lib/doc/lpc/etc/
foundation2_fluffos_v1/lib/doc/lpc/intermediate/
foundation2_fluffos_v1/lib/doc/lpc/types/
foundation2_fluffos_v1/lib/doc/mudlib/
foundation2_fluffos_v1/lib/doc/mudlib/Features/
foundation2_fluffos_v1/lib/domains/Examples/armour/
foundation2_fluffos_v1/lib/domains/Examples/etc/
foundation2_fluffos_v1/lib/domains/Examples/npc/
foundation2_fluffos_v1/lib/domains/Examples/room/
foundation2_fluffos_v1/lib/domains/Examples/virtual/
foundation2_fluffos_v1/lib/domains/Examples/virtual/exaA/
foundation2_fluffos_v1/lib/domains/Examples/virtual/exaB/
foundation2_fluffos_v1/lib/domains/Examples/weapon/
foundation2_fluffos_v1/lib/domains/School/doc/
foundation2_fluffos_v1/lib/domains/School/room/
foundation2_fluffos_v1/lib/domains/School/room/Classes/
foundation2_fluffos_v1/lib/domains/School/room/Offices/
foundation2_fluffos_v1/lib/domains/Standard/
foundation2_fluffos_v1/lib/domains/Standard/pools/
foundation2_fluffos_v1/lib/domains/Standard/std/
foundation2_fluffos_v1/lib/domains/Standard/xtra/
foundation2_fluffos_v1/lib/include/
foundation2_fluffos_v1/lib/lib/obj/
foundation2_fluffos_v1/lib/news/
foundation2_fluffos_v1/lib/save/
foundation2_fluffos_v1/lib/secure/cfg/
foundation2_fluffos_v1/lib/secure/cmds/player/
foundation2_fluffos_v1/lib/secure/lib/
foundation2_fluffos_v1/old/
foundation2_fluffos_v1/win32/
/*    /secure/lib/login.c
 *    from the Foundation II LPC Library
 *    the login object, connecting players to their objects
 *    created by Descartes of Borg 940115
 */

#include <lib.h>
#include <config.h> 
#include <news.h>
#include <flags.h>
#include <daemons.h> 
#include <objects.h>
 
static private int CrackCount, CopyExists; 
static private string Name, CapName, Client, TermType; 
static private object Player; 
static int *Screen;
 
static void logon();
static void get_name(string str);
string GetKeyName();
static void get_password(string str);
static private int locked_access();
static private int check_password(string str);
static private int valid_site(string ip);
static private int boot_copy();
static void disconnect_copy(string str);
static private void exec_user();
static void new_user(string str);
static void choose_password(string str);
static void confirm_password(string str2, string str1);
static int register_client();
static void continue_login();
static void choose_gender(string str);
static void enter_email(string str);
static void enter_real_name(string str);
static void idle();
static void receive_message(string cl, string msg);
static private void internal_eventDestruct();
void eventDestruct();

void create() { 
    Name = ""; 
    Client = 0;
    CrackCount = 0; 
    Screen = ({ 0, 0 });
    Player = 0; 
  } 
 
static void logon() { 
    call_out("idle", LOGON_TIMEOUT); 
    receive(read_file(WELCOME));
    receive("\n"+center("Driver: "+version()+"    Mudlib: "+mudlib()+" "+
      mudlib_version()+"    AMCP 1.1 compliant"));
    receive("\nWhat name do you wish? ");
    input_to("get_name"); 
} 
 
static void get_name(string str) { 
    if(!str || str == "") { 
        receive("\nInvalid entry.  Please try again.\n");
        internal_eventDestruct();
        return; 
      } 
    if(sscanf(str, "%s:%s", CapName, Client) != 2) {
        Client = 0;
        Name = convert_name(CapName = str);
    }
    else {
        Name = convert_name(CapName);
        receive("\n");
        if(find_player(Name)) CopyExists = 1;
        else CopyExists = 0;
        if(!register_client()) return;
    }
    if(find_player(Name)) CopyExists = 1;
    else CopyExists = 0;
    continue_login();
}

static void continue_login() {
    if((int)master()->is_locked()) { 
        message("news", read_file(LOCKED_NEWS), this_object());
        if(locked_access()) 
          message("system", "\n    >>> Access allowed <<<\n", this_object()); 
        else { 
            message("system", "\n    >>> Access denied <<<\n", this_object()); 
            internal_eventDestruct();
            return; 
	  } 
      } 
    if(!user_exists(Name)) { 
        if(!((int)BANISH_D->valid_name(Name))) { 
            message("system", sprintf("\n%s is not a valid name choice for %s.\n", 
              capitalize(Name), mud_name()), this_object()); 
            message("system", sprintf("Names must be alphabetic characters no " 
	      "longer than %d letters,\nand no less than %d letters.\n", 
              MAX_USER_NAME_LENGTH, MIN_USER_NAME_LENGTH), this_object()); 
            message("prompt", "\nPlease enter another name: ", this_object()); 
            input_to("get_name"); 
            return; 
	  } 
        if(!((int)BANISH_D->allow_logon(Name, query_ip_number()))) { 
            message("news", read_file(REGISTRATION_NEWS), this_object()); 
            internal_eventDestruct();
            return; 
	  } 
        message("prompt", sprintf("Do you really wish %s to be your name? (y/n) ", 
          CapName), this_object()); 
        Player = (object)master()->player_object(Name);
        input_to("new_user"); 
        return; 
      } 
    if(!((int)BANISH_D->allow_logon(Name, query_ip_number()))) { 
        message("news", read_file(BANISHED_NEWS), this_object()); 
        internal_eventDestruct();
        return; 
      } 
    Player = (object)master()->player_object(Name);
    message("password", "Password: ", this_object());
    if(Client) input_to("get_password");
    else input_to("get_password", I_NOECHO | I_NOESC);
  } 
 
static void get_password(string str) { 
    if(!str || str == "") { 
        message("system", "\nYou must enter a password.  Try again later.\n", 
          this_object()); 
        internal_eventDestruct();
        return; 
      } 
    if(!check_password(str)) { 
        message("system", "\nInvalid password.\n", this_object()); 
        if(++CrackCount > MAX_PASSWORD_TRIES) { 
            message("system", "No more attempts allowed.\n", this_object()); 
            internal_eventDestruct();
            return; 
	  } 
        log_file("watch/logon", sprintf("%s from %s\n", Name, query_ip_number())); 
        message("password", "Password: ", this_object());
        if(Client) input_to("get_password");
        else input_to("get_password", I_NOECHO | I_NOESC);
        return; 
      } 
    if(!CopyExists) exec_user();
    else boot_copy(); 
  } 
 
static private int locked_access() { 
    int i; 
    
    if((int)BANISH_D->is_guest(Name)) return 1; 
    i = sizeof(LOCKED_ACCESS_ALLOWED); 
    while(i--) if(member_group(Name, LOCKED_ACCESS_ALLOWED[i])) return 1; 
    return 0; 
  } 
 
static private int check_password(string str) { 
    string pass; 
 
    if((pass = (string)Player->GetPassword()) != crypt(str, pass)) return 0; 
    return valid_site(query_ip_number()); 
  } 
 
static private int valid_site(string ip) { 
    string a, b; 
    string *miens; 
    int i; 
 
    if(!(i = sizeof(miens = (string *)Player->query_valid_sites()))) return 1; 
    while(i--) { 
        if(ip == miens[i]) return 1; 
        if(sscanf(miens[i], "%s.*s", a) && sscanf(ip, a+"%s", b)) return 1; 
      } 
    return 0; 
  } 
 
static private int boot_copy() { 
    if(interactive(Player)) { 
        message("system", "\nThere currently exists an interactive copy of you.\n", 
          this_object()); 
        message("prompt", "Do you wish to take over this interactive copy? (y/n) ", 
          this_object()); 
        input_to("disconnect_copy", I_NORMAL); 
        return 1; 
      } 
    log_file("enter", sprintf("%s (exec): %s\n", Name, ctime(time()))); 
    if(exec(Player, this_object())) Player->restart_heart(); 
    else message("system", "Problem reconnecting.\n", this_object()); 
    internal_eventDestruct();
    return 1; 
  } 
 
static void disconnect_copy(string str) { 
    object tmp; 
 
    if((str = lower_case(str)) == "" || str[0] != 'y') { 
        message("system", "\nThen please try again later!\n", this_object()); 
        internal_eventDestruct();
        return; 
      } 
    message("system", "You are being taken over by hostile aliens!", Player); 
    exec(tmp = new(LIB_CREATOR), Player); 
    exec(Player, this_object()); 
    Player->SetClient(Client);
    destruct(tmp); 
    message("system", "\nAllowing login.\n", Player); 
    internal_eventDestruct();
  } 
 
static private void exec_user() { 
    if(!exec(Player, this_object())) { 
        message("system", "\nProblem connecting.\n", this_object()); 
        Player->eventDestruct();
        destruct(this_object());
        return; 
      } 
    Player->SetClient(Client);
    Player->SetTerminal(TermType);
    Player->SetScreen(Screen[0], Screen[1]);
    catch(Player->Setup());
    destruct(this_object()); 
} 
 
static void new_user(string str) { 
    if((str = lower_case(str)) == "" || str[0] != 'y') { 
        message("prompt", "\nOk, then enter the name you really want: ", this_object()); 
        Player->eventDestruct();
        input_to("get_name"); 
        return; 
      } 
    log_file("new_players", sprintf("%s : %s : %s\n", query_ip_number(), Name,  
      ctime(time()))); 
    message("password", "Please choose a password of at least 5 letters: ", 
      this_object()); 
    if(Client) input_to("choose_password");
    else input_to("choose_password", I_NOECHO | I_NOESC);
  } 
 
static void choose_password(string str) { 
    if(strlen(str) < 5) { 
        message("system", "\nYour password must be at least 5 letters long.\n", 
          this_object()); 
        message("password", "Please choose another password: ", this_object()); 
        if(Client) input_to("choose_password");
        else input_to("choose_password", I_NOECHO | I_NOESC);
      } 
    message("password", "\nPlease confirm your password choice: ", this_object()); 
    if(Client) input_to("confirm_password", str);
    else input_to("confirm_password", I_NOECHO | I_NOESC, str);
  } 
 
static void confirm_password(string str2, string str1) { 
    if(str1 == str2) { 
        Player->SetPassword(str2 = crypt(str2, 0)); 
        message("prompt", "\nPlease choose an interesting gender (male or female): ", 
          this_object()); 
        input_to("choose_gender"); 
        return; 
      } 
    else { 
        message("password", "\nPassword entries do not match.  Choose a password: ", 
          this_object()); 
        if(Client) input_to("choose_password");
        else input_to("choose_password", I_NOECHO | I_NOESC); 
        return; 
      } 
  } 
 
static void choose_gender(string str) { 
    if(str != "male" && str != "female") { 
        message("system", "\nCute, but pretend to be either male or female instead\n", 
          this_object()); 
        message("prompt", "Gender: ", this_object()); 
        input_to("choose_gender"); 
        return; 
      } 
    Player->SetGender(str); 
    message("system", sprintf("You may format %s to appear however you want "
      "using alternative\ncapitalization, spaces, \"'\", or \"-\".\n", CapName), 
        this_object());
    message("prompt", sprintf("Please choose a display name (default: %s): ", CapName), this_object());
    input_to("choose_cap_name");
}

static void choose_cap_name(string str) {
    if(!str || str == "") str = capitalize(CapName);
    if(!((int)BANISH_D->valid_cap_name(str, Name))) {
        message("prompt", "Incorrect format.  Choose again: ", this_object());
        input_to("choose_cap_name");
        return;
    }
    Player->SetCapName(capitalize(str));
    message("prompt", "Email: ", this_object());
    input_to("enter_email"); 
  } 
 
static void enter_email(string str) { 
    string a, b; 
 
    if(!str || str == "" || sscanf(str, "%s@%s", a, b) != 2) { 
        message("system", "\nEmail must be in the form user@host.\n", 
          this_object()); 
        message("prompt", "Email: ", this_object());
        input_to("enter_email"); 
        return; 
      } 
    Player->SetEmail(str); 
    message("prompt", "\nIf you do not mind, enter your real name (optional): ", 
      this_object()); 
    input_to("enter_real_name"); 
  } 
 
static void enter_real_name(string str) { 
    if(!str || str == "") str = "Unknown"; 
    Player->SetRealName(str); 
    log_file("enter", sprintf("%s (new player): %s\n", CapName, 
			      ctime(time()))); 
    exec_user(); 
} 
 
static void idle() { 
    receive("\nLogin timed out.\n");
    internal_eventDestruct();
  } 
 
void receive_message(string cl, string msg) { 
    if(Client) receive("<"+cl+">"+msg+"\n");
    else receive(msg);
  } 

static private void internal_eventDestruct() {
    if(Player && !CopyExists) destruct(Player);
    destruct(this_object());
}

void eventDestruct() {
    internal_eventDestruct();
}

static int register_client() {
    string client, ver;

    if(sscanf(Client, "%s/%s", client, ver) != 2) ver = 0;
    if(member_array(Client, SUPPORTED_CLIENTS) == -1) {
        receive("<protocol>"+implode(SUPPORTED_CLIENTS, ",")+"\n");
        input_to("input_protocol");
        return 0;
    }
    receive("<connect>\n");
    return 1;
}

static void input_protocol(string str) {
    string classes, client;

    if(sscanf(str, "<%s>%s", classes, client) != 2  || classes != "protocol" ||
      member_array(client, SUPPORTED_CLIENTS) == -1 || client == "none")
        Client = 0;
    else Client = client;
    if(Client) receive("<connect>\n");
    continue_login();
}

string GetKeyName() {
    if(!interactive(this_object())) return 0;
    else if(Name) return Name;
    else return "";
}

string GetCapName() {
    string tmp;

    tmp = GetKeyName();
    return (tmp ? capitalize(tmp) : "");
}

void terminal_type(string str) {
    if( !stringp(str) ) return;
    else TermType = lower_case(str);

}

void window_size(int width, int height) {
    Screen = ({ width, height });
}

string *GetChannels() { return ({}); } /* This is for chat daemon */