core/GameDataFetcher.cpp
changeset 2474 1f4345fb0f75
parent 2371 323fbf1ab608
child 2475 297d0a773483
     1.1 --- a/core/GameDataFetcher.cpp	Mon Dec 22 20:12:33 2008 -0600
     1.2 +++ b/core/GameDataFetcher.cpp	Fri Dec 26 23:26:21 2008 -0500
     1.3 @@ -42,8 +42,9 @@
     1.4  #include <netdb.h>
     1.5  #include <arpa/inet.h>
     1.6  
     1.7 -#define INVALID_SOCKET -1
     1.8 -#define closesocket close
     1.9 +#define INVALID_SOCKET		-1
    1.10 +#define closesocket 		close
    1.11 +#define WSAGetLastError()	errno
    1.12  #endif
    1.13  
    1.14  #include "sh_vector.h"
    1.15 @@ -61,6 +62,7 @@
    1.16  #include "TimerSys.h"
    1.17  #include "compat_wrappers.h"
    1.18  #include "sm_stringutil.h"
    1.19 +#include "md5.h"
    1.20  
    1.21  #define QUERY_MAX_LENGTH 1024
    1.22  
    1.23 @@ -73,9 +75,9 @@
    1.24  bool g_restartAfterUpdate = false;
    1.25  
    1.26  int g_serverPort = 6500;
    1.27 -char g_serverAddress[100] = "hayate.alliedmods.net";
    1.28 +char g_serverAddress[100] = "smupdate.alliedmods.net";
    1.29  
    1.30 -void FetcherThread::RunThread( IThreadHandle *pHandle )
    1.31 +void FetcherThread::RunThread(IThreadHandle *pHandle)
    1.32  {
    1.33  	char lock_path[PLATFORM_MAX_PATH];
    1.34  	g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp");
    1.35 @@ -127,9 +129,7 @@
    1.36  
    1.37  	if (g_disableGameDataUpdate)
    1.38  	{
    1.39 -#ifdef DEBUG
    1.40  		g_Logger.LogMessage("Skipping GameData Query due to DisableAutoUpdate being set to true");
    1.41 -#endif
    1.42  
    1.43  		fclose(logfile);
    1.44  		unlink(lock_path);
    1.45 @@ -148,13 +148,15 @@
    1.46  
    1.47  	int sent = SendData(socketDescriptor, query, len);
    1.48  
    1.49 -#ifdef DEBUG
    1.50 -	g_Logger.LogToOpenFile(logfile, "Sent Query!");
    1.51 -#endif
    1.52 +IF_DEBUG_SPEW
    1.53 +	g_Logger.LogToOpenFile(logfile, "Sent gamedata query");
    1.54 +ENDIF_DEBUG_SPEW
    1.55  
    1.56  	if (sent == 0)
    1.57  	{
    1.58 +IF_DEBUG_SPEW
    1.59  		g_Logger.LogToOpenFile(logfile, "Failed to send gamedata query data to remote host");
    1.60 +ENDIF_DEBUG_SPEW
    1.61  
    1.62  		closesocket(socketDescriptor);
    1.63  		fclose(logfile);
    1.64 @@ -170,12 +172,12 @@
    1.65  	unlink(lock_path);
    1.66  }
    1.67  
    1.68 -void FetcherThread::OnTerminate( IThreadHandle *pHandle, bool cancel )
    1.69 +void FetcherThread::OnTerminate(IThreadHandle *pHandle, bool cancel)
    1.70  {
    1.71  	g_blockGameDataLoad = false;
    1.72  }
    1.73  
    1.74 -int FetcherThread::BuildGameDataQuery( char *buffer, int maxlen )
    1.75 +int FetcherThread::BuildGameDataQuery(char *buffer, int maxlen)
    1.76  {
    1.77  	char gamedata_path[PLATFORM_MAX_PATH];
    1.78  	g_SourceMod.BuildPath(Path_SM, gamedata_path, sizeof(gamedata_path), "gamedata");
    1.79 @@ -204,41 +206,39 @@
    1.80  		{
    1.81  			const char *name = dir->GetEntryName();
    1.82  			size_t len = strlen(name);
    1.83 -			if (len >= 4
    1.84 -				&& strcmp(&name[len-4], ".txt") == 0)
    1.85 +			if (len >= 4 && strcmp(&name[len-4], ".txt") == 0)
    1.86  			{
    1.87 +				MD5 md5;
    1.88 +				SMCError err;
    1.89 +				SMCStates states;
    1.90 +				unsigned char raw[16];
    1.91  				char file[PLATFORM_MAX_PATH];
    1.92  
    1.93  				g_LibSys.PathFormat(file, sizeof(file), "%s/%s", gamedata_path, name);
    1.94  
    1.95 -				SMCStates states;
    1.96 -				if (g_TextParser.ParseFile_SMC(file, &g_MD5Builder, &states) == SMCError_Okay)
    1.97 +				g_MD5Builder.checksum = &md5;
    1.98 +				if ((err = g_TextParser.ParseFile_SMC(file, &g_MD5Builder, &states)) == SMCError_Okay)
    1.99  				{
   1.100 -					unsigned char *md5 = g_MD5Builder.GetMD5();
   1.101 -					if (md5 != NULL)
   1.102 -					{
   1.103 -						(uint8_t)buffer[10]++; //Increment the file counter
   1.104 -						Writer.WriteBytes(md5, 16);
   1.105 -
   1.106 -						g_Logger.LogToOpenFile(logfile, "%s - \"%s\"", file, g_MD5Builder.GetMD5String());
   1.107 +					md5.raw_digest(raw);
   1.108 +					(uint8_t)buffer[10]++; //Increment the file counter
   1.109 +					Writer.WriteBytes(raw, 16);
   1.110  
   1.111 -						FileData *data = new FileData();
   1.112 -						data->filename = new SourceHook::String(file);
   1.113 -						memcpy(data->checksum, g_MD5Builder.GetMD5String(), 33);
   1.114 -						filenames.push_back(data);
   1.115 -					}
   1.116 -					else
   1.117 -					{
   1.118 -#ifdef DEBUG
   1.119 -						g_Logger.LogToOpenFile(logfile, "%s no md5?", file);
   1.120 -#endif
   1.121 -					}
   1.122 +					FileData *data = new FileData();
   1.123 +					data->filename = new SourceHook::String(file);
   1.124 +					md5.hex_digest(data->checksum);
   1.125 +					filenames.push_back(data);
   1.126 +
   1.127 +IF_DEBUG_SPEW
   1.128 +					g_Logger.LogToOpenFile(logfile, "Parsed file: %s as %s", file, data->checksum);
   1.129 +ENDIF_DEBUG_SPEW
   1.130 +
   1.131  				}
   1.132  				else
   1.133  				{
   1.134 -#ifdef DEBUG
   1.135 -					g_Logger.LogToOpenFile(logfile, "%s failed!", file);
   1.136 -#endif
   1.137 +IF_DEBUG_SPEW
   1.138 +					const char *error = g_TextParser.GetSMCErrorString(err);
   1.139 +					g_Logger.LogToOpenFile(logfile, "Parsing of file %s failed: %s", file, error);
   1.140 +ENDIF_DEBUG_SPEW
   1.141  				}
   1.142  			}
   1.143  		}
   1.144 @@ -251,17 +251,16 @@
   1.145  
   1.146  int FetcherThread::ConnectSocket()
   1.147  {
   1.148 -	struct protoent *ptrp;
   1.149 -	ptrp = getprotobyname("tcp");
   1.150 -
   1.151 -#ifdef WIN32
   1.152 +#if defined PLATFORM_WINDOWS
   1.153  	WSADATA wsaData;
   1.154  	WSAStartup(0x0101, &wsaData);
   1.155  #endif
   1.156  
   1.157 -	if (ptrp == NULL) 
   1.158 +	struct protoent *ptrp;
   1.159 +	
   1.160 +	if ((ptrp = getprotobyname("tcp")) == NULL) 
   1.161  	{
   1.162 -		g_Logger.LogToOpenFile(logfile, "Failed to find TCP");
   1.163 +		g_Logger.LogToOpenFile(logfile, "Error: Failed to find TCP protocol");
   1.164  		return INVALID_SOCKET;
   1.165  	}
   1.166  
   1.167 @@ -269,12 +268,9 @@
   1.168  
   1.169  	if (socketDescriptor == INVALID_SOCKET)
   1.170  	{
   1.171 -		//bugger aye?
   1.172 -#ifdef WIN32
   1.173 -		g_Logger.LogToOpenFile(logfile, "Failed to create a new socket - Error %i", WSAGetLastError());
   1.174 -#else
   1.175 -		g_Logger.LogToOpenFile(logfile, "Failed to create a new socket - Error %i", errno);
   1.176 -#endif
   1.177 +		char error[255];
   1.178 +		g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
   1.179 +		g_Logger.LogToOpenFile(logfile, "Error: Failed to create socket: %s", error);
   1.180  		closesocket(socketDescriptor);
   1.181  		return INVALID_SOCKET;
   1.182  	}
   1.183 @@ -291,7 +287,7 @@
   1.184  	{
   1.185  		if ((local_addr.sin_addr.s_addr = inet_addr(g_serverAddress)) == INADDR_NONE)
   1.186  		{
   1.187 -			g_Logger.LogToOpenFile(logfile, "Couldn't locate address");
   1.188 +			g_Logger.LogToOpenFile(logfile, "Couldn't locate address: %s", g_serverAddress);
   1.189  			closesocket(socketDescriptor);
   1.190  			return INVALID_SOCKET;
   1.191  		}
   1.192 @@ -303,11 +299,9 @@
   1.193  
   1.194  	if (connect(socketDescriptor, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
   1.195  	{
   1.196 -#ifdef WIN32
   1.197 -		g_Logger.LogToOpenFile(logfile, "Couldn't connect - Error %i", WSAGetLastError());
   1.198 -#else
   1.199 -		g_Logger.LogToOpenFile(logfile, "Couldn't connect - Error %i", errno);
   1.200 -#endif
   1.201 +		char error[255];
   1.202 +		g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
   1.203 +		g_Logger.LogToOpenFile(logfile, "Couldn't connect to %s: %s", g_serverAddress, error);
   1.204  		closesocket(socketDescriptor);
   1.205  		return INVALID_SOCKET;
   1.206  	}
   1.207 @@ -318,35 +312,34 @@
   1.208  void FetcherThread::ProcessGameDataQuery(int socketDescriptor)
   1.209  {
   1.210  	char buffer[50];
   1.211 -#ifdef DEBUG
   1.212 +
   1.213 +IF_DEBUG_SPEW
   1.214  	g_Logger.LogToOpenFile(logfile, "Waiting for reply!");
   1.215 -#endif
   1.216 +ENDIF_DEBUG_SPEW
   1.217  
   1.218  	//Read in the header bytes
   1.219  	int returnLen = RecvData(socketDescriptor, buffer, 12);
   1.220  
   1.221 -#ifdef DEBUG
   1.222 -	g_Logger.LogToOpenFile(logfile, "Recv Completed");
   1.223 -#endif
   1.224  
   1.225  	if (returnLen == 0)
   1.226  	{
   1.227 -#ifdef DEBUG
   1.228 -		g_Logger.LogToOpenFile(logfile, ",but it failed.");
   1.229 -#endif
   1.230 -		/* Timeout or fail? */
   1.231 +		char error[255];
   1.232 +		g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
   1.233 +		g_Logger.LogToOpenFile(logfile, "Did not receive reply: %s", error);
   1.234  		return;
   1.235  	}
   1.236  
   1.237 -#ifdef DEBUG
   1.238 +IF_DEBUG_SPEW
   1.239  	g_Logger.LogToOpenFile(logfile, "Received Header!");
   1.240 -#endif
   1.241 +ENDIF_DEBUG_SPEW
   1.242  
   1.243  	bf_read Reader = bf_read("GameDataQuery", buffer, 12);
   1.244  
   1.245  	if (Reader.ReadByte() != 'A' || Reader.ReadByte() != 'G')
   1.246  	{
   1.247 +IF_DEBUG_SPEW
   1.248  		g_Logger.LogToOpenFile(logfile, "Unknown Query Response");
   1.249 +ENDIF_DEBUG_SPEW
   1.250  		return;
   1.251  	}
   1.252  
   1.253 @@ -359,17 +352,23 @@
   1.254  	build[2] = Reader.ReadShort();
   1.255  	build[3] = Reader.ReadShort();
   1.256  
   1.257 -#ifdef DEBUG
   1.258 -	g_Logger.LogToOpenFile(logfile, "Update Status: %i - Latest %i.%i.%i.%i", updateStatus, build[0], build[1], build[2], build[3]);
   1.259 -#endif
   1.260 +IF_DEBUG_SPEW
   1.261 +	g_Logger.LogToOpenFile(logfile,
   1.262 +						   "Update Status: %i - Latest %i.%i.%i.%i",
   1.263 +						   updateStatus,
   1.264 +						   build[0],
   1.265 +						   build[1],
   1.266 +						   build[2],
   1.267 +						   build[3]);
   1.268 +ENDIF_DEBUG_SPEW
   1.269  
   1.270  	HandleUpdateStatus(updateStatus, build);
   1.271  
   1.272  	int changedFiles = Reader.ReadByte();
   1.273  
   1.274 -#ifdef DEBUG
   1.275 +IF_DEBUG_SPEW
   1.276  	g_Logger.LogToOpenFile(logfile, "Files to download: %i", changedFiles);
   1.277 -#endif
   1.278 +ENDIF_DEBUG_SPEW
   1.279  
   1.280  	for (int i=0; i<changedFiles; i++)
   1.281  	{
   1.282 @@ -387,9 +386,9 @@
   1.283  		int index = Reader.ReadByte();
   1.284  		int tempLen = Reader.ReadUBitLong(32);
   1.285  
   1.286 -#ifdef DEBUG
   1.287 +IF_DEBUG_SPEW
   1.288  		g_Logger.LogToOpenFile(logfile, "File index %i and length %i", index, tempLen);
   1.289 -#endif
   1.290 +ENDIF_DEBUG_SPEW
   1.291  
   1.292  		void *memPtr;
   1.293  		memtable->CreateMem(tempLen+1, &memPtr);
   1.294 @@ -397,9 +396,9 @@
   1.295  		//Read the contents of our file into the memtable
   1.296  		returnLen = RecvData(socketDescriptor, (char *)memPtr, tempLen);
   1.297  
   1.298 -#ifdef DEBUG
   1.299 -		g_Logger.LogToOpenFile(logfile, "Recieved %i bytes", returnLen);
   1.300 -#endif
   1.301 +IF_DEBUG_SPEW
   1.302 +		g_Logger.LogToOpenFile(logfile, "Received %i bytes", returnLen);
   1.303 +ENDIF_DEBUG_SPEW
   1.304  
   1.305  		if (returnLen == 0)
   1.306  		{
   1.307 @@ -410,7 +409,7 @@
   1.308  		((unsigned char *)memPtr)[tempLen] = '\0';
   1.309  
   1.310  		FileData *data = filenames.at(index);
   1.311 -		const char* filename;
   1.312 +		const char *filename;
   1.313  		if (data != NULL)
   1.314  		{
   1.315  			filename = data->filename->c_str();
   1.316 @@ -419,12 +418,12 @@
   1.317  
   1.318  			if (fp)
   1.319  			{
   1.320 -				fprintf(fp, (const char *)memPtr);
   1.321 +				fprintf(fp, "%s", (const char *)memPtr);
   1.322  				fclose(fp);
   1.323  			}
   1.324  			else
   1.325  			{
   1.326 -				g_Logger.LogToOpenFile(logfile, "Failed to open file \"%s\"", filename);
   1.327 +				g_Logger.LogToOpenFile(logfile, "Failed to open file \"%s\" for writing", filename);
   1.328  			}
   1.329  		}
   1.330  		else
   1.331 @@ -434,14 +433,13 @@
   1.332  
   1.333  		memtable->Reset();
   1.334  
   1.335 -#ifdef DEBUG
   1.336 -		g_Logger.LogToOpenFile(logfile, "Updated File %s", filename);
   1.337 -#endif
   1.338 +
   1.339 +		g_Logger.LogToOpenFile(logfile, "Updated file: %s", filename);
   1.340  	}
   1.341  
   1.342 -#ifdef DEBUG
   1.343 +IF_DEBUG_SPEW
   1.344  	g_Logger.LogToOpenFile(logfile, "File Downloads Completed!");
   1.345 -#endif
   1.346 +ENDIF_DEBUG_SPEW
   1.347  
   1.348  	bool needsRestart = false;
   1.349  
   1.350 @@ -456,8 +454,9 @@
   1.351  
   1.352  	if (returnLen == 0)
   1.353  	{
   1.354 -		/* Timeout or fail? */
   1.355 -		g_Logger.LogToOpenFile(logfile, "Failed to receive unknown count");
   1.356 +		char error[255];
   1.357 +		g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
   1.358 +		g_Logger.LogToOpenFile(logfile, "Did not receive count reply: %s", error);
   1.359  		return;
   1.360  	}
   1.361  
   1.362 @@ -465,28 +464,27 @@
   1.363  
   1.364  	changedFiles = Reader.ReadByte();
   1.365  
   1.366 -	if (changedFiles == 0)
   1.367 +	if (changedFiles < 1)
   1.368  	{
   1.369 -#ifdef DEBUG
   1.370 +IF_DEBUG_SPEW
   1.371  		g_Logger.LogToOpenFile(logfile, "No unknown files. We're all done");
   1.372 -#endif
   1.373 +ENDIF_DEBUG_SPEW
   1.374  		return;
   1.375  	}
   1.376  
   1.377  	char *changedFileIndexes = new char[changedFiles];
   1.378  
   1.379 -#ifdef DEBUG
   1.380 +IF_DEBUG_SPEW
   1.381  	g_Logger.LogToOpenFile(logfile, "%i Files were unknown", changedFiles);
   1.382 -#endif
   1.383 +ENDIF_DEBUG_SPEW
   1.384  
   1.385  	returnLen = RecvData(socketDescriptor, changedFileIndexes, changedFiles);
   1.386  
   1.387  	if (returnLen == 0)
   1.388  	{
   1.389 -		/* Timeout or fail? */
   1.390 -#ifdef DEBUG
   1.391 -		g_Logger.LogToOpenFile(logfile, "Failed to receive unknown list");
   1.392 -#endif
   1.393 +		char error[255];
   1.394 +		g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
   1.395 +		g_Logger.LogToOpenFile(logfile, "Did not receive list reply: %s", error);
   1.396  		return;
   1.397  	}
   1.398  
   1.399 @@ -509,21 +507,22 @@
   1.400  		}
   1.401  
   1.402  		g_LibSys.GetFileFromPath(fileName, sizeof(fileName), pathname);
   1.403 -#ifdef DEBUG
   1.404 +IF_DEBUG_SPEW
   1.405  		g_Logger.LogToOpenFile(logfile, "Unknown File %i : %s", index, fileName);
   1.406 -#endif
   1.407 +ENDIF_DEBUG_SPEW
   1.408  	}
   1.409  
   1.410  	delete [] changedFileIndexes;
   1.411  
   1.412  	if (needsRestart && g_restartAfterUpdate)
   1.413  	{
   1.414 +		/* :TODO: none of this is thread safe. */
   1.415  		g_Logger.LogMessage("Automatically restarting server after a successful gamedata update!");
   1.416  		engine->ServerCommand("quit\n");
   1.417  	}
   1.418  }
   1.419  
   1.420 -int FetcherThread::RecvData( int socketDescriptor, char *buffer, int len )
   1.421 +int FetcherThread::RecvData(int socketDescriptor, char *buffer, int len)
   1.422  {
   1.423  	fd_set fds;
   1.424  	struct timeval tv;
   1.425 @@ -562,7 +561,7 @@
   1.426  	return bytesReceivedTotal;	
   1.427  }
   1.428  
   1.429 -int FetcherThread::SendData( int socketDescriptor, char *buffer, int len )
   1.430 +int FetcherThread::SendData(int socketDescriptor, char *buffer, int len)
   1.431  {
   1.432  	fd_set fds;
   1.433  	struct timeval tv;
   1.434 @@ -597,7 +596,7 @@
   1.435  	return sentBytesTotal;
   1.436  }
   1.437  
   1.438 -void FetcherThread::HandleUpdateStatus( UpdateStatus status, short version[4] )
   1.439 +void FetcherThread::HandleUpdateStatus(UpdateStatus status, short version[4])
   1.440  {
   1.441  	switch (status)
   1.442  	{
   1.443 @@ -609,14 +608,12 @@
   1.444  
   1.445  		case Update_NewBuild:
   1.446  		{
   1.447 -			g_Logger.LogMessage("SourceMod Update: A new Mercurial build is available from sourcemod.net");
   1.448 -			g_Logger.LogMessage("Current Version: %i.%i.%i.%i Available: %i.%i.%i.%i", version[0], version[1], version[2], version[3], version[0], version[1], version[2], version[3]);
   1.449  			break;
   1.450  		}
   1.451  
   1.452  		case Update_MinorAvailable:
   1.453  		{
   1.454 -			g_Logger.LogMessage("SourceMod Update: An incremental minor release of SourceMod is now available from sourcemod.net");
   1.455 +			g_Logger.LogMessage("SourceMod Update: A new release of SourceMod is now available from sourcemod.net");
   1.456  			g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]);
   1.457  			break;
   1.458  		}
   1.459 @@ -630,8 +627,8 @@
   1.460  
   1.461  		case Update_CriticalAvailable:
   1.462  		{
   1.463 -			g_Logger.LogError("SourceMod Update: A new critical release of SourceMod is now available from sourcemod.net. It is strongly recommended that you update");
   1.464 -			g_Logger.LogMessage("Current Version: %i.%i.%i.%i Available: %i.%i.%i.%i", version[0], version[1], version[2], version[3], version[0], version[1], version[2], version[3]);
   1.465 +			g_Logger.LogError("SourceMod Update: A critical SourceMod release is available from sourcemod.net. It is strongly recommended that you update!");
   1.466 +			g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]);
   1.467  			break;
   1.468  		}
   1.469  	}
   1.470 @@ -665,14 +662,14 @@
   1.471  		char *error, 
   1.472  		size_t maxlength)
   1.473  	{
   1.474 -		if (strcmp(key, "DisableAutoUpdate") == 0)
   1.475 +		if (strcasecmp(key, "DisableAutoUpdate") == 0)
   1.476  		{
   1.477 -			if (strcmp(value, "yes") == 0)
   1.478 +			if (strcasecmp(value, "yes") == 0)
   1.479  			{
   1.480  				g_disableGameDataUpdate = true;
   1.481  				return ConfigResult_Accept;
   1.482  			}
   1.483 -			else if (strcmp(value, "no") == 0)
   1.484 +			else if (strcasecmp(value, "no") == 0)
   1.485  			{
   1.486  				g_disableGameDataUpdate = false;
   1.487  				return ConfigResult_Accept;
   1.488 @@ -681,14 +678,14 @@
   1.489  			return ConfigResult_Reject;
   1.490  		}
   1.491  
   1.492 -		if (strcmp(key, "ForceRestartAfterUpdate") == 0)
   1.493 +		if (strcasecmp(key, "ForceRestartAfterUpdate") == 0)
   1.494  		{
   1.495 -			if (strcmp(value, "yes") == 0)
   1.496 +			if (strcasecmp(value, "yes") == 0)
   1.497  			{
   1.498  				g_restartAfterUpdate = true;
   1.499  				return ConfigResult_Accept;
   1.500  			}
   1.501 -			else if (strcmp(value, "no") == 0)
   1.502 +			else if (strcasecmp(value, "no") == 0)
   1.503  			{
   1.504  				g_restartAfterUpdate = false;
   1.505  				return ConfigResult_Accept;
   1.506 @@ -697,14 +694,14 @@
   1.507  			return ConfigResult_Reject;
   1.508  		}
   1.509  
   1.510 -		if (strcmp(key, "AutoUpdateServer") == 0)
   1.511 +		if (strcasecmp(key, "AutoUpdateServer") == 0)
   1.512  		{
   1.513  			UTIL_Format(g_serverAddress, sizeof(g_serverAddress), "%s", value);
   1.514  
   1.515  			return ConfigResult_Accept;
   1.516  		}
   1.517  
   1.518 -		if (strcmp(key, "AutoUpdatePort") == 0)
   1.519 +		if (strcasecmp(key, "AutoUpdatePort") == 0)
   1.520  		{
   1.521  			int port = atoi(value);
   1.522  
   1.523 @@ -722,6 +719,55 @@
   1.524  	}
   1.525  } g_InitFetch;
   1.526  
   1.527 +BuildMD5ableBuffer::BuildMD5ableBuffer()
   1.528 +{
   1.529 +	stringTable = new BaseStringTable(2048);
   1.530 +}
   1.531 +
   1.532 +BuildMD5ableBuffer::~BuildMD5ableBuffer()
   1.533 +{
   1.534 +	delete stringTable;
   1.535 +}
   1.536 +
   1.537 +void BuildMD5ableBuffer::ReadSMC_ParseStart()
   1.538 +{
   1.539 +	stringTable->Reset();
   1.540 +}
   1.541 +
   1.542 +SMCResult BuildMD5ableBuffer::ReadSMC_KeyValue(const SMCStates *states,
   1.543 +											   const char *key,
   1.544 +											   const char *value)
   1.545 +{
   1.546 +	stringTable->AddString(key);
   1.547 +	stringTable->AddString(value);
   1.548 +
   1.549 +	return SMCResult_Continue;
   1.550 +}
   1.551 +
   1.552 +SMCResult BuildMD5ableBuffer::ReadSMC_NewSection(const SMCStates *states, const char *name)
   1.553 +{
   1.554 +	stringTable->AddString(name);
   1.555 +
   1.556 +	return SMCResult_Continue;
   1.557 +}
   1.558 +
   1.559 +void BuildMD5ableBuffer::ReadSMC_ParseEnd(bool halted, bool failed)
   1.560 +{
   1.561 +	if (halted || failed)
   1.562 +	{
   1.563 +		return;
   1.564 +	}
   1.565 +
   1.566 +	void *data = stringTable->GetMemTable()->GetAddress(0);
   1.567 +
   1.568 +	if (data != NULL)
   1.569 +	{
   1.570 +		checksum->update((unsigned char *)data, stringTable->GetMemTable()->GetActualMemUsed());
   1.571 +	}
   1.572 +
   1.573 +	checksum->finalize();
   1.574 +}
   1.575 +
   1.576  CON_COMMAND(sm_gamedata_md5, "Checks the MD5 sum for a given gamedata file")
   1.577  {
   1.578  #if !defined ORANGEBOX_BUILD
   1.579 @@ -764,3 +810,25 @@
   1.580  
   1.581  	g_SMAPI->ConPrint("File not found!\n");
   1.582  }
   1.583 +
   1.584 +FetcherThread::~FetcherThread()
   1.585 +{
   1.586 +	//delete filenames;
   1.587 +	SourceHook::CVector<FileData *>::iterator iter = filenames.begin();
   1.588 +
   1.589 +	FileData *curData;
   1.590 +
   1.591 +	while (iter != filenames.end())
   1.592 +	{
   1.593 +		curData = (*iter);
   1.594 +		delete curData->filename;
   1.595 +		delete curData;
   1.596 +		iter = filenames.erase(iter);
   1.597 +	}
   1.598 +}
   1.599 +
   1.600 +FetcherThread::FetcherThread() 
   1.601 +{
   1.602 +	memtable = new BaseMemTable(4096);
   1.603 +}
   1.604 +