Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: Common Portability Library
5 : * Purpose: Function wrapper for libcurl HTTP access.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2006, Frank Warmerdam
10 : * Copyright (c) 2009, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #ifndef CPL_HTTP_H_INCLUDED
16 : #define CPL_HTTP_H_INCLUDED
17 :
18 : #include "cpl_conv.h"
19 : #include "cpl_string.h"
20 : #include "cpl_progress.h"
21 : #include "cpl_vsi.h"
22 :
23 : /**
24 : * \file cpl_http.h
25 : *
26 : * Interface for downloading HTTP, FTP documents
27 : */
28 :
29 : /*! @cond Doxygen_Suppress */
30 : #ifndef CPL_HTTP_MAX_RETRY
31 : #define CPL_HTTP_MAX_RETRY 0
32 : #endif
33 :
34 : #ifndef CPL_HTTP_RETRY_DELAY
35 : #define CPL_HTTP_RETRY_DELAY 30.0
36 : #endif
37 : /*! @endcond */
38 :
39 : CPL_C_START
40 :
41 : /*! Describe a part of a multipart message */
42 : typedef struct
43 : {
44 : /*! NULL terminated array of headers */ char **papszHeaders;
45 :
46 : /*! Buffer with data of the part */ GByte *pabyData;
47 : /*! Buffer length */ int nDataLen;
48 : } CPLMimePart;
49 :
50 : /*! Describe the result of a CPLHTTPFetch() call */
51 : typedef struct
52 : {
53 : /*! cURL error code : 0=success, non-zero if request failed */
54 : int nStatus;
55 :
56 : /*! Content-Type of the response */
57 : char *pszContentType;
58 :
59 : /*! Error message from curl, or NULL */
60 : char *pszErrBuf;
61 :
62 : /*! Length of the pabyData buffer */
63 : int nDataLen;
64 : /*! Allocated size of the pabyData buffer */
65 : int nDataAlloc;
66 :
67 : /*! Buffer with downloaded data */
68 : GByte *pabyData;
69 :
70 : /*! Headers returned */
71 : char **papszHeaders;
72 :
73 : /*! Number of parts in a multipart message */
74 : int nMimePartCount;
75 :
76 : /*! Array of parts (resolved by CPLHTTPParseMultipartMime()) */
77 : CPLMimePart *pasMimePart;
78 :
79 : } CPLHTTPResult;
80 :
81 : /*! @cond Doxygen_Suppress */
82 : typedef size_t (*CPLHTTPFetchWriteFunc)(void *pBuffer, size_t nSize,
83 : size_t nMemb, void *pWriteArg);
84 : /*! @endcond */
85 :
86 : int CPL_DLL CPLHTTPEnabled(void);
87 : CPLHTTPResult CPL_DLL *CPLHTTPFetch(const char *pszURL,
88 : CSLConstList papszOptions);
89 : CPLHTTPResult CPL_DLL *
90 : CPLHTTPFetchEx(const char *pszURL, CSLConstList papszOptions,
91 : GDALProgressFunc pfnProgress, void *pProgressArg,
92 : CPLHTTPFetchWriteFunc pfnWrite, void *pWriteArg);
93 : CPLHTTPResult CPL_DLL **CPLHTTPMultiFetch(const char *const *papszURL,
94 : int nURLCount, int nMaxSimultaneous,
95 : CSLConstList papszOptions);
96 :
97 : void CPL_DLL CPLHTTPCleanup(void);
98 : void CPL_DLL CPLHTTPDestroyResult(CPLHTTPResult *psResult);
99 : void CPL_DLL CPLHTTPDestroyMultiResult(CPLHTTPResult **papsResults, int nCount);
100 : int CPL_DLL CPLHTTPParseMultipartMime(CPLHTTPResult *psResult);
101 :
102 : void CPL_DLL CPLHTTPSetDefaultUserAgent(const char *pszUserAgent);
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* To install an alternate network layer to the default Curl one */
106 : /* -------------------------------------------------------------------- */
107 : /** Callback function to process network requests.
108 : *
109 : * If CLOSE_PERSISTENT is found in papszOptions, no network request should be
110 : * issued, but a dummy non-null CPLHTTPResult* should be returned by the
111 : * callback.
112 : *
113 : * Its first arguments are the same as CPLHTTPFetchEx()
114 : * @param pszURL See CPLHTTPFetchEx()
115 : * @param papszOptions See CPLHTTPFetchEx()
116 : * @param pfnProgress See CPLHTTPFetchEx()
117 : * @param pProgressArg See CPLHTTPFetchEx()
118 : * @param pfnWrite See CPLHTTPFetchEx()
119 : * @param pWriteArg See CPLHTTPFetchEx()
120 : * @param pUserData user data value that was passed during
121 : * CPLHTTPPushFetchCallback()
122 : * @return nullptr if the request cannot be processed, in which case the
123 : * previous handler will be used.
124 : */
125 : typedef CPLHTTPResult *(*CPLHTTPFetchCallbackFunc)(
126 : const char *pszURL, CSLConstList papszOptions, GDALProgressFunc pfnProgress,
127 : void *pProgressArg, CPLHTTPFetchWriteFunc pfnWrite, void *pWriteArg,
128 : void *pUserData);
129 :
130 : void CPL_DLL CPLHTTPSetFetchCallback(CPLHTTPFetchCallbackFunc pFunc,
131 : void *pUserData);
132 :
133 : int CPL_DLL CPLHTTPPushFetchCallback(CPLHTTPFetchCallbackFunc pFunc,
134 : void *pUserData);
135 : int CPL_DLL CPLHTTPPopFetchCallback(void);
136 :
137 : /* -------------------------------------------------------------------- */
138 : /* The following is related to OAuth2 authorization around */
139 : /* google services like fusion tables, and potentially others */
140 : /* in the future. Code in cpl_google_oauth2.cpp. */
141 : /* */
142 : /* These services are built on CPL HTTP services. */
143 : /* -------------------------------------------------------------------- */
144 :
145 : char CPL_DLL *GOA2GetAuthorizationURL(const char *pszScope);
146 : char CPL_DLL *GOA2GetRefreshToken(const char *pszAuthToken,
147 : const char *pszScope);
148 : char CPL_DLL *GOA2GetAccessToken(const char *pszRefreshToken,
149 : const char *pszScope);
150 :
151 : char CPL_DLL **GOA2GetAccessTokenFromServiceAccount(
152 : const char *pszPrivateKey, const char *pszClientEmail, const char *pszScope,
153 : CSLConstList papszAdditionalClaims, CSLConstList papszOptions);
154 :
155 : char CPL_DLL **GOA2GetAccessTokenFromCloudEngineVM(CSLConstList papszOptions);
156 :
157 : CPL_C_END
158 :
159 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
160 : /*! @cond Doxygen_Suppress */
161 : // Not sure if this belong here, used in cpl_http.cpp, cpl_vsil_curl.cpp and
162 : // frmts/wms/gdalhttp.cpp
163 : void CPL_DLL *CPLHTTPSetOptions(void *pcurl, const char *pszURL,
164 : const char *const *papszOptions);
165 : char **CPLHTTPGetOptionsFromEnv(const char *pszFilename);
166 :
167 : /** Stores HTTP retry parameters */
168 : struct CPLHTTPRetryParameters
169 : {
170 : int nMaxRetry = CPL_HTTP_MAX_RETRY;
171 : double dfInitialDelay = CPL_HTTP_RETRY_DELAY;
172 : std::string osRetryCodes{};
173 :
174 : CPLHTTPRetryParameters() = default;
175 : explicit CPLHTTPRetryParameters(const CPLStringList &aosHTTPOptions);
176 : };
177 :
178 : /** HTTP retry context */
179 : class CPLHTTPRetryContext
180 : {
181 : public:
182 : explicit CPLHTTPRetryContext(const CPLHTTPRetryParameters &oParams);
183 :
184 : bool CanRetry(int response_code, const char *pszErrBuf,
185 : const char *pszCurlError);
186 : bool CanRetry();
187 :
188 : /** Returns the delay to apply. Only valid after a successful call to CanRetry() */
189 : double GetCurrentDelay() const;
190 :
191 : /** Reset retry counter. */
192 0 : void ResetCounter()
193 : {
194 0 : m_nRetryCount = 0;
195 0 : }
196 :
197 : private:
198 : CPLHTTPRetryParameters m_oParameters{};
199 : int m_nRetryCount = 0;
200 : double m_dfCurDelay = 0.0;
201 : double m_dfNextDelay = 0.0;
202 : };
203 :
204 : void CPL_DLL *CPLHTTPIgnoreSigPipe();
205 : void CPL_DLL CPLHTTPRestoreSigPipeHandler(void *old_handler);
206 : bool CPLMultiPerformWait(void *hCurlMultiHandle, int &repeats);
207 : /*! @endcond */
208 :
209 : bool CPL_DLL CPLIsMachinePotentiallyGCEInstance();
210 : bool CPLIsMachineForSureGCEInstance();
211 :
212 : /** Manager of Google OAuth2 authentication.
213 : *
214 : * This class handles different authentication methods and handles renewal
215 : * of access token.
216 : *
217 : * @since GDAL 2.3
218 : */
219 74 : class GOA2Manager
220 : {
221 : public:
222 : GOA2Manager();
223 :
224 : /** Authentication method */
225 : typedef enum
226 : {
227 : NONE,
228 : GCE,
229 : ACCESS_TOKEN_FROM_REFRESH,
230 : SERVICE_ACCOUNT
231 : } AuthMethod;
232 :
233 : bool SetAuthFromGCE(CSLConstList papszOptions);
234 : bool SetAuthFromRefreshToken(const char *pszRefreshToken,
235 : const char *pszClientId,
236 : const char *pszClientSecret,
237 : CSLConstList papszOptions);
238 : bool SetAuthFromServiceAccount(const char *pszPrivateKey,
239 : const char *pszClientEmail,
240 : const char *pszScope,
241 : CSLConstList papszAdditionalClaims,
242 : CSLConstList papszOptions);
243 :
244 : /** Returns the authentication method. */
245 55 : AuthMethod GetAuthMethod() const
246 : {
247 55 : return m_eMethod;
248 : }
249 :
250 : const char *GetBearer() const;
251 :
252 : /** Returns private key for SERVICE_ACCOUNT method */
253 1 : const CPLString &GetPrivateKey() const
254 : {
255 1 : return m_osPrivateKey;
256 : }
257 :
258 : /** Returns client email for SERVICE_ACCOUNT method */
259 1 : const CPLString &GetClientEmail() const
260 : {
261 1 : return m_osClientEmail;
262 : }
263 :
264 : /** Returns a key that can be used to uniquely identify the instance
265 : * parameters (excluding bearer)
266 : */
267 19 : std::string GetKey() const
268 : {
269 19 : std::string osKey(std::to_string(static_cast<int>(m_eMethod))
270 19 : .append(",client-id=")
271 19 : .append(m_osClientId)
272 19 : .append(",client-secret=")
273 19 : .append(m_osClientSecret)
274 19 : .append(",refresh-token=")
275 19 : .append(m_osRefreshToken)
276 19 : .append(",private-key=")
277 19 : .append(m_osPrivateKey)
278 19 : .append(",client-email=")
279 19 : .append(m_osClientEmail)
280 19 : .append(",scope=")
281 19 : .append(m_osScope));
282 19 : osKey.append(",additional-claims=");
283 19 : for (const auto *pszOption : m_aosAdditionalClaims)
284 : {
285 0 : osKey.append(pszOption);
286 0 : osKey.append("+");
287 : }
288 19 : osKey.append(",options=");
289 19 : for (const auto *pszOption : m_aosOptions)
290 : {
291 0 : osKey.append(pszOption);
292 0 : osKey.append("+");
293 : }
294 19 : return osKey;
295 : }
296 :
297 : private:
298 : mutable CPLString m_osCurrentBearer{};
299 : mutable time_t m_nExpirationTime = 0;
300 :
301 : AuthMethod m_eMethod = NONE;
302 :
303 : // for ACCESS_TOKEN_FROM_REFRESH
304 : CPLString m_osClientId{};
305 : CPLString m_osClientSecret{};
306 : CPLString m_osRefreshToken{};
307 :
308 : // for SERVICE_ACCOUNT
309 : CPLString m_osPrivateKey{};
310 : CPLString m_osClientEmail{};
311 : CPLString m_osScope{};
312 : CPLStringList m_aosAdditionalClaims{};
313 :
314 : CPLStringList m_aosOptions{};
315 : };
316 :
317 : #endif // __cplusplus
318 :
319 : #endif /* ndef CPL_HTTP_H_INCLUDED */
|