add support for COMPRESSED downloads!!! Of course, both client and server must

both support this. The client tells the server it can support compressed
downloads by setting the z flag in the *cap userinfo. If the server detects
that the client supports compression, and the file to be downloaded is
compressed (more accurately, has the .gz extension), the server sends a special
download packet with a size of -2 (-1 indicates error),, percent of 0, followed
by the new name of the file (eg maps/foo.bsp.gz for maps/foo.bsp). The client
WILL NOT accept a new filename that doesn not match the old name for the length
of the old name. The client also will not accept a new name if there are . or
.. path components. If the client rejects the new name, it prints a warning
message and aborts that download.
This commit is contained in:
Bill Currie 2000-09-28 06:11:55 +00:00
parent 1a7f2af4ec
commit 1aa9084aa9
5 changed files with 83 additions and 34 deletions

View file

@ -49,6 +49,7 @@ extern char com_gamedir[MAX_OSPATH];
extern char gamedirfile[MAX_OSPATH]; extern char gamedirfile[MAX_OSPATH];
void COM_WriteFile (char *filename, void *data, int len); void COM_WriteFile (char *filename, void *data, int len);
int _COM_FOpenFile (char *filename, QFile **gzfile, char *foundname, int zip);
int COM_FOpenFile (char *filename, QFile **gzfile); int COM_FOpenFile (char *filename, QFile **gzfile);
void COM_CloseFile (QFile *h); void COM_CloseFile (QFile *h);
int COM_filelength (QFile *f); int COM_filelength (QFile *f);

View file

@ -1139,10 +1139,14 @@ void CL_Init (void)
Info_SetValueForKey (cls.userinfo, "bottomcolor", "0", MAX_INFO_STRING); Info_SetValueForKey (cls.userinfo, "bottomcolor", "0", MAX_INFO_STRING);
Info_SetValueForKey (cls.userinfo, "rate", "2500", MAX_INFO_STRING); Info_SetValueForKey (cls.userinfo, "rate", "2500", MAX_INFO_STRING);
Info_SetValueForKey (cls.userinfo, "msg", "1", MAX_INFO_STRING); Info_SetValueForKey (cls.userinfo, "msg", "1", MAX_INFO_STRING);
// sprintf (st, "%s-%04d", QW_VERSION, build_number()); // sprintf (st, "%s-%04d", QW_VERSION, build_number());
sprintf (st, "%s", QW_VERSION); sprintf (st, "%s", QW_VERSION);
Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING); Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING);
Info_SetValueForStarKey (cls.userinfo, "stdver", QSG_VERSION, MAX_INFO_STRING); Info_SetValueForStarKey (cls.userinfo, "stdver", QSG_VERSION, MAX_INFO_STRING);
// set the capabilities info. single char flags (possibly with modifiefs)
// defined capabilities:
// z client can accept gzipped files.
Info_SetValueForStarKey (cls.userinfo, "*cap", "z", MAX_INFO_STRING);
CL_InitInput (); CL_InitInput ();
CL_InitTEnts (); CL_InitTEnts ();

View file

