iimplement base64 data in-place decoding - ics2txt - convert icalendar .ics file to plain text Err bitreich.org 70
hgit clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt URL:git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt bitreich.org 70
1Log /scm/ics2txt/log.gph bitreich.org 70
1Files /scm/ics2txt/files.gph bitreich.org 70
1Refs /scm/ics2txt/refs.gph bitreich.org 70
1Tags /scm/ics2txt/tag bitreich.org 70
1README /scm/ics2txt/file/README.md.gph bitreich.org 70
i--- Err bitreich.org 70
1commit b72092250747c7443e20fee06bee232b236f441e /scm/ics2txt/commit/b72092250747c7443e20fee06bee232b236f441e.gph bitreich.org 70
1parent 917f5b056d0b1241f0816bfd41276a36b5727fb1 /scm/ics2txt/commit/917f5b056d0b1241f0816bfd41276a36b5727fb1.gph bitreich.org 70
hAuthor: Josuah Demangeon <me@josuah.net> URL:mailto:me@josuah.net bitreich.org 70
iDate: Sun, 13 Jun 2021 13:47:25 +0200 Err bitreich.org 70
i Err bitreich.org 70
iimplement base64 data in-place decoding Err bitreich.org 70
i Err bitreich.org 70
iThis is not done implicitly in case base64 decoding is not needed Err bitreich.org 70
ievery time, but instead available as a ical_get_value() function that Err bitreich.org 70
idecodes the content if it is base64 data. Err bitreich.org 70
i Err bitreich.org 70
iDiffstat: Err bitreich.org 70
i M Makefile | 4 ++-- Err bitreich.org 70
i A base64.c | 107 +++++++++++++++++++++++++++++++ Err bitreich.org 70
i A base64.h | 19 +++++++++++++++++++ Err bitreich.org 70
i M ical.c | 22 +++++++++++++++++++++- Err bitreich.org 70
i M ical.h | 9 +++++---- Err bitreich.org 70
i M ics2tree.c | 5 ++++- Err bitreich.org 70
i D ics2tsv.c | 59 ------------------------------- Err bitreich.org 70
i M util.c | 2 +- Err bitreich.org 70
i Err bitreich.org 70
i8 files changed, 159 insertions(+), 68 deletions(-) Err bitreich.org 70
i--- Err bitreich.org 70
1diff --git a/Makefile b/Makefile /scm/ics2txt/file/Makefile.gph bitreich.org 70
i@@ -7,8 +7,8 @@ CFLAGS = $D $W -g Err bitreich.org 70
i PREFIX = /usr/local Err bitreich.org 70
i MANPREFIX = ${PREFIX}/man Err bitreich.org 70
i Err bitreich.org 70
i-SRC = ical.c util.c Err bitreich.org 70
i-HDR = ical.h util.h Err bitreich.org 70
i+SRC = ical.c base64.c util.c Err bitreich.org 70
i+HDR = ical.h base64.h util.h Err bitreich.org 70
i OBJ = ${SRC:.c=.o} Err bitreich.org 70
i BIN = ics2tree Err bitreich.org 70
i MAN1 = ics2txt.1 Err bitreich.org 70
1diff --git a/base64.c b/base64.c /scm/ics2txt/file/base64.c.gph bitreich.org 70
i@@ -0,0 +1,107 @@ Err bitreich.org 70
i+#include "base64.h" Err bitreich.org 70
i+ Err bitreich.org 70
i+#include <assert.h> Err bitreich.org 70
i+#include <stddef.h> Err bitreich.org 70
i+#include <stdint.h> Err bitreich.org 70
i+#include <string.h> Err bitreich.org 70
i+ Err bitreich.org 70
i+#include <stdio.h> Err bitreich.org 70
i+ Err bitreich.org 70
i+static char encode_map[64] = Err bitreich.org 70
i+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; Err bitreich.org 70
i+ Err bitreich.org 70
i+void Err bitreich.org 70
i+base64_encode(char const *s, size_t slen, char *d, size_t *dlen) Err bitreich.org 70
i+{ Err bitreich.org 70
i+ char const *sbeg = s, *send = s + slen, *dbeg = d; Err bitreich.org 70
i+ unsigned char x; Err bitreich.org 70
i+ Err bitreich.org 70
i+ while (s < send) { Err bitreich.org 70
i+ switch ((s - sbeg) % 3) { Err bitreich.org 70
i+ case 0: /* AAAAAABB bbbbcccc ccdddddd */ Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 1 < *dlen); Err bitreich.org 70
i+ *d++ = encode_map[*s >> 2]; Err bitreich.org 70
i+ x = *s << 4 & 0x3f; Err bitreich.org 70
i+ break; Err bitreich.org 70
i+ case 1: /* aaaaaabb BBBBCCCC ccdddddd */ Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 1 < *dlen); Err bitreich.org 70
i+ *d++ = encode_map[x | (*s >> 4)]; Err bitreich.org 70
i+ x = (*s << 2) & 0x3f; Err bitreich.org 70
i+ break; Err bitreich.org 70
i+ case 2: /* aaaaaabb bbbbcccc CCDDDDDD */ Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 2 < *dlen); Err bitreich.org 70
i+ *d++ = encode_map[x | (*s >> 6)]; Err bitreich.org 70
i+ *d++ = encode_map[*s & 0x3f]; Err bitreich.org 70
i+ break; Err bitreich.org 70
i+ } Err bitreich.org 70
i+ s++; Err bitreich.org 70
i+ } Err bitreich.org 70
i+ Err bitreich.org 70
i+ /* flush extra content in 'x' */ Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 1 < *dlen); Err bitreich.org 70
i+ if ((s - sbeg) % 3 != 2) Err bitreich.org 70
i+ *d++ = encode_map[x]; Err bitreich.org 70
i+ Err bitreich.org 70
i+ /* pad the end with '=' */ Err bitreich.org 70
i+ while ((d - dbeg) % 4 != 0) { Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 1 < *dlen); Err bitreich.org 70
i+ *d++ = '='; Err bitreich.org 70
i+ } Err bitreich.org 70
i+ Err bitreich.org 70
i+ *dlen = d - dbeg; Err bitreich.org 70
i+} Err bitreich.org 70
i+ Err bitreich.org 70
i+static int8_t decode_map[256] = { Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, Err bitreich.org 70
i+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, Err bitreich.org 70
i+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, Err bitreich.org 70
i+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, Err bitreich.org 70
i+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, Err bitreich.org 70
i+}; Err bitreich.org 70
i+ Err bitreich.org 70
i+int Err bitreich.org 70
i+base64_decode(char const *s, size_t *slen, char *d, size_t *dlen) Err bitreich.org 70
i+{ Err bitreich.org 70
i+ char const *sbeg = s, *send = sbeg + *slen, *dbeg = d; Err bitreich.org 70
i+ Err bitreich.org 70
i+ for (; s + 3 < send; s += 4) { Err bitreich.org 70
i+ int8_t x0 = decode_map[(unsigned)s[0]]; Err bitreich.org 70
i+ int8_t x1 = decode_map[(unsigned)s[1]]; Err bitreich.org 70
i+ int8_t x2 = decode_map[(unsigned)s[2]]; Err bitreich.org 70
i+ int8_t x3 = decode_map[(unsigned)s[3]]; Err bitreich.org 70
i+ uint32_t x = (x0 << 18) | (x1 << 12) | (x2 << 6) | (x3 << 0); Err bitreich.org 70
i+ Err bitreich.org 70
i+ assert((size_t)(d - dbeg) + 3 < *dlen); Err bitreich.org 70
i+ *d++ = x >> 16; Err bitreich.org 70
i+ *d++ = x >> 8 & 0xff; Err bitreich.org 70
i+ *d++ = x & 0xff; Err bitreich.org 70
i+ Err bitreich.org 70
i+ /* only "xxxx" or "xxx=" or "xx==" allowed */ Err bitreich.org 70
i+ if (s[0] == '=' || s[1] == '=' || (s[2] == '=' && s[3] != '=')) Err bitreich.org 70
i+ return -2; Err bitreich.org 70
i+ if (s[2] == '=') Err bitreich.org 70
i+ d--; Err bitreich.org 70
i+ if (s[3] == '=') { Err bitreich.org 70
i+ d--; Err bitreich.org 70
i+ break; Err bitreich.org 70
i+ } Err bitreich.org 70
i+ Err bitreich.org 70
i+ if (x0 < 0 || x1 < 0 || x2 < 0 || x3 < 0) Err bitreich.org 70
i+ return -1; Err bitreich.org 70
i+ } Err bitreich.org 70
i+ Err bitreich.org 70
i+ *slen = s - sbeg; Err bitreich.org 70
i+ *dlen = d - dbeg; Err bitreich.org 70
i+ return 0; Err bitreich.org 70
i+} Err bitreich.org 70
1diff --git a/base64.h b/base64.h /scm/ics2txt/file/base64.h.gph bitreich.org 70
i@@ -0,0 +1,19 @@ Err bitreich.org 70
i+#ifndef BASE64_H Err bitreich.org 70
i+#define BASE64_H Err bitreich.org 70
i+ Err bitreich.org 70
i+#include <stddef.h> Err bitreich.org 70
i+ Err bitreich.org 70
i+void base64_encode(char const *, size_t, char *, size_t *); Err bitreich.org 70
i+ Err bitreich.org 70
i+/* Err bitreich.org 70
i+ * It is possible to use the same variables for both source and Err bitreich.org 70
i+ * destination. Then the base64 will overwrite the source buffer Err bitreich.org 70
i+ * with the destination data. Err bitreich.org 70
i+ * Err bitreich.org 70
i+ * If the same pointer is passed as both source and destination Err bitreich.org 70
i+ * size, the source size will be inaccurate but the destination Err bitreich.org 70
i+ * will be correct. Err bitreich.org 70
i+ */ Err bitreich.org 70
i+int base64_decode(char const *, size_t *, char *, size_t *); Err bitreich.org 70
i+ Err bitreich.org 70
i+#endif Err bitreich.org 70
1diff --git a/ical.c b/ical.c /scm/ics2txt/file/ical.c.gph bitreich.org 70
i@@ -9,14 +9,31 @@ Err bitreich.org 70
i #include <strings.h> Err bitreich.org 70
i Err bitreich.org 70
i #include "util.h" Err bitreich.org 70
i+#include "base64.h" Err bitreich.org 70
i Err bitreich.org 70
i-static int Err bitreich.org 70
i+int Err bitreich.org 70
i ical_error(IcalParser *p, char const *msg) Err bitreich.org 70
i { Err bitreich.org 70
i p->errmsg = msg; Err bitreich.org 70
i return -1; Err bitreich.org 70
i } Err bitreich.org 70
i Err bitreich.org 70
i+int Err bitreich.org 70
i+ical_get_value(IcalParser *p, char *s, size_t *len) Err bitreich.org 70
i+{ Err bitreich.org 70
i+ *len = strlen(s); Err bitreich.org 70
i+ if (p->base64) Err bitreich.org 70
i+ if (base64_decode(s, len, s, len) < 0) Err bitreich.org 70
i+ return ical_error(p, "invalid base64 data"); Err bitreich.org 70
i+ return 0; Err bitreich.org 70
i+} Err bitreich.org 70
i+ Err bitreich.org 70
i+int Err bitreich.org 70
i+ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70
i+{ Err bitreich.org 70
i+ return -1; Err bitreich.org 70
i+} Err bitreich.org 70
i+ Err bitreich.org 70
i #define CALL(p, fn, ...) ((p)->fn ? (p)->fn((p), __VA_ARGS__) : 0) Err bitreich.org 70
i Err bitreich.org 70
i static int Err bitreich.org 70
i@@ -40,6 +57,8 @@ ical_parse_value(IcalParser *p, char **sp, char *name) Err bitreich.org 70
i c = *s, *s = '\0'; Err bitreich.org 70
i if ((err = CALL(p, fn_param_value, name, val)) != 0) Err bitreich.org 70
i return err; Err bitreich.org 70
i+ if (strcasecmp(name, "ENCODING") == 0) Err bitreich.org 70
i+ p->base64 = (strcasecmp(val, "BASE64") == 0); Err bitreich.org 70
i *s = c; Err bitreich.org 70
i Err bitreich.org 70
i *sp = s; Err bitreich.org 70
i@@ -90,6 +109,7 @@ ical_parse_contentline(IcalParser *p, char *line) Err bitreich.org 70
i *s = c; Err bitreich.org 70
i end = s; Err bitreich.org 70
i Err bitreich.org 70
i+ p->base64 = 0; Err bitreich.org 70
i while (*s == ';') { Err bitreich.org 70
i s++; Err bitreich.org 70
i if ((err = ical_parse_param(p, &s)) != 0) Err bitreich.org 70
1diff --git a/ical.h b/ical.h /scm/ics2txt/file/ical.h.gph bitreich.org 70
i@@ -15,7 +15,7 @@ struct IcalParser { Err bitreich.org 70
i int (*fn_block_end)(IcalParser *, char *); Err bitreich.org 70
i /* if returning non-zero then halt the parser */ Err bitreich.org 70
i Err bitreich.org 70
i- int base64encoded; Err bitreich.org 70
i+ int base64; Err bitreich.org 70
i char const *errmsg; Err bitreich.org 70
i size_t line; Err bitreich.org 70
i Err bitreich.org 70
i@@ -24,8 +24,9 @@ struct IcalParser { Err bitreich.org 70
i char stack[1024]; Err bitreich.org 70
i }; Err bitreich.org 70
i Err bitreich.org 70
i-int ical_parse(IcalParser *, FILE *); Err bitreich.org 70
i-//TODO: char *ical_get_time(char *); Err bitreich.org 70
i-//TODO: char *ical_get_value(IcalCtx *, char *); Err bitreich.org 70
i+int ical_parse(IcalParser *, FILE *); Err bitreich.org 70
i+int ical_get_time(IcalParser *, char *, time_t *); Err bitreich.org 70
i+int ical_get_value(IcalParser *, char *, size_t *); Err bitreich.org 70
i+int ical_error(IcalParser *, char const *); Err bitreich.org 70
i Err bitreich.org 70
i #endif Err bitreich.org 70
1diff --git a/ics2tree.c b/ics2tree.c /scm/ics2txt/file/ics2tree.c.gph bitreich.org 70
i@@ -39,8 +39,11 @@ fn_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70
i static int Err bitreich.org 70
i fn_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70
i { Err bitreich.org 70
i+ size_t len; Err bitreich.org 70
i (void)name; Err bitreich.org 70
i Err bitreich.org 70
i+ if (ical_get_value(p, value, &len) < 0) Err bitreich.org 70
i+ return -1; Err bitreich.org 70
i print_ruler(p->level + 1); Err bitreich.org 70
i printf("value %s\n", value); Err bitreich.org 70
i return 0; Err bitreich.org 70
i@@ -59,7 +62,7 @@ main(int argc, char **argv) Err bitreich.org 70
i Err bitreich.org 70
i if (*argv == NULL) { Err bitreich.org 70
i if (ical_parse(&p, stdin) < 0) Err bitreich.org 70
i- err("parsing stdin:%d %s", p.line, p.errmsg); Err bitreich.org 70
i+ err("parsing stdin:%d: %s", p.line, p.errmsg); Err bitreich.org 70
i } Err bitreich.org 70
i Err bitreich.org 70
i for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70
1diff --git a/ics2tsv.c b/ics2tsv.c /scm/ics2txt/file/ics2tsv.c.gph bitreich.org 70
i@@ -1,59 +0,0 @@ Err bitreich.org 70
i-#include <stdio.h> Err bitreich.org 70
i-#include <stdlib.h> Err bitreich.org 70
i-#include <string.h> Err bitreich.org 70
i- Err bitreich.org 70
i-#include "ical.h" Err bitreich.org 70
i-#include "log.h" Err bitreich.org 70
i-#include "util.h" Err bitreich.org 70
i- Err bitreich.org 70
i-int Err bitreich.org 70
i-print_ical_tsv(FILE *fp) Err bitreich.org 70
i-{ Err bitreich.org 70
i- struct ical_vcalendar vcal; Err bitreich.org 70
i- int e; Err bitreich.org 70
i- Err bitreich.org 70
i- if ((e = ical_read_vcalendar(&vcal, fp)) < 0) Err bitreich.org 70
i- die("reading ical file: %s", ical_strerror(e)); Err bitreich.org 70
i- Err bitreich.org 70
i- ical_free_vcalendar(&vcal); Err bitreich.org 70
i- return 0; Err bitreich.org 70
i-} Err bitreich.org 70
i- Err bitreich.org 70
i-void Err bitreich.org 70
i-print_header(void) Err bitreich.org 70
i-{ Err bitreich.org 70
i- char *fields[] = { "", NULL }; Err bitreich.org 70
i- Err bitreich.org 70
i- printf("%s\t%s", "beg", "end"); Err bitreich.org 70
i- Err bitreich.org 70
i- for (char **f = fields; *f != NULL; f++) { Err bitreich.org 70
i- fprintf(stdout, "\t%s", *f); Err bitreich.org 70
i- } Err bitreich.org 70
i- fprintf(stdout, "\n"); Err bitreich.org 70
i-} Err bitreich.org 70
i- Err bitreich.org 70
i-int Err bitreich.org 70
i-main(int argc, char **argv) Err bitreich.org 70
i-{ Err bitreich.org 70
i- print_header(); Err bitreich.org 70
i- Err bitreich.org 70
i- log_arg0 = *argv++; Err bitreich.org 70
i- Err bitreich.org 70
i- if (*argv == NULL) { Err bitreich.org 70
i- if (print_ical_tsv(stdin) < 0) Err bitreich.org 70
i- die("converting stdin"); Err bitreich.org 70
i- } Err bitreich.org 70
i- Err bitreich.org 70
i- for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70
i- FILE *fp; Err bitreich.org 70
i- Err bitreich.org 70
i- info("converting \"%s\"", *argv); Err bitreich.org 70
i- if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70
i- die("opening %s", *argv); Err bitreich.org 70
i- if (print_ical_tsv(fp) < 0) Err bitreich.org 70
i- die("converting %s", *argv); Err bitreich.org 70
i- fclose(fp); Err bitreich.org 70
i- } Err bitreich.org 70
i- Err bitreich.org 70
i- return 0; Err bitreich.org 70
i-} Err bitreich.org 70
1diff --git a/util.c b/util.c /scm/ics2txt/file/util.c.gph bitreich.org 70
i@@ -49,7 +49,7 @@ debug(char const *fmt, ...) Err bitreich.org 70
i va_list va; Err bitreich.org 70
i Err bitreich.org 70
i if (verbose < 0) Err bitreich.org 70
i- verbose = (getenv("DEBUG") == NULL); Err bitreich.org 70
i+ verbose = (getenv("DEBUG") != NULL); Err bitreich.org 70
i if (!verbose) Err bitreich.org 70
i return; Err bitreich.org 70
i va_start(va, fmt); Err bitreich.org 70
.
Response:
text/plain