about summary refs log tree commit diff
path: root/src/engine/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/shared')
-rw-r--r--src/engine/shared/datafile.cpp26
-rw-r--r--src/engine/shared/datafile.h2
-rw-r--r--src/engine/shared/mapchecker.cpp106
-rw-r--r--src/engine/shared/mapchecker.h38
4 files changed, 172 insertions, 0 deletions
diff --git a/src/engine/shared/datafile.cpp b/src/engine/shared/datafile.cpp
index 74583ab8..74936ea0 100644
--- a/src/engine/shared/datafile.cpp
+++ b/src/engine/shared/datafile.cpp
@@ -222,6 +222,32 @@ bool CDataFileReader::Open(class IStorage *pStorage, const char *pFilename, int
 	return true;
 }
 
+bool CDataFileReader::GetCrcSize(class IStorage *pStorage, const char *pFilename, int StorageType, unsigned *pCrc, unsigned *pSize)
+{
+	IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType);
+	if(!File)
+		return false;
+	
+	// get crc and size
+	unsigned Crc = 0;
+	unsigned Size = 0;
+	unsigned char aBuffer[64*1024];
+	while(1)
+	{
+		unsigned Bytes = io_read(File, aBuffer, sizeof(aBuffer));
+		if(Bytes <= 0)
+			break;
+		Crc = crc32(Crc, aBuffer, Bytes); // ignore_convention
+		Size += Bytes;
+	}
+	
+	io_close(File);
+
+	*pCrc = Crc;
+	*pSize = Size;
+	return true;
+}
+
 int CDataFileReader::NumData()
 {
 	if(!m_pDataFile) { return 0; }
diff --git a/src/engine/shared/datafile.h b/src/engine/shared/datafile.h
index ce7b11aa..15bed033 100644
--- a/src/engine/shared/datafile.h
+++ b/src/engine/shared/datafile.h
@@ -16,6 +16,8 @@ public:
 	
 	bool Open(class IStorage *pStorage, const char *pFilename, int StorageType);
 	bool Close();
+
+	static bool GetCrcSize(class IStorage *pStorage, const char *pFilename, int StorageType, unsigned *pCrc, unsigned *pSize);
 	
 	void *GetData(int Index);
 	void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved
diff --git a/src/engine/shared/mapchecker.cpp b/src/engine/shared/mapchecker.cpp
new file mode 100644
index 00000000..dec4271d
--- /dev/null
+++ b/src/engine/shared/mapchecker.cpp
@@ -0,0 +1,106 @@
+/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
+/* If you are missing that file, acquire a complete release at teeworlds.com.                */
+#include <base/math.h>
+#include <base/system.h>
+
+#include <engine/storage.h>
+
+#include <versionsrv/versionsrv.h>
+
+#include "datafile.h"
+#include "memheap.h"
+#include "mapchecker.h"
+
+CMapChecker::CMapChecker()
+{
+	Init();
+	SetDefaults();
+}
+
+void CMapChecker::Init()
+{
+	m_Whitelist.Reset();
+	m_pFirst = 0;
+	m_RemoveDefaultList = false;
+}
+
+void CMapChecker::SetDefaults()
+{
+	AddMaplist(s_aMapVersionList, s_NumMapVersionItems);
+	m_RemoveDefaultList = true;
+}
+
+void CMapChecker::AddMaplist(CMapVersion *pMaplist, int Num)
+{
+	if(m_RemoveDefaultList)
+		Init();
+
+	for(int i = 0; i < Num; ++i)
+	{
+		CWhitelistEntry *pEntry = (CWhitelistEntry *)m_Whitelist.Allocate(sizeof(CWhitelistEntry));
+		pEntry->m_pNext = m_pFirst;
+		m_pFirst = pEntry;
+
+		str_copy(pEntry->m_aMapName, pMaplist[i].m_aName, sizeof(pEntry->m_aMapName));
+		pEntry->m_MapCrc = (pMaplist[i].m_aCrc[0]<<24) | (pMaplist[i].m_aCrc[1]<<16) | (pMaplist[i].m_aCrc[2]<<8) | pMaplist[i].m_aCrc[3]; 
+		pEntry->m_MapSize = (pMaplist[i].m_aSize[0]<<24) | (pMaplist[i].m_aSize[1]<<16) | (pMaplist[i].m_aSize[2]<<8) | pMaplist[i].m_aSize[3];
+	}
+}
+
+bool CMapChecker::IsMapValid(const char *pMapName, unsigned MapCrc, unsigned MapSize)
+{
+	bool StandardMap = false;
+	for(CWhitelistEntry *pCurrent = m_pFirst; pCurrent; pCurrent = pCurrent->m_pNext)
+	{
+		if(str_comp(pCurrent->m_aMapName, pMapName) == 0)
+		{
+			StandardMap = true;
+			if(pCurrent->m_MapCrc == MapCrc && pCurrent->m_MapSize == MapSize)
+				return true;
+		}
+	}
+	return StandardMap?false:true;
+}
+
+bool CMapChecker::ReadAndValidateMap(IStorage *pStorage, const char *pFilename, int StorageType)
+{
+	bool LoadedMapInfo = false;
+	bool StandardMap = false;
+	unsigned MapCrc = 0;
+	unsigned MapSize = 0;
+
+	// extract map name
+	char aMapName[MAX_MAP_LENGTH];
+	const char *pExtractedName = pFilename;
+	const char *pEnd = 0;
+	for(const char *pSrc = pFilename; *pSrc; ++pSrc)
+	{
+		if(*pSrc == '/' || *pSrc == '\\')
+			pExtractedName = pSrc+1;
+		else if(*pSrc == '.')
+			pEnd = pSrc;
+	}
+	int Length = (int)(pEnd - pExtractedName);
+	if(Length <= 0 || Length >= MAX_MAP_LENGTH)
+		return true;
+	str_copy(aMapName, pExtractedName, min((int)MAX_MAP_LENGTH, (int)(pEnd-pExtractedName+1)));
+
+	// check for valid map
+	for(CWhitelistEntry *pCurrent = m_pFirst; pCurrent; pCurrent = pCurrent->m_pNext)
+	{
+		if(str_comp(pCurrent->m_aMapName, aMapName) == 0)
+		{
+			StandardMap = true;
+			if(!LoadedMapInfo)
+			{
+				if(!CDataFileReader::GetCrcSize(pStorage, pFilename, StorageType, &MapCrc, &MapSize))
+					return true;
+				LoadedMapInfo = true;
+			}
+
+			if(pCurrent->m_MapCrc == MapCrc && pCurrent->m_MapSize == MapSize)
+				return true;
+		}
+	}
+	return StandardMap?false:true;
+}
diff --git a/src/engine/shared/mapchecker.h b/src/engine/shared/mapchecker.h
new file mode 100644
index 00000000..0d4332d9
--- /dev/null
+++ b/src/engine/shared/mapchecker.h
@@ -0,0 +1,38 @@
+/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
+/* If you are missing that file, acquire a complete release at teeworlds.com.                */
+#ifndef ENGINE_SHARED_MAPCHECKER_H
+#define ENGINE_SHARED_MAPCHECKER_H
+
+#include "memheap.h"
+
+class CMapChecker
+{
+	enum
+	{
+		MAX_MAP_LENGTH=8,
+	};
+
+	struct CWhitelistEntry
+	{
+		char m_aMapName[MAX_MAP_LENGTH];
+		unsigned m_MapCrc;
+		unsigned m_MapSize;
+		CWhitelistEntry *m_pNext;
+	};
+	
+	class CHeap m_Whitelist;
+	CWhitelistEntry *m_pFirst;
+
+	bool m_RemoveDefaultList;
+
+	void Init();
+	void SetDefaults();
+
+public:
+	CMapChecker();
+	void AddMaplist(class CMapVersion *pMaplist, int Num);
+	bool IsMapValid(const char *pMapName, unsigned MapCrc, unsigned MapSize);
+	bool ReadAndValidateMap(class IStorage *pStorage, const char *pFilename, int StorageType);
+};
+
+#endif