1 /* 2 * Copyright (C) 2005-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 #include "IFile.h" 12 #include "utils/HttpHeader.h" 13 #include "utils/RingBuffer.h" 14 15 #include <map> 16 #include <string> 17 18 typedef void CURL_HANDLE; 19 typedef void CURLM; 20 struct curl_slist; 21 22 namespace XFILE 23 { 24 class CCurlFile : public IFile 25 { 26 private: 27 typedef enum 28 { 29 PROXY_HTTP = 0, 30 PROXY_SOCKS4, 31 PROXY_SOCKS4A, 32 PROXY_SOCKS5, 33 PROXY_SOCKS5_REMOTE, 34 } ProxyType; 35 36 public: 37 CCurlFile(); 38 ~CCurlFile() override; 39 bool Open(const CURL& url) override; 40 bool OpenForWrite(const CURL& url, bool bOverWrite = false) override; 41 bool ReOpen(const CURL& url) override; 42 bool Exists(const CURL& url) override; 43 int64_t Seek(int64_t iFilePosition, int iWhence=SEEK_SET) override; 44 int64_t GetPosition() override; 45 int64_t GetLength() override; 46 int Stat(const CURL& url, struct __stat64* buffer) override; 47 void Close() override; ReadString(char * szLine,int iLineLength)48 bool ReadString(char *szLine, int iLineLength) override { return m_state->ReadString(szLine, iLineLength); } Read(void * lpBuf,size_t uiBufSize)49 ssize_t Read(void* lpBuf, size_t uiBufSize) override { return m_state->Read(lpBuf, uiBufSize); } 50 ssize_t Write(const void* lpBuf, size_t uiBufSize) override; 51 const std::string GetProperty(XFILE::FileProperty type, const std::string &name = "") const override; 52 const std::vector<std::string> GetPropertyValues(XFILE::FileProperty type, const std::string &name = "") const override; 53 int IoControl(EIoControl request, void* param) override; 54 double GetDownloadSpeed() override; 55 56 bool Post(const std::string& strURL, const std::string& strPostData, std::string& strHTML); 57 bool Get(const std::string& strURL, std::string& strHTML); 58 bool ReadData(std::string& strHTML); 59 bool Download(const std::string& strURL, const std::string& strFileName, unsigned int* pdwSize = NULL); 60 bool IsInternet(); 61 void Cancel(); 62 void Reset(); SetUserAgent(const std::string & sUserAgent)63 void SetUserAgent(const std::string& sUserAgent) { m_userAgent = sUserAgent; } 64 void SetProxy(const std::string &type, const std::string &host, uint16_t port, 65 const std::string &user, const std::string &password); SetCustomRequest(const std::string & request)66 void SetCustomRequest(const std::string &request) { m_customrequest = request; } SetAcceptEncoding(const std::string & encoding)67 void SetAcceptEncoding(const std::string& encoding) { m_acceptencoding = encoding; } SetAcceptCharset(const std::string & charset)68 void SetAcceptCharset(const std::string& charset) { m_acceptCharset = charset; } SetTimeout(int connecttimeout)69 void SetTimeout(int connecttimeout) { m_connecttimeout = connecttimeout; } SetLowSpeedTime(int lowspeedtime)70 void SetLowSpeedTime(int lowspeedtime) { m_lowspeedtime = lowspeedtime; } SetPostData(const std::string & postdata)71 void SetPostData(const std::string& postdata) { m_postdata = postdata; } SetReferer(const std::string & referer)72 void SetReferer(const std::string& referer) { m_referer = referer; } SetCookie(const std::string & cookie)73 void SetCookie(const std::string& cookie) { m_cookie = cookie; } SetMimeType(const std::string & mimetype)74 void SetMimeType(const std::string& mimetype) { SetRequestHeader("Content-Type", mimetype); } 75 void SetRequestHeader(const std::string& header, const std::string& value); 76 void SetRequestHeader(const std::string& header, long value); 77 78 void ClearRequestHeaders(); 79 void SetBufferSize(unsigned int size); 80 GetHttpHeader()81 const CHttpHeader& GetHttpHeader() const { return m_state->m_httpheader; } 82 std::string GetURL(void); 83 std::string GetRedirectURL(); 84 85 /* static function that will get content type of a file */ 86 static bool GetHttpHeader(const CURL &url, CHttpHeader &headers); 87 static bool GetMimeType(const CURL &url, std::string &content, const std::string &useragent=""); 88 static bool GetContentType(const CURL &url, std::string &content, const std::string &useragent = ""); 89 90 /* static function that will get cookies stored by CURL in RFC 2109 format */ 91 static bool GetCookies(const CURL &url, std::string &cookies); 92 93 class CReadState 94 { 95 public: 96 CReadState(); 97 ~CReadState(); 98 CURL_HANDLE* m_easyHandle; 99 CURLM* m_multiHandle; 100 101 CRingBuffer m_buffer; // our ringhold buffer 102 unsigned int m_bufferSize; 103 104 char* m_overflowBuffer; // in the rare case we would overflow the above buffer 105 unsigned int m_overflowSize; // size of the overflow buffer 106 int m_stillRunning; // Is background url fetch still in progress 107 bool m_cancelled; 108 int64_t m_fileSize; 109 int64_t m_filePos; 110 bool m_bFirstLoop; 111 bool m_isPaused; 112 bool m_sendRange; 113 bool m_bLastError; 114 bool m_bRetry; 115 116 char* m_readBuffer; 117 118 /* returned http header */ 119 CHttpHeader m_httpheader; IsHeaderDone(void)120 bool IsHeaderDone(void) { return m_httpheader.IsHeaderDone(); } 121 122 curl_slist* m_curlHeaderList; 123 curl_slist* m_curlAliasList; 124 125 size_t ReadCallback(char *buffer, size_t size, size_t nitems); 126 size_t WriteCallback(char *buffer, size_t size, size_t nitems); 127 size_t HeaderCallback(void *ptr, size_t size, size_t nmemb); 128 129 bool Seek(int64_t pos); 130 ssize_t Read(void* lpBuf, size_t uiBufSize); 131 bool ReadString(char *szLine, int iLineLength); 132 int8_t FillBuffer(unsigned int want); 133 void SetReadBuffer(const void* lpBuf, int64_t uiBufSize); 134 135 void SetResume(void); 136 long Connect(unsigned int size); 137 void Disconnect(); 138 }; 139 140 protected: 141 void ParseAndCorrectUrl(CURL &url); 142 void SetCommonOptions(CReadState* state, bool failOnError = true); 143 void SetRequestHeaders(CReadState* state); 144 void SetCorrectHeaders(CReadState* state); 145 bool Service(const std::string& strURL, std::string& strHTML); 146 std::string GetInfoString(int infoType); 147 148 protected: 149 CReadState* m_state; 150 CReadState* m_oldState; 151 unsigned int m_bufferSize; 152 int64_t m_writeOffset = 0; 153 154 std::string m_url; 155 std::string m_userAgent; 156 ProxyType m_proxytype = PROXY_HTTP; 157 std::string m_proxyhost; 158 uint16_t m_proxyport = 3128; 159 std::string m_proxyuser; 160 std::string m_proxypassword; 161 std::string m_customrequest; 162 std::string m_acceptencoding; 163 std::string m_acceptCharset; 164 std::string m_ftpauth; 165 std::string m_ftpport; 166 std::string m_binary; 167 std::string m_postdata; 168 std::string m_referer; 169 std::string m_cookie; 170 std::string m_username; 171 std::string m_password; 172 std::string m_httpauth; 173 std::string m_cipherlist; 174 bool m_ftppasvip; 175 int m_connecttimeout; 176 int m_redirectlimit; 177 int m_lowspeedtime; 178 bool m_opened; 179 bool m_forWrite; 180 bool m_inError; 181 bool m_seekable; 182 bool m_multisession; 183 bool m_skipshout; 184 bool m_postdataset; 185 bool m_allowRetry; 186 bool m_verifyPeer = true; 187 bool m_failOnError = true; 188 curl_slist* m_dnsCacheList = nullptr; 189 190 CRingBuffer m_buffer; // our ringhold buffer 191 char* m_overflowBuffer; // in the rare case we would overflow the above buffer 192 unsigned int m_overflowSize = 0; // size of the overflow buffer 193 194 int m_stillRunning; // Is background url fetch still in progress? 195 196 typedef std::map<std::string, std::string> MAPHTTPHEADERS; 197 MAPHTTPHEADERS m_requestheaders; 198 199 long m_httpresponse; 200 }; 201 } 202