/src/gdal/port/cpl_http.h
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 0  | #define CPL_HTTP_MAX_RETRY 0  | 
31  |  | #endif  | 
32  |  |  | 
33  |  | #ifndef CPL_HTTP_RETRY_DELAY  | 
34  | 0  | #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  |  |     void ResetCounter()  | 
192  | 0  |     { | 
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  |  | 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  |  |     AuthMethod GetAuthMethod() const  | 
245  | 0  |     { | 
246  | 0  |         return m_eMethod;  | 
247  | 0  |     }  | 
248  |  |  | 
249  |  |     const char *GetBearer() const;  | 
250  |  |  | 
251  |  |     /** Returns private key for SERVICE_ACCOUNT method */  | 
252  |  |     const CPLString &GetPrivateKey() const  | 
253  | 0  |     { | 
254  | 0  |         return m_osPrivateKey;  | 
255  | 0  |     }  | 
256  |  |  | 
257  |  |     /** Returns client email for SERVICE_ACCOUNT method */  | 
258  |  |     const CPLString &GetClientEmail() const  | 
259  | 0  |     { | 
260  | 0  |         return m_osClientEmail;  | 
261  | 0  |     }  | 
262  |  |  | 
263  |  |     /** Returns a key that can be used to uniquely identify the instance  | 
264  |  |      * parameters (excluding bearer)  | 
265  |  |      */  | 
266  |  |     std::string GetKey() const  | 
267  | 0  |     { | 
268  | 0  |         std::string osKey(std::to_string(static_cast<int>(m_eMethod))  | 
269  | 0  |                               .append(",client-id=") | 
270  | 0  |                               .append(m_osClientId)  | 
271  | 0  |                               .append(",client-secret=") | 
272  | 0  |                               .append(m_osClientSecret)  | 
273  | 0  |                               .append(",refresh-token=") | 
274  | 0  |                               .append(m_osRefreshToken)  | 
275  | 0  |                               .append(",private-key=") | 
276  | 0  |                               .append(m_osPrivateKey)  | 
277  | 0  |                               .append(",client-email=") | 
278  | 0  |                               .append(m_osClientEmail)  | 
279  | 0  |                               .append(",scope=") | 
280  | 0  |                               .append(m_osScope));  | 
281  | 0  |         osKey.append(",additional-claims="); | 
282  | 0  |         for (const auto *pszOption : m_aosAdditionalClaims)  | 
283  | 0  |         { | 
284  | 0  |             osKey.append(pszOption);  | 
285  | 0  |             osKey.append("+"); | 
286  | 0  |         }  | 
287  | 0  |         osKey.append(",options="); | 
288  | 0  |         for (const auto *pszOption : m_aosOptions)  | 
289  | 0  |         { | 
290  | 0  |             osKey.append(pszOption);  | 
291  | 0  |             osKey.append("+"); | 
292  | 0  |         }  | 
293  | 0  |         return osKey;  | 
294  | 0  |     }  | 
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 */  |