Browse Source

Renamed DatIO->getHeaderHash to GetHeaderHash and implemented additional storage for dat file header hash

Ivan Arkhipov 5 years ago
parent
commit
b196d5db9f
3 changed files with 39 additions and 23 deletions
  1. 1 1
      include/DatSubsystems/DatIO.h
  2. 1 1
      src/DatSubsystems/DatIO.cpp
  3. 37 21
      src/DatSubsystems/DatLocaleManager.cpp

+ 1 - 1
include/DatSubsystems/DatIO.h

@@ -50,7 +50,7 @@ namespace LOTRO_DAT {
 
         DatOperationResult<> DeInit();
 
-        unsigned int getHeaderHash();
+        unsigned int GetHeaderHash();
     private:
 
         void ClearData();

+ 1 - 1
src/DatSubsystems/DatIO.cpp

@@ -385,7 +385,7 @@ namespace LOTRO_DAT {
         fprintf(file, "DatLibrary: EOF buffer size constant = %d\n", MAX_EOF_BUFFER);
     }
 
-    unsigned int DatIO::getHeaderHash() {
+    unsigned int DatIO::GetHeaderHash() {
         std::string values =
                 std::to_string(constant1) +
                 std::to_string(constant2) +

+ 37 - 21
src/DatSubsystems/DatLocaleManager.cpp

@@ -3,6 +3,8 @@
 #include <DatFile.h>
 #include <SubFile.h>
 
+#define DAT_LOCALE_DICT_VERSION 102
+
 namespace LOTRO_DAT {
     DatLocaleManager::DatLocaleManager(DatFile *datFilePtr) : dat(datFilePtr), current_locale_(ORIGINAL) {
     }
@@ -22,6 +24,7 @@ namespace LOTRO_DAT {
      * 4                                bytes for dict size (in bytes)
      * 4                                bytes for locale version
      * 4                                bytes for .dat file size (with patches)
+     * 4                                bytes for header hash
      * 15                               bytes for "Hi from Gi1dor"
      * 4                                bytes for LOCALE mark ("PATC" or "ORIG")
      * 4                                bytes for orig_dict.size()
@@ -62,13 +65,25 @@ namespace LOTRO_DAT {
             }
         }
 
-        BinaryData locale_info(12);
-        dat->GetIO().ReadData(locale_info, 12, locale_offset);
+        BinaryData locale_info(16);
+        dat->GetIO().ReadData(locale_info, 16, locale_offset);
 
         long long dict_size = locale_info.ToNumber<4>(0);
         long long dict_version = locale_info.ToNumber<4>(4);
+        long long patched_file_end = locale_info.ToNumber<4>(8);
+        long long dat_file_header_hash = locale_info.ToNumber<4>(12);
 
-        if (dict_version != 101) {
+        if (dict_version != DAT_LOCALE_DICT_VERSION) {
+            dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
+            if (CheckLocaleCorrect())
+                return DatOperationResult<>(SUCCESS);
+            else
+                return DatOperationResult<>(ERROR,
+                                            "Version of locales' dictionary is incorrect, through patched mark is standing. Dat file may be corrupted");
+        }
+
+        if (dat_file_header_hash != dat->GetIO().GetHeaderHash()) {
+            LOG(INFO) << "Header hash, written after last patch apply doesn't match current hash. Seems like dat-file was modified somewhere else, so removing all patch data";
             dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
             if (CheckLocaleCorrect())
                 return DatOperationResult<>(SUCCESS);
@@ -78,7 +93,7 @@ namespace LOTRO_DAT {
         }
 
         BinaryData dicts_data = BinaryData((unsigned) dict_size);
-        dat->GetIO().ReadData(dicts_data, dict_size - 12, locale_offset + 12);
+        dat->GetIO().ReadData(dicts_data, dict_size - 16, locale_offset + 16);
 
         if (dicts_data.size() < 15) {
             dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
@@ -135,9 +150,9 @@ namespace LOTRO_DAT {
         LOG(INFO) << "Finished initialising locales";
 
         if (CheckLocaleCorrect()) {
-            dat->GetFileSystem().patched_file_end = locale_info.ToNumber<4>(8);
+            dat->GetFileSystem().patched_file_end = patched_file_end;
             LOG(INFO) << "Locales initialisation success. Dictionary size is " << dict_size << ". Version is "
-                      << dict_version << ". Localed .dat size = " << dat->GetFileSystem().patched_file_end;
+                      << dict_version << ". Localed .dat size = " << patched_file_end;
             return DatOperationResult<>(SUCCESS);
         } else {
             orig_dict_.clear();
@@ -309,8 +324,8 @@ namespace LOTRO_DAT {
         fprintf(file, "Locale status = %lld\n", locale_status);
 
         if (locale_offset != 0) {
-            BinaryData locale_info(12);
-            dat->GetIO().ReadData(locale_info, 12, locale_offset);
+            BinaryData locale_info(16);
+            dat->GetIO().ReadData(locale_info, 16, locale_offset);
 
             long long dict_size = locale_info.ToNumber<4>(0);
             long long dict_version = locale_info.ToNumber<4>(4);
@@ -346,7 +361,7 @@ namespace LOTRO_DAT {
             return locale_status == 0;
 
         BinaryData dicts_data = BinaryData(4);
-        auto operation = dat->GetIO().ReadData(dicts_data, 4, locale_offset + 12 + 15);
+        auto operation = dat->GetIO().ReadData(dicts_data, 4, locale_offset + 16 + 15);
         if (operation.result == ERROR)
             return locale_status == 0;
 
@@ -360,7 +375,7 @@ namespace LOTRO_DAT {
             return false;
         }
 
-        if (locale_status != 0 && locale_status != dat->GetIO().getHeaderHash()){
+        if (locale_status != 0 && locale_status != dat->GetIO().GetHeaderHash()){
             LOG(ERROR) << "CHCKLOCALECORRECT: Locale hash doesn't match!";
             return false;
         }
@@ -417,6 +432,7 @@ namespace LOTRO_DAT {
      * 4                                bytes for dict size (in bytes)
      * 4                                bytes for locale version
      * 4                                bytes for .dat file size (with patches)
+     * 4                                bytes for dat file header hash
      * 15                               bytes for "Hi from Gi1dor"
      * 4                                bytes for LOCALE
      * 4                                bytes for orig_dict.size()
@@ -444,13 +460,13 @@ namespace LOTRO_DAT {
             return DatOperationResult<>(SUCCESS);
         }
 
-        BinaryData binary_data = BinaryData(4 + 4 + 4 + 14 + 15 + 4
+        BinaryData binary_data = BinaryData(4 + 4 + 4 + 4 + 14 + 15 + 4
                                             + 4 + (32 + 4) * orig_dict_.size()
                                             + 4 + (32 + 4) * patch_dict_.size()
                                             + 4 + 4 * inactive_categories.size());
 
-        // First 12 bytes will be filled just before writing data to file
-        size_t current_size = 12;
+        // First 16 bytes will be filled just before writing data to file
+        size_t current_size = 16;
 
         binary_data.Append(BinaryData("Hi from Gi1dor!", 15), current_size);
         current_size += 15;
@@ -493,14 +509,14 @@ namespace LOTRO_DAT {
         long long dict_size = dicts_data.ToNumber<4>(0);
 
         if (binary_data.size() > dict_size || dict_offset == 0) {
-            long long new_dict_offset = dat->GetFileSystem().patched_file_end + 12;
+            long long new_dict_offset = dat->GetFileSystem().patched_file_end + 16;
 
-            // Updating first 12 bytes
+            // Updating first 16 bytes
             binary_data.Append(BinaryData::FromNumber<4>(std::max(binary_data.size() + 4, 20u * 1024u * 1024u)), 0);
-            binary_data.Append(BinaryData::FromNumber<4>(101), 4);
+            binary_data.Append(BinaryData::FromNumber<4>(DAT_LOCALE_DICT_VERSION), 4);
             binary_data.Append(
                     BinaryData::FromNumber<4>(dat->GetFileSystem().patched_file_end + binary_data.size() + 20 * 1024 * 1024), 8);
-
+            binary_data.Append(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 12);
             auto operation = dat->GetIO().WriteData(binary_data, binary_data.size(), new_dict_offset);
             if (operation.result != SUCCESS) {
                 return DatOperationResult<>(ERROR, "LOCALEDEINIT: Cannot write locales");
@@ -509,7 +525,7 @@ namespace LOTRO_DAT {
             dat->GetIO().WriteData(BinaryData::FromNumber<4>(new_dict_offset), 4, 300);
 
             if (current_locale_ == PATCHED) {
-                dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().getHeaderHash()), 4, 296);
+                dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 4, 296);
             } else {
                 dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 296);
             }
@@ -522,11 +538,12 @@ namespace LOTRO_DAT {
             dat->GetFileSystem().patched_file_end += nulls.size();
         } else {
             binary_data.Append(BinaryData::FromNumber<4>(std::max(binary_data.size() + 4, 20u * 1024u * 1024u)), 0);
-            binary_data.Append(BinaryData::FromNumber<4>(101), 4);
+            binary_data.Append(BinaryData::FromNumber<4>(DAT_LOCALE_DICT_VERSION), 4);
             binary_data.Append(BinaryData::FromNumber<4>(dat->GetFileSystem().patched_file_end), 8);
+            binary_data.Append(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 12);
 
             if (current_locale_ == PATCHED) {
-                dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().getHeaderHash()), 4, 296);
+                dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 4, 296);
             } else {
                 dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 296);
             }
@@ -538,7 +555,6 @@ namespace LOTRO_DAT {
             }
         }
 
-
         LOG(INFO) << "Locales committed successfully";
         return DatOperationResult<>(SUCCESS);
     }