2018-09-06 13:47:33 +00:00
|
|
|
/**
|
|
|
|
* Copyright (C) 2017-2018, U.S. Government
|
|
|
|
*/
|
|
|
|
#include <Utils.h>
|
|
|
|
#include <HirsRuntimeException.h>
|
2018-11-26 21:45:22 +00:00
|
|
|
|
|
|
|
#include <re2/re2.h>
|
2018-09-06 13:47:33 +00:00
|
|
|
|
2020-11-27 18:09:04 +00:00
|
|
|
#include <dirent.h>
|
2018-09-06 13:47:33 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cctype>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using std::hex;
|
|
|
|
using std::ifstream;
|
|
|
|
using std::ios;
|
|
|
|
using std::ofstream;
|
2018-10-02 20:21:35 +00:00
|
|
|
using std::remove;
|
2018-09-06 13:47:33 +00:00
|
|
|
using std::setfill;
|
|
|
|
using std::setw;
|
|
|
|
using std::string;
|
|
|
|
using std::stringstream;
|
|
|
|
using std::vector;
|
|
|
|
|
|
|
|
using hirs::exception::HirsRuntimeException;
|
|
|
|
|
|
|
|
namespace hirs {
|
|
|
|
|
2018-10-12 02:03:25 +00:00
|
|
|
namespace json_utils {
|
|
|
|
|
|
|
|
string JSONFieldParser::parseJsonStringField(const std::string &jsonObject,
|
|
|
|
const std::string &jsonFieldName) {
|
|
|
|
stringstream regexPatternStream;
|
|
|
|
regexPatternStream << "(?i)\\\""
|
|
|
|
<< jsonFieldName
|
|
|
|
<< "\\\"\\s*:\\s*\\\"(.*)\\\"";
|
|
|
|
|
|
|
|
string value;
|
|
|
|
if (RE2::PartialMatch(jsonObject, regexPatternStream.str(), &value)) {
|
|
|
|
return value;
|
|
|
|
} else {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace json_utils
|
|
|
|
|
2018-09-06 13:47:33 +00:00
|
|
|
namespace file_utils {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether or not the argument directory exists.
|
|
|
|
* @return True if the directory exists. False, otherwise.
|
|
|
|
*/
|
|
|
|
bool dirExists(const string& path) {
|
|
|
|
struct stat pathinfo;
|
|
|
|
|
|
|
|
if (stat(path.c_str(), &pathinfo) != 0) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return (pathinfo.st_mode & S_IFDIR) != 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether or not the argument file name exists and is a
|
|
|
|
* regular file.
|
|
|
|
* @param filename file to check for existence
|
|
|
|
* @return True if the file exists. False, otherwise.
|
|
|
|
*/
|
|
|
|
bool fileExists(const string& filename) {
|
|
|
|
struct stat buffer;
|
|
|
|
|
|
|
|
if (stat(filename.c_str(), &buffer) != 0) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return S_ISREG(buffer.st_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
string fileToString(const string& filename) {
|
|
|
|
stringstream ss;
|
|
|
|
ifstream t(filename);
|
|
|
|
if (!t.good()) {
|
|
|
|
ss << "Unable to open file: " << filename;
|
|
|
|
throw HirsRuntimeException(ss.str(),
|
|
|
|
"Utils.cpp::file_utils::fileToString");
|
|
|
|
}
|
|
|
|
ss << t.rdbuf();
|
|
|
|
t.close();
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the contents of an entire file into a string. If
|
|
|
|
* the file can't be opened, the default value is returned.
|
|
|
|
* @param filename the name and path of the file to read.
|
|
|
|
* @param defaultVal the value to return if the file can't be
|
|
|
|
* opened.
|
|
|
|
* @return the contents of the specified file as a string.
|
|
|
|
*/
|
|
|
|
string fileToString(const string& filename, const string& defaultVal) {
|
|
|
|
stringstream ss;
|
|
|
|
ifstream t(filename);
|
|
|
|
if (!t.good()) {
|
|
|
|
return defaultVal;
|
|
|
|
}
|
|
|
|
ss << t.rdbuf();
|
|
|
|
t.close();
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string getFileAsOneLineOrEmptyString(const string& filename) {
|
|
|
|
return string_utils::trimNewLines(fileToString(filename, ""));
|
|
|
|
}
|
|
|
|
|
2020-11-30 13:38:46 +00:00
|
|
|
vector<string> search_directory(const string& directory) {
|
2020-11-27 18:09:04 +00:00
|
|
|
DIR *dr;
|
2020-11-30 13:38:46 +00:00
|
|
|
std::vector<string> files;
|
2020-11-27 18:09:04 +00:00
|
|
|
dr = opendir(directory.c_str());
|
|
|
|
|
|
|
|
if (dr) {
|
|
|
|
struct dirent *en;
|
|
|
|
while ((en = readdir(dr)) != NULL) {
|
|
|
|
stringstream ss;
|
|
|
|
ss << directory.c_str();
|
|
|
|
ss << en->d_name;
|
|
|
|
try {
|
2020-11-30 13:38:46 +00:00
|
|
|
files.push_back(fileToString(ss.str()));
|
2020-11-27 18:09:04 +00:00
|
|
|
} catch (HirsRuntimeException& hirsRuntimeException) {
|
|
|
|
std::cout << hirsRuntimeException.what();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// close directory
|
|
|
|
closedir(dr);
|
|
|
|
}
|
|
|
|
|
2020-11-30 13:38:46 +00:00
|
|
|
return files;
|
2020-11-27 18:09:04 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 13:47:33 +00:00
|
|
|
/**
|
|
|
|
* Takes a byte string and writes the contents to a file of the given name.
|
|
|
|
* @param bytes string bytes to write
|
|
|
|
* @param filename file name to be written to
|
|
|
|
*/
|
|
|
|
void writeBinaryFile(const string& bytes, const string& filename) {
|
|
|
|
ofstream file(filename, ios::out | ios::binary);
|
|
|
|
if (file.is_open()) {
|
|
|
|
file.write(bytes.c_str(), bytes.size());
|
|
|
|
file.close();
|
|
|
|
} else {
|
|
|
|
throw std::invalid_argument("Cannot write to specified file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int getFileSize(const string& filename) {
|
|
|
|
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
|
|
|
|
return in.tellg();
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy portion of file to temp file
|
|
|
|
void splitFile(const string& inFilename, const string& outFilename,
|
|
|
|
int startPos, int readSize) {
|
|
|
|
ifstream inStr(inFilename, ifstream::binary);
|
|
|
|
ofstream outStr(outFilename, ofstream::binary);
|
|
|
|
|
|
|
|
inStr.seekg(startPos);
|
|
|
|
char* fileBlock = new char[readSize];
|
|
|
|
|
|
|
|
inStr.read(fileBlock, readSize);
|
|
|
|
outStr.write(fileBlock, readSize);
|
|
|
|
|
|
|
|
inStr.close();
|
|
|
|
outStr.close();
|
|
|
|
|
|
|
|
delete[] fileBlock;
|
|
|
|
}
|
2018-11-26 21:45:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the filename from the end of a filesystem path
|
|
|
|
* @param path the filesystem path
|
|
|
|
* @return the filename from the path
|
|
|
|
*/
|
|
|
|
string trimFilenameFromPath(const string& path) {
|
|
|
|
auto lastPathSeparatorIndex = path.find_last_of('/');
|
|
|
|
// Return path if it wasn't actually a path
|
|
|
|
if (lastPathSeparatorIndex == string::npos) {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return path.substr(lastPathSeparatorIndex + 1);
|
|
|
|
}
|
2018-09-06 13:47:33 +00:00
|
|
|
} // namespace file_utils
|
|
|
|
|
|
|
|
namespace string_utils {
|
|
|
|
|
|
|
|
string binaryToHex(const string& bin) {
|
|
|
|
stringstream output;
|
|
|
|
for (int i = 0; i < 20; i++) {
|
|
|
|
stringstream str;
|
|
|
|
str << hex << setfill('0') << setw(2) << static_cast<int>(bin[i]);
|
|
|
|
string dig = str.str();
|
|
|
|
if (dig.length() > 2) {
|
|
|
|
dig = dig.substr(dig.length() - 2, 2);
|
|
|
|
}
|
|
|
|
output << dig;
|
|
|
|
}
|
|
|
|
return output.str();
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:35 +00:00
|
|
|
bool contains(const string& str, const string& substring) {
|
|
|
|
return str.find(substring) != string::npos;
|
|
|
|
}
|
|
|
|
|
2018-09-06 13:47:33 +00:00
|
|
|
string longToHex(const uint32_t& value) {
|
|
|
|
stringstream output;
|
|
|
|
output << "0x" << hex << value;
|
|
|
|
return output.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isHexString(const string& str) {
|
|
|
|
bool isHexStringFlag = !str.empty();
|
|
|
|
if (isHexStringFlag) {
|
|
|
|
auto startIndex = str.begin();
|
|
|
|
if (str.substr(0, 2) == "0x") {
|
|
|
|
startIndex += 2;
|
|
|
|
}
|
|
|
|
isHexStringFlag = std::all_of(startIndex, str.end(), isxdigit);
|
|
|
|
}
|
|
|
|
return isHexStringFlag;
|
|
|
|
}
|
|
|
|
|
|
|
|
string hexToBytes(const string& hexString) {
|
|
|
|
// if the string has an odd number of chars, return an empty string
|
|
|
|
if (!isHexString(hexString) || hexString.size() % 2 != 0) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<uint8_t> bytes;
|
|
|
|
for (uint32_t i = 0; i < hexString.length(); i += 2) {
|
|
|
|
string byteString = hexString.substr(i, 2);
|
|
|
|
uint8_t byte = static_cast<uint8_t>(strtol(byteString.c_str(),
|
|
|
|
nullptr, 16));
|
|
|
|
bytes.push_back(byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
return string(bytes.begin(), bytes.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t hexToLong(const string& hexString) {
|
|
|
|
uint32_t value;
|
|
|
|
stringstream conversionStream;
|
|
|
|
conversionStream << hexString;
|
|
|
|
conversionStream >> hex >> value;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimNewLines(string str) {
|
2018-10-02 20:21:35 +00:00
|
|
|
return trimChar(str, '\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimQuotes(string str) {
|
|
|
|
return trimChar(str, '\"');
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimChar(string str, char targetChar) {
|
|
|
|
str.erase(remove(str.begin(), str.end(), targetChar), str.end());
|
2018-09-06 13:47:33 +00:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimWhitespaceFromLeft(string str) {
|
|
|
|
RE2 pattern("^\\s+");
|
|
|
|
while (RE2::PartialMatch(str, pattern)) {
|
|
|
|
str = str.erase(0, 1);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimWhitespaceFromRight(string str) {
|
|
|
|
RE2 pattern("\\s+$");
|
|
|
|
while (RE2::PartialMatch(str, pattern)) {
|
|
|
|
str = str.erase(str.length()-1, 1);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
string trimWhitespaceFromBothEnds(string str) {
|
|
|
|
return trimWhitespaceFromRight(trimWhitespaceFromLeft(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace string_utils
|
|
|
|
|
|
|
|
} // namespace hirs
|