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;
.