From ad8033f54c25e6ac1ab1a1e505cce326da870f40 Mon Sep 17 00:00:00 2001
From: Bertram <yohanndotferreiraatorange.fr>
Date: Sun, 25 Apr 2010 21:59:29 +0200
Subject: Added a Byte Order Mask (BOM) filter to the ResourceManager.

Reviewed by: Jaxad0127
---
 src/common/permissionmanager.cpp    |  3 ++-
 src/game-server/itemmanager.cpp     |  3 ++-
 src/game-server/mapmanager.cpp      |  3 ++-
 src/game-server/mapreader.cpp       |  3 ++-
 src/game-server/monstermanager.cpp  |  3 ++-
 src/game-server/resourcemanager.cpp | 29 +++++++++++++++++++++++++++--
 src/game-server/resourcemanager.hpp |  3 ++-
 src/game-server/skillmanager.cpp    |  3 ++-
 src/game-server/statusmanager.cpp   |  3 ++-
 src/scripting/script.cpp            |  3 ++-
 10 files changed, 45 insertions(+), 11 deletions(-)

(limited to 'src')

diff --git a/src/common/permissionmanager.cpp b/src/common/permissionmanager.cpp
index 5ff73762..ecfd4643 100644
--- a/src/common/permissionmanager.cpp
+++ b/src/common/permissionmanager.cpp
@@ -54,7 +54,8 @@ void PermissionManager::initialize(const std::string & file)
 void PermissionManager::reload()
 {
     int size;
-    char *data = ResourceManager::loadFile(permissionFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(permissionFile, size, true);
 
     if (!data) {
         LOG_ERROR("Permission Manager: Could not find "
diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp
index f70eada0..5c946a47 100644
--- a/src/game-server/itemmanager.cpp
+++ b/src/game-server/itemmanager.cpp
@@ -47,7 +47,8 @@ void ItemManager::initialize(const std::string &file)
 void ItemManager::reload()
 {
     int size;
-    char *data = ResourceManager::loadFile(itemReferenceFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(itemReferenceFile, size, true);
 
     if (!data) {
         LOG_ERROR("Item Manager: Could not find " << itemReferenceFile << "!");
diff --git a/src/game-server/mapmanager.cpp b/src/game-server/mapmanager.cpp
index d1d8864a..b27348b2 100644
--- a/src/game-server/mapmanager.cpp
+++ b/src/game-server/mapmanager.cpp
@@ -45,7 +45,8 @@ unsigned int MapManager::initialize(const std::string &mapReferenceFile)
     unsigned int loadedMaps = 0;
 
     int size;
-    char *data = ResourceManager::loadFile(mapReferenceFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(mapReferenceFile, size, true);
 
     if (!data) {
         LOG_ERROR("Map Manager: Could not find " << mapReferenceFile << "!");
diff --git a/src/game-server/mapreader.cpp b/src/game-server/mapreader.cpp
index cb91a6c0..30e73bfc 100644
--- a/src/game-server/mapreader.cpp
+++ b/src/game-server/mapreader.cpp
@@ -43,7 +43,8 @@ bool MapReader::readMap(const std::string &filename, MapComposite
 *composite)
 {
     int fileSize;
-    char *buffer = ResourceManager::loadFile(filename, fileSize);
+    // Note: The file is checked for UTF-8 BOM.
+    char *buffer = ResourceManager::loadFile(filename, fileSize, true);
 
     if (buffer == NULL)
     {
diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp
index bdd30503..e3beda72 100644
--- a/src/game-server/monstermanager.cpp
+++ b/src/game-server/monstermanager.cpp
@@ -63,7 +63,8 @@ void MonsterManager::initialize(const std::string &file)
 void MonsterManager::reload()
 {
     int size;
-    char *data = ResourceManager::loadFile(monsterReferenceFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(monsterReferenceFile, size, true);
 
     if (!data) {
         LOG_ERROR("Monster Manager: Could not find "
diff --git a/src/game-server/resourcemanager.cpp b/src/game-server/resourcemanager.cpp
index 328680e1..06958e7e 100644
--- a/src/game-server/resourcemanager.cpp
+++ b/src/game-server/resourcemanager.cpp
@@ -115,7 +115,8 @@ bool ResourceManager::exists(const std::string &path)
     return PHYSFS_exists(path.c_str());
 }
 
-char *ResourceManager::loadFile(const std::string &fileName, int &fileSize)
+char *ResourceManager::loadFile(const std::string &fileName, int &fileSize,
+                                             bool removeBOM)
 {
     // Attempt to open the specified file using PhysicsFS
     PHYSFS_file* file = PHYSFS_openRead(fileName.c_str());
@@ -131,6 +132,30 @@ char *ResourceManager::loadFile(const std::string &fileName, int &fileSize)
     // Get the size of the file
     fileSize = PHYSFS_fileLength(file);
 
+    if (removeBOM)
+    {
+        // Inspired by BOMstrip from:
+        // Peter Pentchev, 2008, public domain.
+        const std::string utf8Bom = "\xef\xbb\xbf";
+        char bomBuffer[utf8Bom.length()];
+        PHYSFS_read(file, bomBuffer, 1, utf8Bom.length());
+
+        std::istringstream iss(std::string(bomBuffer, utf8Bom.length()));
+        std::string line;
+
+        // if we find a BOM, then we remove it from the buffer
+        if (std::getline(iss, line) && !line.substr(0, 3).compare(utf8Bom))
+        {
+            LOG_INFO("Found a Byte Order Mask (BOM) in '" << fileName);
+            fileSize = fileSize - utf8Bom.length();
+        }
+        else
+        {
+            // No BOM, we get back to the file start.
+            PHYSFS_seek(file, 0);
+        }
+    }
+
     // Allocate memory and load the file
     char *buffer = (char *)malloc(fileSize + 1);
     if (PHYSFS_read(file, buffer, 1, fileSize) != fileSize)
@@ -144,7 +169,7 @@ char *ResourceManager::loadFile(const std::string &fileName, int &fileSize)
     // Close the file and let the user deallocate the memory
     PHYSFS_close(file);
 
-    // Add a trailing nul character, so that the file can be used as a string
+    // Add a trailing null character, so that the file can be used as a string
     buffer[fileSize] = 0;
     return buffer;
 }
diff --git a/src/game-server/resourcemanager.hpp b/src/game-server/resourcemanager.hpp
index 5ae421c4..74c41891 100644
--- a/src/game-server/resourcemanager.hpp
+++ b/src/game-server/resourcemanager.hpp
@@ -46,7 +46,8 @@ namespace ResourceManager
      *         or <code>NULL</code> on failure.
      * @note The array contains an extra \0 character at position fileSize.
      */
-    char *loadFile(const std::string &fileName, int &fileSize);
+    char *loadFile(const std::string &fileName, int &fileSize,
+                   bool removeBOM = false);
 }
 
 #endif
diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp
index 8c931e69..c4a18e50 100644
--- a/src/game-server/skillmanager.cpp
+++ b/src/game-server/skillmanager.cpp
@@ -45,7 +45,8 @@ void SkillManager::reload()
     */
 
     int size;
-    char *data = ResourceManager::loadFile(skillReferenceFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(skillReferenceFile, size, true);
 
     if (!data) {
         LOG_ERROR("Item Manager: Could not find " << skillReferenceFile << "!");
diff --git a/src/game-server/statusmanager.cpp b/src/game-server/statusmanager.cpp
index 0c05d01f..3472ae79 100644
--- a/src/game-server/statusmanager.cpp
+++ b/src/game-server/statusmanager.cpp
@@ -44,7 +44,8 @@ void StatusManager::initialize(const std::string &file)
 void StatusManager::reload()
 {
     int size;
-    char *data = ResourceManager::loadFile(statusReferenceFile, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *data = ResourceManager::loadFile(statusReferenceFile, size, true);
 
     if (!data) {
         LOG_ERROR("Status Manager: Could not find " << statusReferenceFile << "!");
diff --git a/src/scripting/script.cpp b/src/scripting/script.cpp
index 06f99dfc..39a04049 100644
--- a/src/scripting/script.cpp
+++ b/src/scripting/script.cpp
@@ -73,7 +73,8 @@ void Script::update()
 bool Script::loadFile(const std::string &name)
 {
     int size;
-    char *buffer = ResourceManager::loadFile(name, size);
+    // Note: The file is checked for UTF-8 BOM.
+    char *buffer = ResourceManager::loadFile(name, size, true);
     if (buffer)
     {
         mScriptFile = name;
-- 
cgit v1.2.3-70-g09d2