Exemplo n.º 1
0
int Web_Get( const char *url, const char *referer, const char *name, int resume, int max_downloading_time, int timeout, int ( *_progress )(double), int noreuse )
{
	CURLcode code;
	int fsize;

	// init/reinit curl
	Web_Init();

	code = curl_easy_setopt( curl, CURLOPT_URL, url );
	if( code != CURLE_OK )
	{
		Com_Printf( "Failed to set url\n" );;
		return 0;
	}

	if( referer )
	{
		code = curl_easy_setopt( curl, CURLOPT_REFERER, referer );
		if( code != CURLE_OK )
		{
			Com_Printf( "Failed to set Referer\n" );
			return 0;
		}
	}

	// connection timeout
	code = curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT, timeout );
	if( code != CURLE_OK )
	{
		Com_Printf( "Failed to set libcurl connection timeout\n" );
		return 0;
	}

	code = curl_easy_setopt( curl, CURLOPT_TIMEOUT, max_downloading_time );
	if( code != CURLE_OK )
	{
		Com_Printf( "Failed to set libcurl global timeout\n" );
		return 0;
	}

	if( noreuse )
	{
		code = curl_easy_setopt( curl, CURLOPT_FORBID_REUSE, 1 );
		if( code != CURLE_OK )
		{
			Com_Printf( "Failed to forbid reuse\n" );
			return 0;
		}
	}

	if( resume == 1 )
	{
		// test if file exist
		fsize = FS_FOpenAbsoluteFile( name, NULL, FS_READ );
		if( fsize < 0 )
			goto new_file; // file does not exist

		code = curl_easy_setopt( curl, CURLOPT_RESUME_FROM, fsize );
		if( code != CURLE_OK )
		{
			Com_Printf( "Failed to set file resume from length\n" );
			return 0;
		}
	}
	else
	{
		// we will append to the file so if it already exist we will have twice the data
		// so delete the file if it exist
		FS_RemoveAbsoluteFile( name );
	}

