/
CDC-1.2b/
CDC-1.2b/src/
parent $connection_interfaces
object $http_interface

var $root dbref 'http_interface
var $root child_index 3435
var $root fertile 1
var $root manager $http_interface
var $root owned [$http_interface]
var $root owners [$http_interface]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $has_commands commands [["GET *", 'get_cmd]]
var $has_commands shortcuts []
var $connection_interfaces connection 0
var $root inited 1
var $http_interface uri ""
var $http_interface header #[]
var $http_interface http_version ""
var $http_interface method ""
var $http_interface status 0
var $old_command_environment verb_cache #[]
var $old_command_environment command_cache [["GET *", 'get_cmd]]
var $old_command_environment shortcuts_cache []

method init_http_interface
    (> .perms(caller(), $root) <);
    status = 0;
    uri = "";
    header = #[];
    http_version = "";
    method = "";
.

method get_cmd
    arg cmd, line;
    
    if (status == 0) {
        if (!line) {
            line = "Invalid use of method GET.";
            .send_response($http.get_error(403, line));
            return 'disconnect;
        }
        line = explode(line);
        if (listlen(line) > 1)
            http_version = line[2];
        else
            http_version = "HTTP/1.0";
        uri = line[1];
        method = "GET";
        status = 1;
    } else {
        line = "Method GET already received!";
        .send_response($http.get_error(400, line));
        return 'disconnect;
    }
.

method invalid_cmd
    arg line;
    var lines;
    
    if (status == 1) {
        // I had it set to be just ":" but I think spaces should be in them.
        line = explode(line, ": ");
        if (listlen(line) == 1)
            line = [@line, ""];
        else if (listlen(line) > 2)
            line = [line[1], $list.to_string(sublist(line, 2))];
        header = header.add_elem(line[1], line[2]);
    } else {
        line = ("Invalid method: \"" + line) + "\".";
        .send_response($http.get_error(400, line));
        return 'disconnect;
    }
.

method send_response
    arg body, [args];
    var types, buffer, c;
    
    types = [@args, "text/html"][1];
    switch (type(body)) {
        case 'list:
            buffer = $list.to_buffer(body);
        case 'buffer:
            buffer = body;
    }
    c = .connection();
    c.send("HTTP/1.0 200 OK");
    c.send("Server: ColdWeb/0.1");
    c.send("Content-type: " + types);
    c.send("Content-length: " + tostr(buffer_len(buffer)));
    c.send("");
    c.echo(buffer, 'buffer);
    .log_request(buffer_len(buffer));
.

method error
    arg error, str;
    var lines, x;
    
    lines = (| errors[error] |) || ["Oops, server just broke."];
    for x in (lines)
        strsub(x, "%s", str).send_response(lines);
.

method uninit_http_interface
    (> .perms(caller(), $root) <);
    uri = "";
    header = #[];
    http_version = "";
    method = "";
.

method null_cmd
    arg line;
    
    .process_http_method();
    return (> pass(line) <);
.

method log_request
    arg content_length;
    var line, c, agent;
    
    // was going to have this be like the standard logfile, but decided
    // I didn't like that
    c = .connection();
    line = c.address();
    agent = (| ((.header())["User-Agent"])[1] |) || "";
    line = (((((((line + " \"") + method) + " ") + uri) + " ") + http_version) + "\" ") + agent;
    $http_log.log(line);
.

method process_GET
    var path, output, object, line, bin, ctype;
    
    (> .perms(sender(), 'this) <);
    
    // Ok, we are going to interpret the URI in funky ways.
    path = explode(uri, "/");
    ctype = "text/html";
    if (!path) {
        output = ($login.build_html()) + ($http_root_file.retrieve_html());
    } else if (((path[1])[1]) == "~") {
        object = (| $user_db.find(substr(path[1], 2)) |);
        output = (| object.http_request(method, sublist(path, 2)) |);
    } else if ((path[1]) == "objects") {
        object = (| $object.to_dbref(path[2]) |);
        output = (| object.generate_html(@sublist(path, 3)) |);
    } else if (match_begin("bin", path[1])) {
        if (listlen(path) > 2)
            line = $list.to_string(sublist(path, 3));
        if ("?" in (path[2])) {
            line = substr(path[2], ("?" in (path[2])) + 1) + (line || "");
            bin = substr(path[2], 1, ("?" in (path[2])) - 1);
        } else {
            bin = path[2];
        }
        output = (| $http.(tosym("bin_" + bin))(line) |);
    } else {
        object = $http_root_file.find_file([$http_root_file.filename(), @path]);
        output = (| object.retrieve_html() |);
        ctype = (| object.content_type() |);
    }
    if (!output) {
        line = ("Unable to find " + uri) + ".";
        output = $http.get_error(404, line);
    }
    
    // intentionally add the tail here, we can slap tCD comments
    // at the end.
    if (ctype == "text/html")
        output = output + ["<hr size=4><a href=\"/\"><b>the Cold Dark</b></a></body>"];
    else if (ctype == "text/plain")
        output = output + ["-------------", "the Cold Dark"];
    .send_response(output, ctype);
.

method process_http_method
    (> .perms(sender(), 'this) <);
    .(tosym("process_" + method))();
.

method header
    return header;
.