blob: 7665afc1989ae5502f8dee832137ecc0babd1cfa [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"
Davide Pesaventodd461432017-01-28 21:47:26 -050023#include "../encoding/buffer.hpp"
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070024#include "../encoding/buffer-stream.hpp"
Davide Pesavento03115ce2017-01-27 01:17:55 -050025#include "../security/transform/buffer-source.hpp"
26#include "../security/transform/hex-decode.hpp"
Davide Pesaventofdda2412017-01-28 18:53:51 -050027#include "../security/transform/hex-encode.hpp"
Davide Pesavento03115ce2017-01-27 01:17:55 -050028#include "../security/transform/stream-sink.hpp"
29
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070030#include <sstream>
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070031
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070032namespace ndn {
33
Davide Pesaventoe78eeca2017-02-23 23:22:32 -050034std::ostream&
35operator<<(std::ostream& os, const AsHex& hex)
36{
37 printHex(os, hex.m_value, os.flags() & std::ostream::uppercase);
38 return os;
39}
40
41void
42printHex(std::ostream& os, uint64_t num, bool wantUpperCase)
43{
44 auto osFlags = os.flags();
45 // std::showbase doesn't work with number 0
46 os << "0x" << std::noshowbase << std::noshowpos
47 << (wantUpperCase ? std::uppercase : std::nouppercase)
48 << std::hex << num;
49 os.flags(osFlags);
50}
51
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070052void
Davide Pesaventofdda2412017-01-28 18:53:51 -050053printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070054{
Davide Pesavento218e5be2017-02-03 00:13:47 -050055 namespace tr = security::transform;
56 BOOST_ASSERT(buffer != nullptr || length == 0);
57 tr::bufferSource(buffer, length) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(os);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070058}
59
60void
Davide Pesaventofdda2412017-01-28 18:53:51 -050061printHex(std::ostream& os, const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070062{
Davide Pesaventofdda2412017-01-28 18:53:51 -050063 return printHex(os, buffer.buf(), buffer.size(), wantUpperCase);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070064}
65
66std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050067toHex(const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070068{
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070069 std::ostringstream result;
Davide Pesavento218e5be2017-02-03 00:13:47 -050070 printHex(result, buffer, length, wantUpperCase);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070071 return result.str();
72}
73
74std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050075toHex(const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070076{
Davide Pesavento218e5be2017-02-03 00:13:47 -050077 return toHex(buffer.buf(), buffer.size(), wantUpperCase);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070078}
79
80int
Davide Pesavento03115ce2017-01-27 01:17:55 -050081fromHexChar(char c)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070082{
83 if (c >= '0' && c <= '9')
84 return c - '0';
85 else if (c >= 'A' && c <= 'F')
86 return c - 'A' + 0xA;
87 else if (c >= 'a' && c <= 'f')
88 return c - 'a' + 0xA;
89 else
90 return -1;
91}
92
Davide Pesavento03115ce2017-01-27 01:17:55 -050093shared_ptr<Buffer>
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070094fromHex(const std::string& hexString)
95{
Davide Pesavento03115ce2017-01-27 01:17:55 -050096 namespace tr = security::transform;
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070097
98 OBufferStream os;
Davide Pesavento03115ce2017-01-27 01:17:55 -050099 try {
100 tr::bufferSource(hexString) >> tr::hexDecode() >> tr::streamSink(os);
101 }
102 catch (const tr::Error& e) {
103 BOOST_THROW_EXCEPTION(StringHelperError(std::string("Conversion from hex failed: ") + e.what()));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700104 }
105
Davide Pesavento03115ce2017-01-27 01:17:55 -0500106 return os.buf();
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700107}
108
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700109std::string
110unescape(const std::string& str)
111{
112 std::ostringstream result;
113
114 for (size_t i = 0; i < str.size(); ++i) {
115 if (str[i] == '%' && i + 2 < str.size()) {
116 int hi = fromHexChar(str[i + 1]);
117 int lo = fromHexChar(str[i + 2]);
118
119 if (hi < 0 || lo < 0)
120 // Invalid hex characters, so just keep the escaped string.
121 result << str[i] << str[i + 1] << str[i + 2];
122 else
123 result << static_cast<char>((hi << 4) | lo);
124
125 // Skip ahead past the escaped value.
126 i += 2;
127 }
Davide Pesavento218e5be2017-02-03 00:13:47 -0500128 else {
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700129 // Just copy through.
130 result << str[i];
Davide Pesavento218e5be2017-02-03 00:13:47 -0500131 }
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700132 }
133
134 return result.str();
135}
136
137} // namespace ndn