@ -377,11 +377,9 @@ void CL_ParseDownload (void)
return; // not in demo playback return; // not in demo playback
} }
if (size == -1) if (size == -1) {
{
Con_Printf ("File not found.\n"); Con_Printf ("File not found.\n");
if (cls.download) if (cls.download) {
{
Con_Printf ("cls.download shouldn't have been set\n"); Con_Printf ("cls.download shouldn't have been set\n");
Qclose (cls.download); Qclose (cls.download);
cls.download = NULL; cls.download = NULL;
@ -390,9 +388,27 @@ void CL_ParseDownload (void)
return; return;
} }
if (size == -2) {
char *newname = MSG_ReadString();
if (strncmp (newname, cls.downloadname, strlen(cls.downloadname))
|| strstr(newname, "/../")
|| strstr(newname, "/./")) {
Con_Printf ("WARNING: server tried to give a strange new name: %s\n",
newname);
CL_RequestNextDownload ();
return;
}
if (cls.download) {
Qclose (cls.download);
unlink (cls.downloadname);
}
strncpy (cls.downloadname, newname, sizeof (cls.downloadname));
Con_Printf ("downloading to %s\n", cls.downloadname);
return;
}
// open the file if not opened yet // open the file if not opened yet
if (!cls.download) if (!cls.download) {
{
if (strncmp(cls.downloadtempname,"skins/",6)) if (strncmp(cls.downloadtempname,"skins/",6))
snprintf (name, sizeof(name), "%s/%s", com_gamedir, cls.downloadtempname); snprintf (name, sizeof(name), "%s/%s", com_gamedir, cls.downloadtempname);
else else
@ -401,8 +417,7 @@ void CL_ParseDownload (void)
COM_CreatePath (name); COM_CreatePath (name);
cls.download = Qopen (name, "wb"); cls.download = Qopen (name, "wb");
if (!cls.download) if (!cls.download) {
{
msg_readcount += size; msg_readcount += size;
Con_Printf ("Failed to open %s\n", cls.downloadtempname); Con_Printf ("Failed to open %s\n", cls.downloadtempname);
CL_RequestNextDownload (); CL_RequestNextDownload ();
@ -413,14 +428,12 @@ void CL_ParseDownload (void)
Qwrite (cls.download, net_message.data + msg_readcount, size); Qwrite (cls.download, net_message.data + msg_readcount, size);
msg_readcount += size; msg_readcount += size;
if (percent != 100) if (percent != 100) {
{
// change display routines by zoid // change display routines by zoid
// request next block // request next block
#if 0 #if 0
Con_Printf ("."); Con_Printf (".");
if (10*(percent/10) != cls.downloadpercent) if (10*(percent/10) != cls.downloadpercent) {
{
cls.downloadpercent = 10*(percent/10); cls.downloadpercent = 10*(percent/10);
Con_Printf ("%i%%", cls.downloadpercent); Con_Printf ("%i%%", cls.downloadpercent);
} }
@ -429,9 +442,7 @@ void CL_ParseDownload (void)
MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
SZ_Print (&cls.netchan.message, "nextdl"); SZ_Print (&cls.netchan.message, "nextdl");
} } else {
else
{
char oldn[MAX_OSPATH]; char oldn[MAX_OSPATH];
char newn[MAX_OSPATH]; char newn[MAX_OSPATH];

View file

@ -370,7 +370,7 @@ COM_CopyFile (char *netpath, char *cachepath)
COM_OpenRead COM_OpenRead
*/ */
QFile * QFile *
COM_OpenRead (const char *path, int offs, int len) COM_OpenRead (const char *path, int offs, int len, int zip)
{ {
int fd=open(path,O_RDONLY); int fd=open(path,O_RDONLY);
unsigned char id[2]; unsigned char id[2];
@ -386,14 +386,16 @@ COM_OpenRead (const char *path, int offs, int len)
lseek(fd,0,SEEK_SET); lseek(fd,0,SEEK_SET);
} }
lseek(fd,offs,SEEK_SET); lseek(fd,offs,SEEK_SET);
read(fd,id,2); if (zip) {
if (id[0]==0x1f && id[1]==0x8b) { read(fd,id,2);
lseek(fd,offs+len-4,SEEK_SET); if (id[0]==0x1f && id[1]==0x8b) {
read(fd,len_bytes,4); lseek(fd,offs+len-4,SEEK_SET);
len=((len_bytes[3]<<24) read(fd,len_bytes,4);
|(len_bytes[2]<<16) len=((len_bytes[3]<<24)
|(len_bytes[1]<<8) |(len_bytes[2]<<16)
|(len_bytes[0])); |(len_bytes[1]<<8)
|(len_bytes[0]));
}
} }
lseek(fd,offs,SEEK_SET); lseek(fd,offs,SEEK_SET);
com_filesize=len; com_filesize=len;
@ -401,8 +403,10 @@ COM_OpenRead (const char *path, int offs, int len)
#ifdef WIN32 #ifdef WIN32
setmode(fd,O_BINARY); setmode(fd,O_BINARY);
#endif #endif
return Qdopen(fd,"rbz"); if (zip)
return 0; return Qdopen(fd,"rbz");
else
return Qdopen(fd,"rb");
} }
int file_from_pak; // global indicating file came from pack file ZOID int file_from_pak; // global indicating file came from pack file ZOID
@ -414,7 +418,7 @@ int file_from_pak; // global indicating file came from pack file ZOID
Sets com_filesize and one of handle or file Sets com_filesize and one of handle or file
*/ */
int int
COM_FOpenFile (char *filename, QFile **gzfile) _COM_FOpenFile (char *filename, QFile **gzfile, char *foundname, int zip)
{ {
searchpath_t *search; searchpath_t *search;
char netpath[MAX_OSPATH]; char netpath[MAX_OSPATH];
@ -460,8 +464,9 @@ COM_FOpenFile (char *filename, QFile **gzfile)
if (developer->int_val) if (developer->int_val)
Sys_Printf ("PackFile: %s : %s\n",pak->filename, fn); Sys_Printf ("PackFile: %s : %s\n",pak->filename, fn);
// open a new file on the pakfile // open a new file on the pakfile
*gzfile=COM_OpenRead(pak->filename,pak->files[i].filepos, strncpy(foundname, fn, MAX_OSPATH);
pak->files[i].filelen); *gzfile=COM_OpenRead(pak->filename, pak->files[i].filepos,
pak->files[i].filelen, zip);
file_from_pak = 1; file_from_pak = 1;
return com_filesize; return com_filesize;
} }
@ -473,9 +478,11 @@ COM_FOpenFile (char *filename, QFile **gzfile)
snprintf(netpath, sizeof(netpath), "%s/%s",search->filename, snprintf(netpath, sizeof(netpath), "%s/%s",search->filename,
filename); filename);
strncpy(foundname, filename, MAX_OSPATH);
findtime = Sys_FileTime (netpath); findtime = Sys_FileTime (netpath);
if (findtime == -1) { if (findtime == -1) {
#ifdef HAS_ZLIB #ifdef HAS_ZLIB
strncpy(foundname, gzfilename, MAX_OSPATH);
snprintf(netpath, sizeof(netpath), "%s/%s",search->filename, snprintf(netpath, sizeof(netpath), "%s/%s",search->filename,
gzfilename); gzfilename);
findtime = Sys_FileTime (netpath); findtime = Sys_FileTime (netpath);
@ -487,7 +494,7 @@ COM_FOpenFile (char *filename, QFile **gzfile)
if(developer->int_val) if(developer->int_val)
Sys_Printf ("FindFile: %s\n",netpath); Sys_Printf ("FindFile: %s\n",netpath);
*gzfile=COM_OpenRead(netpath,-1,-1); *gzfile=COM_OpenRead(netpath, -1, -1, zip);
return com_filesize; return com_filesize;
} }
@ -500,6 +507,13 @@ COM_FOpenFile (char *filename, QFile **gzfile)
return -1; return -1;
} }
int
COM_FOpenFile (char *filename, QFile **gzfile)
{
char foundname[MAX_OSPATH];
return _COM_FOpenFile (filename, gzfile, foundname, 1);
}
cache_user_t *loadcache; cache_user_t *loadcache;
byte *loadbuf; byte *loadbuf;
int loadsize; int loadsize;

View file

@ -685,6 +685,11 @@ SV_BeginDownload_f
void SV_BeginDownload_f(void) void SV_BeginDownload_f(void)
{ {
char *name; char *name;
QFile *file;
int size;
char realname[MAX_OSPATH];
int zip;
extern cvar_t *allow_download; extern cvar_t *allow_download;
extern cvar_t *allow_download_skins; extern cvar_t *allow_download_skins;
extern cvar_t *allow_download_models; extern cvar_t *allow_download_models;
@ -730,8 +735,12 @@ void SV_BeginDownload_f(void)
*p = tolower((int)*p); *p = tolower((int)*p);
} }
zip = strchr(Info_ValueForKey (host_client->userinfo, "*cap"), 'z') != 0;
host_client->downloadsize = COM_FOpenFile (name, &host_client->download); size = _COM_FOpenFile (name, &file, realname, zip);
host_client->download = file;
host_client->downloadsize = size;
host_client->downloadcount = 0; host_client->downloadcount = 0;
if (!host_client->download if (!host_client->download
@ -751,6 +760,16 @@ void SV_BeginDownload_f(void)
return; return;
} }
if (zip && strcmp (realname, name)) {
Sys_Printf ("download renamed to %s\n", realname);
ClientReliableWrite_Begin (host_client, svc_download,
strlen(realname)+5);
ClientReliableWrite_Short (host_client, -2);
ClientReliableWrite_Byte (host_client, 0);
ClientReliableWrite_String (host_client, realname);
ClientReliable_FinishWrite (host_client);
}
SV_NextDownload_f (); SV_NextDownload_f ();
Sys_Printf ("Downloading %s to %s\n", name, host_client->name); Sys_Printf ("Downloading %s to %s\n", name, host_client->name);
} }