diff options
author | saturneric <[email protected]> | 2023-12-27 03:20:11 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2023-12-27 03:20:11 +0000 |
commit | 566d5e41a34e08b06a5c84fd4ad9f944b6b31feb (patch) | |
tree | 996184047486e1484b3101e68ebc0b43b4ccf11e | |
parent | fix: add test cases and test file basical operations (diff) | |
download | GpgFrontend-566d5e41a34e08b06a5c84fd4ad9f944b6b31feb.tar.gz GpgFrontend-566d5e41a34e08b06a5c84fd4ad9f944b6b31feb.zip |
feat: avoid reading entire file to memory
-rw-r--r-- | src/core/function/gpg/GpgFileOpera.cpp | 296 | ||||
-rw-r--r-- | src/core/function/gpg/GpgFileOpera.h | 63 | ||||
-rw-r--r-- | src/core/model/GpgData.cpp | 32 | ||||
-rw-r--r-- | src/core/model/GpgData.h | 22 | ||||
-rw-r--r-- | src/test/core/GpgCoreTestFileBasicOpera.cpp | 16 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowFileSlotFunction.cpp | 93 |
6 files changed, 295 insertions, 227 deletions
diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp index 45286df2..7c247b95 100644 --- a/src/core/function/gpg/GpgFileOpera.cpp +++ b/src/core/function/gpg/GpgFileOpera.cpp @@ -31,120 +31,129 @@ #include "core/function/gpg/GpgBasicOperator.h" #include "core/model/GFBuffer.h" +#include "core/model/GpgData.h" #include "core/model/GpgDecryptResult.h" #include "core/model/GpgEncryptResult.h" #include "core/model/GpgKey.h" #include "core/model/GpgSignResult.h" #include "core/model/GpgVerifyResult.h" +#include "core/utils/AsyncUtils.h" #include "core/utils/GpgUtils.h" #include "core/utils/IOUtils.h" namespace GpgFrontend { +auto PathPreCheck(const std::filesystem::path& path, bool read) + -> std::tuple<bool, std::string> { + QFileInfo const file_info(path); + QFileInfo const path_info(file_info.absolutePath()); + + if (!path_info.exists()) { + return {false, _("")}; + } + if (read ? !file_info.isReadable() : !path_info.isWritable()) { + return {false, _("")}; + } + return {true, _("")}; +} + +GpgFileOpera::GpgFileOpera(int channel) + : SingletonFunctionObject<GpgFileOpera>(channel) {} + void GpgFileOpera::EncryptFile(std::vector<GpgKey> keys, const std::filesystem::path& in_path, bool ascii, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + std::vector<gpgme_key_t> recipients(keys.begin(), keys.end()); - GpgBasicOperator::GetInstance().Encrypt( - std::move(keys), std::get<1>(read_result), ascii, - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgEncryptResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto result = ExtractParams<GpgEncryptResult>(data_object, 0); - auto buffer = ExtractParams<GFBuffer>(data_object, 1); - if (CheckGpgError(err) == GPG_ERR_NO_ERROR) { - if (!WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - } - cb(err, TransferParams(result)); - }); + // Last entry data_in array has to be nullptr + recipients.emplace_back(nullptr); + + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); + auto err = CheckGpgError(gpgme_op_encrypt(ctx, recipients.data(), + GPGME_ENCRYPT_ALWAYS_TRUST, + data_in, data_out)); + data_object->Swap({GpgEncryptResult(gpgme_op_encrypt_result(ctx))}); + + return err; + }, + cb, "gpgme_op_encrypt", "2.1.0"); } void GpgFileOpera::DecryptFile(const std::filesystem::path& in_path, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } - - GpgBasicOperator::GetInstance().Decrypt( - std::get<1>(read_result), - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgDecryptResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto result = ExtractParams<GpgDecryptResult>(data_object, 0); - auto buffer = ExtractParams<GFBuffer>(data_object, 1); - - if (CheckGpgError(err) == GPG_ERR_NO_ERROR && - !WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - - cb(err, TransferParams(result)); - }); + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + auto err = CheckGpgError( + gpgme_op_decrypt(ctx_.DefaultContext(), data_in, data_out)); + data_object->Swap( + {GpgDecryptResult(gpgme_op_decrypt_result(ctx_.DefaultContext()))}); + + return err; + }, + cb, "gpgme_op_decrypt", "2.1.0"); } void GpgFileOpera::SignFile(KeyArgsList keys, const std::filesystem::path& in_path, bool ascii, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } - - GpgBasicOperator::GetInstance().Sign( - std::move(keys), std::get<1>(read_result), GPGME_SIG_MODE_DETACH, ascii, - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgSignResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto result = ExtractParams<GpgSignResult>(data_object, 0); - auto buffer = ExtractParams<GFBuffer>(data_object, 1); - - if (CheckGpgError(err) == GPG_ERR_NO_ERROR && - !WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - cb(err, TransferParams(result)); - }); + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgError err; + + // Set Singers of this opera + GpgBasicOperator::GetInstance().SetSigners(keys, ascii); + + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); + err = CheckGpgError( + gpgme_op_sign(ctx, data_in, data_out, GPGME_SIG_MODE_DETACH)); + + data_object->Swap({ + GpgSignResult(gpgme_op_sign_result(ctx)), + }); + return err; + }, + cb, "gpgme_op_sign", "2.1.0"); } void GpgFileOpera::VerifyFile(const std::filesystem::path& data_path, const std::filesystem::path& sign_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(data_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgError err; + + GpgData data_in(data_path, true); + GpgData data_out; + if (!sign_path.empty()) { + GpgData sig_data(sign_path, true); + err = CheckGpgError(gpgme_op_verify(ctx_.DefaultContext(), sig_data, + data_in, nullptr)); + } else { + err = CheckGpgError(gpgme_op_verify(ctx_.DefaultContext(), data_in, + nullptr, data_out)); + } - GFBuffer sign_buffer; - if (!sign_path.empty()) { - auto read_result = ReadFileGFBuffer(sign_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } - sign_buffer = std::get<1>(read_result); - } + data_object->Swap({ + GpgVerifyResult(gpgme_op_verify_result(ctx_.DefaultContext())), + }); - GpgBasicOperator::GetInstance().Verify( - std::get<1>(read_result), sign_buffer, - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgVerifyResult>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto result = ExtractParams<GpgVerifyResult>(data_object, 0); - cb(err, TransferParams(result)); - }); + return err; + }, + cb, "gpgme_op_verify", "2.1.0"); } void GpgFileOpera::EncryptSignFile(KeyArgsList keys, KeyArgsList signer_keys, @@ -152,83 +161,74 @@ void GpgFileOpera::EncryptSignFile(KeyArgsList keys, KeyArgsList signer_keys, bool ascii, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } - - GpgBasicOperator::GetInstance().EncryptSign( - std::move(keys), std::move(signer_keys), std::get<1>(read_result), ascii, - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgEncryptResult, GpgSignResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto encrypt_result = ExtractParams<GpgEncryptResult>(data_object, 0); - auto sign_result = ExtractParams<GpgSignResult>(data_object, 1); - auto buffer = ExtractParams<GFBuffer>(data_object, 2); - if (CheckGpgError(err) == GPG_ERR_NO_ERROR) { - if (!WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - } - cb(err, TransferParams(encrypt_result, sign_result)); - }); + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgError err; + std::vector<gpgme_key_t> recipients(keys.begin(), keys.end()); + + // Last entry data_in array has to be nullptr + recipients.emplace_back(nullptr); + + GpgBasicOperator::GetInstance().SetSigners(signer_keys, ascii); + + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); + err = CheckGpgError(gpgme_op_encrypt_sign(ctx, recipients.data(), + GPGME_ENCRYPT_ALWAYS_TRUST, + data_in, data_out)); + + data_object->Swap({ + GpgEncryptResult(gpgme_op_encrypt_result(ctx)), + GpgSignResult(gpgme_op_sign_result(ctx)), + }); + return err; + }, + cb, "gpgme_op_encrypt_sign", "2.1.0"); } void GpgFileOpera::DecryptVerifyFile(const std::filesystem::path& in_path, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgError err; - GpgBasicOperator::GetInstance().DecryptVerify( - std::get<1>(read_result), - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object - ->Check<GpgDecryptResult, GpgVerifyResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto decrypt_result = ExtractParams<GpgDecryptResult>(data_object, 0); - auto verify_result = ExtractParams<GpgVerifyResult>(data_object, 1); - auto buffer = ExtractParams<GFBuffer>(data_object, 2); - if (CheckGpgError(err) == GPG_ERR_NO_ERROR) { - if (!WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - } - cb(err, TransferParams(decrypt_result, verify_result)); - }); + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + err = CheckGpgError( + gpgme_op_decrypt_verify(ctx_.DefaultContext(), data_in, data_out)); + + data_object->Swap({ + GpgDecryptResult(gpgme_op_decrypt_result(ctx_.DefaultContext())), + GpgVerifyResult(gpgme_op_verify_result(ctx_.DefaultContext())), + }); + + return err; + }, + cb, "gpgme_op_decrypt_verify", "2.1.0"); } + void GpgFileOpera::EncryptFileSymmetric(const std::filesystem::path& in_path, bool ascii, const std::filesystem::path& out_path, const GpgOperationCallback& cb) { - auto read_result = ReadFileGFBuffer(in_path); - if (!std::get<0>(read_result)) { - throw std::runtime_error("read file error"); - } - - GpgBasicOperator::GetInstance().EncryptSymmetric( - std::get<1>(read_result), ascii, - [=](GpgError err, const DataObjectPtr& data_object) { - if (!data_object->Check<GpgEncryptResult, GFBuffer>()) { - throw std::runtime_error("data object transfers wrong arguments"); - } - auto result = ExtractParams<GpgEncryptResult>(data_object, 0); - auto buffer = ExtractParams<GFBuffer>(data_object, 1); - if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { - cb(err, TransferParams(result)); - return; - } - - if (!WriteFileGFBuffer(out_path, buffer)) { - throw std::runtime_error("write buffer to file error"); - } - - cb(err, TransferParams(result)); - }); + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + GpgData data_in(in_path, true); + GpgData data_out(out_path, false); + + auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); + auto err = CheckGpgError(gpgme_op_encrypt( + ctx, nullptr, GPGME_ENCRYPT_SYMMETRIC, data_in, data_out)); + data_object->Swap({ + GpgEncryptResult(gpgme_op_encrypt_result(ctx)), + }); + + return err; + }, + cb, "gpgme_op_encrypt_symmetric", "2.1.0"); } - } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgFileOpera.h b/src/core/function/gpg/GpgFileOpera.h index a358b60a..73649d47 100644 --- a/src/core/function/gpg/GpgFileOpera.h +++ b/src/core/function/gpg/GpgFileOpera.h @@ -28,6 +28,8 @@ #pragma once +#include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgContext.h" #include "core/function/result_analyse/GpgResultAnalyse.h" #include "core/typedef/GpgTypedef.h" @@ -38,9 +40,18 @@ namespace GpgFrontend { * * @class class: GpgBasicOperator */ -class GPGFRONTEND_CORE_EXPORT GpgFileOpera { +class GPGFRONTEND_CORE_EXPORT GpgFileOpera + : public SingletonFunctionObject<GpgFileOpera> { public: /** + * @brief Construct a new Gpg File Opera object + * + * @param channel + */ + explicit GpgFileOpera( + int channel = SingletonFunctionObject::GetDefaultChannel()); + + /** * @brief Encrypted file with public key * * @param keys Used public key @@ -50,10 +61,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param channel Channel in context * @return unsigned int error code */ - static void EncryptFile(KeyArgsList keys, - const std::filesystem::path& in_path, bool ascii, - const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void EncryptFile(KeyArgsList keys, const std::filesystem::path& in_path, + bool ascii, const std::filesystem::path& out_path, + const GpgOperationCallback& cb); /** * @brief Encrypted file symmetrically (with password) @@ -64,10 +74,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param channel * @return unsigned int */ - static void EncryptFileSymmetric(const std::filesystem::path& in_path, - bool ascii, - const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void EncryptFileSymmetric(const std::filesystem::path& in_path, bool ascii, + const std::filesystem::path& out_path, + const GpgOperationCallback& cb); /** * @brief @@ -77,9 +86,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param result * @return GpgError */ - static void DecryptFile(const std::filesystem::path& in_path, - const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void DecryptFile(const std::filesystem::path& in_path, + const std::filesystem::path& out_path, + const GpgOperationCallback& cb); /** * @brief Sign file with private key @@ -91,9 +100,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param channel * @return GpgError */ - static void SignFile(KeyArgsList keys, const std::filesystem::path& in_path, - bool ascii, const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void SignFile(KeyArgsList keys, const std::filesystem::path& in_path, + bool ascii, const std::filesystem::path& out_path, + const GpgOperationCallback& cb); /** * @brief Verify file with public key @@ -104,9 +113,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param channel Channel in context * @return GpgError */ - static void VerifyFile(const std::filesystem::path& data_path, - const std::filesystem::path& sign_path, - const GpgOperationCallback& cb); + void VerifyFile(const std::filesystem::path& data_path, + const std::filesystem::path& sign_path, + const GpgOperationCallback& cb); /** * @brief Encrypt and sign file with public key and private key @@ -120,10 +129,10 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param channel * @return GpgError */ - static void EncryptSignFile(KeyArgsList keys, KeyArgsList signer_keys, - const std::filesystem::path& in_path, bool ascii, - const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void EncryptSignFile(KeyArgsList keys, KeyArgsList signer_keys, + const std::filesystem::path& in_path, bool ascii, + const std::filesystem::path& out_path, + const GpgOperationCallback& cb); /** * @brief @@ -134,9 +143,13 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera { * @param verify_res * @return GpgError */ - static void DecryptVerifyFile(const std::filesystem::path& in_path, - const std::filesystem::path& out_path, - const GpgOperationCallback& cb); + void DecryptVerifyFile(const std::filesystem::path& in_path, + const std::filesystem::path& out_path, + const GpgOperationCallback& cb); + + private: + GpgContext& ctx_ = GpgContext::GetInstance( + SingletonFunctionObject::GetChannel()); ///< Corresponding context }; } // namespace GpgFrontend diff --git a/src/core/model/GpgData.cpp b/src/core/model/GpgData.cpp index 19f45e22..6a6105eb 100644 --- a/src/core/model/GpgData.cpp +++ b/src/core/model/GpgData.cpp @@ -28,6 +28,8 @@ #include "core/model/GpgData.h" +#include <unistd.h> + #include "core/typedef/GpgTypedef.h" namespace GpgFrontend { @@ -63,6 +65,35 @@ GpgData::GpgData(const void* buffer, size_t size, bool copy) { data_ref_ = std::unique_ptr<struct gpgme_data, DataRefDeleter>(data); } +GpgData::GpgData(int fd) : fd_(fd) { + gpgme_data_t data; + + auto err = gpgme_data_new_from_fd(&data, fd); + assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR); + + data_ref_ = std::unique_ptr<struct gpgme_data, DataRefDeleter>(data); +} + +GpgData::GpgData(const std::filesystem::path& path, bool read) { + gpgme_data_t data; + + fp_ = fopen(path.string().c_str(), read ? "rb" : "wb"); + auto err = gpgme_data_new_from_stream(&data, fp_); + assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR); + + data_ref_ = std::unique_ptr<struct gpgme_data, DataRefDeleter>(data); +} + +GpgData::~GpgData() { + if (fp_ != nullptr) { + fclose(fp_); + } + + if (fd_ >= 0) { + close(fd_); + } +} + auto GpgData::Read2Buffer() -> ByteArrayPtr { gpgme_off_t ret = gpgme_data_seek(*this, 0, SEEK_SET); ByteArrayPtr out_buffer = std::make_unique<std::string>(); @@ -110,5 +141,4 @@ auto GpgData::Read2GFBuffer() -> GFBuffer { } GpgData::operator gpgme_data_t() { return data_ref_.get(); } - } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgData.h b/src/core/model/GpgData.h index cd2e193e..4abde270 100644 --- a/src/core/model/GpgData.h +++ b/src/core/model/GpgData.h @@ -57,10 +57,30 @@ class GPGFRONTEND_CORE_EXPORT GpgData { /** * @brief Construct a new Gpg Data object * + * @param fd + */ + explicit GpgData(int fd); + + /** + * @brief Construct a new Gpg Data object + * + * @param path + */ + explicit GpgData(const std::filesystem::path& path, bool read); + + /** + * @brief Construct a new Gpg Data object + * */ explicit GpgData(GFBuffer); /** + * @brief Destroy the Gpg Data object + * + */ + ~GpgData(); + + /** * @brief * * @return gpgme_data_t @@ -95,6 +115,8 @@ class GPGFRONTEND_CORE_EXPORT GpgData { GFBuffer cached_buffer_; std::unique_ptr<struct gpgme_data, DataRefDeleter> data_ref_ = nullptr; ///< + FILE* fp_ = nullptr; + int fd_ = -1; }; } // namespace GpgFrontend diff --git a/src/test/core/GpgCoreTestFileBasicOpera.cpp b/src/test/core/GpgCoreTestFileBasicOpera.cpp index d07eae4f..029ff6fc 100644 --- a/src/test/core/GpgCoreTestFileBasicOpera.cpp +++ b/src/test/core/GpgCoreTestFileBasicOpera.cpp @@ -50,7 +50,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptDecrTest) { auto input_file = CreateTempFileAndWriteData("Hello GpgFrontend!"); auto output_file = GetTempFilePath(); - GpgFileOpera::EncryptFile( + GpgFileOpera::GetInstance().EncryptFile( {encrypt_key}, input_file, true, output_file, [output_file, &callback_called_flag](GpgError err, const DataObjectPtr& data_obj) { @@ -61,7 +61,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptDecrTest) { ASSERT_EQ(CheckGpgError(err), GPG_ERR_NO_ERROR); auto decrpypt_output_file = GetTempFilePath(); - GpgFileOpera::DecryptFile( + GpgFileOpera::GetInstance().DecryptFile( output_file, decrpypt_output_file, [decrpypt_output_file, &callback_called_flag]( GpgError err, const DataObjectPtr& data_obj) { @@ -95,7 +95,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptSymmetricDecrTest) { auto input_file = CreateTempFileAndWriteData("Hello GpgFrontend!"); auto output_file = GetTempFilePath(); - GpgFileOpera::EncryptFileSymmetric( + GpgFileOpera::GetInstance().EncryptFileSymmetric( input_file, true, output_file, [&callback_called_flag, output_file](GpgError err, const DataObjectPtr& data_obj) { @@ -105,7 +105,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptSymmetricDecrTest) { ASSERT_EQ(CheckGpgError(err), GPG_ERR_NO_ERROR); auto decrpypt_output_file = GetTempFilePath(); - GpgFileOpera::DecryptFile( + GpgFileOpera::GetInstance().DecryptFile( output_file, decrpypt_output_file, [&callback_called_flag, decrpypt_output_file]( GpgError err, const DataObjectPtr& data_obj) { @@ -142,7 +142,7 @@ TEST_F(GpgCoreTest, CoreFileSignVerifyNormalTest) { auto input_file = CreateTempFileAndWriteData("Hello GpgFrontend!"); auto output_file = GetTempFilePath(); - GpgFileOpera::SignFile( + GpgFileOpera::GetInstance().SignFile( {sign_key}, input_file, true, output_file, [&callback_called_flag, input_file, output_file]( GpgError err, const DataObjectPtr& data_obj) { @@ -151,7 +151,7 @@ TEST_F(GpgCoreTest, CoreFileSignVerifyNormalTest) { ASSERT_TRUE(result.InvalidSigners().empty()); ASSERT_EQ(CheckGpgError(err), GPG_ERR_NO_ERROR); - GpgFileOpera::VerifyFile( + GpgFileOpera::GetInstance().VerifyFile( input_file, output_file, [&callback_called_flag](GpgError err, const DataObjectPtr& data_obj) { @@ -187,7 +187,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptSignDecrVerifyTest) { ASSERT_TRUE(sign_key.IsPrivateKey()); ASSERT_TRUE(sign_key.IsHasActualSigningCapability()); - GpgFileOpera::EncryptSignFile( + GpgFileOpera::GetInstance().EncryptSignFile( {encrypt_key}, {sign_key}, input_file, true, output_file, [&callback_called_flag, output_file](GpgError err, const DataObjectPtr& data_obj) { @@ -199,7 +199,7 @@ TEST_F(GpgCoreTest, CoreFileEncryptSignDecrVerifyTest) { ASSERT_EQ(CheckGpgError(err), GPG_ERR_NO_ERROR); auto decrpypt_output_file = GetTempFilePath(); - GpgFileOpera::DecryptVerifyFile( + GpgFileOpera::GetInstance().DecryptVerifyFile( output_file, decrpypt_output_file, [&callback_called_flag, decrpypt_output_file]( GpgError err, const DataObjectPtr& data_obj) { diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp index b46ef5f5..c4d8370a 100644 --- a/src/ui/main_window/MainWindowFileSlotFunction.cpp +++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp @@ -108,7 +108,7 @@ auto ProcessTarballIntoDirectory(QWidget* parent, if (if_error || !exists(target_path)) { throw std::runtime_error("Decompress Failed"); } - return {true, target_path.u8string()}; + return {true, target_path.string()}; } catch (...) { SPDLOG_ERROR("decompress error"); return {false, path}; @@ -122,11 +122,11 @@ auto ProcessTarballIntoDirectory(QWidget* parent, * @param path the tarball to be converted */ auto ProcessDirectoryIntoTarball(QWidget* parent, std::filesystem::path path) - -> bool { + -> std::tuple<bool, std::filesystem::path> { try { auto base_path = path.parent_path(); auto target_path = path; - path = path.replace_extension(""); + target_path = target_path.replace_extension(""); SPDLOG_DEBUG("base path: {} target archive path: {} selected_dir_path: {}", base_path.u8string(), target_path.u8string(), path.u8string()); @@ -134,23 +134,24 @@ auto ProcessDirectoryIntoTarball(QWidget* parent, std::filesystem::path path) bool if_error = false; process_operation(parent, _("Making Tarball"), [&](DataObjectPtr) -> int { try { - GpgFrontend::ArchiveFileOperator::CreateArchive(base_path, target_path, - 0, {path}); + // GpgFrontend::ArchiveFileOperator::CreateArchive(base_path, + // target_path, + // 0, {path}); } catch (const std::runtime_error& e) { if_error = true; } return 0; }); - if (if_error || !exists(target_path)) { - throw std::runtime_error("Compress Failed"); + if (!exists(target_path)) { + return {false, ""}; } - path = target_path.u8string().c_str(); + + return {if_error, target_path.replace_extension(".tar")}; } catch (...) { - SPDLOG_ERROR("compress error"); - return false; + SPDLOG_ERROR("compress caught exception error"); + return {false, ""}; } - return true; } void MainWindow::SlotFileEncrypt() { @@ -171,16 +172,13 @@ void MainWindow::SlotFileEncrypt() { // get file info QFileInfo const file_info(path); - if (file_info.isDir()) { - path = path.replace_extension(".tar"); - } - const auto* extension = ".asc"; if (non_ascii_when_export || file_info.isDir()) { extension = ".gpg"; } - auto out_path = path.replace_extension(path.extension().string() + extension); + auto out_path = path; + out_path = out_path.replace_extension(path.extension().string() + extension); if (QFile::exists(out_path)) { auto out_file_name = boost::format(_("The target file %1% already exists, " "do you need to overwrite it?")) % @@ -192,15 +190,6 @@ void MainWindow::SlotFileEncrypt() { if (ret == QMessageBox::Cancel) return; } - if (file_info.isDir()) { - // stop if the process making tarball failed - if (!ProcessDirectoryIntoTarball(this, path)) { - QMessageBox::critical(this, _("Error"), - _("Unable to convert the folder into tarball.")); - return; - } - } - if (key_ids->empty()) { // Symmetric Encrypt auto ret = QMessageBox::information( @@ -210,9 +199,22 @@ void MainWindow::SlotFileEncrypt() { QMessageBox::Ok | QMessageBox::Cancel); if (ret == QMessageBox::Cancel) return; + if (file_info.isDir()) { + // stop if the process making tarball failed + const auto [success, target_path] = + ProcessDirectoryIntoTarball(this, path); + if (!success) { + QMessageBox::critical(this, _("Error"), + _("Unable to convert the folder into tarball.")); + return; + } + // reset target + path = target_path; + } + CommonUtils::WaitForOpera( this, _("Symmetrically Encrypting"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::EncryptFileSymmetric( + GpgFileOpera::GetInstance().EncryptFileSymmetric( path, !non_ascii_when_export, out_path, [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting @@ -244,6 +246,7 @@ void MainWindow::SlotFileEncrypt() { return; } + auto p_keys = GpgKeyGetter::GetInstance().GetKeys(key_ids); // check key abilities @@ -262,7 +265,7 @@ void MainWindow::SlotFileEncrypt() { CommonUtils::WaitForOpera( this, _("Encrypting"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::EncryptFile( + GpgFileOpera::GetInstance().EncryptFile( {p_keys->begin(), p_keys->end()}, path, !non_ascii_when_export, out_path, [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting @@ -315,7 +318,7 @@ void MainWindow::SlotFileDecrypt() { CommonUtils::WaitForOpera( this, _("Decrypting"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::DecryptFile( + GpgFileOpera::GetInstance().DecryptFile( path, out_path, [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting op_hd(); @@ -411,7 +414,7 @@ void MainWindow::SlotFileSign() { CommonUtils::WaitForOpera( this, _("Signing"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::EncryptFile( + GpgFileOpera::GetInstance().SignFile( {keys->begin(), keys->end()}, path, !non_ascii_when_export, sig_file_path, [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting @@ -433,27 +436,23 @@ void MainWindow::SlotFileSign() { void MainWindow::SlotFileVerify() { auto* file_tree_view = edit_->SlotCurPageFileTreeView(); - auto path = file_tree_view->GetSelected(); - -#ifdef WINDOWS - std::filesystem::path in_path = path.toStdU16String(); -#else - std::filesystem::path in_path = path.toStdString(); -#endif + auto path_qstr = file_tree_view->GetSelected(); + auto path = ConvertPathByOS(path_qstr); + if (!PathPreCheck(this, path)) return; - std::filesystem::path sign_file_path = in_path; + std::filesystem::path sign_file_path = path; std::filesystem::path data_file_path; - if (in_path.extension() == ".gpg") { + if (path.extension() == ".gpg") { swap(data_file_path, sign_file_path); - } else if (in_path.extension() == ".sig" || in_path.extension() == ".asc") { + } else if (path.extension() == ".sig" || path.extension() == ".asc") { data_file_path = sign_file_path.parent_path() / sign_file_path.stem(); } SPDLOG_DEBUG("sign_file_path: {} {}", sign_file_path.u8string(), sign_file_path.extension().u8string()); - if (in_path.extension() != ".gpg") { + if (path.extension() != ".gpg") { bool ok; QString const text = QInputDialog::getText( this, _("Origin file to verify"), _("Filepath"), QLineEdit::Normal, @@ -479,7 +478,7 @@ void MainWindow::SlotFileVerify() { CommonUtils::WaitForOpera( this, _("Verifying"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::DecryptFile( + GpgFileOpera::GetInstance().VerifyFile( data_file_path.u8string(), sign_file_path.u8string(), [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting @@ -552,7 +551,8 @@ void MainWindow::SlotFileEncryptSign() { extension = ".gpg"; } - auto out_path = path.replace_extension(path.extension().string() + extension); + auto out_path = path; + out_path = out_path.replace_extension(path.extension().string() + extension); if (QFile::exists(out_path)) { auto ret = QMessageBox::warning( this, _("Warning"), @@ -576,16 +576,19 @@ void MainWindow::SlotFileEncryptSign() { // convert directory into tarball if (file_info.isDir()) { // stop if the process making tarball failed - if (!ProcessDirectoryIntoTarball(this, path)) { + const auto [success, target_path] = ProcessDirectoryIntoTarball(this, path); + if (!success) { QMessageBox::critical(this, _("Error"), _("Unable to convert the folder into tarball.")); return; } + // reset target + path = target_path; } CommonUtils::WaitForOpera( this, _("Encrypting and Signing"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::EncryptSignFile( + GpgFileOpera::GetInstance().EncryptSignFile( {p_keys->begin(), p_keys->end()}, {p_signer_keys->begin(), p_signer_keys->end()}, path, !non_ascii_when_export, out_path, @@ -652,7 +655,7 @@ void MainWindow::SlotFileDecryptVerify() { CommonUtils::WaitForOpera( this, _("Decrypting and Verifying"), [=](const OperaWaitingHd& op_hd) { - GpgFileOpera::DecryptVerifyFile( + GpgFileOpera::GetInstance().DecryptVerifyFile( path, out_path, [=](GpgError err, const DataObjectPtr& data_obj) { // stop waiting op_hd(); |