Commit 4917bd95 authored by Geoff Simmons's avatar Geoff Simmons

add decode_n() and transcode_n()

Patch by Nils Goroll <nils.goroll@uplex.de>
parent 3e74a3e5
......@@ -121,7 +121,8 @@ base64_encode(const enum encoding enc, char *restrict const buf,
ssize_t
base64_decode(const enum encoding dec, char *restrict const buf,
const size_t buflen, const char *restrict const p, va_list ap)
const size_t buflen, ssize_t inlen,
const char *const p, va_list ap)
{
const struct b64_alphabet *alpha = &b64_alphabet[dec];
char *dest = buf;
......@@ -139,7 +140,7 @@ base64_decode(const enum encoding dec, char *restrict const buf,
errno = EINVAL;
return -1;
}
while (*s) {
while (*s && (inlen == -1 || inlen > 0)) {
while (n < 4) {
char b = alpha->i64[(unsigned) *s++];
u <<= 6;
......@@ -155,6 +156,11 @@ base64_decode(const enum encoding dec, char *restrict const buf,
u |= (unsigned) b;
if (!*s)
break;
if (inlen != -1) {
--inlen;
if (inlen == 0)
break;
}
}
if (n == 4) {
if (decode(&dest, buf, buflen, u, n-term) < 0) {
......@@ -164,6 +170,8 @@ base64_decode(const enum encoding dec, char *restrict const buf,
n = 0;
}
}
if (inlen != -1 && inlen == 0)
break;
}
if (n) {
if (!alpha->padding)
......
......@@ -100,7 +100,8 @@ hex_encode(const enum encoding enc, char *restrict const buf,
ssize_t
hex_decode(const enum encoding dec, char *restrict const buf,
const size_t buflen, const char *restrict const p, va_list ap)
const size_t buflen, ssize_t n,
const char *restrict const p, va_list ap)
{
char *dest = buf;
unsigned char extranib = 0;
......@@ -132,22 +133,30 @@ hex_decode(const enum encoding dec, char *restrict const buf,
errno = EINVAL;
return -1;
}
if (n != -1 && len > n)
len = n;
if ((len+1) >> 1 > buflen) {
errno = ENOMEM;
return -1;
}
if (len & 1)
if (len & 1) {
extranib = '0';
len++;
}
for (const char *s = p; s != vrt_magic_string_end;
for (const char *s = p; len > 0 && s != vrt_magic_string_end;
s = va_arg(ap, const char *)) {
if (s == NULL || *s == '\0')
continue;
if (extranib)
if (extranib) {
*dest++ = hex2byte(extranib, *s++);
while (*s && *(s+1)) {
len -= 2;
}
while (len >= 2 && *s && *(s+1)) {
*dest++ = hex2byte(*s, *(s+1));
s += 2;
len -= 2;
}
extranib = *s;
}
......
......@@ -64,8 +64,9 @@ id_encode(const enum encoding enc, char *restrict const buf,
}
ssize_t
id_decode(const enum encoding enc, char *restrict const buf,
const size_t buflen, const char *restrict const p, va_list ap)
id_decode(const enum encoding enc,
char *restrict const buf, const size_t buflen,
ssize_t n, const char *restrict const p, va_list ap)
{
char *dest = buf;
size_t len, outlen = 0;
......@@ -78,6 +79,13 @@ id_decode(const enum encoding enc, char *restrict const buf,
if (s == NULL || *s == '\0')
continue;
len = strlen(s);
if (n >= 0) {
if (n == 0)
break;
if (len > n)
len = n;
n -= len;
}
if ((outlen += len) > buflen) {
errno = ENOMEM;
return -1;
......
......@@ -226,7 +226,7 @@ vmod_blob__init(VRT_CTX, struct vmod_blobcode_blob **blobp, const char *vcl_name
va_start(ap, p);
errno = 0;
len = func[dec].decode(dec, b->blob.priv, len, p, ap);
len = func[dec].decode(dec, b->blob.priv, len, -1, p, ap);
va_end(ap);
if (len == -1) {
......@@ -325,10 +325,10 @@ vmod_blob__fini(struct vmod_blobcode_blob **blobp)
/* Functions */
VCL_BLOB __match_proto__(td_blobcode_decode)
vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
static VCL_BLOB
decode(VRT_CTX, VCL_INT n, VCL_ENUM decs, const char *restrict const p,
va_list ap) {
enum encoding dec = parse_encoding(decs);
va_list ap;
struct wb_s wb;
struct vmod_priv *b;
char *snap, *buf;
......@@ -355,10 +355,8 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
}
buf = wb_buf(&wb);
va_start(ap, p);
errno = 0;
len = func[dec].decode(dec, buf, wb_space(&wb), p, ap);
va_end(ap);
len = func[dec].decode(dec, buf, wb_space(&wb), n, p, ap);
if (len == -1) {
err_decode(ctx, p);
......@@ -379,6 +377,30 @@ vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
return b;
}
VCL_BLOB __match_proto__(td_blobcode_decode)
vmod_decode(VRT_CTX, VCL_ENUM decs, const char *p, ...) {
va_list ap;
VCL_BLOB r;
va_start(ap, p);
r = decode(ctx, -1, decs, p, ap);
va_end(ap);
return (r);
}
VCL_BLOB __match_proto__(td_blobcode_decode_n)
vmod_decode_n(VRT_CTX, VCL_INT n, VCL_ENUM decs, const char *p, ...) {
va_list ap;
VCL_BLOB r;
va_start(ap, p);
r = decode(ctx, n, decs, p, ap);
va_end(ap);
return (r);
}
VCL_STRING __match_proto__(td_blobcode_encode)
vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
enum encoding enc = parse_encoding(encs);
......@@ -417,13 +439,14 @@ vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b) {
return wb_finish(&wb, NULL);
}
VCL_STRING __match_proto__(td_blobcode_transcode)
vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
static VCL_STRING
transcode(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
const char *restrict const p, va_list ap) {
enum encoding dec = parse_encoding(decs);
enum encoding enc = parse_encoding(encs);
struct wb_s wb;
ssize_t len;
va_list ap;
va_list aq;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (INIT_FINI(ctx)) {
......@@ -435,19 +458,22 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
AENC(dec);
AENC(enc);
/* Allocate space for the decoded blob on the stack */
va_start(ap, p);
size_t l = decode_l_va(dec, p, ap);
va_end(ap);
/*
* Allocate space for the decoded blob on the stack
* ignoring the limitation imposed by n
*/
va_copy(aq, ap);
size_t l = decode_l_va(dec, p, aq);
va_end(aq);
if (l == 0)
return "";
/* XXX: handle stack overflow? */
char buf[l];
va_start(ap, p);
errno = 0;
len = func[dec].decode(dec, buf, l, p, ap);
va_end(ap);
va_copy(aq, ap);
len = func[dec].decode(dec, buf, l, n, p, aq);
va_end(aq);
if (len == -1) {
err_decode(ctx, p);
......@@ -459,9 +485,8 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
* legal, just return the concatenated string.
*/
if (enc == dec) {
va_start(ap, p);
VCL_STRING s = VRT_String(ctx->ws, NULL, p, ap);
va_end(ap);
VCL_STRING s;
s = VRT_String(ctx->ws, NULL, p, ap);
return s;
}
......@@ -484,6 +509,32 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, const char *p, ...) {
return wb_finish(&wb, NULL);
}
VCL_STRING __match_proto__(td_blobcode_transcode)
vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs,
const char *p, ...) {
va_list ap;
VCL_STRING r;
va_start(ap, p);
r = transcode(ctx, -1, decs, encs, p, ap);
va_end(ap);
return (r);
}
VCL_STRING __match_proto__(td_blobcode_transcode_n)
vmod_transcode_n(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
const char *p, ...) {
va_list ap;
VCL_STRING r;
va_start(ap, p);
r = transcode(ctx, n, decs, encs, p, ap);
va_end(ap);
return (r);
}
VCL_STRING __match_proto__(td_blobcode_version)
vmod_version(VRT_CTX __attribute__((unused)))
{
......
......@@ -77,6 +77,7 @@ ssize_t encode_f(const enum encoding enc, char *restrict const buf,
* dec: decoding enum (from parse_encoding.h)
* buf: destination of the decoded data
* buflen: maximum length available at buf
* inlen: maximum length to read or -1 to read up to \0
* p, ap: strings obtained from a VCL STRING_LIST
*
* The regions pointed to by buf and any of the strings in p or ap MUST
......@@ -93,7 +94,8 @@ ssize_t encode_f(const enum encoding enc, char *restrict const buf,
*/
typedef
ssize_t decode_f(const enum encoding dec, char *restrict const buf,
const size_t buflen, const char *restrict const p, va_list ap);
const size_t buflen, const ssize_t inlen,
const char *restrict const p, va_list ap);
/* id.c */
len_f id_encode_l;
......
......@@ -144,6 +144,14 @@ Description
Example
``blobcode.decode(decoding=BASE64, encoded="Zm9vYmFyYmF6")``
$Function BLOB decode_n(INT n,
ENUM {IDENTITY, BASE64, BASE64URL,
BASE64URLNOPAD, HEX} decoding,
STRING_LIST encoded)
Description
Same as ``decode()``, but only decode ``n`` characters.
$Function STRING encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEXUC, HEXLC} encoding, BLOB blob)
......@@ -171,6 +179,16 @@ Example
``set req.http.Hex2Base64 = blobcode.transcode(decoding=HEX,``
``encoding=BASE64, encoded="666f6f");``
$Function STRING transcode_n(INT n,
ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEX} decoding,
ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEXUC, HEXLC} encoding,
STRING_LIST encoded)
Description
Same as ``transcode()``, but only transcode ``n`` characters.
$Function STRING version()
Description
......
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