Commit 09f3a681 authored by Geoff Simmons's avatar Geoff Simmons

first implementation of hex_decode()

parent ae773ead
......@@ -26,8 +26,12 @@
*
*/
#include <ctype.h>
#include <errno.h>
#include "vmod_convert.h"
#include "vrt.h"
#include "vas.h"
static const char hex_alphabet[][16] = {
......@@ -35,6 +39,72 @@ static const char hex_alphabet[][16] = {
"0123456789ABCDEF"
};
static char nibble[128];
static inline int
isxstr(const char * const p, ssize_t *l)
{
const char *s = p;
while (*s)
if (!isxdigit(*s++))
return 0;
else
*l += 1;
return 1;
}
static inline ssize_t
check(const char * const p, va_list ap)
{
ssize_t len = 0;
const char *next;
va_list ap2;
if (p == vrt_magic_string_end)
return 0;
if (p != NULL && !isxstr(p, &len))
return -1;
va_copy(ap2, ap);
while ((next = va_arg(ap2, const char *)) != vrt_magic_string_end)
if (next != NULL && !isxstr(next, &len)) {
len = -1;
break;
}
va_end(ap2);
return len;
}
static inline void
decode_str(const char *restrict const p, char *restrict *restrict dest,
unsigned char *restrict extranib)
{
const unsigned char *s = (unsigned char *) p;
char *d = *dest;
if (*extranib)
*d++ = (nibble[*extranib] << 4) | nibble[*s++];
while (*s && *(s+1)) {
*d++ = (nibble[*s] << 4) | nibble[*(s+1)];
s += 2;
}
*extranib = *s;
*dest += d - *dest;
}
void
hex_init(void)
{
for (int i = 0; i < 128; i++)
nibble[i] = -1;
for (char c = '0'; c <= '9'; c++)
nibble[(int) c] = c - '0';
for (char c = 'a'; c <= 'f'; c++)
nibble[(int) c] = c - 'a' + 10;
for (char c = 'A'; c <= 'F'; c++)
nibble[(int) c] = c - 'A' + 10;
}
ssize_t
hex_encode(const enum encoding enc, char *restrict const buf,
const size_t maxlen, const char *restrict const in,
......@@ -59,3 +129,44 @@ hex_encode(const enum encoding enc, char *restrict const buf,
return p - buf;
}
ssize_t
hex_decode(const enum encoding dec, char *restrict const buf,
const size_t maxlen, const char *restrict const p, va_list ap)
{
const char *next;
char *dest = buf;
unsigned char extranib = 0;
ssize_t len;
AN(buf);
assert(dec == HEX);
if (p == vrt_magic_string_end)
return 0;
if ((len = check(p, ap)) == 0)
return 0;
if (len == -1) {
errno = EINVAL;
return -1;
}
if ((len+1) >> 1 > maxlen) {
errno = ENOMEM;
return -1;
}
if (len & 1)
extranib = '0';
SKIP_EMPTY(next, ap);
assert(next != vrt_magic_string_end || (p != NULL && *p != '\0'));
if (p != NULL && *p != '\0')
decode_str(p, &dest, &extranib);
while (next != vrt_magic_string_end) {
decode_str(next, &dest, &extranib);
SKIP_EMPTY(next, ap);
}
assert(dest <= buf + maxlen);
return dest - buf;
}
......@@ -20,6 +20,36 @@ varnish v1 -vcl+backend {
convert.encode(HEX, convert.decode(IDENTITY,
"The quick brown fox jumps over the lazy dog"));
set resp.http.dec =
convert.encode(IDENTITY, convert.decode(HEX,
"666F6F206261722062617A2071757578"));
set resp.http.decempty =
convert.encode(IDENTITY, convert.decode(HEX, ""));
set resp.http.decempty2bytes =
convert.encode(IDENTITY, convert.decode(HEX, "00"));
set resp.http.decempty1byte =
convert.encode(IDENTITY, convert.decode(HEX, "0"));
set req.http.part1 = "666";
set resp.http.dec2pieces =
convert.encode(IDENTITY, convert.decode(HEX, req.http.part1 +
"F6F206261722062617A2071757578"));
set req.http.part2 = "57578";
set resp.http.dec3pieces =
convert.encode(IDENTITY, convert.decode(HEX, req.http.part1 +
"F6F206261722062617A20717" + req.http.part2));
set resp.http.decmanypieces =
convert.encode(IDENTITY, convert.decode(HEX, "" + req.http.unset +
req.http.part1 + req.http.unset + "" +
req.http.unset + "" + "F6F206261722062617A20717" +
"" + req.http.unset + req.http.part2 +
req.http.unset + "" + req.http.unset));
set resp.http.hexlcxcode =
convert.transcode(IDENTITY, HEXLC, req.url +
"Hel" + "lo " + "" + "world" +
......@@ -37,6 +67,13 @@ client c1 {
rxresp
expect resp.http.hexlc == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
expect resp.http.hexuc == "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67"
expect resp.http.dec == "foo bar baz quux"
expect resp.http.decempty == ""
expect resp.http.decempty2bytes == ""
expect resp.http.decempty1byte == ""
expect resp.http.dec2pieces == "foo bar baz quux"
expect resp.http.dec3pieces == "foo bar baz quux"
expect resp.http.decmanypieces == "foo bar baz quux"
expect resp.http.hexlcxcode == "2f48656c6c6f20776f726c642f"
expect resp.http.hexucxcode == "2F48656C6C6F20776F726C642F"
}
......
......@@ -116,6 +116,8 @@ decode(const enum encoding dec, char *restrict const buf,
switch(dec) {
case IDENTITY:
return id_decode(dec, buf, maxlen, p, ap);
case HEX:
return hex_decode(dec, buf, maxlen, p, ap);
default:
WRONG("Illegal decoding");
}
......@@ -149,6 +151,7 @@ event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e event)
if (event != VCL_EVENT_LOAD)
return 0;
hex_init();
base64_init();
return (0);
}
......
......@@ -109,4 +109,6 @@ void base64_init(void);
encode_f base64_encode;
/* hex.c */
void hex_init(void);
encode_f hex_encode;
decode_f hex_decode;
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