Commit 3ad6ccfa authored by Geoff Simmons's avatar Geoff Simmons

- code compiles and passes make check

- implement base64_encode(), no test yet
- added encodings BASE64URL and BASE64URLNOPAD
parent 4c1e3936
......@@ -105,6 +105,8 @@ sub parse_token_code_gen {
my @vals = (qw(
IDENTITY
BASE64
BASE64URL
BASE64URLNOPAD
HEX
HEXLC));
......@@ -127,7 +129,7 @@ EOF
_OUT($h_out,
"enum encoding {\n\t_INVALID = 0,\n\t".
join(",\n\t", @vals)."\n};\n");
join(",\n\t", @vals).",\n\t__MAX_ENCODING\n};\n");
_OUT($h_out, <<'EOF');
......
#include <stdio.h>
#include <stdlib.h>
#include "vcl.h"
#include "vrt.h"
#include "vcc_if.h"
#include "parse_encoding.h"
#include "wb.h"
//#include "cache/cache.h"
int
init_function(struct vmod_priv *priv, const struct VCL_conf *conf)
{
return (0);
}
/*
* SAFE LENGTH ESTIMATES
*/
#define base64_decode_l(l) ((l * 3 / 4) + 1)
#define base64_encode_l(l) (((((l * 4 / 3) + 3) / 4) * 4) + 1)
#define hex_decode_l(l) ((l * 2) + 1)
#define hex_encode_l(l) ((l / 2) + 1)
static const struct vmod_priv const null_blob[1] =
{
......@@ -30,13 +33,51 @@ struct b64_state_s {
ssize_t l;
};
struct
static struct b64_alphabet {
char *b64;
char i64[256];
int padding;
} b64_alphabet[__MAX_ENCODING];
static bool
b64_e(const enum encodings enc, const char *in,
size_t inlen, char *out, size_t outlen)
static void
alpha_init(struct b64_alphabet *alpha)
{
int i;
const char *p;
for (i = 0; i < 256; i++)
alpha->i64[i] = -1;
for (p = alpha->b64, i = 0; *p; p++, i++)
alpha->i64[(int)*p] = (char)i;
if (alpha->padding)
alpha->i64[alpha->padding] = 0;
}
int __match_proto__(vmod_event_f)
event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e event)
{
(void) priv;
if (event != VCL_EVENT_LOAD)
return 0;
b64_alphabet[BASE64].b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
"ghijklmnopqrstuvwxyz0123456789+/";
b64_alphabet[BASE64].padding = '=';
b64_alphabet[BASE64URL].b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
"ghijklmnopqrstuvwxyz0123456789-_";
b64_alphabet[BASE64URL].padding = '=';
b64_alphabet[BASE64URLNOPAD].b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
"ghijklmnopqrstuvwxyz0123456789-_";
b64_alphabet[BASE64URLNOPAD].padding = 0;
alpha_init(&b64_alphabet[BASE64]);
alpha_init(&b64_alphabet[BASE64URL]);
alpha_init(&b64_alphabet[BASE64URLNOPAD]);
return (0);
}
/*
* Base64-encode *in (size: inlen) into *out, max outlen bytes. If there is
......@@ -51,77 +92,83 @@ size_t inlen, char *out, size_t outlen)
*
* FIXME: outlenorig is silly. Flip the logic.
*/
static size_t
base64_encode (const enum encodings enc, const char *in,
size_t inlen, char *out, size_t outlen)
static VCL_BLOB
base64_encode (struct ws *ws, const enum encoding enc, struct vmod_priv *rblob,
const char *in, size_t inlen)
{
struct b64_alphabet *alpha = &b64_alphabet[enc];
size_t outlenorig = outlen;
unsigned char tmp[3], idx;
if (outlen<4)
return -1;
if (inlen == 0) {
*out = '\0';
return (1);
}
while (1) {
assert(inlen);
assert(outlen>3);
tmp[0] = (unsigned char) in[0];
tmp[1] = (unsigned char) in[1];
tmp[2] = (unsigned char) in[2];
*out++ = alpha->b64[(tmp[0] >> 2) & 0x3f];
idx = (tmp[0] << 4);
if (inlen>1)
idx += (tmp[1] >> 4);
idx &= 0x3f;
*out++ = alpha->b64[idx];
if (inlen>1) {
idx = (tmp[1] << 2);
if (inlen>2)
idx += tmp[2] >> 6;
idx &= 0x3f;
*out++ = alpha->b64[idx];
} else {
if (alpha->padding)
*out++ = alpha->padding;
}
if (inlen>2) {
*out++ = alpha->b64[tmp[2] & 0x3f];
} else {
if (alpha->padding)
*out++ = alpha->padding;
}
/*
* XXX: Only consume 4 bytes, but since we need a fifth for
* XXX: NULL later on, we might as well test here.
*/
if (outlen<5)
return -1;
outlen -= 4;
if (inlen<4)
break;
inlen -= 3;
in += 3;
}
assert(outlen);
outlen--;
*out = '\0';
return outlenorig-outlen;
struct b64_alphabet *alpha = &b64_alphabet[enc];
struct wb_s wb;
char *p;
size_t outlen;
unsigned char tmp[3], idx;
CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
AN(rblob);
if (in == NULL || inlen == 0)
return null_blob;
p = wb_create(ws, &wb);
outlen = wb_space(&wb);
if (outlen < base64_encode_l(inlen))
return NULL;
while (1) {
assert(inlen);
assert(outlen > 3);
tmp[0] = (unsigned char) in[0];
tmp[1] = (unsigned char) in[1];
tmp[2] = (unsigned char) in[2];
*p++ = alpha->b64[(tmp[0] >> 2) & 0x3f];
idx = (tmp[0] << 4);
if (inlen > 1)
idx += (tmp[1] >> 4);
idx &= 0x3f;
*p++ = alpha->b64[idx];
if (inlen > 1) {
idx = (tmp[1] << 2);
if (inlen > 2)
idx += tmp[2] >> 6;
idx &= 0x3f;
*p++ = alpha->b64[idx];
} else {
if (alpha->padding)
*p++ = alpha->padding;
}
if (inlen > 2) {
*p++ = alpha->b64[tmp[2] & 0x3f];
} else {
if (alpha->padding)
*p++ = alpha->padding;
}
/*
* XXX: Only consume 4 bytes, but since we need a fifth for
* XXX: NULL later on, we might as well test here.
*/
assert(outlen >= 5);
outlen -= 4;
if (inlen < 4)
break;
inlen -= 3;
in += 3;
}
assert(outlen > 0);
wb_advanceP(&wb, p);
(void) wb_finish_blob(&wb, rblob);
if (rblob->len == 0)
return null_blob;
return rblob;
}
......@@ -222,17 +269,34 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
return null_blob;
}
VCL_STRING
vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
enum encoding enc = parse_encoding(encs);
struct vmod_priv tmp[1];
const struct vmod_priv *r;
const struct vmod_priv *r = NULL;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
assert(enc != _INVALID);
AN(b);
switch(enc) {
case IDENTITY:
// XXX
break;
case BASE64:
case BASE64URL:
case BASE64URLNOPAD:
r = base64_encode(ctx->ws, enc, tmp, b->priv, b->len);
break;
case HEX:
case HEXLC: // XXX: lower-case?
r = hex_encode(ctx->ws, tmp, b->len, b->priv,
vrt_magic_string_end);
break;
default:
WRONG("Illegal encoding");
}
assert(enc == HEXLC); // XXX
r = hex_encode(ctx->ws, tmp, b->len, b->priv, vrt_magic_string_end);
if (r == NULL)
return NULL;
return r->priv;
......
......@@ -12,13 +12,13 @@ DESCRIPTION
XXX write doc
XXX gen ENUMs
$Init init_function
$Event event
$Function BLOB decode(ENUM { IDENTITY, BASE64, HEX}, STRING_LIST)
$Function BLOB decode(ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX}, STRING_LIST)
XXX DOC
$Function STRING encode(ENUM { IDENTITY, BASE64, HEXLC}, BLOB)
$Function STRING encode(ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEXLC}, BLOB)
XXX DOC
$Function STRING transcode(ENUM { IDENTITY, BASE64, HEX}, ENUM { IDENTITY, BASE64, HEXLC}, STRING_LIST)
$Function STRING transcode(ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX}, ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEXLC}, STRING_LIST)
XXX DOC
$Function BLOB transcode_blob(ENUM { IDENTITY, BASE64, HEX}, ENUM { IDENTITY, BASE64, HEXLC}, BLOB)
$Function BLOB transcode_blob(ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX}, ENUM { IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEXLC}, BLOB)
XXX DOC
......@@ -41,7 +41,7 @@ static inline void
wb_advanceP(struct wb_s *wb, char *w) {
assert(w > wb->w);
assert(w < wb_end(wb)); // final byte
wb->w = w;;
wb->w = w;
}
char *wb_create(struct ws *ws, struct wb_s *wb);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment