From c8092f9f45a3673c860a4e0bcd0d1ad7ec677ac1 Mon Sep 17 00:00:00 2001 From: Mr_Goldberg Date: Sun, 19 Sep 2021 01:07:19 -0400 Subject: [PATCH] Implement GetFileDetails. --- dll/base.cpp | 33 +++++ dll/base.h | 2 + dll/local_storage.cpp | 29 +--- dll/steam_apps.cpp | 21 ++- sha/sha1.hpp | 335 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 391 insertions(+), 29 deletions(-) create mode 100644 sha/sha1.hpp diff --git a/dll/base.cpp b/dll/base.cpp index 7a07926..e15b40a 100644 --- a/dll/base.cpp +++ b/dll/base.cpp @@ -256,6 +256,39 @@ std::string canonical_path(std::string path) return output; } +bool file_exists_(std::string full_path) +{ +#if defined(STEAM_WIN32) + struct _stat buffer; + if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) + return false; + + if ( buffer.st_mode & _S_IFDIR) + return false; +#else + struct stat buffer; + if (stat(full_path.c_str(), &buffer) != 0) + return false; + + if (S_ISDIR(buffer.st_mode)) + return false; +#endif + + return true; +} + +unsigned int file_size_(std::string full_path) +{ +#if defined(STEAM_WIN32) + struct _stat buffer = {}; + if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) return 0; +#else + struct stat buffer = {}; + if (stat (full_path.c_str(), &buffer) != 0) return 0; +#endif + return buffer.st_size; +} + static void steam_auth_ticket_callback(void *object, Common_Message *msg) { PRINT_DEBUG("steam_auth_ticket_callback\n"); diff --git a/dll/base.h b/dll/base.h index 646c851..b69de48 100644 --- a/dll/base.h +++ b/dll/base.h @@ -101,6 +101,8 @@ std::string get_full_lib_path(); std::string get_full_program_path(); std::string get_current_path(); std::string canonical_path(std::string path); +bool file_exists_(std::string full_path); +unsigned int file_size_(std::string full_path); #define DEFAULT_CB_TIMEOUT 0.002 diff --git a/dll/local_storage.cpp b/dll/local_storage.cpp index 8697600..5448e73 100644 --- a/dll/local_storage.cpp +++ b/dll/local_storage.cpp @@ -607,24 +607,7 @@ bool Local_Storage::file_exists(std::string folder, std::string file) } std::string full_path = save_directory + appid + folder + file; - -#if defined(STEAM_WIN32) - struct _stat buffer; - if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) - return false; - - if ( buffer.st_mode & _S_IFDIR) - return false; -#else - struct stat buffer; - if (stat(full_path.c_str(), &buffer) != 0) - return false; - - if (S_ISDIR(buffer.st_mode)) - return false; -#endif - - return true; + return file_exists_(full_path); } unsigned int Local_Storage::file_size(std::string folder, std::string file) @@ -635,15 +618,7 @@ unsigned int Local_Storage::file_size(std::string folder, std::string file) } std::string full_path = save_directory + appid + folder + file; - -#if defined(STEAM_WIN32) - struct _stat buffer = {}; - if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) return 0; -#else - struct stat buffer = {}; - if (stat (full_path.c_str(), &buffer) != 0) return 0; -#endif - return buffer.st_size; + return file_size_(full_path); } bool Local_Storage::file_delete(std::string folder, std::string file) diff --git a/dll/steam_apps.cpp b/dll/steam_apps.cpp index 12c80e4..2b154fd 100644 --- a/dll/steam_apps.cpp +++ b/dll/steam_apps.cpp @@ -16,6 +16,7 @@ . */ #include "steam_apps.h" +#include "../sha/sha1.hpp" Steam_Apps::Steam_Apps(Settings *settings, class SteamCallResults *callback_results) { @@ -201,6 +202,7 @@ uint32 Steam_Apps::GetInstalledDepots( DepotId_t *pvecDepots, uint32 cMaxDepots uint32 Steam_Apps::GetAppInstallDir( AppId_t appID, char *pchFolder, uint32 cchFolderBufferSize ) { PRINT_DEBUG("GetAppInstallDir %u %p %u\n", appID, pchFolder, cchFolderBufferSize); + std::lock_guard lock(global_mutex); //TODO return real path instead of dll path std::string installed_path = settings->getAppInstallPath(appID); @@ -279,8 +281,23 @@ void Steam_Apps::RequestAllProofOfPurchaseKeys() STEAM_CALL_RESULT( FileDetailsResult_t ) SteamAPICall_t Steam_Apps::GetFileDetails( const char* pszFileName ) { - PRINT_DEBUG("GetFileDetails\n"); - return 0; + PRINT_DEBUG("GetFileDetails %s\n", pszFileName); + FileDetailsResult_t data = {}; + //TODO? this function should only return found if file is actually part of the steam depots + if (file_exists_(pszFileName)) { + data.m_eResult = k_EResultOK; // + std::ifstream stream(utf8_decode(pszFileName), std::ios::binary); + SHA1 checksum; + checksum.update(stream); + checksum.final().copy((char *)data.m_FileSHA, sizeof(data.m_FileSHA)); + data.m_ulFileSize = file_size_(pszFileName); + //TODO data.m_unFlags; 0 is file //TODO: check if 64 is folder + } else { + data.m_eResult = k_EResultFileNotFound; + } + + std::lock_guard lock(global_mutex); + return callback_results->addCallResult(data.k_iCallback, &data, sizeof(data)); } // Get command line if game was launched via Steam URL, e.g. steam://run////. diff --git a/sha/sha1.hpp b/sha/sha1.hpp new file mode 100644 index 0000000..1d4944f --- /dev/null +++ b/sha/sha1.hpp @@ -0,0 +1,335 @@ +/* + sha1.hpp - source code of + + ============ + SHA-1 in C++ + ============ + + 100% Public Domain. + + Original C Code + -- Steve Reid + Small changes to fit into bglibs + -- Bruce Guenter + Translation to simpler C++ Code + -- Volker Diels-Grabsch + Safety fixes + -- Eugene Hopkinson + Header-only library + -- Zlatko Michailov +*/ + +#ifndef SHA1_HPP +#define SHA1_HPP + + +#include +#include +#include +#include +#include +#include + + +class SHA1 +{ +public: + SHA1(); + void update(const std::string &s); + void update(std::istream &is); + std::string final(); + static std::string from_file(const std::string &filename); + +private: + uint32_t digest[5]; + std::string buffer; + uint64_t transforms; +}; + + +static const size_t BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */ +static const size_t BLOCK_BYTES = BLOCK_INTS * 4; + + +inline static void reset(uint32_t digest[], std::string &buffer, uint64_t &transforms) +{ + /* SHA1 initialization constants */ + digest[0] = 0x67452301; + digest[1] = 0xefcdab89; + digest[2] = 0x98badcfe; + digest[3] = 0x10325476; + digest[4] = 0xc3d2e1f0; + + /* Reset counters */ + buffer = ""; + transforms = 0; +} + + +inline static uint32_t rol(const uint32_t value, const size_t bits) +{ + return (value << bits) | (value >> (32 - bits)); +} + + +inline static uint32_t blk(const uint32_t block[BLOCK_INTS], const size_t i) +{ + return rol(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i], 1); +} + + +/* + * (R0+R1), R2, R3, R4 are the different operations used in SHA1 + */ + +inline static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +{ + z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +{ + block[i] = blk(block, i); + z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +{ + block[i] = blk(block, i); + z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +{ + block[i] = blk(block, i); + z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5); + w = rol(w, 30); +} + + +inline static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) +{ + block[i] = blk(block, i); + z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5); + w = rol(w, 30); +} + + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ + +inline static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t &transforms) +{ + /* Copy digest[] to working vars */ + uint32_t a = digest[0]; + uint32_t b = digest[1]; + uint32_t c = digest[2]; + uint32_t d = digest[3]; + uint32_t e = digest[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(block, a, b, c, d, e, 0); + R0(block, e, a, b, c, d, 1); + R0(block, d, e, a, b, c, 2); + R0(block, c, d, e, a, b, 3); + R0(block, b, c, d, e, a, 4); + R0(block, a, b, c, d, e, 5); + R0(block, e, a, b, c, d, 6); + R0(block, d, e, a, b, c, 7); + R0(block, c, d, e, a, b, 8); + R0(block, b, c, d, e, a, 9); + R0(block, a, b, c, d, e, 10); + R0(block, e, a, b, c, d, 11); + R0(block, d, e, a, b, c, 12); + R0(block, c, d, e, a, b, 13); + R0(block, b, c, d, e, a, 14); + R0(block, a, b, c, d, e, 15); + R1(block, e, a, b, c, d, 0); + R1(block, d, e, a, b, c, 1); + R1(block, c, d, e, a, b, 2); + R1(block, b, c, d, e, a, 3); + R2(block, a, b, c, d, e, 4); + R2(block, e, a, b, c, d, 5); + R2(block, d, e, a, b, c, 6); + R2(block, c, d, e, a, b, 7); + R2(block, b, c, d, e, a, 8); + R2(block, a, b, c, d, e, 9); + R2(block, e, a, b, c, d, 10); + R2(block, d, e, a, b, c, 11); + R2(block, c, d, e, a, b, 12); + R2(block, b, c, d, e, a, 13); + R2(block, a, b, c, d, e, 14); + R2(block, e, a, b, c, d, 15); + R2(block, d, e, a, b, c, 0); + R2(block, c, d, e, a, b, 1); + R2(block, b, c, d, e, a, 2); + R2(block, a, b, c, d, e, 3); + R2(block, e, a, b, c, d, 4); + R2(block, d, e, a, b, c, 5); + R2(block, c, d, e, a, b, 6); + R2(block, b, c, d, e, a, 7); + R3(block, a, b, c, d, e, 8); + R3(block, e, a, b, c, d, 9); + R3(block, d, e, a, b, c, 10); + R3(block, c, d, e, a, b, 11); + R3(block, b, c, d, e, a, 12); + R3(block, a, b, c, d, e, 13); + R3(block, e, a, b, c, d, 14); + R3(block, d, e, a, b, c, 15); + R3(block, c, d, e, a, b, 0); + R3(block, b, c, d, e, a, 1); + R3(block, a, b, c, d, e, 2); + R3(block, e, a, b, c, d, 3); + R3(block, d, e, a, b, c, 4); + R3(block, c, d, e, a, b, 5); + R3(block, b, c, d, e, a, 6); + R3(block, a, b, c, d, e, 7); + R3(block, e, a, b, c, d, 8); + R3(block, d, e, a, b, c, 9); + R3(block, c, d, e, a, b, 10); + R3(block, b, c, d, e, a, 11); + R4(block, a, b, c, d, e, 12); + R4(block, e, a, b, c, d, 13); + R4(block, d, e, a, b, c, 14); + R4(block, c, d, e, a, b, 15); + R4(block, b, c, d, e, a, 0); + R4(block, a, b, c, d, e, 1); + R4(block, e, a, b, c, d, 2); + R4(block, d, e, a, b, c, 3); + R4(block, c, d, e, a, b, 4); + R4(block, b, c, d, e, a, 5); + R4(block, a, b, c, d, e, 6); + R4(block, e, a, b, c, d, 7); + R4(block, d, e, a, b, c, 8); + R4(block, c, d, e, a, b, 9); + R4(block, b, c, d, e, a, 10); + R4(block, a, b, c, d, e, 11); + R4(block, e, a, b, c, d, 12); + R4(block, d, e, a, b, c, 13); + R4(block, c, d, e, a, b, 14); + R4(block, b, c, d, e, a, 15); + + /* Add the working vars back into digest[] */ + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; + digest[4] += e; + + /* Count the number of transformations */ + transforms++; +} + + +inline static void buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS]) +{ + /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */ + for (size_t i = 0; i < BLOCK_INTS; i++) + { + block[i] = (buffer[4*i+3] & 0xff) + | (buffer[4*i+2] & 0xff)<<8 + | (buffer[4*i+1] & 0xff)<<16 + | (buffer[4*i+0] & 0xff)<<24; + } +} + + +inline SHA1::SHA1() +{ + reset(digest, buffer, transforms); +} + + +inline void SHA1::update(const std::string &s) +{ + std::istringstream is(s); + update(is); +} + + +inline void SHA1::update(std::istream &is) +{ + while (true) + { + char sbuf[BLOCK_BYTES]; + is.read(sbuf, BLOCK_BYTES - buffer.size()); + buffer.append(sbuf, (std::size_t)is.gcount()); + if (buffer.size() != BLOCK_BYTES) + { + return; + } + uint32_t block[BLOCK_INTS]; + buffer_to_block(buffer, block); + transform(digest, block, transforms); + buffer.clear(); + } +} + + +/* + * Add padding and return the message digest. + */ + +inline std::string SHA1::final() +{ + /* Total number of hashed bits */ + uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8; + + /* Padding */ + buffer += (char)0x80; + size_t orig_size = buffer.size(); + while (buffer.size() < BLOCK_BYTES) + { + buffer += (char)0x00; + } + + uint32_t block[BLOCK_INTS]; + buffer_to_block(buffer, block); + + if (orig_size > BLOCK_BYTES - 8) + { + transform(digest, block, transforms); + for (size_t i = 0; i < BLOCK_INTS - 2; i++) + { + block[i] = 0; + } + } + + /* Append total_bits, split this uint64_t into two uint32_t */ + block[BLOCK_INTS - 1] = (uint32_t)total_bits; + block[BLOCK_INTS - 2] = (uint32_t)(total_bits >> 32); + transform(digest, block, transforms); + + unsigned char output[20]; + for (size_t i = 0; i < sizeof(digest) / sizeof(digest[0]); i++) + { + output[i*4] = digest[i] >> 24; + output[i*4 + 1] = (digest[i] >> 16) & 0xFF; + output[i*4 + 2] = (digest[i] >> 8) & 0xFF; + output[i*4 + 3] = (digest[i]) & 0xFF; + } + + /* Reset for next run */ + reset(digest, buffer, transforms); + + return std::string((char *)output, sizeof(output)); +} + + +inline std::string SHA1::from_file(const std::string &filename) +{ + std::ifstream stream(filename.c_str(), std::ios::binary); + SHA1 checksum; + checksum.update(stream); + return checksum.final(); +} + + +#endif /* SHA1_HPP */