diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000..6f0591a --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,84 @@ +# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. +# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml +name: CMake on multiple platforms + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [ubuntu-latest, windows-latest] + build_type: [Release] + c_compiler: [gcc, clang, cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: ubuntu-latest + c_compiler: clang + cpp_compiler: clang++ + exclude: + - os: windows-latest + c_compiler: gcc + - os: windows-latest + c_compiler: clang + - os: ubuntu-latest + c_compiler: cl + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: libuncso2-${{ matrix.c_compiler }}-${{ matrix.os }} + path: build/ + + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }}/tests + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --build-config ${{ matrix.build_type }} + #run: ./ci/test.ps1 diff --git a/.gitignore b/.gitignore index d296ea2..0567178 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,25 @@ # Generated documentation /docs -# VSCode configs +# VS Code settings /.vscode +/.cache + +# Visual Studio work directory +/.vs/ +# Visual Studio build directory +/out/ + +# CMake build directory +/build + +# AppImage executables +*.AppImage + +/CMakeUserPresets.json + +# Arch Linux +/.SRCINFO +/src +/pkg +*.tar.zst diff --git a/.gitmodules b/.gitmodules index 49b74c0..87c5012 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,9 @@ [submodule "external/catch2"] path = external/catch2 url = https://github.com/catchorg/Catch2 -[submodule "external/cryptopp-cmake"] - path = external/cryptopp-cmake - url = https://github.com/noloader/cryptopp-cmake/ [submodule "external/cryptopp"] path = external/cryptopp url = https://github.com/weidai11/cryptopp -[submodule "external/gsl-lite"] - path = external/gsl-lite - url = https://github.com/martinmoene/gsl-lite +[submodule "external/cryptopp-cmake"] + path = external/cryptopp-cmake + url = https://github.com/abdes/cryptopp-cmake.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 02c7446..b16a85f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13.0) +cmake_minimum_required(VERSION 3.13) if(POLICY CMP0077) cmake_policy(SET CMP0077 NEW) @@ -31,9 +31,6 @@ endif() # option(PKG_BUILD_SHARED "Build libuncso2 as a shared library" ON) option(PKG_BUILD_TESTS "Build tests" ${PKG_IS_STANDALONE}) -option(PKG_DEPS_AS_SHARED_LIBS - "Build libuncso2 dependencies as shared libraries" ON) -option(PKG_USE_CLANG_FSAPI "Use libc++fs when available" OFF) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_modules") @@ -48,7 +45,6 @@ set(PKG_GENERATED_DIR "${CMAKE_BINARY_DIR}/generated") set(PKG_LIB_CRYPTOPP_DIR "${PKG_LIBS_DIR}/cryptopp") set(PKG_LIB_CRYPTOPP_CMAKE_DIR "${PKG_LIBS_DIR}/cryptopp-cmake") -set(PKG_LIB_GSL_DIR "${PKG_LIBS_DIR}/gsl-lite") set(PKG_LIB_LZMA_DIR "${PKG_LIBS_DIR}/lzma") set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -69,29 +65,8 @@ generate_libuc2_version(VERSION_FILE # Dependencies # -# Setup Crypto++'s CMake files -configure_file("${PKG_LIB_CRYPTOPP_CMAKE_DIR}/CMakeLists.txt" - "${PKG_LIB_CRYPTOPP_DIR}/" COPYONLY) -configure_file("${PKG_LIB_CRYPTOPP_CMAKE_DIR}/cryptopp-config.cmake" - "${PKG_LIB_CRYPTOPP_DIR}/" COPYONLY) - -# Disable Crypto++ testing -set(BUILD_TESTING FALSE CACHE BOOL "" FORCE) - -# Only build Crypto++ either static or shared libraries -if(NOT MSVC) - if(PKG_DEPS_AS_SHARED_LIBS) - # set(BUILD_STATIC FALSE CACHE BOOL "" FORCE) - else() - set(BUILD_SHARED FALSE CACHE BOOL "" FORCE) - endif() -else() - # Don't build FIPS DLL - set(BUILD_SHARED FALSE CACHE BOOL "" FORCE) -endif() - -add_subdirectory("${PKG_LIB_CRYPTOPP_DIR}") -set(CryptoPP_INCLUDE_DIRS "${PKG_LIB_CRYPTOPP_DIR}") +set(CRYPTOPP_SOURCES "${PKG_LIB_CRYPTOPP_DIR}") +add_subdirectory("${PKG_LIB_CRYPTOPP_CMAKE_DIR}") # Enable weak namespace for MD5 add_definitions(-DCRYPTOPP_ENABLE_NAMESPACE_WEAK=1) @@ -170,7 +145,7 @@ source_group("Source Files" FILES ${PKG_SOURCES_BASE}) source_group("Public Header Files" FILES ${PKG_PUBLIC_HEADERS_BASE}) source_group("Header Files" FILES ${PKG_HEADERS_BASE}) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_definitions(-DCMAKE_EXPORT_COMPILE_COMMANDS=ON) @@ -194,7 +169,7 @@ set_target_properties(uncso2 PROPERTIES VERSION ${LIB_VERSION}) # Enable all warnings # if(MSVC) - target_compile_options(uncso2 PRIVATE /W4) + target_compile_options(uncso2 PRIVATE /DWIN32 /D_WINDOWS /W4 /EHsc) else() target_compile_options(uncso2 PRIVATE -Wall -Wextra -pedantic) endif() @@ -205,10 +180,8 @@ endif() target_include_directories(uncso2 PRIVATE "headers") target_include_directories(uncso2 PRIVATE "${PKG_PUBLIC_HEADERS_DIR}") -target_include_directories(uncso2 - PRIVATE "${LZMA_INCLUDE_DIR}" - "${CryptoPP_INCLUDE_DIRS}" - "${PKG_LIB_GSL_DIR}/include") +target_include_directories(uncso2 PRIVATE "external") +target_include_directories(uncso2 PRIVATE "${LZMA_INCLUDE_DIR}") # the generated version header's directory target_include_directories(uncso2 PRIVATE ${PKG_GENERATED_DIR}) @@ -217,26 +190,7 @@ target_include_directories(uncso2 PRIVATE ${PKG_GENERATED_DIR}) # Setup library directories # -if(PKG_USE_CLANG_FSAPI) - message(STATUS "libuncso2: Using libc++fs") - target_link_libraries(uncso2 c++fs) -elseif(NOT MSVC) - message(STATUS "libuncso2: Using stdlibc++fs") - target_link_libraries(uncso2 stdc++fs) -endif() - -if(NOT MSVC) - if(PKG_DEPS_AS_SHARED_LIBS) - target_link_libraries(uncso2 cryptopp-shared) - else() - target_link_libraries(uncso2 cryptopp-static) - endif() -else() - # Don't use FIPS DLL - target_link_libraries(uncso2 cryptopp-static) -endif() - -target_link_libraries(uncso2 lzma) +target_link_libraries(uncso2 lzma cryptopp) # # Set include directory for dependent projects @@ -256,3 +210,10 @@ if(PKG_BUILD_TESTS) message("libuncso2: Building tests") add_subdirectory(tests) endif() + +# +# Installation rules +# + +install(TARGETS uncso2 DESTINATION lib) +install(DIRECTORY ${PKG_PUBLIC_HEADERS_ROOT_DIR}/ DESTINATION include/libuncso2) diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..35e21bd --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,41 @@ +pkgname=libuncso2 +pkgver=1.2.0 +pkgrel=1 +pkgdesc="Backend for UnCSO2" +arch=(any) +url="https://github.com/harmonytf/libuncso2" +license=(GPL-3.0-only) +makedepends=(cmake) +source=() +_sourcedir="$pkgname" + +prepare() { + ln -snf "$startdir" "$srcdir" +} + +build() { + cmake -B build -S "$_sourcedir" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -Wno-dev + cmake --build build +} + +check() { + ctest --test-dir "$_sourcedir/build/tests" --build-config RelWithDebInfo --output-on-failure +} + +package() { + DESTDIR="$pkgdir" cmake --install build + install -Dm644 "$_sourcedir/COPYING" -t "$pkgdir/usr/share/licenses/$pkgname" + + rm -rf "$pkgdir/usr/bin/cryptest" + rm -rf "$pkgdir/usr/include/cryptopp" + rm -rf "$pkgdir/usr/lib/libcryptopp.a" + rm -rf "$pkgdir/usr/share/cmake" + rm -rf "$pkgdir/usr/share/cryptopp" + rm -rf "$pkgdir/usr/share/pkgconfig/cryptopp.pc" + + rm -rf "$pkgdir/usr/bin" + rm -rf "$pkgdir/usr/share/pkgconfig" +} diff --git a/README.md b/README.md index d54506a..be797df 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,23 @@ # libuncso2 +[![GitHub License](https://img.shields.io/github/license/harmonytf/libuncso2)](https://raw.githubusercontent.com/harmonytf/libuncso2/master/COPYING) +[![GitHub Release](https://img.shields.io/github/v/release/harmonytf/libuncso2)](https://github.com/harmonytf/libuncso2/releases/latest) +[![AUR Version](https://img.shields.io/aur/version/libuncso2?logo=archlinux)](https://aur.archlinux.org/packages/libuncso2) +[![AUR-BIN Version](https://img.shields.io/aur/version/libuncso2-bin?logo=archlinux&label=aur-bin)](https://aur.archlinux.org/packages/libuncso2-bin) + A library to decrypt and parse PKG files used by Nexon's videogame Counter-Strike Online 2. PKG is an encrypted archive file format used in Counter-Strike Online 2 and Titanfall Online to store the games' file data. It's based on the ekey's reversing work of at [XeNTaX's forums](https://forum.xentax.com/viewtopic.php?f=21&t=11117). -Used as the back-end for the GUI program [UnCSO2](https://github.com/L-Leite/UnCSO2). +Used as the back-end for the GUI program [UnCSO2](https://github.com/harmonytf/UnCSO2). Tested on: -- GNU/Linux - GCC 8.3.0 (32 and 64 bits) -- GNU/Linux - Clang 8.0.0 (32 and 64 bits) -- Windows 10 - MSVC 2017 (32 and 64 bits) + +- GNU/Linux - GCC 15.2.1 (64 bits) +- GNU/Linux - Clang 21.1.4 (64 bits) +- Windows 10 - MSVC 2022 (64 bits) ## Features @@ -20,10 +26,6 @@ Tested on: - Decrypt '.e*' files, such as files with .etxt, .escv or .ecfg extensions. - Decompress LZMA deflated textures. -## Build status - -[![Build status](https://ci.appveyor.com/api/projects/status/oygibb8s9c3xxdba/branch/master?svg=true)](https://ci.appveyor.com/project/L-Leite/libuncso2/branch/master) - ## Examples Decrypting and parsing a PKG file, then, extract its entries to the disk: @@ -188,8 +190,8 @@ add_subdirectory("libuncso2") file(GLOB SOMEAPP_ALL_SOURCES "main.cpp") -# C++17 is required -set(CMAKE_CXX_STANDARD 17) +# C++20 is required +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(someapp ${SOMEAPP_ALL_SOURCES}) @@ -204,7 +206,6 @@ libuncso2 uses the following libraries: - [Catch2](https://github.com/catchorg/Catch2) (used in the test application), Boost Software License. - [Crypto++](https://www.cryptopp.com/), Public domain. -- [GSL Lite](https://github.com/martinmoene/gsl-lite), MIT license. - [LZMA SDK](https://www.7-zip.org/sdk.html), Public domain. ## License diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100755 index 0857893..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.1.5-{build} - -image: - - Visual Studio 2017 - - Ubuntu1604 - -environment: - matrix: - - BUILD_COMBO: windows-mingw - - BUILD_COMBO: windows-msvc - - BUILD_COMBO: linux-gcc - - BUILD_COMBO: linux-clang - -matrix: - exclude: - - image: Visual Studio 2017 - BUILD_COMBO: linux-gcc - - image: Visual Studio 2017 - BUILD_COMBO: linux-clang - - image: Ubuntu1604 - BUILD_COMBO: windows-mingw - - image: Ubuntu1604 - BUILD_COMBO: windows-msvc - - -configuration: - - Debug - - Release - -install: - - ps: ./ci/setup.ps1 - -build_script: - - ps: ./ci/build.ps1 - -test_script: - - ps: ./ci/test.ps1 - -#on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/ci/build.ps1 b/ci/build.ps1 index 68b1f62..8a5679e 100644 --- a/ci/build.ps1 +++ b/ci/build.ps1 @@ -7,7 +7,7 @@ function SetupVsToolsPath { # from https://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html # split location to shorten the command - Push-Location 'C:\Program Files (x86)\Microsoft Visual Studio\2017' + Push-Location 'C:\Program Files\Microsoft Visual Studio\2022' Push-Location '.\Community\VC\Auxiliary\Build' cmd /c "vcvars64.bat&set" | @@ -26,8 +26,6 @@ $curConfig = $env:CONFIGURATION $isMsvcBuild = $curBuildCombo -eq 'windows-msvc' -$clangFsOption = 'DPKG_USE_CLANG_FSAPI=OFF'; - Write-Host "Running build script..." Write-Host "Current script build combo is: $curBuildCombo $curConfig" @@ -43,7 +41,6 @@ switch ($curBuildCombo) { "linux-clang" { $targetCompilerCC = 'clang-8' $targetCompilerCXX = 'clang++-8' - $clangFsOption = 'DPKG_USE_CLANG_FSAPI=ON'; break } "windows-mingw" { @@ -54,7 +51,7 @@ switch ($curBuildCombo) { "windows-msvc" { $targetCompilerCC = 'cl' $targetCompilerCXX = 'cl' - # add msvc 17 tools to path + # add msvc tools to path SetupVsToolsPath break } @@ -74,7 +71,7 @@ CreateDirectory ./build Push-Location ./build if ($isMsvcBuild) { - cmake -G "Visual Studio 15 2017" -A "x64" ../ + cmake -G "Visual Studio 17 2022" -A "x64" ../ } else { cmake -G "Ninja" ` diff --git a/ci/setup.ps1 b/ci/setup.ps1 index 05fe474..674fb6f 100644 --- a/ci/setup.ps1 +++ b/ci/setup.ps1 @@ -2,7 +2,7 @@ function SetupVsToolsPath { # from https://allen-mack.blogspot.com/2008/03/replace-visual-studio-command-prompt.html # split location to shorten the command - Push-Location 'C:\Program Files (x86)\Microsoft Visual Studio\2017' + Push-Location 'C:\Program Files\Microsoft Visual Studio\2022' Push-Location '.\Community\VC\Auxiliary\Build' cmd /c "vcvars64.bat&set" | diff --git a/ci/test.ps1 b/ci/test.ps1 index e7c8337..fa546a7 100644 --- a/ci/test.ps1 +++ b/ci/test.ps1 @@ -1,26 +1,14 @@ Write-Host 'Running test script...' -$curBuildCombo = $env:BUILD_COMBO - -$isMingwBuild = $curBuildCombo -eq 'windows-mingw' -$isMsvcBuild = $curBuildCombo -eq 'windows-msvc' - # go to the test binary dir -Push-Location ./build/tests +Push-Location ./build/tests if ($isLinux) { ./pkg_test } elseif ($isWindows) { - if ($isMingwBuild) { - # copy libuncso2 and crypto++ dlls to the tests directory - Copy-Item "..\libuncso2.dll" -Destination ".\" - Copy-Item "..\external\cryptopp\libcryptopp.dll" -Destination ".\" - } - elseif ($isMsvcBuild) { - # copy libuncso2 dll to the tests directory - Copy-Item "..\uncso2.dll" -Destination ".\" - } + # copy libuncso2 dll to the tests directory + Copy-Item "..\uncso2.dll" -Destination ".\" ./pkg_test.exe } diff --git a/external/catch2 b/external/catch2 index f0dc4d9..a6ee7e2 160000 --- a/external/catch2 +++ b/external/catch2 @@ -1 +1 @@ -Subproject commit f0dc4d9be078d21ccabcb0798f03c332a153f84f +Subproject commit a6ee7e20cd4011129816df7992c1a9db2ef4b58f diff --git a/external/cryptopp b/external/cryptopp index e16be7a..60f81a7 160000 --- a/external/cryptopp +++ b/external/cryptopp @@ -1 +1 @@ -Subproject commit e16be7a380edba5b0aefaaccaf1717112e8652af +Subproject commit 60f81a77e0c9a0e7ffc1ca1bc438ddfa2e43b78e diff --git a/external/cryptopp-cmake b/external/cryptopp-cmake index 33e33e9..d2b072a 160000 --- a/external/cryptopp-cmake +++ b/external/cryptopp-cmake @@ -1 +1 @@ -Subproject commit 33e33e93a46b6d81f1e877d30a68791943409a10 +Subproject commit d2b072ab65c036f3dca67f4204ad57d66728bf99 diff --git a/external/gsl-lite b/external/gsl-lite deleted file mode 160000 index 503b14b..0000000 --- a/external/gsl-lite +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 503b14bdd1cfa9a797dc3dddab6baac7e13504bf diff --git a/external/lzma/CMakeLists.txt b/external/lzma/CMakeLists.txt index 0381910..b5c55f9 100644 --- a/external/lzma/CMakeLists.txt +++ b/external/lzma/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.13) project(lzma) diff --git a/headers/ciphers/aescipher.hpp b/headers/ciphers/aescipher.hpp index 70bf37b..0572c90 100644 --- a/headers/ciphers/aescipher.hpp +++ b/headers/ciphers/aescipher.hpp @@ -12,7 +12,7 @@ class CAesCipher : public IBaseCipher virtual void Initialize(std::string_view key, std::string_view iv, bool paddingEnabled = false); - virtual std::uint64_t Decrypt(gsl::span inData, - gsl::span outBuffer); + virtual std::uint64_t Decrypt(std::span inData, + std::span outBuffer); }; } // namespace uc2 diff --git a/headers/ciphers/basecipher.hpp b/headers/ciphers/basecipher.hpp index ef8ba70..46127a5 100644 --- a/headers/ciphers/basecipher.hpp +++ b/headers/ciphers/basecipher.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include namespace uc2 @@ -12,8 +12,8 @@ class IBaseCipher virtual ~IBaseCipher() = default; virtual void Initialize(std::string_view key, std::string_view iv, bool paddingEnabled = false) = 0; - virtual std::uint64_t Decrypt(gsl::span inData, - gsl::span outBuffer) = 0; + virtual std::uint64_t Decrypt(std::span inData, + std::span outBuffer) = 0; protected: std::string_view m_szvKey; diff --git a/headers/ciphers/blowfishcipher.hpp b/headers/ciphers/blowfishcipher.hpp index 180054d..4359952 100644 --- a/headers/ciphers/blowfishcipher.hpp +++ b/headers/ciphers/blowfishcipher.hpp @@ -12,7 +12,7 @@ class CBlowfishCipher : public IBaseCipher virtual void Initialize(std::string_view key, std::string_view iv, bool paddingEnabled = false); - virtual std::uint64_t Decrypt(gsl::span inData, - gsl::span outBuffer); + virtual std::uint64_t Decrypt(std::span inData, + std::span outBuffer); }; } // namespace uc2 diff --git a/headers/ciphers/descipher.hpp b/headers/ciphers/descipher.hpp index f601863..f779120 100644 --- a/headers/ciphers/descipher.hpp +++ b/headers/ciphers/descipher.hpp @@ -12,7 +12,7 @@ class CDesCipher : public IBaseCipher virtual void Initialize(std::string_view key, std::string_view iv, bool paddingEnabled = false); - virtual std::uint64_t Decrypt(gsl::span inData, - gsl::span outBuffer); + virtual std::uint64_t Decrypt(std::span inData, + std::span outBuffer); }; } // namespace uc2 diff --git a/headers/encryptedfileimpl.hpp b/headers/encryptedfileimpl.hpp index 237222d..8794814 100644 --- a/headers/encryptedfileimpl.hpp +++ b/headers/encryptedfileimpl.hpp @@ -2,7 +2,7 @@ #include "encryptedfile.hpp" -#include +#include namespace uc2 { @@ -27,22 +27,22 @@ class EncryptedFileImpl : public EncryptedFile std::vector& fileData, const std::uint8_t (&keyCollection)[4][16]); EncryptedFileImpl(std::string_view fileName, - gsl::span fileDataView, - gsl::span keyCollectionView); + std::span fileDataView, + std::span keyCollectionView); virtual ~EncryptedFileImpl() override; virtual std::pair Decrypt() override; static ptr_t CreateSpan( - std::string_view fileName, gsl::span fileDataView, - gsl::span keyCollectionView); + std::string_view fileName, std::span fileDataView, + std::span keyCollectionView); private: bool IsHeaderValid() const; private: std::string_view m_szvFileName; - gsl::span m_FileDataView; - gsl::span m_KeyCollectionView; + std::span m_FileDataView; + std::span m_KeyCollectionView; }; } // namespace uc2 diff --git a/headers/keyhashes.hpp b/headers/keyhashes.hpp index 55a387b..669b3d5 100755 --- a/headers/keyhashes.hpp +++ b/headers/keyhashes.hpp @@ -1,6 +1,7 @@ #include #include -#include +#include +#include #include #include @@ -8,7 +9,7 @@ namespace uc2 { std::vector GeneratePkgIndexKey( int iKey, std::string_view szPkgName, - gsl::span keyCollectionView); + std::span keyCollectionView); std::string GeneratePkgFileKey(std::string_view szvPkgName, std::string_view szKey); diff --git a/headers/lzmaDecoder.h b/headers/lzmaDecoder.h index c2ce22d..bbfa105 100644 --- a/headers/lzmaDecoder.h +++ b/headers/lzmaDecoder.h @@ -38,7 +38,7 @@ class CLZMAStream; class CLZMA { public: - static unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); + static size_t Uncompress( unsigned char *pInput, unsigned char *pOutput ); static bool IsCompressed( unsigned char *pInput ); static unsigned int GetActualSize( unsigned char *pInput ); }; @@ -63,9 +63,10 @@ class CLZMAStream // Attempt to read up to nMaxInputBytes from the compressed stream, writing up to nMaxOutputBytes to pOutput. // Makes progress until blocked on input or output. // Returns false if read stops due to an error or if called at EOF (GetExpectedBytesRemaining == 0) - bool Read( unsigned char *pInput, unsigned int nMaxInputBytes, - unsigned char *pOutput, unsigned int nMaxOutputBytes, - /* out */ unsigned int &nCompressedBytesRead, /* out */ unsigned int &nOutputBytesWritten ); + bool Read(unsigned char* pInput, size_t nMaxInputBytes, + unsigned char* pOutput, size_t nMaxOutputBytes, + /* out */ size_t& nCompressedBytesRead, + /* out */ size_t& nOutputBytesWritten); // Get the expected uncompressed bytes yet to be read from this stream. Returns false if not yet known, such as // before being fed the header. @@ -79,7 +80,8 @@ class CLZMAStream eHeaderParse_NeedMoreBytes }; - eHeaderParse TryParseHeader( unsigned char *pInput, unsigned int nBytesAvailable, /* out */ unsigned int &nBytesConsumed ); + eHeaderParse TryParseHeader(unsigned char* pInput, size_t nBytesAvailable, + /* out */ size_t& nBytesConsumed); void FreeDecoderState(); bool CreateDecoderState( const unsigned char *pProperties ); @@ -87,10 +89,10 @@ class CLZMAStream // Init from a zip-embedded LZMA stream. Requires the original size be passed from zip headers. CLzmaDec_t *m_pDecoderState; - unsigned int m_nActualSize; - unsigned int m_nActualBytesRead; - unsigned int m_nCompressedSize; - unsigned int m_nCompressedBytesRead; + size_t m_nActualSize; + size_t m_nActualBytesRead; + size_t m_nCompressedSize; + size_t m_nCompressedBytesRead; // If we have read past the header bool m_bParsedHeader : 1; diff --git a/headers/lzmatextureimpl.hpp b/headers/lzmatextureimpl.hpp index 2eeeea6..619cc3b 100644 --- a/headers/lzmatextureimpl.hpp +++ b/headers/lzmatextureimpl.hpp @@ -2,7 +2,7 @@ #include "lzmatexture.hpp" -#include +#include namespace uc2 { @@ -28,7 +28,7 @@ class LzmaTextureImpl : public LzmaTexture { public: LzmaTextureImpl(std::vector& texData); - LzmaTextureImpl(gsl::span texDataView); + LzmaTextureImpl(std::span texDataView); virtual ~LzmaTextureImpl(); virtual std::uint64_t GetOriginalSize() override; @@ -36,9 +36,9 @@ class LzmaTextureImpl : public LzmaTexture virtual bool Decompress(std::uint8_t* outBuffer, std::uint64_t outBufferSize) override; - static bool IsLzmaTextureSpan(gsl::span texData); + static bool IsLzmaTextureSpan(std::span texData); private: - gsl::span m_TexDataView; + std::span m_TexDataView; }; } // namespace uc2 diff --git a/headers/pkg/pkgentryimpl.hpp b/headers/pkg/pkgentryimpl.hpp index bdac7a2..bd49beb 100644 --- a/headers/pkg/pkgentryimpl.hpp +++ b/headers/pkg/pkgentryimpl.hpp @@ -2,7 +2,7 @@ #include "pkgentry.hpp" -#include +#include #include #include @@ -13,7 +13,7 @@ class PkgEntryImpl : public PkgEntry public: PkgEntryImpl(std::string_view filePath, std::uint64_t pkgFileOffset, std::uint64_t encryptedSize, std::uint64_t decryptedSize, - bool isEncrypted, gsl::span fileData, + bool isEncrypted, std::span fileData, std::string_view szvPkgKey = {}); virtual ~PkgEntryImpl() override; @@ -27,7 +27,7 @@ class PkgEntryImpl : public PkgEntry virtual std::uint64_t GetDecryptedSize() override; virtual bool IsEncrypted() override; - void SetDataBufferView(gsl::span newDataView); + void SetDataBufferView(std::span newDataView); void ReleaseDataBufferView(); private: @@ -37,7 +37,7 @@ class PkgEntryImpl : public PkgEntry const std::uint64_t iBytesToDecrypt) const noexcept; private: - gsl::span m_FileDataView; + std::span m_FileDataView; std::string m_szHashedKey; diff --git a/headers/pkg/pkgfileimpl.hpp b/headers/pkg/pkgfileimpl.hpp index 4c290e9..c163482 100644 --- a/headers/pkg/pkgfileimpl.hpp +++ b/headers/pkg/pkgfileimpl.hpp @@ -2,7 +2,7 @@ #include "pkgfile.hpp" -#include +#include #include #include "pkg/pkgstructures.hpp" @@ -15,7 +15,7 @@ class PkgFileImpl : public PkgFile PkgFileImpl(std::string szFilename, std::vector& fileData, std::string szEntryKey = {}, std::string szDataKey = {}, PkgFileOptions* options = nullptr); - PkgFileImpl(std::string szFilename, gsl::span fileDataView, + PkgFileImpl(std::string szFilename, std::span fileDataView, std::string szEntryKey = {}, std::string szDataKey = {}, PkgFileOptions* pOptions = nullptr); virtual ~PkgFileImpl() override; @@ -27,7 +27,7 @@ class PkgFileImpl : public PkgFile virtual void SetTfoPkg(bool bNewState) override; virtual void SetDataBuffer(std::vector& newFileData) override; - void SetDataBufferSpan(gsl::span newDataBuffer); + void SetDataBufferSpan(std::span newDataBuffer); virtual void ReleaseDataBuffer() override; virtual std::uint64_t GetFullHeaderSize() override; @@ -40,12 +40,12 @@ class PkgFileImpl : public PkgFile virtual std::vector& GetEntries() override; static ptr_t CreateSpan(std::string szFilename, - gsl::span fileDataView = {}, + std::span fileDataView = {}, std::string szEntryKey = {}, std::string szDataKey = {}, PkgFileOptions* pOptions = nullptr); - template + template std::uint64_t GetFullHeaderSizeInternal() const; private: @@ -60,7 +60,7 @@ class PkgFileImpl : public PkgFile template bool DecryptHeaderInternal(); - template + template void ParseEntries(); void UpdateEntriesDataView(); @@ -68,8 +68,8 @@ class PkgFileImpl : public PkgFile template PkgHeaderType* GetPkgHeader() const; - template - PkgEntryHeader_t* GetEntriesHeader() const; + template + PkgEntryHeaderType* GetEntriesHeader() const; private: std::string m_szFilename; @@ -78,7 +78,7 @@ class PkgFileImpl : public PkgFile std::string m_szMd5Hash; - gsl::span m_FileDataView; + std::span m_FileDataView; std::vector> m_Entries; diff --git a/headers/pkg/pkgindeximpl.hpp b/headers/pkg/pkgindeximpl.hpp index 1845225..620635b 100755 --- a/headers/pkg/pkgindeximpl.hpp +++ b/headers/pkg/pkgindeximpl.hpp @@ -2,7 +2,7 @@ #include "pkgindex.hpp" -#include +#include namespace uc2 { @@ -15,14 +15,14 @@ class PkgIndexImpl : public PkgIndex std::vector& fileData, const std::uint8_t (*keyCollection)[4][16]); PkgIndexImpl(std::string_view indexFilename, - gsl::span fileDataView, - gsl::span keyCollectionView); + std::span fileDataView, + std::span keyCollectionView); virtual ~PkgIndexImpl() override; virtual void SetKeyCollection( const std::uint8_t (*keyCollection)[4][16]) override; void SetKeyCollectionSpan( - gsl::span keyCollectionView); + std::span keyCollectionView); virtual void ValidateHeader() override; @@ -31,13 +31,13 @@ class PkgIndexImpl : public PkgIndex virtual const std::vector& GetFilenames() override; static ptr_t CreateSpan( - std::string_view indexFilename, gsl::span fileDataView, - gsl::span keyCollectionView); + std::string_view indexFilename, std::span fileDataView, + std::span keyCollectionView); private: std::string_view m_szvIndexFilename; - gsl::span m_FileDataView; - gsl::span m_KeyCollectionView; + std::span m_FileDataView; + std::span m_KeyCollectionView; std::vector m_vFilenames; diff --git a/headers/pkg/pkgstructures.hpp b/headers/pkg/pkgstructures.hpp index eb9e9bb..373fa65 100644 --- a/headers/pkg/pkgstructures.hpp +++ b/headers/pkg/pkgstructures.hpp @@ -59,5 +59,19 @@ struct PkgEntryHeader_t static_assert(sizeof(PkgEntryHeader_t) == 288, "The pkg entry header's size must be 288 bytes long"); +struct PkgEntryHeaderTfo_t +{ + char szFilePath[260 + 1]; + std::uint64_t iOffset; + std::uint64_t iEncryptedSize; + std::uint64_t iDecryptedSize; + std::uint8_t Unknown285; + std::uint8_t bIsEncrypted; + std::uint8_t Pad[1]; +}; + +static_assert(sizeof(PkgEntryHeader_t) == 288, + "The TFO pkg entry header's size must be 288 bytes long"); + #pragma pack(pop) } // namespace uc2 diff --git a/sources/bindings/encryptedfile.cpp b/sources/bindings/encryptedfile.cpp index 5011064..77db22f 100755 --- a/sources/bindings/encryptedfile.cpp +++ b/sources/bindings/encryptedfile.cpp @@ -8,10 +8,10 @@ extern "C" const char* filename, void* dataBuffer, uint64_t dataSize, const uint8_t (*keyCollection)[4][16]) { - gsl::span dataView(reinterpret_cast(dataBuffer), + std::span dataView(reinterpret_cast(dataBuffer), dataSize); - gsl::span keyCollectionView(keyCollection, + std::span keyCollectionView(keyCollection, 16 * 4); try @@ -20,7 +20,7 @@ extern "C" keyCollectionView); return reinterpret_cast(newPkg.release()); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -63,7 +63,7 @@ extern "C" return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } diff --git a/sources/bindings/lzmatexture.cpp b/sources/bindings/lzmatexture.cpp index 2d618e7..1b06b29 100755 --- a/sources/bindings/lzmatexture.cpp +++ b/sources/bindings/lzmatexture.cpp @@ -13,7 +13,7 @@ extern "C" reinterpret_cast(texBuffer), texSize); return reinterpret_cast(newTex.release()); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -39,7 +39,7 @@ extern "C" { return pTex->GetOriginalSize(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -71,7 +71,7 @@ extern "C" return pTex->Decompress(reinterpret_cast(outBuffer), outBufferSize); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } diff --git a/sources/bindings/pkgentry.cpp b/sources/bindings/pkgentry.cpp index 74d7283..cace0b0 100755 --- a/sources/bindings/pkgentry.cpp +++ b/sources/bindings/pkgentry.cpp @@ -25,7 +25,7 @@ extern "C" return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } @@ -45,7 +45,7 @@ extern "C" { return pEntry->GetFilePath().data(); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -65,7 +65,7 @@ extern "C" { return pEntry->GetPkgFileOffset(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -85,7 +85,7 @@ extern "C" { return pEntry->GetEncryptedSize(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -105,7 +105,7 @@ extern "C" { return pEntry->GetDecryptedSize(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -124,7 +124,7 @@ extern "C" { return pEntry->IsEncrypted(); } - catch (const std::exception& e) + catch (const std::exception&) { return false; } diff --git a/sources/bindings/pkgfile.cpp b/sources/bindings/pkgfile.cpp index 26803f7..82999fb 100755 --- a/sources/bindings/pkgfile.cpp +++ b/sources/bindings/pkgfile.cpp @@ -9,7 +9,7 @@ extern "C" const char* szEntryKey, const char* szDataKey, PkgFileOptions_t options /*= NULL*/) { - gsl::span dataView(reinterpret_cast(dataBuffer), + std::span dataView(reinterpret_cast(dataBuffer), dataSize); auto pOptions = reinterpret_cast(options); @@ -20,7 +20,7 @@ extern "C" filename, dataView, szEntryKey, szDataKey, pOptions); return reinterpret_cast(newPkg.release()); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -95,7 +95,7 @@ extern "C" auto pPkg = reinterpret_cast(pkgHandle); - gsl::span dataView(reinterpret_cast(dataBuffer), + std::span dataView(reinterpret_cast(dataBuffer), dataSize); pPkg->SetDataBufferSpan(dataView); @@ -127,7 +127,7 @@ extern "C" { return pPkg->GetFullHeaderSize(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -147,7 +147,7 @@ extern "C" pPkg->DecryptHeader(); return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } @@ -167,7 +167,7 @@ extern "C" pPkg->Parse(); return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } @@ -186,7 +186,7 @@ extern "C" { return pPkg->GetEntries().size(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -205,7 +205,7 @@ extern "C" { return reinterpret_cast(pPkg->GetEntries().data()); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } diff --git a/sources/bindings/pkgfileoptions.cpp b/sources/bindings/pkgfileoptions.cpp index 86d0c7d..c474a7a 100755 --- a/sources/bindings/pkgfileoptions.cpp +++ b/sources/bindings/pkgfileoptions.cpp @@ -11,7 +11,7 @@ extern "C" auto newOptions = uc2::PkgFileOptions::Create(); return reinterpret_cast(newOptions.release()); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -38,7 +38,7 @@ extern "C" { pOptions->SetTfoPkg(state); } - catch (const std::exception& e) + catch (const std::exception&) { return; } @@ -58,7 +58,7 @@ extern "C" { return pOptions->IsTfoPkg(); } - catch (const std::exception& e) + catch (const std::exception&) { return false; } diff --git a/sources/bindings/pkgindex.cpp b/sources/bindings/pkgindex.cpp index 8cd9a55..f17dfb9 100755 --- a/sources/bindings/pkgindex.cpp +++ b/sources/bindings/pkgindex.cpp @@ -8,10 +8,10 @@ extern "C" const char* filename, void* dataBuffer, uint64_t dataSize, const uint8_t (*keyCollection)[4][16]) { - gsl::span dataView(reinterpret_cast(dataBuffer), + std::span dataView(reinterpret_cast(dataBuffer), dataSize); - gsl::span keyCollectionView(keyCollection, + std::span keyCollectionView(keyCollection, 16 * 4); try @@ -20,7 +20,7 @@ extern "C" keyCollectionView); return reinterpret_cast(newPkg.release()); } - catch (const std::exception& e) + catch (const std::exception&) { return NULL; } @@ -60,7 +60,7 @@ extern "C" pIndex->ValidateHeader(); return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } @@ -80,7 +80,7 @@ extern "C" pIndex->Parse(); return true; } - catch (const std::exception& e) + catch (const std::exception&) { return false; } @@ -100,7 +100,7 @@ extern "C" { return pPkg->GetFilenames().size(); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } @@ -121,7 +121,7 @@ extern "C" return reinterpret_cast( pPkg->GetFilenames().data()); } - catch (const std::exception& e) + catch (const std::exception&) { return 0; } diff --git a/sources/ciphers/aescipher.cpp b/sources/ciphers/aescipher.cpp index 2f65176..e6f65f2 100644 --- a/sources/ciphers/aescipher.cpp +++ b/sources/ciphers/aescipher.cpp @@ -1,8 +1,8 @@ #include "ciphers/aescipher.hpp" -#include -#include -#include +#include +#include +#include namespace uc2 { @@ -18,8 +18,8 @@ void CAesCipher::Initialize(std::string_view key, std::string_view iv, this->m_bPaddingEnabled = paddingEnabled; } -std::uint64_t CAesCipher::Decrypt(gsl::span inData, - gsl::span outBuffer) +std::uint64_t CAesCipher::Decrypt(std::span inData, + std::span outBuffer) { CryptoPP::CBC_Mode::Decryption dec; diff --git a/sources/ciphers/blowfishcipher.cpp b/sources/ciphers/blowfishcipher.cpp index dea5464..6496ffa 100644 --- a/sources/ciphers/blowfishcipher.cpp +++ b/sources/ciphers/blowfishcipher.cpp @@ -1,8 +1,8 @@ #include "ciphers/blowfishcipher.hpp" -#include -#include -#include +#include +#include +#include namespace uc2 { @@ -18,8 +18,8 @@ void CBlowfishCipher::Initialize(std::string_view key, std::string_view iv, this->m_bPaddingEnabled = paddingEnabled; } -std::uint64_t CBlowfishCipher::Decrypt(gsl::span inData, - gsl::span outBuffer) +std::uint64_t CBlowfishCipher::Decrypt(std::span inData, + std::span outBuffer) { CryptoPP::CBC_Mode::Decryption dec; diff --git a/sources/ciphers/descipher.cpp b/sources/ciphers/descipher.cpp index 779078d..5d01cf7 100644 --- a/sources/ciphers/descipher.cpp +++ b/sources/ciphers/descipher.cpp @@ -1,8 +1,8 @@ #include "ciphers/descipher.hpp" -#include -#include -#include +#include +#include +#include namespace uc2 { @@ -18,8 +18,8 @@ void CDesCipher::Initialize(std::string_view key, std::string_view iv, this->m_bPaddingEnabled = paddingEnabled; } -std::uint64_t CDesCipher::Decrypt(gsl::span inData, - gsl::span outBuffer) +std::uint64_t CDesCipher::Decrypt(std::span inData, + std::span outBuffer) { CryptoPP::CBC_Mode::Decryption dec; diff --git a/sources/decryptor.cpp b/sources/decryptor.cpp index 9c6ae95..0bb0478 100755 --- a/sources/decryptor.cpp +++ b/sources/decryptor.cpp @@ -81,9 +81,9 @@ std::vector CDecryptor::Decrypt( std::size_t CDecryptor::Decrypt(const void* pStart, void* pOutBuffer, const std::size_t iLength) const { - gsl::span inData( + std::span inData( static_cast(pStart), iLength); - gsl::span outData(static_cast(pOutBuffer), + std::span outData(static_cast(pOutBuffer), iLength); return this->m_pCipher->Decrypt(inData, outData); } @@ -91,9 +91,9 @@ std::size_t CDecryptor::Decrypt(const void* pStart, void* pOutBuffer, std::size_t CDecryptor::DecryptInBuffer(void* pBuffer, const std::size_t iLength) const { - gsl::span inData( + std::span inData( static_cast(pBuffer), iLength); - gsl::span outData(static_cast(pBuffer), + std::span outData(static_cast(pBuffer), iLength); return this->m_pCipher->Decrypt(inData, outData); } @@ -103,7 +103,7 @@ std::vector CDecryptor::Decrypt(const void* pStart, { std::vector vOutData(iLength); - gsl::span inData( + std::span inData( static_cast(pStart), iLength); this->m_pCipher->Decrypt(inData, vOutData); diff --git a/sources/encryptedfile.cpp b/sources/encryptedfile.cpp index d314a19..21a8f50 100644 --- a/sources/encryptedfile.cpp +++ b/sources/encryptedfile.cpp @@ -24,12 +24,13 @@ EncryptedFile::ptr_t EncryptedFile::Create( const std::uint64_t iDataSize, const std::uint8_t (&keyCollection)[4][16]) { return EncryptedFileImpl::CreateSpan( - fileName, gsl::span(pData, iDataSize), keyCollection); + fileName, std::span(pData, iDataSize), + { &keyCollection, 1 }); } EncryptedFile::ptr_t EncryptedFileImpl::CreateSpan( - std::string_view fileName, gsl::span fileDataView, - gsl::span keyCollectionView) + std::string_view fileName, std::span fileDataView, + std::span keyCollectionView) { return std::make_unique(fileName, fileDataView, keyCollectionView); @@ -38,7 +39,7 @@ EncryptedFile::ptr_t EncryptedFileImpl::CreateSpan( bool EncryptedFile::IsEncryptedFile(std::uint8_t* pData, const std::uint64_t iDataSize) { - gsl::span dataView(pData, iDataSize); + std::span dataView(pData, iDataSize); if (iDataSize < sizeof(EncryptedFileHeader_t)) { @@ -84,8 +85,8 @@ EncryptedFileImpl::EncryptedFileImpl(std::string_view fileName, } EncryptedFileImpl::EncryptedFileImpl( - std::string_view fileName, gsl::span fileDataView, - gsl::span keyCollectionView) + std::string_view fileName, std::span fileDataView, + std::span keyCollectionView) : m_szvFileName(fileName), m_FileDataView(fileDataView), m_KeyCollectionView(keyCollectionView) { diff --git a/sources/keyhashes.cpp b/sources/keyhashes.cpp index 2aca6af..136d6c8 100755 --- a/sources/keyhashes.cpp +++ b/sources/keyhashes.cpp @@ -3,14 +3,14 @@ #include #include -#include -#include +#include +#include namespace uc2 { std::vector GeneratePkgIndexKey( int iKey, std::string_view szPkgName, - gsl::span keyCollectionView) + std::span keyCollectionView) { constexpr const std::uint32_t iVersion = 2; static_assert(sizeof(iVersion) == 4, "iVersion's size must be 4 bytes"); diff --git a/sources/lzmaDecoder.cpp b/sources/lzmaDecoder.cpp index 1d61932..16a4165 100644 --- a/sources/lzmaDecoder.cpp +++ b/sources/lzmaDecoder.cpp @@ -27,11 +27,11 @@ #include "lzmaDecoder.h" // Allocator to pass to LZMA functions -static void* SzAlloc(ISzAllocPtr p, std::size_t size) +static void* SzAlloc(ISzAllocPtr, std::size_t size) { return malloc(size); } -static void SzFree(ISzAllocPtr p, void* address) +static void SzFree(ISzAllocPtr, void* address) { free(address); } @@ -75,7 +75,7 @@ unsigned int CLZMA::GetActualSize(unsigned char* pInput) // adequate sized output buffer or memory corruption will occur. //----------------------------------------------------------------------------- /* static */ -unsigned int CLZMA::Uncompress(unsigned char* pInput, unsigned char* pOutput) +size_t CLZMA::Uncompress(unsigned char* pInput, unsigned char* pOutput) { lzma_header_t* pHeader = (lzma_header_t*)pInput; if (pHeader->id != LZMA_ID) @@ -161,10 +161,10 @@ bool CLZMAStream::CreateDecoderState(const unsigned char* pProperties) // Attempt to read up to nMaxInputBytes from the compressed stream, writing up // to nMaxOutputBytes to pOutput. Returns false if read stops due to an error. -bool CLZMAStream::Read(unsigned char* pInput, unsigned int nMaxInputBytes, - unsigned char* pOutput, unsigned int nMaxOutputBytes, - /* out */ unsigned int& nCompressedBytesRead, - /* out */ unsigned int& nOutputBytesWritten) +bool CLZMAStream::Read(unsigned char* pInput, size_t nMaxInputBytes, + unsigned char* pOutput, size_t nMaxOutputBytes, + /* out */ size_t& nCompressedBytesRead, + /* out */ size_t& nOutputBytesWritten) { nCompressedBytesRead = 0; nOutputBytesWritten = 0; @@ -173,7 +173,7 @@ bool CLZMAStream::Read(unsigned char* pInput, unsigned int nMaxInputBytes, // Check for initial chunk of data if (!m_bParsedHeader) { - unsigned int nBytesConsumed = 0; + size_t nBytesConsumed = 0; eHeaderParse parseResult = TryParseHeader(pInput, nMaxInputBytes, nBytesConsumed); @@ -280,8 +280,8 @@ void CLZMAStream::InitZIPHeader(unsigned int nCompressedSize, } CLZMAStream::eHeaderParse CLZMAStream::TryParseHeader( - unsigned char* pInput, unsigned int nBytesAvailable, - /* out */ unsigned int& nBytesConsumed) + unsigned char* pInput, size_t nBytesAvailable, + /* out */ size_t& nBytesConsumed) { nBytesConsumed = 0; @@ -316,8 +316,7 @@ CLZMAStream::eHeaderParse CLZMAStream::TryParseHeader( return eHeaderParse_Fail; } - if (nBytesAvailable < - static_cast(nLZMAPropertiesSize) + 4) + if (nBytesAvailable < static_cast(nLZMAPropertiesSize) + 4) { return eHeaderParse_NeedMoreBytes; } diff --git a/sources/lzmatexture.cpp b/sources/lzmatexture.cpp index 114bf5c..cba3e98 100644 --- a/sources/lzmatexture.cpp +++ b/sources/lzmatexture.cpp @@ -16,7 +16,7 @@ LzmaTexture::ptr_t LzmaTexture::Create(std::uint8_t* pData, const std::uint64_t iDataSize) { return std::make_unique( - gsl::span(pData, iDataSize)); + std::span(pData, iDataSize)); } LzmaTextureImpl::LzmaTextureImpl(std::vector& texData) @@ -29,7 +29,7 @@ LzmaTextureImpl::LzmaTextureImpl(std::vector& texData) } } -LzmaTextureImpl::LzmaTextureImpl(gsl::span texDataView) +LzmaTextureImpl::LzmaTextureImpl(std::span texDataView) : m_TexDataView(texDataView) { if (LzmaTexture::IsLzmaTexture(this->m_TexDataView.data(), @@ -98,7 +98,7 @@ bool LzmaTextureImpl::Decompress(std::uint8_t* outBuffer, bool LzmaTexture::IsLzmaTexture(std::uint8_t* pData, const std::uint64_t iDataSize) { - gsl::span dataView(pData, iDataSize); + std::span dataView(pData, iDataSize); return LzmaTextureImpl::IsLzmaTextureSpan(dataView); } @@ -107,7 +107,7 @@ std::uint64_t LzmaTexture::GetHeaderSize() return sizeof(LzmaVtfHeader_t); } -bool LzmaTextureImpl::IsLzmaTextureSpan(gsl::span texData) +bool LzmaTextureImpl::IsLzmaTextureSpan(std::span texData) { const std::uint64_t iFileDataSize = texData.size_bytes(); diff --git a/sources/pkg/pkgentry.cpp b/sources/pkg/pkgentry.cpp index 2311565..5b2c078 100755 --- a/sources/pkg/pkgentry.cpp +++ b/sources/pkg/pkgentry.cpp @@ -37,7 +37,7 @@ PkgEntryImpl::PkgEntryImpl(std::string_view szFilePath, std::uint64_t pkgFileOffset, std::uint64_t encryptedSize, std::uint64_t decryptedSize, bool isEncrypted, - gsl::span fileDataView, + std::span fileDataView, std::string_view szvPkgKey /*= {}*/) : m_FileDataView(fileDataView), m_szFilePath(MakeUnixSeparated(szFilePath)), m_iPkgFileOffset(pkgFileOffset), m_iEncryptedSize(encryptedSize), @@ -70,6 +70,13 @@ std::pair PkgEntryImpl::DecryptFile( "libuncso2: The entry's file data is empty."); } + if (iBytesToDecrypt > this->m_iDecryptedSize) + { + throw std::invalid_argument( + "libuncso2: The amount of bytes requested to decrypt is bigger " + "than decrypted file size."); + } + const bool bDecryptAll = iBytesToDecrypt == 0; const std::uint64_t iAlignedBytes = bDecryptAll == true ? 0 : RoundNumberToBlock(iBytesToDecrypt); @@ -142,7 +149,8 @@ std::pair PkgEntryImpl::HandleEncryptedFile( const std::uint64_t iTargetEncDataSize = bDecryptAll == true ? this->m_iEncryptedSize : iBytesToDecrypt; const std::uint64_t iTargetDecDataSize = - bDecryptAll == true ? this->m_iDecryptedSize : iBytesToDecrypt; + bDecryptAll == true ? this->m_iDecryptedSize : + std::min(this->m_iDecryptedSize, iBytesToDecrypt); // The data must be decrypted each PKG_DATA_BLOCK_SIZE (which at the // time of writing this is 65536), or else only the first 65536 @@ -176,13 +184,13 @@ std::pair PkgEntryImpl::HandlePlainFile( return { pFileStart, iTargetDecDataSize }; } -void PkgEntryImpl::SetDataBufferView(gsl::span newDataView) +void PkgEntryImpl::SetDataBufferView(std::span newDataView) { this->m_FileDataView = newDataView; } void PkgEntryImpl::ReleaseDataBufferView() { - this->m_FileDataView = gsl::span(); + this->m_FileDataView = std::span(); } } // namespace uc2 \ No newline at end of file diff --git a/sources/pkg/pkgfile.cpp b/sources/pkg/pkgfile.cpp index f5cae54..18cdd2e 100755 --- a/sources/pkg/pkgfile.cpp +++ b/sources/pkg/pkgfile.cpp @@ -36,7 +36,7 @@ std::uint64_t PkgFile::GetHeaderSize(bool bTfoPkg) } PkgFile::ptr_t PkgFileImpl::CreateSpan(std::string szFilename, - gsl::span fileData, + std::span fileData, std::string szEntryKey /*= {}*/, std::string szDataKey /*= {}*/, PkgFileOptions* pOptions /* = nullptr*/) @@ -58,7 +58,7 @@ PkgFileImpl::PkgFileImpl(std::string szFilename, } PkgFileImpl::PkgFileImpl(std::string szFilename, - gsl::span fileData, + std::span fileData, std::string szEntryKey /*= {}*/, std::string szDataKey /*= {}*/, PkgFileOptions* pOptions /* = nullptr*/) @@ -151,7 +151,7 @@ void PkgFileImpl::SetDataBuffer(std::vector& newFileData) this->UpdateEntriesDataView(); } -void PkgFileImpl::SetDataBufferSpan(gsl::span newDataBuffer) +void PkgFileImpl::SetDataBufferSpan(std::span newDataBuffer) { this->m_FileDataView = newDataBuffer; this->UpdateEntriesDataView(); @@ -166,11 +166,13 @@ std::uint64_t PkgFileImpl::GetFullHeaderSize() { if (this->m_bIsTfoPkg == true) { - return PkgFileImpl::GetFullHeaderSizeInternal(); + return PkgFileImpl::GetFullHeaderSizeInternal(); } else { - return PkgFileImpl::GetFullHeaderSizeInternal(); + return PkgFileImpl::GetFullHeaderSizeInternal(); } } @@ -179,7 +181,7 @@ std::string_view PkgFileImpl::GetMd5Hash() return this->m_szMd5Hash; } -template +template std::uint64_t PkgFileImpl::GetFullHeaderSizeInternal() const { if (this->IsHeaderDecryptedInternal() == false) @@ -197,7 +199,7 @@ std::uint64_t PkgFileImpl::GetFullHeaderSizeInternal() const auto pPkgHeader = this->GetPkgHeader(); return PKG_HEADER_SKIP_HASH_OFFSET + sizeof(PkgHeaderType) + - pPkgHeader->iEntries * sizeof(PkgEntryHeader_t); + pPkgHeader->iEntries * sizeof(PkgEntryHeaderType); } bool PkgFileImpl::DecryptHeader() @@ -241,11 +243,11 @@ void PkgFileImpl::Parse() if (this->m_bIsTfoPkg == true) { - this->ParseEntries(); + this->ParseEntries(); } else { - this->ParseEntries(); + this->ParseEntries(); } } @@ -277,7 +279,7 @@ bool PkgFileImpl::DecryptHeaderInternal() return true; } -template +template void PkgFileImpl::ParseEntries() { if (this->IsHeaderDecryptedInternal() == false) @@ -290,19 +292,19 @@ void PkgFileImpl::ParseEntries() this->m_FileDataView.subspan(0, PKG_HEADER_SKIP_HASH_OFFSET).data()); auto pPkgHeader = this->GetPkgHeader(); - auto pEntries = this->GetEntriesHeader(); + auto pEntries = this->GetEntriesHeader(); const std::uint64_t iDataStartOffset = PKG_HEADER_SKIP_HASH_OFFSET + sizeof(PkgHeaderType) + - pPkgHeader->iEntries * sizeof(PkgEntryHeader_t); + pPkgHeader->iEntries * sizeof(PkgEntryHeaderType); CAesCipher cipher; CDecryptor decryptor(&cipher, this->m_szHashedEntryKey, false); for (std::uint32_t i = 0; i < pPkgHeader->iEntries; i++) { - PkgEntryHeader_t* entry = &pEntries[i]; - decryptor.DecryptInBuffer(entry, sizeof(PkgEntryHeader_t)); + PkgEntryHeaderType* entry = &pEntries[i]; + decryptor.DecryptInBuffer(entry, sizeof(PkgEntryHeaderType)); auto pNewEntry = std::make_unique( entry->szFilePath, iDataStartOffset + entry->iOffset, @@ -333,12 +335,12 @@ PkgHeaderType* PkgFileImpl::GetPkgHeader() const return reinterpret_cast(data); } -template -PkgEntryHeader_t* PkgFileImpl::GetEntriesHeader() const +template +PkgEntryHeaderType* PkgFileImpl::GetEntriesHeader() const { std::uint64_t data = reinterpret_cast(this->m_FileDataView.data()); data += PKG_HEADER_SKIP_HASH_OFFSET + sizeof(PkgHeaderType); - return reinterpret_cast(data); + return reinterpret_cast(data); } } // namespace uc2 \ No newline at end of file diff --git a/sources/pkg/pkgindex.cpp b/sources/pkg/pkgindex.cpp index eff8f62..f200128 100755 --- a/sources/pkg/pkgindex.cpp +++ b/sources/pkg/pkgindex.cpp @@ -12,7 +12,7 @@ namespace uc2 constexpr const std::uint16_t SUPPORTED_PKG_VERSION = 2; std::vector SplitTextFileByLine( - gsl::span fileBuffer) + std::span fileBuffer) { constexpr std::string_view szNewLine("\r\n", 2); @@ -46,8 +46,8 @@ PkgIndex::ptr_t PkgIndex::Create( } PkgIndex::ptr_t PkgIndexImpl::CreateSpan( - std::string_view indexFilename, gsl::span fileDataView, - gsl::span keyCollectionView) + std::string_view indexFilename, std::span fileDataView, + std::span keyCollectionView) { return std::make_unique(indexFilename, fileDataView, keyCollectionView); @@ -66,8 +66,8 @@ PkgIndexImpl::PkgIndexImpl(std::string_view indexFilename, } PkgIndexImpl::PkgIndexImpl( - std::string_view indexFilename, gsl::span fileDataView, - gsl::span keyCollectionView) + std::string_view indexFilename, std::span fileDataView, + std::span keyCollectionView) : m_szvIndexFilename(indexFilename), m_FileDataView(fileDataView), m_KeyCollectionView(keyCollectionView), m_bHeaderValidated(false) { @@ -81,7 +81,7 @@ void PkgIndexImpl::SetKeyCollection(const std::uint8_t (*keyCollection)[4][16]) } void PkgIndexImpl::SetKeyCollectionSpan( - gsl::span keyCollectionView) + std::span keyCollectionView) { this->m_KeyCollectionView = keyCollectionView; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fbee469..d0c7fed 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,7 +21,7 @@ set(PKG_TESTS_TFO_NEXON_SOURCES "tfo/nexon/test_pkgindex.cpp" "tfo/nexon/settings.hpp") -set(PKG_TESTS_SOURCES_BASE "test_main.cpp" "utils.cpp") +set(PKG_TESTS_SOURCES_BASE "utils.cpp") set(PKG_TESTS_HEADERS_BASE "utils.hpp") @@ -45,13 +45,7 @@ target_include_directories(pkg_test target_include_directories(pkg_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(${PKG_LIB_CATCH_DIR} catch) -target_link_libraries(pkg_test Catch2::Catch2) - -if(PKG_USE_CLANG_FSAPI) - target_link_libraries(pkg_test c++abi c++fs) -elseif(NOT MSVC) - target_link_libraries(pkg_test stdc++fs) -endif() +target_link_libraries(pkg_test Catch2::Catch2WithMain) target_link_libraries(pkg_test uncso2) @@ -63,3 +57,15 @@ file(GLOB PKG_TEST_REQUIRED_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gamefiles/*") foreach(file ${PKG_TEST_REQUIRED_FILES}) configure_file(${file} "${CMAKE_CURRENT_BINARY_DIR}/" COPYONLY) endforeach() + +if(WIN32) + add_custom_command( + TARGET pkg_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/../uncso2.dll + ${CMAKE_CURRENT_BINARY_DIR}) +endif() + +include(CTest) +include(Catch) +catch_discover_tests(pkg_test) diff --git a/tests/cso2/nexon/test_encfile.cpp b/tests/cso2/nexon/test_encfile.cpp index 28b8695..f6f20f0 100644 --- a/tests/cso2/nexon/test_encfile.cpp +++ b/tests/cso2/nexon/test_encfile.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/tests/cso2/nexon/test_lzmatex.cpp b/tests/cso2/nexon/test_lzmatex.cpp index b3cbe0b..502a6d5 100644 --- a/tests/cso2/nexon/test_lzmatex.cpp +++ b/tests/cso2/nexon/test_lzmatex.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/tests/cso2/nexon/test_pkgfile.cpp b/tests/cso2/nexon/test_pkgfile.cpp index 33d6831..679bd12 100644 --- a/tests/cso2/nexon/test_pkgfile.cpp +++ b/tests/cso2/nexon/test_pkgfile.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/tests/cso2/nexon/test_pkgindex.cpp b/tests/cso2/nexon/test_pkgindex.cpp index b6525c9..1fc7e93 100644 --- a/tests/cso2/nexon/test_pkgindex.cpp +++ b/tests/cso2/nexon/test_pkgindex.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/tests/gamefiles/d0112b5fb371db812eb586c3d8d19f4f.pkg b/tests/gamefiles/d0112b5fb371db812eb586c3d8d19f4f.pkg new file mode 100644 index 0000000..71d0cca Binary files /dev/null and b/tests/gamefiles/d0112b5fb371db812eb586c3d8d19f4f.pkg differ diff --git a/tests/test_main.cpp b/tests/test_main.cpp deleted file mode 100644 index 4ed06df..0000000 --- a/tests/test_main.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include diff --git a/tests/tfo/nexon/settings.hpp b/tests/tfo/nexon/settings.hpp index e58bea8..150436d 100644 --- a/tests/tfo/nexon/settings.hpp +++ b/tests/tfo/nexon/settings.hpp @@ -33,20 +33,35 @@ constexpr const std::uint8_t IndexKeyCollection[4][16] = { // // PKG data START // -const std::string PkgFilename = "0a4b4196394ecf251c532f1552ccf3b3.pkg"s; const std::string PackageEntryKey = "lkgui781kl789sd!@#%89&^sd"s; - const std::string PackageFileKey = "^9gErg2Sx7bnk7@#sdfjnh@"s; -constexpr const std::uint64_t PackageFileCount = 4; - -const std::array PackageFileHashes = { - "42d3b7b74b8feb7f6801930ba58aef6bb85fa2d8a465cffef36c906566cbeeb4", - "58389be7fbcaa33e143c8e7ed85b7ed73e5d69d095972e9d260a4171ed959224", - "2968dce6245f50c7ae9803e1b765ff9ed7705a459c4041f4623a46dea24b9873", - "638f05cce5002f65917125931a07f2541b4fca6819623950f9c306bba18d9ae7", +const std::vector>> Packages = { + { + "0a4b4196394ecf251c532f1552ccf3b3.pkg", + { + "cab6520af0e54b17b46a9ae45611c339e64e50e06f341dd834464acc9689af15", + "31d262620204566d8c3f7bf40f637d6229c2b15b1dd5abee1f784d7b5fba6c97", + "c013887bc3e6e16e4ce84d6c674faea8e70e27b2b0d2864e534f78c88b2be270", + "c9173ac086723d08025380964c38e905a93116eb77ea7d6d3edb24e07bc81d4b", + } + }, + { + "d0112b5fb371db812eb586c3d8d19f4f.pkg", + { + "c32759a871bc14ce2f84381a63dec7895b4376a9d69ef65421a770cae9ab34e4", + "5a2c571f3fec0c83075a97a7f6f8bc52864e9fc2c5576d9db77fd3d25c73950b", + "437510ea732d3d10befc8940cbb2e38777271fdb51e23c5354843f4625a4f99d", + "4355f6960122aac15ee3f069ab2da06783cf4e17a132fef6eac36309d3be0bc7", + "55562fbc475b77283260950ca5810571d27096bc5d5f89388e2736ce7dd21bb3", + "7c2ed35e2ce03c61e199fb7842759605b5443262d6319ce3e1cb71ce28e00bae", + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "443a3b4d621cbba7429118d82a001e513327d8831a76414e3b47052cdf2888a5", + } + }, }; + // // PKG data END // diff --git a/tests/tfo/nexon/test_pkgfile.cpp b/tests/tfo/nexon/test_pkgfile.cpp index a4e79cc..324472c 100644 --- a/tests/tfo/nexon/test_pkgfile.cpp +++ b/tests/tfo/nexon/test_pkgfile.cpp @@ -1,7 +1,8 @@ -#include +#include #include #include +#include #include #include @@ -13,36 +14,43 @@ using namespace std::literals::string_view_literals; TEST_CASE("TFO Pkg file can be decrypted and parsed", "[pkgfile]") { - SECTION("Can parse entries") + SECTION("Can parse entries and verify their hashes") { - auto [bWasRead, vFileBuffer] = ReadFileToBuffer(tfo::PkgFilename); - - REQUIRE(bWasRead == true); - REQUIRE(vFileBuffer.empty() == false); - try { - auto pPkgOptions = uc2::PkgFileOptions::Create(); - pPkgOptions->SetTfoPkg(true); + for (auto&& pair : tfo::Packages) + { + auto pPkgFilename = pair.first; + auto iPackageFileCount = pair.second.size(); + auto pPackageFileHashes = pair.second; - auto pPkgFile = uc2::PkgFile::Create( - tfo::PkgFilename, vFileBuffer, tfo::PackageEntryKey, - tfo::PackageFileKey, pPkgOptions.get()); + auto [bWasRead, vFileBuffer] = ReadFileToBuffer(pPkgFilename); - pPkgFile->DecryptHeader(); - pPkgFile->Parse(); + REQUIRE(bWasRead == true); + REQUIRE(vFileBuffer.empty() == false); - REQUIRE(pPkgFile->GetEntries().size() == tfo::PackageFileCount); + auto pPkgOptions = uc2::PkgFileOptions::Create(); + pPkgOptions->SetTfoPkg(true); - std::size_t iCurIndex = 0; - for (auto&& entry : pPkgFile->GetEntries()) - { - fs::path entryPath = entry->GetFilePath(); - auto [fileData, fileDataLen] = entry->DecryptFile(); - REQUIRE(GetDataHash(fileData, fileDataLen) == - tfo::PackageFileHashes[iCurIndex]); + auto pPkgFile = uc2::PkgFile::Create( + pPkgFilename, vFileBuffer, tfo::PackageEntryKey, + tfo::PackageFileKey, pPkgOptions.get()); + + pPkgFile->DecryptHeader(); + pPkgFile->Parse(); + + REQUIRE(pPkgFile->GetEntries().size() == iPackageFileCount); - iCurIndex++; + std::size_t iCurIndex = 0; + for (auto&& entry : pPkgFile->GetEntries()) + { + fs::path entryPath = entry->GetFilePath(); + auto [fileData, fileDataLen] = entry->DecryptFile(); + REQUIRE(GetDataHash(fileData, fileDataLen) == + pPackageFileHashes[iCurIndex]); + + iCurIndex++; + } } } catch (const std::exception& e) @@ -57,7 +65,10 @@ TEST_CASE("TFO Pkg file partially decrypting an entry", "[pkgfile]") { SECTION("Can decrypt 16 bytes of an entry") { - auto [bWasRead, vFileBuffer] = ReadFileToBuffer(tfo::PkgFilename); + auto pPkgFilename = tfo::Packages[0].first; + auto pPackageFileCount = tfo::Packages[0].second.size(); + + auto [bWasRead, vFileBuffer] = ReadFileToBuffer(pPkgFilename); REQUIRE(bWasRead == true); REQUIRE(vFileBuffer.empty() == false); @@ -68,13 +79,13 @@ TEST_CASE("TFO Pkg file partially decrypting an entry", "[pkgfile]") pPkgOptions->SetTfoPkg(true); auto pPkgFile = uc2::PkgFile::Create( - tfo::PkgFilename, vFileBuffer, tfo::PackageEntryKey, + pPkgFilename, vFileBuffer, tfo::PackageEntryKey, tfo::PackageFileKey, pPkgOptions.get()); pPkgFile->DecryptHeader(); pPkgFile->Parse(); - REQUIRE(pPkgFile->GetEntries().size() == tfo::PackageFileCount); + REQUIRE(pPkgFile->GetEntries().size() == pPackageFileCount); constexpr const std::uint64_t iTargetFileLen = 16; @@ -91,7 +102,10 @@ TEST_CASE("TFO Pkg file partially decrypting an entry", "[pkgfile]") } SECTION("Can decrypt 23 bytes of an entry") { - auto [bWasRead, vFileBuffer] = ReadFileToBuffer(tfo::PkgFilename); + auto pPkgFilename = tfo::Packages[0].first; + auto pPackageFileCount = tfo::Packages[0].second.size(); + + auto [bWasRead, vFileBuffer] = ReadFileToBuffer(pPkgFilename); REQUIRE(bWasRead == true); REQUIRE(vFileBuffer.empty() == false); @@ -102,13 +116,13 @@ TEST_CASE("TFO Pkg file partially decrypting an entry", "[pkgfile]") pPkgOptions->SetTfoPkg(true); auto pPkgFile = uc2::PkgFile::Create( - tfo::PkgFilename, vFileBuffer, tfo::PackageEntryKey, + pPkgFilename, vFileBuffer, tfo::PackageEntryKey, tfo::PackageFileKey, pPkgOptions.get()); pPkgFile->DecryptHeader(); pPkgFile->Parse(); - REQUIRE(pPkgFile->GetEntries().size() == tfo::PackageFileCount); + REQUIRE(pPkgFile->GetEntries().size() == pPackageFileCount); constexpr const std::uint64_t iTargetFileLen = 23; constexpr const std::uint64_t iExpectedFileLen = 32; @@ -124,6 +138,49 @@ TEST_CASE("TFO Pkg file partially decrypting an entry", "[pkgfile]") throw e; } } + SECTION("Can decrypt an 8 byte entry") + { + auto pPkgFilename = tfo::Packages[1].first; + auto pPackageFileCount = tfo::Packages[1].second.size(); + + auto [bWasRead, vFileBuffer] = ReadFileToBuffer(pPkgFilename); + + REQUIRE(bWasRead == true); + REQUIRE(vFileBuffer.empty() == false); + + try + { + auto pPkgOptions = uc2::PkgFileOptions::Create(); + pPkgOptions->SetTfoPkg(true); + + auto pPkgFile = uc2::PkgFile::Create( + pPkgFilename, vFileBuffer, tfo::PackageEntryKey, + tfo::PackageFileKey, pPkgOptions.get()); + + pPkgFile->DecryptHeader(); + pPkgFile->Parse(); + + REQUIRE(pPkgFile->GetEntries().size() == pPackageFileCount); + + constexpr const std::uint64_t iEncryptedFileLen = 16; + constexpr const std::uint64_t iTargetFileLen = 8; + + auto&& entry = pPkgFile->GetEntries().at(0); + REQUIRE(entry->IsEncrypted()); + REQUIRE(entry->GetEncryptedSize() == iEncryptedFileLen); + REQUIRE(entry->GetDecryptedSize() == iTargetFileLen); + REQUIRE(entry->GetFilePath() == "/r1/datarevision.txt"); + auto [fileData, fileDataLen] = entry->DecryptFile(entry->GetDecryptedSize()); + + REQUIRE(fileDataLen == iTargetFileLen); + REQUIRE(strcmp(reinterpret_cast(fileData), "17973 \r\n") == 0); + } + catch (const std::exception& e) + { + std::cerr << e.what() << '\n'; + throw e; + } + } } TEST_CASE("TFO Pkg file can be decrypted and parsed using C bindings", @@ -131,7 +188,11 @@ TEST_CASE("TFO Pkg file can be decrypted and parsed using C bindings", { SECTION("Can parse entries") { - auto [bWasRead, vFileBuffer] = ReadFileToBuffer(tfo::PkgFilename); + auto pPkgFilename = tfo::Packages[0].first; + auto pPackageFileCount = tfo::Packages[0].second.size(); + auto pPackageFileHashes = tfo::Packages[0].second; + + auto [bWasRead, vFileBuffer] = ReadFileToBuffer(pPkgFilename); REQUIRE(bWasRead == true); REQUIRE(vFileBuffer.empty() == false); @@ -142,7 +203,7 @@ TEST_CASE("TFO Pkg file can be decrypted and parsed using C bindings", uncso2_PkgFileOptions_SetTfoPkg(pOptions, true); PkgFile_t pPkg = uncso2_PkgFile_Create( - tfo::PkgFilename.data(), vFileBuffer.data(), vFileBuffer.size(), + pPkgFilename.data(), vFileBuffer.data(), vFileBuffer.size(), tfo::PackageEntryKey.data(), tfo::PackageFileKey.data(), pOptions); REQUIRE(pPkg != nullptr); @@ -157,7 +218,7 @@ TEST_CASE("TFO Pkg file can be decrypted and parsed using C bindings", std::uint64_t iEntriesNum = uncso2_PkgFile_GetEntriesNum(pPkg); PkgEntry_t* pEntries = uncso2_PkgFile_GetEntries(pPkg); - REQUIRE(iEntriesNum == tfo::PackageFileCount); + REQUIRE(iEntriesNum == pPackageFileCount); for (std::size_t y = 0; y < iEntriesNum; y++) { @@ -168,7 +229,7 @@ TEST_CASE("TFO Pkg file can be decrypted and parsed using C bindings", REQUIRE(bValidEntry == true); REQUIRE(GetDataHash(reinterpret_cast(pOutBuffer), - iOutBufferSize) == tfo::PackageFileHashes[y]); + iOutBufferSize) == pPackageFileHashes[y]); } uncso2_PkgFile_Free(pPkg); diff --git a/tests/tfo/nexon/test_pkgindex.cpp b/tests/tfo/nexon/test_pkgindex.cpp index 1a29ce8..3fe86db 100644 --- a/tests/tfo/nexon/test_pkgindex.cpp +++ b/tests/tfo/nexon/test_pkgindex.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/version.txt b/version.txt index 314c3d7..867e524 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.1.5 \ No newline at end of file +1.2.0 \ No newline at end of file