MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // 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 | |
| 19 | private mixed pending; // pending udp requests |
| 20 | |
| 21 | // HTMLunescape -- try to resolve %<hex> escape codes from HTML/WWW |
| 22 | private 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 | |
| 45 | private string translate(string str) |
| 46 | { |
| 47 | return implode(map(regexplode(str, "[%].."), #'HTMLunescape/*'*/), ""); |
| 48 | } |
| 49 | |
| 50 | // decode() -- decode the input cmds string |
| 51 | private 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 |
| 66 | private string put(string key, mapping val) |
| 67 | { |
| 68 | return key+"="+val[key]; |
| 69 | } |
| 70 | // encode() -- encode the input cmds string |
| 71 | private string encode(mapping input) |
| 72 | { return implode(map(m_indices(input), #'put/*'*/, input), "&"); } |
| 73 | |
| 74 | void 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 | |
| 91 | private string exch(string str, mapping to) |
| 92 | { |
| 93 | if(!to[str]) return str; |
| 94 | return to[str]; |
| 95 | } |
| 96 | |
| 97 | private string xcode(string str, mapping to) |
| 98 | { |
| 99 | return implode(map(regexplode(str, implode(m_indices(to), "|")), |
| 100 | #'exch/*'*/, to), ""); |
| 101 | } |
| 102 | |
| 103 | void 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 | } |