From 256c07ff2870cd56e37ff576bd2080e059b312e6 Mon Sep 17 00:00:00 2001 From: James Yonan Date: Sat, 27 Jun 2015 16:36:20 -0600 Subject: [PATCH] Added new source file openvpn/http/urlencode.hpp to deal with URL validation, encoding, and decoding. --- openvpn/http/urlencode.hpp | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 openvpn/http/urlencode.hpp diff --git a/openvpn/http/urlencode.hpp b/openvpn/http/urlencode.hpp new file mode 100644 index 00000000..63cdb51c --- /dev/null +++ b/openvpn/http/urlencode.hpp @@ -0,0 +1,98 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2015 OpenVPN Technologies, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_HTTP_URLENCODE_H +#define OPENVPN_HTTP_URLENCODE_H + +#include +#include + +#include +#include +#include +#include + +namespace openvpn { + namespace URL { + OPENVPN_EXCEPTION(url_error); + + inline std::string decode(const std::string& encoded) + { + enum State { + TEXT, + PERCENT, + DIGIT + }; + + int value = 0; + State state = TEXT; + std::string ret; + + for (auto &c : encoded) + { + switch (state) + { + case TEXT: + { + if (c == '%') + state = PERCENT; + else + ret += c; + break; + } + case PERCENT: + { + const int v = parse_hex_char(c); + if (v < 0) + throw url_error(std::string("decode error after %: ") + encoded); + value = v; + state = DIGIT; + break; + } + case DIGIT: + { + const int v = parse_hex_char(c); + if (v < 0) + throw url_error(std::string("decode error after %: ") + encoded); + ret += static_cast((value * 16) + v); + state = TEXT; + } + } + } + if (state != TEXT) + throw url_error(std::string("decode error: %-encoding item not closed out: ") + encoded); + if (!Unicode::is_valid_utf8(ret)) + throw url_error(std::string("not UTF-8: ") + encoded); + return ret; + } + + inline std::vector decode_path(const std::string& path) + { + std::vector list; + Split::by_char_void(list, path, '/'); + for (auto &i : list) + i = decode(i); + return list; + } + } +} + +#endif