/
CDC-1.1/
parent $has_commands
object $old_connection

var $old_connection user 0
var $old_connection addr 0
var $old_connection port 0
var $old_connection buffer `[]
var $old_connection connect_help ["Connection HELP", "===============", "", "Creating a user:          `create <username> <password> <email>`", "", "Connecting as a guest:    `connect guest <name> <email>`", "              Example:    `connect guest John Doe johnd@site.usa.com`", "", "Connecting as a user:     `connect <name> <password>`", "             Example:     `connect John Doe mypassword`", "", "Quitting (this screen):   `quit`   or   `@quit`", "", "Connected User's Listing: `who`    or   `@who`"]
var $old_connection connect_notes []
var $has_commands commands [["@quit|QUIT", 'quit_cmd], ["h?elp", 'help_cmd], ["@who|WHO", 'who_cmd], ["c?onnect guest *", 'connect_guest_cmd], ["c?onnect *", 'connect_cmd], ["m?otd", 'motd_cmd], ["c?reate *", 'create_cmd]]
var $has_commands shortcuts []
var $root inited 1
var $root child_index 5481
var $root owners [$old_connection]
var $root fertile 1
var $root owned [$old_connection]
var $root manager $old_connection
var $root writable [$old_connection]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'old_connection
var $old_connection ip 0

method init_old_connection
    .perms(caller(), $root);
    user = 0;
    addr = 0;
    port = 0;
    ip = 0;
    buffer = `[];
.

method uninit_old_connection
    .perms(caller(), $root);
    user.connection_logged_out(addr, port);
.

method tell
    arg what, [format];
    var l;
    
    // Crag: added caller() != $parse so I can use $parse.tell_error().
    // sigh...
    if ((sender() != this()) && ((sender() != user) && (caller() != $parse)))
        throw(~perm, "Sender not this or the user.");
    
    // if (user)
    //  .prompt(user.get_prompt(), 1);
    echo(buffer_from_strings([what]));
    
    // if (user)
    //  .prompt(user.get_prompt(), 0);
.

