Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alibek Omarov
2026-05-07 13:50:55 +05:00
7 changed files with 68 additions and 42 deletions

View File

@@ -2956,12 +2956,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
if( filename[0] != '!' )
Con_Printf( "processing %s\n", filename );
if( !Q_strnicmp( filename, DEFAULT_DOWNLOADED_DIRECTORY, sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1 ))
{
// skip "downloaded/" part to avoid mismatch with needed resources list
filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
}
}
else if( !successfully_received )
{

View File

@@ -58,8 +58,8 @@ GNU General Public License for more details.
// path to saved games
#define DEFAULT_SAVE_DIRECTORY "save/"
// path to download games
#define DEFAULT_DOWNLOADED_DIRECTORY "downloaded/"
// goldsrc compatible suffix for downloads directory
#define DEFAULT_DOWNLOADED_DIRECTORY_SUFFIX "_downloads"
// path to user mod directory
#define DEFAULT_CUSTOM_DIRECTORY "custom/"

View File

@@ -101,6 +101,13 @@ static int HTTP_FileResolveNS( httpfile_t *file );
static int HTTP_FileSendRequest( httpfile_t *file );
static int HTTP_FileDecompress( httpfile_t *file );
static const char *HTTP_DownloadPath( char *buf, size_t buflen, const char *path, qboolean incomplete )
{
Q_snprintf( buf, buflen, "../%s" DEFAULT_DOWNLOADED_DIRECTORY_SUFFIX "/%s%s",
GI->gamefolder, path, incomplete ? ".incomplete" : "" );
return buf;
}
/*
==============
HTTP_FreeFile
@@ -110,7 +117,7 @@ Skip to next server/file
*/
static void HTTP_FreeFile( httpfile_t *file, qboolean error )
{
char incname[MAX_SYSPATH + 64]; // plus downloaded/ plus .incomplete
char incname[MAX_SYSPATH + 64]; // plus ../{gamedir}_downloads/ plus .incomplete
qboolean was_open = false;
file->blocktime = 0;
@@ -132,7 +139,7 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
file->socket = -1;
Q_snprintf( incname, sizeof( incname ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", file->path );
HTTP_DownloadPath( incname, sizeof( incname ), file->path, true );
if( error )
{
@@ -149,7 +156,9 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
if( http_autoremove.value == 1 ) // remove broken file
{
Con_Printf( S_ERROR "no servers to download %s\n", file->path );
FS_AllowDirectPaths( true );
FS_Delete( incname );
FS_AllowDirectPaths( false );
}
else // autoremove disabled, keep file
{
@@ -161,14 +170,18 @@ static void HTTP_FreeFile( httpfile_t *file, qboolean error )
{
if( file->compressed )
{
FS_AllowDirectPaths( true );
FS_Delete( incname );
FS_AllowDirectPaths( false );
}
else
{
// Success, rename and process file
char name[MAX_SYSPATH];
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s", file->path );
HTTP_DownloadPath( name, sizeof( name ), file->path, false );
FS_AllowDirectPaths( true );
FS_Rename( incname, name );
FS_AllowDirectPaths( false );
}
}
@@ -195,9 +208,13 @@ static int HTTP_FileQueue( httpfile_t *file )
}
Con_Reportf( "HTTP: Starting download %s from %s:%d\n", file->path, file->server->host, file->server->port );
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s.incomplete", file->path );
HTTP_DownloadPath( name, sizeof( name ), file->path, true );
if( !( file->file = FS_Open( name, "wb+", true )))
FS_AllowDirectPaths( true );
file->file = FS_Open( name, "wb+", true );
FS_AllowDirectPaths( false );
if( !file->file )
{
Con_Printf( S_ERROR "HTTP: cannot open %s!\n", name );
HTTP_FreeFile( file, true );
@@ -458,7 +475,7 @@ static int HTTP_FileDecompress( httpfile_t *file )
data_in = Mem_Malloc( host.mempool, compressed_len + 1 );
data_out = Mem_Malloc( host.mempool, decompressed_len + 1 );
Q_snprintf( name, sizeof( name ), DEFAULT_DOWNLOADED_DIRECTORY "%s", file->path );
HTTP_DownloadPath( name, sizeof( name ), file->path, false );
memset( &decompress_stream, 0, sizeof( decompress_stream ));
decompress_stream.total_in = decompress_stream.avail_in = compressed_len;
@@ -483,7 +500,9 @@ static int HTTP_FileDecompress( httpfile_t *file )
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
{
FS_AllowDirectPaths( true );
g_fsapi.WriteFile( name, data_out, decompressed_len );
FS_AllowDirectPaths( false );
HTTP_FreeFile( file, false );
}
else HTTP_FreeFile( file, true );

View File

@@ -1240,20 +1240,24 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
return false;
}
if( filename[0] != '!' )
{
string temp_filename;
Q_snprintf( temp_filename, sizeof( temp_filename ), DEFAULT_DOWNLOADED_DIRECTORY "%s", filename );
Q_strncpy( filename, temp_filename, sizeof( filename ));
}
Q_strncpy( chan->incomingfilename, filename, sizeof( chan->incomingfilename ));
if( filename[0] != '!' && FS_FileExists( filename, false ))
if( filename[0] != '!' )
{
Con_Printf( S_ERROR "can't download %s, already exists\n", filename );
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return true;
string write_path;
Q_snprintf( write_path, sizeof( write_path ), "../%s" DEFAULT_DOWNLOADED_DIRECTORY_SUFFIX "/%s", GI->gamefolder, filename );
Q_strncpy( filename, write_path, sizeof( filename ));
FS_AllowDirectPaths( true );
qboolean exists = FS_FileExists( filename, false );
FS_AllowDirectPaths( false );
if( exists )
{
Con_Printf( S_ERROR "can't download %s, already exists\n", filename );
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return true;
}
}
// create file from buffers
@@ -1339,8 +1343,9 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
}
else
{
// g-cont. it's will be stored downloaded files directly into game folder
FS_AllowDirectPaths( true );
FS_WriteFile( filename, buffer, nsize );
FS_AllowDirectPaths( false );
Mem_Free( buffer );
}

View File

@@ -58,7 +58,7 @@ static inline const char *IdToDir( char *dir, size_t size, const char *id )
if( !Q_strcmp( id, "GAMEDOWNLOAD" ))
{
Q_snprintf( dir, size, "%s/" DEFAULT_DOWNLOADED_DIRECTORY , GI->gamefolder );
Q_snprintf( dir, size, "%s" DEFAULT_DOWNLOADED_DIRECTORY_SUFFIX, GI->gamefolder );
return dir;
}

View File

@@ -292,8 +292,6 @@ static inline qboolean FS_AppendToPath( char *dst, size_t *pi, const size_t len,
qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t len, qboolean createpath )
{
const char *prev;
const char *next;
size_t i = 0;
if( !FS_AppendToPath( dst, &i, len, dir->name, path, "init" ))
@@ -303,7 +301,19 @@ qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t l
if( COM_StringEmpty( path ))
return true;
for( prev = path, next = Q_strchrnul( prev, '/' );
// we can't and shouldn't track parent directories to not track the whole filesystem
// exit early for this case
// FIXME: track the path to catch other cases
if( !Q_strncmp( path, "..", 2 ) && ( path[2] == '\0' || path[2] == '/' ))
{
if( !FS_AppendToPath( dst, &i, len, path, path, "escape to parent directory" ))
return false;
// check file existense
return createpath ? true : FS_SysFileOrFolderExists( dst );
}
for( const char *prev = path, *next = Q_strchrnul( prev, '/' );
;
prev = next + 1, next = Q_strchrnul( prev, '/' ))
{

View File

@@ -1314,7 +1314,7 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
if( isGameDir )
{
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_DOWNLOADED_DIRECTORY, dir );
Q_snprintf( buf, sizeof( buf ), "%s" DEFAULT_DOWNLOADED_DIRECTORY_SUFFIX "/", dir );
FS_AddGameDirectory( buf, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
}
Q_snprintf( buf, sizeof( buf ), "%s/", dir );
@@ -3204,16 +3204,6 @@ qboolean FS_Rename( const char *oldname, const char *newname )
if( FS_CheckNastyPath( oldname ) || FS_CheckNastyPath( newname ))
return false;
if( !fs_writepath )
return false;
if( COM_StringEmptyOrNULL( oldname ) || COM_StringEmptyOrNULL( newname ))
return false;
// no work done
if( !Q_stricmp( oldname, newname ))
return true;
// fix up slashes
Q_strncpy( oldname2, oldname, sizeof( oldname2 ));
Q_strncpy( newname2, newname, sizeof( newname2 ));
@@ -3221,6 +3211,14 @@ qboolean FS_Rename( const char *oldname, const char *newname )
COM_FixSlashes( oldname2 );
COM_FixSlashes( newname2 );
// no work done
if( !Q_stricmp( oldname2, newname2 ))
return true;
// no writing directory is set, no changes should be made
if( !fs_writepath )
return false;
// file does not exist
if( !FS_FixFileCase( fs_writepath->dir, oldname2, oldpath, sizeof( oldpath ), false ))
return false;
@@ -3256,7 +3254,7 @@ qboolean GAME_EXPORT FS_Delete( const char *path )
if( FS_CheckNastyPath( path ))
return false;
if( !fs_writepath || COM_StringEmptyOrNULL( path ))
if( !fs_writepath )
return false;
Q_strncpy( path2, path, sizeof( path2 ));