Commit 4c1e3936 authored by Nils Goroll's avatar Nils Goroll

wip

parent ce5f2bc5
......@@ -12,7 +12,9 @@ nodist_libvmod_convert_la_SOURCES = \
vcc_if.c \
vcc_if.h \
parse_encoding.h \
parse_encoding.c
parse_encoding.c \
wb.h \
wb.c
parse_encoding.h: parse_encoding.c
......
......@@ -2,10 +2,11 @@
#include <stdlib.h>
#include "vrt.h"
#include "cache/cache.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)
......@@ -22,6 +23,109 @@ static const struct vmod_priv const null_blob[1] =
}
};
struct b64_state_s {
uint32_t magic;
#define B64_STATE_MAGIC 0xc0b64b64
unsigned char bytes[2];
ssize_t l;
};
struct
static bool
b64_e(const enum encodings enc, const char *in,
size_t inlen, char *out, size_t outlen)
{
/*
* Base64-encode *in (size: inlen) into *out, max outlen bytes. If there is
* insufficient space, it will bail out and return -1. Otherwise, it will
* null-terminate and return the used space.
* The alphabet `a` defines... the alphabet. Padding is optional.
* Inspired heavily by gnulib/Simon Josefsson (as referenced in RFC4648)
*
* XXX: tmp[] and idx are used to ensure the reader (and author) retains
* XXX: a limited amount of sanity. They are strictly speaking not
* XXX: necessary, if you don't mind going crazy.
*
* 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)
{
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;
}
static inline char
hexnibblelc(char c)
{
......@@ -42,16 +146,20 @@ static VCL_BLOB
hex_encode_va(struct ws *ws, struct vmod_priv *rblob, const ssize_t len,
const char *in, va_list va)
{
char *p = ws->f;
char *out = p; // should be const, but (struct vmod_priv).priv isnt
const char *e = out + WS_Reserve(ws, 0);
struct wb_s wb[1];
char *p;
ssize_t insz;
int i;
AN(rblob);
if (in == vrt_magic_string_end)
goto nodata;
return null_blob;
p = wb_create(ws, wb);
if (p == NULL)
return NULL;
const char *e = wb_end(wb);
if (len != -1)
insz = len;
......@@ -63,8 +171,7 @@ hex_encode_va(struct ws *ws, struct vmod_priv *rblob, const ssize_t len,
do {
if (insz == 0)
goto next;
// p + 2 includes terminating null byte
for (i = 0; i < insz && p + 2 < e; i++) {
for (i = 0; i < insz && p + 1 < e; i++) {
*p++ = hexnibblelc((in[i] & 0xf0) >> 4);
*p++ = hexnibblelc( in[i] & 0x0f);
}
......@@ -78,26 +185,17 @@ hex_encode_va(struct ws *ws, struct vmod_priv *rblob, const ssize_t len,
insz = (in != NULL) ? strlen(in) : 0;
} while(1);
if (p == out)
goto nodata;
*p++ = '\0';
assert(p < e);
wb_advanceP(wb, p);
rblob->priv = out;
rblob->len = p - out - 1;
rblob->free = NULL;
(void) wb_finish_blob(wb, rblob);
WS_ReleaseP(ws, p);
if (rblob->len == 0)
return null_blob;
return rblob;
nodata:
WS_Release(ws, 0);
return null_blob;
err:
WS_Release(ws, 0);
wb_reset(wb);
return NULL;
}
......
/*-
* Copyright 2015 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Authors: Nils Goroll <nils.goroll@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* write buffer: utility functions to append-write on a varnish workspace
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "wb.h"
#include "vrt.h"
char *
wb_create(struct ws *ws, struct wb_s *wb)
{
if (WS_Reserve(ws, 0) == 0) {
wb->w = NULL;
wb->ws = NULL;
return NULL;
}
wb->w = ws->f;
wb->ws = ws;
return wb->w;
}
void
wb_reset(struct wb_s *wb)
{
WS_Release(wb->ws, 0);
memset(wb, 0, sizeof(*wb));
}
bool
wb_append(struct wb_s *wb, const char *format, ...)
{
int len;
va_list ap;
const ssize_t space = wb_space(wb);
va_start(ap, format);
len = vsnprintf(wb->w, space, format, ap);
va_end(ap);
if (len >= space) {
wb_reset(wb);
return false;
} else {
wb_advance(wb, len);
}
return true;
}
/*
* release varnish workspace
*
* return start of buffer
*/
char *
wb_finish(struct wb_s *wb, ssize_t *l)
{
char *r = wb->ws->f;
assert(wb->ws->r - wb->w > 0);
if (l)
*l = wb_len(wb);
*wb->w = '\0';
wb->w++;
/* amount of space used */
WS_ReleaseP(wb->ws, wb->w);
return r;
}
/*
* finish into a blob
*/
struct vmod_priv *
wb_finish_blob(struct wb_s *wb, struct vmod_priv *blob) {
ssize_t l;
blob->priv = wb_finish(wb, &l);
blob->len = l;
blob->free = NULL;
return blob;
}
#include <stdbool.h>
#include <unistd.h>
#include "cache/cache.h"
struct ws;
struct wb_s {
struct ws *ws; // varnish workspace
char *w; // current write position
};
/* return one byte less for the final zero byte */
static inline const char*
wb_end(struct wb_s *wb) {
return wb->ws->r - 1;
}
/* return one byte less for the final zero byte */
static inline ssize_t
wb_space(struct wb_s *wb) {
ssize_t f = wb->ws->r - wb->w;
assert(f > 0);
return f - 1;
}
static inline ssize_t
wb_len(struct wb_s *wb) {
ssize_t l = wb->w - wb->ws->f;
assert(l >= 0);
return l;
}
static inline void
wb_advance(struct wb_s *wb, ssize_t l) {
wb->w += l; // final byte
assert(wb->w < wb_end(wb));
}
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;;
}
char *wb_create(struct ws *ws, struct wb_s *wb);
void wb_reset(struct wb_s *wb);
bool wb_printf(struct wb_s *wb, const char *format, ...);
char *wb_finish(struct wb_s *wb, ssize_t *l);
struct vmod_priv *wb_finish_blob(struct wb_s *wb, struct vmod_priv *blob);
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