0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00

Added new source file openvpn/http/urlencode.hpp to deal with

URL validation, encoding, and decoding.
This commit is contained in:
James Yonan 2015-06-27 16:36:20 -06:00
parent 0ec1bf62ba
commit 256c07ff28

View File

@ -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 <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_HTTP_URLENCODE_H
#define OPENVPN_HTTP_URLENCODE_H
#include <string>
#include <vector>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/split.hpp>
#include <openvpn/common/hexstr.hpp>
#include <openvpn/common/unicode.hpp>
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<unsigned char>((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<std::string> decode_path(const std::string& path)
{
std::vector<std::string> list;
Split::by_char_void<decltype(list), NullLex, Split::NullLimit>(list, path, '/');
for (auto &i : list)
i = decode(i);
return list;
}
}
}
#endif