Add IO support
This commit is contained in:
parent
3f22ff89e7
commit
ff96e73fc7
@ -1,4 +1,4 @@
|
||||
set(SOURCES main.cpp crypto.cpp utils.cpp)
|
||||
set(SOURCES main.cpp crypto.cpp io.cpp utils.cpp)
|
||||
|
||||
add_executable(horcrux ${SOURCES})
|
||||
add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SOURCES})
|
||||
|
97
src/io.cpp
Normal file
97
src/io.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include <iostream>
|
||||
#include "io.h"
|
||||
|
||||
namespace horcrux {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
FsPlainInput::FsPlainInput(const std::string& path) : file_path(path)
|
||||
{
|
||||
if (fs::status(path).type() != fs::file_type::regular){
|
||||
throw std::invalid_argument("Input is not a regular file");
|
||||
}
|
||||
file_size = fs::file_size(file_path);
|
||||
if (file_size == 0){
|
||||
throw std::invalid_argument("Input is empty, nothing to encrypt");
|
||||
}
|
||||
file_stream = std::ifstream(file_path, std::ios::binary);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> FsPlainInput::read(){
|
||||
std::vector<unsigned char> result(file_size);
|
||||
file_stream.read(reinterpret_cast<char*>(result.data()), file_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames)
|
||||
{
|
||||
if (filenames.empty()){
|
||||
throw std::invalid_argument("No files to decrypt");
|
||||
}
|
||||
for (auto name : filenames){
|
||||
auto path = fs::path{name};
|
||||
if (fs::status(path).type() != fs::file_type::regular){
|
||||
throw std::invalid_argument("Input is not a regular file");
|
||||
}
|
||||
file_paths.emplace_back(path, fs::file_size(path));
|
||||
total_size += file_paths.back().second;
|
||||
}
|
||||
if (total_size == 0){
|
||||
throw std::invalid_argument("No data to decrypt");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> FsCryptoInput::read(){
|
||||
std::vector<unsigned char> result(total_size);
|
||||
size_t data_read{0};
|
||||
for (auto& f : file_paths){
|
||||
std::ifstream ifstream(f.first);
|
||||
ifstream.read(reinterpret_cast<char*>(result.data()) + data_read, f.second);
|
||||
data_read += f.second;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FsPlainOutput::FsPlainOutput(const std::string& filename)
|
||||
: file_path(filename)
|
||||
{
|
||||
if (fs::exists(file_path) && fs::status(file_path).type() != fs::file_type::regular){
|
||||
throw std::invalid_argument("Output file is not a regular file");
|
||||
}
|
||||
}
|
||||
size_t FsPlainOutput::write(const std::vector<unsigned char>& to_write){
|
||||
std::ofstream out(file_path, std::ios::binary);
|
||||
out.write(reinterpret_cast<const char*>(to_write.data()), to_write.size());
|
||||
return to_write.size();
|
||||
}
|
||||
|
||||
FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num, const size_t horcrux_size = 0,
|
||||
const std::string& filename = "horcrux")
|
||||
: folder_path(folder), base_name(filename),
|
||||
num(horcrux_num), size(horcrux_size)
|
||||
{
|
||||
if (fs::status(folder_path).type() != fs::file_type::directory){
|
||||
throw std::invalid_argument("Output is not a directory");
|
||||
}
|
||||
|
||||
if (horcrux_num <= 0){
|
||||
throw std::invalid_argument("Invalid horcrux num");
|
||||
}
|
||||
}
|
||||
|
||||
size_t FsCryptoOutput::write(const std::vector<unsigned char>& to_write){
|
||||
size = to_write.size() / num;
|
||||
std::ofstream f;
|
||||
created_files.clear();
|
||||
size_t data_written{0};
|
||||
for (int i = 0; i < num; ++i){
|
||||
std::string name = base_name + '_' + std::to_string(i) + ".enc";
|
||||
created_files.emplace_back(folder_path / name);
|
||||
f = std::ofstream(created_files.back(),
|
||||
std::ios::binary | std::ios::trunc);
|
||||
auto chunk_size = i + 1 != num ? size : size + to_write.size() % size;
|
||||
f.write(reinterpret_cast<const char*>(to_write.data()) + data_written, chunk_size);
|
||||
data_written += chunk_size;
|
||||
}
|
||||
return data_written;
|
||||
}
|
||||
};
|
47
src/io.h
Normal file
47
src/io.h
Normal file
@ -0,0 +1,47 @@
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
namespace horcrux {
|
||||
|
||||
class FsPlainInput {
|
||||
std::filesystem::path file_path;
|
||||
size_t file_size;
|
||||
std::ifstream file_stream;
|
||||
|
||||
public:
|
||||
FsPlainInput(const std::string& path);
|
||||
std::vector<unsigned char> read();
|
||||
};
|
||||
|
||||
class FsCryptoInput {
|
||||
std::vector<std::pair<std::filesystem::path, size_t>> file_paths;
|
||||
size_t total_size{0};
|
||||
|
||||
public:
|
||||
FsCryptoInput(const std::vector<std::string>& filenames);
|
||||
std::vector<unsigned char> read();
|
||||
};
|
||||
|
||||
class FsPlainOutput {
|
||||
std::filesystem::path file_path;
|
||||
|
||||
public:
|
||||
FsPlainOutput(const std::string& filename);
|
||||
size_t write(const std::vector<unsigned char>& to_write);
|
||||
};
|
||||
|
||||
class FsCryptoOutput {
|
||||
std::filesystem::path folder_path;
|
||||
std::string base_name;
|
||||
int num;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
std::vector<std::filesystem::path> created_files;
|
||||
|
||||
FsCryptoOutput(const std::string& folder, const int horcrux_num, const size_t horcrux_size, const std::string& filename);
|
||||
size_t write(const std::vector<unsigned char>& to_write);
|
||||
};
|
||||
};
|
@ -1,7 +1,11 @@
|
||||
set(BINARY ${CMAKE_PROJECT_NAME}_test)
|
||||
|
||||
add_executable(${BINARY} main.cpp crypto-test.cpp utils-test.cpp)
|
||||
add_executable(${BINARY} main.cpp crypto-test.cpp io-test.cpp utils-test.cpp)
|
||||
|
||||
add_test(NAME test COMMAND ${BINARY})
|
||||
|
||||
target_link_libraries(${BINARY} PUBLIC ${CMAKE_PROJECT_NAME}_lib gtest)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_work_dir
|
||||
DESTINATION ${CMAKE_BINARY_DIR})
|
||||
add_definitions(-DTEST_WORK_DIR="${CMAKE_BINARY_DIR}/test_work_dir")
|
||||
|
126
test/io-test.cpp
Normal file
126
test/io-test.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "io.cpp"
|
||||
|
||||
#ifndef TEST_WORK_DIR
|
||||
#error Please define TEST_WORK_DIR
|
||||
#endif
|
||||
|
||||
const std::string folder{TEST_WORK_DIR};
|
||||
const std::string noexist{TEST_WORK_DIR "/nope"};
|
||||
const std::string empty{TEST_WORK_DIR "/empty"};
|
||||
const std::string text{TEST_WORK_DIR "/test.txt"};
|
||||
const std::string image{TEST_WORK_DIR "/mangoni.jpg"};
|
||||
|
||||
static std::vector<unsigned char> generic_read_file(const std::string& filename){
|
||||
auto ifstream = std::ifstream{filename, std::ios::binary};
|
||||
auto path = std::filesystem::path{filename};
|
||||
auto size = std::filesystem::file_size(path);
|
||||
std::vector<unsigned char> buf(size);
|
||||
ifstream.read(reinterpret_cast<char*>(buf.data()), size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
TEST(IoTests, FsPlainInput) {
|
||||
EXPECT_THROW(horcrux::FsPlainInput input{noexist}, std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsPlainInput input{folder}, std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsPlainInput input{empty}, std::invalid_argument);
|
||||
EXPECT_NO_THROW(horcrux::FsPlainInput input{text});
|
||||
EXPECT_NO_THROW(horcrux::FsPlainInput input{image});
|
||||
}
|
||||
|
||||
TEST(IoTests, FsPlainInputReadText) {
|
||||
auto input = horcrux::FsPlainInput{text};
|
||||
auto buf = generic_read_file(text);
|
||||
EXPECT_EQ(buf, input.read());
|
||||
}
|
||||
|
||||
TEST(IoTests, FsPlainInputReadImg) {
|
||||
auto input = horcrux::FsPlainInput{image};
|
||||
auto buf = generic_read_file(image);
|
||||
EXPECT_EQ(buf, input.read());
|
||||
}
|
||||
|
||||
TEST(IoTests, FsCryptoOutput) {
|
||||
EXPECT_THROW(horcrux::FsCryptoOutput output(noexist, 1), std::invalid_argument);
|
||||
EXPECT_NO_THROW(horcrux::FsCryptoOutput output(folder, 1));
|
||||
EXPECT_THROW(horcrux::FsCryptoOutput output(folder, 0), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoOutput output(empty, 1), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoOutput output(text, 1), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoOutput output(image, 1), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(IoTests, FsCryptoOutputWriteImage){
|
||||
auto ifstream = std::ifstream{image, std::ios::binary};
|
||||
auto buf = generic_read_file(image);
|
||||
|
||||
horcrux::FsCryptoOutput out(folder, 10);
|
||||
auto written = out.write(buf);
|
||||
EXPECT_EQ(written, buf.size());
|
||||
|
||||
EXPECT_EQ(10, out.created_files.size());
|
||||
for_each(out.created_files.begin(), out.created_files.end(),
|
||||
[](auto f){std::filesystem::remove(f);});
|
||||
}
|
||||
|
||||
TEST(IoTests, FsCryptoOutputWriteText){
|
||||
auto buf = generic_read_file(text);
|
||||
|
||||
horcrux::FsCryptoOutput out(folder, 2);
|
||||
auto written = out.write(buf);
|
||||
EXPECT_EQ(written, buf.size());
|
||||
|
||||
EXPECT_EQ(2, out.created_files.size());
|
||||
for_each(out.created_files.begin(), out.created_files.end(),
|
||||
[](auto f){std::filesystem::remove(f);});
|
||||
}
|
||||
|
||||
TEST(IoTest, FsCryptoInput){
|
||||
EXPECT_THROW(horcrux::FsCryptoInput output({noexist, text, image}), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoInput output({folder, text, image}), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoInput output({}), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoInput output({empty}), std::invalid_argument);
|
||||
EXPECT_THROW(horcrux::FsCryptoInput output({empty, empty}), std::invalid_argument);
|
||||
EXPECT_NO_THROW(horcrux::FsCryptoInput output({empty, empty, text}));
|
||||
EXPECT_NO_THROW(horcrux::FsCryptoInput output({image, empty, text}));
|
||||
}
|
||||
|
||||
TEST(IoTest, FsCryptoInputImage){
|
||||
auto buf = generic_read_file(image);
|
||||
//split image using FsCryptoOutput
|
||||
auto out = horcrux::FsCryptoOutput(folder, 7);
|
||||
auto written = out.write(buf);
|
||||
EXPECT_EQ(written, buf.size());
|
||||
|
||||
std::vector<std::string> files;
|
||||
transform(out.created_files.begin(), out.created_files.end(),std::back_inserter(files), [](auto p){return p.string();});
|
||||
auto in = horcrux::FsCryptoInput(files);
|
||||
auto read = in.read();
|
||||
EXPECT_EQ(read, buf);
|
||||
|
||||
files.push_back(text);
|
||||
in = horcrux::FsCryptoInput(files);
|
||||
read = in.read();
|
||||
EXPECT_NE(read, buf);
|
||||
|
||||
for_each(out.created_files.begin(), out.created_files.end(),
|
||||
[](auto f){std::filesystem::remove(f);});
|
||||
}
|
||||
|
||||
TEST(IoTest, FsPlainOuput){
|
||||
|
||||
EXPECT_NO_THROW(horcrux::FsPlainOutput output{noexist});
|
||||
EXPECT_THROW(horcrux::FsPlainOutput output{folder}, std::invalid_argument);
|
||||
EXPECT_NO_THROW(horcrux::FsPlainOutput output{empty});
|
||||
EXPECT_NO_THROW(horcrux::FsPlainOutput output{text});
|
||||
EXPECT_NO_THROW(horcrux::FsPlainOutput output{image});
|
||||
}
|
||||
|
||||
TEST(IoTest, FsPlainOutputWrite){
|
||||
auto buf = generic_read_file(image);
|
||||
auto out = horcrux::FsPlainOutput(noexist);
|
||||
auto written = out.write(buf);
|
||||
EXPECT_EQ(written, buf.size());
|
||||
auto buf2 = generic_read_file(noexist);
|
||||
EXPECT_EQ(buf, buf2);
|
||||
std::filesystem::remove(noexist);
|
||||
}
|
0
test/test_work_dir/empty
Normal file
0
test/test_work_dir/empty
Normal file
BIN
test/test_work_dir/mangoni.jpg
Normal file
BIN
test/test_work_dir/mangoni.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
28
test/test_work_dir/test.txt
Normal file
28
test/test_work_dir/test.txt
Normal file
@ -0,0 +1,28 @@
|
||||
What's your name Catalogna
|
||||
What's your name Catalogna
|
||||
What's your name Catalogna
|
||||
What's your name Catalogna
|
||||
Cara non so perché ma quando io ti vedo mi vien da vomitare
|
||||
Forse sara' perché tu mangi troppa catalogna, catalogna
|
||||
Catalogna catalogna cata cata cata cata catalogna
|
||||
Catalogna catalogna e nessun altro tipo di verdura cotta.
|
||||
Sono andato in un centro di allevamento di cinghiali in Lunigiana
|
||||
E ti ho comprato un cinghialino, l'ho arrostito e l'ho riempito
|
||||
Con un tacchino di terra cotta ripieno di un piccione vivo con il verme
|
||||
In bocca, ho arrostito tutto insieme te l'ho portato, oh, non l'hai
|
||||
Mangiato eri immersa in una vasca di catalogna. Non si fa cosi'!
|
||||
Catalogna catalogna cata cata cata cata catalogna
|
||||
Catalogna catalogna cata cata cata cata catalogna
|
||||
Non puoi mangiare solo catalogna
|
||||
E' una dieta costituita da un elemento solo
|
||||
Non mi puoi far credere che questo sia sufficiente
|
||||
Alla tua corretta crescita, perdi i capelli,
|
||||
Non puoi vivere mangiando solo catalogna,
|
||||
Non mi puoi convincere di questo fatto.
|
||||
Ehi... ma... no... amore ma... solo ora invece capisco
|
||||
Che la catalogna effettivamente ci permette di condurre
|
||||
Una vita psichicamente corretta e anche sessualmente
|
||||
Fantastica! Si', ho capito, infilami la catalogna nel culo,
|
||||
Voglio fare all'amore con te, infilamela nei capezzoli,
|
||||
Voglio godere tantissimo!...
|
||||
Siamo cresciuti mangiando verdura voglio morire con te
|
Loading…
Reference in New Issue
Block a user