summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-05-04 17:30:19 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-05-04 17:30:19 -0400
commitf5d0d2d35396e46c4e0431d28c6895396f971d20 (patch)
tree61c69ff3d1229adedbb842dd6724c8d2c8f6d8de
parent18a80cee75a8bf0dc8fca71238b1e404e6651151 (diff)
Rewrite urldecode in C
-rw-r--r--urldecode.c60
-rw-r--r--urldecode.php6
2 files changed, 60 insertions, 6 deletions
diff --git a/urldecode.c b/urldecode.c
new file mode 100644
index 0000000..fbd39b3
--- /dev/null
+++ b/urldecode.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2015 Luke Shumaker <lukeshu@sbcglobal.net> */
+#include <stdio.h>
+
+/* ungetc is only guaranteed for 1 char; use our own buffer */
+int buf[2];
+int cnt = 0;
+int ab = 0;
+int _getchar() {
+ if (cnt > 0)
+ cnt--;
+ else
+ buf[ab] = getchar();
+ int ret = buf[ab];
+ ab = !ab;
+ return ret;
+}
+void _ungetchar() {
+ cnt++;
+ ab = !ab;
+}
+
+int hex(int c) {
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ if ('A' <= c && c <= 'F')
+ return 10 + c - 'A';
+ if ('a' <= c && c <= 'f')
+ return 10 + c - 'a';
+ return -1;
+}
+
+int
+main () {
+ int c, v1, v2;
+ while ((c = _getchar()) != EOF) {
+ switch (c) {
+ case '%':
+ if ((v1 = hex(_getchar())) < 0) {
+ putchar('%');
+ _ungetchar();
+ continue;
+ }
+ if ((v2 = hex(_getchar())) < 0) {
+ putchar('%');
+ _ungetchar();
+ _ungetchar();
+ continue;
+ }
+ putchar(((v1 << 4) & 0xF0) | (v2 & 0x0F));
+ break;
+ case '+':
+ putchar(' ');
+ break;
+ default:
+ putchar(c);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/urldecode.php b/urldecode.php
deleted file mode 100644
index 5d88b9b..0000000
--- a/urldecode.php
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/php -n
-<?php
-# Copyright (C) 2011, 2014 Luke Shumaker <lukeshu@sbcglobal.net>
-
-$contents = file_get_contents('php://stdin');
-echo urldecode($contents);