--- code/qcommon/files.c.orig	2011-12-24 12:29:32 UTC
+++ code/qcommon/files.c
@@ -195,6 +195,9 @@ static const unsigned int missionpak_checksums[] =
 	1438664554u
 };
 
+int dangerousPaksFound;
+char dangerousPakNames[MAX_ZPATH][MAX_SEARCH_PATHS];
+
 // if this is defined, the executable positively won't work with any paks other
 // than the demo pak, even if productid is present.  This is only used for our
 // last demo release to prevent the mac and linux users from using the demo
@@ -250,6 +253,7 @@ static	cvar_t		*fs_basepath;
 #endif
 
 static	cvar_t		*fs_basepath;
+static	cvar_t		*fs_libpath;
 static	cvar_t		*fs_basegame;
 static	cvar_t		*fs_gamedirvar;
 static	searchpath_t	*fs_searchpaths;
@@ -529,30 +533,32 @@ qboolean FS_CreatePath (char *OSPath) {
 
 /*
 =================
-FS_CheckFilenameIsNotExecutable
+FS_CheckFilenameIsMutable
 
-ERR_FATAL if trying to maniuplate a file with the platform library extension
+ERR_FATAL if trying to maniuplate a file with the platform library, QVM, or pk3 extension
 =================
  */
-static void FS_CheckFilenameIsNotExecutable( const char *filename,
+static void FS_CheckFilenameIsMutable( const char *filename,
 		const char *function )
 {
-	// Check if the filename ends with the library extension
-	if( !Q_stricmp( COM_GetExtension( filename ), DLL_EXT ) )
+	// Check if the filename ends with the library, QVM, or pk3 extension
+	if( COM_CompareExtension( filename, DLL_EXT )
+		|| COM_CompareExtension( filename, ".qvm" )
+		|| COM_CompareExtension( filename, ".pk3" ) )
 	{
 		Com_Error( ERR_FATAL, "%s: Not allowed to manipulate '%s' due "
-			"to %s extension\n", function, filename, DLL_EXT );
+			"to %s extension", function, filename, COM_GetExtension( filename ) );
 	}
 }
 
 /*
-===========
+=================
 FS_Remove
 
 ===========
 */
 void FS_Remove( const char *osPath ) {
-	FS_CheckFilenameIsNotExecutable( osPath, __func__ );
+	FS_CheckFilenameIsMutable( osPath, __func__ );
 
 	remove( osPath );
 }
@@ -564,7 +570,7 @@ void FS_HomeRemove( const char *homePath ) {
 ===========
 */
 void FS_HomeRemove( const char *homePath ) {
-	FS_CheckFilenameIsNotExecutable( homePath, __func__ );
+	FS_CheckFilenameIsMutable( homePath, __func__ );
 
 	remove( FS_BuildOSPath( fs_homepath->string,
 			fs_gamedir, homePath ) );
@@ -643,7 +649,7 @@ fileHandle_t FS_SV_FOpenFileWrite( const char *filenam
 		Com_Printf( "FS_SV_FOpenFileWrite: %s\n", ospath );
 	}
 
-	FS_CheckFilenameIsNotExecutable( ospath, __func__ );
+	FS_CheckFilenameIsMutable( ospath, __func__ );
 
 	if( FS_CreatePath( ospath ) ) {
 		return 0;
@@ -735,7 +741,7 @@ FS_SV_Rename
 
 ===========
 */
-void FS_SV_Rename( const char *from, const char *to ) {
+void FS_SV_Rename( const char *from, const char *to, qboolean safe ) {
 	char			*from_ospath, *to_ospath;
 
 	if ( !fs_searchpaths ) {
@@ -754,7 +760,9 @@ void FS_SV_Rename( const char *from, const char *to ) 
 		Com_Printf( "FS_SV_Rename: %s --> %s\n", from_ospath, to_ospath );
 	}
 
-	FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
+	if ( safe ) {
+		FS_CheckFilenameIsMutable( to_ospath, __func__ );
+	}
 
 	rename(from_ospath, to_ospath);
 }
@@ -784,7 +792,7 @@ void FS_Rename( const char *from, const char *to ) {
 		Com_Printf( "FS_Rename: %s --> %s\n", from_ospath, to_ospath );
 	}
 
-	FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
+	FS_CheckFilenameIsMutable( to_ospath, __func__ );
 
 	rename(from_ospath, to_ospath);
 }
@@ -843,7 +851,7 @@ fileHandle_t FS_FOpenFileWrite( const char *filename )
 		Com_Printf( "FS_FOpenFileWrite: %s\n", ospath );
 	}
 
-	FS_CheckFilenameIsNotExecutable( ospath, __func__ );
+	FS_CheckFilenameIsMutable( ospath, __func__ );
 
 	if( FS_CreatePath( ospath ) ) {
 		return 0;
@@ -891,7 +899,7 @@ fileHandle_t FS_FOpenFileAppend( const char *filename 
 		Com_Printf( "FS_FOpenFileAppend: %s\n", ospath );
 	}
 
-	FS_CheckFilenameIsNotExecutable( ospath, __func__ );
+	FS_CheckFilenameIsMutable( ospath, __func__ );
 
 	if( FS_CreatePath( ospath ) ) {
 		return 0;
@@ -963,6 +971,7 @@ int FS_FOpenFileRead( const char *filename, fileHandle
 	FILE			*temp;
 	int				l;
 	char demoExt[16];
+	qboolean isLocalConfig, isQVM;
 
 	hash = 0;
 
@@ -970,11 +979,22 @@ int FS_FOpenFileRead( const char *filename, fileHandle
 		Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
 	}
 
+	isLocalConfig = !Q_stricmp(filename, "autoexec.cfg") || !Q_stricmp(filename, "q3config.cfg");
+	isQVM = COM_CompareExtension(filename, ".qvm");
+
 	if ( file == NULL ) {
 		// just wants to see if file is there
 		for ( search = fs_searchpaths ; search ; search = search->next ) {
 			//
 			if ( search->pack ) {
+				// autoexec.cfg and q3config.cfg can only be loaded outside of pk3 files.
+				if (isLocalConfig)
+					continue;
+
+				// QVMs can't be loaded from pk3 in the "download" directory
+				if (isQVM && !Q_stricmp(search->pack->pakGamename, "download"))
+					continue;
+
 				hash = FS_HashFileName(filename, search->pack->hashSize);
 			}
 			// is the element a pak file?
@@ -1040,6 +1060,14 @@ int FS_FOpenFileRead( const char *filename, fileHandle
 	for ( search = fs_searchpaths ; search ; search = search->next ) {
 		//
 		if ( search->pack ) {
+			// autoexec.cfg and q3config.cfg can only be loaded outside of pk3 files.
+			if (isLocalConfig)
+				continue;
+
+			// QVMs can't be loaded from pk3 in the "download" directory
+			if (isQVM && !Q_stricmp(search->pack->pakGamename, "download"))
+				continue;
+
 			hash = FS_HashFileName(filename, search->pack->hashSize);
 		}
 		// is the element a pak file?
@@ -1657,7 +1685,7 @@ of a zip file.
 of a zip file.
 =================
 */
-static pack_t *FS_LoadZipFile(const char *zipfile, const char *basename)
+static pack_t *FS_LoadZipFile(const char *zipfile, const char *basename, const char *gamename )
 {
 	fileInPack_t	*buildBuffer;
 	pack_t			*pack;
@@ -1666,11 +1694,12 @@ static pack_t *FS_LoadZipFile(const char *zipfile, con
 	unz_global_info gi;
 	char			filename_inzip[MAX_ZPATH];
 	unz_file_info	file_info;
-	int				i, len;
+	int				i, j, len;
 	long			hash;
 	int				fs_numHeaderLongs;
 	int				*fs_headerLongs;
 	char			*namePtr;
+	qboolean		alreadydangerous = qfalse;
 
 	fs_numHeaderLongs = 0;
 
@@ -1714,6 +1743,7 @@ static pack_t *FS_LoadZipFile(const char *zipfile, con
 
 	Q_strncpyz( pack->pakFilename, zipfile, sizeof( pack->pakFilename ) );
 	Q_strncpyz( pack->pakBasename, basename, sizeof( pack->pakBasename ) );
+	Q_strncpyz( pack->pakGamename, gamename, sizeof( pack->pakGamename ) );
 
 	// strip .pk3 if needed
 	if ( strlen( pack->pakBasename ) > 4 && !Q_stricmp( pack->pakBasename + strlen( pack->pakBasename ) - 4, ".pk3" ) ) {
@@ -1730,6 +1760,30 @@ static pack_t *FS_LoadZipFile(const char *zipfile, con
 		if (err != UNZ_OK) {
 			break;
 		}
+
+		if (!Q_stricmp(pack->pakGamename, "download") && (
+				COM_CompareExtension(filename_inzip, ".qvm") ||
+				!Q_stricmp(filename_inzip, "autoexec.cfg") ||
+				!Q_stricmp(filename_inzip, "q3config.cfg")))
+		{
+
+			for (j = 0; j < dangerousPaksFound; j++) {
+				if (!strcmp(dangerousPakNames[j], pack->pakBasename)) {
+					alreadydangerous = qtrue;
+					break;
+				}
+			}
+
+			if (!alreadydangerous) {
+				Q_strncpyz(dangerousPakNames[dangerousPaksFound], pack->pakBasename, MAX_ZPATH);
+				dangerousPaksFound++;
+			}
+
+			Com_Printf(S_COLOR_RED "Dangerous file %s found in %s\n",
+					filename_inzip,
+					pack->pakFilename);
+		}
+
 		if (file_info.uncompressed_size > 0) {
 			fs_headerLongs[fs_numHeaderLongs++] = LittleLong(file_info.crc);
 		}
@@ -1784,7 +1838,7 @@ qboolean FS_CompareZipChecksum(const char *zipfile)
 	pack_t *thepak;
 	int index, checksum;
 	
-	thepak = FS_LoadZipFile(zipfile, "");
+	thepak = FS_LoadZipFile(zipfile, "", "");
 	
 	if(!thepak)
 		return qfalse;
@@ -2569,10 +2623,8 @@ void FS_AddGameDirectory( const char *path, const char
 
 	for ( i = 0 ; i < numfiles ; i++ ) {
 		pakfile = FS_BuildOSPath( path, dir, pakfiles[i] );
-		if ( ( pak = FS_LoadZipFile( pakfile, pakfiles[i] ) ) == 0 )
+		if ( ( pak = FS_LoadZipFile( pakfile, pakfiles[i], dir ) ) == 0 )
 			continue;
-		// store the game name for downloading
-		strcpy(pak->pakGamename, dir);
 		
 		fs_packFiles += pak->numfiles;
 
@@ -2854,11 +2906,14 @@ static void FS_Startup( const char *gameName )
 
 	Com_Printf( "----- FS_Startup -----\n" );
 
+	dangerousPaksFound = 0;
+
 	fs_packFiles = 0;
 
 	fs_debug = Cvar_Get( "fs_debug", "0", 0 );
 	fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
 	fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
+	fs_libpath = Cvar_Get ("fs_libpath", Sys_DefaultLibPath(), CVAR_INIT );
 	homePath = Sys_DefaultHomePath();
 	if (!homePath || !homePath[0]) {
 		homePath = fs_basepath->string;
@@ -2878,6 +2933,11 @@ static void FS_Startup( const char *gameName )
 	if (fs_apppath->string[0])
 		FS_AddGameDirectory(fs_apppath->string, gameName);
 	#endif
+
+	// Search default library location if given
+	if (fs_libpath->string[0]) {
+		FS_AddGameDirectory ( fs_libpath->string, gameName );
+	}
 	
 	// NOTE: same filtering below for mods and basegame
 	if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) {
