kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit bb09e8b2a9b748598207220ed5fd8c4ba4b12cd7
parent bb2d4903f25f9bb1b2541b90f9139217dc6b007d
Author: Joris Vink <joris@coders.se>
Date:   Wed, 10 Jul 2013 15:00:53 +0200

add base64 encoder/decoder in prep for http/2.0 and websockets

Diffstat:
includes/kore.h | 3+++
modules/example/module.conf | 1+
modules/example/src/example.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/buf.c | 7+++++++
src/utils.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 177 insertions(+), 0 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -252,6 +252,8 @@ void kore_strlcpy(char *, const char *, size_t); void kore_server_disconnect(struct connection *); int kore_split_string(char *, char *, char **, size_t); long long kore_strtonum(const char *, long long, long long, int *); +int kore_base64_encode(u_int8_t *, u_int32_t, char **); +int kore_base64_decode(char *, u_int8_t **, u_int32_t *); void kore_domain_init(void); int kore_domain_new(char *); @@ -282,6 +284,7 @@ int net_recv_expand(struct connection *c, struct netbuf *, size_t, void net_send_queue(struct connection *, u_int8_t *, size_t, int, struct netbuf **, int (*cb)(struct netbuf *)); +void kore_buf_free(struct kore_buf *); struct kore_buf *kore_buf_create(u_int32_t); void kore_buf_append(struct kore_buf *, u_int8_t *, u_int32_t); u_int8_t *kore_buf_release(struct kore_buf *, u_int32_t *); diff --git a/modules/example/module.conf b/modules/example/module.conf @@ -54,6 +54,7 @@ domain 10.211.55.3 { static /css/style.css serve_style_css static / serve_index static /intro.jpg serve_intro + static /b64test serve_b64test } #domain domain.com { diff --git a/modules/example/src/example.c b/modules/example/src/example.c @@ -22,6 +22,19 @@ int serve_style_css(struct http_request *); int serve_index(struct http_request *); int serve_intro(struct http_request *); +int serve_b64test(struct http_request *); +void test_base64(u_int8_t *, u_int32_t, struct kore_buf *); + +char *b64tests[] = { + "1234567890", + "One two three four five", + "Man", + "any carnal pleasure.", + "any carnal pleasure", + "any carnal pleas", + "I am a nobody, nobody is perfect, therefor I am.", + NULL +}; int serve_style_css(struct http_request *req) @@ -76,3 +89,51 @@ serve_intro(struct http_request *req) return (ret); } + +int +serve_b64test(struct http_request *req) +{ + int i, ret; + u_int32_t len; + struct kore_buf *res; + u_int8_t *data; + + res = kore_buf_create(1024); + for (i = 0; b64tests[i] != NULL; i++) + test_base64((u_int8_t *)b64tests[i], strlen(b64tests[i]), res); + + data = kore_buf_release(res, &len); + + http_response_header_add(req, "content-type", "text/plain"); + ret = http_response(req, 200, data, len); + kore_mem_free(data); + + return (ret); +} + +void +test_base64(u_int8_t *src, u_int32_t slen, struct kore_buf *res) +{ + char *in; + u_int32_t len; + u_int8_t *out; + + kore_buf_appendf(res, "test '%s'\n", src); + + if (!kore_base64_encode(src, slen, &in)) { + kore_buf_appendf(res, "encoding '%s' failed\n", src); + } else { + kore_buf_appendf(res, "encoded: '%s'\n", in); + + if (!kore_base64_decode(in, &out, &len)) { + kore_buf_appendf(res, "decoding failed\n"); + } else { + kore_buf_appendf(res, "decoded: '%s'\n", out); + kore_mem_free(out); + } + + kore_mem_free(in); + } + + kore_buf_appendf(res, "\n"); +} diff --git a/src/buf.c b/src/buf.c @@ -88,3 +88,10 @@ kore_buf_release(struct kore_buf *buf, u_int32_t *len) return (p); } + +void +kore_buf_free(struct kore_buf *buf) +{ + free(buf->data); + free(buf); +} diff --git a/src/utils.c b/src/utils.c @@ -35,6 +35,8 @@ static struct { { NULL, 0 }, }; +static char b64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + void kore_debug_internal(char *file, int line, const char *fmt, ...) { @@ -244,6 +246,109 @@ kore_time_ms(void) return (tv.tv_sec * 1000 + (tv.tv_usec / 1000)); } +int +kore_base64_encode(u_int8_t *data, u_int32_t len, char **out) +{ + struct kore_buf *res; + u_int8_t n, *pdata; + int i, padding; + u_int32_t idx, b, plen; + + if ((len % 3) != 0) { + padding = 3 - (len % 3); + plen = len + padding; + pdata = (u_int8_t *)kore_malloc(plen); + + memcpy(pdata, data, len); + memset(pdata + len, 0, padding); + } else { + plen = len; + padding = 0; + pdata = data; + } + + res = kore_buf_create(plen); + + i = 2; + b = 0; + for (idx = 0; idx < plen; idx++) { + b |= (pdata[idx] << (i * 8)); + if (i-- == 0) { + for (i = 3; i >= 0; i--) { + n = (b >> (6 * i)) & 0x3f; + if (n >= sizeof(b64table)) { + kore_debug("unable to encode %d", n); + kore_buf_free(res); + return (KORE_RESULT_ERROR); + } + + if (idx >= len && i < padding) + break; + + kore_buf_append(res, + (u_int8_t *)&(b64table[n]), 1); + } + + b = 0; + i = 2; + } + } + + for (i = 0; i < padding; i++) + kore_buf_append(res, (u_int8_t *)"=", 1); + + if (pdata != data) + kore_mem_free(pdata); + + pdata = kore_buf_release(res, &plen); + *out = kore_malloc(plen + 1); + kore_strlcpy(*out, (char *)pdata, plen + 1); + kore_mem_free(pdata); + + return (KORE_RESULT_OK); +} + +int +kore_base64_decode(char *in, u_int8_t **out, u_int32_t *olen) +{ + int i; + struct kore_buf *res; + u_int8_t d, n, o; + u_int32_t b, len, idx; + + i = 3; + b = 0; + len = strlen(in); + res = kore_buf_create(len); + + for (idx = 0; idx < len; idx++) { + for (o = 0; o < sizeof(b64table); o++) { + if (b64table[o] == in[idx]) { + d = o; + break; + } + } + + /* XXX - This could be bad? */ + if (o == sizeof(b64table)) + d = 0; + + b |= (d & 0x3f) << (i * 6); + if (i-- == 0) { + for (i = 2; i >= 0; i--) { + n = (b >> (8 * i)); + kore_buf_append(res, &n, 1); + } + + b = 0; + i = 3; + } + } + + *out = kore_buf_release(res, olen); + return (KORE_RESULT_OK); +} + void fatal(const char *fmt, ...) {