Gav Wood
10 years ago
11 changed files with 511 additions and 35 deletions
@ -0,0 +1,16 @@ |
|||
cmake_policy(SET CMP0015 NEW) |
|||
set(CMAKE_AUTOMOC OFF) |
|||
|
|||
aux_source_directory(. SRC_LIST) |
|||
|
|||
include_directories(BEFORE ..) |
|||
include_directories(${LEVELDB_INCLUDE_DIRS}) |
|||
|
|||
set(EXECUTABLE rlp) |
|||
|
|||
add_executable(${EXECUTABLE} ${SRC_LIST}) |
|||
|
|||
target_link_libraries(${EXECUTABLE} devcrypto) |
|||
|
|||
install( TARGETS ${EXECUTABLE} DESTINATION bin) |
|||
|
@ -0,0 +1,128 @@ |
|||
/*
|
|||
base64.cpp and base64.h |
|||
|
|||
Copyright (C) 2004-2008 René Nyffenegger |
|||
|
|||
This source code is provided 'as-is', without any express or implied |
|||
warranty. In no event will the author be held liable for any damages |
|||
arising from the use of this software. |
|||
|
|||
Permission is granted to anyone to use this software for any purpose, |
|||
including commercial applications, and to alter it and redistribute it |
|||
freely, subject to the following restrictions: |
|||
|
|||
1. The origin of this source code must not be misrepresented; you must not |
|||
claim that you wrote the original source code. If you use this source code |
|||
in a product, an acknowledgment in the product documentation would be |
|||
appreciated but is not required. |
|||
|
|||
2. Altered source versions must be plainly marked as such, and must not be |
|||
misrepresented as being the original source code. |
|||
|
|||
3. This notice may not be removed or altered from any source distribution. |
|||
|
|||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch |
|||
*/ |
|||
/// code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c
|
|||
/// originally by René Nyffenegger, modified by some other guy and then again by Gav Wood.
|
|||
|
|||
#include "base64.h" |
|||
|
|||
#include <iostream> |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
|
|||
static const std::string base64_chars = |
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
|||
"abcdefghijklmnopqrstuvwxyz" |
|||
"0123456789+/"; |
|||
|
|||
static inline bool is_base64(byte c) { |
|||
return (isalnum(c) || (c == '+') || (c == '/')); |
|||
} |
|||
|
|||
std::string dev::base64_encode(bytesConstRef _in) { |
|||
std::string ret; |
|||
int i = 0; |
|||
int j = 0; |
|||
byte char_array_3[3]; |
|||
byte char_array_4[4]; |
|||
|
|||
auto buf = _in.data(); |
|||
auto bufLen = _in.size(); |
|||
|
|||
while (bufLen--) { |
|||
char_array_3[i++] = *(buf++); |
|||
if (i == 3) { |
|||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; |
|||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); |
|||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); |
|||
char_array_4[3] = char_array_3[2] & 0x3f; |
|||
|
|||
for(i = 0; (i <4) ; i++) |
|||
ret += base64_chars[char_array_4[i]]; |
|||
i = 0; |
|||
} |
|||
} |
|||
|
|||
if (i) |
|||
{ |
|||
for(j = i; j < 3; j++) |
|||
char_array_3[j] = '\0'; |
|||
|
|||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; |
|||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); |
|||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); |
|||
char_array_4[3] = char_array_3[2] & 0x3f; |
|||
|
|||
for (j = 0; (j < i + 1); j++) |
|||
ret += base64_chars[char_array_4[j]]; |
|||
|
|||
while((i++ < 3)) |
|||
ret += '='; |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
bytes dev::base64_decode(std::string const& encoded_string) { |
|||
int in_len = encoded_string.size(); |
|||
int i = 0; |
|||
int j = 0; |
|||
int in_ = 0; |
|||
byte char_array_4[4], char_array_3[3]; |
|||
bytes ret; |
|||
|
|||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { |
|||
char_array_4[i++] = encoded_string[in_]; in_++; |
|||
if (i ==4) { |
|||
for (i = 0; i <4; i++) |
|||
char_array_4[i] = base64_chars.find(char_array_4[i]); |
|||
|
|||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); |
|||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); |
|||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; |
|||
|
|||
for (i = 0; (i < 3); i++) |
|||
ret.push_back(char_array_3[i]); |
|||
i = 0; |
|||
} |
|||
} |
|||
|
|||
if (i) { |
|||
for (j = i; j <4; j++) |
|||
char_array_4[j] = 0; |
|||
|
|||
for (j = 0; j <4; j++) |
|||
char_array_4[j] = base64_chars.find(char_array_4[j]); |
|||
|
|||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); |
|||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); |
|||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; |
|||
|
|||
for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]); |
|||
} |
|||
|
|||
return ret; |
|||
} |
@ -0,0 +1,40 @@ |
|||
/*
|
|||
base64.cpp and base64.h |
|||
|
|||
Copyright (C) 2004-2008 René Nyffenegger |
|||
|
|||
This source code is provided 'as-is', without any express or implied |
|||
warranty. In no event will the author be held liable for any damages |
|||
arising from the use of this software. |
|||
|
|||
Permission is granted to anyone to use this software for any purpose, |
|||
including commercial applications, and to alter it and redistribute it |
|||
freely, subject to the following restrictions: |
|||
|
|||
1. The origin of this source code must not be misrepresented; you must not |
|||
claim that you wrote the original source code. If you use this source code |
|||
in a product, an acknowledgment in the product documentation would be |
|||
appreciated but is not required. |
|||
|
|||
2. Altered source versions must be plainly marked as such, and must not be |
|||
misrepresented as being the original source code. |
|||
|
|||
3. This notice may not be removed or altered from any source distribution. |
|||
|
|||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch |
|||
*/ |
|||
/// code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c
|
|||
/// originally by René Nyffenegger, modified by some other guy and then again by Gav Wood.
|
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
#include <string> |
|||
#include <libdevcore/Common.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
std::string base64_encode(bytesConstRef _in); |
|||
bytes base64_decode(std::string const& _in); |
|||
|
|||
} |
@ -0,0 +1,279 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum 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 General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file main.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* RLP tool. |
|||
*/ |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <boost/algorithm/string.hpp> |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/CommonIO.h> |
|||
#include <libdevcore/RLP.h> |
|||
#include <libdevcrypto/SHA3.h> |
|||
#include "base64.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
|
|||
void help() |
|||
{ |
|||
cout |
|||
<< "Usage rlp [OPTIONS] [ <file> | -- ]" << endl |
|||
<< "Options:" << endl |
|||
<< " -V,--version Show the version and exit." << endl |
|||
; |
|||
exit(0); |
|||
} |
|||
|
|||
void version() |
|||
{ |
|||
cout << "rlp version " << dev::Version << endl; |
|||
exit(0); |
|||
} |
|||
|
|||
enum class Mode { |
|||
ListArchive, |
|||
ExtractArchive, |
|||
Render, |
|||
}; |
|||
|
|||
enum class Encoding { |
|||
Auto, |
|||
Hex, |
|||
Base64, |
|||
Binary, |
|||
}; |
|||
|
|||
bool isAscii(string const& _s) |
|||
{ |
|||
for (char c: _s) |
|||
if (c < 32) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
class RLPStreamer |
|||
{ |
|||
public: |
|||
struct Prefs |
|||
{ |
|||
string indent = " "; |
|||
bool hexInts = false; |
|||
bool forceString = false; |
|||
bool escapeAll = false; |
|||
bool forceHex = false; |
|||
}; |
|||
|
|||
RLPStreamer(ostream& _out, Prefs _p): m_out(_out), m_prefs(_p) {} |
|||
|
|||
void output(RLP const& _d, unsigned _level = 0) |
|||
{ |
|||
if (_d.isNull()) |
|||
m_out << "null"; |
|||
else if (_d.isInt()) |
|||
if (m_prefs.hexInts) |
|||
m_out << toHex(toCompactBigEndian(_d.toInt<bigint>(RLP::LaisezFaire))); |
|||
else |
|||
m_out << _d.toInt<bigint>(RLP::LaisezFaire); |
|||
else if (_d.isData()) |
|||
if (m_prefs.forceString || (!m_prefs.forceHex && isAscii(_d.toString()))) |
|||
m_out << escaped(_d.toString(), m_prefs.escapeAll); |
|||
else |
|||
m_out << toHex(_d.data()); |
|||
else if (_d.isList()) |
|||
{ |
|||
m_out << "["; |
|||
string newline = "\n"; |
|||
for (unsigned i = 0; i < _level + 1; ++i) |
|||
newline += m_prefs.indent; |
|||
int j = 0; |
|||
for (auto i: _d) |
|||
{ |
|||
m_out << (j++ ? |
|||
(m_prefs.indent.empty() ? ", " : ("," + newline)) : |
|||
(m_prefs.indent.empty() ? " " : newline)); |
|||
output(i, _level + 1); |
|||
} |
|||
newline = newline.substr(0, newline.size() - m_prefs.indent.size()); |
|||
m_out << (m_prefs.indent.empty() ? (j ? " ]" : "]") : (j ? newline + "]" : "]")); |
|||
} |
|||
} |
|||
|
|||
private: |
|||
std::ostream& m_out; |
|||
Prefs m_prefs; |
|||
}; |
|||
|
|||
int main(int argc, char** argv) |
|||
{ |
|||
Encoding encoding = Encoding::Auto; |
|||
Mode mode = Mode::Render; |
|||
string inputFile = "--"; |
|||
bool lenience = false; |
|||
RLPStreamer::Prefs prefs; |
|||
|
|||
for (int i = 1; i < argc; ++i) |
|||
{ |
|||
string arg = argv[i]; |
|||
if (arg == "-h" || arg == "--help") |
|||
help(); |
|||
else if (arg == "-r" || arg == "--render") |
|||
mode = Mode::Render; |
|||
else if ((arg == "-i" || arg == "--indent") && argc > i) |
|||
prefs.indent = argv[++i]; |
|||
else if (arg == "--hex-ints") |
|||
prefs.hexInts = true; |
|||
else if (arg == "--force-string") |
|||
prefs.forceString = true; |
|||
else if (arg == "--force-hex") |
|||
prefs.forceHex = true; |
|||
else if (arg == "--force-escape") |
|||
prefs.escapeAll = true; |
|||
else if (arg == "-l" || arg == "--list-archive") |
|||
mode = Mode::ListArchive; |
|||
else if (arg == "-e" || arg == "--extract-archive") |
|||
mode = Mode::ExtractArchive; |
|||
else if (arg == "-L" || arg == "--lenience") |
|||
lenience = true; |
|||
else if (arg == "-V" || arg == "--version") |
|||
version(); |
|||
else if (arg == "-x" || arg == "--hex" || arg == "--base-16") |
|||
encoding = Encoding::Hex; |
|||
else if (arg == "--64" || arg == "--base-64") |
|||
encoding = Encoding::Base64; |
|||
else if (arg == "-b" || arg == "--bin" || arg == "--base-256") |
|||
encoding = Encoding::Binary; |
|||
else |
|||
inputFile = arg; |
|||
} |
|||
|
|||
bytes in; |
|||
if (inputFile == "--") |
|||
for (int i = cin.get(); i != -1; i = cin.get()) |
|||
in.push_back((byte)i); |
|||
else |
|||
in = contents(inputFile); |
|||
if (encoding == Encoding::Auto) |
|||
{ |
|||
encoding = Encoding::Hex; |
|||
for (char b: in) |
|||
if (b != '\n' && b != ' ' && b != '\t') |
|||
{ |
|||
if (encoding == Encoding::Hex && (b < '0' || b > '9' ) && (b < 'a' || b > 'f' ) && (b < 'A' || b > 'F' )) |
|||
{ |
|||
cerr << "'" << b << "':" << (int)b << endl; |
|||
encoding = Encoding::Base64; |
|||
} |
|||
if (encoding == Encoding::Base64 && (b < '0' || b > '9' ) && (b < 'a' || b > 'z' ) && (b < 'A' || b > 'Z' ) && b != '+' && b != '/') |
|||
{ |
|||
encoding = Encoding::Binary; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
bytes b; |
|||
switch (encoding) |
|||
{ |
|||
case Encoding::Hex: |
|||
{ |
|||
string s = asString(in); |
|||
boost::algorithm::replace_all(s, " ", ""); |
|||
boost::algorithm::replace_all(s, "\n", ""); |
|||
boost::algorithm::replace_all(s, "\t", ""); |
|||
b = fromHex(s); |
|||
break; |
|||
} |
|||
case Encoding::Base64: |
|||
{ |
|||
string s = asString(in); |
|||
boost::algorithm::replace_all(s, " ", ""); |
|||
boost::algorithm::replace_all(s, "\n", ""); |
|||
boost::algorithm::replace_all(s, "\t", ""); |
|||
b = base64_decode(s); |
|||
break; |
|||
} |
|||
default: |
|||
swap(b, in); |
|||
break; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
RLP rlp(b); |
|||
switch (mode) |
|||
{ |
|||
case Mode::ListArchive: |
|||
{ |
|||
if (!rlp.isList()) |
|||
{ |
|||
cout << "Error: Invalid format; RLP data is not a list." << endl; |
|||
exit(1); |
|||
} |
|||
cout << rlp.itemCount() << " items:" << endl; |
|||
for (auto i: rlp) |
|||
{ |
|||
if (!i.isData()) |
|||
{ |
|||
cout << "Error: Invalid format; RLP list item is not data." << endl; |
|||
if (!lenience) |
|||
exit(1); |
|||
} |
|||
cout << " " << i.size() << " bytes: " << sha3(i.data()) << endl; |
|||
} |
|||
break; |
|||
} |
|||
case Mode::ExtractArchive: |
|||
{ |
|||
if (!rlp.isList()) |
|||
{ |
|||
cout << "Error: Invalid format; RLP data is not a list." << endl; |
|||
exit(1); |
|||
} |
|||
cout << rlp.itemCount() << " items:" << endl; |
|||
for (auto i: rlp) |
|||
{ |
|||
if (!i.isData()) |
|||
{ |
|||
cout << "Error: Invalid format; RLP list item is not data." << endl; |
|||
if (!lenience) |
|||
exit(1); |
|||
} |
|||
ofstream fout; |
|||
fout.open(toString(sha3(i.data()))); |
|||
fout.write(reinterpret_cast<char const*>(i.data().data()), i.data().size()); |
|||
} |
|||
break; |
|||
} |
|||
case Mode::Render: |
|||
{ |
|||
RLPStreamer s(cout, prefs); |
|||
s.output(rlp); |
|||
cout << endl; |
|||
break; |
|||
} |
|||
default:; |
|||
} |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Error: Invalid format; bad RLP." << endl; |
|||
exit(1); |
|||
} |
|||
|
|||
return 0; |
|||
} |
Loading…
Reference in new issue