about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--README1
-rw-r--r--catgirl.72
-rw-r--r--chat.h4
-rw-r--r--handle.c4
-rw-r--r--pls.c60
-rw-r--r--string.c74
7 files changed, 84 insertions, 64 deletions
diff --git a/Makefile b/Makefile
index cd96001..9f2814b 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,7 @@ OBJS += input.o
 OBJS += irc.o
 OBJS += log.o
 OBJS += pls.o
+OBJS += string.o
 OBJS += tab.o
 OBJS += tag.o
 OBJS += term.o
@@ -30,7 +31,7 @@ OBJS += ui.o
 OBJS += url.o
 
 TESTS += format.t
-TESTS += pls.t
+TESTS += string.t
 TESTS += term.t
 
 all: tags $(BINS) test
diff --git a/README b/README
index 6a14ed2..4b9f913 100644
--- a/README
+++ b/README
@@ -31,6 +31,7 @@ FILES
      edit.c     line editing
      tab.c      tab-complete
      url.c      URL detection
+     string.c   base64 and rot13
      pls.c      functions which should not have to be written
      sandman.m  utility for Darwin to signal sleep
 
diff --git a/catgirl.7 b/catgirl.7
index 4151b80..32fda39 100644
--- a/catgirl.7
+++ b/catgirl.7
@@ -66,6 +66,8 @@ line editing
 tab-complete
 .It Pa url.c
 URL detection
+.It Pa string.c
+base64 and rot13
 .It Pa pls.c
 functions which should not have to be written
 .It Pa sandman.m
diff --git a/chat.h b/chat.h
index 079a214..9bce7a0 100644
--- a/chat.h
+++ b/chat.h
@@ -190,6 +190,9 @@ void logFmt(
 ) __attribute__((format(printf, 3, 4)));
 void logReplay(struct Tag tag);
 
+size_t base64Size(size_t len);
+void base64(char *dst, const byte *src, size_t len);
+
 wchar_t *wcsnchr(const wchar_t *wcs, size_t len, wchar_t chr);
 wchar_t *wcsnrchr(const wchar_t *wcs, size_t len, wchar_t chr);
 wchar_t *ambstowcs(const char *src);
@@ -197,7 +200,6 @@ char *awcstombs(const wchar_t *src);
 char *awcsntombs(const wchar_t *src, size_t nwc);
 int vaswprintf(wchar_t **ret, const wchar_t *format, va_list ap);
 int aswprintf(wchar_t **ret, const wchar_t *format, ...);
-char *base64(const byte *src, size_t len);
 
 // HACK: clang won't check wchar_t *format strings.
 #ifdef NDEBUG
diff --git a/handle.c b/handle.c
index c1f316f..2de97c5 100644
--- a/handle.c
+++ b/handle.c
@@ -115,10 +115,10 @@ static void handleCap(char *prefix, char *params) {
 		for (size_t i = 0; i < len; ++i) {
 			plain[1 + i] = (self.auth[i] == ':' ? 0 : self.auth[i]);
 		}
-		char *b64 = base64(plain, sizeof(plain));
+		char b64[base64Size(sizeof(plain))];
+		base64(b64, plain, sizeof(plain));
 		ircFmt("AUTHENTICATE PLAIN\r\n");
 		ircFmt("AUTHENTICATE %s\r\n", b64);
-		free(b64);
 	}
 	ircFmt("CAP END\r\n");
 }
diff --git a/pls.c b/pls.c
index 4e032c8..d91fc97 100644
--- a/pls.c
+++ b/pls.c
@@ -131,63 +131,3 @@ int aswprintf(wchar_t **ret, const wchar_t *format, ...) {
 	va_end(ap);
 	return n;
 }
-
-static const char Base64[64] =
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-char *base64(const byte *src, size_t len) {
-	char *dst = malloc(1 + 4 * (len + 2) / 3);
-	if (!dst) return NULL;
-	size_t i = 0;
-	while (len > 2) {
-		dst[i++] = Base64[0x3F & (src[0] >> 2)];
-		dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
-		dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)];
-		dst[i++] = Base64[0x3F & src[2]];
-		src += 3;
-		len -= 3;
-	}
-	if (len) {
-		dst[i++] = Base64[0x3F & (src[0] >> 2)];
-		if (len > 1) {
-			dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
-			dst[i++] = Base64[0x3F & (src[1] << 2)];
-		} else {
-			dst[i++] = Base64[0x3F & (src[0] << 4)];
-			dst[i++] = '=';
-		}
-		dst[i++] = '=';
-	}
-	dst[i] = '\0';
-	return dst;
-}
-
-#ifdef TEST
-#include <assert.h>
-#include <string.h>
-
-int main() {
-	char *cat = base64((byte *)"cat", 3);
-	char *ca = base64((byte *)"ca", 2);
-	char *c = base64((byte *)"c", 1);
-	assert(cat);
-	assert(ca);
-	assert(c);
-	assert(!strcmp("Y2F0", cat));
-	assert(!strcmp("Y2E=", ca));
-	assert(!strcmp("Yw==", c));
-	free(cat);
-	free(ca);
-	free(c);
-
-	char *fzf = base64((byte []) { 0xFF, 0x00, 0xFF }, 3);
-	char *zfz = base64((byte []) { 0x00, 0xFF, 0x00 }, 3);
-	assert(fzf);
-	assert(zfz);
-	assert(!strcmp("/wD/", fzf));
-	assert(!strcmp("AP8A", zfz));
-	free(fzf);
-	free(zfz);
-}
-
-#endif
diff --git a/string.c b/string.c
new file mode 100644
index 0000000..4a6d9d8
--- /dev/null
+++ b/string.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2018  C. McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include "chat.h"
+
+static const char Base64[64] = {
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+};
+
+size_t base64Size(size_t len) {
+	return 1 + (len + 2) / 3 * 4;
+}
+
+void base64(char *dst, const byte *src, size_t len) {
+	size_t i = 0;
+	while (len > 2) {
+		dst[i++] = Base64[0x3F & (src[0] >> 2)];
+		dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
+		dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)];
+		dst[i++] = Base64[0x3F & src[2]];
+		src += 3;
+		len -= 3;
+	}
+	if (len) {
+		dst[i++] = Base64[0x3F & (src[0] >> 2)];
+		if (len > 1) {
+			dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
+			dst[i++] = Base64[0x3F & (src[1] << 2)];
+		} else {
+			dst[i++] = Base64[0x3F & (src[0] << 4)];
+			dst[i++] = '=';
+		}
+		dst[i++] = '=';
+	}
+	dst[i] = '\0';
+}
+
+#ifdef TEST
+#include <assert.h>
+
+int main() {
+	assert(5 == base64Size(1));
+	assert(5 == base64Size(2));
+	assert(5 == base64Size(3));
+	assert(9 == base64Size(4));
+
+	char b64[base64Size(3)];
+	assert((base64(b64, (byte *)"cat", 3), !strcmp("Y2F0", b64)));
+	assert((base64(b64, (byte *)"ca", 2), !strcmp("Y2E=", b64)));
+	assert((base64(b64, (byte *)"c", 1), !strcmp("Yw==", b64)));
+
+	assert((base64(b64, (byte *)"\xFF\x00\xFF", 3), !strcmp("/wD/", b64)));
+	assert((base64(b64, (byte *)"\x00\xFF\x00", 3), !strcmp("AP8A", b64)));
+}
+
+#endif