/
ColdWeb-0.2/
ColdWeb-0.2/root/
// ------------------------------------------------------------------
// Object $http

parent $daemon
object $http

var $http header #[]
var $http method ""
var $http http ""
var $http status 0
var $http URI ""
var $http bytes 0
var $http ctype ""
var $http full 0

method initialize
    (| pass() |);
    header = #[];
    method = "";
    http = "HTTP/1.0";
    status = 200;
    URI = "";
    ctype = $sys.htmlv();
    full = 1;
.

method set_status
    arg status;

    set_var('status, status);
.

method process_header
    arg line, i;
    var n, v;

    if (!method) {
        status = 400;
        return .respond($sys.response(400, "No Method Specified!"));
    }
    n = substr(line, 1, i - 1);
    if (line[i + 1] == " ")
        i = i + 1;
    v = substr(line, i + 1);
    header = header.add_elem(n, v);
.

method process_method
    arg line;

    line = explode(line);
    if (!(line[1] in $sys.methods())) {
        status = 405;
        return .respond($sys.response(status,
                        "Method: \"" + line[1] + "\"."));
    }
    method = line[1];
    line = delete(line, 1);
    if (!line) {
        status = 400;
        return .respond($sys.response(status, "No URI specified!"));
    }
    URI = line[1];
    if (listlen(line) > 1) {
        http = line[2];
    } else {
        http = "HTTP/0.9";
        full = 0;
    }
.

method handle_method
    if (!method) {
        status = 400;
        return .respond($sys.response(status, "No Method specified!"));
    }
    .(tosym("method_" + method))();
.

method process_line;
    arg line;
    var i;

    if (i = (":" in line)) {
        .process_header(line, i);
    } else if (line) {
        // if return's false, it is a simple request, do not wait for CR
        .process_method(line);
        if (!full) {
            if (method != "GET") {
                status = 400;
                .respond($sys.response(status, "Invalid HTTP/0.9 method."));
            } else
                .handle_method();
        }
    } else {
        .handle_method();
    }
.

method log_request
    var line;

    line = .host() + " - - [" + timestamp() + "] \"" + method + " " +
            URI + " " + http + "\" " + tostr(status) + " " + tostr(bytes);
    if ((| header["User-Agent"] |))
         line = line + ";; " + header["User-Agent"].to_string();
    .lwrite(line);
.

method send_header
    if (full)
        .send([http + " " + tostr(status),
               "Server: ColdWeb/0.2",
               "Content-type: " + ctype,
               "Content-length: " + tostr(bytes),
               ""]);
.

method respond
    arg body;

    if (type(body) != 'buffer)
        body = buffer_from_strings(body);
    bytes = buffer_len(body);
    .send_header();
    echo(body);
    .close();
    .log_request();
.


method respond_with_file
    arg fstat;

    bytes = fstat[2];
    .send_header();
    echo_file(URI);
    .close();
    .log_request();
.

method find_filename
    var file, actual, stat, ifiles, i;

    stat = (| stat_file(URI) |);
    if (!stat) {
        ifiles = ["home.html", "index.html", "welcome.html"];
        file = URI;
        actual = URI;
        if (file[strlen(file)] != "/")
            file = file + "/";
        while (!stat && ifiles) {
            URI = file + ifiles[1];
            stat = (| stat_file(URI) |);
            ifiles = delete(ifiles, 1);
        }
        if (!stat) {
            URI = actual;
            status = 404;
            .respond($sys.response(status,
                     "Unable to find URL " + toliteral(URI) + "."));
            return 0;
        }
    }

    if (i = URI.rindex(".")) {
        switch (substr(URI, i + 1)) {
            case "txt":
                ctype = "text/plain";
            case "gif":
                ctype = "image/gif";
        }
    }

    return stat;
.

method method_GET
    var stat;

    if (!stat = .find_filename())
        return;
    .respond_with_file(stat);
.

method method_HEAD
    var stat;

    if (!(stat = .find_filename()))
        return;
    bytes = stat[2];
    .send_header();
    .close();
    .log_request();
    .respond_with_file(stat);
.