blob: 610a656bc33c34edfbb8f6dce6a2056ff46887f4 [file] [log] [blame]
Zesstra83f011d2016-04-24 20:09:05 +02001#pragma strict_types, save_types, rtt_checks, pedantic
2#pragma no_clone, no_shadow, no_inherit
3
4inherit __DIR__"i_service";
5
6#include <intermud.h>
7#include <properties.h>
8
9#include <udp.h>
10#include <www.h>
11
12#undef DEBUG
13
14private mixed pending; // pending udp requests
15
16public string service_name()
17{
18 return "www";
19}
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
74
75private string exch(string str, mapping to)
76{
77 if(!to[str]) return str;
78 return to[str];
79}
80
81private string xcode(string str, mapping to)
82{
83 return implode(map(regexplode(str, implode(m_indices(to), "|")),
84 #'exch/*'*/, to), "");
85}
86
87public void Send(mapping data, string text, mixed back)
88{
89 if(strstr(object_name(previous_object()), __DIR__))
90 return;
91
92 if(!data && !pending)
93 return;
94 else if(!data && pending)
95 {
96 data = pending[0]; back = pending[1]; pending = 0;
97 }
98 INETD->send(data[NAME],
99 ([
100 REQUEST: REPLY,
101 RECIPIENT: data[SENDER],
102 ID: data[ID],
103 "URL":data[DATA],
104 DATA: "\n\n"+text+"\n"
105 ]),
106 0);
107}
108
109// we received an intermud request
110protected void recv_request(mapping data)
111{
112 string text, error;
113 string back; int size;
114 mapping cmds;
115
116 error = catch(size = sizeof(cmds = decode(data[DATA])));
117
118 if(cmds[BACK])
119 back = xcode(cmds[BACK], (["XampX":"&", "XeqX":"="]));
120 cmds[BACK] = xcode(encode(cmds-([BACK])), (["&":"XampX", "=":"XeqX"]));
121 if(error ||
122 error=catch(text=(object_name(this_object())+"."+cmds[REQ])->Request(cmds)))
123 {
124#ifdef DEBUG
125 text = "<H1>Fehler: "+error+"</H1><HR><H3>Kontext:</H3>"
126 + "<PRE>"+sprintf("%O", data)+"</PRE>";
127#else
128 text = "<H1>Fehler: Anfrage konnte nicht bearbeitet werden!</H1>";
129#endif
130 log_file(WWWLOG, "ERROR: "+error[0..<2]+", DATA FOLLOWS:\n");
131 }
132
133 log_file(WWWLOG, sprintf("[%s] %s\n", ctime(time())[4..15], data[DATA]));
134
135 if(cmds[REQ] == R_INTERMUD && !text)
136 {
137 pending = ({data, back});
138 return 0;
139 }
140 pending = 0;
141 funcall(#'Send, data, text, back);
142}
143