aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xbmc/filesystem/CurlFile.cpp46
-rw-r--r--xbmc/filesystem/CurlFile.h4
-rw-r--r--xbmc/utils/HttpHeader.cpp75
-rw-r--r--xbmc/utils/HttpHeader.h18
4 files changed, 107 insertions, 36 deletions
diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp
index be3c915a65..c951a09464 100644
--- a/xbmc/filesystem/CurlFile.cpp
+++ b/xbmc/filesystem/CurlFile.cpp
@@ -140,31 +140,16 @@ static inline void* realloc_simple(void *ptr, size_t size)
size_t CCurlFile::CReadState::HeaderCallback(void *ptr, size_t size, size_t nmemb)
{
- // clear any previous header
- if(m_headerdone)
- {
- m_httpheader.Clear();
- m_headerdone = false;
- }
-
+ std::string inString;
// libcurl doc says that this info is not always \0 terminated
- char* strData = (char*)ptr;
- int iSize = size * nmemb;
-
- if (strData[iSize] != 0)
- {
- strData = (char*)malloc(iSize + 1);
- strncpy(strData, (char*)ptr, iSize);
- strData[iSize] = 0;
- }
- else strData = strdup((char*)ptr);
-
- if(strcmp(strData, "\r\n") == 0)
- m_headerdone = true;
-
- m_httpheader.Parse(strData);
+ const char* strBuf = (const char*)ptr;
+ const size_t iSize = size * nmemb;
+ if (strBuf[iSize - 1] == 0)
+ inString.assign(strBuf, iSize - 1); // skip last char if it's zero
+ else
+ inString.append(strBuf, iSize);
- free(strData);
+ m_httpheader.Parse(inString);
return iSize;
}
@@ -248,7 +233,6 @@ CCurlFile::CReadState::CReadState()
m_cancelled = false;
m_bFirstLoop = true;
m_sendRange = true;
- m_headerdone = false;
m_readBuffer = 0;
m_isPaused = false;
m_curlHeaderList = NULL;
@@ -332,7 +316,7 @@ long CCurlFile::CReadState::Connect(unsigned int size)
m_bufferSize = size;
m_buffer.Destroy();
m_buffer.Create(size * 3);
- m_headerdone = false;
+ m_httpheader.Clear();
// read some data in to try and obtain the length
// maybe there's a better way to get this info??
@@ -652,7 +636,7 @@ void CCurlFile::SetCorrectHeaders(CReadState* state)
if( !h.GetValue("icy-notice1").empty()
|| !h.GetValue("icy-name").empty()
|| !h.GetValue("icy-br").empty() )
- h.Parse("Content-Type: audio/mpeg\r\n");
+ h.AddParam("Content-Type", "audio/mpeg");
}
/* hack for google video */
@@ -661,7 +645,7 @@ void CCurlFile::SetCorrectHeaders(CReadState* state)
{
CStdString strValue = h.GetValue("Content-Disposition");
if (strValue.Find("filename=") > -1 && strValue.Find(".flv") > -1)
- h.Parse("Content-Type: video/flv\r\n");
+ h.AddParam("Content-Type", "video/flv");
}
}
@@ -1562,6 +1546,14 @@ void CCurlFile::SetRequestHeader(CStdString header, long value)
m_requestheaders[header] = buffer;
}
+std::string CCurlFile::GetServerReportedCharset(void)
+{
+ if (!m_state)
+ return "";
+
+ return m_state->m_httpheader.GetCharset();
+}
+
/* STATIC FUNCTIONS */
bool CCurlFile::GetHttpHeader(const CURL &url, CHttpHeader &headers)
{
diff --git a/xbmc/filesystem/CurlFile.h b/xbmc/filesystem/CurlFile.h
index a828c8895a..64f7b86a4b 100644
--- a/xbmc/filesystem/CurlFile.h
+++ b/xbmc/filesystem/CurlFile.h
@@ -90,6 +90,7 @@ namespace XFILE
void SetBufferSize(unsigned int size);
const CHttpHeader& GetHttpHeader() { return m_state->m_httpheader; }
+ std::string GetServerReportedCharset(void);
/* static function that will get content type of a file */
static bool GetHttpHeader(const CURL &url, CHttpHeader &headers);
@@ -120,7 +121,8 @@ namespace XFILE
/* returned http header */
CHttpHeader m_httpheader;
- bool m_headerdone;
+ bool IsHeaderDone(void)
+ { return m_httpheader.IsHeaderDone(); }
struct XCURL::curl_slist* m_curlHeaderList;
struct XCURL::curl_slist* m_curlAliasList;
diff --git a/xbmc/utils/HttpHeader.cpp b/xbmc/utils/HttpHeader.cpp
index fcc6732918..c9dade3669 100644
--- a/xbmc/utils/HttpHeader.cpp
+++ b/xbmc/utils/HttpHeader.cpp
@@ -23,6 +23,7 @@
CHttpHeader::CHttpHeader()
{
+ m_headerdone = false;
}
CHttpHeader::~CHttpHeader()
@@ -31,6 +32,9 @@ CHttpHeader::~CHttpHeader()
void CHttpHeader::Parse(const std::string& strData)
{
+ if (m_headerdone)
+ Clear();
+
size_t pos = 0;
const size_t len = strData.length();
while (pos < len)
@@ -41,7 +45,12 @@ void CHttpHeader::Parse(const std::string& strData)
if (lineEnd == std::string::npos)
break;
- if (valueStart != std::string::npos && valueStart < lineEnd)
+ if (lineEnd == pos)
+ {
+ m_headerdone = true;
+ break;
+ }
+ else if (valueStart != std::string::npos && valueStart < lineEnd)
{
std::string strParam(strData, pos, valueStart - pos);
std::string strValue(strData, valueStart + 1, lineEnd - valueStart - 1);
@@ -61,10 +70,40 @@ void CHttpHeader::Parse(const std::string& strData)
}
}
-std::string CHttpHeader::GetValue(std::string strParam) const
+void CHttpHeader::AddParam(const std::string& param, const std::string& value, const bool overwrite /*= false*/)
{
- StringUtils::ToLower(strParam);
+ if (param.empty() || value.empty())
+ return;
+
+ std::string paramLower(param);
+ if (overwrite)
+ { // delete ALL parameters with the same name
+ // note: 'GetValue' always returns last added parameter,
+ // so you probably don't need to overwrite
+ for (size_t i = 0; i < m_params.size();)
+ {
+ if (m_params[i].first == param)
+ m_params.erase(m_params.begin() + i);
+ else
+ ++i;
+ }
+ }
+
+ StringUtils::ToLower(paramLower);
+ m_params.push_back(HeaderParams::value_type(paramLower, value));
+}
+
+std::string CHttpHeader::GetValue(const std::string& strParam) const
+{
+ std::string paramLower(strParam);
+ StringUtils::ToLower(paramLower);
+
+ return GetValueRaw(paramLower);
+}
+
+std::string CHttpHeader::GetValueRaw(const std::string& strParam) const
+{
// look in reverse to find last parameter (probably most important)
for (HeaderParams::const_reverse_iterator iter = m_params.rbegin(); iter != m_params.rend(); ++iter)
{
@@ -100,8 +139,38 @@ std::string CHttpHeader::GetHeader(void) const
return strHeader;
}
+std::string CHttpHeader::GetMimeType(void) const
+{
+ std::string strValue(GetValueRaw("content-type"));
+
+ return strValue.substr(0, strValue.find(';'));
+}
+
+std::string CHttpHeader::GetCharset(void) const
+{
+ std::string strValue(GetValueRaw("content-type"));
+ if (strValue.empty())
+ return strValue;
+
+ const size_t semicolonPos = strValue.find(';');
+ if (semicolonPos == std::string::npos)
+ return "";
+
+ StringUtils::ToUpper(strValue);
+ size_t posCharset;
+ if ((posCharset = strValue.find("; CHARSET=", semicolonPos)) != std::string::npos)
+ posCharset += 10;
+ else if ((posCharset = strValue.find(";CHARSET=", semicolonPos)) != std::string::npos)
+ posCharset += 9;
+ else
+ return "";
+
+ return strValue.substr(posCharset, strValue.find(';', posCharset) - posCharset);
+}
+
void CHttpHeader::Clear()
{
m_params.clear();
m_protoLine.clear();
+ m_headerdone = false;
}
diff --git a/xbmc/utils/HttpHeader.h b/xbmc/utils/HttpHeader.h
index 4ddb279105..5e1b6b9061 100644
--- a/xbmc/utils/HttpHeader.h
+++ b/xbmc/utils/HttpHeader.h
@@ -24,8 +24,6 @@
#include <vector>
#include <string>
-#define HTTPHEADER_CONTENT_TYPE "Content-Type"
-
class CHttpHeader
{
public:
@@ -37,18 +35,28 @@ public:
~CHttpHeader();
void Parse(const std::string& strData);
- std::string GetValue(std::string strParam) const;
+ void AddParam(const std::string& param, const std::string& value, const bool overwrite = false);
+
+ std::string GetValue(const std::string& strParam) const;
std::vector<std::string> GetValues(std::string strParam) const;
std::string GetHeader(void) const;
- std::string GetMimeType() { return GetValue(HTTPHEADER_CONTENT_TYPE); }
- std::string GetProtoLine() { return m_protoLine; }
+ std::string GetMimeType(void) const;
+ std::string GetCharset(void) const;
+ inline std::string GetProtoLine() const
+ { return m_protoLine; }
+
+ inline bool IsHeaderDone(void) const
+ { return m_headerdone; }
void Clear();
protected:
+ std::string GetValueRaw(const std::string& strParam) const;
+
HeaderParams m_params;
std::string m_protoLine;
+ bool m_headerdone;
};