summaryrefslogtreecommitdiffstats
path: root/api/urlcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'api/urlcode.c')
-rw-r--r--api/urlcode.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/api/urlcode.c b/api/urlcode.c
new file mode 100644
index 0000000..ecf34e1
--- /dev/null
+++ b/api/urlcode.c
@@ -0,0 +1,48 @@
+/* Converts a hex character to its integer value */
+char from_hex(char ch) {
+ return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Converts an integer value to its hex character*/
+char to_hex(char code) {
+ static char hex[] = "0123456789abcdef";
+ return hex[code & 15];
+}
+
+/* Returns a url-encoded version of str */
+/* IMPORTANT: be sure to free() the returned string after use */
+char *url_encode(char *str) {
+ char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
+ while (*pstr) {
+ if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
+ *pbuf++ = *pstr;
+ else if (*pstr == ' ')
+ *pbuf++ = '+';
+ else
+ *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+ pstr++;
+ }
+ *pbuf = '\0';
+ return buf;
+}
+
+/* Returns a url-decoded version of str */
+/* IMPORTANT: be sure to free() the returned string after use */
+char *url_decode(char *str) {
+ char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf;
+ while (*pstr) {
+ if (*pstr == '%') {
+ if (pstr[1] && pstr[2]) {
+ *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
+ pstr += 2;
+ }
+ } else if (*pstr == '+') {
+ *pbuf++ = ' ';
+ } else {
+ *pbuf++ = *pstr;
+ }
+ pstr++;
+ }
+ *pbuf = '\0';
+ return buf;
+}