diff --git a/README.md b/README.md index 2c49bbb2..f2f67bc0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Dual licenses: choose [_Creative Commons_](https://creativecommons.org/share-you [`./cxx/`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/) _C++_ implementations of posts (for now is just neural system pure virtual template ([`./cxx/ClassCns.hxx`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/ClassCns.hxx)) + antivirus([`./cxx/VirusAnalysis.cxx`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/VirusAnalysis.cxx)) + assistant([`./cxx/AssistantCns.cxx`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/AssistantCns.cxx)), with lots of [issues](https://github.com/SwuduSusuwu/SubStack/issues) which you can contribute to, or can request that more resources go to). # How to use this -Targets: Windows/Linux/Android/OSX/iOS; minimum [_C++11_](https://gcc.gnu.org/projects/cxx-status.html#cxx11) (all `CXX` with `201102 <= __cplusplus`,) due to use of `auto`, `decltype`, `for(value: list) {}`, `nullptr`, `__func__`). +Targets: Windows/Linux/Android/OSX/iOS; minimum [_C++11_](https://gcc.gnu.org/projects/cxx-status.html#cxx11) (all `CXX` with `201102 <= __cplusplus`,) due to use of `auto`, `class {bool defaultMemberInit = true};`, `decltype`, `for(value: list) {}`, `nullptr`, `__func__`). Usage: [`./build.sh [OPTIONS]`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/build.sh) produces objects (`./obj/*.o`, for distribution into other tools,) plus [_Executable and Linkable Format_](https://wikipedia.org/wiki/Executable_and_Linkable_Format) (`./bin/a.out`, to do examples/[unit tests](https://wikipedia.org/wiki/Unit_test#Agile) which prove how effective functions execute,) both of which you can redirect with `export OBJDIR=___` (or `export BINDIR=___`.) - [`./cxx/main.hxx`](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/main.hxx) has constants to use to interpret `a.out`'s return values. diff --git a/cxx/AssistantCns.cxx b/cxx/AssistantCns.cxx index fe384416..8ac0fd79 100644 --- a/cxx/AssistantCns.cxx +++ b/cxx/AssistantCns.cxx @@ -1,11 +1,11 @@ /* Dual licenses: choose "Creative Commons" or "Apache 2" (allows all uses) */ #ifndef INCLUDES_cxx_AssistantCns_cxx #define INCLUDES_cxx_AssistantCns_cxx -#include "AssistantCns.hxx" /* assistantParseQuestion assistantParseResponses assistantParseUrls */ +#include "AssistantCns.hxx" /* assistantCnsProcessQuestion assistantCnsProcessResponses assistantCnsProcessUrls */ #include "ClassCns.hxx" /* Cns CnsMode execvex */ #include "ClassPortableExecutable.hxx" /* FileBytecode FilePath */ #include "ClassResultList.hxx" /* explodeToList listMaxSize listHasValue ResultList ResultListBytecode resultListDumpTo resultListProduceHashes */ -#include "ClassSha2.hxx" /* sha2 */ +#include "ClassSha2.hxx" /* classSha2 */ #include "ClassSys.hxx" /* execvex */ #include "Macros.hxx" /* SUSUWU_NOTICE_EXECUTEVERBOSE */ #include /* assert */ @@ -49,7 +49,7 @@ const bool assistantCnsTests() { assert(3 == responsesOrNull.hashes.size()); SUSUWU_NOTICE_EXECUTEVERBOSE(resultListDumpTo(questionsOrNull, std::cout, true, true, false)); SUSUWU_NOTICE_EXECUTEVERBOSE((resultListDumpTo(responsesOrNull, std::cout, false, false, false), std::cout << std::endl)); - questionsResponsesFromHosts(questionsOrNull, responsesOrNull); + assistantCnsDownloadHosts(questionsOrNull, responsesOrNull); produceAssistantCns(questionsOrNull, responsesOrNull, assistantCns); return true; } @@ -69,22 +69,22 @@ void produceAssistantCns(const ResultList &questionsOrNull, const ResultList &re cns.setupSynapses(inputsToOutputs); } -void questionsResponsesFromHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts) { +void assistantCnsDownloadHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts) { for(const auto &host : hosts) { execvex("wget '" + host + "/robots.txt' -Orobots.txt"); execvex("wget '" + host + "' -Oindex.xhtml"); questionsOrNull.signatures.push_back(host); - questionsResponsesFromXhtml(questionsOrNull, responsesOrNull, "index.xhtml"); + assistantCnsProcessXhtml(questionsOrNull, responsesOrNull, "index.xhtml"); } } -void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml) { - auto noRobots = assistantParseUrls("robots.txt"); - auto question = assistantParseQuestion(localXhtml); +void assistantCnsProcessXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml) { + auto noRobots = assistantCnsProcessUrls("robots.txt"); + auto question = assistantCnsProcessQuestion(localXhtml); if(!question.empty()) { - auto questionSha2 = sha2(question); + auto questionSha2 = classSha2(question); if(listHasValue(questionsOrNull.hashes, questionSha2)) { /* TODO */ } else { decltype(question) response = ""; - auto responses = assistantParseResponses(localXhtml); + auto responses = assistantCnsProcessResponses(localXhtml); if(!responses.empty()) { questionsOrNull.hashes.insert(questionSha2); questionsOrNull.bytecodes.push_back(question); @@ -95,7 +95,7 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon } response += responseIt; } - auto responseSha2 = sha2(response); + auto responseSha2 = classSha2(response); if(listHasValue(responsesOrNull.hashes, responseSha2)) { /* TODO */ } else { responsesOrNull.hashes.insert(responseSha2); responsesOrNull.bytecodes.push_back(response); @@ -103,12 +103,12 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon } } } - auto urls = assistantParseUrls(localXhtml); + auto urls = assistantCnsProcessUrls(localXhtml); for(const auto &url : urls) { if(!listHasValue(questionsOrNull.signatures, url) && !listHasValue(noRobots, url)) { execvex("wget '" + url + "' -O" + localXhtml); questionsOrNull.signatures.push_back(url); - questionsResponsesFromXhtml(questionsOrNull, responsesOrNull, localXhtml); + assistantCnsProcessXhtml(questionsOrNull, responsesOrNull, localXhtml); } } } @@ -116,7 +116,7 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon #include #include #endif /* BOOST_VERSION */ -const std::vector assistantParseUrls(const FilePath &localXhtml) { +const std::vector assistantCnsProcessUrls(const FilePath &localXhtml) { const std::vector urls; #ifdef BOOST_VERSION boost::property_tree::ptree pt; @@ -130,8 +130,8 @@ const std::vector assistantParseUrls(const FilePath &localXhtml) { #endif /* else !BOOST_VERSION */ return urls; } -const FileBytecode assistantParseQuestion(const FilePath &localXhtml) {return "";} /* TODO */ -const std::vector assistantParseResponses(const FilePath &localXhtml) {return {};} /* TODO */ +const FileBytecode assistantCnsProcessQuestion(const FilePath &localXhtml) {return "";} /* TODO */ +const std::vector assistantCnsProcessResponses(const FilePath &localXhtml) {return {};} /* TODO */ const std::string assistantCnsProcess(const Cns &cns, const FileBytecode &bytecode) { return cns.processToString(bytecode); diff --git a/cxx/AssistantCns.hxx b/cxx/AssistantCns.hxx index 2d5a921e..4a628cfd 100644 --- a/cxx/AssistantCns.hxx +++ b/cxx/AssistantCns.hxx @@ -16,14 +16,14 @@ namespace Susuwu { extern Cns assistantCns; extern std::string assistantCnsResponseDelimiter; -/* if (with example inputs) these functions (`questionsResponsesFromHosts()` `produceAssistantCns()`) pass, `return true;` +/* if (with example inputs) these functions (`assistantCnsDownloadHosts()` `produceAssistantCns()`) pass, `return true;` * @throw std::bad_alloc * @throw std::logic_error * @pre @code assistantCns.hasImplementation() @endcode */ const bool assistantCnsTests(); static const bool assistantCnsTestsNoexcept() SUSUWU_NOEXCEPT {return templateCatchAll(assistantCnsTests, "assistantCnsTests()");} -/* Universal Resources Locators of hosts which `questionsResponsesFromHosts()` uses +/* Universal Resources Locators of hosts which `assistantCnsDownloadHosts()` uses * Wikipedia is a special case; has compressed downloads of databases ( https://wikipedia.org/wiki/Wikipedia:Database_download ) * Github is a special case; has compressed downloads of repositories ( https://docs.github.com/en/get-started/start-your-journey/downloading-files-from-github ) */ @@ -34,11 +34,11 @@ extern std::vector assistantCnsDefaultHosts; * If no responses, `0 == responsesOrNull.bytecodes[x].size()` (ignore). * `questionsOrNull.signatures[x] = Universal Resource Locator` * @code sha2(ResultList.bytecodes[x]) == ResultList.hashes[x] @endcode */ -void questionsResponsesFromHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts = assistantCnsDefaultHosts); -void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml = "index.xhtml"); -const std::vector assistantParseUrls(const FilePath &localXhtml = "index.xhtml"); /* TODO: for XML/XHTML could just use [ https://www.boost.io/libraries/regex/ https://github.com/boostorg/regex ] or [ https://www.boost.org/doc/libs/1_85_0/doc/html/property_tree/parsers.html#property_tree.parsers.xml_parser https://github.com/boostorg/property_tree/blob/develop/doc/xml_parser.qbk ] */ -const FileBytecode assistantParseQuestion(const FilePath &localXhtml = "index.xhtml"); /* TODO: regex or XML parser */ -const std::vector assistantParseResponses(const FilePath &localXhtml = "index.xhtml"); /* TODO: regex or XML parser */ +void assistantCnsDownloadHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts = assistantCnsDefaultHosts); +void assistantCnsProcessXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml = "index.xhtml"); +const std::vector assistantCnsProcessUrls(const FilePath &localXhtml = "index.xhtml"); /* TODO: for XML/XHTML could just use [ https://www.boost.io/libraries/regex/ https://github.com/boostorg/regex ] or [ https://www.boost.org/doc/libs/1_85_0/doc/html/property_tree/parsers.html#property_tree.parsers.xml_parser https://github.com/boostorg/property_tree/blob/develop/doc/xml_parser.qbk ] */ +const FileBytecode assistantCnsProcessQuestion(const FilePath &localXhtml = "index.xhtml"); /* TODO: regex or XML parser */ +const std::vector assistantCnsProcessResponses(const FilePath &localXhtml = "index.xhtml"); /* TODO: regex or XML parser */ /* @pre `questionsOrNull` maps to `responsesOrNull`, * `0 == questionsOrNull.bytecodes[x].size()` for new assistant synthesis (empty question has responses), diff --git a/cxx/ClassResultList.hxx b/cxx/ClassResultList.hxx index f026f251..ba079c9a 100644 --- a/cxx/ClassResultList.hxx +++ b/cxx/ClassResultList.hxx @@ -4,7 +4,7 @@ #define INCLUDES_cxx_ClassResultList_hxx //#include "ClassObject.hxx" /* Object */ /* TODO: fix "Initialization of non-aggregate type" */ #include "ClassPortableExecutable.hxx" /* FilePath FileBytecode FileHash */ -#include "ClassSha2.hxx" /* sha2 */ +#include "ClassSha2.hxx" /* classSha2 */ #include "ClassSys.hxx" /* classSysHexOs */ #include "Macros.hxx" /* SUSUWU_NOEXCEPT SUSUWU_PREFER_CSTR */ #include /* std::search std::find std::set_intersection */ @@ -92,7 +92,7 @@ template * @post @code !hashes.empty() @endcode */ void listToHashes(const List &list /* ResultList::bytecodes or ResultList::hex*/, List2 &hashes /* ResultList::hashess */) { for(const auto &value : list) { - hashes.insert(sha2(value)); + hashes.insert(classSha2(value)); } } /* Usage: if `ResultList` was not produced with `.hashes` */ diff --git a/cxx/ClassSha2.cxx b/cxx/ClassSha2.cxx index 7a2c5ab2..8f79a5db 100644 --- a/cxx/ClassSha2.cxx +++ b/cxx/ClassSha2.cxx @@ -4,7 +4,7 @@ #include "ClassPortableExecutable.hxx" /* FileBytecode FileHash */ #include "ClassSha2.hxx" #include "ClassSys.hxx" /* classSysHexStr classSysUSecondClock templateCatchAll */ -#include "Macros.hxx" /* SUSUWU_NOEXCEPT SUSUWU_NOTICE_EXECUTE SUSUWU_PRINT SUSUWU_INFO SUSUWU_NOTICE */ +#include "Macros.hxx" /* SUSUWU_NOEXCEPT SUSUWU_NOTICE_EXECUTE SUSUWU_INFO SUSUWU_NOTICE SUSUWU_WARNING */ #include /* CHAR_BIT */ #include /* std::runtime_error */ #include /* std::to_string */ @@ -13,26 +13,26 @@ extern "C" { #include "../c/rfc6234/sha.h" /* SHA256HashSize, SHA256Context, SHA256Reset, SHA256Input, SHA256Result, SHA1*, SHA512* */ } namespace Susuwu { -Sha2 sha2 = sha256; -/* const */ FileHash /* 128 bits, not null-terminated */ sha1(const FileBytecode &bytecode) { +ClassSha2 classSha2 = classSha256; +/* const */ FileHash /* 128 bits, not null-terminated */ classSha1(const FileBytecode &bytecode) { FileHash result; SHA1Context context; result.resize(SHA1HashSize); - SHA1Reset(&context); /* If `undefined symbol: SHA1Reset`, affix `sha1.o` to `${LD_FLAGS}` */ + SHA1Reset(&context); /* If `undefined symbol: SHA1Reset`, affix `classSha1.o` to `${LD_FLAGS}` */ SHA1Input(&context, reinterpret_cast(&bytecode[0]), bytecode.size()); SHA1Result(&context, reinterpret_cast(&result[0])); return result; } -/* const */ FileHash /* 256 bits, not null-terminated */ sha256(const FileBytecode &bytecode) { +/* const */ FileHash /* 256 bits, not null-terminated */ classSha256(const FileBytecode &bytecode) { FileHash result; SHA256Context context; result.resize(SHA256HashSize); - SHA256Reset(&context); /* If `undefined symbol: SHA256Reset`, affix `sha224-256.o` to `${LD_FLAGS}` */ + SHA256Reset(&context); /* If `undefined symbol: SHA256Reset`, affix `classSha224-256.o` to `${LD_FLAGS}` */ SHA256Input(&context, reinterpret_cast(&bytecode[0]), bytecode.size()); SHA256Result(&context, reinterpret_cast(&result[0])); return result; } -/* const */ FileHash /* 512 bits, not null-terminated */ sha512(const FileBytecode &bytecode) { +/* const */ FileHash /* 512 bits, not null-terminated */ classSha512(const FileBytecode &bytecode) { FileHash result; SHA512Context context; result.resize(SHA512HashSize); @@ -46,24 +46,24 @@ const bool classSha2Tests() { /* is just to test glue code (which wraps rfc6234) const char nulls[65536 /* 65536 == 2^16 == 64kb */] = {0}; std::string nullStr(nulls, &nulls[65536]); const ClassSysUSeconds tsDrift = classSysUSecondClock(), ts2Drift = classSysUSecondClock() - tsDrift, ts = classSysUSecondClock(); - const FileHash hash = sha2(nullStr); + const FileHash hash = classSha2(nullStr); const ClassSysUSeconds ts2 = classSysUSecondClock() - ts2Drift; const std::string hashStrCompute = "0x" + classSysHexStr(hash); const std::string hashStrTrue = "0xde2f256064a0af797747c2b97505dc0b9f3df0de4f489eac731c23ae9ca9cc31"; if(ts == ts2) { - SUSUWU_PRINT(WARNING, "0 ms (0 μs) to compute `sha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = inf mbps"); + SUSUWU_WARNING("0 ms (0 μs) to compute `classSha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = inf mbps"); } else { - SUSUWU_INFO(std::to_string((ts2 - ts) / 1000) + " ms (" + std::to_string(ts2 - ts) + " μs) to compute `sha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = " + std::to_string(float(65536) * CHAR_BIT /* to bits */ / (ts2 - ts) /* to bpμs */ * 1000000 /* to bps */ / (1 << 20) /* to mbps */) + "mbps"); + SUSUWU_INFO(std::to_string((ts2 - ts) / 1000) + " ms (" + std::to_string(ts2 - ts) + " μs) to compute `classSha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = " + std::to_string(float(65536) * CHAR_BIT /* to bits */ / (ts2 - ts) /* to bpμs */ * 1000000 /* to bps */ / (1 << 20) /* to mbps */) + "mbps"); } - SUSUWU_NOTICE("This `sha2()` is from `./build.sh --debug`: `./build.sh --release` has 2x this throughput"); + SUSUWU_NOTICE("This `classSha2()` is from `./build.sh --debug`: `./build.sh --release` has 2x this throughput"); if(0 == hash.size()) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`0 == sha2(std::string()).size();")); - } else if(hashStrTrue.size() != hashStrCompute.size() && sha256 == sha2) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`sha2 = sha256;`, but `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`")); + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`0 == classSha2(std::string()).size();")); + } else if(hashStrTrue.size() != hashStrCompute.size() && classSha256 == classSha2) { + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`classSha2 = classSha256;`, but `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`")); } else if(hashStrTrue.size() != hashStrCompute.size()) { - SUSUWU_INFO("`(sha256 != sha2)`, `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`"); + SUSUWU_INFO("`(classSha256 != classSha2)`, `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`"); } else if(hashStrTrue != hashStrCompute) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "sha2(char nulls[65535] = {0}) did not compute " + hashStrTrue)); + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "classSha2(char nulls[65535] = {0}) did not compute " + hashStrTrue)); } return true; } diff --git a/cxx/ClassSha2.hxx b/cxx/ClassSha2.hxx index 95b5b223..c3ea39f3 100644 --- a/cxx/ClassSha2.hxx +++ b/cxx/ClassSha2.hxx @@ -6,11 +6,11 @@ #include "Macros.hxx" /* SUSUWU_NOEXCEPT */ namespace Susuwu { /* Uses https://www.rfc-editor.org/rfc/rfc6234#section-8.2.2 */ -/* const */ FileHash /* 128 bits, not null-terminated */ sha1(const FileBytecode &bytecode); -/* const */ FileHash /* 256 bits, not null-terminated */ sha256(const FileBytecode &bytecode); -/* const */ FileHash /* 512 bits, not null-terminated */ sha512(const FileBytecode &bytecode); -typedef FileHash (*Sha2)(const FileBytecode &bytecode); -extern Sha2 sha2/* = sha256 */; /* To compress, apps can execute `sha2 = sha1;`. To double hash sizes, execute `sha2 = sha512;`. (Notice: this does not recompute hashes which exist) */ +/* const */ FileHash /* 128 bits, not null-terminated */ classSha1(const FileBytecode &bytecode); +/* const */ FileHash /* 256 bits, not null-terminated */ classSha256(const FileBytecode &bytecode); +/* const */ FileHash /* 512 bits, not null-terminated */ classSha512(const FileBytecode &bytecode); +typedef FileHash (*ClassSha2)(const FileBytecode &bytecode); +extern ClassSha2 classSha2/* = classSha256 */; /* To compress, apps can execute `sha2 = classSha1;`. To double hash sizes, execute `sha2 = classSha512;`. (Notice: this does not recompute hashes which exist) */ const bool classSha2Tests(); const bool classSha2TestsNoexcept() SUSUWU_NOEXCEPT; }; /* namespace Susuwu */ diff --git a/cxx/ClassSys.cxx b/cxx/ClassSys.cxx index 2513502b..feab8654 100644 --- a/cxx/ClassSys.cxx +++ b/cxx/ClassSys.cxx @@ -1,23 +1,23 @@ /* Dual licenses: choose "Creative Commons" or "Apache 2" (allows all uses) */ #ifndef INCLUDES_cxx_ClassSys_cxx #define INCLUDES_cxx_ClassSys_cxx -#include "Macros.hxx" /* ERROR SUSUWU_ERRSTR SUSUWU_NOEXCEPT SUSUWU_PRINT WARNING */ +#include "Macros.hxx" /* ERROR SUSUWU_ERRSTR SUSUWU_NOEXCEPT SUSUWU_POSIX SUSUWU_WARNING SUSUWU_WIN32*/ #include "ClassSys.hxx" /* classSysHexStr classSysHexOs */ #include /* assert */ #include /* errno */ #include /* exit EXIT_FAILURE EXIT_SUCCESS getenv strtol */ #include /* std::cerr std::cout std::endl std::flush std::ios::eofbit std::ios::goodbit */ -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX #include /* std::runtime_error */ #include /* pid_t */ #include /* waitpid WIFEXITED WEXITSTATUS WIFSIGNALED WSIGTERM */ #include /* execve execv fork geteuid getuid setuid */ #else -# ifdef __WIN32__ -# include /* IsUserAnAdmin */ -# endif /* def __WIN32__ */ +# ifdef SUSUWU_WIN32 +# include /* IsUserAnAdmin */ +# endif /* def SUSUWU_WIN32 */ typedef int pid_t; -#endif /* def _POSIX_VERSION */ +#endif /* def SUSUWU_POSIX */ #include /* std::stringstream */ #include /* std::string std::to_string */ #include /* std::vector */ @@ -36,7 +36,7 @@ const bool classSysInit(int argc, const char **args) { } const pid_t execvesFork(const std::vector &argvS, const std::vector &envpS) SUSUWU_NOEXCEPT { -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX const pid_t pid = fork(); if(0 != pid) { if(-1 == pid) { @@ -65,14 +65,14 @@ const pid_t execvesFork(const std::vector &argvS, const std::vector execve(argv[0], &argv[0], &envp[0]); /* NORETURN */ } exit(EXIT_FAILURE); /* execv*() is `NORETURN`. NOLINT(concurrency-mt-unsafe) */ -#else /* ndef _POSIX_VERSION */ -# undef ERROR /* undo `shlobj.h`'s `#define ERROR 0` */ - SUSUWU_ERROR("execvesFork: {#ifndef _POSIX_VERSION /* TODO: convert to win32 */}"); +#else /* ndef SUSUWU_POSIX */ +# undef ERROR /* undo `shlobj.h`'s `#define ERROR 0` */ + SUSUWU_ERROR("execvesFork: {#ifndef SUSUWU_POSIX /* TODO: convert to win32 */}"); return -1; -#endif /* ndef _POSIX_VERSION */ +#endif /* ndef SUSUWU_POSIX */ } const int execves(const std::vector &argvS, const std::vector &envpS) { -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX const pid_t pid = execvesFork(argvS, envpS); int wstatus = 0; if(-1 == pid) { @@ -86,65 +86,65 @@ const int execves(const std::vector &argvS, const std::vector(strtol(sudoUidStr, &sudoUidStrIt, 10)); if(sudoUidStr == sudoUidStrIt || -1 == setuid(sudoUid)) { /* prevent reescalation to root */ - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(-1 == setuid(sudoUid)) /* can't prevent reescalation to root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(-1 == setuid(sudoUid)) /* can't prevent reescalation to root */}"); } } } -# endif /* !def LINUX */ +# endif /* !def LINUX */ if(0 == sudoUid) { - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(0 == sudoUid) /* stuck as root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(0 == sudoUid) /* stuck as root */}"); } else if(-1 == seteuid(sudoUid)) { - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(-1 == seteuid(sudoUid)) /* stuck as root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(-1 == seteuid(sudoUid)) /* stuck as root */}"); } } -/* #elif defined __WIN32__ */ //TODO: https://stackoverflow.com/questions/6418791/requesting-administrator-privileges-at-run-time says you must spawn new processes to do this +/* #elif defined SUSUWU_WIN32 */ //TODO: https://stackoverflow.com/questions/6418791/requesting-administrator-privileges-at-run-time says you must spawn new processes to do this #else - SUSUWU_PRINT(WARNING, "classSysSetRoot(bool) {#ifndef _POSIX_VERSION /* TODO */}"); -#endif /* _POSIX_VERSION */ + SUSUWU_WARNING("classSysSetRoot(bool) {#ifndef SUSUWU_POSIX /* TODO */}"); +#endif /* SUSUWU_POSIX */ return classSysHasRoot(); } diff --git a/cxx/ClassSys.hxx b/cxx/ClassSys.hxx index aa02d063..d8537a5b 100644 --- a/cxx/ClassSys.hxx +++ b/cxx/ClassSys.hxx @@ -2,7 +2,7 @@ #pragma once #ifndef INCLUDES_cxx_ClassSys_hxx #define INCLUDES_cxx_ClassSys_hxx -#include "Macros.hxx" /* ERROR SUSUWU_NOEXCEPT SUSUWU_PRINT */ +#include "Macros.hxx" /* SUSUWU_ERROR SUSUWU_NOEXCEPT SUSUWU_POSIX */ #include /* assert */ #include /* std::chrono */ #include /* std::exception */ @@ -11,7 +11,7 @@ #include /* std::cerr std::cin std::endl */ #include /* std::stringstream */ #include /* std::string std::to_string */ -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX #include /* pid_t */ #else typedef int pid_t; @@ -43,9 +43,9 @@ static const pid_t execvexFork(const std::string &toSh) SUSUWU_NOEXCEPT {return const int execves(const std::vector &argvS = {}, const std::vector &envpS = {}); static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});} -/* #if _POSIX_VERSION, `return (0 == geteuid());` #elif __WIN32__ `return IsUserAnAdmin();` #endif `return false;` */ +/* #if SUSUWU_POSIX, `return (0 == geteuid());` #elif SUSUWU_WIN32 `return IsUserAnAdmin();` #endif `return false;` */ const bool classSysHasRoot(); -/* #if _POSIX_VERSION, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif +/* #if SUSUWU_POSIX, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif * Usage: classSysSetRoot(true); functionsWhichRequireRoot; classSysSetRoot(false); */ const bool classSysSetRoot(bool root); /* root ? (seteuid(0) : (seteuid(getuid() || atoi(getenv("SUDO_UID"))), setuid(geteuid)); return classSysHasRoot(); */ @@ -111,7 +111,7 @@ auto templateCatchAll(Func func, const std::string &funcName, Args... args) -> c try { return func(args...); } catch (const std::exception &ex) { - SUSUWU_PRINT(ERROR, funcName + " {throw std::exception(\"" + ex.what() + "\");}"); + SUSUWU_ERROR(funcName + " {throw std::exception(\"" + ex.what() + "\");}"); return decltype(func(args...))(); /* `func(args...)`'s default return value; if `int func(args...)`, `return 0;`. If `bool func(args...)`, `return false;` */ } } diff --git a/cxx/Macros.hxx b/cxx/Macros.hxx index 2140c074..70b59812 100644 --- a/cxx/Macros.hxx +++ b/cxx/Macros.hxx @@ -39,9 +39,6 @@ # else /* (202002 <= __cplusplus) else */ # define SUSUWU_NO_UNIQUE_ADDRESS /* No-op */ # endif /* if (202002 <= __cplusplus) */ -# if defined(SUSUWU_CXX11) || ((defined __has_cpp_attribute) && __has_cpp_attribute(noreturn)) /* TODO: [Cmake test for `\[\[noreturn\]\]`](https://stackoverflow.com/a/33517293/24473928) */ -# else /* C++11 else */ -# endif /* else no `[[noreturn]]` */ #else /* def __cplusplus */ # include /* assert static_assert */ # define IF_SUSUWU_CPLUSPLUS(TRUE, FALSE) FALSE @@ -55,15 +52,22 @@ #define SUSUWU_COMMA , /* to pass to macro functions whose `__VA_ARGS__` is conditional */ #define SUSUWU_PRAGMA(S) _Pragma(#S) /* `#pragma S` in macro functions is `_Pragma(S)` (but without this indirection/wrap, gives `error: _Pragma takes a parenthesized string literal`/`expected string literal in pragma message`.) Usage: `SUSUWU_PRAGMA(message("Message"))` */ -#if (!defined _POSIX_VERSION) && (defined _POSIX_C_SOURCE) -# define _POSIX_VERSION _POSIX_C_SOURCE /* "Error: ... ndef _POSIX_VERSION" fix. Now, you can just do `#ifdef _POSIX_VERSION` for POSIX code paths */ -#endif /* (!defined _POSIX_VERSION) && (defined _POSIX_C_SOURCE) */ -#if (!defined __WIN32__) && (defined _WIN32 || __MSC_VER /* || defined __CYGWIN__ (should use `#ifdef _POSIX_VERSION` path) */) -# define __WIN32__ /* https://stackoverflow.com/questions/430424/are-there-any-macros-to-determine-if-my-code-is-being-compiled-to-windows/430435#430435 says that __WIN32__ is not always defined on Windows targets */ -#endif -#ifndef __has_feature -# define __has_feature(X) false /* `gcc` "error: missing binary operator before token \"(\"" fix */ -#endif /* ndef __has_feature */ +#if defined(_POSIX_VERSION) || defined(_POSIX_C_SOURCE) || defined(__CYGWIN__) /* Purpose: Often, `_POSIX_VERSION` is not set on POSIX targets */ +# define SUSUWU_POSIX _POSIX_VERSION /* Usage: `#ifdef SUSUWU_WIN32\n#include \n#endif` */ +#endif /* defined*_POSIX_VERSION) || defined(_POSIX_C_SOURCE) || defined(__CYGWIN__) */ +#if defined(__WIN32__) || defined(_WIN32) || defined(__MSC_VER) || defined(__MINGW32__) /* Purpose: https://stackoverflow.com/questions/430424/are-there-any-macros-to-determine-if-my-code-is-being-compiled-to-windows/430435#430435 says that __WIN32__ is not always defined on Windows targets */ +# define SUSUWU_WIN32 /* Usage: `#ifdef SUSUWU_WIN32\n#include \n#endif` */ +#endif /* defined(__WIN32__) || defined(_WIN32) || defined(__MSC_VER) || defined(__MINGW32__) */ +#if defined(__clang__) || defined(__has_feature) /* Purpose: `gcc` "error: missing binary operator before token \"(\"" fix */ +# define SUSUWU_HAS_FEATURE(X) __has_feature(x) /* Usage: `#if SUSUWU_HAS_FEATURE(cxx_noexcept)\nnoexcept\n#endif` */ +#else /* defined(__clang__) || defined(__has_feature) else */ +# define SUSUWU_HAS_FEATURE(X) false +#endif /* defined(__clang__) || defined(__has_feature) else */ +#if defined(__has_cpp_attribute) +# define SUSUWU_HAS_ATTRIBUTE(X) __has_cpp_attribute(x) /* Usage: `#if SUSUWU_HAS_ATTRIBUTE(noreturn)\nnoreturn\n#endif` */ +#else /* defined(__has_cpp_attribute) else */ +# define SUSUWU_HAS_ATTRIBUTE(X) false +#endif /* defined(__has_cpp_attribute) else */ #if defined(SUSUWU_C11) || defined(SUSUWU_CXX11) # define SUSUWU_NORETURN [[noreturn]] /* Usage: `SUSUWU_NORETURN void exit();` is close to `void exit() [[ensures:: false]];` or `exit(); SUSUWU_UNREACHABLE;` */ @@ -83,12 +87,12 @@ # define SUSUWU_ENSURES(X) /* `@post @code X @encode` */ #endif /* else !def USE_CONTRACTS */ -#if defined(SUSUWU_CXX11) || (defined(__clang__) && __has_feature(cxx_noexcept)) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114) /* [Other `noexcept` tests](https://stackoverflow.com/questions/18387640/how-to-deal-with-noexcept-in-visual-studio) */ +#if defined(SUSUWU_CXX11) || (defined(__clang__) && SUSUWU_HAS_FEATURE(cxx_noexcept)) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114) /* [Other `noexcept` tests](https://stackoverflow.com/questions/18387640/how-to-deal-with-noexcept-in-visual-studio) */ # define SUSUWU_NOEXCEPT noexcept /* Usage: `void info() SUSUWU_NOEXCEPT; ... {info();}` is close to `void versionInfo() [[ensures: true]]; ... {info();}` or `{try {versionInfo();} catch(...) {SUSUWU_UNREACHABLE;}} */ /* Usage 2: `void versionInfo() SUSUWU_NOEXCEPT(std::is_nothrow_constructible::value); {versionInfo();}` is close to `{try {versionInfo();} catch(...) {if(std::is_nothrow_constructible::value) {SUSUWU_UNREACHABLE;}}}` */ -#else /* C++11 else */ +#else /* SUSUWU_CXX11 else */ # define SUSUWU_NOEXCEPT /* old `g++`/`clang++` "error: expected function body after function declarator" fix */ -#endif /* else no `noexcept` */ +#endif /* SUSUWU_CXX11 else */ /* `SUSUWU_UNREACHABLE` is close to `SUSUWU_ASSUME(false)` */ #if !defined(NDEBUG_) @@ -182,16 +186,16 @@ const int macrosTestsNoexcept() SUSUWU_NOEXCEPT; #endif #ifdef SUSUWU_SH_RUNTIME_COLORS # pragma message("[Info: `-DSUSUWU_SH_RUNTIME_COLORS` is TODO; https://github.com/SwuduSusuwu/SubStack/issues/17 to contribute]") -#endif /* #elif !defined(_POSIX_VERSION) TODO */ +#endif /* #elif !defined(SUSUWU_POSIX) TODO */ #ifdef SUSUWU_SH_RUNTIME_OSC # pragma message("[Info: `-DSUSUWU_SH_RUNTIME_OSC` is TODO; https://github.com/SwuduSusuwu/SubStack/issues/17 to contribute]") -#endif /* #elif !defined(_POSIX_VERSION) TODO */ -#if !defined(_POSIX_VERSION) -# define SUSUWU_SH_COLORS_UNSUPPORTED /* assume "dumb terminals" (such as __WIN32__ or __MINGW32__ often has) if built without runtime tests for color attributes, on non-POSIX systems */ -# define SUSUWU_SH_OSC_UNSUPPORTED /* assume "dumb terminals" (such as __WIN32__ or __MINGW32__ often has) if built without runtime tests for Operating System Commands, on non-POSIX systems */ +#endif /* #elif !defined(SUSUWU_POSIX) TODO */ +#if !defined(SUSUWU_POSIX) +# define SUSUWU_SH_COLORS_UNSUPPORTED /* assume "dumb terminals" (such as SUSUWU_WIN32 often has) if built without runtime tests for color attributes, on non-POSIX systems */ +# define SUSUWU_SH_OSC_UNSUPPORTED /* assume "dumb terminals" (such as SUSUWU_WIN32 often has) if built without runtime tests for Operating System Commands, on non-POSIX systems */ #endif #if defined(SUSUWU_SH_OSC_UNSUPPORTED) && !defined(SUSUWU_SH_SKIP_OSC) -# define SUSUWU_SH_SKIP_OSC true /* you can use `-DSUSUWU_SH_SKIP_OSC=false` to force unsupported Operating System Command use (such as if build is __WIN32__ but you assume Win10+ `xterm` support) */ +# define SUSUWU_SH_SKIP_OSC true /* you can use `-DSUSUWU_SH_SKIP_OSC=false` to force unsupported Operating System Command use (such as if build is SUSUWU_WIN32 but you assume Win10+ `xterm` support) */ #endif /* SUSUWU_SH_OSC_UNSUPPORTED && !defined SUSUWU_SH_SKIP_OSC */ #ifdef SUSUWU_SH_SKIP_OSC /* `-DSUSUWU_SH_SKIP_OSC=true` to turn Operating System Commands off */ # define SUSUWU_SH_TO_CLIPBOARD_PREFIX "" @@ -203,7 +207,7 @@ const int macrosTestsNoexcept() SUSUWU_NOEXCEPT; # define SUSUWU_SH_TO_CLIPBOARD(base64_str) fprintf(stdout, SUSUWU_SH_TO_CLIPBOARD_PREFIX "%s" SUSUWU_SH_TO_CLIPBOARD_SUFFIX, IF_SUSUWU_CPLUSPLUS(std::string(base64_str).c_str(), base64_str)); /* TODO: `std::cout` version of this */ #endif /* def SUSUWU_SH_SKIP_OSC else */ #if defined(SUSUWU_SH_COLORS_UNSUPPORTED) && !defined(SUSUWU_SH_SKIP_COLORS) -# define SUSUWU_SH_SKIP_COLORS true /* you can use `-DSUSUWU_SH_SKIP_COLORS=false` to force unsupported color use (such as if build is for __WIN32__ but you assume Win10+ `xterm` support) */ +# define SUSUWU_SH_SKIP_COLORS true /* you can use `-DSUSUWU_SH_SKIP_COLORS=false` to force unsupported color use (such as if build is for SUSUWU_WIN32 but you assume Win10+ `xterm` support) */ #endif /* SUSUWU_SH_COLORS_UNSUPPORTED && !defined SUSUWU_SH_SKIP_COLORS */ # define SUSUWU_SH_BEL "\07" /* Bell sound */ # define SUSUWU_SH_ESC "\033" /* Escape */ diff --git a/cxx/VirusAnalysis.cxx b/cxx/VirusAnalysis.cxx index bcf7455d..3c8c0e23 100644 --- a/cxx/VirusAnalysis.cxx +++ b/cxx/VirusAnalysis.cxx @@ -4,7 +4,7 @@ #include "ClassCns.hxx" /* Cns CnsMode */ #include "ClassPortableExecutable.hxx" /* PortableExecutable */ #include "ClassResultList.hxx" /* size_t listMaxSize listHasValue listProduceSignature listFindSignatureOfValue ResultList resultListDumpTo resultListProduceHashes */ -#include "ClassSha2.hxx" /* sha2 */ +#include "ClassSha2.hxx" /* classSha2 */ #include "ClassSys.hxx" /* classSysArgc classSysArgs classSysHasRoot classSysHexStr classSysSetRoot execvex */ #include "Macros.hxx" /* ERROR NOTICE SUSUWU_ERRSTR SUSUWU_NOTICE SUSUWU_NOTICE_EXECUTEVERBOSE SUSUWU_SH_VERBOSE */ #include "VirusAnalysis.hxx" /* passList abortList *AnalyisCaches */ @@ -166,7 +166,7 @@ const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ign /* `clang-tidy` on: NOLINTEND(readability-implicit-bool-conversion) */ const VirusAnalysisResult virusAnalysis(const PortableExecutable &file) { - const auto fileHash = sha2(file.bytecode); + const auto fileHash = classSha2(file.bytecode); for(const auto &analysis : virusAnalyses) { switch(analysis(file, fileHash)) { case virusAnalysisPass: diff --git a/cxx/VirusAnalysis.hxx b/cxx/VirusAnalysis.hxx index fc4d9d47..15c4b463 100644 --- a/cxx/VirusAnalysis.hxx +++ b/cxx/VirusAnalysis.hxx @@ -5,7 +5,7 @@ #include "ClassCns.hxx" /* Cns CnsMode */ #include "ClassPortableExecutable.hxx" /* PortableExecutable FilePath FileBytecode */ #include "ClassResultList.hxx" /* ResultList smallestUniqueSubstr */ -#include "ClassSha2.hxx" /* sha2 */ +#include "ClassSha2.hxx" /* classSha2 */ #include "ClassSys.hxx" /* templateCatchAll */ #include "Macros.hxx" /* SUSUWU_NOEXCEPT */ #include /* std::map */ @@ -104,7 +104,7 @@ void virusAnalysisResetCaches() SUSUWU_NOEXCEPT; typedef const VirusAnalysisResult (*VirusAnalysisFun)(const PortableExecutable &file, const ResultListHash &fileHash); extern std::vector virusAnalyses; -const VirusAnalysisResult virusAnalysis(const PortableExecutable &file); /* auto hash = sha2(file.bytecode); for(VirusAnalysisFun analysis : virusAnalyses) {analysis(file, hash);} */ +const VirusAnalysisResult virusAnalysis(const PortableExecutable &file); /* auto hash = classSha2(file.bytecode); for(VirusAnalysisFun analysis : virusAnalyses) {analysis(file, hash);} */ const VirusAnalysisResult virusAnalysisRemoteAnalysis(const PortableExecutable &file, const ResultListHash &fileHash); /* TODO: compatible hosts to upload to */ const VirusAnalysisResult virusAnalysisManualReviewCacheless(const PortableExecutable &file, const ResultListHash &fileHash); /* Ask user to "Block", "Submit to remote hosts for analysis", or "Allow". */ static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file, const ResultListHash &fileHash) { @@ -115,7 +115,7 @@ static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecuta return manualReviewCaches[fileHash] = virusAnalysisManualReviewCacheless(file, fileHash); } } -static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file) { return virusAnalysisManualReview(file, sha2(file.bytecode)); } +static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file) { return virusAnalysisManualReview(file, classSha2(file.bytecode)); } /* Setup virus fix CMS, uses more resources than `produceAnalysisCns()` */ /* `abortOrNull` should map to `passOrNull` (`ResultList` is composed of `std::tuple`s, because just `produceVirusFixCns()` requires this), diff --git a/posts/VirusAnalysis.md b/posts/VirusAnalysis.md index c86b8c43..e30a2d5f 100644 --- a/posts/VirusAnalysis.md +++ b/posts/VirusAnalysis.md @@ -1,7 +1,7 @@ **Virus analysis tools should use local static analysis + sandboxes + artificial CNS (central nervous systems) to secure us** _[This post](https://swudususuwu.substack.com/p/howto-produce-better-virus-scanners) allows all uses._ -Static analysis + sandbox + CNS = 1 second (approx) analysis of **new executables** (protects all app launches,) but _caches_ reduce this to **less than 1ms** (just cost to lookup `ResultList::hashes`, which is `std::unordered_set`; a hashmap of hashes). +Static analysis + sandbox + CNS = 1 second (approx) analysis of **new executables** (protects all app launches,) but _caches_ reduce this to **less than 1ms** (just cost to lookup `ResultList::hashes`, which is `std::unordered_set`; a hashmap of hashes). `Licenses: allows all uses ("Creative Commons"/"Apache 2")` [Removed duplicate licenses, `#if` guards, `#include`s, `namespace`s, `NOLINTBEGIN`s, `NOLINTEND`s from all except `main.hxx`; follow URLs for whole sources] @@ -46,9 +46,6 @@ For the most new sources (+ static libs), use apps such as [iSH](https://apps.ap # else /* (202002 <= __cplusplus) else */ # define SUSUWU_NO_UNIQUE_ADDRESS /* No-op */ # endif /* if (202002 <= __cplusplus) */ -# if defined(SUSUWU_CXX11) || ((defined __has_cpp_attribute) && __has_cpp_attribute(noreturn)) /* TODO: [Cmake test for `\[\[noreturn\]\]`](https://stackoverflow.com/a/33517293/24473928) */ -# else /* C++11 else */ -# endif /* else no `[[noreturn]]` */ #else /* def __cplusplus */ # include /* assert static_assert */ # define IF_SUSUWU_CPLUSPLUS(TRUE, FALSE) FALSE @@ -62,16 +59,22 @@ For the most new sources (+ static libs), use apps such as [iSH](https://apps.ap #define SUSUWU_COMMA , /* to pass to macro functions whose `__VA_ARGS__` is conditional */ #define SUSUWU_PRAGMA(S) _Pragma(#S) /* `#pragma S` in macro functions is `_Pragma(S)` (but without this indirection/wrap, gives `error: _Pragma takes a parenthesized string literal`/`expected string literal in pragma message`.) Usage: `SUSUWU_PRAGMA(message("Message"))` */ -#if (!defined _POSIX_VERSION) && (defined _POSIX_C_SOURCE) -# define _POSIX_VERSION _POSIX_C_SOURCE /* "Error: ... ndef _POSIX_VERSION" fix. Now, you can just do `#ifdef _POSIX_VERSION` for POSIX code paths */ -#endif /* (!defined _POSIX_VERSION) && (defined _POSIX_C_SOURCE) */ -#if (!defined __WIN32__) && (defined _WIN32 || __MSC_VER /* || defined __CYGWIN__ (should use `#ifdef _POSIX_VERSION` path) */) -# define __WIN32__ /* https://stackoverflow.com/questions/430424/are-there-any-macros-to-determine-if-my-code-is-being-compiled-to-windows/430435#430435 says that __WIN32__ is not always defined on Windows targets */ -#endif - -#ifndef __has_feature -# define __has_feature(X) false /* `gcc` "error: missing binary operator before token \"(\"" fix */ -#endif /* ndef __has_feature */ +#if defined(_POSIX_VERSION) || defined(_POSIX_C_SOURCE) || defined(__CYGWIN__) /* Purpose: Often, `_POSIX_VERSION` is not set on POSIX targets */ +# define SUSUWU_POSIX _POSIX_VERSION /* Usage: `#ifdef SUSUWU_WIN32\n#include \n#endif` */ +#endif /* defined*_POSIX_VERSION) || defined(_POSIX_C_SOURCE) || defined(__CYGWIN__) */ +#if defined(__WIN32__) || defined(_WIN32) || defined(__MSC_VER) || defined(__MINGW32__) /* Purpose: https://stackoverflow.com/questions/430424/are-there-any-macros-to-determine-if-my-code-is-being-compiled-to-windows/430435#430435 says that __WIN32__ is not always defined on Windows targets */ +# define SUSUWU_WIN32 /* Usage: `#ifdef SUSUWU_WIN32\n#include \n#endif` */ +#endif /* defined(__WIN32__) || defined(_WIN32) || defined(__MSC_VER) || defined(__MINGW32__) */ +#if defined(__clang__) || defined(__has_feature) /* Purpose: `gcc` "error: missing binary operator before token \"(\"" fix */ +# define SUSUWU_HAS_FEATURE(X) __has_feature(x) /* Usage: `#if SUSUWU_HAS_FEATURE(cxx_noexcept)\nnoexcept\n#endif` */ +#else /* defined(__clang__) || defined(__has_feature) else */ +# define SUSUWU_HAS_FEATURE(X) false +#endif /* defined(__clang__) || defined(__has_feature) else */ +#if defined(__has_cpp_attribute) +# define SUSUWU_HAS_ATTRIBUTE(X) __has_cpp_attribute(x) /* Usage: `#if SUSUWU_HAS_ATTRIBUTE(noreturn)\nnoreturn\n#endif` */ +#else /* defined(__has_cpp_attribute) else */ +# define SUSUWU_HAS_ATTRIBUTE(X) false +#endif /* defined(__has_cpp_attribute) else */ #if defined(SUSUWU_C11) || defined(SUSUWU_CXX11) # define SUSUWU_NORETURN [[noreturn]] /* Usage: `SUSUWU_NORETURN void exit();` is close to `void exit() [[ensures:: false]];` or `exit(); SUSUWU_UNREACHABLE;` */ @@ -91,7 +94,7 @@ For the most new sources (+ static libs), use apps such as [iSH](https://apps.ap # define SUSUWU_ENSURES(X) /* `@post @code X @encode` */ #endif /* else !def USE_CONTRACTS */ -#if defined(SUSUWU_CXX11) || (defined(__clang__) && __has_feature(cxx_noexcept)) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114) /* [Other `noexcept` tests](https://stackoverflow.com/questions/18387640/how-to-deal-with-noexcept-in-visual-studio) */ +#if defined(SUSUWU_CXX11) || (defined(__clang__) && SUSUWU_HAS_FEATURE(cxx_noexcept)) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180021114) /* [Other `noexcept` tests](https://stackoverflow.com/questions/18387640/how-to-deal-with-noexcept-in-visual-studio) */ # define SUSUWU_NOEXCEPT noexcept /* Usage: `void info() SUSUWU_NOEXCEPT; ... {info();}` is close to `void versionInfo() [[ensures: true]]; ... {info();}` or `{try {versionInfo();} catch(...) {SUSUWU_UNREACHABLE;}} */ /* Usage 2: `void versionInfo() SUSUWU_NOEXCEPT(std::is_nothrow_constructible::value); {versionInfo();}` is close to `{try {versionInfo();} catch(...) {if(std::is_nothrow_constructible::value) {SUSUWU_UNREACHABLE;}}}` */ #else /* C++11 else */ @@ -190,7 +193,7 @@ const int macrosTestsNoexcept() SUSUWU_NOEXCEPT; #endif #ifdef SUSUWU_SH_RUNTIME_COLORS # pragma message("[Info: `-DSUSUWU_SH_RUNTIME_COLORS` is TODO; https://github.com/SwuduSusuwu/SubStack/issues/17 to contribute]") -#endif /* #elif !defined(_POSIX_VERSION) TODO */ +#endif /* #elif !defined(SUSUWU_POSIX) TODO */ #define SUSUWU_SH_ESC "\033" /* Escape */ #define SUSUWU_SH_CSI SUSUWU_SH_ESC "[" /* Control Sequence Introducer */ #define SUSUWU_SH_DEFAULT SUSUWU_SH_CSI "0m" @@ -350,9 +353,9 @@ static const pid_t execvexFork(const std::string &toSh) SUSUWU_NOEXCEPT {return const int execves(const std::vector &argvS = {}, const std::vector &envpS = {}); static const int execvex(const std::string &toSh) {return execves({"/bin/sh", "-c", toSh});} -/* #if _POSIX_VERSION, `return (0 == geteuid());` #elif __WIN32__ `return IsUserAnAdmin();` #endif `return false;` */ +/* #if SUSUWU_POSIX, `return (0 == geteuid());` #elif SUSUWU_WIN32 `return IsUserAnAdmin();` #endif `return false;` */ const bool classSysHasRoot(); -/* #if _POSIX_VERSION, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif +/* #if SUSUWU_POSIX, `root ? (seteuid(0) : (seteuid(getuid() || getenv("SUDO_UID")), setuid(geteuid)); return classSysHasRoot();` #endif * Usage: classSysSetRoot(true); functionsWhichRequireRoot; classSysSetRoot(false); */ const bool classSysSetRoot(bool root); /* root ? (seteuid(0) : (seteuid(getuid() || atoi(getenv("SUDO_UID"))), setuid(geteuid)); return classSysHasRoot(); */ @@ -418,7 +421,7 @@ auto templateCatchAll(Func func, const std::string &funcName, Args... args) -> c try { return func(args...); } catch (const std::exception &ex) { - SUSUWU_PRINT(ERROR, funcName + " {throw std::exception(\"" + ex.what() + "\");}"); + SUSUWU_ERROR(funcName + " {throw std::exception(\"" + ex.what() + "\");}"); return decltype(func(args...))(); /* `func(args...)`'s default return value; if `int func(args...)`, `return 0;`. If `bool func(args...)`, `return false;` */ } } @@ -443,7 +446,7 @@ const bool classSysInit(int argc, const char **args) { } const pid_t execvesFork(const std::vector &argvS, const std::vector &envpS) SUSUWU_NOEXCEPT { -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX const pid_t pid = fork(); if(0 != pid) { if(-1 == pid) { @@ -460,7 +463,7 @@ const pid_t execvesFork(const std::vector &argvS, const std::vector } argv.push_back(nullptr); if(envpS.empty()) { /* Reuse LD_PRELOAD to fix https://github.com/termux-play-store/termux-issues/issues/24 */ - execv(argv[0], &argv[0]); /* NORETURN */ + execv(argv[0], &argv[0]); /* SUSUWU_NORETURN */ } else { std::vector envpSmutable = {envpS.cbegin(), envpS.cend()}; std::vector envp; @@ -469,17 +472,17 @@ const pid_t execvesFork(const std::vector &argvS, const std::vector envp.push_back(const_cast(x.c_str())); } envp.push_back(nullptr); - execve(argv[0], &argv[0], &envp[0]); /* NORETURN */ + execve(argv[0], &argv[0], &envp[0]); /* SUSUWU_NORETURN */ } - exit(EXIT_FAILURE); /* execv*() is `NORETURN`. NOLINT(concurrency-mt-unsafe) */ -#else /* ndef _POSIX_VERSION */ -# undef ERROR /* undo `shlobj.h`'s `#define ERROR 0` */ - SUSUWU_ERROR("execvesFork: {#ifndef _POSIX_VERSION /* TODO: convert to win32 */}"); + exit(EXIT_FAILURE); /* execv*() is `SUSUWU_NORETURN`. NOLINT(concurrency-mt-unsafe) */ +#else /* ndef SUSUWU_POSIX */ +# undef ERROR /* undo `shlobj.h`'s `#define ERROR 0` */ + SUSUWU_ERROR("execvesFork: {#ifndef SUSUWU_POSIX /* TODO: convert to win32 */}"); return -1; -#endif /* ndef _POSIX_VERSION */ +#endif /* ndef SUSUWU_POSIX */ } const int execves(const std::vector &argvS, const std::vector &envpS) { -#ifdef _POSIX_VERSION +#ifdef SUSUWU_POSIX const pid_t pid = execvesFork(argvS, envpS); int wstatus = 0; if(-1 == pid) { @@ -492,65 +495,65 @@ const int execves(const std::vector &argvS, const std::vector(strtol(sudoUidStr, &sudoUidStrIt, 10)); if(sudoUidStr == sudoUidStrIt || -1 == setuid(sudoUid)) { /* prevent reescalation to root */ - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(-1 == setuid(sudoUid)) /* can't prevent reescalation to root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(-1 == setuid(sudoUid)) /* can't prevent reescalation to root */}"); } } } -# endif /* !def LINUX */ +# endif /* !def LINUX */ if(0 == sudoUid) { - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(0 == sudoUid) /* stuck as root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(0 == sudoUid) /* stuck as root */}"); } else if(-1 == seteuid(sudoUid)) { - SUSUWU_PRINT(WARNING, "classSysSetRoot(false) {(-1 == seteuid(sudoUid)) /* stuck as root */}"); + SUSUWU_WARNING("classSysSetRoot(false) {(-1 == seteuid(sudoUid)) /* stuck as root */}"); } } -/* #elif defined __WIN32__ */ //TODO: https://stackoverflow.com/questions/6418791/requesting-administrator-privileges-at-run-time says you must spawn new processes to do this +/* #elif defined SUSUWU_WIN32 */ //TODO: https://stackoverflow.com/questions/6418791/requesting-administrator-privileges-at-run-time says you must spawn new processes to do this #else - SUSUWU_PRINT(WARNING, "classSysSetRoot(bool) {#ifndef _POSIX_VERSION /* TODO */}"); -#endif /* _POSIX_VERSION */ + SUSUWU_WARNING("classSysSetRoot(bool) {#ifndef SUSUWU_POSIX /* TODO */}"); +#endif /* SUSUWU_POSIX */ return classSysHasRoot(); } @@ -584,37 +587,37 @@ const bool classSysTests() { ``` `less` [cxx/ClassSha2.hxx](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/ClassSha2.hxx) ``` -/* const */ FileHash /* 128 bits, not null-terminated */ sha1(const FileBytecode &bytecode); -/* const */ FileHash /* 256 bits, not null-terminated */ sha256(const FileBytecode &bytecode); -/* const */ FileHash /* 512 bits, not null-terminated */ sha512(const FileBytecode &bytecode); -typedef FileHash (*Sha2)(const FileBytecode &bytecode); -extern Sha2 sha2/* = sha256 */; /* To compress, apps can execute `sha2 = sha1;`. To double hash sizes, execute `sha2 = sha512;`. (Notice: this does not recompute hashes which exist) */ +/* const */ FileHash /* 128 bits, not null-terminated */ classSha1(const FileBytecode &bytecode); +/* const */ FileHash /* 256 bits, not null-terminated */ classSha256(const FileBytecode &bytecode); +/* const */ FileHash /* 512 bits, not null-terminated */ classSha512(const FileBytecode &bytecode); +typedef FileHash (*ClassSha2)(const FileBytecode &bytecode); +extern ClassSha2 classSha2/* = classSha256 */; /* To compress, apps can execute `classSha2 = classSha1;`. To double hash sizes, execute `classSha2 = classSha512;`. (Notice: this does not recompute hashes which exist) */ const bool classSha2Tests(); const bool classSha2TestsNoexcept() SUSUWU_NOEXCEPT; ``` `less` [cxx/ClassSha2.cxx](https://github.com/SwuduSusuwu/SubStack/blob/trunk/cxx/ClassSha2.cxx) ``` /* Uses https://www.rfc-editor.org/rfc/rfc6234#section-8.2.2 */ -Sha2 sha2 = sha256; -/* const */ FileHash /* 128 bits, not null-terminated */ sha1(const FileBytecode &bytecode) { +ClassSha2 classSha2 = classSha256; +/* const */ FileHash /* 128 bits, not null-terminated */ classSha1(const FileBytecode &bytecode) { FileHash result; SHA1Context context; result.resize(SHA1HashSize); - SHA1Reset(&context); /* If `undefined symbol: SHA1Reset`, affix `sha1.o` to `${LD_FLAGS}` */ + SHA1Reset(&context); /* If `undefined symbol: SHA1Reset`, affix `classSha1.o` to `${LD_FLAGS}` */ SHA1Input(&context, reinterpret_cast(&bytecode[0]), bytecode.size()); SHA1Result(&context, reinterpret_cast(&result[0])); return result; } -/* const */ FileHash /* 256 bits, not null-terminated */ sha256(const FileBytecode &bytecode) { +/* const */ FileHash /* 256 bits, not null-terminated */ classSha256(const FileBytecode &bytecode) { FileHash result; SHA256Context context; result.resize(SHA256HashSize); - SHA256Reset(&context); /* If `undefined symbol: SHA256Reset`, affix `sha224-256.o` to `${LD_FLAGS}` */ + SHA256Reset(&context); /* If `undefined symbol: SHA256Reset`, affix `classSha224-256.o` to `${LD_FLAGS}` */ SHA256Input(&context, reinterpret_cast(&bytecode[0]), bytecode.size()); SHA256Result(&context, reinterpret_cast(&result[0])); return result; } -/* const */ FileHash /* 512 bits, not null-terminated */ sha512(const FileBytecode &bytecode) { +/* const */ FileHash /* 512 bits, not null-terminated */ classSha512(const FileBytecode &bytecode) { FileHash result; SHA512Context context; result.resize(SHA512HashSize); @@ -628,24 +631,24 @@ const bool classSha2Tests() { /* is just to test glue code (which wraps rfc6234) const char nulls[65536 /* 65536 == 2^16 == 64kb */] = {0}; std::string nullStr(nulls, &nulls[65536]); const ClassSysUSeconds tsDrift = classSysUSecondClock(), ts2Drift = classSysUSecondClock() - tsDrift, ts = classSysUSecondClock(); - const FileHash hash = sha2(nullStr); + const FileHash hash = classSha2(nullStr); const ClassSysUSeconds ts2 = classSysUSecondClock() - ts2Drift; const std::string hashStrCompute = "0x" + classSysHexStr(hash); const std::string hashStrTrue = "0xde2f256064a0af797747c2b97505dc0b9f3df0de4f489eac731c23ae9ca9cc31"; if(ts == ts2) { - SUSUWU_PRINT(WARNING, "0 ms (0 μs) to compute `sha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = inf mbps"); + SUSUWU_WARNING("0 ms (0 μs) to compute `classSha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = inf mbps"); } else { - SUSUWU_INFO(std::to_string((ts2 - ts) / 1000) + " ms (" + std::to_string(ts2 - ts) + " μs) to compute `sha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = " + std::to_string(float(65536) * CHAR_BIT /* to bits */ / (ts2 - ts) /* to bpμs */ * 1000000 /* to bps */ / (1 << 20) /* to mbps */) + "mbps"); + SUSUWU_INFO(std::to_string((ts2 - ts) / 1000) + " ms (" + std::to_string(ts2 - ts) + " μs) to compute `classSha2(std::string(nulls, &nulls[65536])) == " + hashStrCompute + "` = " + std::to_string(float(65536) * CHAR_BIT /* to bits */ / (ts2 - ts) /* to bpμs */ * 1000000 /* to bps */ / (1 << 20) /* to mbps */) + "mbps"); } - SUSUWU_NOTICE("This `sha2()` is from `./build.sh --debug`: `./build.sh --release` has 2x this throughput"); + SUSUWU_NOTICE("This `classSha2()` is from `./build.sh --debug`: `./build.sh --release` has 2x this throughput"); if(0 == hash.size()) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`0 == sha2(std::string()).size();")); - } else if(hashStrTrue.size() != hashStrCompute.size() && sha256 == sha2) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`sha2 = sha256;`, but `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`")); + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`0 == classSha2(std::string()).size();")); + } else if(hashStrTrue.size() != hashStrCompute.size() && classSha256 == classSha2) { + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "`classSha2 = classSha256;`, but `(" + std::to_string(hash.size()) + " == classSha2(std::string()).size())`")); } else if(hashStrTrue.size() != hashStrCompute.size()) { - SUSUWU_INFO("`(sha256 != sha2)`, `(" + std::to_string(hash.size()) + " == sha2(std::string()).size())`"); + SUSUWU_INFO("`(classSha256 != classSha2)`, `(" + std::to_string(hash.size()) + " == classSha2(std::string()).size())`"); } else if(hashStrTrue != hashStrCompute) { - throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "sha2(char nulls[65535] = {0}) did not compute " + hashStrTrue)); + throw std::runtime_error(SUSUWU_ERRSTR(ERROR, "classSha2(char nulls[65535] = {0}) did not compute " + hashStrTrue)); } return true; } @@ -726,7 +729,7 @@ template * @post @code !hashes.empty() @endcode */ void listToHashes(const List &list /* ResultList::bytecodes or ResultList::hex*/, List2 &hashes /* ResultList::hashess */) { for(const auto &value : list) { - hashes.insert(sha2(value)); + hashes.insert(classSha2(value)); } } /* Usage: if `ResultList` was not produced with `.hashes` */ @@ -970,7 +973,7 @@ typedef class ApxrCns : Cns { #include /* Sources: `pkg install python` */ typedef class HsomCns : Cns { /* TODO. ( https://stackoverflow.com/questions/3286448/calling-a-python-method-from-c-c-and-extracting-its-return-value ) suggests various syntaxes to use for this, with unanswered comments such as "Does this support classes?" */ //template void setupSynapses(const std::vector>) { /* TODO: templates not allowed for virtual functions with C++ ( https://stackoverflow.com/a/78440416/24473928 ), so must produce codes for each combination of inputMode+outputMode */ - void setupSynapses(const std::vector>) { + void setupSynapses(const std::vector>) override { setenv("PYTHONPATH",".",1); Py_Initialize(); // PyRun_SimpleString("import sys; sys.path.append('.')"); PyRun_SimpleString("import hsom; from hsom import SelfOrganizingNetwork;"); @@ -1135,7 +1138,7 @@ void virusAnalysisResetCaches() SUSUWU_NOEXCEPT; typedef const VirusAnalysisResult (*VirusAnalysisFun)(const PortableExecutable &file, const ResultListHash &fileHash); extern std::vector virusAnalyses; -const VirusAnalysisResult virusAnalysis(const PortableExecutable &file); /* auto hash = sha2(file.bytecode); for(VirusAnalysisFun analysis : virusAnalyses) {analysis(file, hash);} */ +const VirusAnalysisResult virusAnalysis(const PortableExecutable &file); /* auto hash = classSha2(file.bytecode); for(VirusAnalysisFun analysis : virusAnalyses) {analysis(file, hash);} */ const VirusAnalysisResult virusAnalysisRemoteAnalysis(const PortableExecutable &file, const ResultListHash &fileHash); /* TODO: compatible hosts to upload to */ const VirusAnalysisResult virusAnalysisManualReviewCacheless(const PortableExecutable &file, const ResultListHash &fileHash); /* Ask user to "Block", "Submit to remote hosts for analysis", or "Allow". */ static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file, const ResultListHash &fileHash) { @@ -1146,7 +1149,7 @@ static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecuta return manualReviewCaches[fileHash] = virusAnalysisManualReviewCacheless(file, fileHash); } } -static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file) { return virusAnalysisManualReview(file, sha2(file.bytecode)); } +static const VirusAnalysisResult virusAnalysisManualReview(const PortableExecutable &file) { return virusAnalysisManualReview(file, classSha2(file.bytecode)); } /* Setup virus fix CMS, uses more resources than `produceAnalysisCns()` */ /* `abortOrNull` should map to `passOrNull` (`ResultList` is composed of `std::tuple`s, because just `produceVirusFixCns()` requires this), @@ -1308,7 +1311,7 @@ const VirusAnalysisHook virusAnalysisHook(VirusAnalysisHook hookStatus) { /* Ign } const VirusAnalysisResult virusAnalysis(const PortableExecutable &file) { - const auto fileHash = sha2(file.bytecode); + const auto fileHash = classSha2(file.bytecode); for(const auto &analysis : virusAnalyses) { switch(analysis(file, fileHash)) { case virusAnalysisPass: @@ -1638,14 +1641,14 @@ For comparison; `produceVirusFixCns` is close to assistants (such as "ChatGPT 4. extern Cns assistantCns; extern std::string assistantCnsResponseDelimiter; -/* if (with example inputs) these functions (`questionsResponsesFromHosts()` `produceAssistantCns()`) pass, `return true;` +/* if (with example inputs) these functions (`assistantCnsDownloadHosts()` `produceAssistantCns()`) pass, `return true;` * @throw std::bad_alloc * @throw std::logic_error * @pre @code assistantCns.hasImplementation() @endcode */ const bool assistantCnsTests(); static const bool assistantCnsTestsNoexcept() SUSUWU_NOEXCEPT {return templateCatchAll(assistantCnsTests, "assistantCnsTests()");} -/* Universal Resources Locators of hosts which `questionsResponsesFromHosts()` uses +/* Universal Resources Locators of hosts which `assistantCnsDownloadHosts()` uses * Wikipedia is a special case; has compressed downloads of databases ( https://wikipedia.org/wiki/Wikipedia:Database_download ) * Github is a special case; has compressed downloads of repositories ( https://docs.github.com/en/get-started/start-your-journey/downloading-files-from-github ) */ @@ -1655,9 +1658,9 @@ extern std::vector assistantCnsDefaultHosts; * @post If no question, `0 == questionsOrNull.bytecodes[x].size()` (new synthesis). * If no responses, `0 == responsesOrNull.bytecodes[x].size()` (ignore). * `questionsOrNull.signatures[x] = Universal Resource Locator` - * @code sha2(ResultList.bytecodes[x]) == ResultList.hashes[x] @endcode */ -void questionsResponsesFromHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts = assistantCnsDefaultHosts); -void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &filepath = "index.xhtml"); + * @code classSha2(ResultList.bytecodes[x]) == ResultList.hashes[x] @endcode */ +void assistantCnsDownloadHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts = assistantCnsDefaultHosts); +void assistantCnsProcessXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &filepath = "index.xhtml"); const std::vector ParseUrls(const FilePath &filepath = "index.xhtml"); /* TODO: for XML/XHTML could just use [ https://www.boost.io/libraries/regex/ https://github.com/boostorg/regex ] or [ https://www.boost.org/doc/libs/1_85_0/doc/html/property_tree/parsers.html#property_tree.parsers.xml_parser https://github.com/boostorg/property_tree/blob/develop/doc/xml_parser.qbk ] */ const FileBytecode ParseQuestion(const FilePath &filepath = "index.xhtml"); /* TODO: regex or XML parser */ const std::vector ParseResponses(const FilePath &filepath = "index.xhtml"); /* TODO: regex or XML parser */ @@ -1711,7 +1714,7 @@ const bool assistantCnsTests() { assert(3 == responsesOrNull.hashes.size()); SUSUWU_NOTICE_EXECUTEVERBOSE(resultListDumpTo(questionsOrNull, std::cout, true, true, false)); SUSUWU_NOTICE_EXECUTEVERBOSE((resultListDumpTo(responsesOrNull, std::cout, false, false, false), std::cout << std::endl)); - questionsResponsesFromHosts(questionsOrNull, responsesOrNull); + assistantCnsDownloadHosts(questionsOrNull, responsesOrNull); produceAssistantCns(questionsOrNull, responsesOrNull, assistantCns); return true; } @@ -1731,22 +1734,22 @@ void produceAssistantCns(const ResultList &questionsOrNull, const ResultList &re cns.setupSynapses(inputsToOutputs); } -void questionsResponsesFromHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts) { +void assistantCnsDownloadHosts(ResultList &questionsOrNull, ResultList &responsesOrNull, const std::vector &hosts) { for(const auto &host : hosts) { execvex("wget '" + host + "/robots.txt' -Orobots.txt"); execvex("wget '" + host + "' -Oindex.xhtml"); questionsOrNull.signatures.push_back(host); - questionsResponsesFromXhtml(questionsOrNull, responsesOrNull, "index.xhtml"); + assistantCnsProcessXhtml(questionsOrNull, responsesOrNull, "index.xhtml"); } } -void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml) { - auto noRobots = assistantParseUrls("robots.txt"); - auto question = assistantParseQuestion(localXhtml); +void assistantCnsProcessXhtml(ResultList &questionsOrNull, ResultList &responsesOrNull, const FilePath &localXhtml) { + auto noRobots = assistantCnsProcessUrls("robots.txt"); + auto question = assistantCnsProcessQuestion(localXhtml); if(!question.empty()) { - auto questionSha2 = sha2(question); + auto questionSha2 = classSha2(question); if(listHasValue(questionsOrNull.hashes, questionSha2)) { /* TODO */ } else { decltype(question) response = ""; - auto responses = assistantParseResponses(localXhtml); + auto responses = assistantCnsProcessResponses(localXhtml); if(!responses.empty()) { questionsOrNull.hashes.insert(questionSha2); questionsOrNull.bytecodes.push_back(question); @@ -1757,7 +1760,7 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon } response += responseIt; } - auto responseSha2 = sha2(response); + auto responseSha2 = classSha2(response); if(listHasValue(responsesOrNull.hashes, responseSha2)) { /* TODO */ } else { responsesOrNull.hashes.insert(responseSha2); responsesOrNull.bytecodes.push_back(response); @@ -1765,12 +1768,12 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon } } } - auto urls = assistantParseUrls(localXhtml); + auto urls = assistantCnsProcessUrls(localXhtml); for(const auto &url : urls) { if(!listHasValue(questionsOrNull.signatures, url) && !listHasValue(noRobots, url)) { execvex("wget '" + url + "' -O" + localXhtml); questionsOrNull.signatures.push_back(url); - questionsResponsesFromXhtml(questionsOrNull, responsesOrNull, localXhtml); + assistantCnsProcessXhtml(questionsOrNull, responsesOrNull, localXhtml); } } } @@ -1778,7 +1781,7 @@ void questionsResponsesFromXhtml(ResultList &questionsOrNull, ResultList &respon #include #include #endif /* BOOST_VERSION */ -const std::vector assistantParseUrls(const FilePath &localXhtml) { +const std::vector assistantCnsProcessUrls(const FilePath &localXhtml) { const std::vector urls; #ifdef BOOST_VERSION boost::property_tree::ptree pt; @@ -1788,12 +1791,12 @@ const std::vector assistantParseUrls(const FilePath &localXhtml) { pt.get_child("html.a href")) urls.push_back(v.second.data()); #else /* else !BOOST_VERSION */ -# pragma message("TODO: process XHTML without Boost") +# pragma message("TODO: process XHTML without Boost") #endif /* else !BOOST_VERSION */ return urls; } -const FileBytecode assistantParseQuestion(const FilePath &localXhtml) {return "";} /* TODO */ -const std::vector assistantParseResponses(const FilePath &localXhtml) {return {};} /* TODO */ +const FileBytecode assistantCnsProcessQuestion(const FilePath &localXhtml) {return "";} /* TODO */ +const std::vector assistantCnsProcessResponses(const FilePath &localXhtml) {return {};} /* TODO */ const std::string assistantCnsProcess(const Cns &cns, const FileBytecode &bytecode) { return cns.processToString(bytecode);