method connect
    arg [args];
    var x, addr_arg, port_arg;
    
    if (sender() != 0)
        throw(~perm, "Sender not the server.");
    addr_arg = args[1];
    port_arg = args[2];
    addr = hostname(addr_arg);
    ip = addr_arg;
    port = port_arg;
    if (!(| .motd() |)) {
        .tell("Error displaying the Message of the Day, hit enter once, if this problem");
        .tell("continues email: " + ($sys.get_system_email('login)));
    }
    $sys.connection_starting();
    (| $scheduler.add_task(300, 'timeout) |);
.

method disconnect
    if (sender() != 0)
        throw(~perm, "Sender not the server.");
    .tell("Goodbye.");
    .destroy();
.

method parse
    arg incoming;
    var lines, line, loc;
    
    if ((sender() != 0) && (caller() != 0))
        throw(~perm, "Sender and caller are not the server");
    lines = buffer_to_strings(buffer_append(buffer, incoming));
    buffer = lines[listlen(lines)];
    for line in (sublist(lines, 1, listlen(lines) - 1))
        (| .parse_line(line) |);
.

method parse_line
    arg str;
    var cmd, x, coms;
    
    if ((caller() != definer()) || (sender() != this()))
        throw(~perm, "Invalid access to private method.");
    
    // send it to the user object, otherwize they are at the MOTD
    if (user) {
        if ((user.parse_line(str)) == 'disconnect)
            disconnect();
        return;
    }
    
    // they are at the MOTD
    // Display tracebacks, even though user may be clueless
    catch any {
        cmd = .match_command(str);
        if (cmd) {
            .(cmd[1])(@cmd[2]);
        } else {
            .tell("");
            if (str)
                .tell(("I don't understand \"" + ($string.chop(str, 57))) + "\".");
            .tell("Try: help, quit, who, motd, create, connect, or connect guest.");
        }
    } with handler {
        if (((traceback()[1])[3]) != 'no_traceback) {
            for str in (traceback())
                .tell(str);
        }
    }
    if (!user)
        .enh_tell(["", "> "]);
.

method user
    return user;
.

method addr
    return addr;
.

method port
    return port;
.

method connect_cmd
    arg com, words;
    var words, u, password, salt, syn, name, passwd;
    
    .perms(sender(), 'this);
    
    // arrg, this is kludgy, but its the best we can do on $old_connection
    syn = "`connect <name> <pass>' (last word is taken as the password)";
    
    // Get user name and password--sort accordingly
    words = explode(words);
    if (listlen(words) < 2)
        $parse.tell_error(syn);
    passwd = words[listlen(words)];
    name = $list.to_string(sublist(words, 1, listlen(words) - 1));
    
    // Look for a user with the given name.
    catch ~namenf {
        u = $user_db.find(name);
    } with handler {
        $parse.tell_error("Either that user does not exist or has a different password.", syn);
    }
    
    // Check if the password is correct.
    if (!(u.check_password(passwd)))
        $parse.tell_error("Either that user does not exist or has a different password.", syn);
    
    // Log the user in.
    user = u;
    user.connection_logged_in(addr, port);
.

method create_cmd
    arg com, words;
    var words, syn;
    
    syn = "!  Usage: `create <name> <password> <email@host>'";
    if (sender() != this())
        throw(~perm, "Sender is not this.");
    
    // Get user name, password, and email.
    words = explode(words);
    if (listlen(words) != 3)
        return .tell(syn);
    
    // Create a new user object.
    catch any {
        user = $sys.create_user(words[1], words[2], words[3]);
    } with handler {
        .tell(syn);
        switch (error()) {
            case ~duplicate:
                .tell(("!  The user " + toliteral(words[1])) + " already exists.");
            default:
                .tell("!  There was a problem creating you:");
                .tell("!  => " + ((traceback()[1])[2]));
                .tell("!  If there is a problem contact: " + ($sys.get_system_email('login)));
    
                // $sys.log(traceback());
        }
        if (user) {
            (| user.destroy() |);
            user = 0;
        }
        return;
    }
    
    // Log the user in.
    user.connection_logged_in(addr, port);
.

method quit_cmd
    arg dummy;
    
    if (sender() != this())
        throw(~perm, "Sender is not this.");
    .tell("Goodbye.");
    disconnect();
.

method user_going_away
    if (caller() != $user)
        throw(~perm, "Caller is not $user.");
    disconnect();
.

method connect_guest_cmd
    arg com, com2, words;
    var syn, email, name, result;
    
    .perms(sender(), 'this);
    syn = "=> Syntax: 'connect guest <name> <email>' (type 'help' for more help)";
    
    // Get user name and password.
    words = explode(words);
    if (listlen(words) < 2)
        return .tell(syn);
    name = $list.to_string(sublist(words, 1, listlen(words) - 1));
    email = words[listlen(words)];
    result = $code.valid_email(email);
    if ((result[1]) != 'valid) {
        switch (result[1]) {
            case 'invalid:
                .tell("!  The given email address is not a legitimate address.");
                .tell("!  Specify both username and hostname (do not use brackets).");
                return;
            case 'invip, 'invhostname:
                .echo($string.wrap_line(((("The hostname \"" + (result[3])) + "\" is invalid, when in actuality you are connecting from \"") + ((addr == "-1") ? ip | addr)) + "\".  The server is not currently locking out invalid email addresses, although your connection has been noted (We do realize that some hosts may not function normally).", 79, "!  ", 1));
                $channels.announce('System, ((((((("Invalid Connection Email: " + email) + " <") + addr) + ":") + ip) + "> (") + name) + ")");
        }
    }
    catch any {
        user = $sys.create_user(name, 0, email, 'anonymous_class);
    } with handler {
        .tell(syn);
        switch (error()) {
            case ~duplicate:
                .tell(("!  The name " + toliteral(words[1])) + " is already in use.");
            default:
                .tell("!  There was a problem creating you:");
                .tell("!  => " + ((traceback()[1])[2]));
                .tell("!  If there is a problem contact: " + ($sys.get_system_email('login)));
        }
        // $sys.log(traceback());
        return;
    }
    
    // Log the user in.
    $sys.log((("GUEST: " + (words[1])) + " ") + (words[2]));
    user.connection_logged_in(addr, port);
.

method echo_file
    arg what;
    
    if ((sender() != this()) && (sender() != user))
        throw(~perm, "Sender not this or the user.");
    echo_file(what);
.

method spiffy_quote
    return $code.random_theme_quote();
.

method connect_help
    return connect_help;
.

method who_cmd
    arg com;
    var l;
    
    for l in ($code.generate_listing($user_db.connected()))
        .tell(l);
.

method motd
    var line, stuff;
    
    // a slightly cooler in-db welcome message
    if ((sender() != this()) || (caller() != definer()))
        throw(~perm, "Invalid access to private method.");
    .echo($motd.build('default));
    .tell("");
    .echo(" ** Use 'H?elp' for a list of commands **", 'center);
    .tell("");
.

method enh_tell
    arg what;
    var elem, out;
    
    // Echo list consisting of buffers and strings.
    // if (!$sys.is_system(sender()) && (caller() != $user || sender() != this()))
    //  throw(~perm, "Permission Denied: Invalid call to a private method.");
    for elem in (what) {
        if (type(elem) == 'string)
            echo(buffer_truncate(buffer_from_strings([elem]), strlen(elem)));
        else
            echo(elem);
    }
.

method enh_tell_move
    arg X, Y;
    
    // Move cursor on most ANSI and VT terminals to X,Y
    .enh_tell([`[27], ((("[" + tostr(Y)) + ";") + tostr(X)) + "H"]);
.

method help_cmd
    arg com;
    var l;
    
    .perms(sender(), 'this);
    for l in ($old_connection.connect_help())
        .tell(l);
.

method connect_notes
    return connect_notes;
.

method prompt
    arg prompt, [erase];
    var buf;
    
    buf = buffer_from_strings([prompt]);
    buf = buffer_truncate(buf, buffer_len(buf) - 2);
    erase = erase && (erase[1]);
    if (erase) {
        buf = buffer_len(buf);
        while (buf) {
            echo(`[8]);
            buf = buf - 1;
        }
    } else {
        echo(buf);
        if (prompt)
            echo(`[255, 249]);
    }
.

method echo
    arg what, [format];
    var l;
    
    // the difference being that this one is designed for non-connected conns
    if ((sender() != this()) && (sender() != user))
        throw(~perm, "Sender not this or the user.");
    format = [@format, 'none][1];
    if (type(what) == 'list) {
        for l in (what)
            .echo(l, format);
    } else {
        switch (format) {
            case 'center:
                what = $string.center(what, 79);
        }
        echo(buffer_from_strings([what]));
    }
.

method motd_cmd
    arg [args];
    
    .perms(sender(), 'this);
    .motd();
.

method timeout
    .perms(sender(), 'this);
    if (!user) {
        .tell("Timeout (5 minutes).");
        disconnect();
    }
.