[Curl] Bug fix after r219606
[WebKit-https.git] / Source / WebCore / platform / network / curl / CurlContext.h
1 /*
2  * Copyright (C) 2013 Apple Inc.  All rights reserved.
3  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "URL.h"
30
31 #include <wtf/Lock.h>
32 #include <wtf/NeverDestroyed.h>
33 #include <wtf/Noncopyable.h>
34 #include <wtf/Threading.h>
35
36 #if OS(WINDOWS)
37 #include <windows.h>
38 #include <winsock2.h>
39 #endif
40
41 #include <curl/curl.h>
42
43 namespace WebCore {
44
45 enum class CurlProxyType {
46     Invalid = -1,
47     HTTP = CURLPROXY_HTTP,
48     Socks4 = CURLPROXY_SOCKS4,
49     Socks4A = CURLPROXY_SOCKS4A,
50     Socks5 = CURLPROXY_SOCKS5,
51     Socks5Hostname = CURLPROXY_SOCKS5_HOSTNAME
52 };
53
54 // CurlGlobal --------------------------------------------
55 // to make the initialization of libcurl happen before other initialization of CurlContext
56
57 class CurlGlobal {
58 protected:
59     CurlGlobal()
60     {
61         curl_global_init(CURL_GLOBAL_ALL);
62     }
63     
64     virtual ~CurlGlobal()
65     {
66         curl_global_cleanup();
67     }
68 };
69
70 // CurlShareHandle --------------------------------------------
71
72 class CurlShareHandle {
73     WTF_MAKE_NONCOPYABLE(CurlShareHandle);
74
75 public:
76     CurlShareHandle();
77     ~CurlShareHandle();
78
79     CURLSH* handle() const { return m_shareHandle; }
80
81 private:
82     static void lockCallback(CURL*, curl_lock_data, curl_lock_access, void*);
83     static void unlockCallback(CURL*, curl_lock_data, void*);
84     static Lock* mutexFor(curl_lock_data);
85
86     CURLSH* m_shareHandle { nullptr };
87 };
88
89 // CurlContext --------------------------------------------
90
91 class CurlContext : public CurlGlobal {
92     WTF_MAKE_NONCOPYABLE(CurlContext);
93
94 public:
95     struct ProxyInfo {
96         String host;
97         unsigned long port;
98         CurlProxyType type { CurlProxyType::Invalid };
99         String username;
100         String password;
101
102         const String url() const;
103     };
104
105     static const char* const errorDomain;
106
107     static CurlContext& singleton()
108     {
109         static CurlContext shared;
110         return shared;
111     }
112
113     virtual ~CurlContext();
114
115     const CurlShareHandle& shareHandle() { return m_shareHandle; }
116
117     // Cookie
118     const char* getCookieJarFileName() const { return m_cookieJarFileName.data(); }
119     void setCookieJarFileName(const char* cookieJarFileName) { m_cookieJarFileName = CString(cookieJarFileName); }
120
121     // Certificate
122     const char* getCertificatePath() const { return m_certificatePath.data(); }
123     bool shouldIgnoreSSLErrors() const { return m_ignoreSSLErrors; }
124
125     // Proxy
126     const ProxyInfo& proxyInfo() const { return m_proxy; }
127     void setProxyInfo(const ProxyInfo& info) { m_proxy = info;  }
128     void setProxyInfo(const String& host = emptyString(), unsigned long port = 0, CurlProxyType = CurlProxyType::HTTP, const String& username = emptyString(), const String& password = emptyString());
129
130 #ifndef NDEBUG
131     FILE* getLogFile() const { return m_logFile; }
132     bool isVerbose() const { return m_verbose; }
133 #endif
134
135 private:
136     ProxyInfo m_proxy;
137     CString m_cookieJarFileName;
138     CString m_certificatePath;
139     CurlShareHandle m_shareHandle;
140     bool m_ignoreSSLErrors { false };
141
142     CurlContext();
143     void initCookieSession();
144
145
146 #ifndef NDEBUG
147     FILE* m_logFile { nullptr };
148     bool m_verbose { false };
149 #endif
150 };
151
152 // CurlMultiHandle --------------------------------------------
153
154 class CurlMultiHandle {
155     WTF_MAKE_NONCOPYABLE(CurlMultiHandle);
156
157 public:
158     CurlMultiHandle();
159     ~CurlMultiHandle();
160
161     CURLMcode addHandle(CURL*);
162     CURLMcode removeHandle(CURL*);
163
164     CURLMcode getFdSet(fd_set&, fd_set&, fd_set&, int&);
165     CURLMcode perform(int&);
166     CURLMsg* readInfo(int&);
167
168 private:
169     CURLM* m_multiHandle { nullptr };
170 };
171
172 // CurlSList -------------------------------------------------
173
174 class CurlSList {
175 public:
176     CurlSList() { }
177     ~CurlSList() { clear(); }
178
179     operator struct curl_slist** () { return &m_list; }
180
181     const struct curl_slist* head() const { return m_list; }
182     bool isEmpty() const { return !m_list; }
183     void clear()
184     {
185         if (m_list) {
186             curl_slist_free_all(m_list);
187             m_list = nullptr;
188         }
189     }
190
191     void append(const char* str) { m_list = curl_slist_append(m_list, str); }
192     void append(const String& str) { append(str.latin1().data()); }
193
194 private:
195     struct curl_slist* m_list { nullptr };
196 };
197
198 // CurlHandle -------------------------------------------------
199
200 class HTTPHeaderMap;
201
202 class CurlHandle {
203     WTF_MAKE_NONCOPYABLE(CurlHandle);
204
205 public:
206     enum VerifyPeer {
207         VerifyPeerDisable = 0L,
208         VerifyPeerEnable = 1L
209     };
210
211     enum VerifyHost {
212         VerifyHostLooseNameCheck = 0,
213         VerifyHostStrictNameCheck = 2
214     };
215
216     CurlHandle();
217     ~CurlHandle();
218
219     CURL* handle() const { return m_handle; }
220
221     CURLcode perform();
222     CURLcode pause(int);
223
224     CURLcode errorCode() const { return m_errorCode; }
225     void setErrorCode(CURLcode errorCode) { m_errorCode = errorCode; }
226
227     const String errorDescription() const;
228
229     void enableShareHandle();
230
231     void* privateData() const { return m_privateData; }
232     void setPrivateData(void* userData) { m_privateData = userData; }
233
234     void setUrl(const String&);
235     const char* url() const { return m_url; }
236
237     void appendRequestHeaders(const HTTPHeaderMap&);
238     void appendRequestHeader(const String&, const String&);
239     void appendRequestHeader(const String&);
240     void enableRequestHeaders();
241
242     void enableHttpGetRequest();
243     void enableHttpHeadRequest();
244     void enableHttpPostRequest();
245     void setPostFields(const char*, long);
246     void setPostFieldLarge(curl_off_t);
247     void enableHttpPutRequest();
248     void setInFileSizeLarge(curl_off_t);
249     void setHttpCustomRequest(const String&);
250
251     void enableAcceptEncoding();
252     void enableAllowedProtocols();
253
254     void enableFollowLocation();
255     void enableAutoReferer();
256
257     void enableHttpAuthentication(long);
258     void setHttpAuthUserPass(const String&, const String&);
259
260     void enableCAInfoIfExists();
261     void setSslVerifyPeer(VerifyPeer);
262     void setSslVerifyHost(VerifyHost);
263     void setSslCert(const char*);
264     void setSslCertType(const char*);
265     void setSslKeyPassword(const char*);
266
267     void enableCookieJarIfExists();
268     void setCookieList(const char*);
269     void fetchCookieList(CurlSList &cookies) const;
270
271     void enableProxyIfExists();
272
273     void enableTimeout();
274
275     // Callback function
276     void setHeaderCallbackFunction(curl_write_callback, void*);
277     void setWriteCallbackFunction(curl_write_callback, void*);
278     void setReadCallbackFunction(curl_read_callback, void*);
279     void setSslCtxCallbackFunction(curl_ssl_ctx_callback, void*);
280
281     // Status
282     URL getEffectiveURL() const;
283     CURLcode getPrimaryPort(long&);
284     CURLcode getResponseCode(long&);
285     CURLcode getContentLenghtDownload(long long&);
286     CURLcode getHttpAuthAvail(long&);
287     CURLcode getTimes(double&, double&, double&, double&);
288
289     static long long maxCurlOffT();
290
291 #ifndef NDEBUG
292     void enableVerboseIfUsed();
293     void enableStdErrIfUsed();
294 #endif
295
296 private:
297     void clearUrl();
298
299     static int expectedSizeOfCurlOffT();
300
301     CURL* m_handle { nullptr };
302     char m_errorBuffer[CURL_ERROR_SIZE] { };
303     CURLcode m_errorCode;
304
305     char* m_url { nullptr };
306     void* m_privateData { nullptr };
307     CurlSList m_requestHeaders;
308 };
309
310 }