ftp/http stuff should work again. the download menu is still out of action, however.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1734 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2005-12-22 02:29:11 +00:00
parent a32c1af46d
commit 054663b990
8 changed files with 161 additions and 98 deletions

View file

@ -1,5 +1,10 @@
#include "quakedef.h"
#ifdef WEBCLIENT
//#define DOWNLOADMENU
#endif
#ifdef DOWNLOADMENU
#define ROOTDOWNLOADABLESSOURCE "http://fteqw.sourceforge.net/downloadables.txt"
#define INSTALLEDFILES "installed.lst" //the file that resides in the quakedir (saying what's installed).
@ -13,8 +18,6 @@
int dlcount=1;
extern char *com_basedir;
//note: these are allocated for the life of the exe
char *downloadablelist[256] = {
ROOTDOWNLOADABLESSOURCE
@ -51,7 +54,7 @@ typedef struct {
package_t *availablepackages;
int numpackages;
static package_t *BuildPackageList(FILE *f, int flags, char *prefix)
static package_t *BuildPackageList(vfsfile_t *f, int flags, char *prefix)
{
char line[1024];
package_t *p;
@ -62,13 +65,14 @@ static package_t *BuildPackageList(FILE *f, int flags, char *prefix)
do
{
fgets(line, sizeof(line)-1, f);
if (!VFS_GETS(f, line, sizeof(line)-1))
break;
while((sl=strchr(line, '\n')))
*sl = '\0';
while((sl=strchr(line, '\r')))
*sl = '\0';
Cmd_TokenizeString (line, false, false);
} while (!feof(f) && !Cmd_Argc());
} while (!Cmd_Argc());
if (strcmp(Cmd_Argv(0), "version"))
return NULL; //it's not the right format.
@ -80,9 +84,9 @@ static package_t *BuildPackageList(FILE *f, int flags, char *prefix)
return NULL; //it's not the right version.
}
while(!feof(f))
while(1)
{
if (!fgets(line, sizeof(line)-1, f))
if (!VFS_GETS(f, line, sizeof(line)-1))
break;
while((sl=strchr(line, '\n')))
*sl = '\0';
@ -155,23 +159,27 @@ static package_t *BuildPackageList(FILE *f, int flags, char *prefix)
static void WriteInstalledPackages(void)
{
char *s;
package_t *p;
char *fname = va("%s/%s", com_basedir, INSTALLEDFILES);
FILE *f = fopen(fname, "wb");
vfsfile_t *f = FS_OpenVFS(INSTALLEDFILES, "wb", FS_BASE);
if (!f)
{
Con_Printf("menu_download: Can't update installed list\n");
return;
}
fprintf(f, "version 1\n");
s = "version 1\n";
VFS_WRITE(f, s, strlen(s));
for (p = availablepackages; p ; p=p->next)
{
if (p->flags & DPF_HAVEAVERSION)
fprintf(f, "\"%s\" \"%s\" \"%s\" %i \"%s\"\n", p->fullname, p->src, p->dest, p->version, p->gamedir);
{
s = ("\"%s\" \"%s\" \"%s\" %i \"%s\"\n", p->fullname, p->src, p->dest, p->version, p->gamedir);
VFS_WRITE(f, s, strlen(s));
}
}
fclose(f);
VFS_CLOSE(f);
}
static qboolean ComparePackages(package_t **l, package_t *p)
@ -236,14 +244,14 @@ static void ConcatPackageLists(package_t *l2)
static void dlnotification(char *localfile, qboolean sucess)
{
int i;
FILE *f;
vfsfile_t *f;
COM_RefreshFSCache_f();
COM_FOpenFile(localfile, &f);
f = FS_OpenVFS (localfile, "rb", FS_BASE);
if (f)
{
i = atoi(localfile+7);
ConcatPackageLists(BuildPackageList(f, 0, downloadablelistnameprefix[i]));
fclose(f);
VFS_CLOSE(f);
}
}
@ -489,14 +497,20 @@ void Menu_DownloadStuff_f (void)
{
static qboolean loadedinstalled;
char *fname = va("%s/%s", com_basedir, INSTALLEDFILES);
FILE *f = loadedinstalled?NULL:fopen(fname, "rb");
vfsfile_t *f = loadedinstalled?NULL:FS_OpenVFS(INSTALLEDFILES, "rb", FS_BASE);
loadedinstalled = true;
if (f)
{
ConcatPackageLists(BuildPackageList(f, DPF_DELETEONUNINSTALL|DPF_HAVEAVERSION|DPF_WANTTOINSTALL, ""));
fclose(f);
VFS_CLOSE(f);
}
}
}
#elif defined(WEBCLIENT)
void Menu_DownloadStuff_f (void)
{
Con_Printf("Not yet reimplemented\n");
}
#endif

View file

@ -114,8 +114,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect')
#define FISH //sw rendering only
#define ZLIB //zip/pk3 support
// #define WEBSERVER //http/ftp servers
// #define WEBCLIENT //http/ftp clients.
#define WEBSERVER //http/ftp servers
#define WEBCLIENT //http/ftp clients.
#define RUNTIMELIGHTING //calculate lit/lux files the first time the map is loaded and doesn't have a loadable lit.
// #define QTERM //qterm... adds a console command that allows running programs from within quake - bit like xterm.
#define CL_MASTER //query master servers and stuff for a dynamic server listing.

View file

@ -307,6 +307,7 @@ typedef struct vfsfile_s {
unsigned long (*Tell) (struct vfsfile_s *file);
unsigned long (*GetLen) (struct vfsfile_s *file); //could give some lag
void (*Close) (struct vfsfile_s *file);
void (*Flush) (struct vfsfile_s *file);
} vfsfile_t;
#define VFS_CLOSE(vf) (vf->Close(vf))
@ -315,8 +316,8 @@ typedef struct vfsfile_s {
#define VFS_SEEK(vf,pos) (vf->Seek(vf,pos))
#define VFS_READ(vf,buffer,buflen) (vf->ReadBytes(vf,buffer,buflen))
#define VFS_WRITE(vf,buffer,buflen) (vf->WriteBytes(vf,buffer,buflen))
#define VFS_FLUSH(vf)
#define VFS_GETS(vf,buffer,buflen) Sys_Error("VFS_GETS not implemented"),false //:(
#define VFS_FLUSH(vf) do{if(vf->Flush)vf->Flush(vf);}while(0)
#define VFS_GETS(vf,buffer,buflen) (Sys_Error("VFS_GETS not implemented"),false) //:(
void FS_Remove(char *fname, int relativeto);
vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto);

View file

@ -234,7 +234,7 @@ iwboolean FTP_ClientConnThink (FTPclientconn_t *con) //true to kill con
}
while((len = recv(con->datasock, readdata, sizeof(readdata), 0)) >0 )
{
IWebFWrite(readdata, len, 1, con->f);
VFS_WRITE(con->f, readdata, len);
con->transfered += len;
}
if (len == 0)
@ -248,14 +248,14 @@ iwboolean FTP_ClientConnThink (FTPclientconn_t *con) //true to kill con
int pos, sent;
int ammount, wanted = sizeof(readdata);
pos = IWebFTell(con->f);
ammount = IWebFRead(readdata, 1, wanted, con->f);
pos = VFS_TELL(con->f);
ammount = VFS_READ(con->f, readdata, wanted);
sent = send(con->datasock, readdata, ammount, 0);
if (sent == -1)
IWebFSeek(con->f, pos, SEEK_SET); //go back. Too much data
VFS_SEEK(con->f, pos); //go back. Too much data
else
{
IWebFSeek(con->f, pos + sent, SEEK_SET); //written this much
VFS_SEEK(con->f, pos + sent); //written this much
if (!ammount) //file is over
{
@ -380,7 +380,7 @@ iwboolean FTP_ClientConnThink (FTPclientconn_t *con) //true to kill con
con->stage = 6;
if (con->type == ftp_getting)
{
con->f = IWebFOpenWrite(con->localfile, false);
con->f = FS_OpenVFS(con->localfile, "wb", FS_GAME);
if (con->f)
{
sprintf(tempbuff, "RETR %s\r\n", con->file);
@ -396,7 +396,7 @@ iwboolean FTP_ClientConnThink (FTPclientconn_t *con) //true to kill con
}
else if (con->type == ftp_putting)
{
con->f = IWebFOpenRead(con->localfile);
con->f = FS_OpenVFS (con->localfile, "rb", FS_GAME);
if (con->f)
{
sprintf(tempbuff, "STOR %s\r\n", con->file);
@ -438,7 +438,7 @@ usepasv:
{
COM_StripExtension(con->localfile, msg);
strcat(msg, ".tmp");
con->f = IWebFOpenWrite(msg, false);
con->f = FS_OpenVFS (msg, "wb", FS_GAME);
if (!con->f)
{
msg = va("ABOR\r\nQUIT\r\n"); //bummer. we couldn't open this file to output to.
@ -472,10 +472,10 @@ usepasv:
}
con->transfered+=len;
data[len] = 0;
IWebFWrite(data, len, 1, con->f);
VFS_WRITE(con->f, data, len);
}
}
IWebFClose(con->f);
VFS_CLOSE(con->f);
con->f = NULL;
closesocket(con->datasock);
con->datasock = INVALID_SOCKET;
@ -535,7 +535,7 @@ usepasv:
{
if (con->type == ftp_getting)
{
con->f = IWebFOpenWrite(con->localfile, false);
con->f = FS_OpenVFS(con->localfile, "wb", FS_GAME);
if (con->f)
{
con->stage = 8;
@ -557,13 +557,13 @@ usepasv:
}
else if (con->type == ftp_putting)
{
con->f = IWebFOpenRead(con->localfile);
con->f = FS_OpenVFS(con->localfile, "rb", FS_GAME);
if (con->f)
{
msg = va("STOR %s\r\n", con->file);
con->stage = 6;
con->transfered = 0;
con->transfersize = con->f->length;
con->transfersize = VFS_GETLEN(con->f);
}
else
{
@ -642,7 +642,7 @@ void FTP_ClientThink (void)
cls.downloadmethod = DL_NONE;
}
if (con->f)
IWebFClose(con->f);
VFS_CLOSE(con->f);
if (con->controlsock != INVALID_SOCKET)
closesocket(con->controlsock);
if (con->datasock != INVALID_SOCKET)

View file

@ -35,7 +35,7 @@ typedef struct FTPclient_s{
int datasock; //FTP only allows one transfer per connection.
int dataislisten;
int datadir; //0 no data, 1 reading, 2 writing
IWEBFILE *file;
vfsfile_t *file;
unsigned long blocking;
@ -238,18 +238,18 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
int pos, sent;
int ammount, wanted = sizeof(resource);
pos = IWebFTell(cl->file);
ammount = IWebFRead(resource, 1, wanted, cl->file);
pos = VFS_TELL(cl->file);
ammount = VFS_READ(cl->file, resource, wanted);
sent = send(cl->datasock, resource, ammount, 0);
if (sent == -1)
{
IWebFSeek(cl->file, pos, SEEK_SET);
VFS_SEEK(cl->file, pos);
if (qerrno != EWOULDBLOCK)
{
closesocket(cl->datasock);
cl->datasock = INVALID_SOCKET;
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
QueueMessage (cl, "226 Transfer complete .\r\n");
@ -259,7 +259,7 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
else
{
if (sent != ammount)
IWebFSeek(cl->file, pos + sent, SEEK_SET);
VFS_SEEK(cl->file, pos + sent);
if (ammount != wanted && sent == ammount) //file is over
{
@ -268,7 +268,7 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
send(cl->datasock, resource, 0, 0);
closesocket(cl->datasock);
cl->datasock = INVALID_SOCKET;
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
QueueMessage (cl, "226 Transfer complete .\r\n");
@ -281,7 +281,7 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
int len;
while((len = recv(cl->datasock, resource, sizeof(resource), 0)) >0 )
{
IWebFWrite(resource, len, 1, cl->file);
VFS_WRITE(cl->file, resource, len);
}
if (len == -1)
{
@ -290,7 +290,7 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
closesocket(cl->datasock);
cl->datasock = INVALID_SOCKET;
if (cl->file)
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
QueueMessage (cl, "226 Transfer complete .\r\n");
@ -300,7 +300,7 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
if (len == 0)
{
QueueMessage (cl, "226 Transfer complete .\r\n");
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
cl->datadir = 0;
}
@ -586,14 +586,14 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
if (*resource == '/')
{
if (SV_AllowDownload(resource+1))
cl->file = IWebFOpenRead(resource+1);
cl->file = FS_OpenVFS(resource+1, "rb", FS_GAME);
else
cl->file = IWebGenerateFile(resource+1, NULL, 0);
}
else
{
if (SV_AllowDownload(resource))
cl->file = IWebFOpenRead(resource);
cl->file = FS_OpenVFS(resource, "rb", FS_GAME);
else
cl->file = IWebGenerateFile(resource, NULL, 0);
}
@ -653,14 +653,14 @@ iwboolean FTP_ServerThinkForConnection(FTPclient_t *cl)
else
sprintf(resource, "%s%s", cl->path, mode);
cl->file = IWebFOpenRead(resource);
cl->file = FS_OpenVFS(resource, "rb", FS_GAMEONLY);
if (cl->file)
{
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
QueueMessage (cl, "550 File already exists.\r\n");
continue;
}
cl->file = IWebFOpenWrite(resource, false);
cl->file = FS_OpenVFS(resource, "wb", FS_GAME);
if (!cl->file)
{
@ -726,7 +726,7 @@ unsigned int WINAPI BlockingClient(FTPclient_t *cl)
}
if (cl->file)
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
closesocket(cl->controlsock);
if (cl->datasock)
closesocket(cl->datasock);
@ -762,7 +762,7 @@ unsigned long _true = true;
if (FTP_ServerThinkForConnection(cl))
{
if (cl->file)
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
closesocket(cl->controlsock);
if (cl->datasock)
closesocket(cl->datasock);

View file

@ -47,7 +47,7 @@ typedef struct http_con_s {
int contentlength;
IWEBFILE *file;
vfsfile_t *file;
void (*NotifyFunction)(char *localfile, qboolean sucess); //called when failed or succeeded, and only if it got a connection in the first place.
struct http_con_s *next;
@ -201,7 +201,7 @@ static qboolean HTTP_CL_Run(http_con_t *con)
con->bufferused -= ammount;
con->file = IWebFOpenWrite(con->filename, false);
con->file = FS_OpenVFS(con->filename, "wb", FS_GAME);
if (!con->file)
{
Con_Printf("HTTP: Couldn't open file %s\n", con->filename);
@ -210,7 +210,7 @@ static qboolean HTTP_CL_Run(http_con_t *con)
if (!con->file)
{
IWebFWrite(con->buffer+ammount, con->bufferused, 1, con->file);
VFS_WRITE(con->file, con->buffer+ammount, con->bufferused);
con->bufferused = 0;
}
else
@ -281,7 +281,7 @@ static qboolean HTTP_CL_Run(http_con_t *con)
con->totalreceived+=con->chunked;
if (con->file && con->chunked) //we've got a chunk in the buffer
{ //write it
IWebFWrite(con->buffer, con->chunked, 1, con->file);
VFS_WRITE(con->file, con->buffer, con->chunked);
//and move the unparsed chunk to the front.
con->bufferused -= con->chunked;
memmove(con->buffer, con->buffer+con->chunked, con->bufferused);
@ -293,7 +293,7 @@ static qboolean HTTP_CL_Run(http_con_t *con)
con->totalreceived+=ammount;
if (con->file) //we've got a chunk in the buffer
{ //write it
IWebFWrite(con->buffer, con->bufferused, 1, con->file);
VFS_WRITE(con->file, con->buffer, con->bufferused);
con->bufferused = 0;
}
}
@ -306,7 +306,7 @@ static qboolean HTTP_CL_Run(http_con_t *con)
Con_Printf("Recieved file isn't the correct length - must be corrupt - %s\n", con->filename);
Con_Printf("Retrieved %s\n", con->filename);
if (con->file)
IWebFClose(con->file);
VFS_CLOSE(con->file);
else
{
snprintf(Location, sizeof(Location)-1, "%s/%s", com_gamedir, con->filename);

View file

@ -152,7 +152,7 @@ void HTTP_RunExisting (void)
if (cl->outbuffer)
IWebFree(cl->outbuffer);
if (cl->file)
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
IWebFree(cl);
httpconnectioncount--;
cl = prev;
@ -328,7 +328,7 @@ cont:
if (!strnicmp(mode, "P", 1)) //when stuff is posted, data is provided. Give an error message if we couldn't do anything with that data.
cl->file = IWebGenerateFile(resource+1, content, contentlen);
else
cl->file = IWebFOpenRead(resource);
cl->file = FS_OpenVFS(resource, "rb", FS_GAME);
if (!cl->file)
{
if (HTTPmarkup >= 3)
@ -349,9 +349,9 @@ cont:
else
{
if (HTTPmarkup>=3)
sprintf(resource, "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", cl->file->length);
sprintf(resource, "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", VFS_GETLEN(cl->file));
else if (HTTPmarkup==2)
sprintf(resource, "HTTP/1.0 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", cl->file->length);
sprintf(resource, "HTTP/1.0 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %i\r\n" "Server: "FULLENGINENAME"/0\r\n" "\r\n", strstr(resource, ".htm")?"text/html":"text/plain", VFS_GETLEN(cl->file));
else if (HTTPmarkup)
sprintf(resource, "HTTP/0.9 200 OK\r\n\r\n");
else
@ -361,7 +361,7 @@ cont:
if (*mode == 'H' || *mode == 'h')
{
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
}
@ -413,11 +413,11 @@ notimplemented:
{
ExpandOutBuffer(cl, 1500, true);
wanted = cl->outbuffersize - cl->outbufferused;
ammount = IWebFRead(cl->outbuffer+cl->outbufferused, 1, wanted, cl->file);
ammount = VFS_READ(cl->file, cl->outbuffer+cl->outbufferused, wanted);
if (!ammount)
{
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
}
else
@ -457,7 +457,7 @@ notimplemented:
{
if (qerrno != EWOULDBLOCK) //they closed on us. Assume end.
{
IWebFClose(cl->file);
VFS_CLOSE(cl->file);
cl->file = NULL;
cl->close = true;
continue;

View file

@ -326,13 +326,82 @@ IWebFile_t IWebFiles[] = {
typedef struct {
vfsfile_t funcs;
char *buffer;
int length;
int pos;
} vfsmemory_t;
vfsfile_t *VFSMEM_FromZMalloc(char *buffer, int length)
IWeb_FileGen_t *buffer;
int pos;
} vfsgen_t;
int VFSGen_ReadBytes(vfsfile_t *f, char *buffer, int bytes)
{
vfsgen_t *g = (vfsgen_t*)f;
if (bytes + g->pos >= g->buffer->len)
{
bytes = g->buffer->len - g->pos;
if (bytes <= 0)
return 0;
}
memcpy(buffer, g->buffer->data+g->pos, bytes);
g->pos += bytes;
return bytes;
}
int VFSGen_WriteBytes(vfsfile_t *f, char *buffer, int bytes)
{
Sys_Error("VFSGen_WriteBytes: Readonly\n");
return 0;
}
qboolean VFSGen_Seek(vfsfile_t *f, unsigned long newpos)
{
vfsgen_t *g = (vfsgen_t*)f;
if (newpos < 0 || newpos >= g->buffer->len)
return false;
g->pos = newpos;
return true;
}
int VFSGen_Tell(vfsfile_t *f)
{
vfsgen_t *g = (vfsgen_t*)f;
return g->pos;
}
int VFSGen_GetLen(vfsfile_t *f)
{
vfsgen_t *g = (vfsgen_t*)f;
return g->buffer->len;
}
void VFSGen_Close(vfsfile_t *f)
{
vfsgen_t *g = (vfsgen_t*)f;
g->buffer->references--;
if (!g->buffer->references)
{
Z_Free(g->buffer->data);
Z_Free(g->buffer);
}
Z_Free(g);
}
vfsfile_t *VFSGen_Create(IWeb_FileGen_t *gen)
{
vfsgen_t *ret;
ret = Z_Malloc(sizeof(vfsgen_t));
ret->funcs.ReadBytes = VFSGen_ReadBytes;
ret->funcs.WriteBytes = VFSGen_WriteBytes;
ret->funcs.Seek = VFSGen_Seek;
ret->funcs.Tell = VFSGen_Tell;
ret->funcs.GetLen = VFSGen_GetLen;
ret->funcs.Close = VFSGen_Close;
return (vfsfile_t*)ret;
}
vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength)
@ -346,7 +415,7 @@ vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength)
if (*lastrecordedmvd && !strcmp(name, "lastdemo.mvd"))
if (strcmp(name, "lastdemo.mvd")) //no infinate loops please...
return IWebFOpenRead(lastrecordedmvd);
return FS_OpenVFS(lastrecordedmvd, "rb", FS_GAME);
parms = strchr(name, '?');
if (!parms)
@ -363,7 +432,6 @@ vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength)
{
if (!Q_strncasecmp(name, IWebFiles[fnum].name, len+1))
{
IWEBFILE *ret;
if (IWebFiles[fnum].buffer)
{
if (IWebFiles[fnum].lastgenerationtime+10 < Sys_DoubleTime() || contentlength||*parms) //10 sec lifetime
@ -383,33 +451,13 @@ vfsfile_t *IWebGenerateFile(char *name, char *content, int contentlength)
IWebFiles[fnum].GenerationFunction(parms, content, contentlength);
IWebFiles[fnum].buffer = IWeb_GenerationBuffer;
if (!contentlength)
{
IWeb_GenerationBuffer->references++; //so it can't be sent once and freed instantly.
IWebFiles[fnum].lastgenerationtime = Sys_DoubleTime();
}
else
IWebFiles[fnum].lastgenerationtime = -10;
}
ret = VFSMEM_FromZMalloc
ret = IWebMalloc(sizeof(vfsfile_t));
if (!ret)
{
BZ_Free(IWeb_GenerationBuffer);
return NULL;
//so it can't be sent once and freed instantly.
IWebFiles[fnum].lastgenerationtime = Sys_DoubleTime();
}
ret->f = NULL;
ret->bufferdata = IWebFiles[fnum].buffer;
ret->length = ret->bufferdata->len;
ret->bufferdata->references++;
ret->pos = 0;
ret->start = 0;
ret->end = ret->start+ret->length;
IWebFiles[fnum].buffer->references++;
IWeb_GenerationBuffer = NULL;
return ret;
return VFSGen_Create(IWebFiles[fnum].buffer);
}
}
return NULL;