mirror of
https://github.com/ogoguel/activegs-ios.git
synced 2024-10-06 00:58:35 +00:00
628 lines
12 KiB
C++
628 lines
12 KiB
C++
/*
|
||
ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS
|
||
Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net
|
||
This code is covered by the GNU GPL licence
|
||
*/
|
||
|
||
#include "ActiveDownload.h"
|
||
//#include <sys/stat.h>
|
||
|
||
#include "ki.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#endif
|
||
|
||
const char * activegsdownloaddir = "_DOWNLOADCACHE";
|
||
const char * activegspersistentdir = "ActiveGSLocalData";
|
||
|
||
|
||
MyString CDownload::persistentPath ;
|
||
//CDownload g_download;
|
||
|
||
int calcCRC(const MYCHAR* ptr)
|
||
{
|
||
int crc=0;
|
||
int l = 0;
|
||
while(*ptr)
|
||
{
|
||
crc ^= *ptr << (l%24);
|
||
ptr++;
|
||
l+=3;
|
||
}
|
||
return crc;
|
||
}
|
||
|
||
|
||
MyString getfilenoext(const MYCHAR *url)
|
||
{
|
||
MyString tmp(getfile(url));
|
||
int pos = tmp.ReverseFind('.');
|
||
return tmp.substr(0,pos);
|
||
}
|
||
|
||
|
||
MyString CDownload::getPersistentDir(const char* url)
|
||
{
|
||
MyString dir;
|
||
// dir.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%s.%08X",getPersistentPath(),getfilenoext(url),calcCRC(url));
|
||
|
||
dir = getPersistentPath();
|
||
dir += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
dir += getfilenoext(url) ;
|
||
/*
|
||
MyString urldir;
|
||
getdir(url,urldir);
|
||
*/
|
||
MyString temp;
|
||
temp.Format(".%08X",calcCRC(url));
|
||
dir += temp.c_str();
|
||
return dir ;
|
||
}
|
||
|
||
bool CDownload::retrieveZippedFile(const MYCHAR* url,int _order,MyString& _path,MyString& _short)
|
||
{
|
||
return retrievePersistentZippedFile(url,_order,_path,_short);
|
||
/*
|
||
|
||
if (bUsePersistentPath)
|
||
return retrievePersistentZippedFile(url,_order,_path,_short);
|
||
else
|
||
return retrieveCachedZippedFile(url,_order,_path,_short);
|
||
*/
|
||
}
|
||
|
||
|
||
// *****************************************************************
|
||
|
||
|
||
// *****************************************************************
|
||
|
||
|
||
CDownload::CDownload(const char* _baseURL)
|
||
{
|
||
requiredExt = NULL;
|
||
bTestOnly = false;
|
||
bNotifyDownloadFailure = true;
|
||
#if defined(DRIVER_ANDROID)
|
||
fromMainThread = true;
|
||
#endif
|
||
setBaseURL(_baseURL);
|
||
|
||
|
||
}
|
||
|
||
void CDownload::deleteDownloadDirectory()
|
||
{
|
||
// détruit le répertoire de téléchargement
|
||
MyString dir;
|
||
dir = getPersistentPath();
|
||
dir += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
dir += activegsdownloaddir;
|
||
deleteDirectory(dir.c_str(),1);
|
||
|
||
}
|
||
|
||
CDownload::~CDownload()
|
||
{
|
||
}
|
||
|
||
bool CDownload::retrieveDistantFile(const char* _url,int _order,MyString& _path, MyString& _short)
|
||
{
|
||
|
||
MyString url;
|
||
normalize(_url,url);
|
||
|
||
|
||
MyString ext(getext(url.c_str()));
|
||
bool bZip = !ext.CompareNoCase("zip");
|
||
bool bRet;
|
||
|
||
if (bZip)
|
||
{
|
||
// essaie de rÈcupÈrer la version existante ?
|
||
|
||
bRet = retrieveZippedFile(url.c_str(),_order,_path,_short);
|
||
|
||
if (!bRet)
|
||
{
|
||
if (bTestOnly)
|
||
return false;
|
||
|
||
// essaie de downloader
|
||
bRet = downloadHTTPFile(url.c_str(),_path);
|
||
|
||
if (bRet)
|
||
{
|
||
if (!unzipFile(url.c_str(),_path.c_str()))
|
||
{
|
||
// unzip failed...
|
||
outputInfo("unzip failed (%s)\n",getfile(url.c_str()));
|
||
bRet=false;
|
||
deleteFile(_path.c_str());
|
||
outputInfo("deleting file (%s) for recovery next time \n",getfile(_path.c_str()));
|
||
|
||
}
|
||
|
||
if (bRet)
|
||
bRet = retrieveZippedFile(url.c_str(),_order,_path,_short);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
// if (bUsePersistentPath)
|
||
{
|
||
// fichier distant non zip
|
||
MyString dir;
|
||
MyString local;
|
||
|
||
dir = getPersistentDir(url.c_str());
|
||
createDirectory(dir.c_str());
|
||
local = dir.c_str();
|
||
local += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
local += getfile(url.c_str()) ;
|
||
|
||
// regarde si le fichier existe ?
|
||
// QUID SI LE FICHIER EST CORROMPU ?
|
||
|
||
FILE* f = fopen(local.c_str(),"rb");
|
||
if (f)
|
||
{
|
||
fclose(f);
|
||
bRet=true;
|
||
}
|
||
else
|
||
{
|
||
// ret<65>l<EFBFBD>charge le fichier
|
||
if (bTestOnly)
|
||
return false;
|
||
bRet = GetFile(url.c_str(),local.c_str());
|
||
|
||
}
|
||
if (bRet)
|
||
_path = local;
|
||
}
|
||
/*
|
||
else
|
||
bRet = downloadHTTPFile(url.c_str(),_path);
|
||
*/
|
||
|
||
if (bRet)
|
||
_short = getfile(_path.c_str());
|
||
|
||
}
|
||
|
||
if (!bRet)
|
||
{
|
||
// showProgress(url.c_str(),-1);
|
||
::showStatus("Failed to download %s\n",getfile(url.c_str()));
|
||
}
|
||
return bRet;
|
||
|
||
}
|
||
|
||
int CDownload::fileExists(const char * _path)
|
||
{
|
||
FILE* f = fopen(_path,"rb");
|
||
if (f)
|
||
{
|
||
fclose(f);
|
||
return 1;
|
||
}
|
||
else
|
||
return 0;
|
||
}
|
||
// *****************************************************************
|
||
|
||
long CDownload::retrieveLocalFile(const MYCHAR* _url,int _order,MyString& _path, MyString& _short)
|
||
{
|
||
|
||
MyString url = _url;
|
||
|
||
MyString ext(getext(url));
|
||
|
||
if (!ext.CompareNoCase("zip"))
|
||
{
|
||
|
||
if (!retrieveZippedFile(url,_order,_path,_short))
|
||
{
|
||
if (!unzipFile(url,url))
|
||
{
|
||
// unzip failed...
|
||
outputInfo("unzip failed (%s)\n",_url);
|
||
return 0;
|
||
}
|
||
if (!retrieveZippedFile(url,_order,_path,_short))
|
||
{
|
||
outputInfo("could not find zip (%s)\n",_url);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
_path = url;
|
||
|
||
_short = getfile(url);
|
||
}
|
||
|
||
|
||
|
||
FILE* f = fopen(_path.c_str(),"rb");
|
||
if (f)
|
||
{
|
||
/*int err =*/ fseek(f,0,SEEK_END);
|
||
long size = ftell(f);
|
||
fclose(f);
|
||
return size;
|
||
}
|
||
else
|
||
{
|
||
outputInfo("could not find file (%s)\n",_url);
|
||
::showStatus("Failed to load %s",getfile(_url));
|
||
return 0;
|
||
}
|
||
|
||
}
|
||
|
||
bool CDownload::makeAbsolutePath(const char* _myp, const char* _base,MyString& _dest)
|
||
{
|
||
|
||
MyString p = _myp;
|
||
MyString header5 = p.Left(5);
|
||
MyString header17 = p.Left(17);
|
||
MyString header8 = p.Left(8);
|
||
MyString header7 = p.Left(7);
|
||
|
||
bool bAbsolute= true;
|
||
|
||
// OG 190110 Added \ for WinCE devices
|
||
if ( ( p[0]=='\\') || ( p[0]=='/') || ( p[1]==':') || (!header5.CompareNoCase("http:")) )
|
||
_dest = p; // absolute path
|
||
else
|
||
if (!header17.CompareNoCase("file://localhost/"))
|
||
_dest = p.substr(17,p.length()-17); // absolute path for opera
|
||
else
|
||
if (!header8.CompareNoCase("file:///"))
|
||
#ifdef WIN32
|
||
_dest = p.substr(8,p.length()-8); // absolute path
|
||
#else
|
||
_dest = p.substr(7,p.length()-7); // keep the / on mac
|
||
#endif
|
||
else
|
||
if (!header7.CompareNoCase("file://"))
|
||
_dest = p.substr(7,p.length()-7); // absolute path
|
||
else
|
||
{
|
||
// newurl.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%s",baseURL,p.c_str());
|
||
_dest = _base;
|
||
_dest += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
_dest += p.c_str();
|
||
bAbsolute = false;
|
||
}
|
||
|
||
return bAbsolute;
|
||
}
|
||
|
||
|
||
int CDownload::parseFilenameAndMakeAbsolute(const char* _myp, int& _order, MyString &newurl)
|
||
{
|
||
|
||
MyString p(_myp);
|
||
|
||
// ignore #id= dans l'url
|
||
int pos = p.ReverseFind("#id=");
|
||
if (pos!=-1)
|
||
p = p.Left(pos);
|
||
|
||
// récupère le #order si présent
|
||
pos = p.ReverseFind("#pos=");
|
||
if (pos!=-1)
|
||
{
|
||
MyString orderstr = p.Mid(pos+5).c_str();
|
||
_order = atoi(orderstr.c_str());
|
||
if (_order<0 || _order>9)
|
||
_order = 0;
|
||
p = p.Left(pos);
|
||
}
|
||
else
|
||
_order = 0;
|
||
|
||
ASSERT (!baseURL.IsEmpty());
|
||
makeAbsolutePath(p.c_str(),baseURL.c_str(),newurl);
|
||
|
||
// OG 03-NOV-03
|
||
// Added files network support
|
||
if ( (newurl[0]=='/') || (newurl[1]==':') || ( (newurl[0]=='\\') /*&& (newurl[1]=='\\')*/ ) )
|
||
return 1; //localPath = true;
|
||
else
|
||
return 0;
|
||
|
||
}
|
||
|
||
// *****************************************************************
|
||
|
||
size_t CDownload::retrieveFile(const char* _myp,MyString& _path,MyString& _short)
|
||
{
|
||
size_t ret;
|
||
|
||
|
||
_path.clear();
|
||
if (!_myp || !_myp[0] ) return false;
|
||
|
||
int _order;
|
||
MyString newurl ;
|
||
int localPath = parseFilenameAndMakeAbsolute(_myp,_order,newurl);
|
||
|
||
/*
|
||
MyString normalized;
|
||
normalize(newurl.c_str(),normalized);
|
||
*/
|
||
|
||
if (localPath)
|
||
ret = retrieveLocalFile(newurl.c_str(),_order,_path,_short);
|
||
else
|
||
{
|
||
/*
|
||
if (_bSizeOnly)
|
||
{
|
||
outputInfo("size only not implemented for distant file (%s)\n",newurl.c_str());
|
||
return 0;
|
||
}
|
||
*/
|
||
ret = retrieveDistantFile(newurl.c_str(),_order,_path,_short);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
const char* getext(const char* _filename)
|
||
{
|
||
MyString tmp(_filename);
|
||
int pos = tmp.ReverseFind('.');
|
||
return _filename+pos+1;
|
||
}
|
||
|
||
|
||
void geturldomain(const char* p,MyString& _domain)
|
||
{
|
||
if (strncasecmp(p,"http:",5))
|
||
_domain = "(local)";
|
||
else
|
||
{
|
||
int l = 7;
|
||
while(p[l] && p[l]!='/') l++;
|
||
char ldir[1024];
|
||
strncpy(ldir,p+7,l-7);
|
||
ldir[l-7]=0;
|
||
_domain = ldir;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void geturldir(const char* p,MyString& _dir)
|
||
{
|
||
// avance jusqu'à un possible'?'
|
||
int l = 0;
|
||
while(p[l] && p[l]!='#') l++;
|
||
if (!l) return ; // chaine vide
|
||
l--;
|
||
// int l=(int)strlen(p)-1;
|
||
while(l>=0) {
|
||
if ( (p[l]=='\\') || (p[l]=='/') )
|
||
break;
|
||
l--;
|
||
}
|
||
char ldir[1024];
|
||
if (l<0)l=0;
|
||
strncpy(ldir,p,l);
|
||
ldir[l]=0;
|
||
_dir = ldir;
|
||
|
||
}
|
||
|
||
|
||
void getdir(const char* p,MyString& _dir)
|
||
{
|
||
int l=(int)strlen(p)-1;
|
||
while(l>=0) {
|
||
if ( (p[l]=='\\') || (p[l]=='/') )
|
||
break;
|
||
l--;
|
||
}
|
||
char ldir[512];
|
||
if (l<0)l=0;
|
||
strncpy(ldir,p,l);
|
||
ldir[l]=0;
|
||
_dir = ldir;
|
||
|
||
}
|
||
|
||
const MYCHAR* getfile(const MYCHAR* p)
|
||
{
|
||
MyString tmp(p);
|
||
int lastslash = tmp.ReverseFind('\\');
|
||
int lastantislash = tmp.ReverseFind('/');
|
||
int pos = lastslash>lastantislash?lastslash:lastantislash;
|
||
return p+pos+1;
|
||
|
||
}
|
||
|
||
void normalize(const MYCHAR* file,MyString& dest)
|
||
{
|
||
MyString work(file);
|
||
work.Replace("\\","/");
|
||
|
||
/*
|
||
// TODO
|
||
const MYCHAR*p;
|
||
|
||
const MYCHAR* find=_MYT("/../");
|
||
while(1) //p=strstr(work.c_str(),find))
|
||
{
|
||
int index = work.Find(find);
|
||
if (index==-1) break;
|
||
|
||
MyString before(work.Left(index));
|
||
|
||
int last = work.ReverseFind('/');
|
||
if (last==-1) break ;
|
||
|
||
|
||
MyString after(work.Mid(index + 4 )); //4=strlen(find)
|
||
|
||
work = before.Left((last-(const MYCHAR*)before.c_str())+1);
|
||
work += after;
|
||
}
|
||
*/
|
||
|
||
dest=work;
|
||
}
|
||
/*
|
||
const char* CDownload::retrieveURL()
|
||
{
|
||
return myURL.c_str();
|
||
}
|
||
void CDownload::setURL(const char* _url )
|
||
{
|
||
myURL = _url;
|
||
myURL.Replace("%20"," ");
|
||
}
|
||
*/
|
||
|
||
void CDownload::setBaseURL(const char* _baseURL)
|
||
{
|
||
if (!strncasecmp(_baseURL,"file:///",8))
|
||
#ifdef WIN32
|
||
_baseURL+=8;
|
||
#else
|
||
_baseURL+=7; // keep the / on mac
|
||
#endif
|
||
else
|
||
if (!strncasecmp(_baseURL,"file://",7))
|
||
_baseURL+=7; // absolute path
|
||
|
||
baseURL = _baseURL ;
|
||
// baseURL.Replace("%20"," ");
|
||
|
||
printf("CDownload::baseURL set to %s\n",_baseURL);
|
||
}
|
||
|
||
const char* CDownload::getPersistentPath()
|
||
{
|
||
if (persistentPath.IsEmpty())
|
||
{
|
||
x_fatal_exit("missing persistent path!");
|
||
return NULL;
|
||
}
|
||
//this->initPersistentPath();
|
||
|
||
const char* p = persistentPath.c_str();
|
||
return p;
|
||
}
|
||
|
||
|
||
void CDownload::initPersistentPath()
|
||
{
|
||
if (!persistentPath.IsEmpty())
|
||
return ;
|
||
|
||
MyString systemPath ;
|
||
initPersistentSystemPath(systemPath);
|
||
createDirectory(systemPath.c_str());
|
||
|
||
systemPath += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
systemPath += activegspersistentdir;
|
||
createDirectory(systemPath.c_str());
|
||
|
||
persistentPath = systemPath;
|
||
|
||
systemPath += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
systemPath += activegsdownloaddir;
|
||
createDirectory(systemPath.c_str());
|
||
|
||
}
|
||
|
||
/*
|
||
bool CDownload::createCacheEntryName(const char* _url, const char* _pathname, int _index, MyString& _cacheEntryName)
|
||
{
|
||
_cacheEntryName.Format("%s_%d_%s",_url,_index,_pathname);
|
||
return true;
|
||
}
|
||
*/
|
||
|
||
void CDownload::deleteCachedFile(const MYCHAR* _path)
|
||
{
|
||
|
||
MyString url ;
|
||
int order;
|
||
int localPath = parseFilenameAndMakeAbsolute(_path,order,url);
|
||
if (!localPath)
|
||
{
|
||
// détruit le fichier downloadé
|
||
MyString downloaded;
|
||
getPersistentDownloadedFile(_path,downloaded);
|
||
printf("delete getPersistentDownloadedFile %s\n",downloaded.c_str());
|
||
deleteFile(downloaded.c_str());
|
||
}
|
||
|
||
|
||
MyString ext(getext(url));
|
||
if (!localPath || !ext.CompareNoCase("zip"))
|
||
{
|
||
// détruit le répertoire d'extraction
|
||
MyString dir = getPersistentDir(url);
|
||
printf("delete dir %s\n",dir.c_str());
|
||
deleteDirectory(dir.c_str());
|
||
}
|
||
}
|
||
|
||
void CDownload::getPersistentDirectoryFile(const char* _file, const char* _dir, MyString &dir)
|
||
{
|
||
dir = getPersistentPath();
|
||
dir += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
dir += _dir;
|
||
dir += ACTIVEGS_DIRECTORY_SEPARATOR;
|
||
|
||
MyString fnoext =getfilenoext(getfile(_file));
|
||
MyString temp;
|
||
temp.Format("%s.%08X.%s",fnoext.c_str(),calcCRC(_file),getext(_file));
|
||
dir += temp.c_str();
|
||
}
|
||
|
||
|
||
void CDownload::getPersistentDownloadedFile(const char* _file, MyString &dir)
|
||
{
|
||
|
||
return getPersistentDirectoryFile(_file,activegsdownloaddir,dir);
|
||
|
||
}
|
||
|
||
|
||
bool CDownload::downloadHTTPFile(const char* filename,MyString& _gotfile)
|
||
{
|
||
outputInfo("downloadHTTPFile %s\n",filename);
|
||
|
||
getPersistentDownloadedFile(filename,_gotfile);
|
||
|
||
// regarde si le fichier existe
|
||
FILE* f = fopen(_gotfile.c_str(),"rb");
|
||
if (f)
|
||
{
|
||
fclose(f);
|
||
// _gotfile = _gotfile;
|
||
return true;
|
||
}
|
||
|
||
return GetFile(filename,_gotfile.c_str());
|
||
|
||
}
|
||
|