2023-06-01 16:09:22 +03:00
|
|
|
//
|
|
|
|
// Created by Andrew on 01/06/2023.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "header.h"
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
bool loadJSON(const fs::path& filename, json *output) {
|
|
|
|
if (!fs::exists(filename)) {
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("ERROR: File {} does not exist\n", filename.string());
|
2023-06-05 18:43:31 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ifstream f(filename);
|
2023-06-07 01:04:39 +03:00
|
|
|
*output = json::parse(f, nullptr, false, false);
|
|
|
|
|
|
|
|
if (output->is_discarded()) {
|
|
|
|
fmt::print("ERROR: Unable to parse keys from {}\n", filename.string());
|
|
|
|
return false;
|
|
|
|
}
|
2023-06-05 18:43:31 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-02 07:25:43 +03:00
|
|
|
void showHelp(char *argv[]) {
|
2023-06-05 18:43:31 +03:00
|
|
|
fmt::print("usage: {} \n", argv[0]);
|
|
|
|
fmt::print("\t-h --help\tshow this message\n");
|
|
|
|
fmt::print("\t-v --verbose\tenable verbose output\n");
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("\t-n --number\tnumber of keys to generate (defaults to 1)\n");
|
2023-06-05 18:43:31 +03:00
|
|
|
fmt::print("\t-f --file\tspecify which keys file to load (defaults to keys.json)\n");
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n");
|
2023-06-05 18:43:31 +03:00
|
|
|
fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n");
|
|
|
|
fmt::print("\t-l --list\tshow which products/binks can be loaded\n");
|
|
|
|
fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n");
|
|
|
|
fmt::print("\n\n");
|
2023-06-02 07:25:43 +03:00
|
|
|
}
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
int parseCommandLine(int argc, char* argv[], Options* options) {
|
|
|
|
// set default options
|
|
|
|
*options = Options {
|
2023-06-02 07:25:43 +03:00
|
|
|
"2E",
|
|
|
|
640,
|
2023-06-05 18:43:31 +03:00
|
|
|
"keys.json",
|
2023-06-07 01:04:39 +03:00
|
|
|
1,
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
false,
|
2023-06-02 07:25:43 +03:00
|
|
|
false,
|
|
|
|
false,
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
std::string arg = argv[i];
|
|
|
|
|
|
|
|
if (arg == "-v" || arg == "--verbose") {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->verbose = true;
|
2023-06-02 07:25:43 +03:00
|
|
|
} else if (arg == "-h" || arg == "--help") {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->help = true;
|
2023-06-07 01:04:39 +03:00
|
|
|
} else if (arg == "-n" || arg == "--number") {
|
|
|
|
if (i == argc - 1) {
|
|
|
|
options->error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nKeys;
|
|
|
|
if (!sscanf(argv[i+1], "%d", &nKeys)) {
|
|
|
|
options->error = true;
|
|
|
|
} else {
|
|
|
|
options->numKeys = nKeys;
|
|
|
|
}
|
|
|
|
i++;
|
2023-06-02 07:25:43 +03:00
|
|
|
} else if (arg == "-b" || arg == "--bink") {
|
2023-06-07 01:04:39 +03:00
|
|
|
if (i == argc - 1) {
|
|
|
|
options->error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
options->binkid = argv[i+1];
|
2023-06-02 07:25:43 +03:00
|
|
|
i++;
|
|
|
|
} else if (arg == "-l" || arg == "--list") {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->list = true;
|
2023-06-02 07:25:43 +03:00
|
|
|
} else if (arg == "-c" || arg == "--channelid") {
|
2023-06-07 01:04:39 +03:00
|
|
|
if (i == argc - 1) {
|
|
|
|
options->error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-06-02 07:25:43 +03:00
|
|
|
int siteID;
|
|
|
|
if (!sscanf(argv[i+1], "%d", &siteID)) {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->error = true;
|
2023-06-02 07:25:43 +03:00
|
|
|
} else {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->channelID = siteID;
|
2023-06-02 07:25:43 +03:00
|
|
|
}
|
|
|
|
i++;
|
2023-06-05 18:43:31 +03:00
|
|
|
} else if (arg == "-f" || arg == "--file") {
|
2023-06-07 01:04:39 +03:00
|
|
|
if (i == argc - 1) {
|
|
|
|
options->error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
options->keysFilename = argv[i+1];
|
|
|
|
i++;
|
2023-06-07 01:04:39 +03:00
|
|
|
} else if (arg == "-i" || arg == "--instid") {
|
|
|
|
if (i == argc - 1) {
|
|
|
|
options->error = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
options->instid = argv[i+1];
|
|
|
|
i++;
|
2023-06-02 07:25:43 +03:00
|
|
|
} else {
|
2023-06-05 18:43:31 +03:00
|
|
|
options->error = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return !options->error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int validateCommandLine(Options* options, char *argv[], json *keys) {
|
|
|
|
if (options->verbose) {
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("Loading keys file {}\n", options->keysFilename);
|
2023-06-05 18:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!loadJSON(options->keysFilename, keys)) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options->verbose) {
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("Loaded keys from {} successfully\n",options->keysFilename);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options->help || options->error) {
|
|
|
|
if (options->error) {
|
|
|
|
fmt::print("error parsing command line options\n");
|
|
|
|
}
|
|
|
|
showHelp(argv);
|
|
|
|
return 1;
|
2023-06-05 18:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options->list) {
|
|
|
|
for (auto el : (*keys)["Products"].items()) {
|
|
|
|
int id;
|
|
|
|
sscanf((el.value()["BINK"][0]).get<std::string>().c_str(), "%x", &id);
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("{}: {}\n", el.key(), el.value()["BINK"]);
|
2023-06-02 07:25:43 +03:00
|
|
|
}
|
2023-06-05 18:43:31 +03:00
|
|
|
|
|
|
|
fmt::print("\n\n");
|
|
|
|
fmt::print("** Please note: any BINK ID other than 2E is considered experimental at this time **\n");
|
|
|
|
fmt::print("\n");
|
|
|
|
return 1;
|
2023-06-02 07:25:43 +03:00
|
|
|
}
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
int intBinkID;
|
|
|
|
sscanf(options->binkid.c_str(), "%x", &intBinkID);
|
|
|
|
|
2023-06-07 01:04:39 +03:00
|
|
|
if (intBinkID >= 0x40) {
|
|
|
|
options->isBink2002 = true;
|
2023-06-05 18:43:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options->channelID > 999) {
|
2023-06-07 01:04:39 +03:00
|
|
|
fmt::print("ERROR: refusing to create a key with a siteID greater than 999\n");
|
2023-06-05 18:43:31 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2023-06-02 07:25:43 +03:00
|
|
|
}
|
|
|
|
|
2023-06-04 13:31:24 +03:00
|
|
|
void print_product_id(DWORD *pid)
|
2023-06-01 16:09:22 +03:00
|
|
|
{
|
|
|
|
char raw[12];
|
|
|
|
char b[6], c[8];
|
|
|
|
int i, digit = 0;
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
// Cut away last bit of pid and convert it to an accii-number (=raw)
|
2023-06-02 07:25:43 +03:00
|
|
|
sprintf(raw, "%iu", pid[0] >> 1);
|
2023-06-01 16:09:22 +03:00
|
|
|
|
|
|
|
// Make b-part {640-....}
|
|
|
|
strncpy(b, raw, 3);
|
|
|
|
b[3] = 0;
|
|
|
|
|
|
|
|
// Make c-part {...-123456X...}
|
|
|
|
strcpy(c, raw + 3);
|
2023-06-05 18:43:31 +03:00
|
|
|
fmt::print("> {}\n", c);
|
2023-06-01 16:09:22 +03:00
|
|
|
|
|
|
|
// Make checksum digit-part {...56X-}
|
|
|
|
assert(strlen(c) == 6);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
digit -= c[i] - '0'; // Sum digits
|
|
|
|
|
|
|
|
while (digit < 0)
|
|
|
|
digit += 7;
|
|
|
|
c[6] = digit + '0';
|
|
|
|
c[7] = 0;
|
|
|
|
|
2023-06-05 18:43:31 +03:00
|
|
|
fmt::print("Product ID: PPPPP-{}-{}-23xxx\n", b, c);
|
2023-06-01 16:09:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_product_key(char *pk) {
|
|
|
|
assert(strlen(pk) == 25);
|
2023-06-05 18:43:31 +03:00
|
|
|
|
|
|
|
std::string spk = pk;
|
|
|
|
fmt::print("{}-{}-{}-{}-{}",
|
|
|
|
spk.substr(0,5),
|
|
|
|
spk.substr(5,5),
|
|
|
|
spk.substr(10,5),
|
|
|
|
spk.substr(15,5),
|
|
|
|
spk.substr(20,5));
|
2023-06-01 16:09:22 +03:00
|
|
|
}
|