blob: 44083b3109b7c57a903bcd646a9dc4d87355b18a [file] [log] [blame]
Alexander Afanasyev8828ca62015-07-02 13:40:09 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Davide Pesavento03115ce2017-01-27 01:17:55 -05003 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyev8828ca62015-07-02 13:40:09 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "string-helper.hpp"
23#include "../encoding/buffer-stream.hpp"
Davide Pesavento03115ce2017-01-27 01:17:55 -050024#include "../security/transform/buffer-source.hpp"
25#include "../security/transform/hex-decode.hpp"
Davide Pesaventofdda2412017-01-28 18:53:51 -050026#include "../security/transform/hex-encode.hpp"
Davide Pesavento03115ce2017-01-27 01:17:55 -050027#include "../security/transform/stream-sink.hpp"
28
29#include <boost/algorithm/string/trim.hpp>
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070030
31#include <sstream>
32#include <iomanip>
33
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070034namespace ndn {
35
36void
Davide Pesaventofdda2412017-01-28 18:53:51 -050037printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070038{
39 if (buffer == nullptr || length == 0)
40 return;
41
42 auto newFlags = std::ios::hex;
Davide Pesaventofdda2412017-01-28 18:53:51 -050043 if (wantUpperCase) {
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070044 newFlags |= std::ios::uppercase;
45 }
46 auto oldFlags = os.flags(newFlags);
47 auto oldFill = os.fill('0');
48 for (size_t i = 0; i < length; ++i) {
49 os << std::setw(2) << static_cast<unsigned int>(buffer[i]);
50 }
51 os.fill(oldFill);
52 os.flags(oldFlags);
53}
54
55void
Davide Pesaventofdda2412017-01-28 18:53:51 -050056printHex(std::ostream& os, const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070057{
Davide Pesaventofdda2412017-01-28 18:53:51 -050058 return printHex(os, buffer.buf(), buffer.size(), wantUpperCase);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070059}
60
61std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050062toHex(const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070063{
Davide Pesaventofdda2412017-01-28 18:53:51 -050064 BOOST_ASSERT(buffer != nullptr || length == 0);
65
66 namespace tr = security::transform;
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070067
68 std::ostringstream result;
Davide Pesaventofdda2412017-01-28 18:53:51 -050069 tr::bufferSource(buffer, length) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(result);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070070 return result.str();
71}
72
73std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050074toHex(const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070075{
Davide Pesaventofdda2412017-01-28 18:53:51 -050076 namespace tr = security::transform;
77
78 std::ostringstream result;
79 tr::bufferSource(buffer) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(result);
80 return result.str();
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070081}
82
83int
Davide Pesavento03115ce2017-01-27 01:17:55 -050084fromHexChar(char c)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070085{
86 if (c >= '0' && c <= '9')
87 return c - '0';
88 else if (c >= 'A' && c <= 'F')
89 return c - 'A' + 0xA;
90 else if (c >= 'a' && c <= 'f')
91 return c - 'a' + 0xA;
92 else
93 return -1;
94}
95
Davide Pesavento03115ce2017-01-27 01:17:55 -050096shared_ptr<Buffer>
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070097fromHex(const std::string& hexString)
98{
Davide Pesavento03115ce2017-01-27 01:17:55 -050099 namespace tr = security::transform;
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700100
101 OBufferStream os;
Davide Pesavento03115ce2017-01-27 01:17:55 -0500102 try {
103 tr::bufferSource(hexString) >> tr::hexDecode() >> tr::streamSink(os);
104 }
105 catch (const tr::Error& e) {
106 BOOST_THROW_EXCEPTION(StringHelperError(std::string("Conversion from hex failed: ") + e.what()));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700107 }
108
Davide Pesavento03115ce2017-01-27 01:17:55 -0500109 return os.buf();
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700110}
111
112void
113trimLeft(std::string& str)
114{
115 boost::algorithm::trim_left(str);
116}
117
118void
119trimRight(std::string& str)
120{
121 boost::algorithm::trim_right(str);
122}
123
124void
125trim(std::string& str)
126{
127 boost::algorithm::trim(str);
128}
129
130std::string
131unescape(const std::string& str)
132{
133 std::ostringstream result;
134
135 for (size_t i = 0; i < str.size(); ++i) {
136 if (str[i] == '%' && i + 2 < str.size()) {
137 int hi = fromHexChar(str[i + 1]);
138 int lo = fromHexChar(str[i + 2]);
139
140 if (hi < 0 || lo < 0)
141 // Invalid hex characters, so just keep the escaped string.
142 result << str[i] << str[i + 1] << str[i + 2];
143 else
144 result << static_cast<char>((hi << 4) | lo);
145
146 // Skip ahead past the escaped value.
147 i += 2;
148 }
149 else
150 // Just copy through.
151 result << str[i];
152 }
153
154 return result.str();
155}
156
157} // namespace ndn