feat: avoid reading entire file to memory
This commit is contained in:
parent
f8733b9b2b
commit
566d5e41a3
@ -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");
|
||||
}
|
||||
RunGpgOperaAsync(
|
||||
[=](const DataObjectPtr& data_object) -> GpgError {
|
||||
GpgData data_in(in_path, true);
|
||||
GpgData data_out(out_path, false);
|
||||
|
||||
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);
|
||||
auto err = CheckGpgError(
|
||||
gpgme_op_decrypt(ctx_.DefaultContext(), data_in, data_out));
|
||||
data_object->Swap(
|
||||
{GpgDecryptResult(gpgme_op_decrypt_result(ctx_.DefaultContext()))});
|
||||
|
||||
if (CheckGpgError(err) == GPG_ERR_NO_ERROR &&
|
||||
!WriteFileGFBuffer(out_path, buffer)) {
|
||||
throw std::runtime_error("write buffer to file error");
|
||||
}
|
||||
|
||||
cb(err, TransferParams(result));
|
||||
});
|
||||
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");
|
||||
}
|
||||
RunGpgOperaAsync(
|
||||
[=](const DataObjectPtr& data_object) -> GpgError {
|
||||
GpgError err;
|
||||
|
||||
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);
|
||||
// Set Singers of this opera
|
||||
GpgBasicOperator::GetInstance().SetSigners(keys, ascii);
|
||||
|
||||
if (CheckGpgError(err) == GPG_ERR_NO_ERROR &&
|
||||
!WriteFileGFBuffer(out_path, buffer)) {
|
||||
throw std::runtime_error("write buffer to file error");
|
||||
}
|
||||
cb(err, TransferParams(result));
|
||||
});
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
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));
|
||||
}
|
||||
auto result = ExtractParams<GpgVerifyResult>(data_object, 0);
|
||||
cb(err, TransferParams(result));
|
||||
});
|
||||
|
||||
data_object->Swap({
|
||||
GpgVerifyResult(gpgme_op_verify_result(ctx_.DefaultContext())),
|
||||
});
|
||||
|
||||
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");
|
||||
}
|
||||
RunGpgOperaAsync(
|
||||
[=](const DataObjectPtr& data_object) -> GpgError {
|
||||
GpgError err;
|
||||
std::vector<gpgme_key_t> recipients(keys.begin(), keys.end());
|
||||
|
||||
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));
|
||||
});
|
||||
// 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");
|
||||
}
|
||||
RunGpgOperaAsync(
|
||||
[=](const DataObjectPtr& data_object) -> GpgError {
|
||||
GpgData data_in(in_path, true);
|
||||
GpgData data_out(out_path, false);
|
||||
|
||||
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;
|
||||
}
|
||||
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)),
|
||||
});
|
||||
|
||||
if (!WriteFileGFBuffer(out_path, buffer)) {
|
||||
throw std::runtime_error("write buffer to file error");
|
||||
}
|
||||
|
||||
cb(err, TransferParams(result));
|
||||
});
|
||||
return err;
|
||||
},
|
||||
cb, "gpgme_op_encrypt_symmetric", "2.1.0");
|
||||
}
|
||||
|
||||
} // namespace GpgFrontend
|
@ -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,8 +40,17 @@ 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
|
||||
*
|
||||
@ -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
|
||||
|
@ -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
|
@ -54,12 +54,32 @@ class GPGFRONTEND_CORE_EXPORT GpgData {
|
||||
*/
|
||||
GpgData(const void* buffer, size_t size, bool copy = true);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
auto path_qstr = file_tree_view->GetSelected();
|
||||
auto path = ConvertPathByOS(path_qstr);
|
||||
if (!PathPreCheck(this, path)) return;
|
||||
|
||||
#ifdef WINDOWS
|
||||
std::filesystem::path in_path = path.toStdU16String();
|
||||
#else
|
||||
std::filesystem::path in_path = path.toStdString();
|
||||
#endif
|
||||
|
||||
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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user