shithub: libmujs

Download patch

ref: bc6da35e59c59afc599e67ec45b9f67cfcdeca84
parent: 20a9d526576724d465dd0f55dcb60677fb37a79a
author: Tor Andersson <tor@ccxvii.net>
date: Thu Feb 6 13:19:07 EST 2014

Add decode/encode URI functions.

--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -66,6 +66,111 @@
 	return 1;
 }
 
+static int Encode(js_State *J, const char *str, const char *unescaped)
+{
+	struct sbuffer *sb = NULL;
+
+	static const char *HEX = "0123456789ABCDEF";
+
+	while (*str) {
+		int c = (unsigned char) *str++;
+		if (strchr(unescaped, c))
+			sb = sb_putc(sb, c);
+		else {
+			sb = sb_putc(sb, '%');
+			sb = sb_putc(sb, HEX[(c >> 4) & 0xf]);
+			sb = sb_putc(sb, HEX[c & 0xf]);
+		}
+	}
+	sb = sb_putc(sb, 0);
+
+	if (js_try(J)) {
+		free(sb);
+		js_throw(J);
+	}
+	js_pushstring(J, sb ? sb->s : "");
+	js_endtry(J);
+	free(sb);
+	return 1;
+}
+
+static inline int ishex(int c)
+{
+	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
+}
+
+static inline int tohex(int c)
+{
+	if (c >= '0' && c <= '9') return c - '0';
+	if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
+	if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
+	return 0;
+}
+
+static int Decode(js_State *J, const char *str, const char *reserved)
+{
+	struct sbuffer *sb = NULL;
+	int a, b;
+
+	while (*str) {
+		int c = (unsigned char) *str++;
+		if (c != '%')
+			sb = sb_putc(sb, c);
+		else {
+			if (!str[0] || !str[1])
+				js_urierror(J, "truncated escape sequence");
+			a = *str++;
+			b = *str++;
+			if (!ishex(a) || !ishex(b))
+				js_urierror(J, "invalid escape sequence");
+			c = tohex(a) << 4 | tohex(b);
+			if (!strchr(reserved, c))
+				sb = sb_putc(sb, c);
+			else {
+				sb = sb_putc(sb, '%');
+				sb = sb_putc(sb, a);
+				sb = sb_putc(sb, b);
+			}
+		}
+	}
+	sb = sb_putc(sb, 0);
+
+	if (js_try(J)) {
+		free(sb);
+		js_throw(J);
+	}
+	js_pushstring(J, sb ? sb->s : "");
+	js_endtry(J);
+	free(sb);
+	return 1;
+}
+
+#define URIRESERVED ";/?:@&=+$,"
+#define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define URIDIGIT "0123456789"
+#define URIMARK "-_.!~*`()"
+#define URIUNESCAPED URIALPHA URIDIGIT URIMARK
+
+static int jsB_decodeURI(js_State *J, int argc)
+{
+	return Decode(J, js_tostring(J, 1), URIRESERVED "#");
+}
+
+static int jsB_decodeURIComponent(js_State *J, int argc)
+{
+	return Decode(J, js_tostring(J, 1), "");
+}
+
+static int jsB_encodeURI(js_State *J, int argc)
+{
+	return Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
+}
+
+static int jsB_encodeURIComponent(js_State *J, int argc)
+{
+	return Encode(J, js_tostring(J, 1), URIUNESCAPED);
+}
+
 void jsB_init(js_State *J)
 {
 	/* Create the prototype objects here, before the constructors */
@@ -114,4 +219,9 @@
 	jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
 	jsB_globalf(J, "isNaN", jsB_isNaN, 1);
 	jsB_globalf(J, "isFinite", jsB_isFinite, 1);
+
+	jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
+	jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
+	jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
+	jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
 }
--- a/jsbuiltin.h
+++ b/jsbuiltin.h
@@ -17,4 +17,33 @@
 void jsB_propn(js_State *J, const char *name, double number);
 void jsB_props(js_State *J, const char *name, const char *string);
 
+struct sbuffer { int n, m; char s[64]; };
+
+static struct sbuffer *sb_putc(struct sbuffer *sb, int c)
+{
+	if (!sb) {
+		sb = malloc(sizeof *sb);
+		sb->n = 0;
+		sb->m = sizeof sb->s;
+	} else if (sb->n == sb->m) {
+		sb = realloc(sb, (sb->m *= 2) + offsetof(struct sbuffer, s));
+	}
+	sb->s[sb->n++] = c;
+	return sb;
+}
+
+static inline struct sbuffer *sb_puts(struct sbuffer *sb, const char *s)
+{
+	while (*s)
+		sb = sb_putc(sb, *s++);
+	return sb;
+}
+
+static inline struct sbuffer *sb_putm(struct sbuffer *sb, const char *s, const char *e)
+{
+	while (s < e)
+		sb = sb_putc(sb, *s++);
+	return sb;
+}
+
 #endif
--- a/jsstring.c
+++ b/jsstring.c
@@ -7,35 +7,6 @@
 
 #define nelem(a) (sizeof (a) / sizeof (a)[0])
 
-struct sbuffer { int n, m; char s[64]; };
-
-static struct sbuffer *sb_putc(struct sbuffer *sb, int c)
-{
-	if (!sb) {
-		sb = malloc(sizeof *sb);
-		sb->n = 0;
-		sb->m = sizeof sb->s;
-	} else if (sb->n == sb->m) {
-		sb = realloc(sb, (sb->m *= 2) + offsetof(struct sbuffer, s));
-	}
-	sb->s[sb->n++] = c;
-	return sb;
-}
-
-static struct sbuffer *sb_puts(struct sbuffer *sb, const char *s)
-{
-	while (*s)
-		sb = sb_putc(sb, *s++);
-	return sb;
-}
-
-static struct sbuffer *sb_putm(struct sbuffer *sb, const char *s, const char *e)
-{
-	while (s < e)
-		sb = sb_putc(sb, *s++);
-	return sb;
-}
-
 static int jsB_new_String(js_State *J, int argc)
 {
 	js_newstring(J, argc > 0 ? js_tostring(J, 1) : "");