diff --git a/.gitignore b/.gitignore index 1b9f212..47fe4dc 100644 --- a/.gitignore +++ b/.gitignore @@ -371,4 +371,14 @@ x64/ test.* pest2.* *.hh -*.key \ No newline at end of file +*.key +test3/ +test4/ +test5/ +test6/ +test7/ +test8/ +test9/ +test10/ +testx/ +testv/ \ No newline at end of file diff --git a/CompressingManager.cpp b/CompressingManager.cpp deleted file mode 100644 index 74d0b93..0000000 --- a/CompressingManager.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "CompressingManager.h" - -CompressingManager::CompressingManager() -{ } - -CompressingManager::~CompressingManager() -{ } - -//----------------------------------------------------------------------------- -// Kompresja blokowa -// -// Dzielenie vectora na chunki dokładnie po 128KB -// Kompresowanie chunków bez nagłówka -//----------------------------------------------------------------------------- -std::vector CompressingManager::compress(const std::vector& raw) -{ - //std::vector blockSizes; - - // Maksymalny rozmiar chunka - const size_t maxBlockSize = BLOCK_SIZE; - const size_t rawSize = raw.size(); - - uint16_t blockLen = 0; - uint32_t lastChunkRawSize; - std::vector compressedBlocks; - for (size_t offset = 0; offset < rawSize; offset += maxBlockSize) - { - // Rozmiar chunka - const size_t chunkSize = std::min(maxBlockSize, rawSize - offset); - - auto begin = raw.begin() + offset; - auto end = begin + chunkSize; - - // Skopiuj fragment danych do chunka - std::vector chunk(begin, end); - - // Obliczanie rozmiaru skompresowanego bloku - int maxZipChunkSize = LZ4_compressBound(chunkSize); - - // Buffor wyjściowy nadpisany skompresowanymi danymi - std::vector zipChunk(maxZipChunkSize); - - // Kompresja - int zipSize = LZ4_compress_default(chunk.data(), zipChunk.data(), chunkSize, maxZipChunkSize); - - // Zmiana rozmiaru do faktycznego rozmiaru po kompresji - zipChunk.resize(zipSize); - - uint32_t chs = chunk.size(); - uint32_t zch = zipChunk.size(); - - //addIntToVector(compressedBlocks, chs); - lastChunkRawSize = chs; - addIntToVector(compressedBlocks, zch); - compressedBlocks.insert(compressedBlocks.end(), zipChunk.begin(), zipChunk.end()); - - blockLen++; - } - - std::vector zip; - // Wstaw liczbę o ilości bloków do vectora; - // Przekonpwertuj usigned int32 na ciąg znkaów - //uint16_t blockLen = blockSizes .size(); - addIntToVector(zip, blockLen); - addIntToVector(zip, maxBlockSize); - addIntToVector(zip, lastChunkRawSize); - - // Dodaj skompresowane dane - zip.insert(zip.end(), compressedBlocks.begin(), compressedBlocks.end()); - - return zip; -} - -////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// Dekompresja blokowa -//----------------------------------------------------------------------------- -std::vector CompressingManager::decompress(const std::vector& zip) -{ - size_t offset = 0; - const uint16_t chunkLen = getIntFromVector(zip, offset); - const uint32_t chunkBeforeSize = getIntFromVector(zip, offset); - const uint32_t chunkLastSize = getIntFromVector(zip, offset); - - std::vector chunksString; - - // Dekompresja bloków - for (size_t i = 0; i < chunkLen; ++i) - { - // Pobierz rozmiar chunków przed i po skompresowaniem - uint32_t chunkSize = i < chunkLen - 1 ? chunkBeforeSize : chunkLastSize; - uint32_t chunkZipSize = getIntFromVector(zip, offset); - - // Pobierz blok chunka - std::vector zipChunk(chunkZipSize); - std::memcpy(zipChunk.data(), zip.data() + offset, chunkZipSize); - offset += chunkZipSize; - - // Zdeklarój pusty chunk - std::vector chunk(chunkSize); - - // Dekompresja chunka - int sizeData = LZ4_decompress_safe(zipChunk.data(), chunk.data(), static_cast(chunkZipSize), static_cast(chunkSize)); - - if (sizeData < 0) - { - throw std::runtime_error("LZ4 Decompressing Error"); - } - - // Dostosowanie rozmiaru vectora po skompresowaniu - chunk.resize(sizeData); - - // Scal chunki - chunksString.insert(chunksString.end(), chunk.begin(), chunk.end()); - } - - return chunksString; -} \ No newline at end of file diff --git a/CompressingManager.h b/CompressingManager.h deleted file mode 100644 index e3fd839..0000000 --- a/CompressingManager.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#define BLOCK_SIZE 131072 // 128KB - -struct BlockSize -{ - uint32_t raw; - uint32_t zip; -}; - -class CompressingManager -{ -public: - CompressingManager(); - ~CompressingManager(); - - // Kompresja danych - std::vector compress(const std::vector&); - - // Dekompresja - std::vector decompress(const std::vector&); - -private: - std::vector blockSizes; - - // Przekonwertuj zmienną na ciąg na vector - template - void addIntToVector(std::vector& vec, const T& val) - { - size_t tmpSize = vec.size(); - vec.resize(tmpSize + sizeof(val)); - std::memcpy(vec.data() + tmpSize, &val, sizeof(val)); - } - - // Pobierz zmienną z vectora - template - T getIntFromVector(const std::vector& vec, size_t& offset) - { - T tmp{}; - std::memcpy(&tmp, vec.data() + offset, sizeof(tmp)); - offset += sizeof(tmp); - - return tmp; - } -}; - diff --git a/CompressionManager.cpp b/CompressionManager.cpp new file mode 100644 index 0000000..0c934b8 --- /dev/null +++ b/CompressionManager.cpp @@ -0,0 +1,111 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "CompressionManager.h" + +CompressionManager::CompressionManager() + :cctx(ZSTD_createCCtx()) + ,dctx(ZSTD_createDCtx()) +{ + // Ustawienia frameless + size_t rc = 0; + + // Wyłącza ramkę i przestawia strumień na czyste bloki + rc |= ZSTD_CCtx_setParameter(cctx, ZSTD_c_format, ZSTD_f_zstd1_magicless); + + // Wyłącza sumę kontrolną na poziomie ramki + rc |= ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0); + + // Wyłącza zapisywanie „content size” w nagłówku ramki + rc |= ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0); + + // Wyłącza zapisywanie identyfikatora słownika + rc |= ZSTD_CCtx_setParameter(cctx, ZSTD_c_dictIDFlag, 0); + + // Ustawia poziom kompresji + rc |= ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, zstd::compression_level); + + if (ZSTD_isError(rc)) { + std::cerr << "ZSTD_CCtx_setParameter error" << std::endl; + ZSTD_freeCCtx(cctx); + } + + /*====Tutaj Dekompresja=============================================================*/ + + size_t r = 0; + + // Przestawia dekompresję na czyste bloki bez nagłówka + r |= ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, ZSTD_f_zstd1_magicless); + if (ZSTD_isError(r)) + { + std::cerr << "ZSTD_DCtx_setParameter error" << std::endl; + ZSTD_freeDCtx(dctx); + } +} + +CompressionManager::~CompressionManager() +{ + ZSTD_freeCCtx(cctx); + ZSTD_freeDCtx(dctx); +} + +//----------------------------------------------------------------------------- +// Kompresja ZSTD frameless +//----------------------------------------------------------------------------- +std::vector CompressionManager::compress(const std::vector& input) +{ + // Obsługa pustego chunku: zwracamy pusty wynik (0 bajtów). + if (input.empty()) return {}; + + const size_t srcSize = input.size(); + + // Szacowanie rozmiaru skompresowanego vectoru + const size_t maxDst = ZSTD_compressBound(srcSize); + + std::vector out(maxDst); + + // Faktyczna kompresja + size_t written = ZSTD_compress2(cctx, out.data(), maxDst, + input.data(), srcSize); + + if (ZSTD_isError(written)) { + std::cerr << "ZSTD_compress error: " << ZSTD_getErrorName(written) << std::endl; + return {}; + } + + out.resize(written); + return out; +} + +//----------------------------------------------------------------------------- +// Dekompresja ZSTD +//----------------------------------------------------------------------------- +std::vector CompressionManager::decompress(const std::vector& input, const size_t& expected) +{ + std::vector output(expected); + + size_t dsize = ZSTD_decompressDCtx(dctx, output.data(), expected, input.data(), input.size()); + + if (ZSTD_isError(dsize)) { + std::cerr << "ZSTD_decompressDCtx error: " << ZSTD_getErrorName(dsize) << "\n"; + return {}; + } + + return output; +} \ No newline at end of file diff --git a/CompressionManager.h b/CompressionManager.h new file mode 100644 index 0000000..5f747fb --- /dev/null +++ b/CompressionManager.h @@ -0,0 +1,51 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#define ZSTD_STATIC_LINKING_ONLY +#include + +#if ZSTD_VERSION_NUMBER < 10400 +#error "Wymagane zstd >= 1.4.0 dla ZSTD_c_format / ZSTD_f_zstd1_magicless" +#endif + +namespace zstd +{ + inline constexpr short compression_level = 3; +} + +class CompressionManager +{ +public: + CompressionManager(); + ~CompressionManager(); + + std::vector compress(const std::vector&); + std::vector decompress(const std::vector&, const size_t&); + +private: + ZSTD_CCtx* cctx; + ZSTD_DCtx* dctx; +}; + diff --git a/CreateCargo.cpp b/CreateCargo.cpp index cac09a2..fe6f7aa 100644 --- a/CreateCargo.cpp +++ b/CreateCargo.cpp @@ -20,13 +20,15 @@ #include "CreateCargo.h" CreateCargo::CreateCargo() - : signature(SIGNATURE) - , extension(EXTENSION) - , version(VERSION) + : signature(fl::sigpak) + , extension(fl::extpak) , methodFlags(0) + , xxhState(XXH64_createState()) , offset(0) + , hppKey(false) { // TODO Auto-generated constructor stub + XXH64_reset(xxhState, 0); } CreateCargo::~CreateCargo() { @@ -37,7 +39,7 @@ CreateCargo::~CreateCargo() { //----------------------------------------------------------------------------- // Punk wejścia do tworzenia archivum //----------------------------------------------------------------------------- -bool CreateCargo::Create(const std::string& path, int8_t flag) +bool CreateCargo::Create(const std::string& path, const uint8_t& flag) { cargoFile = path + "." + extension; catalogPath = path; @@ -56,14 +58,6 @@ bool CreateCargo::Create(const std::string& path, int8_t flag) return false; } - //Pobieranie listy plików do spakowania - std::cout << "Creating a file list..." << std::endl; - if (!GetFileList(path)) - { - std::cerr << "Error: The specified directory contains no files!" << std::endl; - return false; - } - // Pobieranie listy plików wyjątków if (flag == -1) { @@ -76,6 +70,14 @@ bool CreateCargo::Create(const std::string& path, int8_t flag) GetFilters(filterFile); } + //Pobieranie listy plików do spakowania + std::cout << "Creating a file list..." << std::endl; + if (!GetFileList(path)) + { + std::cerr << "Error: The specified directory contains no files!" << std::endl; + return false; + } + // Utworzenie kontenera cargo.open(cargoFile, std::ios::binary); @@ -86,6 +88,12 @@ bool CreateCargo::Create(const std::string& path, int8_t flag) return false; } + // Zapisywanie klucza szyfrującego + if (flag == flag::enc || flag == flag::ezd || encList.size() > 0) + { + eman.saveKey(catalogPath, hppKey); + } + return true; } @@ -103,14 +111,43 @@ bool CreateCargo::GetFileList(const std::string& path) } else { - if (CheckIgnorePath(tmpPath)) + std::string fileRef = RemoveStartPath(PathToUnixLike(tmpPath)); + + if (fileRef.length() > 255) { - filesList.push_back(PathToUnixLike(tmpPath)); + std::cerr << "The file path is too long. It exceeds 255 characters." << std::endl; + } + else + { + PathConf pc; + if (methodFlags != 0xAB) + { + pc.path = PathToUnixLike(tmpPath); + pc.parameter = methodFlags; + filesPaths.push_back(pc); + } + else + { + if (!FindOnTheList(ignoreList, fileRef) || !CheckFileExtension(fileRef, ignoreList)) + { + if (FindOnTheList(zipList, fileRef) || CheckFileExtension(fileRef, zipList)) + { + pc.parameter = FindOnTheList(encList, fileRef) || CheckFileExtension(fileRef, encList) ? flag::ezd : flag::zip; + } + else + { + pc.parameter = FindOnTheList(encList, fileRef) || CheckFileExtension(fileRef, encList) ? flag::enc : flag::raw; + } + pc.path = PathToUnixLike(tmpPath); + std::cout << pc.path << " - " << pc.parameter << std::endl; + filesPaths.push_back(pc); + } + } } } } - return filesList.size() > 0 ? true : false; + return filesPaths.size() > 0 ? true : false; } //----------------------------------------------------------------------------- @@ -147,49 +184,13 @@ CargoHead CreateCargo::CreateCargoHead(const uint32_t& filesLen, const uint64_t& { CargoHead ch; - ch.signature = signature; - ch.version = version; - ch.files = filesLen; + ch.signature = fl::sigpak; ch.table = table; + ch.files = filesLen; return ch; } -//----------------------------------------------------------------------------- -// Sprawdza czy plik znajduje się na liście -//----------------------------------------------------------------------------- -uint8_t CreateCargo::CheckFileOnTheList(const std::string& path, std::vector& input, std::vector& output) -{ - //Flaga aktywna sprawdza czy plik jest na liście. Jeśli jest to zwraca surowedane - //Przeciwnie kompresuje dane - CompressingManager cm; - - // Kompresja - if (methodFlags == 1) - { - output = cm.compress(input); - return 1; - } - - // Szyfrowanie - if (methodFlags == 2) - { - output = crypt.encrypt(input); - return 2; - } - - // Kompresja i szyfrowanie - if (methodFlags == 3) - { - output = crypt.encrypt(cm.compress(input)); - return 1; - } - - // Zwraca surowe dane - output = std::move(input); - return 0; -} - //----------------------------------------------------------------------------- // Przygotowanie nagłówków i plików //----------------------------------------------------------------------------- @@ -197,52 +198,123 @@ std::vector CreateCargo::ComputingHeadFiles() { //Utwórz header TMP. Zabezpiecza Pierwsze bajty na właściwy nagłówek CargoHead cargoHead = CreateCargoHead(0, 0); - offset += cargoHead.signature.length() + sizeof(cargoHead.version) + sizeof(cargoHead.files) + sizeof(cargoHead.table); + offset += cargoHead.signature.length() + sizeof(cargoHead.files) + sizeof(cargoHead.table); - //Zapisanie TMP nagłowka do pliku + //Zapisanie tymczasowego nagłowka jako rezerwacja miejsca cargo.write(cargoHead.signature.data(), cargoHead.signature.length()); - cargo.write(reinterpret_cast(&cargoHead.version), sizeof(cargoHead.version)); - cargo.write(reinterpret_cast(&cargoHead.files), sizeof(cargoHead.files)); cargo.write(reinterpret_cast(&cargoHead.table), sizeof(cargoHead.table)); + cargo.write(reinterpret_cast(&cargoHead.files), sizeof(cargoHead.files)); std::vector filesTable; - //Tworzenie nagłówków plików - for (const auto& file : filesList) + //Tworzenie nagłówków plików jednocześnie zapisywanie plików + for (const auto& file : filesPaths) { - std::string path = PathToUnixLike(RemoveStartPath(file)); - std::ifstream f(file, std::ios::binary | std::ios::ate); + std::string path = PathToUnixLike(RemoveStartPath(file.path)); + std::ifstream f(file.path, std::ios::binary | std::ios::ate); + + std::cout << path << std::endl; //Obliczanie rozmiaru pliku size_t size = f.tellg(); f.seekg(0, std::ios::beg); - //Wczytanie pliku do pamięci - std::vector buffor(size); - f.read(buffor.data(), size); - f.close(); + if (size > ds::maxFileSize) + { + std::cerr << path << " is too large. It exceeds " << ds::maxFileSize / 1024 / 1024 / 1024 << "GB!" << std::endl; + } + else + { + XXH64_reset(xxhState, 0); - //Tworzenie hashu CRC - const uint64_t crc = XXH64(buffor.data(), buffor.size(), VERSION); + //Wczytanie pliku do pamięci + std::vector buffer(ds::chunk_stream); - //Kompresjia - std::vector zip; - uint8_t method = CheckFileOnTheList(path, buffor, zip); + uint64_t sizeFile = 0; - FilesTable ft; - ft.nameFile = path; - ft.nameLen = path.length(); - ft.hashName = fnv64(path); - ft.offset = offset; - ft.size = zip.size(); - ft.isZip = method; - ft.crc = crc; + const uint32_t chunkBlockSize = ds::block_size; + const uint32_t quantity = (size + chunkBlockSize) / chunkBlockSize; + const uint32_t lastChunkSize = size - (chunkBlockSize * (quantity - 1)); - cargo.write(reinterpret_cast(zip.data()), zip.size()); + // Jeśli jest ustawiona flaga inna niż RAW + // Dodaj do kontenera konfigurację chunków + if (file.parameter != flag::raw) + { + cargo.write(reinterpret_cast(&quantity), sizeof(quantity)); + cargo.write(reinterpret_cast(&chunkBlockSize), sizeof(chunkBlockSize)); + cargo.write(reinterpret_cast(&lastChunkSize), sizeof(lastChunkSize)); + sizeFile = sizeof(quantity) + sizeof(chunkBlockSize) + sizeof(lastChunkSize); + } - filesTable.push_back(ft); - offset += zip.size(); + // Strumieniowanie danych + while (f.read(buffer.data(), ds::chunk_stream) || f.gcount() > 0) + { + const int bufferSize = f.gcount(); + buffer.resize(bufferSize); + + // Aktualizacja XXH64 + XXH64_update(xxhState, buffer.data(), buffer.size()); + + if (file.parameter == flag::raw) + { + // Zapisywanie strumienia do kontenera + cargo.write(reinterpret_cast(buffer.data()), buffer.size()); + sizeFile += bufferSize; + } + else + { + for (uint32_t ofs = 0; ofs < bufferSize; ofs += chunkBlockSize) + { + // Rozmiar chunka + const uint32_t chunkSize = std::min(chunkBlockSize, bufferSize - ofs); + + auto begin = buffer.begin() + ofs; + auto end = begin + chunkSize; + + // Skopiuj fragment danych do chunka + std::vector chunk(begin, end); + + std::vector outChunk; + + // Przetwórz chunki i przetwórz + if ((file.parameter & flag::zip) == flag::zip) + { + // Zaszyfruj i skompresuj lub tylko skompresuj + outChunk = (file.parameter & flag::enc) == flag::enc ? + eman.encrypt(cman.compress(chunk)) : cman.compress(chunk); + } + else + { + // Zaszyfruj lub skopiuj + outChunk = eman.encrypt(chunk); + } + + const uint32_t outSize = outChunk.size(); + + cargo.write(reinterpret_cast(&outSize), sizeof(outSize)); + sizeFile += sizeof(outSize); + + cargo.write(reinterpret_cast(outChunk.data()), outChunk.size()); + sizeFile += outSize; + } + } + } + + f.close(); + + FilesTable ft; + ft.nameFile = path; + ft.nameLen = path.length(); + ft.offset = offset; + ft.size = sizeFile; + ft.flag = file.parameter; + ft.crc = XXH64_digest(xxhState); + + filesTable.push_back(ft); + offset += sizeFile; + } } + return filesTable; } @@ -259,42 +331,26 @@ void CreateCargo::GetFilters(const std::string& filterFile) file.close(); // Lista plików do skompresowania - std::vector zip = jslist[KEY_ZIP].get>(); + if (jslist.contains(key::zip)) + { + zipList = jslist[key::zip].get>(); + } // Lista plików do zaszyfrowania - std::vector enc = jslist[KEY_ENCRYPT].get>(); + if (jslist.contains(key::enc)) + { + encList = jslist[key::enc].get>(); + } // Lista plików do pominięcia - std::vector ignore = jslist[KEY_IGNORE].get>(); - - PrepareList(zip, enc, ignore); -} - -//----------------------------------------------------------------------------- -// Przygotuj listę plików do spakowania -//----------------------------------------------------------------------------- -void CreateCargo::PrepareList(const std::vector& zip, const std::vector& enc, const std::vector& ignore) -{ - PathConf pc; - - for (const auto& item : filesList) + if (jslist.contains(key::ignore)) { - if (!FindOnTheList(ignore, item)) - { - if (FindOnTheList(zip, item)) - { - pc.parameter = FindOnTheList(enc, item) ? 3 : 1; - } - else - { - pc.parameter = FindOnTheList(enc, item) ? 2 : 0; - } - pc.path = item; - filesPaths.push_back(pc); - } + ignoreList = jslist[key::ignore].get>(); } -} + // Flaga tworzenia klucza jako plik nagłówka c++ + hppKey = jslist.value(key::hpp, false); +} //----------------------------------------------------------------------------- // Znajdź wskazany element na liście @@ -305,33 +361,23 @@ bool CreateCargo::FindOnTheList(const std::vector& list, const std: return it == list.end() ? false : true; } -//----------------------------------------------------------------------------- -// Rozdzielanie paternu od ścieżki -//----------------------------------------------------------------------------- -void CreateCargo::ExtPatternAndPathDetection(const std::vector& data, std::vector& pattern, std::vector& path) -{ - for (const auto& d : data) - { - if (d.front() == '*') - { - std::string tmpPattern = d; - tmpPattern.erase(tmpPattern.begin()); - pattern.push_back(UpperString(tmpPattern)); - } - else - { - path.push_back(d); - } - } -} - //----------------------------------------------------------------------------- // Sprawdzanie rozszeżeń plików //----------------------------------------------------------------------------- -bool CreateCargo::CheckFileExtension(const std::filesystem::path& p, const std::vector& patterns) { - std::string ext = UpperString(p.extension().string()); +bool CreateCargo::CheckFileExtension(const std::string& p, const std::vector& patterns) { + std::filesystem::path _p = p; + std::string ext = "*" + UpperString(_p.extension().string()); - return FindOnTheList(patterns, ext); + for (const auto& e : patterns) + { + std::string element = UpperString(e); + if (element == ext) + { + return true; + } + } + + return false; } //----------------------------------------------------------------------------- @@ -343,87 +389,6 @@ std::string CreateCargo::UpperString(std::string s) { return s; } -//----------------------------------------------------------------------------- -// Wygenerój FNV-1a HASH -//----------------------------------------------------------------------------- -uint64_t CreateCargo::fnv64(const std::string& data) -{ - const uint64_t fnvOffset = 14695981039346656037u; - const uint64_t fnvPrime = 1099511628211u; - - uint64_t hash = fnvOffset; - for (unsigned char c : data) - { - hash ^= c; - hash *= fnvPrime; - } - - return hash; -} - -//----------------------------------------------------------------------------- -// Sprawdzanie czy plik znajduje się na liście -//----------------------------------------------------------------------------- -bool CreateCargo::FilteringData(const std::string& path) -{ - std::vector cmPatterns; - std::vector cmPaths; - - // Rozdziel ścieżki i patterny na osobne listy - ExtPatternAndPathDetection(zipList, cmPatterns, cmPaths); - - if (FindOnTheList(cmPatterns, ALL_FILE)) - { - return true; - } - - // Sprawdż czy istnieje plik o danym rozszeżeniu - if (CheckFileExtension(path, cmPatterns)) - { - return true; - } - - // Sprawdź czy instnieje dany plik w danej lokalizacji - if (FindOnTheList(cmPaths, path)) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Kasowanie z listy plików ignorow -//----------------------------------------------------------------------------- -bool CreateCargo::CheckIgnorePath(const std::string& path) -{ - std::vector igPatterns; - std::vector igPaths; - - ExtPatternAndPathDetection(ignoreList, igPatterns, igPaths); - - // Sprawdż czy istnieje plik o danym rozszeżeniu - if (CheckFileExtension(path, igPatterns)) - { - return false; - } - - // Obrubka ścierzki - // Usuwanie katalogu root - std::string cleanPath = RemoveStartPath(path); - - // Przekształcenie ścierzki na format unixowy - std::string unixPath = PathToUnixLike(cleanPath); - - // Sprawdź czy instnieje dany plik w danej lokalizacji - if (FindOnTheList(igPaths, unixPath)) - { - return false; - } - - return true; -} - //----------------------------------------------------------------------------- // Trworzenie archiwum //----------------------------------------------------------------------------- @@ -431,7 +396,7 @@ bool CreateCargo::WriteCargo() { std::cout << "Packing files..." << std::endl; - uint32_t filesLen = filesList.size(); + uint32_t filesLen = filesPaths.size(); //Przygotowanie nagłówków plików i przetworzenie danych std::vector filesHead = ComputingHeadFiles(); @@ -450,11 +415,10 @@ bool CreateCargo::WriteCargo() cargo.write(reinterpret_cast(&head.nameLen), sizeof(head.nameLen)); cargo.write(head.nameFile.data(), head.nameLen); - cargo.write(reinterpret_cast(&head.hashName), sizeof(head.hashName)); cargo.write(reinterpret_cast(&head.offset), sizeof(head.offset)); cargo.write(reinterpret_cast(&head.size), sizeof(head.size)); cargo.write(reinterpret_cast(&head.crc), sizeof(head.crc)); - cargo.write(reinterpret_cast(&head.isZip), sizeof(head.isZip)); + cargo.write(reinterpret_cast(&head.flag), sizeof(head.flag)); } //Cofnij się na początek pliku @@ -465,15 +429,11 @@ bool CreateCargo::WriteCargo() //Nadpisz tymczasowy nagłówek cargo.write(cargoHead.signature.data(), cargoHead.signature.length()); - cargo.write(reinterpret_cast(&cargoHead.version), sizeof(cargoHead.version)); - cargo.write(reinterpret_cast(&cargoHead.files), sizeof(cargoHead.files)); cargo.write(reinterpret_cast(&cargoHead.table), sizeof(cargoHead.table)); + cargo.write(reinterpret_cast(&cargoHead.files), sizeof(cargoHead.files)); cargo.close(); - // Zapisywanie klucza szyfrującego - //crypt.saveKey(catalogPath); - std::cout << "The container was successfully created! " << cargoFile << std::endl; return true; diff --git a/CreateCargo.h b/CreateCargo.h index ab2d93b..279930f 100644 --- a/CreateCargo.h +++ b/CreateCargo.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -34,26 +33,32 @@ #include #include "DataStruct.h" -#include "Txtpp.h" -#include "CompressingManager.h" #include "EncryptionManager.h" +#include "CompressionManager.h" +#define KEY_ZIP "compress" // Pliki do skompresowania +#define KEY_RAW "raw" // Pliki które mają pozostać w oryginalnej formie +#define KEY_IGNORE "ignore" // Pliki pominięte przy pakowaniu +#define KEY_ENCRYPT "encrypt" // Plili które mają być zaszyfrowane +#define ALL_FILE ".*" // Wszystkie pliki -#define COMPRESSION_LEVEL 12 // Poziom kompresji plików (3 < 12) +namespace key +{ + inline constexpr std::string_view zip = "compress"; + inline constexpr std::string_view raw = "raw"; + inline constexpr std::string_view enc = "encrypt"; + inline constexpr std::string_view ignore = "ignore"; + inline constexpr std::string_view all = ".*"; -#define KEY_ZIP "COMPRESS" // Pliki do skompresowania -#define KEY_RAW "RAW" // Pliki które mają pozostać w oryginalnej formie -#define KEY_IGNORE "IGNORE" // Pliki pominięte przy pakowaniu -#define KEY_ENCRYPT "ENCRYPT" // Plili które mają być zaszyfrowane - -#define ALL_FILE ".*" // Wszystkie pliki + inline constexpr std::string_view hpp = "keyhpp"; +} struct PathConf { std::string path; - int8_t parameter; + uint8_t parameter; }; class CreateCargo { @@ -62,14 +67,15 @@ public: virtual ~CreateCargo(); // Punk wejścia do tworzenia archivum - bool Create(const std::string&, int8_t); + bool Create(const std::string&, const uint8_t&); private: const std::string signature; const std::string extension; - const uint8_t version; - int8_t methodFlags; + uint8_t methodFlags; + + XXH64_state_t* xxhState; std::string catalogPath; @@ -78,11 +84,14 @@ private: std::vector filesList; - EncryptionManager crypt; + EncryptionManager eman; + CompressionManager cman; + bool hppKey; // listy wyjątków std::vector ignoreList; std::vector zipList; + std::vector encList; // Główna lista plików z parametrami std::vector filesPaths; @@ -92,7 +101,6 @@ private: uint64_t offset; - // Tworzenie listy plików do spakowania bool GetFileList(const std::string&); @@ -111,34 +119,16 @@ private: // Przygotowanie nagłówków i plików std::vector ComputingHeadFiles(); - // Sprawdzanie czy plik znajduje się na liście - bool FilteringData(const std::string&); - // Wczytanie filtrów wyjątków void GetFilters(const std::string&); - // Sprawdza czy plik znajduje się na liście - uint8_t CheckFileOnTheList(const std::string&, std::vector&, std::vector&); - - // Kasowanie z listy plików ignorow - bool CheckIgnorePath(const std::string&); - // Sprawdzanie rozszeżeń plików - bool CheckFileExtension(const std::filesystem::path&, const std::vector&); + bool CheckFileExtension(const std::string&, const std::vector&); // Zamień cały ciąg na duże litery std::string UpperString(std::string); - // Wygenerój FNV-1a HASH - uint64_t fnv64(const std::string& data); - - // Rozdzielanie paternu od ścieżki - void ExtPatternAndPathDetection(const std::vector&, std::vector&, std::vector&); - // Znajdź wskazany element na liście bool FindOnTheList(const std::vector&, const std::string&); - - // Przygotuj listę plików do spakowania - void PrepareList(const std::vector&, const std::vector&, const std::vector&); }; diff --git a/DataStruct.h b/DataStruct.h index 8136b69..91bf253 100644 --- a/DataStruct.h +++ b/DataStruct.h @@ -22,55 +22,61 @@ #include #include -#define EXTENSION "pak" -#define SIGNATURE "XPAK" - -#define SIGNATURE_KEY_FILE 1497713496 // XKEY - -#define VERSION 100 - -enum StoreMethod +namespace ui { - FILTERING = -1, - RAW = 0, - COMPRESS = 1, - ENCRYPT = 2, - COMPRESSxENCRYPT = 3 -}; + inline constexpr std::string_view title = "exPak"; + inline constexpr std::string_view ver = "0.5"; +} +// Pliki +namespace fl +{ + inline constexpr std::string_view sigpak = "XPAK"; + inline constexpr std::string_view sigkey = "XKEY"; -//Prgoram title -#define PROGRAM_TITLE "eXtendet PAK" -#define PROGRAM_VERSION "v1.1" -#define PROGRAM_AUTHOR "Yanczi" -#define PROGRAM_COMPILING "24 October 2025" -#define PROGRAM_LICENSE "GNU LGPL v3" + inline constexpr std::string_view extpak = "pak"; + inline constexpr std::string_view extkey = "key"; +} -//Limity -#define MAX_FILE_SIZE 2147483648 // 2GB -#define MAX_PAK_SIZE 8796093022208 // 8TB +// Size +namespace ds +{ + // Chunki streamowania + inline constexpr uint32_t chunk_stream = 268435456; // 256MB -// Metody zapisania pliku -#define RAW_FILE 0 -#define ZIP_FILE 1 -#define CRYPT_FILE 2 -#define CRYPT_ZIP 3 + // Blok chunków + inline constexpr uint32_t block_size = 131072; // 128KB + + // Maksymalny rozmiar pliku do spakowania + inline constexpr uint64_t maxFileSize = 8589934592; // 8GB +} + +// Flagi +namespace flag +{ + inline constexpr uint8_t raw = 0x00; // Surowy plik + inline constexpr uint8_t zip = 0x0F; // Kompresja + inline constexpr uint8_t enc = 0xF0; // Szyfrowanie + inline constexpr uint8_t ezd = 0xFF; // Kompresja z szyfrowaniem + + // Flaga do aktywacji filtra zdefiniowanego w json + inline constexpr uint8_t filter = 0xAB; +} struct CargoHead { std::string signature; - uint16_t version; - uint32_t files; + uint8_t version; uint64_t table; + uint32_t files; }; struct FilesTable { uint8_t nameLen; std::string nameFile; - uint64_t hashName; uint64_t offset; - uint32_t size; + uint64_t size; uint64_t crc; - uint8_t isZip; + uint8_t flag; }; \ No newline at end of file diff --git a/EncryptionManager.cpp b/EncryptionManager.cpp index ed67797..a44085e 100644 --- a/EncryptionManager.cpp +++ b/EncryptionManager.cpp @@ -1,3 +1,22 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + #include "EncryptionManager.h" EncryptionManager::EncryptionManager() @@ -8,47 +27,46 @@ EncryptionManager::EncryptionManager() } keyReady = false; + generateKeys(); } std::vector EncryptionManager::encrypt(const std::vector& raw) { - std::vector crypt(raw.size()); - - // Generowanie kluczy - generateKeys(); + std::array nonce_local; + randombytes_buf(nonce_local.data(), nonce_local.size()); + std::vector tmp(raw.size()); if (crypto_stream_chacha20_ietf_xor_ic( - reinterpret_cast(crypt.data()), + reinterpret_cast(tmp.data()), reinterpret_cast(raw.data()), - static_cast(raw.size()), - nonce.data(), 0, key.data()) != 0) + static_cast(raw.size()), + nonce_local.data(), 0, key.data()) != 0) { throw std::runtime_error("crypto_stream_chacha20_ietf_xor_ic failed"); } - return crypt; + std::vector output; + output.insert(output.end(), + reinterpret_cast(nonce_local.data()), + reinterpret_cast(nonce_local.data()) + nonce_local.size()); + + output.insert(output.end(), tmp.begin(), tmp.end()); + + return output; } void EncryptionManager::generateKeys() { if (keyReady) return; - std::cout << "GENEROWANIE KLUCZA" << std::endl; - //randombytes_buf(key.data(), key.size()); crypto_stream_chacha20_ietf_keygen(key.data()); - randombytes_buf(nonce.data(), nonce.size()); keyReady = true; } -void EncryptionManager::saveKey(const std::string& path) +void EncryptionManager::saveKey(const std::string& path, bool hpp) { - std::cout << "ZAPISYWANIE KLUCZA" << std::endl; - - const int sig = SIGNATURE_KEY_FILE; - const short ver = VERSION; - // Wygeneruj time stamp std::time_t now = std::time(nullptr); const int time = static_cast(now); @@ -57,111 +75,86 @@ void EncryptionManager::saveKey(const std::string& path) std::vector keyVec(reinterpret_cast(key.data()), reinterpret_cast(key.data()) + key.size()); - std::vector nonceVec(reinterpret_cast(nonce.data()), - reinterpret_cast(nonce.data()) + nonce.size()); - - const uint64_t crcKey = XXH64(keyVec.data(), keyVec.size(), VERSION); - const uint64_t crcNonce = XXH64(nonceVec.data(), nonceVec.size(), VERSION); + const uint64_t crcKey = XXH64(keyVec.data(), keyVec.size(), 0); // Zapisz ten śmietnik do pliku KEY std::ofstream file(path + ".key", std::ios::binary); - if (!file) { std::cout << "Dupa nie zapisało" << std::endl; } + if (!file) { std::cout << "Failed to save encryption key to file" << std::endl; } - file.write(reinterpret_cast(&sig), sizeof(sig)); - file.write(reinterpret_cast(&ver), sizeof(ver)); + file.write(fl::sigkey.data(), fl::sigkey.length()); file.write(reinterpret_cast(&time), sizeof(time)); file.write(reinterpret_cast(keyVec.data()), keyVec.size()); file.write(reinterpret_cast(&crcKey), sizeof(crcKey)); - file.write(reinterpret_cast(nonceVec.data()), nonceVec.size()); - file.write(reinterpret_cast(&crcNonce), sizeof(crcNonce)); - - if (!file.good()) { std::cout << "Dupa nie zapisało" << std::endl; } file.close(); - //saveCppHeadFile(path); + if (hpp) {saveCppHeadFile(path);} } // Generowanie pliku nagłówkowego CPP z kluczem i nonce void EncryptionManager::saveCppHeadFile(const std::string& path) { - std::vector keyVec(key.begin(), key.end()); - std::vector nonceVec(nonce.begin(), nonce.end()); + const uint32_t keySize = crypto_stream_chacha20_ietf_KEYBYTES; - const std::string headerText = - "// Plik wygenerowany przy wykorzystaniu exPAK\n\n" - "// Klucz deszyfrujący\n" - "const std::array key{" + toHex(keyVec) + "};\n\n" - "// Ciąg nonce\n" - "const std::array nonce{" + toHex(nonceVec) + "}; "; + std::ofstream file(path + ".hpp"); + + file << "// Plik wygenerowany przez " << ui::title << " " << ui::ver << std::endl; + file << std::endl; + file << std::endl; + file << "#pragma once" << std::endl; + file << "#include " << std::endl; + file << "#include " << std::endl; + file << std::endl; + file << "namespace enc" << std::endl; + file << "{" << std::endl; + file << " // Klucz deszyfrujący" << std::endl; + file << " const std::array key{" << std::endl; + file << " " << toHex(key.data(), key.size()) << std::endl; + file << " };" << std::endl; + file << std::endl; + file << "} //namespace" << std::endl; - std::ofstream file(path + ".hh"); - file << headerText; file.close(); } -std::string EncryptionManager::toHex(const std::vector& data) +std::string EncryptionManager::toHex(const unsigned char* data, size_t len) { - std::string bytes; - int sk = data.size(); - int skp = 1; - - for (const auto& b : data) - { - std::stringstream ss; - ss << "0x" << std::hex << std::uppercase << std::setw(2) << std::setfill('0') - << static_cast(b); - - bytes += "'"; - bytes += ss.str(); - bytes += "'"; - - if (skp < sk) - { - bytes += ", "; - skp++; - } + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + for (size_t i = 0; i < len; ++i) { + oss << "0x" << std::setw(2) << static_cast(data[i]); + if (i + 1 != len) oss << ", "; + if ((i + 1) % 12 == 0 && i + 1 != len) oss << "\n "; } - - return bytes; + return oss.str(); } // Wczytaj klucz void EncryptionManager::loadKey(const std::string& path) { - std::cout << "ODCZYT KLUCZA" << std::endl; std::ifstream file(path + ".key", std::ios::binary); - - int sig; - short ver; + std::vector sig(fl::sigkey.size()); + int8_t ver; int time; // Wczytaj - file.read(reinterpret_cast(&sig), sizeof(sig)); - file.read(reinterpret_cast(&ver), sizeof(ver)); + file.read(sig.data(), sig.size()); // Sprawdź czy plik klucza jest poprawny - if (sig != SIGNATURE_KEY_FILE || ver != VERSION) + if (std::string(sig.begin(), sig.end()) != fl::sigkey) { throw std::runtime_error("Invalid key file!"); } std::vector keyVec(key.size()); - std::vector nonceVec(nonce.size()); uint64_t crcKey; - uint64_t crcNonce; file.read(reinterpret_cast(&time), sizeof(time)); file.read(keyVec.data(), keyVec.size()); file.read(reinterpret_cast(&crcKey), sizeof(crcKey)); - file.read(nonceVec.data(), nonceVec.size()); - file.read(reinterpret_cast(&crcNonce), sizeof(crcNonce)); - - std::cout << crcKey << " - " << XXH64(keyVec.data(), keyVec.size(), VERSION) << std::endl; // Sprawdź integralność klucza - if (XXH64(keyVec.data(), keyVec.size(), VERSION) != crcKey - || XXH64(nonceVec.data(), nonceVec.size(), VERSION) != crcNonce) + if (XXH64(keyVec.data(), keyVec.size(), 0) != crcKey) { throw std::runtime_error("Key integrity error!"); } @@ -170,19 +163,29 @@ void EncryptionManager::loadKey(const std::string& path) // Przekonwertuj vector na array key = toArray(keyVec); - nonce = toArray(nonceVec); } // Deszyfracja std::vector EncryptionManager::decrypt(const std::vector& crypt) { - std::vector raw(crypt.size()); + const size_t cryptoSize = crypto_stream_chacha20_ietf_NONCEBYTES; + + std::array nonce_local; + std::memcpy(nonce_local.data(), + reinterpret_cast(crypt.data()), cryptoSize); + + + const size_t rawSize = crypt.size() - cryptoSize; + std::vector tmp(rawSize); + std::memcpy(tmp.data(), crypt.data() + cryptoSize, rawSize); + + std::vector raw(rawSize); if (crypto_stream_chacha20_ietf_xor( reinterpret_cast(raw.data()), - reinterpret_cast(crypt.data()), - static_cast(crypt.size()), - nonce.data(), key.data()) != 0) + reinterpret_cast(tmp.data()), + static_cast(tmp.size()), + nonce_local.data(), key.data()) != 0) { throw std::runtime_error("Data decryption error!"); } diff --git a/EncryptionManager.h b/EncryptionManager.h index bee6845..b502b1b 100644 --- a/EncryptionManager.h +++ b/EncryptionManager.h @@ -1,3 +1,22 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + #pragma once #include @@ -23,16 +42,19 @@ public: std::vector encrypt(const std::vector&); std::vector decrypt(const std::vector&); - void saveKey(const std::string&); + void saveKey(const std::string&, bool); void loadKey(const std::string&); + // Generowanie hash BLAKE2b + //static std::array hashBlake(const std::vector&); + //static bool compareBlake(const std::vector&, const std::array&); + private: std::array key{}; - std::array nonce{}; bool keyReady; void generateKeys(); - std::string toHex(const std::vector&); + std::string toHex(const unsigned char*, size_t); void saveCppHeadFile(const std::string&); template diff --git a/ExtractCargo.cpp b/ExtractCargo.cpp index fbbfeb8..c944347 100644 --- a/ExtractCargo.cpp +++ b/ExtractCargo.cpp @@ -22,12 +22,11 @@ ExtractCargo::ExtractCargo() :filesLen(0) , tablePosition(0) - , filesHeadsOffset(0) - , version(VERSION) - , signature(SIGNATURE) + , xxhState(XXH64_createState()) + , signature(fl::sigpak) { // TODO Auto-generated constructor stub - + XXH64_reset(xxhState, 0); } ExtractCargo::~ExtractCargo() @@ -45,6 +44,8 @@ bool ExtractCargo::Extract(const std::string& cFile) { cargoFileName = cFile; + std::cout << "START EXTRACT " << cFile << std::endl; + //Sprawdź czy plik istnieje if (!std::filesystem::exists(cargoFileName)) { @@ -60,8 +61,12 @@ bool ExtractCargo::Extract(const std::string& cFile) } // Wczytaj klucz deszyfrujący - //std::filesystem::path kdir = cargoFileName.stem(); - //eman.loadKey(kdir.string()); + std::filesystem::path kdir = cargoFileName.stem(); + if (std::filesystem::exists(kdir.string() + ".key")) + { + std::cout << "Decryption key detected" << std::endl; + eman.loadKey(kdir.string()); + } //Otwieranie kontenera cargoFile.open(cargoFileName, std::ios::binary); @@ -83,7 +88,7 @@ bool ExtractCargo::Extract(const std::string& cFile) bool ExtractCargo::CheckCargoFile() { std::vector magic(signature.size()); - uint16_t cargoVer = 0; + int8_t cargoVer = 0; if (!cargoFile.is_open()) { @@ -92,40 +97,15 @@ bool ExtractCargo::CheckCargoFile() } cargoFile.read(magic.data(), magic.size()); - cargoFile.read(reinterpret_cast(&cargoVer), sizeof(cargoVer)); - cargoFile.read(reinterpret_cast(&filesLen), sizeof(filesLen)); - cargoFile.read(reinterpret_cast(&tablePosition), sizeof(tablePosition)); - - std::cout << std::string(magic.begin(), magic.end()) << std::endl; - if (std::string(magic.begin(), magic.end()) != signature) { std::cerr << "Error: Corrupted Cargo" << std::endl; return false; } - if (cargoVer != version) - { - std::cerr << "Error: Wrong cargo version" << std::endl; - return false; - } - - filesHeadsOffset = signature.length() + sizeof(cargoVer) + sizeof(filesLen); - - return true; -} - -//----------------------------------------------------------------------------- -// Sprawdzanie sumy kontrolnej -//----------------------------------------------------------------------------- -bool ExtractCargo::HashValid(const std::vector& data, const uint64_t& crc) -{ - uint64_t actualCrc = XXH64(data.data(), data.size(), VERSION); - - if (actualCrc != crc) - { - return false; - } + // Pobierz pozycję tablicy plików i jej rozmiar + cargoFile.read(reinterpret_cast(&tablePosition), sizeof(tablePosition)); + cargoFile.read(reinterpret_cast(&filesLen), sizeof(filesLen)); return true; } @@ -136,7 +116,6 @@ bool ExtractCargo::HashValid(const std::vector& data, const uint64_t& crc) void ExtractCargo::LoadFilesTable() { cargoFile.seekg(tablePosition); - for (uint32_t i = 0; i < filesLen; ++i) { FilesTable fhTmp; @@ -146,11 +125,10 @@ void ExtractCargo::LoadFilesTable() cargoFile.read(nameBuffor.data(), fhTmp.nameLen); fhTmp.nameFile = std::string(nameBuffor.begin(), nameBuffor.end()); - cargoFile.read(reinterpret_cast(&fhTmp.hashName), sizeof(fhTmp.hashName)); cargoFile.read(reinterpret_cast(&fhTmp.offset), sizeof(fhTmp.offset)); cargoFile.read(reinterpret_cast(&fhTmp.size), sizeof(fhTmp.size)); cargoFile.read(reinterpret_cast(&fhTmp.crc), sizeof(fhTmp.crc)); - cargoFile.read(reinterpret_cast(&fhTmp.isZip), sizeof(fhTmp.isZip)); + cargoFile.read(reinterpret_cast(&fhTmp.flag), sizeof(fhTmp.flag)); filesHeads.push_back(fhTmp); } @@ -161,29 +139,80 @@ void ExtractCargo::LoadFilesTable() //----------------------------------------------------------------------------- void ExtractCargo::ExtractingFilesFromCargo() { - CompressingManager cm; - for (const auto& fh : filesHeads) { std::filesystem::path dir = cargoFileName.stem() / fh.nameFile; CreateDirections(dir); + + std::cout << dir.string() << std::endl; + std::ofstream file(dir, std::ios::binary); - cargoFile.seekg(fh.offset); - std::vector buffor(fh.size); - cargoFile.read(buffor.data(), fh.size); + XXH64_reset(xxhState, 0); - std::vector rawBuffor = fh.isZip ? cm.decompress(buffor) : eman.decrypt(buffor); - - if (!HashValid(rawBuffor, fh.crc)) + // Strumień wyciągający + if (fh.flag == flag::raw) { - std::cerr << fh.nameFile << " Error: Corrupted data integration CRC" << std::endl; + for (uint64_t sc = 0; sc < fh.size; sc += ds::chunk_stream) + { + const uint32_t streamChunk = std::min(ds::chunk_stream, static_cast(fh.size - sc)); + + std::vector buffer(streamChunk); + cargoFile.read(buffer.data(), streamChunk); + XXH64_update(xxhState, buffer.data(), buffer.size()); + file.write(reinterpret_cast(buffer.data()), streamChunk); + } + } + else + { + uint32_t chunkLen; + uint32_t chunkBeforeSize; + uint32_t chunkLastSize; + + cargoFile.read(reinterpret_cast(&chunkLen), sizeof(chunkLen)); + cargoFile.read(reinterpret_cast(&chunkBeforeSize), sizeof(chunkBeforeSize)); + cargoFile.read(reinterpret_cast(&chunkLastSize), sizeof(chunkLastSize)); + + std::vector chunksString; + + // Dekompresja bloków + for (size_t i = 0; i < chunkLen; ++i) + { + // Pobierz rozmiar chunków przed i po skompresowaniem + uint32_t chunkSize = i < chunkLen - 1 ? chunkBeforeSize : chunkLastSize; + + uint32_t chunkZipSize; + cargoFile.read(reinterpret_cast(&chunkZipSize), sizeof(chunkZipSize)); + + // Pobierz blok chunka + std::vector buffer(chunkZipSize); + cargoFile.read(buffer.data(), chunkZipSize); + + std::vector rawBuffer(chunkSize); + if ((fh.flag & flag::zip) == flag::zip) + { + rawBuffer = (fh.flag & flag::enc) == flag::enc ? + cman.decompress(eman.decrypt(buffer), chunkSize) : + cman.decompress(buffer, chunkSize); + } + else + { + rawBuffer = eman.decrypt(buffer); + } + + XXH64_update(xxhState, rawBuffer.data(), rawBuffer.size()); + file.write(reinterpret_cast(rawBuffer.data()), chunkSize); + } } - file.write(reinterpret_cast(rawBuffor.data()), rawBuffor.size()); - file.close(); + + if (XXH64_digest(xxhState) != fh.crc) + { + std::cerr << dir.string() << " Error: Corrupted data integration CRC" << std::endl; + + } } std::cout << "Unpacking complete!" << std::endl; diff --git a/ExtractCargo.h b/ExtractCargo.h index 164a0fc..9fce5f5 100644 --- a/ExtractCargo.h +++ b/ExtractCargo.h @@ -28,11 +28,12 @@ #include #include #include +#include #include #include "DataStruct.h" -#include "CompressingManager.h" #include "EncryptionManager.h" +#include "CompressionManager.h" class ExtractCargo { public: @@ -47,9 +48,8 @@ private: uint32_t filesLen; uint64_t tablePosition; - uint8_t filesHeadsOffset; + XXH64_state_t* xxhState; - const uint8_t version; const std::string signature; std::vector filesHeads; @@ -58,7 +58,7 @@ private: std::ifstream cargoFile; EncryptionManager eman; - + CompressionManager cman; // Sprawdzenie poprawności archiwum bool CheckCargoFile(); @@ -69,9 +69,6 @@ private: // Pobieranie nagłówków plików void LoadFilesTable(); - // Sprawdzanie sumy kontrolnej - bool HashValid(const std::vector&, const uint64_t&); - // Utwórz katalog void CreateDirections(std::filesystem::path); diff --git a/Interface.cpp b/Interface.cpp deleted file mode 100644 index 9e0d7e6..0000000 --- a/Interface.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Interface.h" - -Interface::Interface() { - // TODO Auto-generated constructor stub - -} - -Interface::~Interface() { - // TODO Auto-generated destructor stub -} - -void Interface::TextBorder(const std::string& title, const std::string& text) -{ - auto element = ftxui::window(ftxui::text(title), ftxui::paragraphAlignLeft(text)); - auto screen = ftxui::Screen::Create(ftxui::Dimension::Fit(element)); - ftxui::Render(screen, element); - screen.Print(); -} \ No newline at end of file diff --git a/Interface.h b/Interface.h deleted file mode 100644 index e060f7f..0000000 --- a/Interface.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include - -class Interface { -public: - Interface(); - virtual ~Interface(); - - void TextBorder(const std::string&, const std::string&); -}; - diff --git a/README.md b/README.md index e1ca22d..704bf0a 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,9 @@ **libsodium - https://github.com/jedisct1/libsodium** -**LZ4 - https://github.com/lz4/lz4.git** +**xxHash - https://github.com/Cyan4973/xxHash.git** + +**Zstd - https://github.com/facebook/zstd.git** **FTXUI - https://github.com/ArthurSonzogni/FTXUI.git** diff --git a/Tui.cpp b/Tui.cpp new file mode 100644 index 0000000..eff5894 --- /dev/null +++ b/Tui.cpp @@ -0,0 +1,71 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "Tui.h" + +Tui::Tui() { + // TODO Auto-generated constructor stub + +} + +Tui::~Tui() { + // TODO Auto-generated destructor stub +} + +void Tui::TextBorder(const std::string& title, const std::string& text) +{ + auto element = ftxui::window(ftxui::text(title), ftxui::paragraphAlignLeft(text)); + auto screen = ftxui::Screen::Create(ftxui::Dimension::Fit(element)); + ftxui::Render(screen, element); + screen.Print(); +} + +void Tui::table(const std::vector>& data) +{ + ftxui::Table table(data); + + // Styl ogólny tabeli (ramki) + table.SelectAll().Border(ftxui::LIGHT); + + // Oddzielenie nagłówka od danych podwójną linią + table.SelectRow(0).Border(ftxui::LIGHT); + table.SelectRow(0).Decorate(ftxui::bold); // Pogrubienie nagłówka + table.SelectRow(0).SeparatorVertical(ftxui::LIGHT); + table.SelectRow(0).Border(ftxui::LIGHT); + + table.SelectColumn(0).DecorateCells(ftxui::center); + table.SelectColumn(1).DecorateCells(ftxui::center); + + table.SelectColumn(2).DecorateCells([](ftxui::Element e) { + return e | ftxui::flex; + }); + + table.SelectColumn(3).DecorateCells(ftxui::center); + + table.SelectColumn(0).BorderRight(ftxui::LIGHT); + table.SelectColumn(1).BorderRight(ftxui::LIGHT); + table.SelectColumn(2).BorderRight(ftxui::LIGHT); + + auto document = table.Render(); + + auto screen = ftxui::Screen::Create(ftxui::Dimension::Full(), ftxui::Dimension::Fit(document)); + + ftxui::Render(screen, document); + screen.Print(); +} \ No newline at end of file diff --git a/Tui.h b/Tui.h new file mode 100644 index 0000000..d3b7b99 --- /dev/null +++ b/Tui.h @@ -0,0 +1,34 @@ +/* + * This file is part of VoidArchiveTool. + * + * Copyright (C) 2025 Yanczi + * + * Void Archive Toolis free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + +class Tui { +public: + Tui(); + virtual ~Tui(); + + void TextBorder(const std::string&, const std::string&); + void table(const std::vector>&); +}; \ No newline at end of file diff --git a/Txtpp.h b/Txtpp.h deleted file mode 100644 index 70940bb..0000000 --- a/Txtpp.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This file is part of VoidArchiveTool. - * - * Copyright (C) 2025 Yanczi - * - * Void Archive Toolis free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - - - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -class Txtpp { -public: - Txtpp(const std::string& path = "") - { - if (path != "") - { - Load(path); - } - } - - ~Txtpp() - { - if (file.is_open()) - { - file.close(); - } - } - - bool Load(const std::string& path) - { - if (!std::filesystem::exists(path)) - { - return false; - } - - file.open(path); - - return file.is_open(); - } - - void Close() - { - file.close(); - } - - std::vector Get(const std::string& key) - { - std::vector tmp; - Parse(key, tmp); - return tmp; - } - - template - T getValue(const std::string& key, const std::string& val) - { - std::vector tmp; - Parse(key, tmp); - - for (const auto& line : tmp) - { - std::string cleanLine = RemoveSpaces(line); - std::string t; - std::string v; - - bool tv = false; - - for (const char& c : cleanLine) - { - if (c != ":") {tv = true;} - - if (!tv) { t += c; } - else { v += c; } - } - } - - return tmp; - } - -private: - const char sectionStart = '{'; - const char sectionEnd = '}'; - - std::ifstream file; - - //----------------------------------------------------------------------------- - // Wyszukiwanie danych po kluczu - //----------------------------------------------------------------------------- - void Parse(const std::string& key, std::vector& data) - { - std::string fullkey = sectionStart + key + sectionEnd; - std::string line; - bool wr = false; - - file.clear(); - file.seekg(std::ios::beg); - - while (getline(file, line)) - { - std::string tmp = RemoveSpaces(line); - if (tmp != "") - { - if (CheckKey(tmp)) - { - wr = UpperString(tmp) == fullkey ? true : false; - } - else - { - if (wr) { data.push_back(tmp); } - } - } - } - } - - //----------------------------------------------------------------------------- - // Usuwa spacje - //----------------------------------------------------------------------------- - std::string RemoveSpaces(std::string _line) - { - std::stringstream ss(_line); - char word; - std::string tmp; - std::string beforeWord = ""; - - while (ss >> word) - { - tmp += word; - } - - return tmp; - } - - //----------------------------------------------------------------------------- - // Sprawdza czy dany ciąg jest kluczem - //----------------------------------------------------------------------------- - bool CheckKey(std::string key) - { - if (key[0] == sectionStart && key[key.length() - 1]) - { - return true; - } - return false; - } - - //----------------------------------------------------------------------------- - // Zamień cały ciąg na duże litery - //----------------------------------------------------------------------------- - std::string UpperString(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), - [](unsigned char c) { return static_cast(std::toupper(c)); }); - return s; - } -}; - diff --git a/ViewCargo.cpp b/ViewCargo.cpp index 2a2860e..9b95d12 100644 --- a/ViewCargo.cpp +++ b/ViewCargo.cpp @@ -20,14 +20,7 @@ #include "ViewCargo.h" ViewCargo::ViewCargo() - :signature(SIGNATURE) - , version(VERSION) - , filesLen(0) - , tablePos(0) -{ - // TODO Auto-generated constructor stub - -} +{} //----------------------------------------------------------------------------- // Wywoływanie @@ -49,38 +42,25 @@ bool ViewCargo::View(const std::string& path) } //Sprawdź czy kontener jest prawidłowy - if (!CheckCargoFile(path)) + if (!ViewFiles(path)) { std::cerr << "Nie prawidlowa struktura kontenera Void" << std::endl; return false; } - //Table Header - std::vector headElements; - - headElements.push_back(ftxui::text(" Zip ") | ftxui::bold); - headElements.push_back(ftxui::text("Nazwa pliku") | ftxui::bold | ftxui::size(ftxui::WIDTH, ftxui::EQUAL, 56)); - headElements.push_back(ftxui::text("Hash Name") | ftxui::bold | ftxui::size(ftxui::WIDTH, ftxui::EQUAL, 20)); - - filesList.push_back(hbox(std::move(headElements))); - - - //Pobieranie listy plików - GetFileList(path); - - //Renderowanie listy plików - RenderList(); - return true; } //----------------------------------------------------------------------------- // Sprawdzenie poprawności kontenera //----------------------------------------------------------------------------- -bool ViewCargo::CheckCargoFile(const std::string& path) +bool ViewCargo::ViewFiles(const std::string& path) { - std::vector magic(signature.length()); - uint16_t cargoVer = 0; + uint64_t tabPos = 0; + uint32_t tabSize = 0; + + std::vector magic(fl::sigpak.length()); + int8_t cargoVer = 0; std::ifstream cargo(path, std::ios::binary); @@ -91,46 +71,30 @@ bool ViewCargo::CheckCargoFile(const std::string& path) } //--------------------------------------------------------------- - // Odczytywanie pierwszych 11 bajtów nagłówka pliku - // 6 pierwszych to sygnatura - // 1 wersja kontenera - // 4 ilość plików w kontenerze + // Odczytywanie pierwszych 16 bajtów nagłówka pliku + // 4 Sygnatura kontenera XPAK + // 8 Offset tablicy plików + // 4 Rozmiar tablicy plików //--------------------------------------------------------------- cargo.read(magic.data(), magic.size()); - cargo.read(reinterpret_cast(&cargoVer), sizeof(cargoVer)); - cargo.read(reinterpret_cast(&filesLen), sizeof(filesLen)); - cargo.read(reinterpret_cast(&tablePos), sizeof(tablePos)); + cargo.read(reinterpret_cast(&tabPos), sizeof(tabPos)); + cargo.read(reinterpret_cast(&tabSize), sizeof(tabSize)); //Sprawdź czy kontener ma poprawną sygnature - if (std::string(magic.begin(), magic.end()) != signature) + if (std::string(magic.begin(), magic.end()) != fl::sigpak) { std::cerr << "Error: Corrupted Cargo" << std::endl; cargo.close(); return false; } - //Sprawdź spójność wersji kontenera - if (cargoVer != version) - { - std::cerr << "Error: Wrong cargo version" << std::endl; - cargo.close(); - return false; - } + std::cout << "ZIP" << " " << "ENC" << " " << "Path" << std::endl; - cargo.close(); + // Przeskocz do tablicy plików + cargo.seekg(tabPos); - return true; -} - -//----------------------------------------------------------------------------- -// Pobieranie listy plików z kontenera -//----------------------------------------------------------------------------- -void ViewCargo::GetFileList(const std::string& path) -{ - std::ifstream cargo(path, std::ios::binary); - cargo.seekg(tablePos); - - for (uint32_t i = 0; i < filesLen; ++i) + // Załaduj dane o plikach + for (uint32_t i = 0; i < tabSize; ++i) { FilesTable fhTmp; cargo.read(reinterpret_cast(&fhTmp.nameLen), sizeof(fhTmp.nameLen)); @@ -139,60 +103,50 @@ void ViewCargo::GetFileList(const std::string& path) cargo.read(nameBuffor.data(), fhTmp.nameLen); fhTmp.nameFile = std::string(nameBuffor.begin(), nameBuffor.end()); - cargo.read(reinterpret_cast(&fhTmp.hashName), sizeof(fhTmp.hashName)); cargo.read(reinterpret_cast(&fhTmp.offset), sizeof(fhTmp.offset)); cargo.read(reinterpret_cast(&fhTmp.size), sizeof(fhTmp.size)); cargo.read(reinterpret_cast(&fhTmp.crc), sizeof(fhTmp.crc)); - cargo.read(reinterpret_cast(&fhTmp.isZip), sizeof(fhTmp.isZip)); + cargo.read(reinterpret_cast(&fhTmp.flag), sizeof(fhTmp.flag)); //Tworzenie wierszy tabeli - CreateTableRow(fhTmp.nameFile, fhTmp.isZip, fhTmp.hashName); + ShowFile(fhTmp.nameFile, fhTmp.flag); } cargo.close(); + + return true; } //----------------------------------------------------------------------------- // Generowanie wierszy do tabeli //----------------------------------------------------------------------------- -void ViewCargo::CreateTableRow(const std::string& file, const uint8_t& zip, const uint64_t& hash) +void ViewCargo::ShowFile(const std::string& file, const uint8_t& flag) { - //Zamiania crc liczbowej na hex string - std::stringstream ss; - ss << "0x" << std::hex << std::uppercase << hash; + std::string compresedCheck = "[ ]"; + std::string encryptedCheck = "[ ]"; - std::vector cell; - - ftxui::Element eZip; - - //Dodawanie check boxa czy plik jest spakowany czy nie - if (zip == 1) + // Ustawianie checkboxów + switch (flag) { - eZip = ftxui::text(" [x] ") | ftxui::color(ftxui::Color::Cyan); - } - else - { - eZip = ftxui::text(" [ ] ") | ftxui::color(ftxui::Color::White); + case flag::zip: + compresedCheck = "[x]"; + break; + + case flag::enc: + encryptedCheck = "[x]"; + break; + + case flag::ezd: + compresedCheck = "[x]"; + encryptedCheck = "[x]"; + break; + + default: + compresedCheck = "[ ]"; + encryptedCheck = "[ ]"; + break; } - //Dodawanie komurek - cell.push_back(eZip); - cell.push_back(ftxui::text(file) | ftxui::size(ftxui::WIDTH, ftxui::EQUAL, 56)); - cell.push_back(ftxui::text(ss.str()) | ftxui::size(ftxui::WIDTH, ftxui::EQUAL, 20)); - - //Konwersja komurek na wiersz - filesList.push_back(ftxui::hbox(std::move(cell))); -} - -//----------------------------------------------------------------------------- -// Renderowanie listy plików -//----------------------------------------------------------------------------- -void ViewCargo::RenderList() -{ - //Dodawanie wierszy do kolumn - ftxui::Element table = ftxui::vbox(std::move(filesList)); - - auto screen = ftxui::Screen::Create(ftxui::Dimension::Fit(table)); - ftxui::Render(screen, table); - screen.Print(); + // Wyświetlanie + std::cout << compresedCheck << " " << encryptedCheck << " " << file << std::endl; } diff --git a/ViewCargo.h b/ViewCargo.h index bdfb7f8..576b336 100644 --- a/ViewCargo.h +++ b/ViewCargo.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "DataStruct.h" @@ -38,17 +39,8 @@ public: bool View(const std::string&); private: - const std::string signature; - const uint16_t version; - - uint32_t filesLen; - uint64_t tablePos; - std::vector filesList; - - bool CheckCargoFile(const std::string&); - void GetFileList(const std::string&); - void RenderList(); - void CreateTableRow(const std::string&, const uint8_t&, const uint64_t&); + bool ViewFiles(const std::string&); + void ShowFile(const std::string&, const uint8_t&); }; diff --git a/license/FTXUI/LICENSE.txt b/license/FTXUI/LICENSE.txt new file mode 100644 index 0000000..fe4588c --- /dev/null +++ b/license/FTXUI/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2019 Arthur Sonzogni. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/license/lz4/LICENSE.txt b/license/lz4/LICENSE.txt deleted file mode 100644 index 972594f..0000000 --- a/license/lz4/LICENSE.txt +++ /dev/null @@ -1,12 +0,0 @@ -This repository uses 2 different licenses : -- all files in the `lib` directory use a BSD 2-Clause license -- all other files use a GPL-2.0-or-later license, unless explicitly stated otherwise - -Relevant license is reminded at the top of each source file, -and with presence of COPYING or LICENSE file in associated directories. - -This model is selected to emphasize that -files in the `lib` directory are designed to be included into 3rd party applications, -while all other files, in `programs`, `tests` or `examples`, -are intended to be used "as is", as part of their intended scenarios, -with no intention to support 3rd party integration use cases. \ No newline at end of file diff --git a/license/zstd/LICENSE.txt b/license/zstd/LICENSE.txt new file mode 100644 index 0000000..ca66d17 --- /dev/null +++ b/license/zstd/LICENSE.txt @@ -0,0 +1,30 @@ +BSD License + +For Zstandard software + +Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook, nor Meta, nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/testx/herrsher-of-the-void.png b/testx/herrsher-of-the-void.png new file mode 100644 index 0000000..d6dfc12 Binary files /dev/null and b/testx/herrsher-of-the-void.png differ diff --git a/testx/mus_honkai_space.ogg b/testx/mus_honkai_space.ogg new file mode 100644 index 0000000..136cba5 Binary files /dev/null and b/testx/mus_honkai_space.ogg differ diff --git a/testx/text_file.txt b/testx/text_file.txt new file mode 100644 index 0000000..02a2623 --- /dev/null +++ b/testx/text_file.txt @@ -0,0 +1,126 @@ +Nam strzelać nie kazano. - WstÄ…piĹ‚em na dziaĹ‚o +I spĂłjrzaĹ‚em na pole; dwieĹ›cie armat grzmiaĹ‚o. +Artyleryi ruskiej ciÄ…gnÄ… siÄ™ szeregi, +Prosto, dĹ‚ugo, daleko, jako morza brzegi; +I widziaĹ‚em ich wodza: przybiegĹ‚, mieczem skinÄ…Ĺ‚ +I jak ptak jedno skrzydĹ‚o wojska swego zwinÄ…Ĺ‚; +Wylewa siÄ™ spod skrzydĹ‚a Ĺ›ciĹ›niona piechota +DĹ‚ugÄ… czarnÄ… kolumnÄ…, jako lawa bĹ‚ota, +Nasypana iskrami bagnetĂłw. Jak sÄ™py +Czarne chorÄ…gwie na Ĺ›mierć prowadzÄ… zastÄ™py. + +Przeciw nim sterczy biaĹ‚a, wÄ…ska, zaostrzona, +Jak gĹ‚az bodzÄ…cy morze, reduta Ordona. +Sześć tylko miaĹ‚a armat; wciÄ…ĹĽ dymiÄ… i Ĺ›wiecÄ…; +I nie tyle prÄ™dkich słów gniewne usta miecÄ…, +Nie tyle przejdzie uczuć przez duszÄ™ w rozpaczy, +Ile z tych dziaĹ‚ leciaĹ‚o bomb, kul i kartaczy. +Patrz, tam granat w sam Ĺ›rodek kolumny siÄ™ nurza, +Jak w fale bryĹ‚a lawy, puĹ‚k dymem zachmurza; +PÄ™ka Ĺ›rĂłd dymu granat, szyk pod niebo leci +I ogromna Ĺ‚ysina Ĺ›rĂłd kolumny Ĺ›wieci. + +Tam kula, lecÄ…c, z dala grozi, szumi, wyje. +Ryczy jak byk przed bitwÄ…, miota siÄ™, grunt ryje; - +JuĹĽ dopadĹ‚a; jak boa Ĺ›rĂłd kolumn siÄ™ zwija, +Pali piersiÄ…, rwie zÄ™bem, oddechem zabija. +Najstraszniejszej nie widać, lecz sĹ‚ychać po dĹşwiÄ™ku, +Po waleniu siÄ™ trupĂłw, po ranionych jÄ™ku: +Gdy kolumnÄ™ od koĹ„ca do koĹ„ca przewierci, +Jak gdyby Ĺ›rodkiem wojska przeszedĹ‚ anioĹ‚ Ĺ›mierci. + +GdzieĹĽ jest krĂłl, co na rzezie tĹ‚umy te wyprawia? +Czy dzieli ich odwagÄ™, czy pierĹ› sam nadstawia? +Nie, on siedzi o pięćset mil na swej stolicy, +KrĂłl wielki, samowĹ‚adnik Ĺ›wiata poĹ‚owicy; +ZmarszczyĹ‚ brwi, - i tysiÄ…ce kibitek wnet leci; +PodpisaĹ‚, - tysiÄ…c matek opĹ‚akuje dzieci; +SkinÄ…Ĺ‚, - padajÄ… knuty od Niemna do Chiwy. +Mocarzu, jak BĂłg silny, jak szatan zĹ‚oĹ›liwy, +Gdy TurkĂłw za BaĹ‚kanem twoje straszÄ… spiĹĽe, +Gdy poselstwo paryskie twoje stopy liĹĽe, - +Warszawa jedna twojej mocy siÄ™ urÄ…ga, +Podnosi na ciÄ™ rÄ™kÄ™ i koronÄ™ Ĺ›ciÄ…ga, +KoronÄ™ KazimierzĂłw, Chrobrych z twojej gĹ‚owy, +BoĹ› jÄ… ukradĹ‚ i skrwawiĹ‚, synu Wasilowy! + +Car dziwi siÄ™ - ze strachu. drzÄ… Petersburczany, +Car gniewa siÄ™ - ze strachu mrÄ… jego dworzany; +Ale sypiÄ… siÄ™ wojska, ktĂłrych BĂłg i wiara +Jest Car. - Car gniewny: umrzem, rozweselim Cara. +PosĹ‚any wĂłdz kaukaski z siĹ‚ami pół-Ĺ›wiata, +Wierny, czynny i sprawny - jak knut w rÄ™ku kata. + +Ura! ura! Patrz, blisko reduty, juĹĽ w rowy +WalÄ… siÄ™, na faszynÄ™ kĹ‚adÄ…c swe tuĹ‚owy; +JuĹĽ czerniÄ… siÄ™ na biaĹ‚ych palisadach wałów. +Jeszcze reduta w Ĺ›rodku, jasna od wystrzałów, +Czerwieni siÄ™ nad czerniÄ…: jak w Ĺ›rodek mrowiaka +Wrzucony motyl bĹ‚yska, - mrowie go naciska, - +ZgasĹ‚ - tak zgasĹ‚a reduta. CzyĹĽ ostatnie dziaĹ‚o +StrÄ…cone z Ĺ‚oĹĽa w piasku paszczÄ™ zagrzebaĹ‚o? +Czy zapaĹ‚ krwiÄ… ostatni bombardyjer zalaĹ‚? +ZgasnÄ…Ĺ‚ ogieĹ„. - JuĹĽ Moskal rogatki wywalaĹ‚. + +GdzieĹĽ rÄ™czna broĹ„? - Ach, dzisiaj pracowaĹ‚a wiÄ™cej +NiĹĽ na wszystkich przeglÄ…dach za wĹ‚adzy ksiÄ…ĹĽÄ™cej; +ZgadĹ‚em, dlaczego milczy, - bo nieraz widziaĹ‚em +GarstkÄ™ naszych walczÄ…cÄ… z Moskali nawaĹ‚em. +Gdy godzinÄ™ woĹ‚ano dwa sĹ‚owa: pal, nabij; +Gdy oddechy dym tĹ‚umi, trud ramiona sĹ‚abi; +A wciÄ…ĹĽ grzmi rozkaz wodzĂłw, wre ĹĽoĹ‚nierza czynność; +Na koniec bez rozkazu peĹ‚niÄ… swÄ… powinność, +Na koniec bez rozwagi, bez czucia, pamiÄ™ci, +Ĺ»oĹ‚nierz jako mĹ‚yn palny nabija - grzmi - krÄ™ci +BroĹ„ od oka do nogi, od nogi na oko: +AĹĽ rÄ™ka w Ĺ‚adownicy dĹ‚ugo i głęboko +SzukaĹ‚a, nie znalazĹ‚a - i ĹĽoĹ‚nierz pobladnÄ…Ĺ‚, +Nie znalazĹ‚szy Ĺ‚adunku, juĹĽ broniÄ… nie wĹ‚adnÄ…Ĺ‚; +I uczuĹ‚, ĹĽe go pali strzelba rozogniona; +UpuĹ›ciĹ‚ jÄ… i upadĹ‚; - nim dobijÄ…, skona. +Takem myĹ›liĹ‚, - a w szaniec nieprzyjaciół kupa +JuĹĽ Ĺ‚azĹ‚a, jak robactwo na Ĺ›wieĹĽego trupa. + +PociemniaĹ‚o mi w oczach - a gdym Ĺ‚zy ocieraĹ‚, +SĹ‚yszaĹ‚em, ĹĽe coĹ› do mnie mĂłwiĹ‚ mĂłj JeneraĹ‚. +On przez lunetÄ™ wspartÄ… na moim ramieniu +DĹ‚ugo na szturm i szaniec poglÄ…daĹ‚ w milczeniu. +Na koniec rzekĹ‚; "Stracona". - Spod lunety jego +Wymknęło siÄ™ Ĺ‚ez kilka, - rzekĹ‚ do mnie: "Kolego, +Wzrok mĹ‚ody od szkieĹ‚ lepszy; patrzaj, tam na wale, +Znasz Ordona, czy widzisz, gdzie jest?" - "Jenerale, +Czy go znam? - Tam staĹ‚ zawsze, to dziaĹ‚o kierowaĹ‚. +Nie widzÄ™ - znajdÄ™ - dojrzÄ™! - Ĺ›rĂłd dymu siÄ™ schowaĹ‚: +Lecz Ĺ›rĂłd najgÄ™stszych kłębĂłw dymu ileĹĽ razy +WidziaĹ‚em rÄ™kÄ™ jego, dajÄ…cÄ… rozkazy. - +WidzÄ™ go znowu, - widzÄ™ rÄ™kÄ™ - bĹ‚yskawicÄ™, +Wywija, grozi wrogom, trzyma palnÄ… Ĺ›wiĂ©cÄ™, +BiorÄ… go - zginÄ…Ĺ‚ - o nie, - skoczyĹ‚ w dół, - do lochĂłw"! +"Dobrze - rzecze JeneraĹ‚ - nie odda im prochĂłw". + +Tu blask - dym - chwila cicho - i huk jak stu gromĂłw. +ZaćmiĹ‚o siÄ™ powietrze od ziemi wylomĂłw, +Harmaty podskoczyĹ‚y i jak wystrzelone +ToczyĹ‚y siÄ™ na koĹ‚ach - lonty zapalone +Nie trafiĹ‚y do swoich panew. I dym wionÄ…Ĺ‚ +Prosto ku nam; i w gÄ™stej chmurze nas ochĹ‚onÄ…Ĺ‚. +I nie byĹ‚o nic widać prĂłcz granatĂłw blasku +I powoli dym rzedniaĹ‚, opadaĹ‚ deszcz piasku. +SpojrzaĹ‚em na redutÄ™; - waĹ‚y, palisady, +DziaĹ‚a i naszych garstka, i wrogĂłw gromady; +Wszystko jako sen znikĹ‚o. - Tylko czarna bryĹ‚a +Ziemi nieksztaĹ‚tnej leĹĽy - rozjemcza mogiĹ‚a. +Tam i ci, co bronili, -i ci, co siÄ™ wdarli, +Pierwszy raz pokĂłj szczery i wieczny zawarli. +Choćby cesarz Moskalom kazaĹ‚ wstać, juĹĽ dusza +Moskiewska. tam raz pierwszy, cesarza nie sĹ‚usza. +Tam zagrzebane tylu set ciaĹ‚a, imiona: +Dusze gdzie? nie wiem; lecz wiem, gdzie dusza Ordona. +On bÄ™dzie Patron szaĹ„cĂłw! - Bo dzieĹ‚o zniszczenia +W dobrej sprawie jest Ĺ›wiÄ™te, Jak dzieĹ‚o tworzenia; +BĂłg wyrzekĹ‚ sĹ‚owo staĹ„ siÄ™, BĂłg i zgiĹ„ wyrzecze. +Kiedy od ludzi wiara i wolność uciecze, +Kiedy ziemiÄ™ despotyzm i duma szalona +OblejÄ…, jak Moskale redutÄ™ Ordona - +KarzÄ…c plemiÄ™ zwyciężcĂłw zbrodniami zatrute, +BĂłg wysadzi tÄ™ ziemiÄ™, jak on swÄ… redutÄ™. \ No newline at end of file diff --git a/voidcmd.cpp b/voidcmd.cpp index 5908996..22e1520 100644 --- a/voidcmd.cpp +++ b/voidcmd.cpp @@ -32,7 +32,7 @@ #include "CreateCargo.h" #include "ExtractCargo.h" #include "ViewCargo.h" -#include "Interface.h" +#include "Tui.h" void RenderHelp() { @@ -40,36 +40,35 @@ void RenderHelp() const std::string HelpInstruction = "pakcmd \n" " \n" - " -c Pack and compress with LZ4 \n" - " -p Pack files from the specified directory \n" - " -e Pack and encrypted from the specified directory \n" - " -f Pack the files according to the guidelines given in the .txt \n" - " -s Pack and encrypted \n" - " -cs Pack and compress \n" + " -c Compressing \n" + " -r Raw files \n" + " -e Encrypted \n" + " -s Compressing and Encrypted \n" + " -f Pack the files according to the guidelines given in the .json \n" " \n" "Extracting: \n" " -x Extract files from the specified container \n" + " \n" + "Others: \n" " -ls List files stored in a container \n" " \n" - " \n" - ".txt \n" + ".json \n" " \n" "Keys: \n" " \n" - " {compress} - Compressing files \n" - " {crypt} - Encrypted files with ChaCha20 \n" + " {compress} - Compressing files \n" + " {crypt} - Encrypted files \n" " {ignore} - Ignoring concrete files \n" " \n" " /path/to/file.ext - Concrete file \n" " *.ext - All files with concrete extension \n" - " *.* - All files !NOT WORKING WITH {ignore} KEY! \n" - " \n"; + " *.* - All files !NOT WORKING WITH {ignore} KEY! \n"; - Interface tui; - tui.TextBorder(HelpTitle, HelpInstruction); + //Interface tui; + //tui.TextBorder(HelpTitle, HelpInstruction); } -bool EmptyPath(std::string path) +static bool EmptyPath(std::string path) { if (path == "") { @@ -81,26 +80,16 @@ bool EmptyPath(std::string path) } int main(int argc, char* argv[]) { - std::string path = ""; - - std::cout << - " 8888888b. d8888 888 d8P \n" - " 888 Y88b d88888 888 d8P \n" - " 888 888 d88P888 888 d8P \n" - " .d88b. 888 888 888 d88P d88P 888 888d88K \n" - "d8P Y8b `Y8bd8P' 8888888P\" d88P 888 8888888b \n" - "88888888 X88K 888 d88P 888 888 Y88b \n" - "Y8b. .d8\"\"8b. 888 d8888888888 888 Y88b \n" - " \"Y8888 888 888 888 d88P 888 888 Y88b\n" - << std::endl; - std::cout << "\n" << PROGRAM_VERSION << " Release " << PROGRAM_COMPILING << std::endl; - std::cout << "Author: " << PROGRAM_AUTHOR << std::endl; - std::cout << "License: " << PROGRAM_LICENSE << "\n" << std::endl; + std::cout << ui::title << std::endl << "ver. " << ui::ver << std::endl; + std::cout << "Author: Yanczi" << std::endl; + std::cout << "License: GNU LGPL v3" << "\n" << std::endl; CreateCargo cargo; ExtractCargo extract; ViewCargo viewCargo; + std::string path = ""; + for (int i = 0; i < argc; ++i) { std::string arg = argv[i]; @@ -111,17 +100,37 @@ int main(int argc, char* argv[]) { if (!EmptyPath(path)) { return 1; } - if (!cargo.Create(path, 1)) + if (!cargo.Create(path, 0x0F)) { return 1; } i++; } - if (arg == "-p" && i + 1 < argc) + if (arg == "-r" && i + 1 < argc) { path = argv[i + 1]; - if (!cargo.Create(path, 0)) + if (!cargo.Create(path, 0x00)) + { + return 1; + } + i++; + } + + if (arg == "-e" && i + 1 < argc) + { + path = argv[i + 1]; + if (!cargo.Create(path, 0xF0)) + { + return 1; + } + i++; + } + + if (arg == "-s" && i + 1 < argc) + { + path = argv[i + 1]; + if (!cargo.Create(path, 0xFF)) { return 1; } @@ -132,7 +141,7 @@ int main(int argc, char* argv[]) { { path = argv[i + 1]; if (!EmptyPath(path)) { return 1; } - if (!cargo.Create(path, -1)) + if (!cargo.Create(path, 0xAB)) { return 1; } diff --git a/voidcmd.vcxproj b/voidcmd.vcxproj index d0fe1d7..ee82946 100644 --- a/voidcmd.vcxproj +++ b/voidcmd.vcxproj @@ -101,16 +101,16 @@ Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);SODIUM_STATIC true - stdcpp17 - 3rd\ftxui\include;3rd\libsodium\include;3rd\json\include;3rd\lz4\include;3rd\xxhash\include + stdcpp20 + 3rd\libsodium\include;3rd\json\include;3rd\zstd\include;3rd\xxhash\include Console true - 3rd\ftxui\Debug;3rd\lz4\lib;3rd\libsodium\lib\Debug - liblz4_static.lib;ftxui-component.lib;ftxui-dom.lib;ftxui-screen.lib;libsodium.lib + 3rd\zstd\lib\Debug;3rd\xxhash\lib\Debug;3rd\libsodium\x64\Debug\v143\static + libsodium.lib;zstd_static.lib;xxhash.lib @@ -119,35 +119,32 @@ true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);SODIUM_STATIC true stdcpp17 - 3rd\ftxui\include;3rd\libsodium\include;3rd\json\include;3rd\lz4\include; + 3rd\libsodium\include;3rd\json\include;3rd\zstd\include;3rd\xxhash\include Console true - 3rd\libsodium\lib\Release;3rd\ftxui\Release;3rd\lz4\lib - liblz4_static.lib;ftxui-component.lib;ftxui-dom.lib;ftxui-screen.lib;libsodium.lib + 3rd\zstd\lib\Release;3rd\libsodium\x64\Release\v143\static;3rd\xxhash\lib\Release + libsodium.lib;zstd_static.lib;xxhash.lib - + - - + - - diff --git a/voidcmd.vcxproj.filters b/voidcmd.vcxproj.filters index 7752806..4dec7bb 100644 --- a/voidcmd.vcxproj.filters +++ b/voidcmd.vcxproj.filters @@ -27,15 +27,12 @@ Pliki ĹşrĂłdĹ‚owe - - Pliki ĹşrĂłdĹ‚owe - - - Pliki ĹşrĂłdĹ‚owe - Pliki ĹşrĂłdĹ‚owe + + Pliki ĹşrĂłdĹ‚owe + @@ -47,21 +44,15 @@ Pliki nagłówkowe - - Pliki nagłówkowe - Pliki nagłówkowe - - Pliki nagłówkowe - - - Pliki nagłówkowe - Pliki nagłówkowe + + Pliki nagłówkowe + diff --git a/xxhash.dll b/xxhash.dll new file mode 100644 index 0000000..4ee9ba0 Binary files /dev/null and b/xxhash.dll differ