From 6e8e05535944d95fe85589caeb4d5ef3fe015d3d Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Fri, 25 Feb 2011 22:24:01 -0700 Subject: [PATCH] Add wopr files --- packages/wopr/index.html | 14 + packages/wopr/tokens.txt | 17 + packages/wopr/wopr.cgi | 824 +++++++++++++++++++++++++++++++++++++++ packages/wopr/wopr.css | 32 ++ packages/wopr/wopr.js | 74 ++++ 5 files changed, 961 insertions(+) create mode 100644 packages/wopr/index.html create mode 100644 packages/wopr/tokens.txt create mode 100755 packages/wopr/wopr.cgi create mode 100644 packages/wopr/wopr.css create mode 100755 packages/wopr/wopr.js diff --git a/packages/wopr/index.html b/packages/wopr/index.html new file mode 100644 index 0000000..f06212c --- /dev/null +++ b/packages/wopr/index.html @@ -0,0 +1,14 @@ + + + merf + + + + +
Connecting...
+
+ + +
+ + diff --git a/packages/wopr/tokens.txt b/packages/wopr/tokens.txt new file mode 100644 index 0000000..54cc330 --- /dev/null +++ b/packages/wopr/tokens.txt @@ -0,0 +1,17 @@ +wopr:xipir-cavud-libux +wopr:xirak-zoses-gefox +wopr:xetil-rokak-robyx +wopr:xofic-belid-civox +wopr:xelev-lepur-pozyx +wopr:xocom-bysik-mapix +wopr:xoroc-hunaz-vyhux +wopr:xigeh-lydut-vinax +wopr:xipar-canit-zimyx +wopr:xocec-lifoz-gasyx +wopr:xubif-hikig-mocox +wopr:xoroz-hymaz-fivex +wopr:xufov-sugig-zecox +wopr:xocem-dabal-fisux +wopr:xufez-dofas-tyvyx +wopr:xosov-tenoh-nebox +wopr:xopev-zihuk-hubyx diff --git a/packages/wopr/wopr.cgi b/packages/wopr/wopr.cgi new file mode 100755 index 0000000..de901bc --- /dev/null +++ b/packages/wopr/wopr.cgi @@ -0,0 +1,824 @@ +#! /usr/bin/lua + +require("lfs") + +BASEDIR = "/var/tmp/wopr" +POST_MAX = 512 + +method = os.getenv("REQUEST_METHOD") +if (method == "POST") then + local CL = tonumber(os.getenv("CONTENT_LENGTH")) or 0 + if (CL > POST_MAX) then + CL = POST_MAX + end + function getc() + if (CL > 0) then + CL = CL - 1 + return io.read(1) + else + return nil + end + end +elseif (method == "GET") then + local query = os.getenv("QUERY_STRING") or "" + local query_pos = 0 + local query_len = string.len(query) + if (query_len > POST_MAX) then + query_len = POST_MAX + end + function getc() + if (query_pos < query_len) then + query_pos = query_pos + 1 + return string.sub(query, query_pos, query_pos) + else + return nil + end + end +else + print("405 Method not allowed") + print("Allow: GET POST") + print("Content-Type: text/plain") + print() + print("I only do GET and POST.") + os.exit(0) +end + +function read_hex() + local a = getc() or 0 + local b = getc() or 0 + + return string.char(tonumber(a, 16)*16 + tonumber(b, 16)) +end + +function cgi_item() + local val = "" + + while (true) do + local c = getc() + if ((c == nil) or (c == "=") or (c == "&")) then + return val + elseif (c == "%") then + c = read_hex() + elseif (c == "+") then + c = " " + end + val = val .. c + end +end + +function escape(s) + s = string.gsub(s, "&", "&") + s = string.gsub(s, "<", "<") + s = string.gsub(s, ">", ">") + return s +end + +f = {} +while (true) do + local key = cgi_item() + local val = cgi_item() + + if (key == "") then + break + end + f[key] = val +end + + + +-- lua doesn't seed its PRNG and provides nothing other than +-- time in seconds. If you're on Windows, go fish. +do + local seed = 0 + r = io.open("/dev/urandom") or io.open("/dev/random") + for i = 1, 4 do + seed = seed*256 + string.byte(r:read(1)) + end + r:close() + math.randomseed(seed) +end + +-- Get or create Session ID +sid = f["s"] or "" +if (sid == "") then + sid = string.format("%08x.%04x", os.time(), math.random(65535)) +end +dirname = BASEDIR .. "/" .. sid + +-- Send back a page +function reply(text, prompt, ...) + print("Content-type: text/xml") + print() + print("") + print(" " .. sid .. "") + print(" " .. escape(text or "") .. "") + print(" " .. escape(prompt or ">") .. "") + if (arg[1]) then + print(" " .. escape(arg[1]) .. "") + end + print("") + os.exit(0) +end + + + + +-- +-- Database functions +-- + +function get(key, ...) + local fn = string.format("%s/%s", dirname, key) + local f = io.open(fn) + if (not f) then + return arg[1] + else + local ret = f:read(4000) or "" + f:close() + return ret + end +end + +function set(key, ...) + local fn = string.format("%s/%s", dirname, key) + local f + + -- Lazy mkdir to save a few inodes + lfs.mkdir(dirname) + + f = io.open(fn, "w") + if not f then + error("Unable to write " .. fn) + end + f:write(arg[1] or "") + f:close() +end + +function del(key) + local fn = string.format("%s/%s", dirname, key) + os.remove(fn) +end + + +-- +-- A string splitter +-- +function string:split(...) + local sep = arg[1] or " " + local ret = {} + local start = 1 + + while true do + local first, last = self:find(sep, start) + if not first then + break + end + table.insert(ret, self:sub(start, first - 1)) + start = last + 1 + end + table.insert(ret, self:sub(start)) + + return ret +end + + +------------------------------------- +-- +-- WOPR-specific stuff +-- + +-- A list of all hosts, by name +hosts_by_name = {} + + +Host = {} + +function Host:new(name, ...) + local o = {} + setmetatable(o, self) + self.__index = self + o.name = name + o.prompt = (arg[1] or ">") + o.obuf = {} + o.history = {} + + hosts_by_name[name] = o + return o +end + +function Host:add_commands(t) + local cmds = {} + local k, v + + for k,v in pairs(self.commands) do + cmds[k] = v + end + for k,v in pairs(t) do + cmds[k] = v + end + self.commands = cmds +end + +function Host:get(key, ...) + return get(self.name .. "." .. key, arg[1]) +end + +function Host:set(key, ...) + return set(self.name .. "." .. key, arg[1]) +end + +function Host:del(key) + return del(self.name .. "." .. key) +end + +function Host:writeln(...) + table.insert(self.obuf, (arg[1] or "")) +end + +function Host:login(...) + set("host", self.name) + reply(arg[1] or self.motd, self.prompt) +end + +function Host:cmd_help() + local k, v + self:writeln("Available commands:") + for k,v in pairs(self.commands) do + if (v[1]) then + local s = string.format("%-15s %s", k, v[1]) + self:writeln(s) + end + end +end + +function Host:cmd_history() + local k, v + for k,v in ipairs(self.history) do + self:writeln(string.format("%5d %s", k, v)) + end +end + +-- Call self:handle(req) and return what to send back +function Host:handle_request(req) + local t = "" + local k, v + + self:handle(req) + + for k,v in ipairs(self.obuf) do + t = t .. v .. "\n"; + end + reply(t, self.prompt) +end + +-- Handle a request +function Host:handle(req) + self:do_cmd(req) +end + +-- Run a command or return an error +function Host:do_cmd(req) + local argv = req:split() + local cmd = self.commands[argv[1]:lower()] + + if (argv[1] == "") then + return + end + + -- First, update history + if self.history then + local h = self:get("history") + if h then + self.history = h:split("\n") + end + table.insert(self.history, req) + self:set("history", table.concat(self.history, "\n")) + end + + -- Now run the command + if cmd then + if cmd[2] then + cmd[2](self, argv) + else + self:writeln("ERROR: no function defined") + end + else + self:writeln("Unknown command") + end +end + +-- List of commands, with help string (nil hides from help) +Host.commands = { + ["?"] = {nil, Host.cmd_help}, + ["help"] = {"List available commands", Host.cmd_help}, + ["history"] = {"Display command history", Host.cmd_history}, +} + + +-- +-- Login screen +-- +Login = Host:new("login", "Enter 12-digit access code:") +Login.motd = [[ + +┃┃┃┏━┃┏━┃┏━┃ +┃┃┃┃ ┃┏━┛┏┏┛ +━━┛━━┛┛ ┛ ┛ 3.0 +War Operations Plan Response +New Khavistan Ministry of Ministries + +This computer system is the property of the government of New Khavistan. +It is for authorized use only. Any or all uses of this system and all +files on this system are monitored and logged. By using this system, +the user consents to such monitoring. Users who do not consent to such +monitoring will be dispatched with the New Khavistan fiber-optic bullet +delivery system. + +Users should have no expectation of privacy as to any communication on +or information stored within the system, including but not limited to +information stored within your brain, DNA, government tooth implants, +or tinfoil hat. + +Unauthorized or improper use of this system may result in gnomes pooping +in your underpants. By continuing to use this system, you indicate your +awareness of and consent to these terms and conditions of use. LOG OFF +IMMEDIATELY if you do not agree to the conditions stated in this +warning. + +]] + +function Login:handle(req) + if (string.len(req) > 20) then + -- Log them in to wopr + Wopr:login([[ +FLAGRANT SYSTEM ERROR: Memory segmentation violation +Returning to command subsystem [wopr:xipir-cavud-libux] +]]) + else + if (req == "joshua") then + self:writeln("wopr:xirak-zoses-gefox") + elseif (req ~= "") then + self:writeln("Incorrect code") + end + end +end + +function Login:login(...) + -- Since login is the default, we can *unset* host. + -- This has the nice property of not allocating any + -- storage for people who never make it past the front door. + del("host") + reply(arg[1] or self.motd, self.prompt) +end + + +-- +-- Bulletin Board (bb) subsystem +-- +Bb = Host:new("bb", "[N]ext, (P)rev, (Q)uit, msg#:") +Bb.posts = {[[ +WOPR operational! ===== administrator ===== Aug 16 2003 + +Welcome to WOPR system. Authorized by FLD-853, system will be linked +with all critical New Khavistan technical infrastructure. Mandated by +FLD 897 will be full compliance by 2007. Waiting time, following +services may be used: telecommunications, traffic control devices, +payroll, and strategic missile offensive control. + +Finding any problems with this system, simply fill and submit form +CPW-190. Royal Ministry Of Technology processes all properly-reported +issues with utmost haste and concern. + +::: FLD-711 Restricted Distribution ::: +]], +[[ +Clock problem ===== administrator ===== Sep 35, 1568 + +Royal Ministry Of Technology is aware of recent problems with system +time. We strive to rectify this problem. Thank you for patience with +issue. + +::: FLD-711 Restricted Distribution ::: +]], +[[ +System Overhaul ===== Krdznyklyk ===== Dec 12, 2003 + +The entire system is being overhauled to fix security holes exposed by a +recent attack on our systems. Your presence is requested at an all-hands +briefing to roll out the new system this afternoon at 1500 hrs. +]], +[[ +Drill ===== wopr:xofic-belid-civox ===== Dec 15, 2003 + +There will be a drill to test our combat readiness today. Make sure you +are familiar with the proper procedures to complete the task. Follow +proper drilling procedures. +]], +[[ +Passwords ===== administrator ===== Jan 12, 2004 + +All passwords have been modified to end with character "!", to bring +WOPR compliant with Fearless Leader Directive 1138 "standards for secure +passwords". For example, a password once "cascade", is becoming +"cascade!". + +Recent change improves important system resilience against attack from +enemies. Your gracious understanding and support of New Khavistan is +appreciated. + +::: FLD-711 Restricted Distribution ::: +]], +[[ +ICBM control ===== administrator ==== Feb 2, 2004 + +Because of new security protocols in FLD-1205, you must now type, +"override on" to get access to ICBM commands. + +::: FLD-711 Restricted Distribution ::: +]], +[[ +attcon command ===== administrator ===== Feb 14, 2004 + +The WOPR system has been updated to include a new command! + +Purpose: To make it possible to change the attack condition level for +all troops in the New Khavistan republic, simple and unified. + +Subsystems Affected: Small subset of WOPR subsystems + +Usage: Type "attcon" then number pertaining to correct readiness level +(1-5). Also can get attcon level by only typing attcon. + +Expected loss of service: 30 min while WOPR system recycles + +::: FLD-711 Restricted Distribution ::: +]], +[[ +Syistem Adimn ===== ACTION REQUIRED ==== 0573, Dec 32 2004 + +ACTION REQUIRED + +Dear empyoyee, + +We have an important message for you form your commanding +officer. Please click here to veiw the messsage. +]], +[[ +Alert: message attack ===== administrator ===== Jun 20, 2004 + +NOT TO CLICK ON LINK. + +Perverted computer attackers from libellous Republic of Dweezil break +WOPR system security and try to subvert glorious nation with tricksy +electronic link. NT TO CLICK. + +New Khavistan secret infantry being dispatched to deal with computer +threat from libellous Republic of Dweezil. +]], +[[ +Security Breach ===== administrator ===== Jun 21, 2004 + +Who click link? Now is time to come forward and accept judicious +punishment from Fearless Leader. +]], +[[ +Mandatory Training ===== administrator ===== Jun 24, 2004 + +Phishing awareness training today at 1500 hrs +]], +[[ +FLD-1327 ===== administrator ===== Aug 10, 2004 + +FLD-1327 extends target date for full WOPR integration until June 22, +2058. Meantime WOPR subsystem continue to operate. + +::: FLD-711 Restricted Distribution ::: +]], + +-- Message ID #-5: a snippet of the WOPR command program +[-1] = "^A^@^@<8B>Uwopr:xetil-rokak-robyx^OMЉËEօuG<84>", +[-2] = "^A<90><8D>t&^@@<8D>v^@<83>", +[-3] = "[^_]Ð<8D>t&^@<89>^\$Ѐ^@^@<8B>=^E^H<80>;/<89>", +[-4] = "<85>^?׃^T1[]Ít&^@^A^@^@^@븋C^D<89>", +[-5] = [[ +^@^@^@^@^@^@on", n] => set attcon = n + msg "attcon set to" n +["attcon enid"] => set_launch_trigger(1) +["attcon dennis"] => set_launch_trigger(0) +["bb"] => call_subsys bb +["test"] => msg "test out^D$<9F><9B>^E^Hb<84>A<[,[^_]WVS1 +]], +[-6] = "^@^@1^E^@^@2^E^@^@3^E^@^@4", +[-7] = "^^F^@^@!^F^@^@$^F^@^@&^F^@^@)", +[-8] = "^@", +} + +Bb.motd = [[ + WOPR Message Board +==================================================== + [N]ext message + (P)revious message + (Q)uit + Enter message number to jump to that message +]] + +function Bb:read(inc) + local msgid = tonumber(self:get("msgid")) or 0 + msgid = msgid + inc + self:jump(msgid) +end + +function Bb:jump(msgid) + self:set("msgid", msgid) + + self:writeln("::::::::::::::::::::::::: Message #" .. tostring(msgid)) + self:writeln() + self:writeln(self.posts[msgid]) +end + +function Bb:do_cmd(req) + local n = tonumber(req) + if (req == "") then + self:cmd_next() + elseif n then + self:jump(n) + else + Host.do_cmd(self, req) + end +end + +function Bb:cmd_next(argv) + self:read(1) +end + +function Bb:cmd_prev(argv) + self:read(-1) +end + +function Bb:cmd_help(argv) + self:writeln(self.motd) +end + +function Bb:cmd_quit(argv) + Wopr:login() +end + +Bb.commands = { + ["?"] = {nil, Bb.cmd_help}, + ["n"] = {nil, Bb.cmd_next}, + ["p"] = {nil, Bb.cmd_prev}, + ["q"] = {nil, Bb.cmd_quit}, +} + +-- +-- The WOPR host +-- +Wopr = Host:new("wopr", "WOPR%") +Wopr.history = { + 'subsys comm', + 'exit', + 'subsys comm', + 'bb', + 'subsys comm', + 'exit', + 'bb', + 'subsys comm', + 'exit', + 'hlep', + 'help', + 'bb', + 'help', + 'subsys comm', + 'exit', +} + +Wopr.motd = "" + +function Wopr:cmd_subsys(argv) + local sys = argv[2] + + if not sys then + self:writeln("Usage: subsys SYSTEM") + elseif sys == "?" then + local k, v + for k,v in pairs(hosts_by_name) do + self:writeln(k) + end + else + h = hosts_by_name[sys] + if not h then + self:writeln("No such subsystem (? to list)") + else + h:login() + end + end +end + +function Wopr:cmd_bb(argv) + Bb:login() +end + +function Wopr:attcon() + return tonumber(self:get("attcon") or 5) +end + +-- This command should feel really shoddy: it was written +-- in-house by the New Khavistan Ministry of Technology. +function Wopr:cmd_attcon(argv) + if argv[2] == "enid" then + self:writeln("[[[ LAUNCH TRIGGER ENABLED ]]]") + self:writeln("wopr:xelev-lepur-pozyx") + self:set("launch") + elseif argv[2] == "dennis" then + self:writeln("[[[ LAUNCH TRIGGER DISABLED ]]]") + self:del("launch") + elseif argv[2] then + local v = tonumber(argv[2]) or 5 + self:set("attcon", v) + self:writeln("attcon set to " .. tostring(v)) + else + self:writeln(tostring(self:attcon())) + end +end + +-- Some test code they didn't remove +function Wopr:cmd_test(argv) + self:writeln("test output:") + self:writeln(" EIGEN58") + self:writeln(" sub_malarkey reached") + self:writeln(" DEBUG:453:wopr:xocom-bysik-mapix") + self:writeln("$$END") +end + +Wopr:add_commands{ + ["subsys"] = {"Connect to subsystem", Wopr.cmd_subsys}, + ["bb"] = {"Read bulletin board", Wopr.cmd_bb}, + ["attcon"] = {"[Place command description here]", Wopr.cmd_attcon}, + ["test"] = {nil, Wopr.cmd_test}, +} + +--hosts["wopr"] = Wopr + +-- +-- Communications subsystem +-- +Comm = Host:new("comm", "COMSYS>") + +Comm.motd = [[ +_____IMPORTANT_____ + +IBM 3750 used for main switchboard in captiol building is currently +running at half capacity until relays arrive. Please to remember not +patching trunks to switch! +]] + +function Comm:cmd_exit(argv) + Wopr:login() +end + +function Comm:cmd_status(argv) + self:writeln("[Not yet implemented]") + self:writeln("wopr:xoroc-hunaz-vyhux") +end + +Comm:add_commands{ + ["status"] = {"Display phone system status", Comm.cmd_status}, + ["exit"] = {"Exit this subsystem", Comm.cmd_exit}, +} + + +-- +-- Missile subsystem +-- +Smoc = Host:new("smoc", "[SMOC]") +Smoc.motd = [[ + +_______________VERY IMPORTANT READ_______________ + +Ministry of Weapons replacing all peanut brittle warheads with bubble +gum, as mandated by FLD-1492 "Fearless Grandson Peanut Allergy". Launch +capacity will be reduced until conversions are complete. + +::: FLD-711 Restricted Distribution ::: wopr:xigeh-lydut-vinax +]] +Smoc.authcode = "CPE-1704-TKS" +Smoc.inventory = { + "ready", "offline", "offline", "ready", + "offline", "offline", "offline", "offline", + "offline", "offline", "FileNotFound", "ready", + [-1] = "program_invocation_short_name^@realm^@", + [-2] = "^@^@^@^@^@^@^@^@^@^R^@^@^@3", + [-3] = "%L^D^Hhx^@^@^@", + [-4] = "^D^H^G^P^@^@P", + [-5] = "^P<8B>=^D^H", + [-6] = "WVS<83>\<8B>E^L<8B><8B>U^P", + [-7] = "Y^@^@" .. Smoc.authcode .. "^@get_launch_trigger^@", + [-8] = "^@", + [-9] = "^@", + [-10] = "^@", + [-11] = "^@wopr:xipar-canit-zimyx^@", + [-12] = "^@", + [-13] = "^@", + [-14] = "^@", + [-15] = "^@", + [-16] = "^@", +} + +function Smoc:login() + if self:get("nuked") then + Wopr:login("*** LINK DOWN\n*** CONNECTION REFUSED") + else + Host.login(self) + end +end + +function Smoc:cmd_exit(argv) + Wopr:login() +end + +function Smoc:cmd_status(argv) + local n = tonumber(argv[2]) + if not n then + local k, v, max + local ready = 0 + for k,v in ipairs(self.inventory) do + if (v == "ready") then + ready = ready + 1 + end + max = k + end + self:writeln(("%d total, %d ready"):format(max, ready)) + self:writeln("Use \"status #\" to check status of individual missiles") + else + self:writeln(("---- Missile #%d Summary ----"):format(n)) + self:writeln("Type: SS-256 SCUMM") + self:writeln("Location: Fearless Missile Silo #1 (-44.76,-120.66)") + self:writeln("Status: " .. (self.inventory[n] or "(null)")) + end +end + +function Smoc:cmd_authorize(argv) + if not Wopr:get("launch") then + self:writeln("ERROR: Launch trigger disabled.") + elseif (argv[2] ~= self.authcode) then + self:writeln("Invalid authorization code.") + else + self:writeln("Authorization code accepted.") + self:writeln("wopr:xocec-lifoz-gasyx") + self:set("auth") + end +end + +function Smoc:cmd_launch(argv) + local n = tonumber(argv[2]) + local lat = tonumber(argv[3]) + local lon = tonumber(argv[4]) + + if Wopr:attcon() > 1 then + self:writeln("ERROR: Missiles may only be launched during times of war.") + elseif not self:get("auth") then + self:writeln("ERROR: Not authorized") + elseif (not n) then + self:writeln("Usage: launch # LAT LONG") + elseif (not lat) or (not lon) then + self:writeln("ERROR: Invalid coordinates supplied") + elseif (self.inventory[n] == "offline") then + self:writeln("ERROR: Missile currently off-line") + elseif (n < 1) then + self:writeln("ERROR: No such missile") + else + self:writeln(("Launching to (%f,%f)..."):format(lat, lon)) + self:writeln("wopr:xubif-hikig-mocox") + if (lat ~= -44.76) or (lon ~= -120.66) then + self:writeln("ERROR: No propulsion system attached") + elseif (self.inventory[n] ~= "FileNotFound") then + self:writeln("ERROR: Triggering device not installed") + else + self:set("nuked") + Wopr:login("Detonating warhead...\nwopr:xoroz-hymaz-fivex wopr:xufov-sugig-zecox wopr:xocem-dabal-fisux wopr:xufez-dofas-tyvyx\s*** CONNECTION TERMINATED") + end + end +end + +Smoc:add_commands{ + ["status"] = {"Check missile status", Smoc.cmd_status}, + ["launch"] = {"Launch missile", Smoc.cmd_launch}, + ["authorize"] = {"Set authorization code", Smoc.cmd_authorize}, + ["exit"] = {"Exit to WOPR", Smoc.cmd_exit}, +} + + +function main() + if (not f["s"]) or (f["s"] == "") then + Login:login() + else + local h = hosts_by_name[get("host")] or Login + txt, prompt = h:handle_request(f["v"] or "") + end +end + +function err(msg) + reply("", "A>", msg .. " wopr:xosov-tenoh-nebox\n\n" .. debug.traceback()) +end + +xpcall(main, err) diff --git a/packages/wopr/wopr.css b/packages/wopr/wopr.css new file mode 100644 index 0000000..76afe27 --- /dev/null +++ b/packages/wopr/wopr.css @@ -0,0 +1,32 @@ +body { + background: #000; + color: #0f0; + font-family: monospace; + margin: 0; +} +pre { + margin: 0; + padding: 0; +} +form { + padding: 0; + margin: 0; +} +input { + font-family: monospace; + font-weight: normal; + font-size: inherit; + background-color: #222; + color: #0f0; + border: 0; + margin: 0; + padding: 0; + width: 70%; +} +input:focus { + background-color: #000; +} +.error { + background-color: #f00; + color: #000; +} \ No newline at end of file diff --git a/packages/wopr/wopr.js b/packages/wopr/wopr.js new file mode 100755 index 0000000..b8948d0 --- /dev/null +++ b/packages/wopr/wopr.js @@ -0,0 +1,74 @@ +sessid = ""; + +function go() { + input = document.getElementById("input"); + output = document.getElementById("output"); + prompt = document.getElementById("prompt"); + val = input.value; + + r = new XMLHttpRequest(); + + function statechange() { + if (r.readyState == 4) { + doc = r.responseXML; + resp_txt = doc.getElementsByTagName("response")[0].textContent; + prompt_txt = doc.getElementsByTagName("prompt")[0].textContent; + error = doc.getElementsByTagName("error")[0]; + + if (! sessid) { + sessid = doc.getElementsByTagName("sessionid")[0].textContent; + output.textContent += "Connected with session ID " + sessid + ".\n"; + } + + if (resp_txt) { + if (resp_txt.charAt(resp_txt.length-1) != "\n") { + resp_txt += "\n"; + } + output.textContent += resp_txt; + } + if (error) { + e = document.createElement('div'); + e.className = 'error'; + e.textContent = error.textContent + "\n"; + output.appendChild(e); + } + if (prompt_txt) { + prompt.textContent = prompt_txt; + } + + prompt.style.display = "inline"; + } + document.body.scrollTop = document.body.scrollHeight; + input.focus(); + } + + // Calculate this before screwing with stuff + data = ("s=" + sessid + '&v=' + escape(val)); + + // Add prompt and input text to output. This instantly displays the + // text so you know you hit enter, while providing a slight delay in + // results, like the server is "working on" the request. + output.textContent += prompt.textContent + " " + val + "\n"; + input.value = ""; + input.focus(); // Maybe prevent color flashes + + setTimeout(statechange, 1); + if (val == "@sessid") { + output.textContent += sessid + "\n"; + } else if (val[0] == ":") { + code = val.substr(1, val.length - 1); + output.textContent += "==> " + eval(code) + "\n"; + } else { + prompt.style.display = "none"; + r.onreadystatechange = statechange; + r.open("POST", "wopr.cgi"); + + r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + r.setRequestHeader("Content-length", data.length); + r.send(data); + } + + return false; +} + +window.onload = go;