Commit 30a16b53 authored by Geoff Simmons's avatar Geoff Simmons

first version with URL encoding

parent 7b8a1650
......@@ -12,6 +12,7 @@ libvmod_blobcode_la_SOURCES = \
base64.h \
base64.c \
hex.c \
url.c \
wb.h \
wb.c
......
......@@ -116,7 +116,10 @@ my @vals = (qw(
BASE64URLNOPAD
HEX
HEXUC
HEXLC));
HEXLC
URL
URLLC
URLUC));
unless ($#ARGV == 1) {
printf(STDERR 'Usage: '.$0." <c-file> <h-file>\n");
......
# looks like -*- perl -*-
varnishtest "url encode and decode"
varnish v1 -vcl {
import blobcode from "${vmod_topbuild}/src/.libs/libvmod_blobcode.so";
import std;
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set req.http.pangram = "The quick brown fox jumps over the lazy dog";
set req.http.hobbes =
{"Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."};
set req.http.umlauts = "Übergrößenträger";
set req.http.phkspeak = "småbørnspædagog";
set req.http.utf8 = "日扼語";
# base64 encoding of all 256 byte values in ascending order
set req.http.b64all =
{"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="};
set resp.http.urllc =
blobcode.encode(URLLC,
blobcode.decode(IDENTITY, req.http.pangram));
set resp.http.urluc =
blobcode.encode(URLUC,
blobcode.decode(IDENTITY, req.http.pangram));
set resp.http.hobbeslc =
blobcode.encode(URLLC, blobcode.decode(IDENTITY, req.http.hobbes));
set resp.http.hobbesuc =
blobcode.encode(URLUC, blobcode.decode(IDENTITY, req.http.hobbes));
set resp.http.umlautslc =
blobcode.encode(URLLC,
blobcode.decode(IDENTITY, req.http.umlauts));
set resp.http.umlautsuc =
blobcode.encode(URLUC,
blobcode.decode(IDENTITY, req.http.umlauts));
set resp.http.phklc =
blobcode.encode(URLLC,
blobcode.decode(IDENTITY, req.http.phkspeak));
set resp.http.phkuc =
blobcode.encode(URLUC,
blobcode.decode(IDENTITY, req.http.phkspeak));
set resp.http.utf8lc =
blobcode.encode(URLLC, blobcode.decode(IDENTITY, req.http.utf8));
set resp.http.utf8uc =
blobcode.encode(URLUC, blobcode.decode(IDENTITY, req.http.utf8));
set resp.http.all-lc =
blobcode.encode(URLLC, blobcode.decode(BASE64, req.http.b64all));
set resp.http.all-uc =
blobcode.encode(URLUC, blobcode.decode(BASE64, req.http.b64all));
set resp.http.empty-lc =
blobcode.encode(URLLC, blobcode.decode(IDENTITY, ""));
set resp.http.empty-uc =
blobcode.encode(URLUC, blobcode.decode(IDENTITY, ""));
set resp.http.urllcparam =
blobcode.encode(blob=blobcode.decode(IDENTITY, req.http.pangram),
encoding=URLLC);
set resp.http.urlucparam =
blobcode.encode(blob=blobcode.decode(IDENTITY, req.http.pangram),
encoding=URLUC);
set req.http.urllcfoobar = "foo%3abar%3abaz%3aquux";
set req.http.urlucfoobar = "foo%3Abar%3Abaz%3Aquux";
set req.http.urlhobbeslc = "Man%20is%20distinguished%2c%20not%20only%20by%20his%20reason%2c%20but%20by%20this%20singular%20passion%20from%20other%20animals%2c%20which%20is%20a%20lust%20of%20the%20mind%2c%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2c%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure.";
set req.http.urlhobbesuc = "Man%20is%20distinguished%2C%20not%20only%20by%20his%20reason%2C%20but%20by%20this%20singular%20passion%20from%20other%20animals%2C%20which%20is%20a%20lust%20of%20the%20mind%2C%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2C%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure.";
set req.http.urllcumlauts = "%c3%9cbergr%c3%b6%c3%9fentr%c3%a4ger";
set req.http.urlucumlauts = "%C3%9Cbergr%C3%B6%C3%9Fentr%C3%A4ger";
set req.http.urllcphk = "sm%c3%a5b%c3%b8rnsp%c3%a6dagog";
set req.http.urlucphk = "sm%C3%A5b%C3%B8rnsp%C3%A6dagog";
set req.http.urllcutf8 = "%e6%97%a5%e6%89%bc%e8%aa%9e";
set req.http.urlucutf8 = "%E6%97%A5%E6%89%BC%E8%AA%9E";
set req.http.urlalluc = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF";
set req.http.urlalllc = "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff";
set resp.http.decuc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlucfoobar));
set resp.http.declc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urllcfoobar));
set resp.http.dechobbesuc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlhobbesuc));
set resp.http.dechobbeslc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlhobbeslc));
set resp.http.decumlautsuc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlucumlauts));
set resp.http.decumlautslc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urllcumlauts));
set resp.http.decphkuc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlucphk));
set resp.http.decphklc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urllcphk));
set resp.http.decutf8uc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urlucutf8));
set resp.http.decutf8lc =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.urllcutf8));
set resp.http.decalluc =
blobcode.encode(BASE64, blobcode.decode(URL, req.http.urlalluc));
set resp.http.decalllc =
blobcode.encode(BASE64, blobcode.decode(URL, req.http.urlalllc));
set resp.http.decempty =
blobcode.encode(IDENTITY, blobcode.decode(URL, ""));
set resp.http.decemptybyte =
blobcode.encode(IDENTITY, blobcode.decode(URL, "%00"));
set resp.http.decemptypieces =
blobcode.encode(IDENTITY,
blobcode.decode(URL, req.http.unset + ""
+ req.http.unset + ""));
set req.http.part1 = "foo%";
set resp.http.dec2pieces =
blobcode.encode(IDENTITY, blobcode.decode(URL, req.http.part1 +
"20bar%20baz%20quux"));
set req.http.part2 = "0quux";
set resp.http.dec3param =
blobcode.encode(blob=blobcode.decode(encoded=req.http.part1 +
"20bar%20baz%2" + req.http.part2,
decoding=URL),
encoding=IDENTITY);
set resp.http.dec3pieces =
blobcode.encode(IDENTITY, blobcode.decode(URL, req.http.part1 +
"20bar%20baz%2" + req.http.part2));
set resp.http.decmanypieces =
blobcode.encode(IDENTITY, blobcode.decode(URL, "" + req.http.unset
+ req.http.part1 + req.http.unset + ""
+ req.http.unset + "" + "20bar%20baz%2"
+ "" + req.http.unset + req.http.part2
+ req.http.unset + "" + req.http.unset));
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.urllc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
expect resp.http.urluc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
expect resp.http.hobbeslc == "Man%20is%20distinguished%2c%20not%20only%20by%20his%20reason%2c%20but%20by%20this%20singular%20passion%20from%20other%20animals%2c%20which%20is%20a%20lust%20of%20the%20mind%2c%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2c%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
expect resp.http.hobbesuc == "Man%20is%20distinguished%2C%20not%20only%20by%20his%20reason%2C%20but%20by%20this%20singular%20passion%20from%20other%20animals%2C%20which%20is%20a%20lust%20of%20the%20mind%2C%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2C%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
expect resp.http.umlautslc == "%c3%9cbergr%c3%b6%c3%9fentr%c3%a4ger"
expect resp.http.umlautsuc == "%C3%9Cbergr%C3%B6%C3%9Fentr%C3%A4ger"
expect resp.http.phklc == "sm%c3%a5b%c3%b8rnsp%c3%a6dagog"
expect resp.http.phkuc == "sm%C3%A5b%C3%B8rnsp%C3%A6dagog"
expect resp.http.utf8lc == "%e6%97%a5%e6%89%bc%e8%aa%9e"
expect resp.http.utf8uc == "%E6%97%A5%E6%89%BC%E8%AA%9E"
expect resp.http.all-lc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
expect resp.http.all-uc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
expect resp.http.empty-uc == ""
expect resp.http.empty-lc == ""
expect resp.http.urllcparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
expect resp.http.urlucparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
expect resp.http.decuc == "foo:bar:baz:quux"
expect resp.http.declc == "foo:bar:baz:quux"
expect resp.http.dechobbesuc == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
expect resp.http.dechobbeslc == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
expect resp.http.decumlautsuc == "Übergrößenträger"
expect resp.http.decumlautslc == "Übergrößenträger"
expect resp.http.decphkuc == "småbørnspædagog"
expect resp.http.decphklc == "småbørnspædagog"
expect resp.http.decutf8uc == "日扼語"
expect resp.http.decutf8lc == "日扼語"
expect resp.http.decalluc == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
expect resp.http.decalllc == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
expect resp.http.decempty == ""
expect resp.http.decemptybyte == ""
expect resp.http.decemptypieces == ""
expect resp.http.dec2pieces == "foo bar baz quux"
expect resp.http.dec3pieces == "foo bar baz quux"
expect resp.http.dec3param == "foo bar baz quux"
expect resp.http.decmanypieces == "foo bar baz quux"
} -run
#varnish v1 -vcl {
# import blobcode from "${vmod_topbuild}/src/.libs/libvmod_blobcode.so";
# backend b { .host = "${bad_ip}"; }
#
# sub vcl_recv {
# return(synth(200));
# }
#
# sub vcl_synth {
# set req.http.foo = "123";
# set resp.http.badurl = blobcode.encode(URLUC,
# blobcode.decode(URL, "g" + req.http.foo));
# }
#}
#client c1 {
# txreq
# rxresp
# expect resp.http.badurl == ""
#} -run
#logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
# expect 0 * Begin req
# expect * = VCL_Error "^vmod blobcode error: cannot decode, illegal encoding beginning with \"g\"$"
#"
# expect * = End
#} -start
#logexpect l1 -wait
/*-
* Copyright 2015-2016 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Authors: Nils Goroll <nils.goroll@uplex.de>
* Geoffrey Simmons <geoffrey.simmons@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.
*
*/
#include <errno.h>
#include <stdint.h>
#include "vmod_blobcode.h"
#include "vrt.h"
#include "vas.h"
enum state_e {
NORMAL,
PERCENT,
FIRSTNIB,
};
size_t
url_encode_l(size_t l)
{
return l * 3;
}
size_t
url_decode_l(size_t l)
{
return l;
}
/*
* Bitmap of unreserved characters according to RFC 3986 section 2.3
* (locale-independent and cacheline friendly)
*/
static const uint8_t unreserved[] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xff, 0x3,
0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x47,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
};
static const char hex_alphabet[][16] = {
"0123456789abcdef",
"0123456789ABCDEF"
};
/*
* Shift the ASCII table over so that it begins at '0', and replace the
* hex digits with their binary values. This fits all of the hex digits
* into 55 bytes (cacheline friendly).
*/
static const uint8_t nibble[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10, 11, 12,
13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10,
11, 12, 13, 14, 15
};
static inline char
hex2byte(const unsigned char hi, const unsigned char lo)
{
return (nibble[hi - '0'] << 4) | nibble[lo - '0'];
}
static inline int
isunreserved(const uint8_t c)
{
return (unreserved[c >> 3] & (1 << (c & 7)));
}
ssize_t
url_encode(const enum encoding enc, char *restrict const buf,
const size_t buflen, const char *restrict const in,
const size_t inlen)
{
char *p = buf;
const char *alphabet = hex_alphabet[0];
AN(buf);
assert(enc == URLUC || enc == URLLC);
if (in == NULL || inlen == 0)
return 0;
if (enc != URLLC)
alphabet = hex_alphabet[1];
for (int i = 0; i < inlen; i++) {
if (isunreserved(in[i])) {
if (p + 1 - buf > buflen)
return -1;
*p++ = in[i];
}
else {
if (p + 3 - buf > buflen)
return -1;
*p++ = '%';
*p++ = alphabet[(in[i] & 0xf0) >> 4];
*p++ = alphabet[in[i] & 0x0f];
}
}
return p - buf;
}
ssize_t
url_decode(const enum encoding dec, char *restrict const buf,
const size_t buflen, ssize_t n, const char *restrict const p,
va_list ap)
{
char *dest = buf;
const char * const end = buf + buflen;
size_t len = SIZE_MAX;
uint8_t nib = 0;
enum state_e state = NORMAL;
AN(buf);
assert(dec == URL);
if (n >= 0 && n < len)
len = n;
for (const char *s = p; len > 0 && s != vrt_magic_string_end;
s = va_arg(ap, const char *)) {
if (s == NULL || *s == '\0')
continue;
while (*s && len) {
uint8_t nib2;
if (dest + 1 > end) {
errno = ENOMEM;
return -1;
}
switch(state) {
case NORMAL:
if (*s == '%')
state = PERCENT;
else
*dest++ = *s;
break;
case PERCENT:
if ((nib = nibble[*s - '0']) == 0xff) {
errno = EINVAL;
return -1;
}
state = FIRSTNIB;
break;
case FIRSTNIB:
if ((nib2 = nibble[*s - '0']) == 0xff) {
errno = EINVAL;
return -1;
}
*dest++ = (nib << 4) | nib2;
nib = 0;
state = NORMAL;
break;
default:
WRONG("illegal URL decode state");
}
s++;
len--;
}
}
if (state != NORMAL) {
errno = EINVAL;
return -1;
}
assert(dest <= end);
return dest - buf;
}
......@@ -57,6 +57,12 @@ struct vmod_blobcode_blob {
.encode_l = hex_encode_l, \
.encode = hex_encode
#define URL_FUNCS \
.decode_l = url_decode_l, \
.decode = url_decode, \
.encode_l = url_encode_l, \
.encode = url_encode
static const struct vmod_blobcode_fptr {
len_f *const decode_l;
decode_f *const decode;
......@@ -96,11 +102,21 @@ static const struct vmod_blobcode_fptr {
},
[HEXLC] = {
HEX_FUNCS
},
[URL] = {
URL_FUNCS
},
[URLUC] = {
URL_FUNCS
},
[URLLC] = {
URL_FUNCS
}
};
#undef B64_FUNCS
#undef HEX_FUNCS
#undef URL_FUNCS
#define ERR(ctx, msg) \
errmsg((ctx), "vmod blobcode error: " msg)
......
......@@ -112,9 +112,16 @@ len_f base64_encode_l;
encode_f base64_encode;
decode_f base64_decode;
/* hex.c */
/* hex.c */
len_f hex_encode_l;
len_f hex_decode_l;
encode_f hex_encode;
decode_f hex_decode;
/* url.c */
len_f url_encode_l;
len_f url_decode_l;
encode_f url_encode;
decode_f url_decode;
......@@ -135,7 +135,7 @@ byte. For example::
req.http.First + req.http.Second));
$Function BLOB decode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEX} decoding, STRING_LIST encoded)
HEX, URL} decoding, STRING_LIST encoded)
Description
Returns the BLOB derived from the string ``encoded``
......@@ -146,7 +146,7 @@ Example
$Function BLOB decode_n(INT n,
ENUM {IDENTITY, BASE64, BASE64URL,
BASE64URLNOPAD, HEX} decoding,
BASE64URLNOPAD, HEX, URL} decoding,
STRING_LIST encoded)
Description
......@@ -155,7 +155,7 @@ Description
the string, then return the same result as ``decode()``.
$Function STRING encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEXUC, HEXLC} encoding, BLOB blob)
HEXUC, HEXLC, URLUC, URLLC} encoding, BLOB blob)
Description
Returns a string representation of the BLOB ``blob`` as
......@@ -166,9 +166,9 @@ Example
``blob=blobcode.decode(BASE64, "Zm9vYmFyYmF6");``
$Function STRING transcode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEX} decoding,
HEX, URL} decoding,
ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEXUC, HEXLC} encoding,
HEXUC, HEXLC, URLUC, URLLC} encoding,
STRING_LIST encoded)
Description
......@@ -183,9 +183,9 @@ Example
$Function STRING transcode_n(INT n,
ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEX} decoding,
HEX, URL} decoding,
ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
HEXUC, HEXLC} encoding,
HEXUC, HEXLC, URLUC, URLLC} encoding,
STRING_LIST encoded)
Description
......@@ -200,7 +200,8 @@ Description
Example
``std.log("Using VMOD blobcode version " + blobcode.version());``
$Object blob(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX} decoding,
$Object blob(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX,
URL} decoding,
STRING_LIST encoded)
Prototype
......@@ -223,7 +224,7 @@ Example
``= blobcode.encode(IDENTITY, theblob.get());``
$Method STRING .encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEXUC,
HEXLC} encoding)
HEXLC, URLUC, URLLC} encoding)
Description
Returns an encoding of BLOB created by the constructor,
......
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