void FileList::ListMissingOrChangedFiles(const char *applicationDirectory, FileList *missingOrChangedFiles, bool alwaysWriteHash, bool neverWriteHash)
{
	unsigned fileLength;
//	CSHA1 sha1;
	FILE *fp;
	char fullPath[512];
	unsigned i;
//	char *fileData;

	for (i=0; i < fileList.Size(); i++)
	{
		strcpy(fullPath, applicationDirectory);
		FixEndingSlash(fullPath);
		strcat(fullPath,fileList[i].filename);
		fp=fopen(fullPath, "rb");
		if (fp==0)
		{
			missingOrChangedFiles->AddFile(fileList[i].filename, 0, 0, 0, FileListNodeContext(0,0), false);
		}
		else
		{
			fseek(fp, 0, SEEK_END);
			fileLength = ftell(fp);
			fseek(fp, 0, SEEK_SET);

			if (fileLength != fileList[i].fileLengthBytes && alwaysWriteHash==false)
			{
				missingOrChangedFiles->AddFile(fileList[i].filename, 0, 0, fileLength, FileListNodeContext(0,0), false);
			}
			else
			{

//				fileData= (char*) rakMalloc( fileLength );
//				fread(fileData, fileLength, 1, fp);

//				sha1.Reset();
//				sha1.Update( ( unsigned char* ) fileData, fileLength );
//				sha1.Final();

//				rakFree(fileData);

				unsigned int hash = SuperFastHashFilePtr(fp);
				if (RakNet::BitStream::DoEndianSwap())
					RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));

				//if (fileLength != fileList[i].fileLength || memcmp( sha1.GetHash(), fileList[i].data, HASH_LENGTH)!=0)
				if (fileLength != fileList[i].fileLengthBytes || memcmp( &hash, fileList[i].data, HASH_LENGTH)!=0)
				{
					if (neverWriteHash==false)
					//	missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)sha1.GetHash(), HASH_LENGTH, fileLength, 0);
						missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char *) &hash, HASH_LENGTH, fileLength, FileListNodeContext(0,0), false);
					else
						missingOrChangedFiles->AddFile((const char*)fileList[i].filename, 0, 0, fileLength, FileListNodeContext(0,0), false);
				}
			}
			fclose(fp);
		}
	}
}
void CClientScriptTransfer::Send(SystemAddress systemAddress)
{
	/*char file[128];
	strcpy(file, "C:\\Users\\JeNkStA\\Desktop\\jessicac.jpg");*/
	m_pNetGame->GetRakServer()->GetRakPeer()->SetSplitMessageProgressInterval(9);
	m_pNetGame->GetRakServer()->GetRakPeer()->AttachPlugin(&m_fileListTransfer);
	m_fileListTransfer.SetCallback(this);
	char szPath[MAX_PATH];
	StringList::iterator iter;
	for(iter = m_pClientScripts.begin(); iter != m_pClientScripts.end(); iter++)
	{
		sprintf(szPath, ".\\clientscripts\\%s", (char*)(*iter));
		struct stat stFileInfo;
		if(stat(szPath, &stFileInfo) == 0)
		{
			unsigned int fileLength = GetFileLength(szPath);
			m_fileList.AddFile((*iter), szPath, 0, fileLength, fileLength, FileListNodeContext(0, 0), true);
		}
		else
		{
			LogPrintf("Warning: Clientscript %s does not exist.", (char*)(*iter));
		}
	}
	m_fileListTransfer.Send(&m_fileList, m_pNetGame->GetRakServer()->GetRakPeer(), systemAddress, 0, HIGH_PRIORITY, 0, false, &m_incrementalReadInterface, 50000);
}
bool AutopatcherMySQLRepository::GetChangelistSinceDate(const char *applicationName, FileList *addedFiles, FileList *deletedFiles, const char *sinceDate, char currentDate[64])
{
	char query[512];
	if (sinceDate != 0 && strlen(sinceDate)>63)
		return false;
	RakNet::RakString escapedApplicationName = GetEscapedString(applicationName);
	RakNet::RakString escapedSinceDate = GetEscapedString(sinceDate);
	sprintf(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());

	int applicationID;
	if (!ExecuteQueryReadInt(query, &applicationID))
	{
		sprintf(lastError,"ERROR: %s not found in UpdateApplicationFiles\n",escapedApplicationName.C_String());
		return false;
	}

	if (sinceDate && sinceDate[0])
		sprintf(query,
		"SELECT filename, fileLength, contentHash, createFile, fileId FROM FileVersionHistory "
		"JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i AND modificationDate > '%s' GROUP BY fileName) MaxId "
		"ON FileVersionHistory.fileId = MaxId.maxId "
		"ORDER BY filename DESC;", applicationID,escapedSinceDate.C_String());
	else
		sprintf(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;
	if (!ExecuteBlockingCommand (query, &result))
		return false;

	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]);
			addedFiles->AddFile(hardDriveFilename, hardDriveFilename, hardDriveHash, HASH_LENGTH, fileLength, FileListNodeContext(0,0), false);
		}
		else
		{
			deletedFiles->AddFile(hardDriveFilename,hardDriveFilename,0,0,0,FileListNodeContext(0,0), false);
		}
	}
	mysql_free_result (result);

	char *localTimestamp =GetLocalTimestamp ();
	if (localTimestamp)
		strcpy(currentDate, localTimestamp);;

	return true;
}
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.SetCallback(cb);
	int prepareResult;
	my_bool falseVar=false;
	RakNet::RakString escapedApplicationName = GetEscapedString(applicationName);
	filesOnHarddrive.AddFilesFromDirectory(applicationDirectory,"", true, true, true, FileListNodeContext(0,0));
	if (filesOnHarddrive.fileList.Size()==0)
	{
		sprintf(lastError,"ERROR: Can't find files at %s in UpdateApplicationFiles\n",applicationDirectory);
		return false;
	}

	sprintf(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());
	int applicationID;

	if (!ExecuteQueryReadInt(query, &applicationID))
	{
		sprintf(lastError,"ERROR: %s not found in UpdateApplicationFiles\n",escapedApplicationName.C_String());
		return false;
	}

	if (!ExecuteBlockingCommand("BEGIN;"))
	{
		return false;
	}
	sprintf(query, "UPDATE Applications SET changeSetId = changeSetId + 1 where applicationID=%i;", applicationID);
	if (!ExecuteBlockingCommand(query))
	{
		Rollback ();
		return false;
	}
	int changeSetId = 0;
	sprintf(query, "SELECT changeSetId FROM Applications WHERE applicationID=%i;", applicationID);
	if (!ExecuteQueryReadInt(query, &changeSetId))
	{
		Rollback ();
		return false;
	}

	// +1 was added in the update
	changeSetId--;

	// Gets all newest files
	sprintf(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;
	if (!ExecuteBlockingCommand(query, &result))
	{
		Rollback();
		return false;
	}
	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);
	}    
	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(0,0), false);
		}
	}
	
	// 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(0,0), 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(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());
		
		if (!ExecuteBlockingCommand (query))
		{
			Rollback();
			deletedFiles.Clear();
			newFiles.Clear();
			return false;
		}
	}
	
	// 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( query, "SELECT fileID from FileVersionHistory WHERE applicationID=%i AND filename='%s' AND createFile=TRUE;", applicationID, GetEscapedString(hardDriveFilename).C_String() );

		MYSQL_RES * res = 0;
		if (!ExecuteBlockingCommand (query, &res))
		{
			Rollback();
			newFiles.Clear();
			return false;
		}
		
		// Create new patches for every create version
		MYSQL_ROW row;

		while ((row = mysql_fetch_row (res)) != 0)
		{
			const char * fileID = row [0];
			
			// The last query handled all the relevant comparisons
			sprintf(query, "SELECT content from FileVersionHistory WHERE fileID=%s", fileID );
			MYSQL_RES * queryResult = 0;
			if (!ExecuteBlockingCommand (query, &queryResult))
			{
				Rollback();
				newFiles.Clear();
				mysql_free_result(res);
				return false;
			}
		
			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(lastError,"CreatePatch failed.");
				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;
			}

			if (mysql_stmt_execute(stmt))
			{
				strcpy (lastError, mysql_stmt_error (stmt));
				mysql_stmt_close(stmt);
				Rollback();
				newFiles.Clear();
				mysql_free_result(res);
				mysql_free_result(queryResult);
				delete [] patch;
				return false;
			}

			mysql_stmt_close(stmt);
			delete [] patch;

			mysql_free_result(queryResult);
		}
         mysql_free_result(res);

		 stmt = mysql_stmt_init(mySqlConnection);
		 sprintf(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;
		 }

		 if (mysql_stmt_execute(stmt))
		 {
			 strcpy (lastError, mysql_stmt_error (stmt));
			 mysql_stmt_close(stmt);
			 Rollback();
			 return false;
		 }

		 mysql_stmt_close(stmt);
	}

	if (!ExecuteBlockingCommand("COMMIT;"))
	{
        Rollback ();
		return false;
	}

	return true;
}
bool AutopatcherMySQLRepository::GetPatches(const char *applicationName, FileList *input, FileList *patchList, char currentDate[64])
{
	char query[512];
	RakNet::RakString escapedApplicationName = GetEscapedString(applicationName);
	sprintf(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String());
	int applicationID;
	if (!ExecuteQueryReadInt (query, &applicationID))
	{
	    sprintf(lastError,"ERROR: %s not found in GetPatches\n",applicationName);
	    return false;
	}

	// 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(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(query, "SELECT 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;
			if (!ExecuteBlockingCommand (query, &result))
			{
				delete [] fn;
				return false;
			}

			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]); 
				patchList->AddFile(userFilename,userFilename, 0, fileLength, fileLength, FileListNodeContext(PC_WRITE_FILE,fileId), 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(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;
			if (!ExecuteBlockingCommand (query, &result))
			{
				delete [] fn;
				return false;
			}

			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(query, "SELECT patch FROM FileVersionHistory WHERE applicationId=%i AND filename='%s' AND contentHash='%s'; ", applicationID, fn, buf);
                    MYSQL_RES * patchResult = 0;
                    if (!ExecuteBlockingCommand (query, &patchResult))
					{
						delete [] fn;
                        return false;
					}

                    MYSQL_ROW 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(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);
						MYSQL_ROW 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), 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_WITH_PATCH,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;
	}

	char *localTimestamp =GetLocalTimestamp ();
	if (localTimestamp)
		strcpy(currentDate, localTimestamp);;

	return true;
}
Exemple #6
0
void FileList::GetDeltaToCurrent(FileList *input, FileList *output, const char *dirSubset, const char *remoteSubdir)
{
	// For all files in this list that do not match the input list, write them to the output list.
	// dirSubset allows checking only a portion of the files in this list.
	unsigned thisIndex, inputIndex;
	unsigned dirSubsetLen, localPathLen, remoteSubdirLen;
	bool match;
	if (dirSubset)
		dirSubsetLen = (unsigned int) strlen(dirSubset);
	else
		dirSubsetLen = 0;
	if (remoteSubdir && remoteSubdir[0])
	{
		remoteSubdirLen=(unsigned int) strlen(remoteSubdir);
		if (IsSlash(remoteSubdir[remoteSubdirLen-1]))
			remoteSubdirLen--;
	}
	else
		remoteSubdirLen=0;

	for (thisIndex=0; thisIndex < fileList.Size(); thisIndex++)
	{
		localPathLen = (unsigned int) fileList[thisIndex].filename.GetLength();
		while (localPathLen>0)
		{
			if (IsSlash(fileList[thisIndex].filename[localPathLen-1]))
			{
				localPathLen--;
				break;
			}
			localPathLen--;
		}

		// fileList[thisIndex].filename has to match dirSubset and be shorter or equal to it in length.
		if (dirSubsetLen>0 &&
			(localPathLen<dirSubsetLen ||
			_strnicmp(fileList[thisIndex].filename.C_String(), dirSubset, dirSubsetLen)!=0 ||
			(localPathLen>dirSubsetLen && IsSlash(fileList[thisIndex].filename[dirSubsetLen])==false)))
			continue;

		match=false;
		for (inputIndex=0; inputIndex < input->fileList.Size(); inputIndex++)
		{
			// If the filenames, hashes, and lengths match then skip this element in fileList.  Otherwise write it to output
			if (_stricmp(input->fileList[inputIndex].filename.C_String()+remoteSubdirLen,fileList[thisIndex].filename.C_String()+dirSubsetLen)==0)
			{
				match=true;
				if (input->fileList[inputIndex].fileLengthBytes==fileList[thisIndex].fileLengthBytes &&
					input->fileList[inputIndex].dataLengthBytes==fileList[thisIndex].dataLengthBytes &&
					memcmp(input->fileList[inputIndex].data,fileList[thisIndex].data,(size_t) fileList[thisIndex].dataLengthBytes)==0)
				{
					// File exists on both machines and is the same.
					break;
				}
				else
				{
					// File exists on both machines and is not the same.
					output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0), false);
					break;
				}
			}
		}
		if (match==false)
		{
            // Other system does not have the file at all
			output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0), false);
		}
	}
}
Exemple #7
0
int main()
{
	printf("This sample demonstrates incrementally sending a file with\n");
	printf("the FileListTransferPlugin. Incremental sends will read and send the.\n");
	printf("file only as needed, rather than putting the whole file in memory.\n");
	printf("This is to support sending large files to many users at the same time.\n");
	printf("Difficulty: Intermediate\n\n");

	TestCB testCB;
	RakNet::FileListTransfer flt1, flt2;
#ifdef USE_TCP
	RakNet::PacketizedTCP tcp1, tcp2;
	#if RAKNET_SUPPORT_IPV6==1
	const bool testInet6=true;
	#else
	const bool testInet6=false;
	#endif
	if (testInet6)
	{
		tcp1.Start(60000,1,-99999,AF_INET6);
		tcp2.Start(60001,1,-99999,AF_INET6);
		tcp2.Connect("::1",60000,false,AF_INET6);
	}
	else
	{
		tcp1.Start(60000,1,-99999,AF_INET);
		tcp2.Start(60001,1,-99999,AF_INET);
		tcp2.Connect("127.0.0.1",60000,false,AF_INET);
	}
	tcp1.AttachPlugin(&flt1);
	tcp2.AttachPlugin(&flt2);
#else
	RakNet::RakPeerInterface *peer1 = RakNet::RakPeerInterface::GetInstance();
	RakNet::RakPeerInterface *peer2 = RakNet::RakPeerInterface::GetInstance();
	RakNet::SocketDescriptor sd1(60000,0),sd2(60001,0);
	peer1->Startup(1,&sd1,1);
	peer2->Startup(1,&sd2,1);
	peer1->SetMaximumIncomingConnections(1);
	peer2->Connect("127.0.0.1",60000,0,0,0);
	peer1->AttachPlugin(&flt1);
	peer2->AttachPlugin(&flt2);
	peer1->SetSplitMessageProgressInterval(9);
	peer2->SetSplitMessageProgressInterval(9);
#endif
	// Print sending progress notifications
	flt1.AddCallback(&testFileListProgress);
	// Run incremental reads in a thread so the read does not block the main thread
	flt1.StartIncrementalReadThreads(1);
	RakNet::FileList fileList;
	RakNet::IncrementalReadInterface incrementalReadInterface;
	printf("Enter complete filename with path to test:\n");
	char str[256];
	Gets(str, sizeof(str));
	if (str[0]==0)
		strcpy(str, "D:\\RakNet\\Lib\\RakNetLibStaticDebug.lib");
	file=str;
	fileCopy=file+"_copy";
	// Reference this file, rather than add it in memory. Will send 1000 byte chunks. The reason to do this is so the whole file does not have to be in memory at once
	unsigned int fileLength = GetFileLength(file.C_String());
	if (fileLength==0)
	{
		printf("Test file %s not found.\n", file.C_String());

#ifdef USE_TCP
#else
		RakNet::RakPeerInterface::DestroyInstance(peer1);
		RakNet::RakPeerInterface::DestroyInstance(peer2);
#endif
		return 1;
	}
	fileList.AddFile(file.C_String(), file.C_String(), 0, fileLength, fileLength, FileListNodeContext(0,0), true);
	// Wait for the connection
	printf("File added.\n");
	RakSleep(100);
	RakNet::Packet *packet1, *packet2;
	while (1)
	{
#ifdef USE_TCP
		RakNet::SystemAddress sa;
		sa=tcp2.HasCompletedConnectionAttempt();
		if (sa!=RakNet::UNASSIGNED_SYSTEM_ADDRESS)
		{
			flt2.SetupReceive(&testCB, false, sa);
			break;
		}
#else
		// Wait for the connection request to be accepted
		packet2=peer2->Receive();
		if (packet2 && packet2->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
		{
			flt2.SetupReceive(&testCB, false, packet2->systemAddress);
			peer2->DeallocatePacket(packet2);
			break;
		}
		peer2->DeallocatePacket(packet2);
#endif
		RakSleep(30);
	}

	// When connected, send the file. Since the file is a reference, it will be sent incrementally
	while (1)
	{
#ifdef USE_TCP
		packet1=tcp1.Receive();
		packet2=tcp2.Receive();
		RakNet::SystemAddress sa;
		sa = tcp1.HasNewIncomingConnection();
		if (sa!=RakNet::UNASSIGNED_SYSTEM_ADDRESS)
			flt1.Send(&fileList,0,sa,0,HIGH_PRIORITY,0, &incrementalReadInterface, 2000 * 1024);
		tcp1.DeallocatePacket(packet1);
		tcp2.DeallocatePacket(packet2);
#else
		packet1=peer1->Receive();
		packet2=peer2->Receive();
		if (packet1 && packet1->data[0]==ID_NEW_INCOMING_CONNECTION)
			flt1.Send(&fileList,peer1,packet1->systemAddress,0,HIGH_PRIORITY,0, &incrementalReadInterface, 2000000);
		
		peer1->DeallocatePacket(packet1);
		peer2->DeallocatePacket(packet2);

#endif
		RakSleep(0);
	}
	
#ifdef USE_TCP
#else
	RakNet::RakPeerInterface::DestroyInstance(peer1);
	RakNet::RakPeerInterface::DestroyInstance(peer1);
#endif


	return 0;
}
Exemple #8
0
int main()
{
	printf("A C++ class used to send email, such as for servers.\n");
	printf("TLS support (such as for Gmail) requires OPEN_SSL_CLIENT_SUPPORT to be defined\nin RakNetDefines.h.\n");
	printf("Difficulty: Beginner\n\n");

    FileList fileList;
	EmailSender emailSender;
	const char *quote = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
//	const char base64Map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//	char output[1024];
//	emailSender.Base64Encoding(quote, strlen(quote), output, base64Map);
//	printf("%s", output);

	char mailServer[128], senderUsername[128], receiver[128], password[128];
	printf("Tests sending email.\n");
	printf("Enter mail server: ");
	gets(mailServer);
	if (mailServer[0]==0)
		strcpy(mailServer, "smtp.gmail.com");
	printf("Enter email account username: "******"*****@*****.**");
	printf("Enter receiver email address: ");
	gets(receiver);
	if (receiver[0]==0)
		strcpy(receiver, "*****@*****.**");
	printf("Enter password needed to send: ");
	gets(password);
	if (password[0]==0)
		strcpy(password, "jenny120");

	// http://mail.google.com/support/bin/answer.py?hl=en&answer=13287
	unsigned short hostPort;
	if (strcmp(mailServer,"smtp.gmail.com")==0)
		hostPort=465;
	else
		hostPort=25;

	fileList.AddFile("quote.txt", "quote.txt", quote, (const unsigned int) strlen(quote), (const unsigned int) strlen(quote), FileListNodeContext(0,0), false);
	const char *sendResult=emailSender.Send(mailServer,
		hostPort,
		senderUsername,
		receiver,
		senderUsername,
		receiver,
		"Test subject.",
		"Test attachment body :).\n.\n..\n.\n(Should be .,.,..,.)\r\n.\r\n.\r\n..\r\n.\r\n(Should be .,.,..,.)12345\r\n.\r\n",
		&fileList,
		true,
		password);
	if (sendResult!=0)
		printf("Send Failed! %s", sendResult);
	else
		printf("Success (probably).\n");
	printf("Press enter to quit.\n");
	char buff[256];
	gets(buff);

	return 0;
}