From 84813db2ae980ecfd0a2bc80c840c93319d1a707 Mon Sep 17 00:00:00 2001 From: Red-F Date: Mon, 8 Oct 2012 22:09:11 +0200 Subject: [PATCH] Provide IFile consumers a rudimentary HTTP POST option via a CurlFile sub-class called HTTPFile. Implements IFile's OpenForWrite and Write methods to POST data with Content-Type set to "Application/Json" --- project/VS2010Express/XBMC.vcxproj | 2 + project/VS2010Express/XBMC.vcxproj.filters | 6 ++ xbmc/filesystem/CurlFile.cpp | 11 ++-- xbmc/filesystem/CurlFile.h | 8 ++- xbmc/filesystem/FileFactory.cpp | 6 +- xbmc/filesystem/HTTPFile.cpp | 65 ++++++++++++++++++++++ xbmc/filesystem/HTTPFile.h | 38 +++++++++++++ xbmc/filesystem/Makefile.in | 1 + 8 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 xbmc/filesystem/HTTPFile.cpp create mode 100644 xbmc/filesystem/HTTPFile.h diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 4c7824dfcdb8c..c0a8a3516ff25 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -477,6 +477,7 @@ + @@ -1020,6 +1021,7 @@ + diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index b471ebfa050e0..cf1711ecbc16a 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -2936,6 +2936,9 @@ interfaces\json-rpc + + filesystem + @@ -5740,6 +5743,9 @@ interfaces\json-rpc + + filesystem + diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp index 5878786fc78e4..143716e8f5622 100644 --- a/xbmc/filesystem/CurlFile.cpp +++ b/xbmc/filesystem/CurlFile.cpp @@ -322,11 +322,13 @@ CCurlFile::CCurlFile() m_bufferSize = 32768; m_binary = true; m_postdata = ""; + m_postdataset = false; m_username = ""; m_password = ""; m_httpauth = ""; m_state = new CReadState(); m_skipshout = false; + m_httpresponse = -1; } //Has to be called before Open() @@ -423,8 +425,8 @@ void CCurlFile::SetCommonOptions(CReadState* state) g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_URL, m_url.c_str()); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_TRANSFERTEXT, FALSE); - // setup POST data if it exists - if (!m_postdata.IsEmpty()) + // setup POST data if it is set (and it may be empty) + if (m_postdataset) { g_curlInterface.easy_setopt(h, CURLOPT_POST, 1 ); g_curlInterface.easy_setopt(h, CURLOPT_POSTFIELDSIZE, m_postdata.length()); @@ -741,6 +743,7 @@ bool CCurlFile::Get(const CStdString& strURL, CStdString& strHTML) bool CCurlFile::Service(const CStdString& strURL, const CStdString& strPostData, CStdString& strHTML) { m_postdata = strPostData; + m_postdataset = true; if (Open(strURL)) { if (ReadData(strHTML)) @@ -840,8 +843,8 @@ bool CCurlFile::Open(const CURL& url) SetCommonOptions(m_state); SetRequestHeaders(m_state); - long response = m_state->Connect(m_bufferSize); - if( response < 0 || response >= 400) + m_httpresponse = m_state->Connect(m_bufferSize); + if( m_httpresponse < 0 || m_httpresponse >= 400) return false; SetCorrectHeaders(m_state); diff --git a/xbmc/filesystem/CurlFile.h b/xbmc/filesystem/CurlFile.h index cc16dded2b798..3ad10b2dc3d32 100644 --- a/xbmc/filesystem/CurlFile.h +++ b/xbmc/filesystem/CurlFile.h @@ -70,7 +70,7 @@ namespace XFILE void SetPostData(CStdString postdata) { m_postdata = postdata; } void SetReferer(CStdString referer) { m_referer = referer; } void SetCookie(CStdString cookie) { m_cookie = cookie; } - void SetMimeType(CStdString mimetype) { SetRequestHeader("Content-Type", m_mimetype); } + void SetMimeType(CStdString mimetype) { SetRequestHeader("Content-Type", mimetype); } void SetRequestHeader(CStdString header, CStdString value); void SetRequestHeader(CStdString header, long value); @@ -125,7 +125,7 @@ namespace XFILE void SetCorrectHeaders(CReadState* state); bool Service(const CStdString& strURL, const CStdString& strPostData, CStdString& strHTML); - private: + protected: CReadState* m_state; unsigned int m_bufferSize; @@ -141,7 +141,6 @@ namespace XFILE CStdString m_postdata; CStdString m_referer; CStdString m_cookie; - CStdString m_mimetype; CStdString m_username; CStdString m_password; CStdString m_httpauth; @@ -153,6 +152,7 @@ namespace XFILE bool m_seekable; bool m_multisession; bool m_skipshout; + bool m_postdataset; CRingBuffer m_buffer; // our ringhold buffer char * m_overflowBuffer; // in the rare case we would overflow the above buffer @@ -165,6 +165,8 @@ namespace XFILE typedef std::map MAPHTTPHEADERS; MAPHTTPHEADERS m_requestheaders; + + long m_httpresponse; }; } diff --git a/xbmc/filesystem/FileFactory.cpp b/xbmc/filesystem/FileFactory.cpp index d67194abf8508..09482c7c10f9a 100644 --- a/xbmc/filesystem/FileFactory.cpp +++ b/xbmc/filesystem/FileFactory.cpp @@ -26,6 +26,7 @@ #include "FileFactory.h" #include "HDFile.h" #include "CurlFile.h" +#include "HTTPFile.h" #include "ShoutcastFile.h" #include "LastFMFile.h" #include "FileReaderFile.h" @@ -144,13 +145,12 @@ IFile* CFileFactory::CreateLoader(const CURL& url) if( g_application.getNetwork().IsAvailable() ) { - if (strProtocol == "http" - || strProtocol == "https" - || strProtocol == "dav" + if (strProtocol == "dav" || strProtocol == "davs" || strProtocol == "ftp" || strProtocol == "ftps" || strProtocol == "rss") return new CCurlFile(); + else if (strProtocol == "http" || strProtocol == "https") return new CHTTPFile(); #ifdef HAS_FILESYSTEM_SFTP else if (strProtocol == "sftp" || strProtocol == "ssh") return new CSFTPFile(); #endif diff --git a/xbmc/filesystem/HTTPFile.cpp b/xbmc/filesystem/HTTPFile.cpp new file mode 100644 index 0000000000000..fb424829a2385 --- /dev/null +++ b/xbmc/filesystem/HTTPFile.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "HTTPFile.h" + +using namespace XFILE; + +CHTTPFile::CHTTPFile(void) +{ + m_openedforwrite = false; +} + + +CHTTPFile::~CHTTPFile(void) +{ +} + +bool CHTTPFile::OpenForWrite(const CURL& url, bool bOverWrite) +{ + // real Open is delayed until we receive the POST data + m_urlforwrite = url; + m_openedforwrite = true; + return true; +} + +int CHTTPFile::Write(const void* lpBuf, int64_t uiBufSize) +{ + // Although we can not verify much, try to catch errors where we can + if (!m_openedforwrite) + return -1; + + CStdString myPostData((char*) lpBuf); + if (myPostData.length() != uiBufSize) + return -1; + + // If we get here, we (most likely) satisfied the pre-conditions that we used OpenForWrite and passed a string as postdata + // we mimic 'post(..)' but do not read any data + m_postdata = myPostData; + m_postdataset = true; + m_openedforwrite = false; + SetMimeType("application/json"); + if (!Open(m_urlforwrite)) + return -1; + + // Finally (and this is a clumsy hack) return the http response code + return (int) m_httpresponse; +} + diff --git a/xbmc/filesystem/HTTPFile.h b/xbmc/filesystem/HTTPFile.h new file mode 100644 index 0000000000000..06e9a275af575 --- /dev/null +++ b/xbmc/filesystem/HTTPFile.h @@ -0,0 +1,38 @@ +#pragma once +/* +* Copyright (C) 2005-2012 Team XBMC +* http://www.xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with XBMC; see the file COPYING. If not, see +* . +* +*/ + +#include "CurlFile.h" +#include "URL.h" + +namespace XFILE +{ + class CHTTPFile : public CCurlFile + { + public: + CHTTPFile(void); + virtual ~CHTTPFile(void); + virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false); + virtual int Write(const void* lpBuf, int64_t uiBufSize); + private: + bool m_openedforwrite; + CURL m_urlforwrite; + }; +} diff --git a/xbmc/filesystem/Makefile.in b/xbmc/filesystem/Makefile.in index 0ac0cac9b8e6a..8c337eb0e40b6 100644 --- a/xbmc/filesystem/Makefile.in +++ b/xbmc/filesystem/Makefile.in @@ -29,6 +29,7 @@ SRCS += HDHomeRunFile.cpp SRCS += HTSPDirectory.cpp SRCS += HTSPSession.cpp SRCS += HTTPDirectory.cpp +SRCS += HTTPFile.cpp SRCS += IDirectory.cpp SRCS += IFile.cpp SRCS += ImageFile.cpp