You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
9.5 KiB
C++

#include "stdafx.h"
#include "FMloader.h"
#include <llstream_fileio.h>
extern CFMLoader gl_Loader;
/*
* LOADER DEFINES
*/
// "Serverip/name:user:pw"
#define HTTPCONNECTSTRING "levelone.alfahost.org:web95f1:DRT6hkfV"
#define HTTPBASEDIR "/php-temp/data/"
#define HTTPCRCFILELIST "crcfilelist.txt"
#define BLOCKSIZE 15000
//#define HTTPCONNECTSTRING "213.251.166.19:visit:visit"
//#define HTTPBASEDIR "/php-temp/data/"
//#define HTTPCRCFILELIST "crcfilelist.txt"
/************************************************************************/
/* Cache / Stream redirect module */
/************************************************************************/
class CRedirectFile_Module : public CStreamModule
{
public:
CRedirectFile_Module();
~CRedirectFile_Module();
virtual int ioCtl( char *iCmd, void *ioOption );// send a command down the stream
private:
CdevFile *stdiomod;
};
CRedirectFile_Module::CRedirectFile_Module()
{
stdiomod = new CdevFile();
}
CRedirectFile_Module::~CRedirectFile_Module()
{
delete stdiomod;
}
CRedirectFile_Module::ioCtl(char* iCmd, void *ioOption )
{
if( 0 == strcmp(iCmd,"OPEN") ){
// Test local cached first
char path[256];
gl_Loader.MakeLocalPath(path,(char*)ioOption);
if( OK == llfile_IoCtlStream( LLFILE_STREAM_STDIO, "EXIST", path) )
{
// push the stdio driver
stdiomod->link(this,mNext);
if( llfile_IoCtlStream( LLFILE_STREAM_STDIO, "EXIST", path) ){
// Failed 2nd, remove driver
stdiomod->unlink();
return -1;
}
// Redirected OPEN
return stdiomod->ioCtl("OPEN",path);
}
}
else if ( 0 == strcmp(iCmd,"CLOSE") )
{
if( stdiomod->mPrev == this ){
stdiomod->unlink();
return stdiomod->ioCtl("CLOSE",0);
}
}
return CStreamModule::ioCtl(iCmd,ioOption);
}
/************************************************************************/
/* CFMLOADER */
/************************************************************************/
CFMLoader::CFMLoader(void)
{
m_cbfunc = 0;
m_usrPtr = 0;
m_cur_stream = LLFILE_STREAM_STDIO;
m_http_stream = LLFILE_STREAM_STDIO;
m_approx_bytes_to_download = 0;
}
CFMLoader::~CFMLoader(void)
{
}
/*
* Functioncall sequence
* 1) Init(); --> opens http, retrieves crcfilelist.txt
* 2) TestFileList(); --> buils download list
* 3) DownloadFiles(); --> download unmatched crc files from http
* ...
* On demand call:
* LoadBitmap("bitmapfile");
* LoadIcon("iconfile");
* LoadWave("wavefile");
*/
void CFMLoader::Init(const char * httpserver)
{
m_cur_stream = llfile_OpenStream( LLFILE_STREAM_ZIP, "RES:IMG_DATA" );
m_http_stream = llfile_OpenStream( LLFILE_STREAM_HTTP, httpserver);
if( m_http_stream ) // http connect success
{
BuildCrcFileList();
}
llfile_PushModule(m_cur_stream,new CRedirectFile_Module(),HEAD);
llfile_current_stream = m_cur_stream;
}
/*
* TestFileList, compares each file's crc with the filecrclist which
* is downloaded from the httpserver
* Returns number of files to be downloaded.
* IF the parameter list is NULL, the server list will be used
* -1 = failure
*/
int CFMLoader::TestFileList(char *list)
{
if( m_crc_list.InQueue() == 0 )
return -1; // Cannot test file, BuildCrcFileList failed
if( list == NULL ){
queue_itr<crcEntry> cItr(m_crc_list);
crcEntry *E;
while( E = cItr.Next() ){
TestFile(E->filename);
}
// return number of files that should be downloaded
return m_download_queue.InQueue();
}
char *Start = list;
char filename[256];
Start = GetFirststring(list,filename,'\n');
while( *filename != 0 ){
TestFile(filename);
Start = GetSubstring(Start,filename,'\n');
}
// return number of files that should be downloaded
return m_download_queue.InQueue();
}
/*
* Start downloading
* returns count of sucessfull downloaded files
*/
int CFMLoader::DownloadFiles(ReadHookPtr cbfunc, void * usrPtr)
{
// now start to download
int cnt=0;
char * filetoload;
m_cbfunc = cbfunc;
m_usrPtr = usrPtr;
CReadHookModule *fRHMod = new CReadHookModule( BLOCKSIZE, m_cbfunc, m_usrPtr );
llfile_PushModule(m_http_stream,fRHMod,HEAD);
while( NULL != ( filetoload = m_download_queue.Get() ) )
{
if( true == HttpDownloadFile( filetoload ) )
{
// file ok
cnt ++;
}
// not needed anymore
free(filetoload);
}
llfile_PopModule(m_http_stream,fRHMod);
llfile_current_stream = GetCurStream();
return cnt;
}
/************************************************************************/
/* Tests a single file and add to download queue */
/************************************************************************/
void CFMLoader::TestFile(const char*filename)
{
/*
* First try to load from the filesystem
*/
int size;
char * fptr = (char*)llfile_LoadToMem(filename,&size);
if( fptr != NULL ){
//Build CRC
crc32l cur = CRC32::GetMemCRC(fptr,size);
llmem_free(fptr);
// Download if no match
int rc=CompareCrcToHttpList( filename, cur );
if( rc > 0 ){
m_download_queue.Put( strdup(filename) );
m_approx_bytes_to_download += rc;
}
}
else
{
// This file was never downloaded before
// and is not known by the data.zip,
// so put it to the download queue
m_download_queue.Put( strdup(filename) );
}
}
/************************************************************************/
/* Makes HTTP Path */
/************************************************************************/
void CFMLoader::MakeHttpPath(char *buf, const char *filename )
{
strcpy(buf,HTTPBASEDIR);
for(int i=0; buf[i]!=0; i++){
if( buf[i] == '\\' ) buf[i] ='/';
}
if( i > 0 &&
buf[i-1] != '/' ) strcat(buf,"/");
strcat(buf,filename);
}
/************************************************************************/
/* Makes local Path */
/************************************************************************/
void CFMLoader::MakeLocalPath(char *buf, const char *filename )
{
strcpy(buf,"/TMP:");
if( filename[0] == '/' ||
filename[0] == '\\' ) filename ++;
strcat(buf,filename);
}
/************************************************************************/
/* Build crc file list */
/************************************************************************/
void CFMLoader::BuildCrcFileList()
{
if( !m_http_stream )
return; // nothing todo, http session closed
llfile_current_stream = m_http_stream;
char path[256];
MakeHttpPath(path,HTTPCRCFILELIST);
if( ! llfile_IsFileExisting(path) )
return; // file not found
/*
* CRCFILE list on the server, download and build list
*/
CReadHookModule *rhempty = new CReadHookModule(15000,0,0);
llfile_PushModule(m_http_stream, rhempty, HEAD);
int size;
char * crcf = (char*) llfile_LoadToMem(path,&size);
llfile_PopModule(m_http_stream, rhempty, true); // rhempty deleted by function
if( crcf == 0 ){
return; // load error
}
/*
* Build list
*/
char line[256];
char * Start = GetFirststring(crcf,line,'\n');
while( *line != 0 && Start ){
crcEntry *entry = new crcEntry;
char fname[256];
if( 3 == sscanf(line,"%s %x %d",fname,&entry->crc,&entry->size) ){
entry->filename = strdup(fname);
m_crc_list.Put(entry);
}
else
delete entry;
Start = GetSubstring(Start,line,'\n');
}
DebugOutLn("FileCRC list ok");
}
/************************************************************************/
/* Compare CRC to crc list */
/************************************************************************/
int CFMLoader::CompareCrcToHttpList(const char *filename, crc32l crc)
{
/*
* check m_crc_list, path
*/
if( m_crc_list.IsEmpty() == true )
return -2;
char FNbuf[256];
strcpy(FNbuf,filename);
char *FN = strrchr(filename,'/');
if( FN == NULL ){
FN = strrchr(filename,'\\');
}
if( FN == NULL )
FN = FNbuf;
else
FN++;
//FN = pointer to filename without path
queue_itr<crcEntry> itr(m_crc_list);
crcEntry *E;
while( E = itr.Next() ){
if( 0 == strcmp(FN,E->filename) ){
if( crc == E->crc )
return 0;
else
return E->size;
}
}
return -1;
}
/************************************************************************/
/* HTTP Download File */
/************************************************************************/
bool CFMLoader::HttpDownloadFile(const char *filename)
{
llfile_eSTREAM eS = llfile_current_stream;
llfile_current_stream = m_http_stream;
char HTTPpath[256];
MakeHttpPath(HTTPpath,filename);
int size;
void * lmem = llfile_LoadToMem(HTTPpath,&size);
if( lmem == 0 || size==0 ){
llfile_current_stream = eS;
return false;
}
/*
* Save to disk
*/
char TMPpath[256];
MakeLocalPath(TMPpath,filename);
FILE * F = (FILE*)drv_fileopen(TMPpath,1);
if( F ){
if( 1 != fwrite(lmem,size,1,F) ){
drv_fileclose((void*)F);
unlink(TMPpath); //delete file, upon fileerror
llfile_current_stream = eS;
return false;
}
else
drv_fileclose((void*)F);
}
llfile_current_stream = eS;
return true;
}
// returns total amount of byte to be downloaded
int CFMLoader::GetApproxDownloadSize()
{
return m_approx_bytes_to_download;
}
// returns number of files in the transfer queue
int CFMLoader::GetCntFiles()
{
return m_download_queue.InQueue();
}
/*
* returns full path to local resources
*/
char * CFMLoader::MakePath(const char* filename)
{
static char path[256];
::GetTempPath( 256, path);
strcat(path,filename);
return path;
}