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 */