aboutsummaryrefslogtreecommitdiff
path: root/src/filesystem/CurlFile.h
blob: 3217b99466394ee5d94a68fdc5abad0ba77c8a6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#pragma once
/*
 *      Copyright (C) 2005-2013 Team XBMC
 *      http://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
 *  <http://www.gnu.org/licenses/>.
 *
 */

#include "IFile.h"
#include "utils/RingBuffer.h"
#include <map>
#include <string>
#include "utils/HttpHeader.h"

namespace XCURL
{
  typedef void CURL_HANDLE;
  typedef void CURLM;
  struct curl_slist;
}

namespace XFILE
{
  class CCurlFile : public IFile
  {
    public:
      typedef enum
      {
        PROXY_HTTP = 0,
        PROXY_SOCKS4,
        PROXY_SOCKS4A,
        PROXY_SOCKS5,
        PROXY_SOCKS5_REMOTE,
      } ProxyType;
    
      CCurlFile();
      virtual ~CCurlFile();
      virtual bool Open(const CURL& url);
      virtual bool OpenForWrite(const CURL& url, bool bOverWrite = false);
      virtual bool Exists(const CURL& url);
      virtual int64_t  Seek(int64_t iFilePosition, int iWhence=SEEK_SET);
      virtual int64_t GetPosition();
      virtual int64_t  GetLength();
      virtual int  Stat(const CURL& url, struct __stat64* buffer);
      virtual void Close();
      virtual bool ReadString(char *szLine, int iLineLength)     { return m_state->ReadString(szLine, iLineLength); }
      virtual ssize_t Read(void* lpBuf, size_t uiBufSize)        { return m_state->Read(lpBuf, uiBufSize); }
      virtual ssize_t Write(const void* lpBuf, size_t uiBufSize);
      virtual std::string GetMimeType()                          { return m_state->m_httpheader.GetMimeType(); }
      virtual std::string GetContent()                           { return m_state->m_httpheader.GetValue("content-type"); }
      virtual int IoControl(EIoControl request, void* param);
      virtual std::string GetContentCharset(void)                { return GetServerReportedCharset(); }

      bool Post(const std::string& strURL, const std::string& strPostData, std::string& strHTML);
      bool Get(const std::string& strURL, std::string& strHTML);
      bool ReadData(std::string& strHTML);
      bool Download(const std::string& strURL, const std::string& strFileName, LPDWORD pdwSize = NULL);
      bool IsInternet();
      void Cancel();
      void Reset();
      void SetUserAgent(const std::string& sUserAgent)           { m_userAgent = sUserAgent; }
      void SetProxy(const std::string &proxy)                    { m_proxy = proxy; }
      void SetProxyUserPass(const std::string &proxyuserpass)    { m_proxyuserpass = proxyuserpass; }
      void SetProxyType(ProxyType proxytype)                     { m_proxytype = proxytype; }
      void SetStreamProxy(const std::string &proxy, ProxyType type);
      void SetCustomRequest(const std::string &request)          { m_customrequest = request; }
      void UseOldHttpVersion(bool bUse)                          { m_useOldHttpVersion = bUse; }
      void SetContentEncoding(const std::string& encoding)       { m_contentencoding = encoding; }
      void SetAcceptCharset(const std::string& charset)          { m_acceptCharset = charset; }
      void SetTimeout(int connecttimeout)                        { m_connecttimeout = connecttimeout; }
      void SetLowSpeedTime(int lowspeedtime)                     { m_lowspeedtime = lowspeedtime; }
      void SetPostData(const std::string& postdata)              { m_postdata = postdata; }
      void SetReferer(const std::string& referer)                { m_referer = referer; }
      void SetCookie(const std::string& cookie)                  { m_cookie = cookie; }
      void SetMimeType(std::string mimetype)                     { SetRequestHeader("Content-Type", mimetype); }
      void SetRequestHeader(const std::string& header, const std::string& value);
      void SetRequestHeader(const std::string& header, long value);

      void ClearRequestHeaders();
      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);
      static bool GetMimeType(const CURL &url, std::string &content, const std::string &useragent="");
      static bool GetContentType(const CURL &url, std::string &content, const std::string &useragent = "");

      /* static function that will get cookies stored by CURL in RFC 2109 format */
      static bool GetCookies(const CURL &url, std::string &cookies);

      class CReadState
      {
      public:
          CReadState();
          ~CReadState();
          XCURL::CURL_HANDLE*    m_easyHandle;
          XCURL::CURLM*          m_multiHandle;

          CRingBuffer     m_buffer;           // our ringhold buffer
          unsigned int    m_bufferSize;

          char *          m_overflowBuffer;   // in the rare case we would overflow the above buffer
          unsigned int    m_overflowSize;     // size of the overflow buffer
          int             m_stillRunning;     // Is background url fetch still in progress
          bool            m_cancelled;
          int64_t         m_fileSize;
          int64_t         m_filePos;
          bool            m_bFirstLoop;
          bool            m_isPaused;
          bool            m_sendRange;

          char*           m_readBuffer;

          /* returned http header */
          CHttpHeader m_httpheader;
          bool        IsHeaderDone(void)
          { return m_httpheader.IsHeaderDone(); }

          struct XCURL::curl_slist* m_curlHeaderList;
          struct XCURL::curl_slist* m_curlAliasList;

          size_t ReadCallback(char *buffer, size_t size, size_t nitems);
          size_t WriteCallback(char *buffer, size_t size, size_t nitems);
          size_t HeaderCallback(void *ptr, size_t size, size_t nmemb);

          bool         Seek(int64_t pos);
          unsigned int Read(void* lpBuf, size_t uiBufSize);
          bool         ReadString(char *szLine, int iLineLength);
          bool         FillBuffer(unsigned int want);
          void         SetReadBuffer(const void* lpBuf, int64_t uiBufSize);

          void         SetResume(void);
          long         Connect(unsigned int size);
          void         Disconnect();
      };

    protected:
      void ParseAndCorrectUrl(CURL &url);
      void SetCommonOptions(CReadState* state);
      void SetRequestHeaders(CReadState* state);
      void SetCorrectHeaders(CReadState* state);
      bool Service(const std::string& strURL, std::string& strHTML);

    protected:
      CReadState*     m_state;
      CReadState*     m_oldState;
      unsigned int    m_bufferSize;
      int64_t         m_writeOffset;

      std::string     m_url;
      std::string     m_userAgent;
      std::string     m_proxy;
      std::string     m_proxyuserpass;
      ProxyType       m_proxytype;
      std::string     m_customrequest;
      std::string     m_contentencoding;
      std::string     m_acceptCharset;
      std::string     m_ftpauth;
      std::string     m_ftpport;
      std::string     m_binary;
      std::string     m_postdata;
      std::string     m_referer;
      std::string     m_cookie;
      std::string     m_username;
      std::string     m_password;
      std::string     m_httpauth;
      std::string     m_cipherlist;
      bool            m_ftppasvip;
      int             m_connecttimeout;
      int             m_lowspeedtime;
      bool            m_opened;
      bool            m_forWrite;
      bool            m_inError;
      bool            m_useOldHttpVersion;
      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
      unsigned int    m_overflowSize;     // size of the overflow buffer

      int             m_stillRunning;     // Is background url fetch still in progress?

      typedef std::map<std::string, std::string> MAPHTTPHEADERS;
      MAPHTTPHEADERS m_requestheaders;

      long            m_httpresponse;
  };
}