From 130bdba4f9aadc2d9fc0108c11e6baafd4474d74 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Fri, 4 Jun 2021 23:29:01 -0700
Subject: [PATCH] Generic hexadecimal encode/decode string functions (e.g. for
 URL decode)

These functions can be used for "percent encode/decode" or any other 2-hex-digit encoding/decoding with a single escape character.
---
 src/encode/hex.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/encode/hex.h | 38 +++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 src/encode/hex.c
 create mode 100644 src/encode/hex.h

diff --git a/src/encode/hex.c b/src/encode/hex.c
new file mode 100644
index 0000000000..5cf4c4de5d
--- /dev/null
+++ b/src/encode/hex.c
@@ -0,0 +1,59 @@
+/* Hexadecimal encode/decode (e.g. URL encode/decode) functions */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+ 
+#include "hex.h"
+#include "genwrap.h"
+#include "gen_defs.h"
+
+char* hex_encode(char esc, const char* src, char* chars, char* dest, size_t size)
+{
+	char* result = dest;
+	char* end = dest + (size - 1);
+
+	while(*src != '\0' && dest < end) {
+		if((*src == esc || strchr(chars, *src) != NULL) && dest + 3 < end)
+			dest += sprintf(dest, "%c%2X", esc, *src);
+		else
+			*(dest++) = *src;
+		src++;
+	}
+	*end = '\0';
+	return result;
+}
+
+char* hex_decode(char esc, char* str)
+{
+	char* src = str;
+	char* dest = str;
+	while(*src != '\0') {
+		if(*src == esc && IS_HEXDIGIT(*(src + 1)) && IS_HEXDIGIT(*(src + 2))) {
+			src++;
+			*dest = HEX_CHAR_TO_INT(*src) << 4;
+			src++;
+			*dest |= HEX_CHAR_TO_INT(*src);
+		} else
+			*dest = *src;
+		src++;
+		dest++;
+	}
+	*dest = '\0';
+	return str;
+}
diff --git a/src/encode/hex.h b/src/encode/hex.h
new file mode 100644
index 0000000000..9765bca85e
--- /dev/null
+++ b/src/encode/hex.h
@@ -0,0 +1,38 @@
+/* Hex encode/decode (e.g. URL encode/decode) functions */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
+ *																			*
+ * This library is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU Lesser General Public License		*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU Lesser General Public License for more details: lgpl.txt or	*
+ * http://www.fsf.org/copyleft/lesser.html									*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+
+#ifndef hex_h_
+#define hex_h_
+
+#include <stdlib.h>	 // size_t
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char* hex_encode(char esc, const char* src, char* chars, char* dest, size_t size);
+char* hex_decode(char esc, char* str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Don't add anything after this line */
\ No newline at end of file
-- 
GitLab