diff --git a/nel/include/nel/gui/group_html.h b/nel/include/nel/gui/group_html.h index 3c94e7fa9..c94bec024 100644 --- a/nel/include/nel/gui/group_html.h +++ b/nel/include/nel/gui/group_html.h @@ -47,6 +47,20 @@ namespace NLGUI extern std::string CurrentCookie; + class ICurlDownloadCB + { + public: + ICurlDownloadCB(const std::string &url) + : url(url) + {} + + virtual ~ICurlDownloadCB() {}; + + virtual void finish() = 0; + + std::string url; + }; + // HTML group /** * Widget to have a resizable scrolltext and its scrollbar @@ -133,9 +147,8 @@ namespace NLGUI void endParagraph(); // add image download (used by view_bitmap.cpp to load web images) - void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage, const std::string &placeholder = "web_del.tga"); - // remove image from download list if present - void removeImageDownload(CViewBase *img); + ICurlDownloadCB *addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage, const std::string &placeholder = "web_del.tga"); + void removeImageDownload(ICurlDownloadCB *handle, CViewBase *img); std::string localImageName(const std::string &url); // Timeout @@ -817,48 +830,89 @@ namespace NLGUI // decode all HTML entities static std::string decodeHTMLEntities(const std::string &str); - struct CDataImageDownload + class CDataDownload : public ICurlDownloadCB { public: - CDataImageDownload(CViewBase *img, CStyleParams style, TImageType type): Image(img), Style(style), Type(type) - { - } + CDataDownload(const std::string &u, const std::string &d) + : ICurlDownloadCB(u), data(NULL), fp(NULL), dest(d), redirects(0), ConnectionTimeout(60) + {} + virtual ~CDataDownload(); + public: - CViewBase * Image; - CStyleParams Style; - TImageType Type; + CCurlWWWData *data; + std::string dest; + std::string tmpdest; + uint32 redirects; + FILE *fp; + uint32 ConnectionTimeout; + }; + + class StylesheetDownloadCB : public CDataDownload + { + public: + StylesheetDownloadCB(const std::string &url, const std::string &dest, CGroupHTML *parent) + : CDataDownload(url, dest), Parent(parent) + {} + + virtual void finish() NL_OVERRIDE; + + private: + CGroupHTML *Parent; }; - struct CDataDownload + class ImageDownloadCB : public CDataDownload { public: - CDataDownload(const std::string &u, const std::string &d, TDataType t, CViewBase *i, const std::string &s, const std::string &m, const CStyleParams &style = CStyleParams(), const TImageType imagetype = NormalImage) - : data(NULL), fp(NULL), url(u), dest(d), type(t), luaScript(s), md5sum(m), redirects(0), ConnectionTimeout(60) + struct SImageInfo + { + SImageInfo(CViewBase *img, const CStyleParams &style, TImageType type) + : Image(img), Style(style), Type(type) + {} + + CViewBase *Image; + CStyleParams Style; + TImageType Type; + }; + + ImageDownloadCB(const std::string &url, const std::string &dest, CViewBase *img, const CStyleParams &style, TImageType type, CGroupHTML *parent) + : CDataDownload(url, dest), Parent(parent) { - if (t == ImgType) imgs.push_back(CDataImageDownload(i, style, imagetype)); + addImage(img, style, type); } - ~CDataDownload(); + virtual void finish() NL_OVERRIDE; + + void addImage(CViewBase *img, const CStyleParams &style, TImageType type); + void removeImage(CViewBase *img); + + private: + std::vector Images; + CGroupHTML *Parent; + CStyleParams Style; + TImageType Type; + }; + + class BnpDownloadCB : public CDataDownload + { public: - CCurlWWWData *data; - std::string url; - std::string dest; - std::string tmpdest; - std::string luaScript; - std::string md5sum; - TDataType type; - uint32 redirects; - FILE *fp; - std::vector imgs; - uint32 ConnectionTimeout; + BnpDownloadCB(const std::string &url, const std::string &dest, const std::string md5sum, const std::string lua, CGroupHTML *parent) + : CDataDownload(url, dest), Parent(parent), m_md5sum(md5sum), m_lua(lua) + {} + + virtual void finish() NL_OVERRIDE; + + private: + CGroupHTML *Parent; + std::string m_md5sum; + std::string m_lua; }; - std::list Curls; + std::list Curls; CURLM *MultiCurl; int RunningCurls; - bool startCurlDownload(CDataDownload &download); - void finishCurlDownload(const CDataDownload &download); + bool startCurlDownload(CDataDownload *download); + void finishCurlDownload(CDataDownload *download); void pumpCurlQueue(); void initImageDownload(); @@ -888,7 +942,7 @@ namespace NLGUI // _CurlWWW download finished void htmlDownloadFinished(bool success, const std::string &error); // images, stylesheets, etc finished downloading - void dataDownloadFinished(bool success, const std::string &error, CDataDownload &data); + void dataDownloadFinished(bool success, const std::string &error, CDataDownload *data); // HtmlType download finished void htmlDownloadFinished(const std::string &content, const std::string &type, long code); diff --git a/nel/include/nel/gui/view_bitmap.h b/nel/include/nel/gui/view_bitmap.h index f7a77cb30..958fdcc5c 100644 --- a/nel/include/nel/gui/view_bitmap.h +++ b/nel/include/nel/gui/view_bitmap.h @@ -28,6 +28,7 @@ namespace NLGUI { + class ICurlDownloadCB; /** * class implementing a bitmap view @@ -61,7 +62,7 @@ namespace NLGUI _TxtHeight = -1; // Support for https://.. textures - _HtmlDownload = false; + _HtmlDownload = NULL; } /// Destructor @@ -141,7 +142,9 @@ namespace NLGUI bool _Flip : 1; bool _Tile : 1; bool _InheritGCAlpha : 1; - bool _HtmlDownload : 1; + + // pointer to active curl download object + ICurlDownloadCB *_HtmlDownload; // For single texture diff --git a/nel/src/gui/group_html.cpp b/nel/src/gui/group_html.cpp index 75d7eb64c..0c48b92a8 100644 --- a/nel/src/gui/group_html.cpp +++ b/nel/src/gui/group_html.cpp @@ -266,6 +266,120 @@ namespace NLGUI data = NULL; } + void CGroupHTML::StylesheetDownloadCB::finish() + { + if (CFile::fileExists(tmpdest)) + { + if (CFile::fileExists(dest)) + { + CFile::deleteFile(dest); + } + CFile::moveFile(dest, tmpdest); + } + Parent->cssDownloadFinished(url, dest); + } + + void CGroupHTML::ImageDownloadCB::addImage(CViewBase *img, const CStyleParams &style, TImageType type) + { + Images.push_back(SImageInfo(img, style, type)); + } + + void CGroupHTML::ImageDownloadCB::removeImage(CViewBase *img) + { + for(std::vector::iterator it = Images.begin(); it != Images.end(); ++it) + { + if (it->Image == img) + { + Images.erase(it); + break; + } + } + } + + void CGroupHTML::ImageDownloadCB::finish() + { + // tmpdest file does not exist if download skipped (ie cache was used) + if (CFile::fileExists(tmpdest) || CFile::getFileSize(tmpdest) == 0) + { + try { + // verify that image is not corrupted + uint32 w, h; + CBitmap::loadSize(tmpdest, w, h); + if (w != 0 && h != 0) + { + if (CFile::fileExists(dest)) + CFile::deleteFile(dest); + } + } + catch(const NLMISC::Exception &e) + { + // exception message has .tmp file name, so keep it for further analysis + nlwarning("Invalid image (%s) from url (%s): %s", tmpdest.c_str(), url.c_str(), e.what()); + } + + // 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(std::vector::iterator it = Images.begin(); it != Images.end(); ++it) + { + SImageInfo &img = *it; + Parent->setImage(img.Image, tmpdest, img.Type); + Parent->setImageSize(img.Image, img.Style); + } + + CFile::moveFile(dest, tmpdest); + } + + if (!CFile::fileExists(dest) || CFile::getFileSize(dest) == 0) + { + // placeholder if cached image failed + dest = "web_del.tga"; + } + + // even if image was cached, incase there was 'http://' image set to CViewBitmap + for(std::vector::iterator it = Images.begin(); it != Images.end(); ++it) + { + SImageInfo &img = *it; + Parent->setImage(img.Image, dest, img.Type); + Parent->setImageSize(img.Image, img.Style); + } + } + + void CGroupHTML::BnpDownloadCB::finish() + { + bool verified = false; + // no tmpfile if file was already in cache + if (CFile::fileExists(tmpdest)) + { + verified = m_md5sum.empty() || (m_md5sum != getMD5(tmpdest).toString()); + if (verified) + { + if (CFile::fileExists(dest)) + { + CFile::deleteFile(dest); + } + CFile::moveFile(dest, tmpdest); + } + else + { + CFile::deleteFile(tmpdest); + } + } + else if (CFile::fileExists(dest)) + { + verified = m_md5sum.empty() || (m_md5sum != getMD5(dest).toString()); + } + + if (!m_lua.empty()) + { + std::string script = "\nlocal __CURRENT_WINDOW__ = \""+Parent->getId()+"\""; + script += toString("\nlocal __DOWNLOAD_STATUS__ = %s\n", verified ? "true" : "false"); + script += m_lua; + CLuaManager::getInstance().executeLuaScript(script, true ); + } + } + // Check if domain is on TrustedDomain bool CGroupHTML::isTrustedDomain(const string &domain) { @@ -479,17 +593,17 @@ namespace NLGUI { if (RunningCurls < options.curlMaxConnections) { - std::list::iterator it=Curls.begin(); - uint c = 0; + std::list::iterator it=Curls.begin(); while(it != Curls.end() && RunningCurls < options.curlMaxConnections) { - if (it->data == NULL) + if ((*it)->data == NULL) { LOG_DL("(%s) starting new download '%s'", _Id.c_str(), it->url.c_str()); if (!startCurlDownload(*it)) { LOG_DL("(%s) failed to start '%s)'", _Id.c_str(), it->url.c_str()); finishCurlDownload(*it); + it = Curls.erase(it); continue; } @@ -504,11 +618,11 @@ namespace NLGUI } // Add url to MultiCurl queue and return cURL handle - bool CGroupHTML::startCurlDownload(CDataDownload &download) + bool CGroupHTML::startCurlDownload(CDataDownload *download) { if (!MultiCurl) { - nlwarning("Invalid MultiCurl handle, unable to download '%s'", download.url.c_str()); + nlwarning("Invalid MultiCurl handle, unable to download '%s'", download->url.c_str()); return false; } @@ -516,28 +630,28 @@ namespace NLGUI time(¤tTime); CHttpCacheObject cache; - if (CFile::fileExists(download.dest)) - cache = CHttpCache::getInstance()->lookup(download.dest); + if (CFile::fileExists(download->dest)) + cache = CHttpCache::getInstance()->lookup(download->dest); if (cache.Expires > currentTime) { - LOG_DL("Cache for (%s) is not expired (%s, expires:%d)", download.url.c_str(), download.dest.c_str(), cache.Expires - currentTime); + LOG_DL("Cache for (%s) is not expired (%s, expires:%d)", download->url.c_str(), download->dest.c_str(), cache.Expires - currentTime); return false; } // use browser Id so that two browsers would not use same temp file - download.tmpdest = localImageName(_Id + download.dest) + ".tmp"; + download->tmpdest = localImageName(_Id + download->dest) + ".tmp"; // erase the tmp file if exists - if (CFile::fileExists(download.tmpdest)) + if (CFile::fileExists(download->tmpdest)) { - CFile::deleteFile(download.tmpdest); + CFile::deleteFile(download->tmpdest); } - FILE *fp = nlfopen (download.tmpdest, "wb"); + FILE *fp = nlfopen (download->tmpdest, "wb"); if (fp == NULL) { - nlwarning("Can't open file '%s' for writing: code=%d '%s'", download.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; } @@ -545,28 +659,28 @@ namespace NLGUI if (!curl) { fclose(fp); - CFile::deleteFile(download.tmpdest); + CFile::deleteFile(download->tmpdest); - nlwarning("Creating cURL handle failed, unable to download '%s'", download.url.c_str()); + nlwarning("Creating cURL handle failed, unable to download '%s'", download->url.c_str()); return false; } - LOG_DL("curl easy handle %p created for '%s'", curl, download.url.c_str()); + LOG_DL("curl easy handle %p created for '%s'", curl, download->url.c_str()); // https:// - if (toLowerAscii(download.url.substr(0, 8)) == "https://") + if (toLowerAscii(download->url.substr(0, 8)) == "https://") { // if supported, use custom SSL context function to load certificates NLWEB::CCurlCertificates::useCertificates(curl); } - download.data = new CCurlWWWData(curl, download.url); - download.fp = fp; + download->data = new CCurlWWWData(curl, download->url); + download->fp = fp; // initial connection timeout, curl default is 300sec - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, download.ConnectionTimeout); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, download->ConnectionTimeout); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, true); - curl_easy_setopt(curl, CURLOPT_URL, download.url.c_str()); + curl_easy_setopt(curl, CURLOPT_URL, download->url.c_str()); // limit curl to HTTP and HTTPS protocols only curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); @@ -580,16 +694,16 @@ namespace NLGUI headers.push_back("If-Modified-Since: " + cache.LastModified); if (headers.size() > 0) - download.data->sendHeaders(headers); + download->data->sendHeaders(headers); // catch headers curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, NLGUI::curlHeaderCallback); - curl_easy_setopt(curl, CURLOPT_WRITEHEADER, download.data); + curl_easy_setopt(curl, CURLOPT_WRITEHEADER, download->data); std::string userAgent = options.appName + "/" + options.appVersion; curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); - CUrlParser uri(download.url); + CUrlParser uri(download->url); if (!uri.host.empty()) sendCookies(curl, uri.host, isTrustedDomain(uri.host)); @@ -599,7 +713,7 @@ namespace NLGUI CURLMcode ret = curl_multi_add_handle(MultiCurl, curl); if (ret != CURLM_OK) { - nlwarning("cURL multi handle %p error %d on '%s'", curl, ret, download.url.c_str()); + nlwarning("cURL multi handle %p error %d on '%s'", curl, ret, download->url.c_str()); return false; } @@ -607,118 +721,21 @@ namespace NLGUI return true; } - void CGroupHTML::finishCurlDownload(const CDataDownload &download) + void CGroupHTML::finishCurlDownload(CDataDownload *download) { - if (download.type == ImgType) + if (download) { - if (CFile::fileExists(download.tmpdest) && CFile::getFileSize(download.tmpdest) > 0) - { - try - { - // verify that image is not corrupted - uint32 w, h; - CBitmap::loadSize(download.tmpdest, w, h); - if (w != 0 && h != 0) - { - 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.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) 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()); - } - } - - return; + download->finish(); + delete download; } - - if (download.type == StylesheetType) - { - if (CFile::fileExists(download.tmpdest)) - { - if (CFile::fileExists(download.dest)) - { - CFile::deleteFile(download.dest); - } - CFile::moveFile(download.dest, download.tmpdest); - } - cssDownloadFinished(download.url, download.dest); - - return; - } - - if (download.type == BnpType) + else { - bool verified = false; - // no tmpfile if file was already in cache - if (CFile::fileExists(download.tmpdest)) - { - 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, download.tmpdest); - } - else - { - CFile::deleteFile(download.tmpdest); - } - } - else if (CFile::fileExists(download.dest)) - { - verified = download.md5sum.empty() || (download.md5sum != getMD5(download.dest).toString()); - } - - std::string script = "\nlocal __CURRENT_WINDOW__ = \""+this->_Id+"\""; - script += toString("\nlocal __DOWNLOAD_STATUS__ = %s\n", verified ? "true" : "false"); - script += download.luaScript; - CLuaManager::getInstance().executeLuaScript(script, true ); - - return; + nlwarning("Unknown CURL download (nullptr)"); } - - nlwarning("Unknown CURL download type (%d) finished '%s'", download.type, download.url.c_str()); } // Add a image download request in the multi_curl - void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style, TImageType type, const std::string &placeholder) + ICurlDownloadCB *CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style, TImageType type, const std::string &placeholder) { std::string finalUrl; img->setModulateGlobalColor(style.GlobalColor); @@ -728,7 +745,7 @@ namespace NLGUI { setImage(img, decodeURIComponent(url), type); setImageSize(img, style); - return; + return NULL; } // load the image from local files/bnp @@ -737,7 +754,7 @@ namespace NLGUI { setImage(img, image, type); setImageSize(img, style); - return; + return NULL; } finalUrl = upgradeInsecureUrl(getAbsoluteUrl(url)); @@ -759,36 +776,40 @@ namespace NLGUI } // Search if we are not already downloading this url. - for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) + for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) { - if(it->url == finalUrl) + if((*it)->url == finalUrl) { LOG_DL("already downloading '%s' img %p", finalUrl.c_str(), img); - it->imgs.push_back(CDataImageDownload(img, style, type)); - return; + ImageDownloadCB *cb = dynamic_cast(*it); + if (cb) + { + cb->addImage(img, style, type); + // return pointer to shared ImageDownloadCB + return cb; + } + else + { + nlwarning("Found image download '%s', but casting to ImageDownloadCB failed", finalUrl.c_str()); + } } } - Curls.push_back(CDataDownload(finalUrl, dest, ImgType, img, "", "", style, type)); - pumpCurlQueue(); + Curls.push_back(new ImageDownloadCB(finalUrl, dest, img, style, type, this)); + // as we return pointer to callback, skip starting downloads just now + //pumpCurlQueue(); + return Curls.back(); } - void CGroupHTML::removeImageDownload(CViewBase *img) + void CGroupHTML::removeImageDownload(ICurlDownloadCB *handle, CViewBase *img) { - for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) - { - // check all active downloads because image does not keep url around - std::vector::iterator imgIter = it->imgs.begin(); - while(imgIter != it->imgs.end()) - { - if (imgIter->Image == img) - { - it->imgs.erase(imgIter); - break; - } - ++imgIter; - } + ImageDownloadCB *cb = dynamic_cast(handle); + if (!cb) { + nlwarning("Trying to remove image from downloads, but ICurlDownloadCB pointer did not cast to ImageDownloadCB"); + return; } + // image will be removed from handle, but handle is kept and image will be downloaded + cb->removeImage(img); } void CGroupHTML::initImageDownload() @@ -815,9 +836,9 @@ namespace NLGUI url = upgradeInsecureUrl(getAbsoluteUrl(url)); // Search if we are not already downloading this url. - for(std::list::const_iterator it = Curls.begin(); it != Curls.end(); ++it) + for(std::list::const_iterator it = Curls.begin(); it != Curls.end(); ++it) { - if(it->url == url) + if((*it)->url == url) { LOG_DL("already downloading '%s'", url.c_str()); return false; @@ -842,7 +863,7 @@ namespace NLGUI } if (action != "delete") { - Curls.push_back(CDataDownload(url, dest, BnpType, NULL, script, md5sum)); + Curls.push_back(new BnpDownloadCB(url, dest, md5sum, script, this)); pumpCurlQueue(); } else @@ -871,7 +892,7 @@ namespace NLGUI _StylesheetQueue.back().Url = url; // push to the front of the queue - Curls.push_front(CDataDownload(url, localImageName(url), StylesheetType, NULL, "", "")); + Curls.push_front(new StylesheetDownloadCB(url, localImageName(url), this)); } pumpCurlQueue(); } @@ -915,9 +936,9 @@ namespace NLGUI } else { - for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) + for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) { - if(it->data && it->data->Request == msg->easy_handle) + if((*it)->data && (*it)->data->Request == msg->easy_handle) { std::string error; bool success = msg->data.result == CURLE_OK; @@ -956,27 +977,30 @@ namespace NLGUI } // remove all queued and already started downloads - for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) + for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) { - if (it->data) + CDataDownload &dl = *(*it); + if (dl.data) { - LOG_DL("(%s) stop data url '%s'", _Id.c_str(), it->url.c_str()); + LOG_DL("(%s) stop data url '%s'", _Id.c_str(), dl.url.c_str()); if (MultiCurl) { - curl_multi_remove_handle(MultiCurl, it->data->Request); + curl_multi_remove_handle(MultiCurl, dl.data->Request); } // close and remove temp file - if (it->fp) + if (dl.fp) { - fclose(it->fp); + fclose(dl.fp); - if (CFile::fileExists(it->tmpdest)) + if (CFile::fileExists(dl.tmpdest)) { - CFile::deleteFile(it->tmpdest); + CFile::deleteFile(dl.tmpdest); } } } + // release CDataDownload + delete *it; } Curls.clear(); @@ -2935,10 +2959,10 @@ namespace NLGUI LOG_DL("Clear pointers to %d curls", Curls.size()); // remove image refs from downloads - for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) + /*for(std::list::iterator it = Curls.begin(); it != Curls.end(); ++it) { it->imgs.clear(); - } + }*/ } // *************************************************************************** @@ -3691,96 +3715,98 @@ namespace NLGUI updateRefreshButton(); } - void CGroupHTML::dataDownloadFinished(bool success, const std::string &error, CDataDownload &data) + void CGroupHTML::dataDownloadFinished(bool success, const std::string &error, CDataDownload *data) { - fclose(data.fp); + fclose(data->fp); - CUrlParser uri(data.url); + CUrlParser uri(data->url); if (!uri.host.empty()) { - receiveCookies(data.data->Request, uri.host, isTrustedDomain(uri.host)); + receiveCookies(data->data->Request, uri.host, isTrustedDomain(uri.host)); } long code = -1; - curl_easy_getinfo(data.data->Request, CURLINFO_RESPONSE_CODE, &code); + curl_easy_getinfo(data->data->Request, CURLINFO_RESPONSE_CODE, &code); - LOG_DL("(%s) transfer '%p' completed with http code %d, url (len %d) '%s'", _Id.c_str(), data.data->Request, code, data.url.size(), data.url.c_str()); - curl_multi_remove_handle(MultiCurl, data.data->Request); + LOG_DL("(%s) transfer '%p' completed with http code %d, url (len %d) '%s'", _Id.c_str(), data->data->Request, code, data->url.size(), data->url.c_str()); + curl_multi_remove_handle(MultiCurl, data->data->Request); // save HSTS header from all requests regardless of HTTP code if (success) { - if (data.data->hasHSTSHeader()) + if (data->data->hasHSTSHeader()) { - CStrictTransportSecurity::getInstance()->setFromHeader(uri.host, data.data->getHSTSHeader()); + CStrictTransportSecurity::getInstance()->setFromHeader(uri.host, data->data->getHSTSHeader()); } // 2XX success, 304 Not Modified if ((code >= 200 && code <= 204) || code == 304) { CHttpCacheObject obj; - obj.Expires = data.data->getExpires(); - obj.Etag = data.data->getEtag(); - obj.LastModified = data.data->getLastModified(); + obj.Expires = data->data->getExpires(); + obj.Etag = data->data->getEtag(); + obj.LastModified = data->data->getLastModified(); - CHttpCache::getInstance()->store(data.dest, obj); - if (code == 304 && CFile::fileExists(data.tmpdest)) + CHttpCache::getInstance()->store(data->dest, obj); + if (code == 304 && CFile::fileExists(data->tmpdest)) { - CFile::deleteFile(data.tmpdest); + CFile::deleteFile(data->tmpdest); } } else if ((code >= 301 && code <= 303) || code == 307 || code == 308) { - if (data.redirects < DEFAULT_RYZOM_REDIRECT_LIMIT) + if (data->redirects < DEFAULT_RYZOM_REDIRECT_LIMIT) { - std::string location(data.data->getLocationHeader()); + std::string location(data->data->getLocationHeader()); if (!location.empty()) { CUrlParser uri(location); if (!uri.isAbsolute()) { - uri.inherit(data.url); + uri.inherit(data->url); location = uri.toString(); } + // clear old request state, and curl easy handle + delete data->data; + data->data = NULL; + data->fp = NULL; + data->url = location; + data->redirects++; + // push same request in the front of the queue // cache filename is based of original url Curls.push_front(data); - // clear old request state - Curls.front().data = NULL; - Curls.front().fp = NULL; - Curls.front().url = location; - Curls.front().redirects++; LOG_DL("Redirect '%s'", location.c_str()); // no finished callback called, so cleanup old temp - if (CFile::fileExists(data.tmpdest)) + if (CFile::fileExists(data->tmpdest)) { - CFile::deleteFile(data.tmpdest); + CFile::deleteFile(data->tmpdest); } return; } - nlwarning("Redirected to empty url '%s'", data.url.c_str()); + nlwarning("Redirected to empty url '%s'", data->url.c_str()); } else { - nlwarning("Redirect limit reached for '%s'", data.url.c_str()); + nlwarning("Redirect limit reached for '%s'", data->url.c_str()); } } else { - nlwarning("HTTP request failed with code [%d] for '%s'\n",code, data.url.c_str()); + nlwarning("HTTP request failed with code [%d] for '%s'\n",code, data->url.c_str()); // 404, 500, etc - if (CFile::fileExists(data.dest)) + if (CFile::fileExists(data->dest)) { - CFile::deleteFile(data.dest); + CFile::deleteFile(data->dest); } } } else { - nlwarning("DATA download failed '%s', error '%s'", data.url.c_str(), error.c_str()); + nlwarning("DATA download failed '%s', error '%s'", data->url.c_str(), error.c_str()); } finishCurlDownload(data); diff --git a/nel/src/gui/view_bitmap.cpp b/nel/src/gui/view_bitmap.cpp index 4186a4362..89c944a18 100644 --- a/nel/src/gui/view_bitmap.cpp +++ b/nel/src/gui/view_bitmap.cpp @@ -46,8 +46,8 @@ namespace NLGUI { CGroupHTML *groupHtml = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:webig:content:html")); if (groupHtml) { - _HtmlDownload = false; - groupHtml->removeImageDownload(dynamic_cast(this)); + groupHtml->removeImageDownload(_HtmlDownload, dynamic_cast(this)); + _HtmlDownload = NULL; } } } @@ -476,12 +476,14 @@ namespace NLGUI if (!CFile::fileExists(localname)) localname = "web_del.tga"; _TextureId.setTexture (localname.c_str(), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); - _HtmlDownload = true; - groupHtml->addImageDownload(TxName, dynamic_cast(this)); + _HtmlDownload = groupHtml->addImageDownload(TxName, dynamic_cast(this)); } } else + { + _HtmlDownload = NULL; _TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); + } } // ----------------------------------------------------------------------------