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