diff options
author | Saturneric <[email protected]> | 2021-09-12 13:56:18 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-09-12 13:56:18 +0000 |
commit | 5874147d9ec0f94a5058241a06c69f586b766a3b (patch) | |
tree | 9da52dd2d97af42952e17e570a630ee6e4aa008e | |
parent | Add clang-related branch coverage options. (diff) | |
download | GpgFrontend-5874147d9ec0f94a5058241a06c69f586b766a3b.tar.gz GpgFrontend-5874147d9ec0f94a5058241a06c69f586b766a3b.zip |
Continue to write core test code.
Diffstat (limited to '')
-rw-r--r-- | .clang-format | 168 | ||||
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/gpg/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/gpg/GpgConstants.cpp | 98 | ||||
-rw-r--r-- | src/gpg/GpgConstants.h | 53 | ||||
-rw-r--r-- | src/gpg/GpgContext.cpp | 11 | ||||
-rw-r--r-- | src/gpg/GpgInfo.h | 8 | ||||
-rw-r--r-- | src/gpg/function/GpgCommandExecutor.cpp | 7 | ||||
-rw-r--r-- | src/gpg/function/GpgFileOpera.cpp | 104 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyGetter.cpp | 27 | ||||
-rw-r--r-- | src/gpg/model/GpgKey.h | 51 | ||||
-rw-r--r-- | test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | test/GpgCoreTest.cpp | 118 | ||||
-rw-r--r-- | test/conf/core.cfg | 10 | ||||
-rw-r--r-- | third_party/CMakeLists.txt | 4 | ||||
-rw-r--r-- | third_party/easyloggingpp/CMakeLists.txt | 3 |
16 files changed, 502 insertions, 187 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..f3111e6b --- /dev/null +++ b/.clang-format @@ -0,0 +1,168 @@ +--- +Language: Cpp +# BasedOnStyle: Chromium +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^<ext/.*\.h>' + Priority: 2 + SortPriority: 0 + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + - Regex: '.*' + Priority: 3 + SortPriority: 0 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +... + diff --git a/CMakeLists.txt b/CMakeLists.txt index fab92efb..56548f06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "Using Complier Msvc") endif() -# Using Standard CXX-20 -set(CMAKE_CXX_STANDARD 20) +# Using Standard C++-17 (Consider compatibility) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -198,7 +198,7 @@ find_package(Boost COMPONENTS date_time filesystem REQUIRED) # Basic Envirnoment Configure set(BASIC_ENV_CONFIG 1) set(QT_MOC_CONFIG 1) -set(ESAY_LOGGING_CPP 1) +set(ESAY_LOGGING_PP 1) if(FULL_APPLICATION_BUILD) message(STATUS "Build Full Application") diff --git a/src/gpg/CMakeLists.txt b/src/gpg/CMakeLists.txt index 9c32761a..e74ba86f 100644 --- a/src/gpg/CMakeLists.txt +++ b/src/gpg/CMakeLists.txt @@ -9,27 +9,29 @@ set(UTILS_DIR ${CMAKE_SOURCE_DIR}/utils) set(GPGME_LIB_DIR ${UTILS_DIR}/gpgme/lib) -if(ESAY_LOGGING_CPP) - message(STATUS "Link ESAY_LOGGING_CPP") - set(THIRD_PARTY_LIBS easy_logging_cpp) +if(ESAY_LOGGING_PP) + message(STATUS "Link ESAY_LOGGING_PP") + set(THIRD_PARTY_LIBS easy_logging_pp config++) endif() +set(BOOST_LIBS Boost::date_time Boost::filesystem) + message(STATUS "Third Party Libraries " ${THIRD_PARTY_LIBS}) if (MINGW) message(STATUS "Link GPG Static Library For MINGW") target_link_libraries(gpg_core ${THIRD_PARTY_LIBS} - Boost::date_time + ${BOOST_LIBS} gpgme gpg-error assuan wsock32) elseif(APPLE) message(STATUS "Link GPG Static Library For macOS") target_link_libraries(gpg_core ${THIRD_PARTY_LIBS} - Boost::date_time - libgpgme.a libgpg-error.a libassuan.a) + ${BOOST_LIBS} + libgpgme.a libgpg-error.a libassuan.a dl) else() message(STATUS "Link GPG Static Library For Unix") target_link_libraries(gpg_core ${THIRD_PARTY_LIBS} libgpgme.a libgpg-error.a libassuan.a - Boost::date_time - pthread) + ${BOOST_LIBS} + pthread dl) endif() diff --git a/src/gpg/GpgConstants.cpp b/src/gpg/GpgConstants.cpp index 2ba04ed2..8090a261 100644 --- a/src/gpg/GpgConstants.cpp +++ b/src/gpg/GpgConstants.cpp @@ -23,21 +23,24 @@ */ #include "gpg/GpgConstants.h" + #include <gpg-error.h> +#include <boost/algorithm/string/predicate.hpp> +#include <filesystem> -const char *GpgFrontend::GpgConstants::PGP_CRYPT_BEGIN = +const char* GpgFrontend::GpgConstants::PGP_CRYPT_BEGIN = "-----BEGIN PGP MESSAGE-----"; -const char *GpgFrontend::GpgConstants::PGP_CRYPT_END = +const char* GpgFrontend::GpgConstants::PGP_CRYPT_END = "-----END PGP MESSAGE-----"; -const char *GpgFrontend::GpgConstants::PGP_SIGNED_BEGIN = +const char* GpgFrontend::GpgConstants::PGP_SIGNED_BEGIN = "-----BEGIN PGP SIGNED MESSAGE-----"; -const char *GpgFrontend::GpgConstants::PGP_SIGNED_END = +const char* GpgFrontend::GpgConstants::PGP_SIGNED_END = "-----END PGP SIGNATURE-----"; -const char *GpgFrontend::GpgConstants::PGP_SIGNATURE_BEGIN = +const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_BEGIN = "-----BEGIN PGP SIGNATURE-----"; -const char *GpgFrontend::GpgConstants::PGP_SIGNATURE_END = +const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_END = "-----END PGP SIGNATURE-----"; -const char *GpgFrontend::GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD = +const char* GpgFrontend::GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD = "GpgF_Scpt://"; gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) { @@ -49,9 +52,10 @@ gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) { return err; } -gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err) { +gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err, + gpgme_error_t predict) { auto err_code = gpg_err_code(err); - if (err_code != GPG_ERR_NO_ERROR) { + if (err_code != predict) { LOG(ERROR) << "[Error " << gpg_err_code(err) << "] Source: " << gpgme_strsource(err) << " Description: " << gpgme_strerror(err); @@ -61,18 +65,17 @@ gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err) { // error-handling gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err, - const std::string &comment) { + const std::string& comment) { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { LOG(ERROR) << "[Error " << gpg_err_code(err) << "] Source: " << gpgme_strsource(err) - << " Description: " << gpgme_strerror(err) << " " - << comment.c_str(); + << " Description: " << gpgme_strerror(err) << " " << comment; } return err; } -std::string -GpgFrontend::beautify_fingerprint(GpgFrontend::BypeArrayRef fingerprint) { +std::string GpgFrontend::beautify_fingerprint( + GpgFrontend::BypeArrayRef fingerprint) { uint len = fingerprint.size(); if ((len > 0) && (len % 4 == 0)) for (uint n = 0; 4 * (n + 1) < len; ++n) @@ -81,14 +84,14 @@ GpgFrontend::beautify_fingerprint(GpgFrontend::BypeArrayRef fingerprint) { } // trim from start (in place) -static inline void ltrim(std::string &s) { +static inline void ltrim(std::string& s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); } // trim from end (in place) -static inline void rtrim(std::string &s) { +static inline void rtrim(std::string& s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }) .base(), @@ -96,12 +99,64 @@ static inline void rtrim(std::string &s) { } // trim from both ends (in place) -static inline std::string trim(std::string &s) { +static inline std::string trim(std::string& s) { ltrim(s); rtrim(s); return s; } +std::string GpgFrontend::read_all_data_in_file(const std::string& path) { + using namespace std::filesystem; + class path file_info(path.c_str()); + + if (!exists(file_info) || !is_regular_file(path)) + throw std::runtime_error("no permission"); + + std::ifstream in_file; + in_file.open(path, std::ios::in); + if (!in_file.good()) + throw std::runtime_error("cannot open file"); + std::istreambuf_iterator<char> begin(in_file); + std::istreambuf_iterator<char> end; + std::string in_buffer(begin, end); + in_file.close(); + return in_buffer; +} + +void GpgFrontend::write_buffer_to_file(const std::string& path, + const std::string& out_buffer) { + std::ofstream out_file(path); + out_file.open(path.c_str(), std::ios::out); + if (!out_file.good()) + throw std::runtime_error("cannot open file"); + out_file.write(out_buffer.c_str(), out_buffer.size()); + out_file.close(); +} + +std::string GpgFrontend::get_file_extension(const std::string& path) { + // Create a Path object from given string + std::filesystem::path path_obj(path); + // Check if file name in the path object has extension + if (path_obj.has_extension()) { + // Fetch the extension from path object and return + return path_obj.extension().string(); + } + // In case of no extension return empty string + return std::string(); +} + +std::string get_file_name_with_path(const std::string& path) { + // Create a Path object from given string + std::filesystem::path path_obj(path); + // Check if file name in the path object has extension + if (path_obj.has_filename()) { + // Fetch the extension from path object and return + return path_obj.parent_path() / path_obj.filename(); + } + // In case of no extension return empty string + throw std::runtime_error("invalid file path"); +} + /* * isSigned returns: * - 0, if text isn't signed at all @@ -109,13 +164,16 @@ static inline std::string trim(std::string &s) { * - 2, if text is completly signed */ int GpgFrontend::text_is_signed(GpgFrontend::BypeArrayRef text) { - if (trim(text).starts_with(GpgConstants::PGP_SIGNED_BEGIN) && - trim(text).ends_with(GpgConstants::PGP_SIGNED_END)) + using boost::algorithm::ends_with; + using boost::algorithm::starts_with; + + auto trim_text = trim(text); + if (starts_with(trim_text, GpgConstants::PGP_SIGNED_BEGIN) && + ends_with(trim_text, GpgConstants::PGP_SIGNED_END)) return 2; else if (text.find(GpgConstants::PGP_SIGNED_BEGIN) != std::string::npos && text.find(GpgConstants::PGP_SIGNED_END) != std::string::npos) return 1; - else return 0; } diff --git a/src/gpg/GpgConstants.h b/src/gpg/GpgConstants.h index e82810b0..f891151f 100644 --- a/src/gpg/GpgConstants.h +++ b/src/gpg/GpgConstants.h @@ -30,11 +30,13 @@ #include <functional> #include <assert.h> +#include <gpg-error.h> #include <gpgme.h> #include <memory> #include <string> #include <easyloggingpp/easylogging++.h> +#include <libconfig.h++> const int RESTART_CODE = 1000; @@ -42,50 +44,61 @@ namespace GpgFrontend { using BypeArrayPtr = std::unique_ptr<std::string>; using StdBypeArrayPtr = std::unique_ptr<std::string>; -using BypeArrayRef = std::string &; +using BypeArrayRef = std::string&; using StringArgsPtr = std::unique_ptr<std::vector<std::string>>; -using StringArgsRef = std::vector<std::string> &; +using StringArgsRef = std::vector<std::string>&; using GpgError = gpgme_error_t; // Result -struct __result_ref_deletor { - void operator()(void *_result) { +struct _result_ref_deletor { + void operator()(void* _result) { if (_result != nullptr) gpgme_result_unref(_result); } }; using GpgEncrResult = - std::unique_ptr<struct _gpgme_op_encrypt_result, __result_ref_deletor>; + std::unique_ptr<struct _gpgme_op_encrypt_result, _result_ref_deletor>; using GpgDecrResult = - std::unique_ptr<struct _gpgme_op_decrypt_result, __result_ref_deletor>; + std::unique_ptr<struct _gpgme_op_decrypt_result, _result_ref_deletor>; using GpgSignResult = - std::unique_ptr<struct _gpgme_op_sign_result, __result_ref_deletor>; + std::unique_ptr<struct _gpgme_op_sign_result, _result_ref_deletor>; using GpgVerifyResult = - std::unique_ptr<struct _gpgme_op_verify_result, __result_ref_deletor>; + std::unique_ptr<struct _gpgme_op_verify_result, _result_ref_deletor>; // Error Info Printer GpgError check_gpg_error(GpgError err); -GpgError check_gpg_error(GpgError gpgmeError, const std::string &comment); -gpg_err_code_t check_gpg_error_2_err_code(gpgme_error_t err); +GpgError check_gpg_error(GpgError gpgmeError, const std::string& comment); +gpg_err_code_t check_gpg_error_2_err_code( + gpgme_error_t err, + gpgme_error_t predict = GPG_ERR_NO_ERROR); // Fingerprint std::string beautify_fingerprint(BypeArrayRef fingerprint); +// File Operation +std::string read_all_data_in_file(const std::string& path); +void write_buffer_to_file(const std::string& path, + const std::string& out_buffer); + +std::string get_file_extension(const std::string& path); +std::string get_file_extension(const std::string& path); +std::string get_file_name_with_path(const std::string& path); + // Check int text_is_signed(BypeArrayRef text); class GpgConstants { -public: - static const char *PGP_CRYPT_BEGIN; - static const char *PGP_CRYPT_END; - static const char *PGP_SIGNED_BEGIN; - static const char *PGP_SIGNED_END; - static const char *PGP_SIGNATURE_BEGIN; - static const char *PGP_SIGNATURE_END; - static const char *GPG_FRONTEND_SHORT_CRYPTO_HEAD; + public: + static const char* PGP_CRYPT_BEGIN; + static const char* PGP_CRYPT_END; + static const char* PGP_SIGNED_BEGIN; + static const char* PGP_SIGNED_END; + static const char* PGP_SIGNATURE_BEGIN; + static const char* PGP_SIGNATURE_END; + static const char* GPG_FRONTEND_SHORT_CRYPTO_HEAD; }; -} // namespace GpgFrontend +} // namespace GpgFrontend -#endif // GPG_CONSTANTS_H +#endif // GPG_CONSTANTS_H diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index db670938..a8c9a6de 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -31,7 +31,7 @@ #include <windows.h> #endif -#define INT2VOIDP(i) (void *)(uintptr_t)(i) +#define INT2VOIDP(i) (void*)(uintptr_t)(i) namespace GpgFrontend { @@ -40,7 +40,6 @@ namespace GpgFrontend { * Set up gpgme-context, set paths to app-run path */ GpgContext::GpgContext() { - static bool _first = true; if (_first) { @@ -76,7 +75,7 @@ GpgContext::GpgContext() { find_gpgconf = true; if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) - find_openpgp = true, info.appPath = engineInfo->file_name; + find_openpgp = true, info.AppPath = engineInfo->file_name; if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0) find_cms = true; @@ -107,7 +106,9 @@ GpgContext::GpgContext() { } } -bool GpgContext::good() const { return good_; } +bool GpgContext::good() const { + return good_; +} void GpgContext::SetPassphraseCb(decltype(test_passphrase_cb) cb) const { gpgme_set_passphrase_cb(*this, cb, nullptr); @@ -117,4 +118,4 @@ std::string GpgContext::getGpgmeVersion() { return {gpgme_check_version(nullptr)}; } -} // namespace GpgFrontend
\ No newline at end of file +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/gpg/GpgInfo.h b/src/gpg/GpgInfo.h index 4c82897f..dbcf3b40 100644 --- a/src/gpg/GpgInfo.h +++ b/src/gpg/GpgInfo.h @@ -31,11 +31,13 @@ * Use to record some info about gnupg */ class GpgInfo { -public: + public: /** * executable binary path of gnupg */ - std::string appPath; + std::string AppPath; + + std::string DatabasePath; }; -#endif // GPGFRONTEND_ZH_CN_TS_GPGINFO_H +#endif // GPGFRONTEND_ZH_CN_TS_GPGINFO_H diff --git a/src/gpg/function/GpgCommandExecutor.cpp b/src/gpg/function/GpgCommandExecutor.cpp index b5e6ccae..efe1446f 100644 --- a/src/gpg/function/GpgCommandExecutor.cpp +++ b/src/gpg/function/GpgCommandExecutor.cpp @@ -29,8 +29,7 @@ using boost::process::async_pipe; void GpgFrontend::GpgCommandExecutor::Execute( StringArgsRef arguments, - const std::function<void(async_pipe &in, async_pipe &out)> &interact_func) { - + const std::function<void(async_pipe& in, async_pipe& out)>& interact_func) { using namespace boost::process; boost::asio::io_service ios; @@ -40,12 +39,12 @@ void GpgFrontend::GpgCommandExecutor::Execute( async_pipe in_pipe_stream(ios); async_pipe out_pipe_stream(ios); - child child_process(ctx.GetInfo().appPath.c_str(), arguments, + child child_process(ctx.GetInfo().AppPath.c_str(), arguments, std_out > in_pipe_stream, std_in < out_pipe_stream); boost::asio::async_read( in_pipe_stream, boost::asio::buffer(buf), - [&](const boost::system::error_code &ec, std::size_t size) { + [&](const boost::system::error_code& ec, std::size_t size) { interact_func(in_pipe_stream, out_pipe_stream); }); diff --git a/src/gpg/function/GpgFileOpera.cpp b/src/gpg/function/GpgFileOpera.cpp index 71e60f76..79214d2d 100644 --- a/src/gpg/function/GpgFileOpera.cpp +++ b/src/gpg/function/GpgFileOpera.cpp @@ -26,42 +26,15 @@ #include "gpg/function/BasicOperator.h" #include <boost/process/detail/config.hpp> -#include <filesystem> + #include <iterator> #include <memory> #include <string> -std::string read_all_data_in_file(const std::string &path) { - using namespace std::filesystem; - class path file_info(path.c_str()); - - if (!exists(file_info) || !is_regular_file(path)) - throw std::runtime_error("no permission"); - - std::ifstream in_file; - in_file.open(path, std::ios::in); - if (!in_file.good()) - throw std::runtime_error("cannot open file"); - std::istreambuf_iterator<char> begin(in_file); - std::istreambuf_iterator<char> end; - std::string in_buffer(begin, end); - in_file.close(); - return in_buffer; -} - -void write_buufer_to_file(const std::string &path, - const std::string &out_buffer) { - std::ofstream out_file(path); - out_file.open(path.c_str(), std::ios::out); - if (!out_file.good()) - throw std::runtime_error("cannot open file"); - out_file.write(out_buffer.c_str(), out_buffer.size()); - out_file.close(); -} - GpgFrontend::GpgError GpgFrontend::GpgFileOpera::EncryptFile( - KeyArgsList &keys, const std::string &path, GpgEncrResult &result) { - + KeyArgsList& keys, + const std::string& path, + GpgEncrResult& result) { std::string in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> out_buffer; @@ -70,38 +43,13 @@ GpgFrontend::GpgError GpgFrontend::GpgFileOpera::EncryptFile( assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - write_buufer_to_file(path + ".asc", *out_buffer); + write_buffer_to_file(path + ".asc", *out_buffer); return err; } -std::string get_file_extension(const std::string &path) { - // Create a Path object from given string - std::filesystem::path path_obj(path); - // Check if file name in the path object has extension - if (path_obj.has_extension()) { - // Fetch the extension from path object and return - return path_obj.extension().string(); - } - // In case of no extension return empty string - return std::string(); -} - -std::string get_file_name_with_path(const std::string &path) { - // Create a Path object from given string - std::filesystem::path path_obj(path); - // Check if file name in the path object has extension - if (path_obj.has_filename()) { - // Fetch the extension from path object and return - return path_obj.parent_path() / path_obj.filename(); - } - // In case of no extension return empty string - throw std::runtime_error("invalid file path"); -} - -GpgFrontend::GpgError -GpgFrontend::GpgFileOpera::DecryptFile(const std::string &path, - GpgDecrResult &result) { - +GpgFrontend::GpgError GpgFrontend::GpgFileOpera::DecryptFile( + const std::string& path, + GpgDecrResult& result) { std::string in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> out_buffer; @@ -116,15 +64,14 @@ GpgFrontend::GpgFileOpera::DecryptFile(const std::string &path, if (!(file_extension == ".asc" || file_extension == ".gpg")) out_file_name += ".out"; - write_buufer_to_file(out_file_name, *out_buffer); + write_buffer_to_file(out_file_name, *out_buffer); return err; } -gpgme_error_t GpgFrontend::GpgFileOpera::SignFile(KeyArgsList &keys, - const std::string &path, - GpgSignResult &result) { - +gpgme_error_t GpgFrontend::GpgFileOpera::SignFile(KeyArgsList& keys, + const std::string& path, + GpgSignResult& result) { auto in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> out_buffer; @@ -133,14 +80,13 @@ gpgme_error_t GpgFrontend::GpgFileOpera::SignFile(KeyArgsList &keys, assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - write_buufer_to_file(path + ".sig", *out_buffer); + write_buffer_to_file(path + ".sig", *out_buffer); return err; } -gpgme_error_t GpgFrontend::GpgFileOpera::VerifyFile(const std::string &path, - GpgVerifyResult &result) { - +gpgme_error_t GpgFrontend::GpgFileOpera::VerifyFile(const std::string& path, + GpgVerifyResult& result) { auto in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> sign_buffer = nullptr; @@ -162,9 +108,10 @@ gpgme_error_t GpgFrontend::GpgFileOpera::VerifyFile(const std::string &path, // TODO gpg_error_t GpgFrontend::GpgFileOpera::EncryptSignFile( - KeyArgsList &keys, const std::string &path, GpgEncrResult &encr_res, - GpgSignResult &sign_res) { - + KeyArgsList& keys, + const std::string& path, + GpgEncrResult& encr_res, + GpgSignResult& sign_res) { auto in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> out_buffer = nullptr; @@ -177,16 +124,15 @@ gpg_error_t GpgFrontend::GpgFileOpera::EncryptSignFile( assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - write_buufer_to_file(path + ".gpg", *out_buffer); + write_buffer_to_file(path + ".gpg", *out_buffer); return err; } -gpg_error_t -GpgFrontend::GpgFileOpera::DecryptVerifyFile(const std::string &path, - GpgDecrResult &decr_res, - GpgVerifyResult &verify_res) { - +gpg_error_t GpgFrontend::GpgFileOpera::DecryptVerifyFile( + const std::string& path, + GpgDecrResult& decr_res, + GpgVerifyResult& verify_res) { auto in_buffer = read_all_data_in_file(path); std::unique_ptr<std::string> out_buffer = nullptr; @@ -200,7 +146,7 @@ GpgFrontend::GpgFileOpera::DecryptVerifyFile(const std::string &path, if (!(file_extension == ".asc" || file_extension == ".gpg")) out_file_name = path + ".out"; - write_buufer_to_file(out_file_name, *out_buffer); + write_buffer_to_file(out_file_name, *out_buffer); return err; } diff --git a/src/gpg/function/GpgKeyGetter.cpp b/src/gpg/function/GpgKeyGetter.cpp index 88f80fbf..6d80088a 100644 --- a/src/gpg/function/GpgKeyGetter.cpp +++ b/src/gpg/function/GpgKeyGetter.cpp @@ -23,49 +23,50 @@ */ #include "gpg/function/GpgKeyGetter.h" +#include <gpg-error.h> +#include "GpgConstants.h" -GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string &fpr) { - LOG(INFO) << "GpgKeyGetter GetKey Fpr " << fpr; +GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) { + DLOG(INFO) << "GpgKeyGetter GetKey Fpr " << fpr; gpgme_key_t _p_key; gpgme_get_key(ctx, fpr.c_str(), &_p_key, 1); if (_p_key == nullptr) - LOG(WARNING) << "GpgKeyGetter GetKey _p_key Null"; + DLOG(WARNING) << "GpgKeyGetter GetKey _p_key Null"; return GpgKey(std::move(_p_key)); } -GpgFrontend::GpgKey -GpgFrontend::GpgKeyGetter::GetPubkey(const std::string &fpr) { +GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey( + const std::string& fpr) { gpgme_key_t _p_key; gpgme_get_key(ctx, fpr.c_str(), &_p_key, 0); return GpgKey(std::move(_p_key)); } GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::FetchKey() { - gpgme_error_t err; - LOG(INFO) << "Clear List and Map"; + DLOG(INFO) << "Clear List and Map"; KeyListPtr keys_list = std::make_unique<std::vector<GpgKey>>(); - LOG(INFO) << "Operate KeyList Start"; + DLOG(INFO) << "Operate KeyList Start"; err = gpgme_op_keylist_start(ctx, nullptr, 0); - assert(gpg_err_code(err) != GPG_ERR_NO_ERROR); + assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - LOG(INFO) << "Start Loop"; + DLOG(INFO) << "Start Loop"; gpgme_key_t key; while ((err = gpgme_op_keylist_next(ctx, &key)) == GPG_ERR_NO_ERROR) { keys_list->push_back(GpgKey(std::move(key))); - LOG(INFO) << "Append Key" << keys_list->back().id().c_str(); + DLOG(INFO) << "Append Key" << keys_list->back().id().c_str(); } - assert(gpg_err_code(err) != GPG_ERR_NO_ERROR); + assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_EOF); err = gpgme_op_keylist_end(ctx); - LOG(INFO) << "Operate KeyList End"; + DLOG(INFO) << "Operate KeyList End"; return keys_list; } diff --git a/src/gpg/model/GpgKey.h b/src/gpg/model/GpgKey.h index c0671b35..52e089ff 100644 --- a/src/gpg/model/GpgKey.h +++ b/src/gpg/model/GpgKey.h @@ -34,7 +34,7 @@ namespace GpgFrontend { class GpgKey { -public: + public: [[nodiscard]] bool good() const { return _key_ref != nullptr; } [[nodiscard]] std::string id() const { return _key_ref->subkeys->keyid; } @@ -53,19 +53,20 @@ public: [[nodiscard]] std::string owner_trust() const { switch (_key_ref->owner_trust) { - case GPGME_VALIDITY_UNKNOWN: - return "Unknown"; - case GPGME_VALIDITY_UNDEFINED: - return "Undefined"; - case GPGME_VALIDITY_NEVER: - return "Never"; - case GPGME_VALIDITY_MARGINAL: - return "Marginal"; - case GPGME_VALIDITY_FULL: - return "FULL"; - case GPGME_VALIDITY_ULTIMATE: - return "Ultimate"; + case GPGME_VALIDITY_UNKNOWN: + return "Unknown"; + case GPGME_VALIDITY_UNDEFINED: + return "Undefined"; + case GPGME_VALIDITY_NEVER: + return "Never"; + case GPGME_VALIDITY_MARGINAL: + return "Marginal"; + case GPGME_VALIDITY_FULL: + return "FULL"; + case GPGME_VALIDITY_ULTIMATE: + return "Ultimate"; } + return "Invalid"; } [[nodiscard]] std::string pubkey_algo() const { @@ -124,33 +125,37 @@ public: GpgKey() = default; - explicit GpgKey(gpgme_key_t &&key); + explicit GpgKey(gpgme_key_t&& key); ~GpgKey() = default; - GpgKey(const gpgme_key_t &key) = delete; + GpgKey(const gpgme_key_t& key) = delete; - GpgKey(GpgKey &&k) noexcept; + GpgKey(GpgKey&& k) noexcept; - GpgKey &operator=(GpgKey &&k) noexcept; + GpgKey& operator=(GpgKey&& k) noexcept; - GpgKey &operator=(const gpgme_key_t &key) = delete; + GpgKey& operator=(const gpgme_key_t& key) = delete; + + bool operator==(const GpgKey& o) { return o.id() == this->id(); } + + bool operator<=(const GpgKey& o) { return this->id() < o.id(); } explicit operator gpgme_key_t() const { return _key_ref.get(); } -private: - struct __key_ref_deletor { + private: + struct _key_ref_deletor { void operator()(gpgme_key_t _key) { if (_key != nullptr) gpgme_key_unref(_key); } }; - using KeyRefHandler = std::unique_ptr<struct _gpgme_key, __key_ref_deletor>; + using KeyRefHandler = std::unique_ptr<struct _gpgme_key, _key_ref_deletor>; KeyRefHandler _key_ref = nullptr; }; -} // namespace GpgFrontend +} // namespace GpgFrontend -#endif // GPGFRONTEND_GPGKEY_H +#endif // GPGFRONTEND_GPGKEY_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5637be37..4e223f63 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,8 @@ find_package(GTest REQUIRED) +# Set configure for test +file(COPY ${CMAKE_SOURCE_DIR}/test/conf DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ FOLLOW_SYMLINK_CHAIN) + aux_source_directory(. TEST_SOURCE) add_executable( diff --git a/test/GpgCoreTest.cpp b/test/GpgCoreTest.cpp index 578d1542..51510e9e 100644 --- a/test/GpgCoreTest.cpp +++ b/test/GpgCoreTest.cpp @@ -24,18 +24,20 @@ #include "GpgFrontendTest.h" -#include <boost/date_time/gregorian/parsers.hpp> +#include <gpg-error.h> #include <gtest/gtest.h> +#include <boost/date_time/gregorian/parsers.hpp> +#include <boost/dll.hpp> #include <memory> +#include "gpg/GpgConstants.h" #include "gpg/function/GpgKeyGetter.h" #include "gpg/function/GpgKeyImportExportor.h" #include "gpg/function/GpgKeyOpera.h" TEST(GpgKeyTest, GpgCoreTest) {} class GpgCoreTest : public ::testing::Test { - -protected: + protected: GpgFrontend::StdBypeArrayPtr secret_key_ = std::make_unique<std::string>( "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" "lQVYBGE0XVEBDADHYmnEbRB8hxqyQmaLmIRU71PTMZc162qWoWTMaPd7a8gQcQwc" @@ -124,17 +126,35 @@ protected: virtual ~GpgCoreTest() = default; virtual void SetUp() { - GpgFrontend::GpgContext::GetInstance().SetPassphraseCb( - GpgFrontend::GpgContext::test_passphrase_cb); + auto config_path = + boost::dll::program_location().parent_path() / "conf" / "core.cfg"; + + using namespace libconfig; + Config cfg; + ASSERT_NO_THROW(cfg.readFile(config_path.c_str())); + + const Setting& root = cfg.getRoot(); + ASSERT_TRUE(root.exists("independent_database")); + bool independent_database = true; + ASSERT_TRUE(root.lookupValue("independent_database", independent_database)); + if (independent_database) + + GpgFrontend::GpgContext::GetInstance().SetPassphraseCb( + GpgFrontend::GpgContext::test_passphrase_cb); GpgFrontend::GpgKeyImportExportor::GetInstance().ImportKey( std::move(this->secret_key_)); } virtual void TearDown() {} + + private: + void dealing_private_keys() {} + + void configure_independent_database() {} }; TEST_F(GpgCoreTest, CoreInitTest) { - auto &ctx = GpgFrontend::GpgContext::GetInstance(); + auto& ctx = GpgFrontend::GpgContext::GetInstance(); ASSERT_TRUE(ctx.good()); } @@ -175,7 +195,9 @@ TEST_F(GpgCoreTest, GpgKeyTest) { ASSERT_FALSE(key.CanAuthActual()); ASSERT_EQ(key.name(), "GpgFrontendTest"); + ASSERT_TRUE(key.comment().empty()); ASSERT_EQ(key.email(), "[email protected]"); + ASSERT_EQ(key.id(), "81704859182661FB"); ASSERT_EQ(key.fpr(), "9490795B78F8AFE9F93BD09281704859182661FB"); ASSERT_EQ(key.expires(), boost::gregorian::from_simple_string("2023-09-05")); ASSERT_EQ(key.pubkey_algo(), "RSA"); @@ -184,6 +206,90 @@ TEST_F(GpgCoreTest, GpgKeyTest) { boost::gregorian::from_simple_string("1970-01-01")); ASSERT_EQ(key.create_time(), boost::gregorian::from_simple_string("2021-09-05")); + + ASSERT_EQ(key.owner_trust(), "Unknown"); + + using namespace boost::posix_time; + ASSERT_EQ(key.expired(), key.expires() < second_clock::local_time().date()); +} + +TEST_F(GpgCoreTest, GpgSubKeyTest) { + auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey( + "9490795B78F8AFE9F93BD09281704859182661FB"); + auto sub_keys = key.subKeys(); + ASSERT_EQ(sub_keys->size(), 2); + + auto& sub_key = sub_keys->back(); + + ASSERT_FALSE(sub_key.revoked()); + ASSERT_FALSE(sub_key.disabled()); + ASSERT_EQ(sub_key.timestamp(), + boost::gregorian::from_simple_string("2021-09-05")); + + ASSERT_FALSE(sub_key.is_cardkey()); + ASSERT_TRUE(sub_key.is_private_key()); + ASSERT_EQ(sub_key.id(), "2B36803235B5E25B"); + ASSERT_EQ(sub_key.fpr(), "50D37E8F8EE7340A6794E0592B36803235B5E25B"); + ASSERT_EQ(sub_key.length(), 3072); + ASSERT_EQ(sub_key.pubkey_algo(), "RSA"); + ASSERT_FALSE(sub_key.can_certify()); + ASSERT_FALSE(sub_key.can_authenticate()); + ASSERT_FALSE(sub_key.can_sign()); + ASSERT_TRUE(sub_key.can_encrypt()); + ASSERT_EQ(key.expires(), boost::gregorian::from_simple_string("2023-09-05")); + + using namespace boost::posix_time; + ASSERT_EQ(sub_key.expired(), + sub_key.expires() < second_clock::local_time().date()); +} + +TEST_F(GpgCoreTest, GpgUIDTest) { + auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey( + "9490795B78F8AFE9F93BD09281704859182661FB"); + auto uids = key.uids(); + ASSERT_EQ(uids->size(), 1); + auto& uid = uids->front(); + + ASSERT_EQ(uid.name(), "GpgFrontendTest"); + ASSERT_TRUE(uid.comment().empty()); + ASSERT_EQ(uid.email(), "[email protected]"); + ASSERT_EQ(uid.uid(), "GpgFrontendTest <[email protected]>"); + ASSERT_FALSE(uid.invalid()); + ASSERT_FALSE(uid.revoked()); +} + +TEST_F(GpgCoreTest, GpgKeySignatureTest) { + auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey( + "9490795B78F8AFE9F93BD09281704859182661FB"); + auto uids = key.uids(); + ASSERT_EQ(uids->size(), 1); + auto& uid = uids->front(); + + auto signatures = uid.signatures(); + ASSERT_EQ(signatures->size(), 1); + auto& signature = signatures->front(); + + ASSERT_EQ(signature.name(), "GpgFrontendTest"); + ASSERT_TRUE(signature.comment().empty()); + ASSERT_EQ(signature.email(), "[email protected]"); + ASSERT_EQ(signature.keyid(), "81704859182661FB"); + ASSERT_EQ(signature.pubkey_algo(), "RSA"); + + ASSERT_FALSE(signature.revoked()); + ASSERT_FALSE(signature.invalid()); + ASSERT_EQ(GpgFrontend::check_gpg_error_2_err_code(signature.status()), + GPG_ERR_NO_ERROR); + ASSERT_EQ(signature.uid(), "GpgFrontendTest <[email protected]>"); +} + +TEST_F(GpgCoreTest, GpgKeyGetterTest) { + auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey( + "9490795B78F8AFE9F93BD09281704859182661FB"); + ASSERT_TRUE(key.good()); + auto keys = GpgFrontend::GpgKeyGetter::GetInstance().FetchKey(); + ASSERT_GE(keys->size(), 1); + + ASSERT_TRUE(find(keys->begin(), keys->end(), key) != keys->end()); } TEST_F(GpgCoreTest, GpgKeyDeleteTest) { diff --git a/test/conf/core.cfg b/test/conf/core.cfg new file mode 100644 index 00000000..b9b194cf --- /dev/null +++ b/test/conf/core.cfg @@ -0,0 +1,10 @@ +# Example application configuration file +version = "1.0"; +independent_database = true; +load_keys: +{ + private_keys = ({ + filename = "pv1.key"; + md5 = ""; + }); +};
\ No newline at end of file diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 56273dcf..0a43857b 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -1,4 +1,4 @@ -if(ESAY_LOGGING_CPP) - message(STATUS "Build Esay LoginPP") +if(ESAY_LOGGING_PP) + message(STATUS "Build EsayLoggingPP") add_subdirectory(easyloggingpp) endif()
\ No newline at end of file diff --git a/third_party/easyloggingpp/CMakeLists.txt b/third_party/easyloggingpp/CMakeLists.txt index ac17833a..9b96f9c4 100644 --- a/third_party/easyloggingpp/CMakeLists.txt +++ b/third_party/easyloggingpp/CMakeLists.txt @@ -1,3 +1,4 @@ aux_source_directory(. EASY_LOGGING_CPP_SOURCE) -add_library(easy_logging_cpp STATIC ${EASY_LOGGING_CPP_SOURCE})
\ No newline at end of file +add_library(easy_logging_pp STATIC ${EASY_LOGGING_CPP_SOURCE}) +target_link_libraries(easy_logging_pp stdc++)
\ No newline at end of file |