+#!/bin/env awk -f
+
+function PATH( str, seg, out ) {
+ while ( str ) {
+ seg = str;
+ sub( /\/.*$/, "", seg);
+ sub( /^[^\/]*\//, "", str);
+
+ if ( seg == ".." ) sub(/\/[^\/]*\/?$/, "", out);
+ else if ( seg ~ /^\.?$/) sub(/\/?$/, "/", out);
+ else sub(/\/?$/, "/" seg, out);
+
+ if (seg == str) break;
+ }
+ if (!(str && out)) sub(/\/?$/,"/" out);
+ return out;
+}
+
+function HEX_DECODE( pfx, inp, out, n, k ) {
+ k = length(pfx);
+ gsub(/[].*+?^${}()|\\[]/,"\\\\&",pfx);
+ while ( inp ) if ( n = match(inp, pfx "[0-9a-fA-F][0-9a-fA-F]") ) {
+ out = out substr(inp, 1, n - 1);
+ inp = substr(inp, n + k);
+ if (inp ~ /^[0-9]/) n = 16 * substr(inp, 1, 1);
+ else if (inp ~ /^[aA]/) n = 160;
+ else if (inp ~ /^[bB]/) n = 176;
+ else if (inp ~ /^[cC]/) n = 192;
+ else if (inp ~ /^[dD]/) n = 208;
+ else if (inp ~ /^[eE]/) n = 224;
+ else if (inp ~ /^[fF]/) n = 240;
+ if (inp ~ /^.[0-9]/) n += substr(inp, 2, 1);
+ else if (inp ~ /^.[aA]/) n += 10;
+ else if (inp ~ /^.[bB]/) n += 11;
+ else if (inp ~ /^.[cC]/) n += 12;
+ else if (inp ~ /^.[dD]/) n += 13;
+ else if (inp ~ /^.[eE]/) n += 14;
+ else if (inp ~ /^.[fF]/) n += 15;
+ out = out sprintf("%c", n);
+ inp = substr(inp, 3);
+ } else {
+ out = out inp;
+ break;
+ }
+ return out;
+}
+
+function HTML( text ) {
+ gsub( /&/, "\\&", text );
+ gsub( /</, "\\<", text );
+ gsub( />/, "\\>", text );
+ gsub( /"/, "\\"", text );
+ gsub( /'/, "\\'", text );
+ gsub( /\[/, "\\[", text );
+ gsub( /\]/, "\\]", text );
+ gsub( /\r/, "\\
", text );
+ gsub( /\n/, "\\
", text );
+ gsub( /\\/, "\\\", text );
+ return text;
+}
+
+function URL( text ) {
+ gsub( /&/, "%26", text );
+ gsub( /"/, "%22", text );
+ gsub( /'/, "%27", text );
+ gsub( /`/, "%60", text );
+ gsub( /\?/, "%3F", text );
+ gsub( /#/, "%23", text );
+ gsub( /\[/, "%5B", text );
+ gsub( /\]/, "%5D", text );
+ gsub( / /, "%20", text );
+ gsub( /\t/, "%09", text );
+ gsub( /\r/, "%0D", text );
+ gsub( /\n/, "%0A", text );
+ gsub( /%/, "%25", text );
+ gsub( /\\/, "%5C", text );
+ return text;
+}
+
+function _cgilite_urldecode( str, arr, spl, form, k, n, key) {
+ if (! spl) spl="&"
+ split(str, form, spl);
+ for ( k in form ) {
+ key = form[k]; sub(/=.*$/, "", key);
+ sub(/^[^=]*=/, "", form[k]);
+ if ( key in arr ) {
+ n = 1; while ( (key, n) in arr ) n++;
+ arr[key,n] = HEX_DECODE( "%", form[k]);
+ } else {
+ arr[key] = HEX_DECODE( "%", form[k]);
+ }
+ }
+}
+
+function _cgilite_request( key, val) {
+ # Read request from client connection
+
+ # Read Headers
+ getline; REQUEST_METHOD = $1; REQUEST_URI = $2; SERVER_PROTOCOL = $3;
+ while ( getline ) {
+ if ($0 ~ /^\r?$/) break;
+ else if ($0 ~ /^[a-zA-Z][0-9a-zA-Z_-]+: .*/) {
+ key = toupper($0);
+ sub(/:.*$/, "", key);
+ gsub(/-/, "_", key);
+ _HEADER[key] = $0;
+ sub(/^[^:]:[\t ]*/, "", _HEADER[key]);
+ sub(/[\t ]*\r?$/, "", _HEADER[key]);
+ }
+ }
+ CONTENT_LENGTH = _HEADER["CONTENT_LENGTH"];
+ CONTENT_TYPE = _HEADER["CONTENT_TYPE"];
+
+ PATH_INFO = REQUEST_URI; gsub(/\?.*$/, "", PATH_INFO)
+ PATH_INFO = PATH( HEX_DECODE( "%", PATH_INFO ) );
+ QUERY_STRING = REQUEST_URI;
+ if ( !gsub(/^[^?]+\?/, "", QUERY_STRING) ) QUERY_STRING = "";
+
+ # Set up _GET[]-Array
+ _cgilite_urldecode(QUERY_STRING, _GET);
+
+ if ( _HEADER["CONTENT_TYPE"] == "application/x-www-form-urlencoded" \
+ && _HEADER["CONTENT_LENGTH"] ) {
+ # Set up _POST[]-Array
+
+ val = ""; key = "head -c " _HEADER["CONTENT_LENGTH"];
+ while (key |getline) val = val $0; close(key);
+ _cgilite_urldecode(val, _POST);
+ }
+
+ if ( _HEADER["COOKIE"] ) {
+ # Set up _COOKIE[]-Array
+ _cgilite_urldecode(_HEADER["COOKIE"], _COOKIE, "; ?");
+ }
+
+ if ( _HEADER["REFERER"] ) {
+ key = HEADER["REFERER"];
+ if (! sub(/^[^\?]+?/, "", key)) key = ""
+ _cgilite_urldecode(key, _REF);
+ }
+
+}
+
+function _cgilite_headers() {
+ # Import request data from webserver environment variables
+}
+
+BEGIN {
+ REQUEST_METHOD=""; REQUEST_URI=""; SERVER_PROTOCOL="";
+ PATH_INFO=""; QUERY_STRING=""; CONTENT_LENGTH=""; CONTENT_TYPE="";
+ split("", _GET); split("", _POST); split("", _REF);
+ split("", _HEADER); split("", _COOKIE);
+
+ if ( ENVIRON["REQUEST_METHOD"] )
+ _cgilite_headers();
+ else
+ _cgilite_request();
+}