TEST_F(TestWebServer, CanNotGetNonExistingFile) { std::string result; CCurlFile curl; ASSERT_FALSE(curl.Get(GetUrlOfTestFile("file_does_not_exist"), result)); ASSERT_TRUE(result.empty()); }
void N7Xml::list_channels() { CStdString strUrl; strUrl.Format("http://%s:%i/n7channel_nt.xml", g_strHostname.c_str(), g_iPort); CStdString strXML; CCurlFile http; if(!http.Get(strUrl, strXML)) { XBMC->Log(LOG_DEBUG, "N7Xml - Could not open connection to N7 backend."); } else { TiXmlDocument xml; xml.Parse(strXML.c_str()); TiXmlElement* rootXmlNode = xml.RootElement(); if (rootXmlNode == NULL) return; TiXmlElement* channelsNode = rootXmlNode->FirstChildElement("channel"); if (channelsNode) { XBMC->Log(LOG_DEBUG, "N7Xml - Connected to N7 backend."); m_connected = true; int iUniqueChannelId = 0; TiXmlNode *pChannelNode = NULL; while ((pChannelNode = channelsNode->IterateChildren(pChannelNode)) != NULL) { CStdString strTmp; PVRChannel channel; /* unique ID */ channel.iUniqueId = ++iUniqueChannelId; /* channel number */ if (!XMLUtils::GetInt(pChannelNode, "number", channel.iChannelNumber)) channel.iChannelNumber = channel.iUniqueId; /* channel name */ if (!XMLUtils::GetString(pChannelNode, "title", strTmp)) continue; channel.strChannelName = strTmp; /* icon path */ const TiXmlElement* pElement = pChannelNode->FirstChildElement("media:thumbnail"); channel.strIconPath = pElement->Attribute("url"); /* channel url */ if (!XMLUtils::GetString(pChannelNode, "guid", strTmp)) channel.strStreamURL = ""; else channel.strStreamURL = strTmp; m_channels.push_back(channel); } } } }
TEST_F(TestWebServer, CanGetFile) { std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, ""); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_HTML), result)); ASSERT_STREQ(TEST_FILES_DATA, result.c_str()); CheckHtmlTestFileResponse(curl); }
void MythXmlCommand::execute(const CStdString& hostname, int port, const MythXmlCommandParameters& params, MythXmlCommandResult& result, int timeout){ CStdString strUrl = createRequestUrl(hostname, port, params); CStdString strXML; CCurlFile http; http.SetTimeout(timeout); if (http.Get(strUrl, strXML)) { CLog::Log(LOGDEBUG, "Got response from mythtv backend: %s", strUrl.c_str()); } http.Cancel(); result.parseData(strXML); }
TEST_F(TestWebServer, CanGetCachedFileWithOlderIfUnmodifiedSince) { // get the last modified date of the file CDateTime lastModified; ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified)); CDateTime lastModifiedOlder = lastModified - CDateTimeSpan(1, 0, 0, 0); // get the file with an older If-Unmodified-Since value std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, ""); curl.SetRequestHeader(MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE, lastModifiedOlder.GetAsRFC1123DateTime()); ASSERT_FALSE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); }
bool CLastFmManager::RadioHandShake() { if (!m_RadioSession.IsEmpty()) return true; //already signed in if (dlgProgress) { dlgProgress->SetLine(2, 15251);//Connecting to Last.fm.. dlgProgress->Progress(); } m_RadioSession = ""; CCurlFile http; CStdString html; CStdString strPassword = g_guiSettings.GetString("scrobbler.lastfmpass"); CStdString strUserName = g_guiSettings.GetString("scrobbler.lastfmusername"); if (strUserName.IsEmpty() || strPassword.IsEmpty()) { CLog::Log(LOGERROR, "Last.fm stream selected but no username or password set."); return false; } CStdString passwordmd5(strPassword); passwordmd5.ToLower(); CStdString url; CURL::Encode(strUserName); url.Format("http://ws.audioscrobbler.com/radio/handshake.php?version=%s&platform=%s&username=%s&passwordmd5=%s&debug=%i&partner=%s", XBMC_LASTFM_VERSION, XBMC_LASTFM_ID, strUserName, passwordmd5, 0, ""); if (!http.Get(url, html)) { CLog::Log(LOGERROR, "Connect to Last.fm radio failed."); return false; } //CLog::Log(LOGDEBUG, "Handshake: %s", html.c_str()); Parameter("session", html, m_RadioSession); Parameter("base_url", html, m_RadioBaseUrl); Parameter("base_path", html, m_RadioBasePath); Parameter("subscriber", html, m_RadioSubscriber); Parameter("banned", html, m_RadioBanned); if (m_RadioSession.CompareNoCase("failed") == 0) { CLog::Log(LOGERROR, "Last.fm return failed response, possible bad username or password?"); m_RadioSession = ""; } return !m_RadioSession.IsEmpty(); }
TEST_F(TestWebServer, CanGetCachedFileWithExactIfModifiedSince) { // get the last modified date of the file CDateTime lastModified; ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified)); // get the file with the exact If-Modified-Since value std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, ""); curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModified.GetAsRFC1123DateTime()); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); ASSERT_TRUE(result.empty()); CheckRangesTestFileResponse(curl, MHD_HTTP_NOT_MODIFIED, true); }
TEST_F(TestWebServer, CanGetRangedFileRange0_) { const std::string rangedFileContent = TEST_FILES_DATA_RANGES; const std::string range = "bytes=0-"; CHttpRanges ranges; ASSERT_TRUE(ranges.Parse(range, rangedFileContent.size())); // get the whole file but specify the beginning of the range std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, range); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); CheckRangesTestFileResponse(curl, result, ranges); }
TEST_F(TestWebServer, CanGetRangedFileRange0_2xEnd) { const std::string rangedFileContent = TEST_FILES_DATA_RANGES; const std::string range = GenerateRangeHeaderValue(0, rangedFileContent.size() * 2); CHttpRanges ranges; ASSERT_TRUE(ranges.Parse(range, rangedFileContent.size())); // get the whole file but specify a larger range std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, range); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); CheckRangesTestFileResponse(curl, result, ranges); }
TEST_F(TestWebServer, CanGetCachedFileWithExactIfUnmodifiedSince) { // get the last modified date of the file CDateTime lastModified; ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified)); // get the file with an older If-Unmodified-Since value std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, ""); curl.SetRequestHeader(MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE, lastModified.GetAsRFC1123DateTime()); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); EXPECT_STREQ(TEST_FILES_DATA_RANGES, result.c_str()); CheckRangesTestFileResponse(curl); }
TEST_F(TestWebServer, CanGetRangedFileRange_Last) { const std::string rangedFileContent = TEST_FILES_DATA_RANGES; std::vector<std::string> rangedContent = StringUtils::Split(TEST_FILES_DATA_RANGES, ";"); const std::string range = StringUtils::Format("bytes=-%u", static_cast<unsigned int>(rangedContent.back().size())); CHttpRanges ranges; ASSERT_TRUE(ranges.Parse(range, rangedFileContent.size())); // get the whole file but specify a larger range std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, range); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); CheckRangesTestFileResponse(curl, result, ranges); }
TEST_F(TestWebServer, CanGetRangedFileRangeFirst_Second) { const std::string rangedFileContent = TEST_FILES_DATA_RANGES; std::vector<std::string> rangedContent = StringUtils::Split(TEST_FILES_DATA_RANGES, ";"); const std::string range = GenerateRangeHeaderValue(rangedContent.front().size() + 1, rangedContent.front().size() + 1 + rangedContent.at(2).size() - 1); CHttpRanges ranges; ASSERT_TRUE(ranges.Parse(range, rangedFileContent.size())); // get the whole file but specify a larger range std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, range); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); CheckRangesTestFileResponse(curl, result, ranges); }
TEST_F(TestWebServer, CanGetCachedFileWithNewerIfModifiedSinceForcingNoCache) { // get the last modified date of the file CDateTime lastModified; ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified)); CDateTime lastModifiedNewer = lastModified + CDateTimeSpan(1, 0, 0, 0); // get the file with a newer If-Modified-Since value but forcing no caching std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, ""); curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModifiedNewer.GetAsRFC1123DateTime()); curl.SetRequestHeader(MHD_HTTP_HEADER_CACHE_CONTROL, "no-cache"); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); EXPECT_STREQ(TEST_FILES_DATA_RANGES, result.c_str()); CheckRangesTestFileResponse(curl); }
TEST_F(TestWebServer, CanGetCachedRangedFileWithExactIfRange) { const std::string rangedFileContent = TEST_FILES_DATA_RANGES; const std::string range = "bytes=0-"; CHttpRanges ranges; ASSERT_TRUE(ranges.Parse(range, rangedFileContent.size())); // get the last modified date of the file CDateTime lastModified; ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified)); // get the whole file (but ranged) with an older If-Range value std::string result; CCurlFile curl; curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, range); curl.SetRequestHeader(MHD_HTTP_HEADER_IF_RANGE, lastModified.GetAsRFC1123DateTime()); ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result)); CheckRangesTestFileResponse(curl, result, ranges); }
TEST_F(TestWebServer, CanGetJsonRpcApiDescription) { std::string result; CCurlFile curl; ASSERT_TRUE(curl.Get(GetUrl(TEST_URL_JSONRPC), result)); ASSERT_FALSE(result.empty()); // get the HTTP header details const CHttpHeader& httpHeader = curl.GetHttpHeader(); // Content-Type must be "application/json" EXPECT_STREQ("application/json", httpHeader.GetMimeType().c_str()); // Accept-Ranges must be "none" EXPECT_STREQ("none", httpHeader.GetValue(MHD_HTTP_HEADER_ACCEPT_RANGES).c_str()); // Cache-Control must contain "mag-age=0" and "no-cache" std::string cacheControl = httpHeader.GetValue(MHD_HTTP_HEADER_CACHE_CONTROL); EXPECT_TRUE(cacheControl.find("max-age=0") != std::string::npos); EXPECT_TRUE(cacheControl.find("no-cache") != std::string::npos); }
bool CPicture::CacheImage(const CStdString& sourceUrl, const CStdString& destFile, int width, int height) { if (width > 0 && height > 0) { CLog::Log(LOGINFO, "Caching image from: %s to %s with width %i and height %i", sourceUrl.c_str(), destFile.c_str(), width, height); DllImageLib dll; if (!dll.Load()) return false; if (URIUtils::IsInternetStream(sourceUrl, true)) { CCurlFile http; CStdString data; if (http.Get(sourceUrl, data)) { if (!dll.CreateThumbnailFromMemory((BYTE *)data.c_str(), data.GetLength(), URIUtils::GetExtension(sourceUrl).c_str(), destFile.c_str(), width, height)) { CLog::Log(LOGERROR, "%s Unable to create new image %s from image %s", __FUNCTION__, destFile.c_str(), sourceUrl.c_str()); return false; } return true; } return false; } if (!dll.CreateThumbnail(sourceUrl.c_str(), destFile.c_str(), width, height, g_guiSettings.GetBool("pictures.useexifrotation"))) { CLog::Log(LOGERROR, "%s Unable to create new image %s from image %s", __FUNCTION__, destFile.c_str(), sourceUrl.c_str()); return false; } return true; } else { CLog::Log(LOGINFO, "Caching image from: %s to %s", sourceUrl.c_str(), destFile.c_str()); return CFile::Cache(sourceUrl, destFile); } }
bool CLastFmManager::ChangeStation(const CURL& stationUrl) { unsigned int start = XbmcThreads::SystemClockMillis(); InitProgressDialog(stationUrl.Get()); StopRadio(false); if (!RadioHandShake()) { CloseProgressDialog(); CGUIDialogOK::ShowAndGetInput(15200, 15206, 0, 0); return false; } UpdateProgressDialog(15252); // Selecting station... CCurlFile http; CStdString url; CStdString html; url.Format("http://" + m_RadioBaseUrl + m_RadioBasePath + "/adjust.php?session=%s&url=%s&debug=%i", m_RadioSession, stationUrl.Get().c_str(), 0); if (!http.Get(url, html)) { CLog::Log(LOGERROR, "Connect to Last.fm to change station failed."); CloseProgressDialog(); return false; } //CLog::Log(LOGDEBUG, "ChangeStation: %s", html.c_str()); CStdString strErrorCode; Parameter("error", html, strErrorCode); if (strErrorCode != "") { CLog::Log(LOGERROR, "Last.fm returned an error (%s) response for change station request.", strErrorCode.c_str()); CloseProgressDialog(); return false; } UpdateProgressDialog(261); //Waiting for start.... g_playlistPlayer.ClearPlaylist(PLAYLIST_MUSIC); RequestRadioTracks(); CacheTrackThumb(XBMC_LASTFM_MINTRACKS); AddToPlaylist(XBMC_LASTFM_MINTRACKS); Create(); //start thread m_hWorkerEvent.Set(); //kickstart the thread CSingleLock lock(m_lockPlaylist); CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC); if ((int)playlist.size()) { g_application.m_strPlayListFile = stationUrl.Get(); //needed to highlight the playing item g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC); g_playlistPlayer.Play(0); CLog::Log(LOGDEBUG, "%s: Done (time: %i ms)", __FUNCTION__, (int)(XbmcThreads::SystemClockMillis() - start)); CloseProgressDialog(); return true; } CloseProgressDialog(); return false; }
void CDownloadQueue::Process() { CLog::Log(LOGNOTICE, "DownloadQueue ready."); CCurlFile http; bool bSuccess; while ( !m_bStop ) { while ( CDownloadQueue::Size() > 0 ) { CSingleLock lock(m_critical); // get the first item, but don't pop it from our queue // so that the download can be interrupted Command request = m_queue.front(); lock.Leave(); bool bFileRequest = request.content.length() > 0; DWORD dwSize = 0; if (bFileRequest) { CFile::Delete(request.content); bSuccess = http.Download(request.location, request.content, &dwSize); } else { bSuccess = http.Get(request.location, request.content); } // now re-grab the item as we may have cancelled our download // while we were working { CSingleLock lock2(m_critical); // open lock2 scope request = m_queue.front(); m_queue.pop(); // if the request has been cancelled our observer will be NULL if (NULL != request.observer) { try { if (bFileRequest) { request.observer->OnFileComplete(request.ticket, request.content, dwSize, bSuccess ? IDownloadQueueObserver::Succeeded : IDownloadQueueObserver::Failed ); } else { request.observer->OnContentComplete(request.ticket, request.content, bSuccess ? IDownloadQueueObserver::Succeeded : IDownloadQueueObserver::Failed ); } } catch (...) { CLog::Log(LOGERROR, "exception while updating download observer."); if (bFileRequest) { CFile::Delete(request.content); } } } } // close lock2 scope } Sleep(500); } CLog::Log(LOGNOTICE, "DownloadQueue terminated."); }
void CRssReader::Process() { while (GetQueueSize()) { CSingleLock lock(*this); int iFeed = m_vecQueue.front(); m_vecQueue.erase(m_vecQueue.begin()); m_strFeed[iFeed] = ""; m_strColors[iFeed] = ""; CCurlFile http; http.SetUserAgent(g_settings.m_userAgent); http.SetTimeout(2); CStdString strXML; CStdString strUrl = m_vecUrls[iFeed]; lock.Leave(); int nRetries = 3; CURL url(strUrl); // we wait for the network to come up if ((url.GetProtocol() == "http" || url.GetProtocol() == "https") && !g_application.getNetwork().IsAvailable(true)) strXML = "<rss><item><title>"+g_localizeStrings.Get(15301)+"</title></item></rss>"; else { unsigned int starttime = XbmcThreads::SystemClockMillis(); while ( (!m_bStop) && (nRetries > 0) ) { unsigned int currenttimer = XbmcThreads::SystemClockMillis() - starttime; if (currenttimer > 15000) { CLog::Log(LOGERROR,"Timeout whilst retrieving %s", strUrl.c_str()); http.Cancel(); break; } nRetries--; if (url.GetProtocol() != "http" && url.GetProtocol() != "https") { CFile file; if (file.Open(strUrl)) { char *yo = new char[(int)file.GetLength()+1]; file.Read(yo,file.GetLength()); yo[file.GetLength()] = '\0'; strXML = yo; delete[] yo; break; } } else if (http.Get(strUrl, strXML)) { CLog::Log(LOGDEBUG, "Got rss feed: %s", strUrl.c_str()); break; } } http.Cancel(); } if ((!strXML.IsEmpty()) && m_pObserver) { // erase any <content:encoded> tags (also unsupported by tinyxml) int iStart = strXML.Find("<content:encoded>"); int iEnd = 0; while (iStart > 0) { // get <content:encoded> end position iEnd = strXML.Find("</content:encoded>", iStart) + 18; // erase the section strXML = strXML.erase(iStart, iEnd - iStart); iStart = strXML.Find("<content:encoded>"); } if (Parse((LPSTR)strXML.c_str(),iFeed)) { CLog::Log(LOGDEBUG, "Parsed rss feed: %s", strUrl.c_str()); } } } UpdateObserver(); }
bool CLastFmManager::RequestRadioTracks() { unsigned int start = XbmcThreads::SystemClockMillis(); CStdString url; CStdString html; url.Format("http://" + m_RadioBaseUrl + m_RadioBasePath + "/xspf.php?sk=%s&discovery=0&desktop=", m_RadioSession); { CCurlFile http; if (!http.Get(url, html)) { m_RadioSession.empty(); CLog::Log(LOGERROR, "LastFmManager: Connect to Last.fm to request tracks failed."); return false; } } //CLog::Log(LOGDEBUG, "RequestRadioTracks: %s", html.c_str()); //parse playlist CXBMCTinyXML xmlDoc; xmlDoc.Parse(html); if (xmlDoc.Error()) { m_RadioSession.empty(); CLog::Log(LOGERROR, "LastFmManager: Unable to parse tracklist Error: %s", xmlDoc.ErrorDesc()); return false; } TiXmlElement* pRootElement = xmlDoc.RootElement(); if (!pRootElement ) { CLog::Log(LOGWARNING, "LastFmManager: No more tracks received"); m_RadioSession.empty(); return false; } TiXmlElement* pBodyElement = pRootElement->FirstChildElement("trackList"); if (!pBodyElement ) { CLog::Log(LOGWARNING, "LastFmManager: No more tracks received, no tracklist"); m_RadioSession.empty(); return false; } TiXmlElement* pTrackElement = pBodyElement->FirstChildElement("track"); if (!pTrackElement) { CLog::Log(LOGWARNING, "LastFmManager: No more tracks received, empty tracklist"); m_RadioSession.empty(); return false; } while (pTrackElement) { CFileItemPtr newItem(new CFileItem); TiXmlElement* pElement = pTrackElement->FirstChildElement("location"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { CStdString url = child->Value(); url.Replace("http:", "lastfm:"); newItem->SetPath(url); } } pElement = pTrackElement->FirstChildElement("title"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { newItem->SetLabel(child->Value()); newItem->GetMusicInfoTag()->SetTitle(child->Value()); } } pElement = pTrackElement->FirstChildElement("creator"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { newItem->GetMusicInfoTag()->SetArtist(child->Value()); } } pElement = pTrackElement->FirstChildElement("album"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { newItem->GetMusicInfoTag()->SetAlbum(child->Value()); } } pElement = pTrackElement->FirstChildElement("duration"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { int iDuration = atoi(child->Value())/1000; newItem->GetMusicInfoTag()->SetDuration(iDuration); } } newItem->FillInDefaultIcon(); pElement = pTrackElement->FirstChildElement("image"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { CStdString coverUrl = child->Value(); if ((coverUrl != "") && (coverUrl.Find("noimage") == -1) && (coverUrl.Right(1) != "/")) { newItem->SetThumbnailImage(coverUrl); } } } //trackauth is needed for validating the track when scrobbling pElement = pTrackElement->FirstChildElement("lastfm:trackauth"); if (pElement) { TiXmlNode* child = pElement->FirstChild(); if (child) { CStdString trackAuth = child->Value(); //abuse comment field for the track authcode newItem->GetMusicInfoTag()->SetComment(trackAuth); } } { CSingleLock lock(m_lockCache); m_RadioTrackQueue->Add(newItem); } pTrackElement = pTrackElement->NextSiblingElement(); } //end parse CSingleLock lock(m_lockCache); int iNrCachedTracks = m_RadioTrackQueue->size(); CLog::Log(LOGDEBUG, "%s: Done (time: %i ms)", __FUNCTION__, (int)(XbmcThreads::SystemClockMillis() - start)); return iNrCachedTracks > 0; }
void CRssReader::Process() { while (GetQueueSize()) { CSingleLock lock(m_critical); int iFeed = m_vecQueue.front(); m_vecQueue.erase(m_vecQueue.begin()); m_strFeed[iFeed].clear(); m_strColors[iFeed].clear(); CCurlFile http; http.SetUserAgent(g_advancedSettings.m_userAgent); http.SetTimeout(2); std::string strXML; std::string strUrl = m_vecUrls[iFeed]; lock.Leave(); int nRetries = 3; CURL url(strUrl); std::string fileCharset; // we wait for the network to come up if ((url.IsProtocol("http") || url.IsProtocol("https")) && !g_application.getNetwork().IsAvailable()) { CLog::Log(LOGWARNING, "RSS: No network connection"); strXML = "<rss><item><title>"+g_localizeStrings.Get(15301)+"</title></item></rss>"; } else { XbmcThreads::EndTime timeout(15000); while (!m_bStop && nRetries > 0) { if (timeout.IsTimePast()) { CLog::Log(LOGERROR, "Timeout while retrieving rss feed: %s", strUrl.c_str()); break; } nRetries--; if (!url.IsProtocol("http") && !url.IsProtocol("https")) { CFile file; auto_buffer buffer; if (file.LoadFile(strUrl, buffer) > 0) { strXML.assign(buffer.get(), buffer.length()); break; } } else { if (http.Get(strUrl, strXML)) { fileCharset = http.GetServerReportedCharset(); CLog::Log(LOGDEBUG, "Got rss feed: %s", strUrl.c_str()); break; } else if (nRetries > 0) Sleep(5000); // Network problems? Retry, but not immediately. else CLog::Log(LOGERROR, "Unable to obtain rss feed: %s", strUrl.c_str()); } } http.Cancel(); } if (!strXML.empty() && m_pObserver) { // erase any <content:encoded> tags (also unsupported by tinyxml) size_t iStart = strXML.find("<content:encoded>"); size_t iEnd = 0; while (iStart != std::string::npos) { // get <content:encoded> end position iEnd = strXML.find("</content:encoded>", iStart) + 18; // erase the section strXML = strXML.erase(iStart, iEnd - iStart); iStart = strXML.find("<content:encoded>"); } if (Parse(strXML, iFeed, fileCharset)) CLog::Log(LOGDEBUG, "Parsed rss feed: %s", strUrl.c_str()); } } UpdateObserver(); }
void CRssReader::Process() { while (GetQueueSize()) { CSingleLock lock(m_critical); int iFeed = m_vecQueue.front(); m_vecQueue.erase(m_vecQueue.begin()); m_strFeed[iFeed] = ""; m_strColors[iFeed] = ""; CCurlFile http; http.SetUserAgent(g_advancedSettings.m_userAgent); http.SetTimeout(2); CStdString strXML; CStdString strUrl = m_vecUrls[iFeed]; lock.Leave(); int nRetries = 3; CURL url(strUrl); // we wait for the network to come up if ((url.GetProtocol() == "http" || url.GetProtocol() == "https") && !g_application.getNetwork().IsAvailable(true)) strXML = "<rss><item><title>"+g_localizeStrings.Get(15301)+"</title></item></rss>"; else { XbmcThreads::EndTime timeout(15000); while (!m_bStop && nRetries > 0) { if (timeout.IsTimePast()) { CLog::Log(LOGERROR, "Timeout whilst retrieving %s", strUrl.c_str()); http.Cancel(); break; } nRetries--; if (url.GetProtocol() != "http" && url.GetProtocol() != "https") { void* bufferPtr; const unsigned int fsize = CFileUtils::LoadFile(strUrl, bufferPtr); if (fsize != 0) { strXML.assign((const char*)bufferPtr, fsize); free(bufferPtr); break; } } else if (http.Get(strUrl, strXML)) { CLog::Log(LOGDEBUG, "Got rss feed: %s", strUrl.c_str()); break; } } http.Cancel(); } if (!strXML.IsEmpty() && m_pObserver) { // erase any <content:encoded> tags (also unsupported by tinyxml) int iStart = strXML.Find("<content:encoded>"); int iEnd = 0; while (iStart > 0) { // get <content:encoded> end position iEnd = strXML.Find("</content:encoded>", iStart) + 18; // erase the section strXML = strXML.erase(iStart, iEnd - iStart); iStart = strXML.Find("<content:encoded>"); } if (Parse((LPSTR)strXML.c_str(), iFeed)) CLog::Log(LOGDEBUG, "Parsed rss feed: %s", strUrl.c_str()); } } UpdateObserver(); }