new_file:

	code = curl_easy_setopt( curl, CURLOPT_WRITEDATA, name );
	if( code != CURLE_OK )
	{
		Com_Printf( "Failed to set writer data\n" );
		return 0;
	}

	Com_DPrintf( "Downloading %s from %s\n", name, url );

	// set callback
	progress = _progress;
	code = curl_easy_perform( curl );
	if( code != CURLE_OK )
	{
		Com_Printf( "Failed to download %s from %s\n", name, url );
		Com_Printf( "Error: %s\n", curl_err );

		Web_Cleanup();
		return 0;
	}

	Web_Cleanup();
	return 1;
}
Exemplo n.º 2
0
/*
* SV_WebDownload
*/
static qboolean SV_WebDownload( const char *baseUrl, const char *filepath, qboolean overwrite, qboolean silent )
{
	qboolean success;
	int alloc_size;
	char *temppath, *writepath, *url;

	if( developer->integer )
		silent = qfalse;

	if( !baseUrl || !baseUrl[0] || !filepath )
		return qfalse;

	if( !strrchr( baseUrl, '/' ) )
	{
		if( !silent )
			Com_Printf( "SV_WebDownload: Invalid URL\n" );
		return qfalse;
	}

	if( filepath[0] == '/' ) // filepath should never begin with a slash
		filepath++;

	if( !COM_ValidateRelativeFilename( filepath ) )
	{
		if( !silent )
			Com_Printf( "SV_WebDownload: Invalid filename\n" );
		return qfalse;
	}

	if( !COM_FileExtension( filepath ) )
	{
		if( !silent )
			Com_Printf( "SV_WebDownload: no file extension\n" );
		return qfalse;
	}

	// full url (baseurl + path)
	alloc_size = strlen( baseUrl ) + 1 + strlen( filepath ) + 1;
	url = Mem_TempMalloc( alloc_size );
	if( baseUrl[ strlen( baseUrl ) - 1 ] == '/' ) // url includes last slash
		Q_snprintfz( url, alloc_size, "%s%s", baseUrl, filepath );
	else
		Q_snprintfz( url, alloc_size, "%s/%s", baseUrl, filepath );

	// add .tmp (relative + .tmp)
	alloc_size = strlen( filepath ) + strlen( ".tmp" ) + 1;
	temppath = Mem_TempMalloc( alloc_size );
	Q_snprintfz( temppath, alloc_size, "%s.tmp", filepath );

	// full write path for curl
	alloc_size = strlen( FS_WriteDirectory() ) + 1 + strlen( temppath ) + 1;
	writepath = Mem_TempMalloc( alloc_size );
	Q_snprintfz( writepath, alloc_size, "%s/%s", FS_WriteDirectory(), temppath );

	webDownloadPercentPrint = 0;
	webDownloadPercentStarted = qfalse;

	success = Web_Get( url, NULL, writepath, qtrue, 60 * 30, 60, SV_WebDownloadProgress, qfalse );

	if( webDownloadPercentStarted )
		Com_Printf( "\n" );

	if( !success )
	{
		if( !silent )
			Com_Printf( "Failed to download remote file.\n" );
		goto failed;
	}

	// rename the downloaded file
	if( !FS_MoveBaseFile( temppath, filepath ) )
	{
		if( !overwrite )
		{
			if( !silent )
				Com_Printf( "Failed to rename temporary file.\n" );
			goto failed;
		}

		// check if it failed because there already exists a file with the same name
		// and in this case remove this file
		if( FS_FOpenBaseFile( filepath, NULL, FS_READ ) != -1 )
		{
			char *backfile;

			alloc_size = strlen( filepath ) + strlen( ".bak" ) + 1;
			backfile = Mem_TempMalloc( alloc_size );
			Q_snprintfz( backfile, alloc_size, "%s.bak", filepath );

			// if there is already a .bak file, destroy it
			if( FS_FOpenBaseFile( backfile, NULL, FS_READ ) != -1 )
				FS_RemoveBaseFile( backfile );

			// move the current file into .bak file
			if( !FS_MoveBaseFile( filepath, backfile ) )
			{
				Mem_TempFree( backfile );
				if( !silent )
					Com_Printf( "Failed to backup destination file.\n" );
				goto failed;
			}

			// now try renaming the downloaded file again
			if( !FS_MoveBaseFile( temppath, filepath ) )
			{
				// didn't work, so restore the backup file
				if( FS_MoveBaseFile( backfile, filepath ) )
				{
					if( !silent )
						Com_Printf( "Failed to rename temporary file, restoring from backup.\n" );
				}
				else
				{
					if( !silent )
						Com_Printf( "Failed to rename temporary file and restore from backup.\n" );
				}

				Mem_TempFree( backfile );
				goto failed;
			}

			Mem_TempFree( backfile );
		}
	}

	Mem_TempFree( temppath );
	Mem_TempFree( writepath );
	Mem_TempFree( url );

	return qtrue;

failed:
	if( !silent )
		Com_Printf( "Removing temporary file: %s\n", writepath );
	FS_RemoveAbsoluteFile( writepath );
	Mem_TempFree( temppath );
	Mem_TempFree( writepath );
	Mem_TempFree( url );

	return qfalse;
}
Exemplo n.º 3
0
/*
* Com_UnloadGameLibrary
*/
void Com_UnloadGameLibrary( void **handle )
{
	gamelib_t *gamelib, *iter, *prev;

	assert( handle );

	if( !handle )
		return;

	gamelib = (gamelib_t *)*handle;
	if( !gamelib )
		return;

	// remove it from the linked list
	if( gamelib == gamelibs )
	{
		gamelibs = gamelib->next;
	}
	else
	{
		prev = NULL;
		iter = gamelibs;
		while( iter )
		{
			if( iter == gamelib )
			{
				assert( prev );
				prev->next = iter->next;
			}
			prev = iter;
			iter = iter->next;
		}
	}

	// close lib, if not statically linked
	if( gamelib->lib )
	{
		if( !Sys_Library_Close( gamelib->lib ) )
			Com_Error( ERR_FATAL, "Sys_CloseLibrary failed" );
		gamelib->lib = NULL;
	}

	// remove tempfile if it's not used by other instances
	if( gamelib->fullname )
	{
		iter = gamelibs;
		while( iter )
		{
			if( !strcmp( gamelib->fullname, iter->fullname ) )
				break;
			iter = iter->next;
		}

		if( !iter )
		{
			char *p;

			FS_RemoveAbsoluteFile( gamelib->fullname );
			p = strrchr( gamelib->fullname, '/' );
			if( p )
			{
				*p = '\0';
				FS_RemoveAbsoluteDirectory( gamelib->fullname );
			}
		}

		Mem_ZoneFree( gamelib->fullname );
	}

	Mem_ZoneFree( gamelib );

	*handle = NULL;
}