2005-04-16 16:22:17 +00:00
# include "quakedef.h"
2005-12-22 02:29:11 +00:00
2014-09-08 23:47:19 +00:00
# if defined(WEBCLIENT) && !defined(NOBUILTINMENUS)
2006-01-21 00:06:49 +00:00
# define DOWNLOADMENU
2005-12-22 02:29:11 +00:00
# endif
# ifdef DOWNLOADMENU
2005-04-16 16:22:17 +00:00
2016-07-26 11:47:59 +00:00
//whole load of extra args for the downloads menu (for the downloads menu to handle engine updates).
# ifdef VKQUAKE
# define PHPVK "&vk=1"
# else
# define PHPVK
# endif
# ifdef GLQUAKE
# define PHPGL "&gl=1"
# else
# define PHPGL
# endif
# ifdef D3DQUAKE
# define PHPD3D "&d3d=1"
# else
# define PHPD3D
# endif
# ifdef MINIMAL
# define PHPMIN "&min=1"
# else
# define PHPMIN
# endif
# ifdef NOLEGACY
# define PHPLEG "&leg=0"
# else
# define PHPLEG "&leg=1"
# endif
# if defined(_DEBUG) || defined(DEBUG)
# define PHPDBG "&dbg=1"
# else
# define PHPDBG
# endif
# ifndef SVNREVISION
# define SVNREVISION -
# endif
# define DOWNLOADABLESARGS "?ver=" STRINGIFY(SVNREVISION) PHPVK PHPGL PHPD3D PHPMIN PHPLEG PHPDBG
2016-07-21 19:36:34 +00:00
extern cvar_t fs_downloads_url ;
2005-04-16 16:22:17 +00:00
# define INSTALLEDFILES "installed.lst" //the file that resides in the quakedir (saying what's installed).
2016-07-21 19:36:34 +00:00
# define DPF_HAVEAVERSION 1 //any old version
# define DPF_WANTTOINSTALL 2 //user selected it
# define DPF_DISPLAYVERSION 4 //some sort of conflict, the package is listed twice, so show versions so the user knows what's old.
# define DPF_FORGETONUNINSTALL 8 //for previously installed packages, remove them from the list if there's no current version any more (should really be automatic if there's no known mirrors)
# define DPF_UNKNOWNVERSION 16 //we have a file with this name already, with no idea where it came from.
2016-07-26 11:47:59 +00:00
# define DPF_HIDDEN 32 //wrong arch, file conflicts, etc. still listed if actually installed.
2005-10-16 12:53:42 +00:00
2013-03-12 23:03:04 +00:00
void CL_StartCinematicOrMenu ( void ) ;
2005-10-16 12:53:42 +00:00
//note: these are allocated for the life of the exe
2016-07-21 19:36:34 +00:00
static char * downloadablelist [ 32 ] ;
static char * downloadablelistnameprefix [ countof ( downloadablelist ) ] ;
static char downloadablelistreceived [ countof ( downloadablelist ) ] ; //well
static int numdownloadablelists = 0 ;
2005-04-16 16:22:17 +00:00
2016-07-26 11:47:59 +00:00
# define THISARCH PLATFORM "_" ARCH_CPU_POSTFIX
2005-04-16 16:22:17 +00:00
typedef struct package_s {
char fullname [ 256 ] ;
char * name ;
2016-07-26 11:47:59 +00:00
struct package_s * override ; //the package that obscures this one (later version, or whatever)
2016-07-21 19:36:34 +00:00
unsigned int trymirrors ;
char * mirror [ 8 ] ;
2005-10-14 18:28:44 +00:00
char gamedir [ 16 ] ;
2016-07-21 19:36:34 +00:00
enum fs_relative fsroot ;
char version [ 16 ] ;
2016-07-26 11:47:59 +00:00
char * arch ;
enum
{
EXTRACT_COPY , //just copy the download over
EXTRACT_XZ , //give the download code a write filter so that it automatically decompresses on the fly
EXTRACT_GZ , //give the download code a write filter so that it automatically decompresses on the fly
EXTRACT_ZIP //extract stuff once it completes. kinda sucky.
} extract ;
2016-07-21 19:36:34 +00:00
struct packagedep_s
{
struct packagedep_s * next ;
enum
{
DEP_CONFLICT ,
2016-07-26 11:47:59 +00:00
DEP_FILECONFLICT , //don't install if this file already exists.
2016-07-21 19:36:34 +00:00
DEP_REQUIRE ,
DEP_RECOMMEND , //like depend, but uninstalling will not bubble.
2016-07-26 11:47:59 +00:00
DEP_FILE
2016-07-21 19:36:34 +00:00
} dtype ;
char name [ 1 ] ;
} * deps ;
2005-10-16 12:53:42 +00:00
2016-07-21 19:36:34 +00:00
struct dl_download * download ;
2005-10-16 12:53:42 +00:00
2005-04-16 16:22:17 +00:00
int flags ;
struct package_s * next ;
} package_t ;
typedef struct {
menucustom_t * list ;
2005-04-18 03:21:16 +00:00
char intermediatefilename [ MAX_QPATH ] ;
2006-01-28 06:41:20 +00:00
char pathprefix [ MAX_QPATH ] ;
2005-04-16 16:22:17 +00:00
int parsedsourcenum ;
2006-01-28 06:41:20 +00:00
qboolean populated ;
2005-04-16 16:22:17 +00:00
} dlmenu_t ;
2016-07-21 19:36:34 +00:00
static package_t * availablepackages ;
static int numpackages ;
# ifdef HAVEAUTOUPDATE
static int autoupdatesetting = - 1 ;
# endif
2005-04-16 16:22:17 +00:00
2016-07-26 11:47:59 +00:00
static qboolean MD_CheckFile ( const char * filename , enum fs_relative base )
{
vfsfile_t * f = FS_OpenVFS ( filename , " rb " , base ) ;
if ( f )
{
VFS_CLOSE ( f ) ;
return true ;
}
return false ;
}
void MD_AddDep ( package_t * p , int deptype , const char * depname )
{
struct packagedep_s * nd , * * link ;
//no dupes.
for ( link = & p - > deps ; ( nd = * link ) ; link = & nd - > next )
{
if ( nd - > dtype = = deptype & & ! strcmp ( nd - > name , depname ) )
return ;
}
//add it on the end, preserving order.
nd = Z_Malloc ( sizeof ( * nd ) + strlen ( depname ) ) ;
nd - > dtype = deptype ;
strcpy ( nd - > name , depname ) ;
nd - > next = * link ;
* link = nd ;
}
2016-07-21 19:36:34 +00:00
static void M_DL_AddSubList ( const char * url , const char * prefix )
{
int i ;
for ( i = 0 ; i < numdownloadablelists ; i + + )
{
if ( ! strcmp ( downloadablelist [ i ] , url ) )
break ;
}
if ( i = = numdownloadablelists & & i < countof ( downloadablelist ) )
{
downloadablelist [ i ] = BZ_Malloc ( strlen ( url ) + 1 ) ;
strcpy ( downloadablelist [ i ] , url ) ;
downloadablelistnameprefix [ i ] = BZ_Malloc ( strlen ( prefix ) + 1 ) ;
strcpy ( downloadablelistnameprefix [ i ] , prefix ) ;
numdownloadablelists + + ;
}
}
static package_t * BuildPackageList ( vfsfile_t * f , int flags , const char * url , const char * prefix )
2005-04-16 16:22:17 +00:00
{
char line [ 1024 ] ;
2016-07-21 19:36:34 +00:00
package_t * p , * o ;
2005-04-16 16:22:17 +00:00
package_t * first = NULL ;
2016-07-26 11:47:59 +00:00
struct packagedep_s * dep ;
2005-04-16 16:22:17 +00:00
char * sl ;
2016-07-21 19:36:34 +00:00
vfsfile_t * pf ;
2005-04-16 16:22:17 +00:00
2005-10-14 18:28:44 +00:00
int version ;
2016-07-21 19:36:34 +00:00
char defaultgamedir [ 64 ] ;
char mirror [ countof ( p - > mirror ) ] [ MAX_OSPATH ] ;
int nummirrors = 0 ;
int argc ;
2005-10-14 18:28:44 +00:00
2013-06-24 09:04:00 +00:00
if ( ! f )
return NULL ;
2016-07-21 19:36:34 +00:00
Q_strncpyz ( defaultgamedir , FS_GetGamedir ( false ) , sizeof ( defaultgamedir ) ) ;
if ( url )
{
Q_strncpyz ( mirror [ nummirrors ] , url , sizeof ( mirror [ nummirrors ] ) ) ;
sl = COM_SkipPath ( mirror [ nummirrors ] ) ;
* sl = 0 ;
nummirrors + + ;
}
2005-04-16 16:22:17 +00:00
do
{
2005-12-22 02:29:11 +00:00
if ( ! VFS_GETS ( f , line , sizeof ( line ) - 1 ) )
break ;
2005-04-16 16:22:17 +00:00
while ( ( sl = strchr ( line , ' \n ' ) ) )
* sl = ' \0 ' ;
while ( ( sl = strchr ( line , ' \r ' ) ) )
* sl = ' \0 ' ;
Cmd_TokenizeString ( line , false , false ) ;
2005-12-22 02:29:11 +00:00
} while ( ! Cmd_Argc ( ) ) ;
2005-04-16 16:22:17 +00:00
if ( strcmp ( Cmd_Argv ( 0 ) , " version " ) )
return NULL ; //it's not the right format.
2005-10-14 18:28:44 +00:00
version = atoi ( Cmd_Argv ( 1 ) ) ;
2016-07-21 19:36:34 +00:00
if ( version ! = 0 & & version ! = 1 & & version ! = 2 )
2005-10-14 18:28:44 +00:00
{
2007-10-05 18:08:47 +00:00
Con_Printf ( " Packagelist is of a future or incompatible version \n " ) ;
2005-04-16 16:22:17 +00:00
return NULL ; //it's not the right version.
2005-10-14 18:28:44 +00:00
}
2005-04-16 16:22:17 +00:00
2005-12-22 02:29:11 +00:00
while ( 1 )
2005-04-16 16:22:17 +00:00
{
2005-12-22 02:29:11 +00:00
if ( ! VFS_GETS ( f , line , sizeof ( line ) - 1 ) )
2005-04-16 16:22:17 +00:00
break ;
while ( ( sl = strchr ( line , ' \n ' ) ) )
* sl = ' \0 ' ;
while ( ( sl = strchr ( line , ' \r ' ) ) )
* sl = ' \0 ' ;
Cmd_TokenizeString ( line , false , false ) ;
2016-07-21 19:36:34 +00:00
argc = Cmd_Argc ( ) ;
if ( argc )
2005-04-16 16:22:17 +00:00
{
2005-10-14 18:28:44 +00:00
if ( ! strcmp ( Cmd_Argv ( 0 ) , " sublist " ) )
2005-04-16 16:22:17 +00:00
{
2016-07-21 19:36:34 +00:00
char * subprefix ;
if ( * prefix )
subprefix = va ( " %s/%s " , prefix , Cmd_Argv ( 2 ) ) ;
else
subprefix = Cmd_Argv ( 2 ) ;
M_DL_AddSubList ( Cmd_Argv ( 1 ) , subprefix ) ;
continue ;
}
if ( ! strcmp ( Cmd_Argv ( 0 ) , " set " ) )
{
if ( ! strcmp ( Cmd_Argv ( 1 ) , " gamedir " ) )
{
if ( argc = = 2 )
Q_strncpyz ( defaultgamedir , FS_GetGamedir ( false ) , sizeof ( defaultgamedir ) ) ;
else
Q_strncpyz ( defaultgamedir , Cmd_Argv ( 2 ) , sizeof ( defaultgamedir ) ) ;
}
else if ( ! strcmp ( Cmd_Argv ( 1 ) , " mirrors " ) )
{
nummirrors = 0 ;
while ( nummirrors < countof ( mirror ) & & 2 + nummirrors < argc )
{
Q_strncpyz ( mirror [ nummirrors ] , Cmd_Argv ( 2 + nummirrors ) , sizeof ( mirror [ nummirrors ] ) ) ;
if ( ! * mirror [ nummirrors ] )
break ;
nummirrors + + ;
}
}
else
{
//erk
}
continue ;
}
if ( version = = 2 )
{
char * fullname = Cmd_Argv ( 0 ) ;
char * file = NULL ;
char * url = NULL ;
char * gamedir = NULL ;
char * ver = NULL ;
2016-07-26 11:47:59 +00:00
int extract = EXTRACT_COPY ;
2005-10-14 18:28:44 +00:00
int i ;
2016-07-26 11:47:59 +00:00
p = Z_Malloc ( sizeof ( * p ) ) ;
2016-07-21 19:36:34 +00:00
for ( i = 1 ; i < argc ; i + + )
2005-04-16 16:22:17 +00:00
{
2016-07-21 19:36:34 +00:00
char * arg = Cmd_Argv ( i ) ;
2016-07-26 11:47:59 +00:00
if ( ! strncmp ( arg , " url= " , 4 ) )
2016-07-21 19:36:34 +00:00
url = arg + 4 ;
else if ( ! strncmp ( arg , " gamedir= " , 8 ) )
gamedir = arg + 8 ;
else if ( ! strncmp ( arg , " ver= " , 4 ) )
ver = arg + 4 ;
else if ( ! strncmp ( arg , " v= " , 2 ) )
ver = arg + 2 ;
2016-07-26 11:47:59 +00:00
else if ( ! strncmp ( arg , " arch= " , 5 ) )
/*arch = arg+5*/ ;
else if ( ! strncmp ( arg , " file= " , 5 ) )
{
if ( ! file )
file = arg + 5 ;
MD_AddDep ( p , DEP_FILE , arg + 5 ) ;
}
2016-07-21 19:36:34 +00:00
else if ( ! strncmp ( arg , " extract= " , 8 ) )
{
if ( ! strcmp ( arg + 8 , " xz " ) )
2016-07-26 11:47:59 +00:00
extract = EXTRACT_XZ ;
2016-07-21 19:36:34 +00:00
else if ( ! strcmp ( arg + 8 , " gz " ) )
2016-07-26 11:47:59 +00:00
extract = EXTRACT_GZ ;
else if ( ! strcmp ( arg + 8 , " zip " ) )
extract = EXTRACT_ZIP ;
2016-07-21 19:36:34 +00:00
else
Con_Printf ( " Unknown decompression method: %s \n " , arg + 8 ) ;
}
else if ( ! strncmp ( arg , " depend= " , 7 ) )
2016-07-26 11:47:59 +00:00
MD_AddDep ( p , DEP_REQUIRE , arg + 7 ) ;
2016-07-21 19:36:34 +00:00
else if ( ! strncmp ( arg , " conflict= " , 9 ) )
2016-07-26 11:47:59 +00:00
MD_AddDep ( p , DEP_CONFLICT , arg + 9 ) ;
else if ( ! strncmp ( arg , " fileconflict= " , 13 ) )
MD_AddDep ( p , DEP_FILECONFLICT , arg + 13 ) ;
2016-07-21 19:36:34 +00:00
else if ( ! strncmp ( arg , " recommend= " , 10 ) )
2016-07-26 11:47:59 +00:00
MD_AddDep ( p , DEP_RECOMMEND , arg + 10 ) ;
else
2016-07-21 19:36:34 +00:00
{
2016-07-26 11:47:59 +00:00
Con_DPrintf ( " Unknown package property \n " ) ;
2016-07-21 19:36:34 +00:00
}
2005-10-14 18:28:44 +00:00
}
2005-10-16 12:53:42 +00:00
2016-07-21 19:36:34 +00:00
if ( * prefix )
2016-07-28 15:57:22 +00:00
Q_snprintfz ( p - > fullname , sizeof ( p - > fullname ) , " %s/%s " , prefix , fullname ) ;
2016-07-21 19:36:34 +00:00
else
2016-07-28 15:57:22 +00:00
Q_snprintfz ( p - > fullname , sizeof ( p - > fullname ) , " %s " , fullname ) ;
2016-07-21 19:36:34 +00:00
p - > name = COM_SkipPath ( p - > fullname ) ;
if ( ! gamedir )
gamedir = defaultgamedir ;
2005-10-16 12:53:42 +00:00
2016-07-21 19:36:34 +00:00
Q_strncpyz ( p - > version , ver ? ver : " " , sizeof ( p - > version ) ) ;
2006-01-28 06:41:20 +00:00
2016-07-21 19:36:34 +00:00
Q_snprintfz ( p - > gamedir , sizeof ( p - > gamedir ) , " %s " , gamedir ) ;
p - > fsroot = FS_ROOT ;
p - > extract = extract ;
if ( url & & ( ! strncmp ( url , " http:// " , 7 ) | | ! strncmp ( url , " https:// " , 8 ) ) )
p - > mirror [ 0 ] = Z_StrDup ( url ) ;
else
{
int m ;
char * ext = " " ;
if ( ! url )
{
2016-07-26 11:47:59 +00:00
if ( extract = = EXTRACT_XZ )
2016-07-21 19:36:34 +00:00
ext = " .xz " ;
2016-07-26 11:47:59 +00:00
else if ( extract = = EXTRACT_GZ )
2016-07-21 19:36:34 +00:00
ext = " .gz " ;
2016-07-26 11:47:59 +00:00
else if ( extract = = EXTRACT_ZIP )
ext = " .zip " ;
2016-07-21 19:36:34 +00:00
url = file ;
}
for ( m = 0 ; m < nummirrors ; m + + )
p - > mirror [ m ] = Z_StrDup ( va ( " %s%s%s " , mirror [ m ] , url , ext ) ) ;
2005-04-16 16:22:17 +00:00
}
2005-10-14 18:28:44 +00:00
}
2016-07-21 19:36:34 +00:00
else
2005-10-14 18:28:44 +00:00
{
2016-07-21 19:36:34 +00:00
if ( argc > 5 | | argc < 3 )
{
Con_Printf ( " Package list is bad - %s \n " , line ) ;
continue ; //but try the next line away
}
p = Z_Malloc ( sizeof ( * p ) ) ;
if ( * prefix )
Q_strncpyz ( p - > fullname , va ( " %s/%s " , prefix , Cmd_Argv ( 0 ) ) , sizeof ( p - > fullname ) ) ;
else
Q_strncpyz ( p - > fullname , Cmd_Argv ( 0 ) , sizeof ( p - > fullname ) ) ;
p - > name = p - > fullname ;
while ( ( sl = strchr ( p - > name , ' / ' ) ) )
p - > name = sl + 1 ;
p - > mirror [ 0 ] = Z_StrDup ( Cmd_Argv ( 1 ) ) ;
2016-07-26 11:47:59 +00:00
MD_AddDep ( p , DEP_FILE , Cmd_Argv ( 2 ) ) ;
2016-07-21 19:36:34 +00:00
Q_strncpyz ( p - > version , Cmd_Argv ( 3 ) , sizeof ( p - > version ) ) ;
Q_strncpyz ( p - > gamedir , Cmd_Argv ( 4 ) , sizeof ( p - > gamedir ) ) ;
if ( ! strcmp ( p - > gamedir , " ../ " ) )
{
p - > fsroot = FS_ROOT ;
* p - > gamedir = 0 ;
}
else
{
if ( ! * p - > gamedir )
{
strcpy ( p - > gamedir , FS_GetGamedir ( false ) ) ;
// p->fsroot = FS_GAMEONLY;
}
p - > fsroot = FS_ROOT ;
}
2005-04-16 16:22:17 +00:00
}
2016-07-26 11:47:59 +00:00
p - > flags = flags ;
2005-04-16 16:22:17 +00:00
2016-07-26 11:47:59 +00:00
if ( p - > arch & & Q_strcasecmp ( p - > arch , THISARCH ) )
p - > flags | = DPF_HIDDEN ;
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype = = DEP_FILECONFLICT )
{
const char * n ;
if ( * p - > gamedir )
n = va ( " %s/%s " , p - > gamedir , dep - > name ) ;
else
n = dep - > name ;
if ( MD_CheckFile ( n , p - > fsroot ) )
p - > flags | = DPF_HIDDEN ;
}
}
2005-04-16 16:22:17 +00:00
2016-07-21 19:36:34 +00:00
if ( flags & DPF_HAVEAVERSION )
{
2016-07-26 11:47:59 +00:00
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
char * n ;
if ( dep - > dtype ! = DEP_FILE )
continue ;
if ( * p - > gamedir )
n = va ( " %s/%s " , p - > gamedir , dep - > name ) ;
else
n = dep - > name ;
pf = FS_OpenVFS ( n , " rb " , p - > fsroot ) ;
if ( pf )
VFS_CLOSE ( pf ) ;
else
Con_Printf ( " WARNING: %s (%s) no longer exists \n " , p - > fullname , n ) ;
}
2016-07-21 19:36:34 +00:00
}
2005-10-16 12:53:42 +00:00
else
2016-07-21 19:36:34 +00:00
{
2016-07-26 11:47:59 +00:00
for ( dep = p - > deps ; dep ; dep = dep - > next )
2016-07-21 19:36:34 +00:00
{
2016-07-26 11:47:59 +00:00
char * n ;
struct packagedep_s * odep ;
if ( dep - > dtype ! = DEP_FILE )
continue ;
if ( * p - > gamedir )
n = va ( " %s/%s " , p - > gamedir , dep - > name ) ;
else
n = dep - > name ;
pf = FS_OpenVFS ( n , " rb " , p - > fsroot ) ;
if ( pf )
{
VFS_CLOSE ( pf ) ;
for ( o = availablepackages ; o ; o = o - > next )
{
if ( o - > flags & DPF_HAVEAVERSION )
{
if ( ! strcmp ( p - > gamedir , o - > gamedir ) & & p - > fsroot = = o - > fsroot )
if ( strcmp ( p - > fullname , o - > fullname ) | | strcmp ( p - > version , o - > version ) )
{
for ( odep = o - > deps ; odep ; odep = odep - > next )
{
if ( ! strcmp ( dep - > name , odep - > name ) )
break ;
}
if ( odep )
break ;
}
}
}
if ( ! o )
{
p - > flags | = DPF_UNKNOWNVERSION ;
break ;
}
}
2016-07-21 19:36:34 +00:00
}
}
2005-10-14 18:28:44 +00:00
2005-04-16 16:22:17 +00:00
p - > next = first ;
first = p ;
}
}
return first ;
}
2016-07-26 11:47:59 +00:00
static void COM_QuotedConcat ( const char * cat , char * buf , size_t bufsize )
{
const unsigned char * gah ;
for ( gah = ( const unsigned char * ) cat ; * gah ; gah + + )
{
if ( * gah < = ' ' | | * gah = = ' $ ' | | * gah = = ' \" ' )
break ;
}
if ( * gah | | * cat = = ' \\ ' | |
strstr ( cat , " // " ) | | strstr ( cat , " /* " ) )
{ //contains some dodgy stuff.
size_t curlen = strlen ( buf ) ;
buf + = curlen ;
bufsize - = curlen ;
COM_QuotedString ( cat , buf , bufsize , false ) ;
}
else
{ //okay, no need for quotes.
Q_strncatz ( buf , cat , bufsize ) ;
}
}
2005-10-16 12:53:42 +00:00
static void WriteInstalledPackages ( void )
{
2005-12-22 02:29:11 +00:00
char * s ;
2005-10-16 12:53:42 +00:00
package_t * p ;
2016-07-26 11:47:59 +00:00
struct packagedep_s * dep ;
2008-12-23 02:55:20 +00:00
vfsfile_t * f = FS_OpenVFS ( INSTALLEDFILES , " wb " , FS_ROOT ) ;
2005-10-16 12:53:42 +00:00
if ( ! f )
{
Con_Printf ( " menu_download: Can't update installed list \n " ) ;
return ;
}
2016-07-21 19:36:34 +00:00
s = " version 2 \n " ;
2005-12-22 02:29:11 +00:00
VFS_WRITE ( f , s , strlen ( s ) ) ;
2005-10-16 12:53:42 +00:00
for ( p = availablepackages ; p ; p = p - > next )
{
if ( p - > flags & DPF_HAVEAVERSION )
2005-12-22 02:29:11 +00:00
{
2016-07-26 11:47:59 +00:00
char buf [ 8192 ] ;
buf [ 0 ] = 0 ;
COM_QuotedString ( p - > fullname , buf , sizeof ( buf ) , false ) ;
if ( * p - > version )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " ver=%s " , p - > version ) , buf , sizeof ( buf ) ) ;
}
//if (*p->gamedir)
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " gamedir=%s " , p - > gamedir ) , buf , sizeof ( buf ) ) ;
}
if ( p - > arch )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " arch=%s " , p - > arch ) , buf , sizeof ( buf ) ) ;
}
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype = = DEP_FILE )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " file=%s " , dep - > name ) , buf , sizeof ( buf ) ) ;
}
else if ( dep - > dtype = = DEP_REQUIRE )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " depend=%s " , dep - > name ) , buf , sizeof ( buf ) ) ;
}
else if ( dep - > dtype = = DEP_CONFLICT )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " conflict=%s " , dep - > name ) , buf , sizeof ( buf ) ) ;
}
else if ( dep - > dtype = = DEP_FILECONFLICT )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " fileconflict=%s " , dep - > name ) , buf , sizeof ( buf ) ) ;
}
else if ( dep - > dtype = = DEP_RECOMMEND )
{
Q_strncatz ( buf , " " , sizeof ( buf ) ) ;
COM_QuotedConcat ( va ( " recommend=%s " , dep - > name ) , buf , sizeof ( buf ) ) ;
}
}
Q_strncatz ( buf , " \n " , sizeof ( buf ) ) ;
VFS_WRITE ( f , buf , strlen ( buf ) ) ;
2005-12-22 02:29:11 +00:00
}
2005-10-16 12:53:42 +00:00
}
2005-12-22 02:29:11 +00:00
VFS_CLOSE ( f ) ;
2005-10-16 12:53:42 +00:00
}
static qboolean ComparePackages ( package_t * * l , package_t * p )
2005-04-16 16:22:17 +00:00
{
int v = strcmp ( ( * l ) - > fullname , p - > fullname ) ;
2016-07-21 19:36:34 +00:00
if ( v > 0 )
2005-04-16 16:22:17 +00:00
{
p - > next = ( * l ) ;
( * l ) = p ;
2016-07-21 19:36:34 +00:00
numpackages + + ;
2005-04-16 16:22:17 +00:00
return true ;
}
else if ( v = = 0 )
{
2016-07-21 19:36:34 +00:00
if ( ! strcmp ( p - > version , ( * l ) - > version ) )
2016-07-26 11:47:59 +00:00
if ( ! strcmp ( p - > gamedir , ( * l ) - > gamedir ) )
// if (!strcmp((*l)->fullname, p->fullname))
{ /*package matches, free the new one, don't add*/
p - > override = * l ;
return false ;
2005-04-16 16:22:17 +00:00
}
p - > flags | = DPF_DISPLAYVERSION ;
( * l ) - > flags | = DPF_DISPLAYVERSION ;
}
return false ;
}
2005-10-16 12:53:42 +00:00
static void InsertPackage ( package_t * * l , package_t * p )
2005-04-16 16:22:17 +00:00
{
package_t * lp ;
if ( ! * l ) //there IS no list.
{
* l = p ;
p - > next = NULL ;
2016-07-21 19:36:34 +00:00
numpackages + + ;
2005-04-16 16:22:17 +00:00
return ;
}
if ( ComparePackages ( l , p ) )
return ;
for ( lp = * l ; lp - > next ; lp = lp - > next )
{
if ( ComparePackages ( & lp - > next , p ) )
return ;
}
lp - > next = p ;
p - > next = NULL ;
2016-07-21 19:36:34 +00:00
numpackages + + ;
2005-04-16 16:22:17 +00:00
}
2005-10-16 12:53:42 +00:00
static void ConcatPackageLists ( package_t * l2 )
2005-04-16 16:22:17 +00:00
{
package_t * n ;
while ( l2 )
{
n = l2 - > next ;
2016-07-21 19:36:34 +00:00
l2 - > next = NULL ;
2005-04-16 16:22:17 +00:00
InsertPackage ( & availablepackages , l2 ) ;
l2 = n ;
}
}
2016-07-21 19:36:34 +00:00
static void M_DL_Notification ( struct dl_download * dl )
2005-08-26 22:56:51 +00:00
{
2005-10-16 12:53:42 +00:00
int i ;
2005-12-22 02:29:11 +00:00
vfsfile_t * f ;
2010-03-14 14:35:56 +00:00
f = dl - > file ;
dl - > file = NULL ;
2006-01-28 06:41:20 +00:00
2010-03-14 14:35:56 +00:00
i = dl - > user_num ;
2006-01-28 06:41:20 +00:00
2005-08-26 22:56:51 +00:00
if ( f )
{
2006-01-28 06:41:20 +00:00
downloadablelistreceived [ i ] = 1 ;
2016-07-21 19:36:34 +00:00
ConcatPackageLists ( BuildPackageList ( f , 0 , dl - > url , downloadablelistnameprefix [ i ] ) ) ;
2005-12-22 02:29:11 +00:00
VFS_CLOSE ( f ) ;
2005-08-26 22:56:51 +00:00
}
2006-01-28 06:41:20 +00:00
else
downloadablelistreceived [ i ] = - 1 ;
2005-08-26 22:56:51 +00:00
}
2006-01-28 06:41:20 +00:00
static void MD_Draw ( int x , int y , struct menucustom_s * c , struct menu_s * m )
2005-04-16 16:22:17 +00:00
{
2006-01-28 06:41:20 +00:00
package_t * p ;
2012-10-08 04:36:10 +00:00
int fl ;
2016-07-21 19:36:34 +00:00
char * n ;
2013-03-12 22:47:42 +00:00
p = c - > dptr ;
2006-01-28 06:41:20 +00:00
if ( p )
{
2012-10-08 04:36:10 +00:00
fl = p - > flags & ( DPF_HAVEAVERSION | DPF_WANTTOINSTALL ) ;
2016-07-26 11:47:59 +00:00
if ( p - > flags & DPF_HIDDEN )
{
Draw_FunString ( x + 4 , y , " --- " ) ;
return ;
}
else if ( p - > download )
2016-07-21 19:36:34 +00:00
Draw_FunString ( x + 4 , y , va ( " %i " , ( int ) p - > download - > qdownload . percent ) ) ;
else if ( p - > trymirrors )
Draw_FunString ( x + 4 , y , " PND " ) ;
else
2012-10-08 04:36:10 +00:00
{
2016-07-21 19:36:34 +00:00
switch ( fl )
{
case 0 :
if ( p - > flags & DPF_UNKNOWNVERSION )
Draw_FunString ( x , y , " ??? " ) ;
else
{
Draw_FunString ( x + 4 , y , " ^Ue080^Ue082 " ) ;
Draw_FunString ( x + 8 , y , " ^Ue081 " ) ;
}
break ;
case DPF_HAVEAVERSION :
2016-07-26 11:47:59 +00:00
Draw_FunString ( x , y , " DEL " ) ;
2016-07-21 19:36:34 +00:00
break ;
case DPF_WANTTOINSTALL :
Draw_FunString ( x , y , " GET " ) ;
break ;
case DPF_HAVEAVERSION | DPF_WANTTOINSTALL :
Draw_FunString ( x + 4 , y , " ^Ue080^Ue082 " ) ;
Draw_FunString ( x + 8 , y , " ^Ue083 " ) ;
break ;
}
2012-10-08 04:36:10 +00:00
}
2006-01-28 06:41:20 +00:00
2016-07-21 19:36:34 +00:00
n = p - > name ;
if ( p - > flags & DPF_DISPLAYVERSION )
n = va ( " %s (%s) " , n , * p - > version ? p - > version : " unversioned " ) ;
2006-01-28 06:41:20 +00:00
if ( & m - > selecteditem - > common = = & c - > common )
2016-07-21 19:36:34 +00:00
Draw_AltFunString ( x + 48 , y , n ) ;
2006-01-28 06:41:20 +00:00
else
2016-07-21 19:36:34 +00:00
Draw_FunString ( x + 48 , y , n ) ;
}
}
2006-01-28 06:41:20 +00:00
2016-07-21 19:36:34 +00:00
//finds the newest version
static package_t * MD_FindPackage ( char * packagename )
{
package_t * p , * r = NULL ;
for ( p = availablepackages ; p ; p = p - > next )
{
if ( ! strcmp ( p - > name , packagename ) )
{
if ( ! r | | strcmp ( r - > version , p - > version ) > 0 )
r = p ;
}
}
return r ;
}
//returns the installed version of a package, if any.
static package_t * MD_HavePackage ( char * packagename )
{
package_t * p ;
for ( p = availablepackages ; p ; p = p - > next )
{
if ( p - > flags & DPF_WANTTOINSTALL )
if ( ! strcmp ( p - > name , packagename ) )
return p ;
}
return NULL ;
}
//just flags, doesn't delete
static void MD_RemovePackage ( package_t * package )
{
package_t * o ;
struct packagedep_s * dep ;
if ( ! ( package - > flags & DPF_WANTTOINSTALL ) )
return ; //looks like its already deselected.
package - > flags & = ~ DPF_WANTTOINSTALL ;
//Is this safe?
package - > trymirrors = 0 ; //if its enqueued, cancel that quickly...
if ( package - > download )
{ //if its currently downloading, cancel it.
DL_Close ( package - > download ) ;
package - > download = NULL ;
}
//remove stuff that depends on us
for ( o = availablepackages ; o ; o = o - > next )
{
for ( dep = package - > deps ; dep ; dep = dep - > next )
if ( dep - > dtype = = DEP_REQUIRE )
if ( ! strcmp ( dep - > name , package - > name ) )
MD_RemovePackage ( o ) ;
}
}
//just flags, doesn't install
static void MD_AddPackage ( package_t * package )
{
package_t * o ;
2016-07-26 11:47:59 +00:00
struct packagedep_s * dep , * dep2 ;
2016-07-21 19:36:34 +00:00
qboolean replacing = false ;
if ( package - > flags & DPF_WANTTOINSTALL )
return ; //looks like its already picked.
2016-07-26 11:47:59 +00:00
//any file-conflicts prevent the package from being installable.
//this is mostly for pak1.pak
for ( dep = package - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype = = DEP_FILECONFLICT )
{
const char * n ;
if ( * package - > gamedir )
n = va ( " %s/%s " , package - > gamedir , dep - > name ) ;
else
n = dep - > name ;
if ( MD_CheckFile ( n , package - > fsroot ) )
return ;
}
}
2016-07-21 19:36:34 +00:00
package - > flags | = DPF_WANTTOINSTALL ;
//first check to see if we're replacing a different version of the same package
for ( o = availablepackages ; o ; o = o - > next )
{
if ( o = = package )
continue ;
if ( o - > flags & DPF_WANTTOINSTALL )
{
if ( ! strcmp ( o - > fullname , package - > fullname ) )
{ //replaces this package
o - > flags & = ~ DPF_WANTTOINSTALL ;
replacing = true ;
}
else
{ //two packages with the same filename are always mutually incompatible, but with totally separate dependancies etc.
2016-07-26 11:47:59 +00:00
qboolean remove = false ;
for ( dep = package - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype = = DEP_FILE )
for ( dep2 = o - > deps ; dep2 ; dep2 = dep2 - > next )
{
if ( dep2 - > dtype = = DEP_FILE )
if ( ! strcmp ( dep - > name , dep2 - > name ) )
{
MD_RemovePackage ( o ) ;
remove = true ;
break ;
}
}
if ( remove )
break ;
}
//fixme: zip content conflicts
2016-07-21 19:36:34 +00:00
}
}
}
//if we are replacing an existing one, then dependancies are already settled (only because we don't do version deps)
if ( replacing )
return ;
//satisfy our dependancies.
for ( dep = package - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype = = DEP_REQUIRE | | dep - > dtype = = DEP_RECOMMEND )
2006-01-28 06:41:20 +00:00
{
2016-07-21 19:36:34 +00:00
package_t * d = MD_FindPackage ( dep - > name ) ;
if ( d )
MD_AddPackage ( d ) ;
}
if ( dep - > dtype = = DEP_CONFLICT )
{
for ( ; ; )
{
package_t * d = MD_HavePackage ( dep - > name ) ;
if ( ! d )
break ;
MD_RemovePackage ( d ) ;
}
2006-01-28 06:41:20 +00:00
}
}
2016-07-21 19:36:34 +00:00
//remove any packages that conflict with us.
for ( o = availablepackages ; o ; o = o - > next )
{
for ( dep = package - > deps ; dep ; dep = dep - > next )
if ( dep - > dtype = = DEP_CONFLICT )
if ( ! strcmp ( dep - > name , package - > name ) )
MD_RemovePackage ( o ) ;
}
2006-01-28 06:41:20 +00:00
}
2015-06-16 23:53:58 +00:00
static qboolean MD_Key ( struct menucustom_s * c , struct menu_s * m , int key , unsigned int unicode )
2006-01-28 06:41:20 +00:00
{
package_t * p , * p2 ;
2016-07-26 11:47:59 +00:00
struct packagedep_s * dep , * dep2 ;
2013-03-12 22:47:42 +00:00
p = c - > dptr ;
2016-07-26 11:47:59 +00:00
if ( p - > flags & DPF_HIDDEN )
return false ;
2013-05-03 04:28:08 +00:00
if ( key = = K_ENTER | | key = = K_KP_ENTER | | key = = K_MOUSE1 )
2006-01-28 06:41:20 +00:00
{
2016-07-26 11:47:59 +00:00
if ( p - > flags & DPF_WANTTOINSTALL )
2016-07-21 19:36:34 +00:00
MD_RemovePackage ( p ) ;
2016-07-26 11:47:59 +00:00
// else if (p->flags & DPF_UNKNOWNVERSION)
// p->flags &= ~DPF_UNKNOWNVERSION;
2016-07-21 19:36:34 +00:00
else
MD_AddPackage ( p ) ;
2006-01-28 06:41:20 +00:00
if ( p - > flags & DPF_WANTTOINSTALL )
{
2016-07-21 19:36:34 +00:00
//any other packages that conflict should be flagged for uninstall now that this one will replace it.
2006-01-28 06:41:20 +00:00
for ( p2 = availablepackages ; p2 ; p2 = p2 - > next )
{
if ( p = = p2 )
continue ;
2016-07-26 11:47:59 +00:00
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype ! = DEP_FILE )
continue ;
for ( dep2 = p2 - > deps ; dep2 ; dep2 = dep2 - > next )
{
if ( dep2 - > dtype ! = DEP_FILE )
continue ;
if ( ! strcmp ( dep - > name , dep2 - > name ) )
{
p2 - > flags & = ~ DPF_WANTTOINSTALL ;
break ;
}
}
}
2006-01-28 06:41:20 +00:00
}
}
else
2016-07-21 19:36:34 +00:00
p - > trymirrors = 0 ;
2006-01-28 06:41:20 +00:00
return true ;
}
2005-04-16 16:22:17 +00:00
2006-01-28 06:41:20 +00:00
return false ;
}
2016-07-21 19:36:34 +00:00
# ifdef HAVEAUTOUPDATE
static void MD_EngineUpdate_Draw ( int x , int y , struct menucustom_s * c , struct menu_s * m )
{
char * settings [ ] =
{
" Unsupported " ,
" Revert " ,
" Off " ,
" Stable Updates " ,
" Unsable Updates "
} ;
int setting = autoupdatesetting ;
char * text ;
if ( setting = = - 1 )
{
setting = Sys_GetAutoUpdateSetting ( ) ;
text = va ( " Auto Update: %s " , settings [ setting + 1 ] ) ;
}
else
text = va ( " Auto Update: %s (unsaved) " , settings [ setting + 1 ] ) ;
if ( & m - > selecteditem - > common = = & c - > common )
Draw_AltFunString ( x + 4 , y , text ) ;
else
Draw_FunString ( x + 4 , y , text ) ;
}
static qboolean MD_EngineUpdate_Key ( struct menucustom_s * c , struct menu_s * m , int key , unsigned int unicode )
{
if ( key = = K_ENTER | | key = = K_KP_ENTER | | key = = K_MOUSE1 )
{
if ( autoupdatesetting = = - 1 )
autoupdatesetting = Sys_GetAutoUpdateSetting ( ) ;
if ( autoupdatesetting ! = - 1 )
{
autoupdatesetting + = 1 ;
if ( autoupdatesetting > = 4 )
autoupdatesetting = 0 ;
}
}
return false ;
}
# endif
2006-01-28 06:41:20 +00:00
qboolean MD_PopMenu ( union menuoption_s * mo , struct menu_s * m , int key )
{
2013-05-03 04:28:08 +00:00
if ( key = = K_ENTER | | key = = K_KP_ENTER | | key = = K_MOUSE1 )
2006-01-28 06:41:20 +00:00
{
M_RemoveMenu ( m ) ;
return true ;
}
return false ;
}
2016-07-21 19:36:34 +00:00
vfsfile_t * FS_XZ_DecompressWriteFilter ( vfsfile_t * infile ) ;
vfsfile_t * FS_GZ_DecompressWriteFilter ( vfsfile_t * outfile , qboolean autoclosefile ) ;
2016-07-26 11:47:59 +00:00
static char * MD_GetTempName ( package_t * p )
{
struct packagedep_s * dep ;
char * destname , * t , * ts ;
//always favour a file so that we can rename safely without needing a copy.
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype ! = DEP_FILE )
continue ;
if ( * p - > gamedir )
destname = va ( " %s/%s.tmp " , p - > gamedir , dep - > name ) ;
else
destname = va ( " %s.tmp " , dep - > name ) ;
return Z_StrDup ( destname ) ;
}
ts = Z_StrDup ( p - > name ) ;
for ( t = ts ; * t ; t + + )
{
switch ( * t )
{
case ' / ' :
case ' ? ' :
case ' < ' :
case ' > ' :
case ' \\ ' :
case ' : ' :
case ' * ' :
case ' | ' :
case ' \" ' :
case ' . ' :
* t = ' _ ' ;
break ;
default :
break ;
}
}
if ( * ts )
{
if ( * p - > gamedir )
destname = va ( " %s/%s.tmp " , p - > gamedir , ts ) ;
else
destname = va ( " %s.tmp " , ts ) ;
}
else
destname = va ( " %x.tmp " , ( unsigned int ) ( quintptr_t ) p ) ;
Z_Free ( ts ) ;
return Z_StrDup ( destname ) ;
}
2010-03-14 14:35:56 +00:00
static void Menu_Download_Got ( struct dl_download * dl ) ;
2016-07-21 19:36:34 +00:00
static void MD_StartADownload ( void )
{
vfsfile_t * tmpfile ;
char * temp ;
// char native[MAX_OSPATH];
package_t * p ;
int simultaneous = 1 ;
int i ;
for ( p = availablepackages ; p ; p = p - > next )
{
if ( p - > download )
simultaneous - - ;
}
for ( p = availablepackages ; p & & simultaneous > 0 ; p = p - > next )
{
if ( p - > trymirrors )
{ //flagged for a (re?)download
char * mirror = NULL ;
for ( i = 0 ; i < countof ( p - > mirror ) ; i + + )
{
if ( p - > mirror [ i ] & & ( p - > trymirrors & ( 1u < < i ) ) )
{
mirror = p - > mirror [ i ] ;
p - > trymirrors & = ~ ( 1u < < i ) ;
break ;
}
}
if ( ! mirror )
{ //erk...
p - > trymirrors = 0 ;
continue ;
}
2016-07-26 11:47:59 +00:00
temp = MD_GetTempName ( p ) ;
2016-07-21 19:36:34 +00:00
//FIXME: we should lock in the temp path, in case the user foolishly tries to change gamedirs.
FS_CreatePath ( temp , p - > fsroot ) ;
switch ( p - > extract )
{
2016-07-26 11:47:59 +00:00
case EXTRACT_ZIP :
case EXTRACT_COPY :
2016-07-21 19:36:34 +00:00
tmpfile = FS_OpenVFS ( temp , " wb " , p - > fsroot ) ;
break ;
# ifdef AVAIL_XZDEC
2016-07-26 11:47:59 +00:00
case EXTRACT_XZ :
2016-07-21 19:36:34 +00:00
{
vfsfile_t * raw ;
raw = FS_OpenVFS ( temp , " wb " , p - > fsroot ) ;
tmpfile = FS_XZ_DecompressWriteFilter ( raw ) ;
if ( ! tmpfile )
VFS_CLOSE ( raw ) ;
}
break ;
# endif
# ifdef AVAIL_GZDEC
2016-07-26 11:47:59 +00:00
case EXTRACT_GZ :
2016-07-21 19:36:34 +00:00
{
vfsfile_t * raw ;
raw = FS_OpenVFS ( temp , " wb " , p - > fsroot ) ;
tmpfile = FS_GZ_DecompressWriteFilter ( raw , true ) ;
if ( ! tmpfile )
VFS_CLOSE ( raw ) ;
}
break ;
# endif
default :
Con_Printf ( " decompression method not supported \n " ) ;
continue ;
}
if ( tmpfile )
p - > download = HTTP_CL_Get ( mirror , NULL , Menu_Download_Got ) ;
if ( p - > download )
{
Con_Printf ( " Downloading %s \n " , p - > fullname ) ;
p - > download - > file = tmpfile ;
2016-07-26 11:47:59 +00:00
p - > download - > user_ctx = temp ;
2016-07-21 19:36:34 +00:00
# ifdef MULTITHREAD
DL_CreateThread ( p - > download , NULL , NULL ) ;
# endif
}
else
{
Con_Printf ( " Unable to download %s \n " , p - > fullname ) ;
p - > flags & = ~ DPF_WANTTOINSTALL ; //can't do it.
if ( tmpfile )
VFS_CLOSE ( tmpfile ) ;
FS_Remove ( temp , p - > fsroot ) ;
}
simultaneous - - ;
}
}
}
static qboolean MD_ApplyDownloads ( union menuoption_s * mo , struct menu_s * m , int key )
2006-01-28 06:41:20 +00:00
{
2013-05-03 04:28:08 +00:00
if ( key = = K_ENTER | | key = = K_KP_ENTER | | key = = K_MOUSE1 )
2006-01-28 06:41:20 +00:00
{
2016-07-26 11:47:59 +00:00
package_t * p , * o , * * link ;
2006-01-28 06:41:20 +00:00
2016-07-21 19:36:34 +00:00
# ifdef HAVEAUTOUPDATE
if ( autoupdatesetting ! = - 1 )
{
Sys_SetAutoUpdateSetting ( autoupdatesetting ) ;
autoupdatesetting = - 1 ;
}
# endif
//delete any that don't exist
2016-07-26 11:47:59 +00:00
for ( link = & availablepackages ; * link ; )
2006-01-28 06:41:20 +00:00
{
2016-07-26 11:47:59 +00:00
p = * link ;
2006-01-28 06:41:20 +00:00
if ( ! ( p - > flags & DPF_WANTTOINSTALL ) & & ( p - > flags & DPF_HAVEAVERSION ) )
{ //if we don't want it but we have it anyway:
2016-07-26 11:47:59 +00:00
qboolean reloadpacks = false ;
struct packagedep_s * dep ;
for ( dep = p - > deps ; dep ; dep = dep - > next )
2006-01-28 06:41:20 +00:00
{
2016-07-26 11:47:59 +00:00
if ( dep - > dtype = = DEP_FILE )
{
if ( ! reloadpacks )
{
char ext [ 8 ] ;
COM_FileExtension ( dep - > name , ext , sizeof ( ext ) ) ;
if ( ! stricmp ( ext , " pak " ) | | ! stricmp ( ext , " pk3 " ) )
{
reloadpacks = true ;
FS_UnloadPackFiles ( ) ;
}
}
if ( * p - > gamedir )
FS_Remove ( va ( " %s/%s " , p - > gamedir , dep - > name ) , p - > fsroot ) ;
else
FS_Remove ( dep - > name , p - > fsroot ) ;
}
2016-07-21 19:36:34 +00:00
}
2016-07-26 11:47:59 +00:00
if ( reloadpacks )
FS_ReloadPackFiles ( ) ;
2006-01-28 06:41:20 +00:00
2016-07-26 11:47:59 +00:00
p - > flags & = ~ DPF_UNKNOWNVERSION ;
p - > flags & = ~ DPF_HAVEAVERSION ;
//make sure it actually got wiped. if there's still a file there then something went screwy.
//we don't reliably know if the remove actually succeeded or failed.
for ( dep = p - > deps ; dep ; dep = dep - > next )
2016-07-21 19:36:34 +00:00
{
2016-07-26 11:47:59 +00:00
if ( dep - > dtype = = DEP_FILE )
{
const char * n ;
if ( * p - > gamedir )
n = va ( " %s/%s " , p - > gamedir , dep - > name ) ;
else
n = dep - > name ;
if ( MD_CheckFile ( n , p - > fsroot ) )
{
p - > flags | = DPF_UNKNOWNVERSION ;
break ;
}
}
2016-07-21 19:36:34 +00:00
}
2016-07-26 11:47:59 +00:00
WriteInstalledPackages ( ) ;
2006-01-28 06:41:20 +00:00
2016-07-21 19:36:34 +00:00
if ( p - > flags & DPF_FORGETONUNINSTALL )
2006-01-28 06:41:20 +00:00
{
2016-07-26 11:47:59 +00:00
* link = p - > next ;
2006-01-28 06:41:20 +00:00
2016-07-26 11:47:59 +00:00
for ( o = availablepackages ; o ; o = o - > next )
{
if ( o - > override = = p )
o - > override = NULL ;
}
p - > flags | = DPF_HIDDEN ;
// BZ_Free(p);
2006-01-28 06:41:20 +00:00
2016-07-26 11:47:59 +00:00
continue ;
2006-01-28 06:41:20 +00:00
}
}
2016-07-26 11:47:59 +00:00
link = & ( * link ) - > next ;
2006-01-28 06:41:20 +00:00
}
2016-07-21 19:36:34 +00:00
//and flag any new/updated ones for a download
2006-01-28 06:41:20 +00:00
for ( p = availablepackages ; p ; p = p - > next )
{
2016-07-21 19:36:34 +00:00
if ( ( p - > flags & DPF_WANTTOINSTALL ) & & ! ( p - > flags & DPF_HAVEAVERSION ) & & ! p - > download )
p - > trymirrors = ~ 0u ;
2006-01-28 06:41:20 +00:00
}
2016-07-21 19:36:34 +00:00
MD_StartADownload ( ) ; //and try to do those downloads.
2006-01-28 06:41:20 +00:00
return true ;
}
return false ;
}
void M_AddItemsToDownloadMenu ( menu_t * m )
{
char path [ MAX_QPATH ] ;
int y ;
2005-04-16 16:22:17 +00:00
package_t * p ;
2006-01-28 06:41:20 +00:00
menucustom_t * c ;
char * slash ;
menuoption_t * mo ;
2005-04-16 16:22:17 +00:00
dlmenu_t * info = m - > data ;
2006-01-28 06:41:20 +00:00
int prefixlen ;
p = availablepackages ;
2005-04-16 16:22:17 +00:00
2006-01-28 06:41:20 +00:00
prefixlen = strlen ( info - > pathprefix ) ;
2016-07-21 19:36:34 +00:00
y = 48 ;
MC_AddCommand ( m , 0 , 170 , y , " Apply " , MD_ApplyDownloads ) ;
y + = 8 ;
MC_AddCommand ( m , 0 , 170 , y , " Back " , MD_PopMenu ) ;
y + = 8 ;
# ifdef HAVEAUTOUPDATE
if ( ! prefixlen )
{
c = MC_AddCustom ( m , 0 , y , p , 0 ) ;
c - > draw = MD_EngineUpdate_Draw ;
c - > key = MD_EngineUpdate_Key ;
c - > common . width = 320 ;
c - > common . height = 8 ;
y + = 8 ;
}
# endif
y + = 4 ; //small gap
2006-01-28 06:41:20 +00:00
for ( p = availablepackages ; p ; p = p - > next )
{
if ( strncmp ( p - > fullname , info - > pathprefix , prefixlen ) )
continue ;
2016-07-26 11:47:59 +00:00
if ( ( p - > flags & DPF_HIDDEN ) & & ! ( p - > flags & DPF_HAVEAVERSION ) )
continue ;
if ( p - > override )
continue ;
2006-01-28 06:41:20 +00:00
slash = strchr ( p - > fullname + prefixlen , ' / ' ) ;
if ( slash )
{
Q_strncpyz ( path , p - > fullname , MAX_QPATH ) ;
slash = strchr ( path + prefixlen , ' / ' ) ;
if ( slash )
* slash = ' \0 ' ;
2008-02-13 07:57:42 +00:00
2006-01-28 06:41:20 +00:00
for ( mo = m - > options ; mo ; mo = mo - > common . next )
if ( mo - > common . type = = mt_button )
if ( ! strcmp ( mo - > button . text , path + prefixlen ) )
break ;
if ( ! mo )
{
2016-07-21 19:36:34 +00:00
menubutton_t * b = MC_AddConsoleCommand ( m , 6 * 8 , 170 , y , path + prefixlen , va ( " menu_download \" %s/ \" " , path ) ) ;
2006-01-28 06:41:20 +00:00
y + = 8 ;
2016-07-21 19:36:34 +00:00
if ( ! m - > selecteditem )
m - > selecteditem = ( menuoption_t * ) b ;
2006-01-28 06:41:20 +00:00
}
}
else
{
2013-03-12 22:47:42 +00:00
c = MC_AddCustom ( m , 0 , y , p , 0 ) ;
2006-01-28 06:41:20 +00:00
c - > draw = MD_Draw ;
c - > key = MD_Key ;
c - > common . width = 320 ;
c - > common . height = 8 ;
y + = 8 ;
2016-07-21 19:36:34 +00:00
if ( ! m - > selecteditem )
m - > selecteditem = ( menuoption_t * ) c ;
2006-01-28 06:41:20 +00:00
}
2016-07-21 19:36:34 +00:00
}
2006-01-28 06:41:20 +00:00
}
void M_Download_UpdateStatus ( struct menu_s * m )
{
2010-03-14 14:35:56 +00:00
struct dl_download * dl ;
2006-01-28 06:41:20 +00:00
dlmenu_t * info = m - > data ;
int i ;
2014-06-12 23:08:42 +00:00
while ( ! cls . download & & ( info - > parsedsourcenum = = - 1 | | info - > parsedsourcenum < numdownloadablelists ) )
2005-04-16 16:22:17 +00:00
{ //done downloading
info - > parsedsourcenum + + ;
2006-01-28 06:41:20 +00:00
if ( info - > parsedsourcenum < numdownloadablelists )
{
if ( ! downloadablelistreceived [ info - > parsedsourcenum ] )
{
2016-07-26 11:47:59 +00:00
dl = HTTP_CL_Get ( va ( " %s " DOWNLOADABLESARGS , downloadablelist [ info - > parsedsourcenum ] ) , NULL , M_DL_Notification ) ;
2010-03-14 14:35:56 +00:00
if ( dl )
2016-07-21 19:36:34 +00:00
{
2010-03-14 14:35:56 +00:00
dl - > user_num = info - > parsedsourcenum ;
2016-07-21 19:36:34 +00:00
dl - > file = VFSPIPE_Open ( ) ;
dl - > isquery = true ;
}
2010-03-14 14:35:56 +00:00
else
2006-01-28 06:41:20 +00:00
Con_Printf ( " Could not contact server \n " ) ;
return ;
}
}
}
for ( i = 0 ; i < numdownloadablelists ; i + + )
{
if ( ! downloadablelistreceived [ i ] )
2005-04-16 16:22:17 +00:00
{
2006-01-28 06:41:20 +00:00
// Draw_String(x+8, y+8, "Waiting for package list");
return ;
2005-04-16 16:22:17 +00:00
}
}
2006-01-28 06:41:20 +00:00
if ( ! info - > populated )
{
info - > populated = true ;
M_AddItemsToDownloadMenu ( m ) ;
}
}
2005-04-16 16:22:17 +00:00
2016-07-26 11:47:59 +00:00
# include "fs.h"
static int QDECL MD_ExtractFiles ( const char * fname , qofs_t fsize , time_t mtime , void * parm , searchpathfuncs_t * spath )
{ //this is gonna suck. threading would help, but gah.
package_t * p = parm ;
flocation_t loc ;
if ( spath - > FindFile ( spath , & loc , fname , NULL ) & & loc . len < 0x80000000u )
{
char * f = malloc ( loc . len ) ;
const char * n ;
if ( f )
{
spath - > ReadFile ( spath , & loc , f ) ;
if ( * p - > gamedir )
n = va ( " %s/%s " , p - > gamedir , fname ) ;
else
n = fname ;
FS_WriteFile ( n , f , loc . len , p - > fsroot ) ;
free ( f ) ;
//keep track of the installed files, so we can delete them properly after.
MD_AddDep ( p , DEP_FILE , fname ) ;
}
}
return 1 ;
}
2010-03-14 14:35:56 +00:00
static void Menu_Download_Got ( struct dl_download * dl )
2005-04-16 16:22:17 +00:00
{
2010-03-14 14:35:56 +00:00
qboolean successful = dl - > status = = DL_FINISHED ;
2005-10-16 12:53:42 +00:00
package_t * p ;
2016-07-26 11:47:59 +00:00
char * tempname = dl - > user_ctx ;
for ( p = availablepackages ; p ; p = p - > next )
{
if ( p - > download = = dl )
break ;
}
2016-07-21 19:36:34 +00:00
if ( dl - > file )
{
VFS_CLOSE ( dl - > file ) ;
dl - > file = NULL ;
}
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
if ( p )
2005-10-16 12:53:42 +00:00
{
2016-07-26 11:47:59 +00:00
char ext [ 8 ] ;
char * destname ;
struct packagedep_s * dep ;
p - > download = NULL ;
if ( ! successful )
2005-10-16 12:53:42 +00:00
{
2016-07-26 11:47:59 +00:00
Con_Printf ( " Couldn't download %s (from %s) \n " , p - > name , dl - > url ) ;
FS_Remove ( tempname , p - > fsroot ) ;
Z_Free ( tempname ) ;
MD_StartADownload ( ) ;
return ;
}
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
if ( p - > extract = = EXTRACT_ZIP )
{
vfsfile_t * f = FS_OpenVFS ( tempname , " rb " , p - > fsroot ) ;
if ( f )
2005-10-16 12:53:42 +00:00
{
2016-07-26 11:47:59 +00:00
searchpathfuncs_t * archive = FSZIP_LoadArchive ( f , tempname , NULL ) ;
if ( archive )
{
archive - > EnumerateFiles ( archive , " * " , MD_ExtractFiles , p ) ;
archive - > ClosePath ( archive ) ;
p - > flags | = DPF_HAVEAVERSION ;
WriteInstalledPackages ( ) ;
if ( ! stricmp ( ext , " pak " ) | | ! stricmp ( ext , " pk3 " ) )
FS_ReloadPackFiles ( ) ;
}
2016-07-21 19:36:34 +00:00
else
2016-07-26 11:47:59 +00:00
VFS_CLOSE ( f ) ;
2005-10-16 12:53:42 +00:00
}
2016-07-26 11:47:59 +00:00
FS_Remove ( tempname , FS_GAMEONLY ) ;
Z_Free ( tempname ) ;
MD_StartADownload ( ) ;
return ;
}
else
{
for ( dep = p - > deps ; dep ; dep = dep - > next )
{
if ( dep - > dtype ! = DEP_FILE )
continue ;
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
COM_FileExtension ( dep - > name , ext , sizeof ( ext ) ) ;
if ( ! stricmp ( ext , " pak " ) | | ! stricmp ( ext , " pk3 " ) )
FS_UnloadPackFiles ( ) ; //we reload them after
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
if ( * p - > gamedir )
destname = va ( " %s/%s " , p - > gamedir , dep - > name ) ;
else
destname = dep - > name ;
if ( FS_Remove ( destname , p - > fsroot ) )
;
if ( ! FS_Rename2 ( tempname , destname , p - > fsroot , p - > fsroot ) )
{
Con_Printf ( " Couldn't rename %s to %s. Removed instead. \n " , tempname , destname ) ;
FS_Remove ( tempname , p - > fsroot ) ;
Z_Free ( tempname ) ;
MD_StartADownload ( ) ;
return ;
}
Z_Free ( tempname ) ;
Con_Printf ( " Downloaded %s (to %s) \n " , p - > name , destname ) ;
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
p - > flags | = DPF_HAVEAVERSION ;
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
WriteInstalledPackages ( ) ;
2016-07-21 19:36:34 +00:00
2016-07-26 11:47:59 +00:00
if ( ! stricmp ( ext , " pak " ) | | ! stricmp ( ext , " pk3 " ) )
FS_ReloadPackFiles ( ) ;
MD_StartADownload ( ) ;
return ;
}
2005-10-16 12:53:42 +00:00
}
2016-07-26 11:47:59 +00:00
Con_Printf ( " menu_download: %s has no filename info \n " , p - > name ) ;
2005-10-16 12:53:42 +00:00
}
2016-07-26 11:47:59 +00:00
else
Con_Printf ( " menu_download: Can't figure out where %s came from (url: %s) \n " , dl - > localname , dl - > url ) ;
2005-10-16 12:53:42 +00:00
2016-07-26 11:47:59 +00:00
FS_Remove ( tempname , FS_GAMEONLY ) ;
Z_Free ( tempname ) ;
2016-07-21 19:36:34 +00:00
MD_StartADownload ( ) ;
2005-04-16 16:22:17 +00:00
}
2016-07-21 19:36:34 +00:00
2005-04-16 16:22:17 +00:00
void Menu_DownloadStuff_f ( void )
{
2016-07-21 19:36:34 +00:00
static qboolean loadedinstalled ;
2006-01-28 06:41:20 +00:00
int i ;
2005-04-16 16:22:17 +00:00
menu_t * menu ;
dlmenu_t * info ;
2015-07-14 14:47:00 +00:00
Key_Dest_Add ( kdm_emenu ) ;
2005-04-16 16:22:17 +00:00
m_state = m_complex ;
menu = M_CreateMenu ( sizeof ( dlmenu_t ) ) ;
info = menu - > data ;
2015-06-18 22:11:30 +00:00
menu - > predraw = M_Download_UpdateStatus ;
2006-01-28 06:41:20 +00:00
/*
2005-04-16 16:22:17 +00:00
menu - > selecteditem = ( menuoption_t * ) ( info - > list = MC_AddCustom ( menu , 0 , 32 , NULL ) ) ;
info - > list - > draw = M_Download_Draw ;
info - > list - > key = M_Download_Key ;
2006-01-28 06:41:20 +00:00
*/
2005-04-16 16:22:17 +00:00
info - > parsedsourcenum = - 1 ;
2016-07-21 19:36:34 +00:00
if ( * fs_downloads_url . string )
M_DL_AddSubList ( fs_downloads_url . string , " " ) ;
2006-01-28 06:41:20 +00:00
Q_strncpyz ( info - > pathprefix , Cmd_Argv ( 1 ) , sizeof ( info - > pathprefix ) ) ;
if ( ! * info - > pathprefix )
{
for ( i = 0 ; i < numdownloadablelists ; i + + )
downloadablelistreceived [ i ] = 0 ;
}
2014-03-30 08:55:06 +00:00
MC_AddWhiteText ( menu , 24 , 170 , 8 , " Downloads " , false ) ;
2016-07-21 19:36:34 +00:00
MC_AddWhiteText ( menu , 16 , 170 , 24 , " ^Ue01d^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01e^Ue01f " , false ) ;
2005-04-16 16:22:17 +00:00
2016-07-21 19:36:34 +00:00
if ( ! loadedinstalled )
2005-04-16 16:22:17 +00:00
{
2016-07-21 19:36:34 +00:00
vfsfile_t * f = FS_OpenVFS ( INSTALLEDFILES , " rb " , FS_ROOT ) ;
2005-04-16 16:22:17 +00:00
loadedinstalled = true ;
if ( f )
{
2016-07-21 19:36:34 +00:00
ConcatPackageLists ( BuildPackageList ( f , DPF_FORGETONUNINSTALL | DPF_HAVEAVERSION | DPF_WANTTOINSTALL , NULL , " " ) ) ;
2005-12-22 02:29:11 +00:00
VFS_CLOSE ( f ) ;
2005-04-16 16:22:17 +00:00
}
}
}
2012-11-27 03:23:19 +00:00
# else
2013-06-23 02:17:02 +00:00
void Menu_DownloadStuff_f ( void )
2012-11-27 03:23:19 +00:00
{
2013-06-23 02:17:02 +00:00
Con_Printf ( " Download menu not implemented in this build \n " ) ;
2012-11-27 03:23:19 +00:00
}
# endif