Init
This commit is contained in:
@ -0,0 +1,844 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "slikenet/string.h"
|
||||
#include "AutopatcherMySQLRepository.h"
|
||||
#include "slikenet/AutopatcherPatchContext.h"
|
||||
#include "slikenet/FileList.h"
|
||||
#include "slikenet/assert.h"
|
||||
#include "slikenet/DS_List.h"
|
||||
// ntohl
|
||||
#ifdef _WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
// If you get fatal error C1083: Cannot open include file: 'mysql.h' then you need to install MySQL. See readme.txt in this sample directory.
|
||||
#include "mysql.h"
|
||||
#include "CreatePatch.h"
|
||||
#include "slikenet/AutopatcherPatchContext.h"
|
||||
// #include "slikenet/DR_SHA1.h"
|
||||
#include <stdlib.h>
|
||||
#include "slikenet/LinuxStrings.h"
|
||||
#include "slikenet/linux_adapter.h"
|
||||
#include "slikenet/osx_adapter.h"
|
||||
|
||||
using namespace SLNet;
|
||||
|
||||
static const unsigned HASH_LENGTH=sizeof(unsigned int);
|
||||
|
||||
struct FileInfo
|
||||
{
|
||||
SLNet::RakString filename;
|
||||
char contentHash [HASH_LENGTH];
|
||||
bool createFile;
|
||||
};
|
||||
|
||||
// alloca
|
||||
#ifdef _COMPATIBILITY_1
|
||||
#elif defined(_WIN32)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
//#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define PQEXECPARAM_FORMAT_TEXT 0
|
||||
#define PQEXECPARAM_FORMAT_BINARY 1
|
||||
|
||||
AutopatcherMySQLRepository::AutopatcherMySQLRepository()
|
||||
{
|
||||
filePartConnection=0;
|
||||
}
|
||||
|
||||
AutopatcherMySQLRepository::~AutopatcherMySQLRepository()
|
||||
{
|
||||
if (filePartConnection)
|
||||
mysql_close(filePartConnection);
|
||||
}
|
||||
bool AutopatcherMySQLRepository::CreateAutopatcherTables(void)
|
||||
{
|
||||
if (!IsConnected())
|
||||
return false;
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
ExecuteBlockingCommand("BEGIN;");
|
||||
|
||||
if (!ExecuteBlockingCommand(
|
||||
"CREATE TABLE Applications ("
|
||||
"applicationID INT AUTO_INCREMENT,"
|
||||
"applicationName VARCHAR(255) NOT NULL UNIQUE,"
|
||||
"changeSetID integer NOT NULL DEFAULT 0,"
|
||||
"userName TEXT NOT NULL,"
|
||||
"PRIMARY KEY (applicationID));"
|
||||
)) {Rollback(); return false;}
|
||||
|
||||
if (!ExecuteBlockingCommand(
|
||||
"CREATE TABLE FileVersionHistory ("
|
||||
"fileID INT AUTO_INCREMENT,"
|
||||
"applicationID INT NOT NULL, "
|
||||
"filename VARCHAR(255) NOT NULL,"
|
||||
"fileLength INT,"
|
||||
"content LONGBLOB,"
|
||||
"contentHash TINYBLOB,"
|
||||
"patch LONGBLOB,"
|
||||
"createFile TINYINT NOT NULL,"
|
||||
"modificationDate double precision DEFAULT (EXTRACT(EPOCH FROM now())),"
|
||||
"lastSentDate double precision,"
|
||||
"timesSent INT NOT NULL DEFAULT 0,"
|
||||
"changeSetID INT NOT NULL,"
|
||||
"userName TEXT NOT NULL,"
|
||||
"PRIMARY KEY (fileID)); "
|
||||
)) {Rollback(); return false;}
|
||||
|
||||
if (!ExecuteBlockingCommand(
|
||||
"CREATE INDEX FV_appID on FileVersionHistory(applicationID);"
|
||||
)) {Rollback(); return false;}
|
||||
|
||||
if (!ExecuteBlockingCommand(
|
||||
"CREATE INDEX FV_fname on FileVersionHistory(filename);"
|
||||
)) {Rollback(); return false;}
|
||||
|
||||
if (!ExecuteBlockingCommand(
|
||||
"CREATE VIEW AutoPatcherView AS SELECT "
|
||||
"FileVersionHistory.applicationid,"
|
||||
"Applications.applicationName,"
|
||||
"FileVersionHistory.fileID,"
|
||||
"FileVersionHistory.fileName,"
|
||||
"FileVersionHistory.createFile,"
|
||||
"FileVersionHistory.fileLength,"
|
||||
"FileVersionHistory.changeSetID,"
|
||||
"FileVersionHistory.lastSentDate,"
|
||||
"FileVersionHistory.modificationDate,"
|
||||
"FileVersionHistory.timesSent "
|
||||
"FROM (FileVersionHistory JOIN Applications ON "
|
||||
"( FileVersionHistory.applicationID = Applications.applicationID )) "
|
||||
"ORDER BY Applications.applicationID ASC, FileVersionHistory.fileID ASC;"
|
||||
)) {Rollback(); return false;}
|
||||
|
||||
bool b = ExecuteBlockingCommand("COMMIT;");
|
||||
//sqlCommandMutex.Unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
bool AutopatcherMySQLRepository::DestroyAutopatcherTables(void)
|
||||
{
|
||||
if (!IsConnected())
|
||||
return false;
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
ExecuteBlockingCommand("DROP INDEX FV_appID;");
|
||||
ExecuteBlockingCommand("DROP INDEX FV_fname;");
|
||||
ExecuteBlockingCommand("DROP TABLE Applications CASCADE;");
|
||||
ExecuteBlockingCommand("DROP TABLE FileVersionHistory CASCADE;");
|
||||
bool b = ExecuteBlockingCommand("DROP VIEW AutoPatcherView;");
|
||||
//sqlCommandMutex.Unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
bool AutopatcherMySQLRepository::AddApplication(const char *applicationName, const char *userName)
|
||||
{
|
||||
// mysql_real_escape_string
|
||||
|
||||
char query[512];
|
||||
sprintf_s(query, "INSERT INTO Applications (applicationName, userName) VALUES ('%s', '%s');", GetEscapedString(applicationName).C_String(), GetEscapedString(userName).C_String());
|
||||
//sqlCommandMutex.Lock();
|
||||
bool b = ExecuteBlockingCommand(query);
|
||||
//sqlCommandMutex.Unlock();
|
||||
return b;
|
||||
}
|
||||
bool AutopatcherMySQLRepository::RemoveApplication(const char *applicationName)
|
||||
{
|
||||
char query[512];
|
||||
sprintf_s(query, "DELETE FROM Applications WHERE applicationName='%s';", GetEscapedString(applicationName).C_String());
|
||||
//sqlCommandMutex.Lock();
|
||||
bool b = ExecuteBlockingCommand(query);
|
||||
//sqlCommandMutex.Unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
bool AutopatcherMySQLRepository::GetChangelistSinceDate(const char *applicationName, FileList *addedOrModifiedFilesWithHashData, FileList *deletedFiles, double sinceDate)
|
||||
{
|
||||
char query[512];
|
||||
SLNet::RakString escapedApplicationName = GetEscapedString(applicationName);
|
||||
sprintf_s(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());
|
||||
|
||||
int applicationID;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteQueryReadInt(query, &applicationID))
|
||||
{
|
||||
// This message covers the lost connection to the SQL server
|
||||
//sqlCommandMutex.Unlock();
|
||||
//sprintf_s(lastError,"ERROR: %s not found in UpdateApplicationFiles\n",escapedApplicationName.C_String());
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
if (sinceDate!=0)
|
||||
sprintf_s(query,
|
||||
"SELECT filename, fileLength, contentHash, createFile, fileId FROM FileVersionHistory "
|
||||
"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i AND modificationDate > %f GROUP BY fileName) MaxId "
|
||||
"ON FileVersionHistory.fileId = MaxId.maxId "
|
||||
"ORDER BY filename DESC;", applicationID,sinceDate);
|
||||
else
|
||||
sprintf_s(query,
|
||||
"SELECT filename, fileLength, contentHash, createFile, fileId FROM FileVersionHistory "
|
||||
"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i GROUP BY fileName) MaxId "
|
||||
"ON FileVersionHistory.fileId = MaxId.maxId "
|
||||
"ORDER BY filename DESC;", applicationID);
|
||||
|
||||
MYSQL_RES * result = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &result))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row (result)) != 0)
|
||||
{
|
||||
const char * createFileResult = row [3];
|
||||
const char * hardDriveFilename = row [0];
|
||||
if (createFileResult[0]=='1')
|
||||
{
|
||||
const char * hardDriveHash = row [2];
|
||||
int fileLength = atoi (row [1]);
|
||||
addedOrModifiedFilesWithHashData->AddFile(hardDriveFilename, hardDriveFilename, hardDriveHash, HASH_LENGTH, fileLength, FileListNodeContext(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
deletedFiles->AddFile(hardDriveFilename,hardDriveFilename,0,0,0,FileListNodeContext(), false);
|
||||
}
|
||||
}
|
||||
mysql_free_result (result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int AutopatcherMySQLRepository::GetPatches(const char *applicationName, FileList *input, bool allowDownloadOfOriginalUnmodifiedFiles, FileList *patchList)
|
||||
{
|
||||
char query[512];
|
||||
SLNet::RakString escapedApplicationName = GetEscapedString(applicationName);
|
||||
sprintf_s(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());
|
||||
int applicationID;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteQueryReadInt (query, &applicationID))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
sprintf_s(lastError,"ERROR: %s not found in GetPatches\n",applicationName);
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
// Go through the input list.
|
||||
for (unsigned inputIndex=0; inputIndex < input->fileList.Size(); inputIndex++)
|
||||
{
|
||||
const char * userHash=input->fileList[inputIndex].data;
|
||||
const char * userFilename=input->fileList[inputIndex].filename;
|
||||
|
||||
char *fn = new char [(strlen(userFilename))*2+1];
|
||||
mysql_real_escape_string(mySqlConnection, fn, userFilename, (unsigned long) strlen(userFilename));
|
||||
|
||||
if (userHash==0)
|
||||
{
|
||||
// If the user does not have a hash in the input list, get the contents of latest version of this named file and write it to the patch list
|
||||
// sprintf_s(query, "SELECT content FROM FileVersionHistory "
|
||||
// "JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i AND filename='%s') MaxId "
|
||||
// "ON FileVersionHistory.fileId = MaxId.maxId",
|
||||
// applicationID, fn);
|
||||
|
||||
sprintf_s(query, "SELECT fileId, fileLength, changeSetID FROM FileVersionHistory "
|
||||
"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i AND filename='%s') MaxId "
|
||||
"ON FileVersionHistory.fileId = MaxId.maxId",
|
||||
applicationID, fn);
|
||||
|
||||
MYSQL_RES * result = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &result))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
delete [] fn;
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row (result);
|
||||
if (row != 0)
|
||||
{
|
||||
//const char * content = row [0];
|
||||
//unsigned long contentLength=mysql_fetch_lengths (result) [0];
|
||||
//patchList->AddFile(userFilename, content, contentLength, contentLength, FileListNodeContext(PC_WRITE_FILE,0));
|
||||
const int fileId = atoi (row [0]);
|
||||
const int fileLength = atoi (row [1]);
|
||||
const int changeSetID = atoi (row [2]);
|
||||
if (allowDownloadOfOriginalUnmodifiedFiles==false && changeSetID==0)
|
||||
{
|
||||
printf("Failure: allowDownloadOfOriginalUnmodifiedFiles==false for %s length %i\n", userFilename, fileLength);
|
||||
|
||||
mysql_free_result(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
patchList->AddFile(userFilename,userFilename, 0, fileLength, fileLength, FileListNodeContext(PC_WRITE_FILE,fileId,0,0), true);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else // Assuming the user does have a hash.
|
||||
{
|
||||
if (input->fileList[inputIndex].dataLengthBytes!=HASH_LENGTH)
|
||||
{
|
||||
delete [] fn;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the hash and ID of the latest version of this file, by filename.
|
||||
sprintf_s(query,
|
||||
"SELECT contentHash, fileId, fileLength FROM FileVersionHistory "
|
||||
"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i AND filename='%s') MaxId "
|
||||
"ON FileVersionHistory.fileId = MaxId.maxId",
|
||||
applicationID, fn);
|
||||
|
||||
MYSQL_RES * result = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &result))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
delete [] fn;
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row (result);
|
||||
if (row != 0)
|
||||
{
|
||||
const char * contentHash = row [0];
|
||||
const int fileId = atoi (row [1]);
|
||||
const int fileLength = atoi (row [2]); // double check if this works
|
||||
|
||||
if (memcmp(contentHash, userHash, HASH_LENGTH)!=0)
|
||||
{
|
||||
char buf [2 * HASH_LENGTH + 1];
|
||||
mysql_real_escape_string(mySqlConnection, buf, userHash, HASH_LENGTH);
|
||||
|
||||
sprintf_s(query, "SELECT patch FROM FileVersionHistory WHERE applicationId=%i AND filename='%s' AND contentHash='%s'; ", applicationID, fn, buf);
|
||||
MYSQL_RES * patchResult = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &patchResult))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
delete [] fn;
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
row = mysql_fetch_row (patchResult);
|
||||
if (row==0)
|
||||
{
|
||||
// If no patch found, then this is a non-release version, or a very old version we are no longer tracking.
|
||||
// Get the contents of latest version of this named file by fileId and return it.
|
||||
|
||||
/*
|
||||
sprintf_s(query, "SELECT content FROM FileVersionHistory WHERE fileId=%d;", fileId);
|
||||
|
||||
if (mysql_query (mySqlConnection, query) != 0)
|
||||
{
|
||||
delete [] fn;
|
||||
strcpy (lastError, mysql_error (mySqlConnection));
|
||||
return false;
|
||||
}
|
||||
|
||||
MYSQL_RES * substrresult = mysql_store_result (mySqlConnection);
|
||||
row = mysql_fetch_row (substrresult);
|
||||
char * file = row [0];
|
||||
unsigned long contentLength = mysql_fetch_lengths (substrresult) [0];
|
||||
|
||||
patchList->AddFile(userFilename, file, fileLength, contentLength, FileListNodeContext(PC_WRITE_FILE,0));
|
||||
mysql_free_result(substrresult);
|
||||
*/
|
||||
patchList->AddFile(userFilename,userFilename, 0, fileLength, fileLength, FileListNodeContext(PC_WRITE_FILE,fileId,0,0), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, write the hash of the new version and then write the patch to get to that version.
|
||||
//
|
||||
char * patch = row [0];
|
||||
unsigned long patchLength = mysql_fetch_lengths (patchResult) [0];
|
||||
|
||||
char *temp = new char [patchLength + HASH_LENGTH];
|
||||
memcpy(temp, contentHash, HASH_LENGTH);
|
||||
memcpy(temp+HASH_LENGTH, patch, patchLength);
|
||||
|
||||
patchList->AddFile(userFilename,userFilename, temp, HASH_LENGTH+patchLength, fileLength, FileListNodeContext(PC_HASH_1_WITH_PATCH,0,0,0) );
|
||||
delete [] temp;
|
||||
}
|
||||
|
||||
mysql_free_result(patchResult);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// else if the hash of this file matches what the user has, the user has the latest version. Done.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// else if there is no such file, skip this file.
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
|
||||
delete [] fn;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AutopatcherMySQLRepository::GetMostRecentChangelistWithPatches(SLNet::RakString &applicationName, FileList *patchedFiles, FileList *addedFiles, FileList *addedOrModifiedFileHashes, FileList *deletedFiles, double *priorRowPatchTime, double *mostRecentRowPatchTime)
|
||||
{
|
||||
// unused parameters
|
||||
(void)applicationName;
|
||||
(void)patchedFiles;
|
||||
(void)addedFiles;
|
||||
(void)addedOrModifiedFileHashes;
|
||||
(void)deletedFiles;
|
||||
(void)priorRowPatchTime;
|
||||
(void)mostRecentRowPatchTime;
|
||||
|
||||
// Not yet implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AutopatcherMySQLRepository::UpdateApplicationFiles(const char *applicationName, const char *applicationDirectory, const char *userName, FileListProgress *cb)
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND bind[3];
|
||||
char query[512];
|
||||
FileList filesOnHarddrive;
|
||||
filesOnHarddrive.AddCallback(cb);
|
||||
int prepareResult;
|
||||
my_bool falseVar=false;
|
||||
SLNet::RakString escapedApplicationName = GetEscapedString(applicationName);
|
||||
filesOnHarddrive.AddFilesFromDirectory(applicationDirectory,"", true, true, true, FileListNodeContext());
|
||||
if (filesOnHarddrive.fileList.Size()==0)
|
||||
{
|
||||
sprintf_s(lastError,"ERROR: Can't find files at %s in UpdateApplicationFiles\n",applicationDirectory);
|
||||
return false;
|
||||
}
|
||||
|
||||
sprintf_s(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());
|
||||
int applicationID;
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteQueryReadInt(query, &applicationID))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
sprintf_s(lastError,"ERROR: %s not found in UpdateApplicationFiles\n",escapedApplicationName.C_String());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExecuteBlockingCommand("BEGIN;"))
|
||||
{
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
sprintf_s(query, "UPDATE Applications SET changeSetId = changeSetId + 1 where applicationID=%i;", applicationID);
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand(query))
|
||||
{
|
||||
Rollback ();
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
int changeSetId = 0;
|
||||
sprintf_s(query, "SELECT changeSetId FROM Applications WHERE applicationID=%i;", applicationID);
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteQueryReadInt(query, &changeSetId))
|
||||
{
|
||||
Rollback ();
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
// +1 was added in the update
|
||||
changeSetId--;
|
||||
|
||||
// Gets all newest files
|
||||
sprintf_s(query, "SELECT filename, contentHash, createFile FROM FileVersionHistory "
|
||||
"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i GROUP BY fileName) MaxId "
|
||||
"ON FileVersionHistory.fileId = MaxId.maxId "
|
||||
"ORDER BY filename DESC;", applicationID);
|
||||
|
||||
MYSQL_RES *result = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand(query, &result))
|
||||
{
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
DataStructures::List <FileInfo> newestFiles;
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row (result)) != 0)
|
||||
{
|
||||
FileInfo fi;
|
||||
fi.filename = row [0];
|
||||
fi.createFile = (atoi (row [2]) != 0);
|
||||
if (fi.createFile)
|
||||
{
|
||||
RakAssert(mysql_fetch_lengths (result) [1] == HASH_LENGTH); // check the data is sensible
|
||||
memcpy (fi.contentHash, row [1], HASH_LENGTH);
|
||||
}
|
||||
newestFiles.Insert (fi, _FILE_AND_LINE_ );
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
|
||||
FileList newFiles;
|
||||
// Loop through files on filesOnHarddrive
|
||||
// If the file in filesOnHarddrive does not exist in the query result, or if it does but the hash is different or non-existent, add this file to the create list
|
||||
for (unsigned fileListIndex=0; fileListIndex < filesOnHarddrive.fileList.Size(); fileListIndex++)
|
||||
{
|
||||
bool addFile=true;
|
||||
if (fileListIndex%10==0)
|
||||
printf("Hashing files %i/%i\n", fileListIndex+1, filesOnHarddrive.fileList.Size());
|
||||
|
||||
const char * hardDriveFilename=filesOnHarddrive.fileList[fileListIndex].filename;
|
||||
const char * hardDriveHash=filesOnHarddrive.fileList[fileListIndex].data;
|
||||
|
||||
for (unsigned i = 0; i != newestFiles.Size (); ++i)
|
||||
{
|
||||
const FileInfo & fi = newestFiles [i];
|
||||
|
||||
if (_stricmp(hardDriveFilename, fi.filename)==0)
|
||||
{
|
||||
if (fi.createFile && memcmp(fi.contentHash, hardDriveHash, HASH_LENGTH)==0)
|
||||
{
|
||||
// File exists in database and is the same
|
||||
addFile=false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Unless set to false, file does not exist in query result or is different.
|
||||
if (addFile)
|
||||
{
|
||||
newFiles.AddFile(hardDriveFilename,hardDriveFilename, filesOnHarddrive.fileList[fileListIndex].data, filesOnHarddrive.fileList[fileListIndex].dataLengthBytes, filesOnHarddrive.fileList[fileListIndex].fileLengthBytes, FileListNodeContext(), false, true);
|
||||
filesOnHarddrive.fileList[fileListIndex].data=0;
|
||||
}
|
||||
}
|
||||
|
||||
// Go through query results that are marked as create
|
||||
// If a file that is currently in the database is not on the harddrive, add it to the delete list
|
||||
FileList deletedFiles;
|
||||
for (unsigned i = 0; i != newestFiles.Size (); ++i)
|
||||
{
|
||||
const FileInfo & fi = newestFiles [i];
|
||||
if (!fi.createFile)
|
||||
continue; // If already false don't mark false again.
|
||||
|
||||
bool fileOnHarddrive=false;
|
||||
for (unsigned fileListIndex=0; fileListIndex < filesOnHarddrive.fileList.Size(); fileListIndex++)
|
||||
{
|
||||
const char * hardDriveFilename=filesOnHarddrive.fileList[fileListIndex].filename;
|
||||
//hardDriveHash=filesOnHarddrive.fileList[fileListIndex].data;
|
||||
|
||||
if (_stricmp(hardDriveFilename, fi.filename)==0)
|
||||
{
|
||||
fileOnHarddrive=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileOnHarddrive)
|
||||
deletedFiles.AddFile(fi.filename,fi.filename,0,0,0,FileListNodeContext(), false);
|
||||
}
|
||||
|
||||
// files on harddrive no longer needed. Free this memory since generating all the patches is memory intensive.
|
||||
filesOnHarddrive.Clear();
|
||||
|
||||
// For each file in the delete list add a row indicating file deletion
|
||||
for (unsigned fileListIndex=0; fileListIndex < deletedFiles.fileList.Size(); fileListIndex++)
|
||||
{
|
||||
if (fileListIndex%10==0)
|
||||
printf("Tagging deleted files %i/%i\n", fileListIndex+1, deletedFiles.fileList.Size());
|
||||
|
||||
sprintf_s(query, "INSERT INTO FileVersionHistory(applicationID, filename, createFile, changeSetID, userName) VALUES (%i, '%s', FALSE,%i,'%s');",
|
||||
applicationID, GetEscapedString(deletedFiles.fileList[fileListIndex].filename).C_String(), changeSetId, GetEscapedString(userName).C_String());
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query))
|
||||
{
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
deletedFiles.Clear();
|
||||
newFiles.Clear();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
}
|
||||
|
||||
// Clear the delete list as it is no longer needed.
|
||||
deletedFiles.Clear();
|
||||
|
||||
// For each file in the create list
|
||||
for (unsigned fileListIndex=0; fileListIndex < newFiles.fileList.Size(); fileListIndex++)
|
||||
{
|
||||
if (fileListIndex%10==0)
|
||||
printf("Adding file %i/%i\n", fileListIndex+1, newFiles.fileList.Size());
|
||||
const char * hardDriveFilename=newFiles.fileList[fileListIndex].filename;
|
||||
const char * hardDriveData=newFiles.fileList[fileListIndex].data+HASH_LENGTH;
|
||||
const char * hardDriveHash=newFiles.fileList[fileListIndex].data;
|
||||
unsigned hardDriveDataLength=newFiles.fileList[fileListIndex].fileLengthBytes;
|
||||
|
||||
sprintf_s( query, "SELECT fileID from FileVersionHistory WHERE applicationID=%i AND filename='%s' AND createFile=TRUE;", applicationID, GetEscapedString(hardDriveFilename).C_String() );
|
||||
|
||||
MYSQL_RES * res = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &res))
|
||||
{
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
newFiles.Clear();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
// Create new patches for every create version
|
||||
while ((row = mysql_fetch_row (res)) != 0)
|
||||
{
|
||||
const char * fileID = row [0];
|
||||
|
||||
// The last query handled all the relevant comparisons
|
||||
sprintf_s(query, "SELECT content from FileVersionHistory WHERE fileID=%s", fileID );
|
||||
MYSQL_RES * queryResult = 0;
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand (query, &queryResult))
|
||||
{
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
newFiles.Clear();
|
||||
mysql_free_result(res);
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
MYSQL_ROW queryRow = mysql_fetch_row (queryResult);
|
||||
|
||||
const unsigned contentLength=mysql_fetch_lengths (queryResult) [0];
|
||||
const char * content=queryRow [0];
|
||||
|
||||
char *patch;
|
||||
unsigned patchLength;
|
||||
if (!CreatePatch(content, contentLength, (char *) hardDriveData, hardDriveDataLength, &patch, &patchLength))
|
||||
{
|
||||
strcpy_s(lastError,"CreatePatch failed.\n");
|
||||
Rollback();
|
||||
|
||||
newFiles.Clear();
|
||||
mysql_free_result(res);
|
||||
mysql_free_result(queryResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
stmt = mysql_stmt_init(mySqlConnection);
|
||||
sprintf (buf, "UPDATE FileVersionHistory SET patch=? where fileID=%s;", fileID);
|
||||
if ((prepareResult=mysql_stmt_prepare(stmt, buf, (unsigned long) strlen(buf)))!=0)
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
unsigned long l1;
|
||||
l1=patchLength;
|
||||
bind[0].buffer_type= MYSQL_TYPE_LONG_BLOB;
|
||||
bind[0].buffer= patch;
|
||||
bind[0].buffer_length= patchLength;
|
||||
bind[0].is_null= &falseVar;
|
||||
bind[0].length=&l1;
|
||||
|
||||
if (mysql_stmt_bind_param(stmt, bind))
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
if (mysql_stmt_execute(stmt))
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
newFiles.Clear();
|
||||
mysql_free_result(res);
|
||||
mysql_free_result(queryResult);
|
||||
delete [] patch;
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
delete [] patch;
|
||||
|
||||
mysql_free_result(queryResult);
|
||||
}
|
||||
mysql_free_result(res);
|
||||
|
||||
stmt = mysql_stmt_init(mySqlConnection);
|
||||
sprintf_s(query, "INSERT INTO FileVersionHistory (applicationID, filename, fileLength, content, contentHash, createFile, changeSetID, userName) "
|
||||
"VALUES (%i, ?, %i,?,?, TRUE, %i, '%s' );",
|
||||
applicationID, hardDriveDataLength, changeSetId, GetEscapedString(userName).C_String());
|
||||
|
||||
if ((prepareResult=mysql_stmt_prepare(stmt, query, (unsigned long) strlen(query)))!=0)
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
unsigned long l2,l3,l4;
|
||||
l2=(unsigned long) strlen(hardDriveFilename);
|
||||
l3=hardDriveDataLength;
|
||||
l4=HASH_LENGTH;
|
||||
bind[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[0].buffer= (void*) hardDriveFilename;
|
||||
bind[0].buffer_length= (unsigned long) strlen(hardDriveFilename);
|
||||
bind[0].is_null= &falseVar;
|
||||
bind[0].length=&l2;
|
||||
|
||||
bind[1].buffer_type= MYSQL_TYPE_LONG_BLOB;
|
||||
bind[1].buffer= (void*) hardDriveData;
|
||||
bind[1].buffer_length= hardDriveDataLength;
|
||||
bind[1].is_null= &falseVar;
|
||||
bind[1].length=&l3;
|
||||
|
||||
bind[2].buffer_type= MYSQL_TYPE_TINY_BLOB;
|
||||
bind[2].buffer= (void*) hardDriveHash;
|
||||
bind[2].buffer_length= HASH_LENGTH;
|
||||
bind[2].is_null= &falseVar;
|
||||
bind[2].length=&l4;
|
||||
|
||||
if (mysql_stmt_bind_param(stmt, bind))
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
if (mysql_stmt_execute(stmt))
|
||||
{
|
||||
strcpy (lastError, mysql_stmt_error (stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
Rollback();
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
//sqlCommandMutex.Lock();
|
||||
if (!ExecuteBlockingCommand("COMMIT;"))
|
||||
{
|
||||
Rollback ();
|
||||
//sqlCommandMutex.Unlock();
|
||||
return false;
|
||||
}
|
||||
//sqlCommandMutex.Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *AutopatcherMySQLRepository::GetLastError(void) const
|
||||
{
|
||||
return MySQLInterface::GetLastError();
|
||||
}
|
||||
unsigned int AutopatcherMySQLRepository::GetFilePart( const char *filename, unsigned int startReadBytes, unsigned int numBytesToRead, void *preallocatedDestination, FileListNodeContext context)
|
||||
{
|
||||
// unused parameters
|
||||
(void)filename;
|
||||
|
||||
char query[512];
|
||||
sprintf_s(query, "SELECT substring(content from %i for %i) FROM FileVersionHistory WHERE fileId=%i;", startReadBytes+1,numBytesToRead,context.flnc_extraData1);
|
||||
|
||||
// CREATE NEW CONNECTION JUST FOR THIS QUERY
|
||||
// This is because the autopatcher is sharing this class, but this is called from multiple threads and mysql is not threadsafe
|
||||
|
||||
MYSQL_RES * result;
|
||||
|
||||
char error[512];
|
||||
filePartConnectionMutex.Lock();
|
||||
if (filePartConnection==0)
|
||||
{
|
||||
filePartConnection = mysql_init(0);
|
||||
mysql_real_connect (filePartConnection, _host, _user, _passwd, _db, _port, _unix_socket, _clientflag);
|
||||
}
|
||||
|
||||
if (mysql_query(filePartConnection, query)!=0)
|
||||
{
|
||||
// #med - review --- should this set the class member maybe?
|
||||
strcpy (error, mysql_error (filePartConnection));
|
||||
}
|
||||
result = mysql_store_result (filePartConnection);
|
||||
|
||||
if (result)
|
||||
{
|
||||
// This has very poor performance with any size for GetIncrementalReadChunkSize, but especially for larger sizes
|
||||
MYSQL_ROW row = mysql_fetch_row (result);
|
||||
if (row != 0)
|
||||
{
|
||||
const char * content = row [0];
|
||||
unsigned long contentLength=mysql_fetch_lengths (result) [0];
|
||||
memcpy(preallocatedDestination,content,contentLength);
|
||||
mysql_free_result (result);
|
||||
|
||||
filePartConnectionMutex.Unlock();
|
||||
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
mysql_free_result (result);
|
||||
}
|
||||
|
||||
filePartConnectionMutex.Unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
const int AutopatcherMySQLRepository::GetIncrementalReadChunkSize(void) const
|
||||
{
|
||||
// AutopatcherMySQLRepository::GetFilePart is extremely slow with larger files
|
||||
return 262144*4;
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief An implementation of the AutopatcherRepositoryInterface to use MySQL to store the relevant data
|
||||
///
|
||||
|
||||
|
||||
|
||||
#ifndef __MYSQL_REPOSITORY_H
|
||||
#define __MYSQL_REPOSITORY_H
|
||||
|
||||
#include "slikenet/AutopatcherRepositoryInterface.h"
|
||||
#include "MySQLInterface.h"
|
||||
#include "slikenet/Export.h"
|
||||
|
||||
namespace SLNet
|
||||
{
|
||||
class FileListProgress;
|
||||
|
||||
|
||||
/// \ingroup Autopatcher
|
||||
/// An implementation of the AutopatcherRepositoryInterface to use MySQL to store the relevant data
|
||||
class RAK_DLL_EXPORT AutopatcherMySQLRepository : public AutopatcherRepositoryInterface, public MySQLInterface
|
||||
{
|
||||
public:
|
||||
AutopatcherMySQLRepository();
|
||||
~AutopatcherMySQLRepository();
|
||||
|
||||
/// Create the tables used by the autopatcher, for all applications. Call this first.
|
||||
/// \return True on success, false on failure.
|
||||
bool CreateAutopatcherTables(void);
|
||||
|
||||
/// Destroy the tables used by the autopatcher. Don't call this unless you don't want to use the autopatcher anymore, or are testing.
|
||||
/// \return True on success, false on failure.
|
||||
bool DestroyAutopatcherTables(void);
|
||||
|
||||
/// Add an application for use by files. Call this second.
|
||||
/// \param[in] applicationName A null terminated string.
|
||||
/// \param[in] userName Stored in the database, but otherwise unused. Useful to track who added this application.
|
||||
/// \return True on success, false on failure.
|
||||
bool AddApplication(const char *applicationName, const char *userName);
|
||||
|
||||
/// Remove an application and files used by that application.
|
||||
/// \param[in] applicationName A null terminated string previously passed to AddApplication
|
||||
/// \return True on success, false on failure.
|
||||
bool RemoveApplication(const char *applicationName);
|
||||
|
||||
/// Update all the files for an application to match what is at the specified directory. Call this third.
|
||||
/// Be careful not to call this with the wrong directory.
|
||||
/// This is implemented in a Begin and Rollback block so you won't a messed up database from get partial updates.
|
||||
/// \param[in] applicationName A null terminated string previously passed to AddApplication
|
||||
/// \param[in] applicationDirectory The base directory of your application. All files in this directory and subdirectories are added.
|
||||
/// \param[in] userName Stored in the database, but otherwise unused. Useful to track who added this revision
|
||||
/// \param[in] cb Callback to get progress updates. Pass 0 to not use.
|
||||
/// \return True on success, false on failure.
|
||||
bool UpdateApplicationFiles(const char *applicationName, const char *applicationDirectory, const char *userName, FileListProgress *cb);
|
||||
|
||||
/// Get list of files added and deleted since a certain date. This is used by AutopatcherServer and not usually explicitly called.
|
||||
/// \param[in] applicationName A null terminated string previously passed to AddApplication
|
||||
/// \param[out] addedFiles A list of the current versions of filenames with SHA1_LENGTH byte hashes as their data that were created after \a sinceData
|
||||
/// \param[out] deletedFiles A list of the current versions of filenames that were deleted after \a sinceData
|
||||
/// \param[in] An input date, in the string format of a timestamp.
|
||||
/// \return True on success, false on failure.
|
||||
virtual bool GetChangelistSinceDate(const char *applicationName, FileList *addedOrModifiedFilesWithHashData, FileList *deletedFiles, double sinceDate);
|
||||
|
||||
/// Get patches (or files) for every file in input, assuming that input has a hash for each of those files. This is used by AutopatcherServer and not usually explicitly called.
|
||||
/// \param[in] applicationName A null terminated string previously passed to AddApplication
|
||||
/// \param[in] input A list of files with hashes to get from the database. If this hash exists, a patch to the current version is returned if this file is not the current version. Otherwise the current version is returned.
|
||||
/// \param[out] patchList A list of files with either the filedata or the patch. This is a subset of \a input. The context data for each file will be either PC_WRITE_FILE (to just write the file) or PC_HASH_WITH_PATCH (to patch). If PC_HASH_WITH_PATCH, then the file contains a SHA1_LENGTH byte patch followed by the hash. The datalength is patchlength + SHA1_LENGTH
|
||||
/// \return 1 on success, 0 on database failure, -1 on tried to download original unmodified file
|
||||
virtual int GetPatches(const char *applicationName, FileList *input, bool allowDownloadOfOriginalUnmodifiedFiles, FileList *patchList);
|
||||
|
||||
// Not yet implemented
|
||||
virtual bool GetMostRecentChangelistWithPatches(SLNet::RakString &applicationName, FileList *patchedFiles, FileList *addedFiles, FileList *addedOrModifiedFileHashes, FileList *deletedFiles, double *priorRowPatchTime, double *mostRecentRowPatchTime);
|
||||
|
||||
/// If any of the above functions fail, the error string is stored internally. Call this to get it.
|
||||
virtual const char *GetLastError(void) const;
|
||||
|
||||
/// Read part of a file into \a destination
|
||||
/// Return the number of bytes written. Return 0 when file is done.
|
||||
/// \param[in] filename Filename to read
|
||||
/// \param[in] startReadBytes What offset from the start of the file to read from
|
||||
/// \param[in] numBytesToRead How many bytes to read. This is also how many bytes have been allocated to preallocatedDestination
|
||||
/// \param[out] preallocatedDestination Write your data here
|
||||
/// \return The number of bytes read, or 0 if none
|
||||
virtual unsigned int GetFilePart( const char *filename, unsigned int startReadBytes, unsigned int numBytesToRead, void *preallocatedDestination, FileListNodeContext context);
|
||||
|
||||
/// \return Passed to FileListTransfer::Send() as the _chunkSize parameter.
|
||||
virtual const int GetIncrementalReadChunkSize(void) const;
|
||||
|
||||
st_mysql *filePartConnection;
|
||||
SimpleMutex filePartConnectionMutex;
|
||||
};
|
||||
|
||||
} // namespace SLNet
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug - Unicode|Win32">
|
||||
<Configuration>Debug - Unicode</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release - Unicode|Win32">
|
||||
<Configuration>Release - Unicode</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Retail - Unicode|Win32">
|
||||
<Configuration>Retail - Unicode</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Retail|Win32">
|
||||
<Configuration>Retail</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9092C339-3CCA-41B4-8B80-FAED313D4168}</ProjectGuid>
|
||||
<RootNamespace>AutopatcherMySQLRepository</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Retail - Unicode|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Retail - Unicode|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'">$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'">$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'">$(Configuration)\</OutDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Retail - Unicode|Win32'">$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;NDEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Retail|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;_RETAIL;NDEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;NDEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Retail - Unicode|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./../;./../../bzip2-1.0.6;./../../../Source;./../../MySQLInterface;C:\Program Files (x86)\MySQL\MySQL Server 5.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;WIN32;_RETAIL;NDEBUG;_LIB;__WIN__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
</ClCompile>
|
||||
<Lib />
|
||||
<Lib>
|
||||
<TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\ApplyPatch.cpp" />
|
||||
<ClCompile Include="AutopatcherMySQLRepository.cpp" />
|
||||
<ClCompile Include="..\..\MySQLInterface\MySQLInterface.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\ApplyPatch.h" />
|
||||
<ClInclude Include="AutopatcherMySQLRepository.h" />
|
||||
<ClInclude Include="..\..\MySQLInterface\MySQLInterface.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\ApplyPatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AutopatcherMySQLRepository.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\MySQLInterface\MySQLInterface.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\ApplyPatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AutopatcherMySQLRepository.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\MySQLInterface\MySQLInterface.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,27 @@
|
||||
#
|
||||
# This file was taken from RakNet 4.082.
|
||||
# Please see licenses/RakNet license.txt for the underlying license and related copyright.
|
||||
#
|
||||
#
|
||||
# Modified work: Copyright (c) 2017-2019, SLikeSoft UG (haftungsbeschränkt)
|
||||
#
|
||||
# This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
# license found in the license.txt file in the root directory of this source tree.
|
||||
#
|
||||
|
||||
project(AutopatcherMySQLRepository)
|
||||
FINDMYSQL()
|
||||
IF(WIN32 AND NOT UNIX)
|
||||
FILE(GLOB ALL_HEADER_SRCS *.h ${MySQLInterface_SOURCE_DIR}/MySQLInterFace.h ${Autopatcher_SOURCE_DIR}/ApplyPatch.h)
|
||||
FILE(GLOB ALL_CPP_SRCS *.cpp ${MySQLInterface_SOURCE_DIR}/MySQLInterFace.cpp ${Autopatcher_SOURCE_DIR}/ApplyPatch.cpp)
|
||||
include_directories(${SLIKENET_HEADER_FILES} ./ ${MySQLInterface_SOURCE_DIR} ${Autopatcher_SOURCE_DIR} ${MYSQL_INCLUDE_DIR} ${BZip2_SOURCE_DIR})
|
||||
add_library(AutoPatcherMySQLRepository STATIC ${ALL_CPP_SRCS} ${ALL_HEADER_SRCS})
|
||||
target_link_libraries (AutoPatcherMySQLRepository ${SLIKENET_COMMON_LIBS} ${MYSQL_LIBRARIES})
|
||||
VSUBFOLDER(AutoPatcherMySQLRepository "Samples/AutoPatcher/Server/MySQL")
|
||||
ELSE(WIN32 AND NOT UNIX)
|
||||
FILE(GLOB ALL_HEADER_SRCS *.h)
|
||||
FILE(GLOB ALL_CPP_SRCS *.cpp)
|
||||
include_directories(${SLIKENET_HEADER_FILES} ./ ${MySQLInterface_SOURCE_DIR} ${Autopatcher_SOURCE_DIR} ${MYSQL_INCLUDE_DIR})
|
||||
add_library(AutoPatcherMySQLRepository STATIC ${ALL_CPP_SRCS} ${ALL_HEADER_SRCS})
|
||||
target_link_libraries (AutoPatcherMySQLRepository ${SLIKENET_COMMON_LIBS} LibAutopatcher LibMySQLInterface ${MYSQL_LIBRARIES})
|
||||
ENDIF(WIN32 AND NOT UNIX)
|
||||
@ -0,0 +1,54 @@
|
||||
# - Find MySQL
|
||||
# Find the MySQL includes and client library
|
||||
# This module defines
|
||||
# MYSQL_INCLUDE_DIR, where to find mysql.h
|
||||
# MYSQL_LIBRARIES, the libraries needed to use MySQL.
|
||||
# MYSQL_FOUND, If false, do not try to use MySQL.
|
||||
#
|
||||
# Copyright (c) 2006, Jaroslaw Staniek, <js@iidea.pl>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
# Note: The referenced COPYING-CMAKE-SCRIPTS file was not present in the RakNet
|
||||
# repository. We also failed to get in touch with the copyright holder by mail
|
||||
# to clarify the situation. To the best of our knowledge the referenced license
|
||||
# is the Modified BSD License.
|
||||
|
||||
if(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
set(MYSQL_FOUND TRUE)
|
||||
|
||||
else(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
|
||||
find_path(MYSQL_INCLUDE_DIR mysql.h
|
||||
/usr/include/mysql
|
||||
/usr/local/include/mysql
|
||||
$ENV{ProgramFiles}/MySQL/*/include
|
||||
$ENV{SystemDrive}/MySQL/*/include
|
||||
)
|
||||
|
||||
if(WIN32 AND MSVC)
|
||||
find_library(MYSQL_LIBRARIES NAMES libmysql
|
||||
PATHS
|
||||
$ENV{ProgramFiles}/MySQL/*/lib/opt
|
||||
$ENV{SystemDrive}/MySQL/*/lib/opt
|
||||
)
|
||||
else(WIN32 AND MSVC)
|
||||
find_library(MYSQL_LIBRARIES NAMES mysqlclient
|
||||
PATHS
|
||||
/usr/lib/mysql
|
||||
/usr/local/lib/mysql
|
||||
)
|
||||
endif(WIN32 AND MSVC)
|
||||
|
||||
if(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
set(MYSQL_FOUND TRUE)
|
||||
message(STATUS "Found MySQL: ${MYSQL_INCLUDE_DIR}, ${MYSQL_LIBRARIES}")
|
||||
else(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
set(MYSQL_FOUND FALSE)
|
||||
message(STATUS "MySQL not found.")
|
||||
endif(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
|
||||
mark_as_advanced(MYSQL_INCLUDE_DIR MYSQL_LIBRARIES)
|
||||
|
||||
endif(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||
Reference in New Issue
Block a user