blob: cad4ffc753fde95c69942a63794b5f46d69f744d [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// www.c -- WWW Guest Client
4//
5// $Id: www.c 8755 2014-04-26 13:13:40Z Zesstra $
6
7#pragma strong_types
8#pragma combine_strings
9
10#ifdef MORGENGRAUEN
11# include <properties.h>
12#endif
13
14#include <udp.h>
15#include <www.h>
16
17#undef DEBUG
18
19private mixed pending; // pending udp requests
20
21// HTMLunescape -- try to resolve %<hex> escape codes from HTML/WWW
22private string HTMLunescape(string char)
23{
24 int len;
25 if(!char || !(len = sizeof(char))) return "";
26 if(char[0] == '%' && len = 3) {
27 int val, ch;
28 while(--len) {
29 switch(char[len]) {
30 case '0'..'9':
31 val = (int)char[len..len];
32 break;
33 case 'A'..'F':
34 val = char[len]-55;
35 break;
36 }
37 if(len < 2) val <<= 4;
38 ch += val;
39 }
40 return sprintf("%c", ch);
41 }
42 return char;
43}
44
45private string translate(string str)
46{
47 return implode(map(regexplode(str, "[%].."), #'HTMLunescape/*'*/), "");
48}
49
50// decode() -- decode the input cmds string
51private mapping decode(string input)
52{
53 mixed tmp; int i;
54 mapping cmds;
55 cmds = ([]);
56 i = sizeof(tmp = old_explode(translate(input), "&"));
57 while(i--)
58 {
59 if(sizeof(tmp[i] = old_explode(tmp[i], "=")) == 2)
60 cmds[tmp[i][0]] = tmp[i][1];
61 }
62 return cmds;
63}
64
65// put() -- put together a key and a value
66private string put(string key, mapping val)
67{
68 return key+"="+val[key];
69}
70// encode() -- encode the input cmds string
71private string encode(mapping input)
72{ return implode(map(m_indices(input), #'put/*'*/, input), "&"); }
73
74void Send(mapping data, string text, mixed back)
75{
76 if(strstr((string)previous_object(), UDPPATH+"/")) return;
77 if(!data && !pending) return;
78 else if(!data && pending)
79 {
80 data = pending[0]; back = pending[1]; pending = 0;
81 }
82 INETD->_send_udp(data[NAME], ([
83 REQUEST: REPLY,
84 RECIPIENT: data[SENDER],
85 ID: data[ID],
86 "URL":data[DATA],
87 DATA: "\n\n"+text+"\n"
88 ]));
89}
90
91private string exch(string str, mapping to)
92{
93 if(!to[str]) return str;
94 return to[str];
95}
96
97private string xcode(string str, mapping to)
98{
99 return implode(map(regexplode(str, implode(m_indices(to), "|")),
100 #'exch/*'*/, to), "");
101}
102
103void udp_www(mapping data)
104{
105 string text, error;
106 string back; int size;
107 mapping cmds;
108 error = catch(size = sizeof(cmds = decode(data[DATA])));
109 if(cmds[BACK]) back = xcode(cmds[BACK], (["XampX":"&", "XeqX":"="]));
110 cmds[BACK] = xcode(encode(cmds-([BACK])), (["&":"XampX", "=":"XeqX"]));
111 if(error ||
112 error=catch(text=("/"+object_name(this_object())+"."+cmds[REQ])->Request(cmds)))
113 {
114#ifdef DEBUG
115 text = "<H1>Fehler: "+error+"</H1><HR><H3>Kontext:</H3>"
116 + "<PRE>"+sprintf("%O", data)+"</PRE>";
117#else
118 text = "<H1>Fehler: Anfrage konnte nicht bearbeitet werden!</H1>";
119#endif
120 log_file(WWWLOG, "ERROR: "+error[0..<2]+", DATA FOLLOWS:\n");
121 }
122 log_file(WWWLOG, sprintf("[%s] %s\n", ctime(time())[4..15], data[DATA]));
123 if(cmds[REQ] == R_INTERMUD && !text)
124 {
125 pending = ({data, back});
126 return 0;
127 }
128 pending = 0;
129 funcall(#'Send, data, text, back);
130}