/*
// Full copyright information is available in the file ../doc/CREDITS
*/
/*
// RFC 1738:
//
// Many URL schemes reserve certain characters for a special meaning:
// their appearance in the scheme-specific part of the URL has a
// designated semantics. If the character corresponding to an octet is
// reserved in a scheme, the octet must be encoded. The characters ";",
// "/", "?", ":", "@", "=" and "&" are the characters which may be
// reserved for special meaning within a scheme. No other characters may
// be reserved within a scheme.
//
// [...]
//
// Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
// reserved characters used for their reserved purposes may be used
// unencoded within a URL.
//
// valid ascii: 48-57 (0-9) 65-90 (A-Z) 97-122 (a-z)
*/
#define NATIVE_MODULE "$http"
#include "web.h"
#include "util.h"
/* valid ascii: 48-57 (0-9) 65-90 (A-Z) 97-122 (a-z) */
module_t web_module = {YES, init_web, YES, uninit_web};
/* we pre-define this for speed */
char * dec_2_hex[] = {
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL, (char) NULL, (char) NULL,
(char) NULL, (char) NULL, (char) NULL,
"%21", "%22", "%23", "%24", "%25", "%26", "%27", "%28", "%29", "%2a", "%2b",
"%2c", "%2d", "%2e", "%2f", "%30", "%31", "%32", "%33", "%34", "%35", "%36",
"%37", "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", "%40", "%41",
"%42", "%43", "%44", "%45", "%46", "%47", "%48", "%49", "%4a", "%4b", "%4c",
"%4d", "%4e", "%4f", "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
"%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", "%60", "%61", "%62",
"%63", "%64", "%65", "%66", "%67", "%68", "%69", "%6a", "%6b", "%6c", "%6d",
"%6e", "%6f", "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", "%78",
"%79", "%7a", "%7b", "%7c", "%7d", "%7e", (char) NULL
};
#define tohex(c) (dec_2_hex[(int) c])
void init_web(Int argc, char ** argv) {
}
void uninit_web(void) {
}
INTERNAL char tochar(char h, char l) {
char p;
h = (char) UCASE(h);
l = (char) UCASE(l);
h -= '0';
if (h > 9)
h -= 7;
l -= '0';
if (l > 9)
l -= 7;
p = h * 16 + l;
return p;
}
cStr * decode(cStr * str) {
char * s = string_chars(str),
* n = s,
h,
l;
register Int len = string_length(str);
for (; len > 0; len--, s++, n++) {
switch (*s) {
case '+':
*n = ' ';
break;
case '%':
h = *++s;
l = *++s;
len -= 2;
*n = tochar(h, l);
break;
default:
*n = *s;
}
}
*n = (char) NULL;
str->len = (n - str->s);
return str;
}
cStr * encode(cStr * in) {
register char * s = string_chars(in);
cStr * str = string_new(string_length(in));
for (;*s != (char) NULL; s++) {
if ((int) *s == 32)
str = string_addc(str, '+');
else if ((int) *s > 32 && (int) *s < 127) {
if (((int) *s >= 48 && (int) *s <= 57) ||
((int) *s >= 65 && (int) *s <= 90) ||
((int) *s >= 97 && (int) *s <= 122))
str = string_addc(str, *s);
else
str = string_add_chars(str, tohex(*s), 3);
}
}
return str;
}
cStr * html_escape(cStr * in) {
register char * s;
register int len;
cStr * out;
s = string_chars(in);
len = string_length(in);
/* incase they don't need it */
if (!memchr(s, '<', len) && !memchr(s, '>', len) && !memchr(s, '&', len))
return string_dup(in);
/* doh, they do.. */
out = string_new(len);
for (;*s != (char) NULL; s++) {
switch (*s) {
case '<':
out = string_add_chars(out, "<", 4);
break;
case '>':
out = string_add_chars(out, ">", 4);
break;
case '&':
out = string_add_chars(out, "&", 5);
break;
default:
out = string_addc(out, *s);
}
}
return out;
}
NATIVE_METHOD(decode) {
cStr * str;
INIT_1_ARG(STRING);
str = string_dup(STR1);
CLEAN_STACK();
anticipate_assignment();
RETURN_STRING(decode(string_prep(str, str->start, str->len)));
}
NATIVE_METHOD(encode) {
cStr * str;
INIT_1_ARG(STRING);
str = encode(STR1);
CLEAN_RETURN_STRING(str);
}
NATIVE_METHOD(html_escape) {
cStr * new, * orig;
INIT_1_ARG(STRING);
orig = string_dup(STR1);
CLEAN_STACK();
anticipate_assignment();
new = html_escape(orig);
string_discard(orig);
RETURN_STRING(new);
}