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