@create $thing named Web Server:Web Server,WWW,httpd @rmprop #0.httpd @corify httpd as $httpd @prop $httpd."port" 70 rc @prop $httpd."calls" {} rc ;$httpd.calls = {"index", "login"} @prop $httpd."base64" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" rc @prop $httpd."help_msg" {} rc @edit $httpd.help_msg enter Ender/Amigo's Generic Web Server ------------------------------------- (For updates, e-mail ender@enderboi.com) ------------------------------------- This object, $httpd, contains all the verbs needed for the main handling of HTML requests. $webbable (Generic Webbable) contains all the properties and verbs for returning most actual HTML responses from individual objects. Operation --------- Upon recieving a HTML request, this object first searches it's .call's property, which contains a list of verbs on $httpd itself which are callable. If the URL requested doesn't exist on $httpd, the server treats it as an object and attempts to call :_html on it. Eg: http://moo.server:port/54 The Web Server will attempt to execute #54:_html. To this verb, it will pass two arguments. The first is the exact page requested, the second a list of headers the web browser passed to the server. Note the server will also try and check the page against corified objects (eg http://moo.server:port/$httpd) All :_html and other callable verbage should return valid HTML -AS A LIST-. The following properties are available: $httpd.port - The port this server listens on $httpd.calls - Contains a list of verbs on $httpd accessable directly (eg, with http://moo.server:port/verbname) The following verbs are available (help $httpd:verbname for more information on each of these): $httpd:start - Frontend to $httpd:server_started. Allows user to type 'start $httpd' $httpd:server_started - Starts the web server listening $httpd:do_login_command - Parses the initial client connection $httpd:do_get - Searches for a valid object/verb, and executes it (for GET requests only) $httpd:do_post - As above, but for POST requests $httpd:error - Return an error page $httpd:index - A wrapper to the page to use by default. $httpd:authorise - Used to force a player to login via WWW $httpd:GetVariable - Return one of the header values $httpd:from64 - De-Base64 encode something . save done @prop $httpd."noauth" 0 rc @prop $httpd."version" 0.4 rc ;;$httpd.("aliases") = {"Web Server", "WWW"} ;;$httpd.("description") = {"You see a small black cube, with a speaker mounted on one side, and a small power light on the top. There is one button next to the light labelled 'Stop'"} @verb $httpd:"start" this none none @program $httpd:start if ((caller != #0) && (!caller.wizard)) player:tell("The cube bleeps, and a female voice whispers 'Access Denied'"); endif result = this:server_started(); if (typeof(result) == INT) player:tell("The cube bleeps, and a female voice whispers 'System Online'"); else player:tell("The cube bleeps, and a female voice whispers 'System Failure'"); endif . @verb $httpd:"do_login_command" none none none rx @program $httpd:do_login_command args = $string_utils:explode(argstr, " "); what = args[1]; where = args[2]; if (!what) return; endif if ((what != "POST") && (what != "GET")) player:notify("501 Method Not Implimented"); boot_player(player); endif envirovars = ""; while (1) string = read(player); if (string == "") break; endif envirovars = (envirovars + "***") + string; endwhile if (what == "POST") this:do_post(args[2], envirovars); endif if (what == "GET") this:do_get(args[2], envirovars); endif return 0; . @verb $httpd:"do_get" this none this rx @program $httpd:do_get where = $string_utils:explode(args[1], "/"); connection = player; if (where[1] == E_RANGE) where = {"index"}; endif if (where[1] in this.calls) out = this:(where[1])(args[1], args[2]); else out = #0.(where[1]):_html(args[1], args[2]); if (typeof(out) == ERR) out = toobj(where[1]):_html(args[1], args[2]); if (out == E_VERBNF) out = this:error(where[1], 404); endif endif endif for line in (out) notify(connection, line, 1); $command_utils:suspend_if_needed(1); if (!(connection in connected_players(1))) return; endif endfor boot_player(connection); . @verb $httpd:"error" none none none rxd @program $httpd:error where = args[1]; code = args[2]; return {"Server Error: ", tostr(code)}; . @verb $httpd:"index" none none none rxd @program $httpd:index return $player_start:_html(@args); . @verb $httpd:"server_started" this none this rx @program $httpd:server_started return listen(this, this.port); . @verb $httpd:"look_self" this none this rx @program $httpd:look_self player:Tell_lines(this.description); for z in (listeners()) if (z[1] == this) player:tell("The power light is on."); return; endif endfor player:tell("The power light is off."); . @verb $httpd:"authorise" none none none rx @program $httpd:authorise whom = #-1; pwd = "notvalid"; out = {}; basic = $httpd:GetVariable(args[2], "Authorization"); basic = basic[8..$]; if (basic) plaintext = $httpd:from64(basic); pwdpair = $string_utils:explode(plaintext, ":"); whom = $string_utils:match_player(pwdpair[1]); if (valid(whom)) pwd = crypt(pwdpair[2], whom.password); endif endif if (whom.password == 0) return whom; endif if (pwd == whom.password) return whom; endif out = {@out, "HTTP/1.1 401 Access Denied", "WWW-Authenticate: Basic realm=\"MOO Login\""}; out = {@out, "", "You must enter a valid MOO username/password to access this resource"}; return out; . @verb $httpd:"GetVariable" this none this @program $httpd:GetVariable envirovars = args[1]; variables = $string_utils:explode(envirovars, "***"); for z in (variables) string = $string_utils:explode(z, ":"); if (string[1] == args[2]) return string[2]; endif endfor return ""; . @verb $httpd:"from64" this none this rx @program $httpd:from64 "This code stolen from $math_utils:from64 @ Midgard"; "Thanks Marty :)"; ":from64(STR base64-encoded input) => STR decoded output"; Out = {}; Input = args[1]; for I in [1..length(Input)] if (Input[I] != "=") Char = index(this.base64, Input[I], 1) - 1; Out = {@Out, Char}; endif if ((ticks_left() < 2000) || (seconds_left() < 2)) suspend(0); endif endfor Bin = ""; for I in (Out) Bin = Bin + $string_utils:right($math_utils:base_conversion(I, 10, 2), 6, "0"); if ((ticks_left() < 2000) || (seconds_left() < 2)) suspend(0); endif endfor Out = ""; for I in [1..length(Bin) / 8] Char = Bin[((I - 1) * 8) + 1..((I - 1) * 8) + 8]; Out = Out + $string_utils:from_ascii(tonum($math_utils:base_conversion(Char, 2, 10))); if ((ticks_left() < 2000) || (seconds_left() < 2)) suspend(0); endif endfor return Out; . @verb $httpd:"test" this none this rx @program $httpd:test "Example of authentication"; authorised = $httpd:authorise(@args); if (typeof(authorised) == LIST) return authorised; endif out = {("Your an OK user, " + tostr(authorised)) + " :)", "
", args[1], " | "}; out = {@out, "(", args[2], ") | "}; out = {@out, "
"}; html = {@html, tostr(this.nogo_msg)}; html = {@html, ""}; html = {@html, "