X-Git-Url: http://code.vuplus.com/gitweb/?a=blobdiff_plain;f=xbmc%2Ffilesystem%2FCurlFile.cpp;h=4808465c1dfc9e7e7712f03a9e11bb3d7784e615;hb=f92a074a74a570f52e546ba4f28d9346bf8ddd31;hp=2197c44ee7dc215456cec79aa7915bb23c30c8eb;hpb=07f2b46b895d757042b751a27dbd53e2f48b6371;p=vuplus_xbmc diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp index 2197c44..4808465 100644 --- a/xbmc/filesystem/CurlFile.cpp +++ b/xbmc/filesystem/CurlFile.cpp @@ -25,6 +25,7 @@ #include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "File.h" +#include "threads/SystemClock.h" #include #include @@ -50,9 +51,6 @@ using namespace XCURL; #define XMIN(a,b) ((a)<(b)?(a):(b)) #define FITS_INT(a) (((a) <= INT_MAX) && ((a) >= INT_MIN)) -#define dllselect select - - curl_proxytype proxyType2CUrlProxyType[] = { CURLPROXY_HTTP, CURLPROXY_SOCKS4, @@ -396,6 +394,7 @@ CCurlFile::CCurlFile() m_username = ""; m_password = ""; m_httpauth = ""; + m_cipherlist = ""; m_proxytype = PROXY_HTTP; m_state = new CReadState(); m_oldState = NULL; @@ -607,6 +606,10 @@ void CCurlFile::SetCommonOptions(CReadState* state) // the 302 response's body length, which cause the next read request failed, so we ignore // content-length for shoutcast file to workaround this. g_curlInterface.easy_setopt(h, CURLOPT_IGNORE_CONTENT_LENGTH, 1); + + // Setup allowed TLS/SSL ciphers. New versions of cURL may deprecate things that are still in use. + if (!m_cipherlist.empty()) + g_curlInterface.easy_setopt(h, CURLOPT_SSL_CIPHER_LIST, m_cipherlist.c_str()); } void CCurlFile::SetRequestHeaders(CReadState* state) @@ -674,7 +677,7 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) /* url encoded. if handed from ftpdirectory */ /* it won't be so let's handle that case */ - CStdString partial, filename(url2.GetFileName()); + CStdString filename(url2.GetFileName()); std::vector array; // if server sent us the filename in non-utf8, we need send back with same encoding. @@ -689,9 +692,7 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) if(it != array.begin()) filename += "/"; - partial = *it; - CURL::Encode(partial); - filename += partial; + filename += CURL::Encode(*it); } /* make sure we keep slashes */ @@ -744,8 +745,6 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) url2.GetProtocolOptions(options); if (options.size() > 0) { - // clear protocol options - url2.SetProtocolOptions(""); // set xbmc headers for(std::map::const_iterator it = options.begin(); it != options.end(); ++it) { @@ -772,11 +771,18 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) m_seekable = false; else if (name.Equals("Accept-Charset")) SetAcceptCharset(value); + else if (name.Equals("HttpProxy")) + SetStreamProxy(value, PROXY_HTTP); + else if (name.Equals("SSLCipherList")) + m_cipherlist = value; else SetRequestHeader(name, value); } } } + + // Unset the protocol options to have an url without protocol options + url2.SetProtocolOptions(""); if (m_username.length() > 0 && m_password.length() > 0) m_url = url2.GetWithoutUserDetails(); @@ -784,6 +790,17 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) m_url = url2.Get(); } +void CCurlFile::SetStreamProxy(const CStdString &proxy, ProxyType type) +{ + CURL url(proxy); + m_proxy = url.GetWithoutUserDetails(); + m_proxyuserpass = url.GetUserName(); + if (!url.GetPassWord().empty()) + m_proxyuserpass += ":" + url.GetPassWord(); + m_proxytype = type; + CLog::Log(LOGDEBUG, "Overriding proxy from URL parameter: %s, type %d", m_proxy.c_str(), proxyType2CUrlProxyType[m_proxytype]); +} + bool CCurlFile::Post(const CStdString& strURL, const CStdString& strPostData, CStdString& strHTML) { m_postdata = strPostData; @@ -857,12 +874,9 @@ bool CCurlFile::Download(const CStdString& strURL, const CStdString& strFileName } // Detect whether we are "online" or not! Very simple and dirty! -bool CCurlFile::IsInternet(bool checkDNS /* = true */) +bool CCurlFile::IsInternet() { CStdString strURL = "http://www.google.com"; - if (!checkDNS) - strURL = "http://74.125.19.103"; // www.google.com ip - bool found = Exists(strURL); Close(); @@ -1120,6 +1134,10 @@ bool CCurlFile::Exists(const CURL& url) int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) { int64_t nextPos = m_state->m_filePos; + + if(!m_seekable) + return -1; + switch(iWhence) { case SEEK_SET: @@ -1144,28 +1162,31 @@ int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) if(m_state->Seek(nextPos)) return nextPos; - if (m_oldState && m_oldState->Seek(nextPos)) + if (m_multisession) { - CReadState *tmp = m_state; - m_state = m_oldState; - m_oldState = tmp; - return nextPos; - } - - if(!m_seekable) - return -1; - - CReadState* oldstate = NULL; - if(m_multisession) - { - CURL url(m_url); - oldstate = m_oldState; - m_oldState = m_state; - m_state = new CReadState(); - - g_curlInterface.easy_aquire(url.GetProtocol(), url.GetHostName(), &m_state->m_easyHandle, &m_state->m_multiHandle ); - - m_state->m_fileSize = m_oldState->m_fileSize; + if (!m_oldState) + { + CURL url(m_url); + m_oldState = m_state; + m_state = new CReadState(); + m_state->m_fileSize = m_oldState->m_fileSize; + g_curlInterface.easy_aquire(url.GetProtocol(), + url.GetHostName(), + &m_state->m_easyHandle, + &m_state->m_multiHandle ); + } + else + { + CReadState *tmp; + tmp = m_state; + m_state = m_oldState; + m_oldState = tmp; + + if (m_state->Seek(nextPos)) + return nextPos; + + m_state->Disconnect(); + } } else m_state->Disconnect(); @@ -1182,18 +1203,26 @@ int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) long response = m_state->Connect(m_bufferSize); if(response < 0 && (m_state->m_fileSize == 0 || m_state->m_fileSize != m_state->m_filePos)) { - m_seekable = false; - if(m_multisession && m_oldState) + if(m_multisession) { - delete m_state; - m_state = m_oldState; - m_oldState = oldstate; + if (m_oldState) + { + delete m_state; + m_state = m_oldState; + m_oldState = NULL; + } + // Retry without mutlisession + m_multisession = false; + return Seek(iFilePosition, iWhence); } - return -1; + else + { + m_seekable = false; + return -1; + } } SetCorrectHeaders(m_state); - delete oldstate; return m_state->m_filePos; } @@ -1497,14 +1526,33 @@ bool CCurlFile::CReadState::FillBuffer(unsigned int want) if (CURLM_OK != g_curlInterface.multi_timeout(m_multiHandle, &timeout) || timeout == -1) timeout = 200; - struct timeval t = { timeout / 1000, (timeout % 1000) * 1000 }; + XbmcThreads::EndTime endTime(timeout); + int rc; - /* Wait until data is available or a timeout occurs. - We call dllselect(maxfd + 1, ...), specially in case of (maxfd == -1), - we call dllselect(0, ...), which is basically equal to sleep. */ - if (SOCKET_ERROR == dllselect(maxfd + 1, &fdread, &fdwrite, &fdexcep, &t)) + do { - CLog::Log(LOGERROR, "CCurlFile::FillBuffer - Failed with socket error"); + unsigned int time_left = endTime.MillisLeft(); + struct timeval t = { time_left / 1000, (time_left % 1000) * 1000 }; + + // Wait until data is available or a timeout occurs. + rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &t); +#ifdef TARGET_WINDOWS + } while(rc == SOCKET_ERROR && WSAGetLastError() == WSAEINTR); +#else + } while(rc == SOCKET_ERROR && errno == EINTR); +#endif + + if(rc == SOCKET_ERROR) + { +#ifdef TARGET_WINDOWS + char buf[256]; + strerror_s(buf, 256, WSAGetLastError()); + CLog::Log(LOGERROR, "CCurlFile::FillBuffer - Failed with socket error:%s", buf); +#else + char const * str = strerror(errno); + CLog::Log(LOGERROR, "CCurlFile::FillBuffer - Failed with socket error:%s", str); +#endif + return false; } }