147 lines
4.2 KiB
C++
147 lines
4.2 KiB
C++
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unistd.h>
|
|
#include <cstring>
|
|
#include <sstream>
|
|
#include <filesystem>
|
|
#include "version.h"
|
|
#include "b64ed.hpp"
|
|
|
|
// Recursively decode and print if nested bb64 command is found
|
|
void recursive_print(const std::string &decoded)
|
|
{
|
|
std::cout << std::string(80, '-') << std::endl;
|
|
std::cout << decoded << std::endl;
|
|
std::cout << std::string(80, '-') << std::endl;
|
|
|
|
size_t pos = decoded.find("bb64 ");
|
|
if (pos != std::string::npos)
|
|
{
|
|
std::istringstream iss(decoded.substr(pos));
|
|
std::string cmd, arg;
|
|
iss >> cmd >> arg;
|
|
if (cmd == "bb64" && !arg.empty())
|
|
{
|
|
std::string nested = base64_decode(arg);
|
|
std::cout << " ";
|
|
std::cout << "nested: " << nested << std::endl;
|
|
recursive_print(nested);
|
|
}
|
|
}
|
|
}
|
|
|
|
constexpr unsigned int hash(const char *s, int off = 0)
|
|
{
|
|
return !s[off] ? 5381 : (hash(s, off + 1) * 33) ^ s[off];
|
|
}
|
|
|
|
std::string get_arch()
|
|
{
|
|
// determine the architecture of the system
|
|
std::string arch;
|
|
#ifdef __aarch64__
|
|
arch = "arm64";
|
|
#elif __x86_64__
|
|
arch = "amd64";
|
|
#endif
|
|
return arch;
|
|
}
|
|
|
|
int update_bb64()
|
|
{
|
|
// determine path to this executable
|
|
std::filesystem::path bb64_path = std::filesystem::canonical("/proc/self/exe");
|
|
std::filesystem::path parent_path = bb64_path.parent_path();
|
|
|
|
// determine the architecture of the system
|
|
std::string arch = get_arch();
|
|
|
|
std::string url = "https://gitea.jde.nz/public/bb64/releases/download/latest/bb64." + arch;
|
|
|
|
// download new version, preserve permissions and ownership
|
|
std::string bash_script;
|
|
bash_script += "docker run --rm -v "+parent_path.string()+":/target";
|
|
bash_script += " gitea.jde.nz/public/debian-curl:latest";
|
|
bash_script += " sh -c \"";
|
|
bash_script += " curl -fsSL " + url + " -o /target/bb64_temp &&";
|
|
bash_script += " chmod --reference=/target/bb64 /target/bb64_temp &&";
|
|
bash_script += " chown --reference=/target/bb64 /target/bb64_temp &&";
|
|
bash_script += " mv /target/bb64_temp /target/bb64";
|
|
bash_script += "\"";
|
|
|
|
std::cout << "Updating " << bb64_path << " to the latest " << arch << " version." << std::endl;
|
|
|
|
// std::cout << "bash_script: " << std::endl
|
|
// << bash_script << std::endl;
|
|
|
|
// run the bash script
|
|
execlp("bash", "bash", "-c", bash_script.c_str(), (char *)nullptr);
|
|
std::cerr << "Failed to execute command." << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
int decode_and_run(const std::string &encoded)
|
|
{
|
|
// Default: decode and run
|
|
std::string decoded = base64_decode(encoded);
|
|
if (decoded.empty())
|
|
{
|
|
std::cerr << "Failed to decode base64 command." << std::endl;
|
|
return -1;
|
|
}
|
|
// Replace current process with bash -c "decoded"
|
|
execlp("bash", "bash", "-c", decoded.c_str(), (char *)nullptr);
|
|
// If execlp returns, there was an error
|
|
std::cerr << "Failed to execute command." << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
std::cerr << "bb64 version " << VERSION << ", by J842." << std::endl;
|
|
// heredoc for instructions
|
|
std::cerr << R"(
|
|
|
|
Usage:
|
|
bb64 BASE64COMMAND Decodes and runs the command
|
|
bb64 -[i|d] BASE64COMMAND Displays the decoded command
|
|
bb64 -e COMMAND Encodes the command and prints the result
|
|
bb64 -u Updates bb64 to the latest version (uses docker)
|
|
|
|
)" << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
std::string mode = argv[1];
|
|
|
|
if (argc == 2)
|
|
{
|
|
if (mode == "-u")
|
|
return update_bb64();
|
|
else
|
|
return decode_and_run(mode);
|
|
}
|
|
|
|
std::ostringstream oss;
|
|
|
|
switch (hash(mode.c_str()))
|
|
{
|
|
case hash("-i"):
|
|
case hash("-d"):
|
|
std::cout << "Decoding command..." << std::endl
|
|
<< std::endl;
|
|
recursive_print(base64_decode(argv[2]));
|
|
break;
|
|
case hash("-e"):
|
|
for (int i = 2; i < argc; ++i)
|
|
oss << (i > 2 ? " " : "") << argv[i];
|
|
std::cout << base64_encode(oss.str()) << std::endl;
|
|
break;
|
|
default:
|
|
std::cerr << "Invalid mode: " << mode << std::endl;
|
|
return -1;
|
|
};
|
|
} |