blob: 4a4808f36399867103f744e5f66b2b94f40132fc [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>
31#include <iomanip>
32
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070033namespace ndn {
34
35void
Davide Pesaventofdda2412017-01-28 18:53:51 -050036printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070037{
38 if (buffer == nullptr || length == 0)
39 return;
40
41 auto newFlags = std::ios::hex;
Davide Pesaventofdda2412017-01-28 18:53:51 -050042 if (wantUpperCase) {
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070043 newFlags |= std::ios::uppercase;
44 }
45 auto oldFlags = os.flags(newFlags);
46 auto oldFill = os.fill('0');
47 for (size_t i = 0; i < length; ++i) {
48 os << std::setw(2) << static_cast<unsigned int>(buffer[i]);
49 }
50 os.fill(oldFill);
51 os.flags(oldFlags);
52}
53
54void
Davide Pesaventofdda2412017-01-28 18:53:51 -050055printHex(std::ostream& os, const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070056{
Davide Pesaventofdda2412017-01-28 18:53:51 -050057 return printHex(os, buffer.buf(), buffer.size(), wantUpperCase);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070058}
59
60std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050061toHex(const uint8_t* buffer, size_t length, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070062{
Davide Pesaventofdda2412017-01-28 18:53:51 -050063 BOOST_ASSERT(buffer != nullptr || length == 0);
64
65 namespace tr = security::transform;
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070066
67 std::ostringstream result;
Davide Pesaventofdda2412017-01-28 18:53:51 -050068 tr::bufferSource(buffer, length) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(result);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070069 return result.str();
70}
71
72std::string
Davide Pesaventofdda2412017-01-28 18:53:51 -050073toHex(const Buffer& buffer, bool wantUpperCase)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070074{
Davide Pesaventofdda2412017-01-28 18:53:51 -050075 namespace tr = security::transform;
76
77 std::ostringstream result;
78 tr::bufferSource(buffer) >> tr::hexEncode(wantUpperCase) >> tr::streamSink(result);
79 return result.str();
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070080}
81
82int
Davide Pesavento03115ce2017-01-27 01:17:55 -050083fromHexChar(char c)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070084{
85 if (c >= '0' && c <= '9')
86 return c - '0';
87 else if (c >= 'A' && c <= 'F')
88 return c - 'A' + 0xA;
89 else if (c >= 'a' && c <= 'f')
90 return c - 'a' + 0xA;
91 else
92 return -1;
93}
94
Davide Pesavento03115ce2017-01-27 01:17:55 -050095shared_ptr<Buffer>
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070096fromHex(const std::string& hexString)
97{
Davide Pesavento03115ce2017-01-27 01:17:55 -050098 namespace tr = security::transform;
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070099
100 OBufferStream os;
Davide Pesavento03115ce2017-01-27 01:17:55 -0500101 try {
102 tr::bufferSource(hexString) >> tr::hexDecode() >> tr::streamSink(os);
103 }
104 catch (const tr::Error& e) {
105 BOOST_THROW_EXCEPTION(StringHelperError(std::string("Conversion from hex failed: ") + e.what()));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700106 }
107
Davide Pesavento03115ce2017-01-27 01:17:55 -0500108 return os.buf();
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700109}
110
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700111std::string
112unescape(const std::string& str)
113{
114 std::ostringstream result;
115
116 for (size_t i = 0; i < str.size(); ++i) {
117 if (str[i] == '%' && i + 2 < str.size()) {
118 int hi = fromHexChar(str[i + 1]);
119 int lo = fromHexChar(str[i + 2]);
120
121 if (hi < 0 || lo < 0)
122 // Invalid hex characters, so just keep the escaped string.
123 result << str[i] << str[i + 1] << str[i + 2];
124 else
125 result << static_cast<char>((hi << 4) | lo);
126
127 // Skip ahead past the escaped value.
128 i += 2;
129 }
130 else
131 // Just copy through.
132 result << str[i];
133 }
134
135 return result.str();
136}
137
138} // namespace ndn