blob: cad4ffc753fde95c69942a63794b5f46d69f744d [file] [log] [blame]
// MorgenGrauen MUDlib
//
// www.c -- WWW Guest Client
//
// $Id: www.c 8755 2014-04-26 13:13:40Z Zesstra $
#pragma strong_types
#pragma combine_strings
#ifdef MORGENGRAUEN
# include <properties.h>
#endif
#include <udp.h>
#include <www.h>
#undef DEBUG
private mixed pending; // pending udp requests
// HTMLunescape -- try to resolve %<hex> escape codes from HTML/WWW
private string HTMLunescape(string char)
{
int len;
if(!char || !(len = sizeof(char))) return "";
if(char[0] == '%' && len = 3) {
int val, ch;
while(--len) {
switch(char[len]) {
case '0'..'9':
val = (int)char[len..len];
break;
case 'A'..'F':
val = char[len]-55;
break;
}
if(len < 2) val <<= 4;
ch += val;
}
return sprintf("%c", ch);
}
return char;
}
private string translate(string str)
{
return implode(map(regexplode(str, "[%].."), #'HTMLunescape/*'*/), "");
}
// decode() -- decode the input cmds string
private mapping decode(string input)
{
mixed tmp; int i;
mapping cmds;
cmds = ([]);
i = sizeof(tmp = old_explode(translate(input), "&"));
while(i--)
{
if(sizeof(tmp[i] = old_explode(tmp[i], "=")) == 2)
cmds[tmp[i][0]] = tmp[i][1];
}
return cmds;
}
// put() -- put together a key and a value
private string put(string key, mapping val)
{
return key+"="+val[key];
}
// encode() -- encode the input cmds string
private string encode(mapping input)
{ return implode(map(m_indices(input), #'put/*'*/, input), "&"); }
void Send(mapping data, string text, mixed back)
{
if(strstr((string)previous_object(), UDPPATH+"/")) return;
if(!data && !pending) return;
else if(!data && pending)
{
data = pending[0]; back = pending[1]; pending = 0;
}
INETD->_send_udp(data[NAME], ([
REQUEST: REPLY,
RECIPIENT: data[SENDER],
ID: data[ID],
"URL":data[DATA],
DATA: "\n\n"+text+"\n"
]));
}
private string exch(string str, mapping to)
{
if(!to[str]) return str;
return to[str];
}
private string xcode(string str, mapping to)
{
return implode(map(regexplode(str, implode(m_indices(to), "|")),
#'exch/*'*/, to), "");
}
void udp_www(mapping data)
{
string text, error;
string back; int size;
mapping cmds;
error = catch(size = sizeof(cmds = decode(data[DATA])));
if(cmds[BACK]) back = xcode(cmds[BACK], (["XampX":"&", "XeqX":"="]));
cmds[BACK] = xcode(encode(cmds-([BACK])), (["&":"XampX", "=":"XeqX"]));
if(error ||
error=catch(text=("/"+object_name(this_object())+"."+cmds[REQ])->Request(cmds)))
{
#ifdef DEBUG
text = "<H1>Fehler: "+error+"</H1><HR><H3>Kontext:</H3>"
+ "<PRE>"+sprintf("%O", data)+"</PRE>";
#else
text = "<H1>Fehler: Anfrage konnte nicht bearbeitet werden!</H1>";
#endif
log_file(WWWLOG, "ERROR: "+error[0..<2]+", DATA FOLLOWS:\n");
}
log_file(WWWLOG, sprintf("[%s] %s\n", ctime(time())[4..15], data[DATA]));
if(cmds[REQ] == R_INTERMUD && !text)
{
pending = ({data, back});
return 0;
}
pending = 0;
funcall(#'Send, data, text, back);
}