|
|
|
@ -524,18 +524,19 @@ namespace NLGUI
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string tmpdest = download.dest + ".tmp";
|
|
|
|
|
// use browser Id so that two browsers would not use same temp file
|
|
|
|
|
download.tmpdest = localImageName(_Id + download.dest) + ".tmp";
|
|
|
|
|
|
|
|
|
|
// erase the tmp file if exists
|
|
|
|
|
if (CFile::fileExists(tmpdest))
|
|
|
|
|
if (CFile::fileExists(download.tmpdest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(tmpdest);
|
|
|
|
|
CFile::deleteFile(download.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *fp = nlfopen (tmpdest, "wb");
|
|
|
|
|
FILE *fp = nlfopen (download.tmpdest, "wb");
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
{
|
|
|
|
|
nlwarning("Can't open file '%s' for writing: code=%d '%s'", tmpdest.c_str (), errno, strerror(errno));
|
|
|
|
|
nlwarning("Can't open file '%s' for writing: code=%d '%s'", download.tmpdest.c_str (), errno, strerror(errno));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -543,7 +544,7 @@ namespace NLGUI
|
|
|
|
|
if (!curl)
|
|
|
|
|
{
|
|
|
|
|
fclose(fp);
|
|
|
|
|
CFile::deleteFile(tmpdest);
|
|
|
|
|
CFile::deleteFile(download.tmpdest);
|
|
|
|
|
|
|
|
|
|
nlwarning("Creating cURL handle failed, unable to download '%s'", download.url.c_str());
|
|
|
|
|
return false;
|
|
|
|
@ -607,54 +608,57 @@ namespace NLGUI
|
|
|
|
|
|
|
|
|
|
void CGroupHTML::finishCurlDownload(const CDataDownload &download)
|
|
|
|
|
{
|
|
|
|
|
std::string tmpfile = download.dest + ".tmp";
|
|
|
|
|
|
|
|
|
|
if (download.type == ImgType)
|
|
|
|
|
{
|
|
|
|
|
// there is race condition if two browser instances are downloading same file
|
|
|
|
|
// second instance deletes first tmpfile and creates new file for itself.
|
|
|
|
|
if (CFile::getFileSize(tmpfile) > 0)
|
|
|
|
|
if (CFile::fileExists(download.tmpdest) && CFile::getFileSize(download.tmpdest) > 0)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// verify that image is not corrupted
|
|
|
|
|
uint32 w, h;
|
|
|
|
|
CBitmap::loadSize(tmpfile, w, h);
|
|
|
|
|
CBitmap::loadSize(download.tmpdest, w, h);
|
|
|
|
|
if (w != 0 && h != 0)
|
|
|
|
|
{
|
|
|
|
|
// if not tmpfile, then img is already in cache
|
|
|
|
|
if (CFile::fileExists(tmpfile))
|
|
|
|
|
{
|
|
|
|
|
if (CFile::fileExists(download.dest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(download.dest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// to reload image on page, the easiest seems to be changing texture
|
|
|
|
|
// to temp file temporarily. that forces driver to reload texture from disk
|
|
|
|
|
// ITexture::touch() seem not to do this.
|
|
|
|
|
// cache was updated, first set texture as temp file
|
|
|
|
|
for(uint i = 0; i < download.imgs.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
setImage(download.imgs[i].Image, tmpfile, download.imgs[i].Type);
|
|
|
|
|
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFile::moveFile(download.dest, tmpfile);
|
|
|
|
|
}
|
|
|
|
|
if (CFile::fileExists(download.dest))
|
|
|
|
|
CFile::deleteFile(download.dest);
|
|
|
|
|
|
|
|
|
|
// to reload image on page, the easiest seems to be changing texture
|
|
|
|
|
// to temp file temporarily. that forces driver to reload texture from disk
|
|
|
|
|
// ITexture::touch() seem not to do this.
|
|
|
|
|
// cache was updated, first set texture as temp file
|
|
|
|
|
for(uint i = 0; i < download.imgs.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
setImage(download.imgs[i].Image, download.dest, download.imgs[i].Type);
|
|
|
|
|
setImage(download.imgs[i].Image, download.tmpdest, download.imgs[i].Type);
|
|
|
|
|
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CFile::moveFile(download.dest, download.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(const NLMISC::Exception &e)
|
|
|
|
|
{
|
|
|
|
|
// exception message has .tmp file name, so keep it for further analysis
|
|
|
|
|
nlwarning("Invalid image (%s): %s", download.url.c_str(), e.what());
|
|
|
|
|
nlwarning("Invalid image (%s) from url (%s): %s", download.tmpdest.c_str(), download.url.c_str(), e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CFile::fileExists(download.dest) && CFile::getFileSize(download.dest) > 0)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// verify that image is not corrupted
|
|
|
|
|
uint32 w, h;
|
|
|
|
|
CBitmap::loadSize(download.dest, w, h);
|
|
|
|
|
if (w != 0 && h != 0)
|
|
|
|
|
for(uint i = 0; i < download.imgs.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
setImage(download.imgs[i].Image, download.dest, download.imgs[i].Type);
|
|
|
|
|
setImageSize(download.imgs[i].Image, download.imgs[i].Style);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(const NLMISC::Exception &e)
|
|
|
|
|
{
|
|
|
|
|
nlwarning("Invalid image (%s) from url (%s): %s", download.dest.c_str(), download.url.c_str(), e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -663,13 +667,13 @@ namespace NLGUI
|
|
|
|
|
|
|
|
|
|
if (download.type == StylesheetType)
|
|
|
|
|
{
|
|
|
|
|
if (CFile::fileExists(tmpfile))
|
|
|
|
|
if (CFile::fileExists(download.tmpdest))
|
|
|
|
|
{
|
|
|
|
|
if (CFile::fileExists(download.dest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(download.dest);
|
|
|
|
|
}
|
|
|
|
|
CFile::moveFile(download.dest, tmpfile);
|
|
|
|
|
CFile::moveFile(download.dest, download.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
cssDownloadFinished(download.url, download.dest);
|
|
|
|
|
|
|
|
|
@ -680,20 +684,20 @@ namespace NLGUI
|
|
|
|
|
{
|
|
|
|
|
bool verified = false;
|
|
|
|
|
// no tmpfile if file was already in cache
|
|
|
|
|
if (CFile::fileExists(tmpfile))
|
|
|
|
|
if (CFile::fileExists(download.tmpdest))
|
|
|
|
|
{
|
|
|
|
|
verified = download.md5sum.empty() || (download.md5sum != getMD5(tmpfile).toString());
|
|
|
|
|
verified = download.md5sum.empty() || (download.md5sum != getMD5(download.tmpdest).toString());
|
|
|
|
|
if (verified)
|
|
|
|
|
{
|
|
|
|
|
if (CFile::fileExists(download.dest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(download.dest);
|
|
|
|
|
}
|
|
|
|
|
CFile::moveFile(download.dest, tmpfile);
|
|
|
|
|
CFile::moveFile(download.dest, download.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(tmpfile);
|
|
|
|
|
CFile::deleteFile(download.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (CFile::fileExists(download.dest))
|
|
|
|
@ -745,7 +749,7 @@ namespace NLGUI
|
|
|
|
|
if (type != OverImage)
|
|
|
|
|
{
|
|
|
|
|
std::string temp = dest;
|
|
|
|
|
if (!CFile::fileExists(temp))
|
|
|
|
|
if (!CFile::fileExists(temp) || CFile::getFileSize(temp) == 0)
|
|
|
|
|
{
|
|
|
|
|
temp = placeholder;
|
|
|
|
|
}
|
|
|
|
@ -857,21 +861,16 @@ namespace NLGUI
|
|
|
|
|
CFile::createDirectory( pathName );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CGroupHTML::addStylesheetDownload(std::vector<std::string> links)
|
|
|
|
|
void CGroupHTML::addStylesheetDownload(const std::vector<CHtmlParser::StyleLink> links)
|
|
|
|
|
{
|
|
|
|
|
for(uint i = 0; i < links.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
std::string url = getAbsoluteUrl(links[i]);
|
|
|
|
|
std::string local = localImageName(url);
|
|
|
|
|
_StylesheetQueue.push_back(links[i]);
|
|
|
|
|
std::string url = getAbsoluteUrl(links[i].Url);
|
|
|
|
|
_StylesheetQueue.back().Url = url;
|
|
|
|
|
|
|
|
|
|
// insert only if url not already downloading
|
|
|
|
|
std::vector<std::string>::const_iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
|
|
|
|
|
if (it == _StylesheetQueue.end())
|
|
|
|
|
{
|
|
|
|
|
_StylesheetQueue.push_back(url);
|
|
|
|
|
// push to the front of the queue
|
|
|
|
|
Curls.push_front(CDataDownload(url, local, StylesheetType, NULL, "", ""));
|
|
|
|
|
}
|
|
|
|
|
// push to the front of the queue
|
|
|
|
|
Curls.push_front(CDataDownload(url, localImageName(url), StylesheetType, NULL, "", ""));
|
|
|
|
|
}
|
|
|
|
|
pumpCurlQueue();
|
|
|
|
|
}
|
|
|
|
@ -971,9 +970,9 @@ namespace NLGUI
|
|
|
|
|
{
|
|
|
|
|
fclose(it->fp);
|
|
|
|
|
|
|
|
|
|
if (CFile::fileExists(it->dest + ".tmp"))
|
|
|
|
|
if (CFile::fileExists(it->tmpdest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(it->dest + ".tmp");
|
|
|
|
|
CFile::deleteFile(it->tmpdest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2549,6 +2548,17 @@ namespace NLGUI
|
|
|
|
|
newParagraph->setResizeFromChildH(true);
|
|
|
|
|
|
|
|
|
|
newParagraph->setMarginLeft(getIndent());
|
|
|
|
|
if (!_Style.Current.TextAlign.empty())
|
|
|
|
|
{
|
|
|
|
|
if (_Style.Current.TextAlign == "left")
|
|
|
|
|
newParagraph->setTextAlign(CGroupParagraph::AlignLeft);
|
|
|
|
|
else if (_Style.Current.TextAlign == "center")
|
|
|
|
|
newParagraph->setTextAlign(CGroupParagraph::AlignCenter);
|
|
|
|
|
else if (_Style.Current.TextAlign == "right")
|
|
|
|
|
newParagraph->setTextAlign(CGroupParagraph::AlignRight);
|
|
|
|
|
else if (_Style.Current.TextAlign == "justify")
|
|
|
|
|
newParagraph->setTextAlign(CGroupParagraph::AlignJustify);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add to the group
|
|
|
|
|
addHtmlGroup (newParagraph, beginSpace);
|
|
|
|
@ -4102,10 +4112,9 @@ namespace NLGUI
|
|
|
|
|
obj.LastModified = data.data->getLastModified();
|
|
|
|
|
|
|
|
|
|
CHttpCache::getInstance()->store(data.dest, obj);
|
|
|
|
|
std::string tmpfile = data.dest + ".tmp";
|
|
|
|
|
if (code == 304 && CFile::fileExists(tmpfile))
|
|
|
|
|
if (code == 304 && CFile::fileExists(data.tmpdest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(tmpfile);
|
|
|
|
|
CFile::deleteFile(data.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ((code >= 301 && code <= 303) || code == 307 || code == 308)
|
|
|
|
@ -4133,10 +4142,9 @@ namespace NLGUI
|
|
|
|
|
|
|
|
|
|
LOG_DL("Redirect '%s'", location.c_str());
|
|
|
|
|
// no finished callback called, so cleanup old temp
|
|
|
|
|
std::string tmpfile = data.dest + ".tmp";
|
|
|
|
|
if (CFile::fileExists(tmpfile))
|
|
|
|
|
if (CFile::fileExists(data.tmpdest))
|
|
|
|
|
{
|
|
|
|
|
CFile::deleteFile(tmpfile);
|
|
|
|
|
CFile::deleteFile(data.tmpdest);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -4209,19 +4217,28 @@ namespace NLGUI
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
void CGroupHTML::cssDownloadFinished(const std::string &url, const std::string &local)
|
|
|
|
|
{
|
|
|
|
|
// remove file from download queue
|
|
|
|
|
std::vector<std::string>::iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
|
|
|
|
|
if (it != _StylesheetQueue.end())
|
|
|
|
|
for(std::vector<CHtmlParser::StyleLink>::iterator it = _StylesheetQueue.begin();
|
|
|
|
|
it != _StylesheetQueue.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
_StylesheetQueue.erase(it);
|
|
|
|
|
}
|
|
|
|
|
if (it->Url == url)
|
|
|
|
|
{
|
|
|
|
|
// read downloaded file into HtmlStyles
|
|
|
|
|
if (CFile::fileExists(local) && it->Index < _HtmlStyles.size())
|
|
|
|
|
{
|
|
|
|
|
CIFile in;
|
|
|
|
|
if (in.open(local))
|
|
|
|
|
{
|
|
|
|
|
if (!in.readAll(_HtmlStyles[it->Index]))
|
|
|
|
|
{
|
|
|
|
|
nlwarning("Failed to read downloaded css file(%s), url(%s)", local.c_str(), url.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CFile::fileExists(local))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
_StylesheetQueue.erase(it);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseStylesheetFile(local);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CGroupHTML::renderDocument()
|
|
|
|
@ -4239,6 +4256,16 @@ namespace NLGUI
|
|
|
|
|
beginBuild();
|
|
|
|
|
removeContent();
|
|
|
|
|
|
|
|
|
|
// process all <style> and <link rel=stylesheet> elements
|
|
|
|
|
for(uint i = 0; i < _HtmlStyles.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (!_HtmlStyles[i].empty())
|
|
|
|
|
{
|
|
|
|
|
_Style.parseStylesheet(_HtmlStyles[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_HtmlStyles.clear();
|
|
|
|
|
|
|
|
|
|
std::list<CHtmlElement>::iterator it = _HtmlDOM.Children.begin();
|
|
|
|
|
while(it != _HtmlDOM.Children.end())
|
|
|
|
|
{
|
|
|
|
@ -4848,9 +4875,6 @@ namespace NLGUI
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
bool CGroupHTML::parseHtml(const std::string &htmlString)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> links;
|
|
|
|
|
std::string styleString;
|
|
|
|
|
|
|
|
|
|
CHtmlElement *parsedDOM;
|
|
|
|
|
if (_CurrentHTMLElement == NULL)
|
|
|
|
|
{
|
|
|
|
@ -4863,16 +4887,28 @@ namespace NLGUI
|
|
|
|
|
parsedDOM = _CurrentHTMLElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<CHtmlParser::StyleLink> links;
|
|
|
|
|
|
|
|
|
|
CHtmlParser parser;
|
|
|
|
|
parser.getDOM(htmlString, *parsedDOM, styleString, links);
|
|
|
|
|
parser.getDOM(htmlString, *parsedDOM, _HtmlStyles, links);
|
|
|
|
|
|
|
|
|
|
if (!styleString.empty())
|
|
|
|
|
// <link> elements inserted from lua::parseHtml are ignored
|
|
|
|
|
if (_CurrentHTMLElement == NULL && !links.empty())
|
|
|
|
|
{
|
|
|
|
|
_Style.parseStylesheet(styleString);
|
|
|
|
|
addStylesheetDownload(links);
|
|
|
|
|
}
|
|
|
|
|
if (!links.empty())
|
|
|
|
|
else if (_CurrentHTMLElement != NULL)
|
|
|
|
|
{
|
|
|
|
|
addStylesheetDownload(links);
|
|
|
|
|
// Called from active element (lua)
|
|
|
|
|
// <style> order is not preserved as document is already being rendered
|
|
|
|
|
for(uint i = 0; i < _HtmlStyles.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (!_HtmlStyles[i].empty())
|
|
|
|
|
{
|
|
|
|
|
_Style.parseStylesheet(_HtmlStyles[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_HtmlStyles.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// this should rarely fail as first element should be <html>
|
|
|
|
@ -4883,7 +4919,7 @@ namespace NLGUI
|
|
|
|
|
{
|
|
|
|
|
if (it->Type == CHtmlElement::ELEMENT_NODE && it->Value == "html")
|
|
|
|
|
{
|
|
|
|
|
// more newly parsed childs from <body> into siblings
|
|
|
|
|
// move newly parsed childs from <body> into siblings
|
|
|
|
|
if (_CurrentHTMLElement) {
|
|
|
|
|
std::list<CHtmlElement>::iterator it2 = it->Children.begin();
|
|
|
|
|
while(it2 != it->Children.end())
|
|
|
|
@ -5380,6 +5416,11 @@ namespace NLGUI
|
|
|
|
|
cellParams.Align = CGroupCell::Center;
|
|
|
|
|
else if (align == "right")
|
|
|
|
|
cellParams.Align = CGroupCell::Right;
|
|
|
|
|
else if (align != "justify")
|
|
|
|
|
align.clear();
|
|
|
|
|
|
|
|
|
|
// copy td align (can be empty) attribute back into css
|
|
|
|
|
_Style.Current.TextAlign = align;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|