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++
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;
|
|
}
|