curlite.hpp
Go to the documentation of this file.
1 /*
2  * curlite.hpp
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013-2014 Ivan Grynko
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  *
26  */
27 
28 #ifndef curlite_hpp_120129ad_36b2_4224_b790_d1658ce03bb4
29 #define curlite_hpp_120129ad_36b2_4224_b790_d1658ce03bb4
30 
31 #include <curl/curl.h>
32 #include <stdexcept>
33 #include <functional>
34 #include <memory>
35 #include <iostream>
36 #include <vector>
37 #include <string>
38 
39 // cURL version check
40 #if LIBCURL_VERSION_MAJOR < 7 || LIBCURL_VERSION_MINOR < 32
41  #error "This version of curlite is incompatible with your cURL version"
42 #endif
43 
44 namespace curlite
45 {
46  template <class FunctionPtr>
47  struct Handler { typedef std::function<typename std::remove_pointer<FunctionPtr>::type> type; };
48 
65 
66  /* Base class of all curlite exceptions
67  */
68 
69  struct Exception : std::runtime_error
70  {
71  Exception( char const *message )
72  : std::runtime_error( message )
73  { }
74  };
75 
76  /* The class implements easy interface of cURL
77  *
78  * Example:
79  * try {
80  * curlite::Easy easy;
81  * easy.set( CURLOPT_URL, "http://duckduckgo.com" );
82  * easy.set( CURLOPT_FOLLOWLOCATION, true );
83  *
84  * std::cout << easy;
85  * } catch( std::exception &e ) {
86  * std::err << e.what() << std::endl;
87  * }
88  */
89 
90  class Easy
91  {
92  struct Pimpl;
93  std::unique_ptr<Pimpl> _impl;
94 
95  Easy( Easy const &other );
96  void operator = ( Easy const &other );
97 
98  bool handleError( CURLcode code );
99 
100  public:
101  // Simplified handlers for most frequent cases
102  typedef std::function<bool (char *, size_t)> SimplifiedDataHandler;
103  typedef std::function<bool (curl_off_t, curl_off_t, curl_off_t, curl_off_t)> SimplifiedProgressHandler;
104 
105  Easy();
106  Easy( Easy &&other );
107  virtual ~Easy();
108 
109  Easy &operator = ( Easy &&other );
110 
111  /* Returns true if there was no error during last operation
112  * Equivalent of (error() == CURLE_OK)
113  */
114 
115  operator bool() const;
116 
117  /* Release the ownership of the managed CURL object if any.
118  *
119  * Returns pointer to the managed CURL object or nullptr.
120  */
121 
122  CURL *release();
123 
124  /* Returns pointer to the managed CURL object
125  */
126 
127  CURL* get() const;
128 
129  /* Set current exception mode.
130  * Pass true to throw exceptions on error, false otherwise.
131  */
132 
133  void setExceptionMode( bool throwExceptions );
134 
135  /* Returns true if exceptions are "on"
136  */
137 
138  bool exceptionMode() const;
139 
140  /* Returns last cURL error code
141  */
142 
143  CURLcode error() const;
144 
145  /* Returns a string describing last cURL error
146  */
147 
148  std::string errorString() const;
149 
150  /* Returns previously set pointer to user data
151  */
152 
153  void *userData() const;
154 
155  /* Set pointer to arbitrary user data, associated with the instance of Easy
156  */
157 
158  void setUserData( void *data );
159 
160  /* Set options for the cURL session
161  * See curl_easy_setopt() for details.
162  */
163 
164  template <class ValueType>
165  bool set( CURLoption opt, ValueType value );
166 
167  bool set( CURLoption key, int value );
168  bool set( CURLoption key, bool value );
169  bool set( CURLoption key, std::string const &value );
170 
171  /* Request internal information from cURL session
172  * See curl_easy_getinfo() for details.
173  */
174 
175  template <class ValueType>
176  ValueType getInfo( CURLINFO key, ValueType const &defaultValue = ValueType() );
177 
178  /* Reset all options of cURL session to their defaults.
179  */
180 
181  void reset();
182 
183  /* Pause/unpause a connection
184  * See curl_easy_pause() for details.
185  */
186 
187  bool pause( int bitmask );
188 
189  /* Perform a blocking file transfer.
190  */
191 
192  bool perform();
193 
194  /* Perform a blocking file upload from a stream
195  */
196 
197  bool operator << ( std::istream &stream );
198 
199  /* Perform a blocking file download to a stream
200  */
201 
202  bool operator >> ( std::ostream &stream );
203 
204  /* Returns url-encoded version of input string
205  */
206 
207  std::string escape( std::string const &url );
208 
209  /* Returns url-decoded version of input string
210  */
211 
212  std::string unescape( std::string const &url );
213 
214  /* Send arbitrary data over the established connection.
215  * Returns the number of bytes actually sent.
216  */
217 
218  size_t send( const char *buffer, size_t bufferSize );
219 
220  /* Receive raw data from the established connection.
221  * Returns the number of bytes actually received.
222  */
223 
224  size_t recv( char *buffer, size_t bufferSize );
225 
226  // set simplified handlers
227  void onRead_( SimplifiedDataHandler f );
228  void onWrite_( SimplifiedDataHandler f );
229  void onHeader_( SimplifiedDataHandler f );
230 
231  void onProgress_( SimplifiedProgressHandler f );
232 
233  // set usual "curl" handlers
234  void onRead( ReadHandler f = ReadHandler(), void *data = nullptr );
235  void onWrite( WriteHandler f = WriteHandler(), void *data = nullptr );
236  void onHeader( WriteHandler f = WriteHandler(), void *data = nullptr );
237 
238  void onIoctl( IoctlHandler f = IoctlHandler(), void *data = nullptr );
239  void onSeek( SeekHandler f = SeekHandler(), void *data = nullptr );
240  void onFnMatch( FnMatchHandler f = FnMatchHandler(), void *data = nullptr );
241 
242  void onProgress( ProgressHandler f = ProgressHandler(), void *data = nullptr );
243  void onXferInfo( XferInfoHandler f = XferInfoHandler(), void *data = nullptr );
244 
245  void onCloseSocket( CloseSocketHandler f = CloseSocketHandler(), void *data = nullptr );
246  void onOpenSocket( OpenSocketHandler f = OpenSocketHandler(), void *data = nullptr );
247  void onSockOpt( SockOptHandler f = SockOptHandler(), void *data = nullptr );
248 
249  void onChunkBegin( ChunkBeginHandler f = ChunkBeginHandler(), void *data = nullptr );
250  void onChunkEnd( ChunkEndHandler f = ChunkEndHandler(), void *data = nullptr );
251 
252  void onSslContext( SslContextHandler f = SslContextHandler(), void *data = nullptr );
253  void onDebug( DebugHandler f = DebugHandler(), void *data = nullptr );
254  };
255 
256 
257  // -- set() stuff
258  static const int kCurlOptTypeInterval = CURLOPTTYPE_OBJECTPOINT - CURLOPTTYPE_LONG;
259 
260  struct OptionInvalidCode { enum { value = -1 }; };
261  struct OptionNullPtrCode { enum { value = -2 }; };
262  struct OptionLongCode { enum { value = CURLOPTTYPE_LONG }; };
263  struct OptionOffsetCode { enum { value = CURLOPTTYPE_OFF_T }; };
264  struct OptionObjectPtrCode { enum { value = CURLOPTTYPE_OBJECTPOINT }; };
265  struct OptionFunctionPtrCode { enum { value = CURLOPTTYPE_FUNCTIONPOINT }; };
266 
267  template <class Type> struct OptionTypeCode : OptionInvalidCode { };
268  template <> struct OptionTypeCode<long> : OptionLongCode { };
269  template <> struct OptionTypeCode<void*> : OptionObjectPtrCode { };
270  template <> struct OptionTypeCode<char*> : OptionObjectPtrCode { };
271  template <> struct OptionTypeCode<const char*> : OptionObjectPtrCode { };
272  template <> struct OptionTypeCode<curl_slist*> : OptionObjectPtrCode { };
273  template <> struct OptionTypeCode<curl_httppost*> : OptionObjectPtrCode { };
274  template <> struct OptionTypeCode<FILE*> : OptionObjectPtrCode { };
275  template <> struct OptionTypeCode<curl_progress_callback> : OptionFunctionPtrCode { };
276  template <> struct OptionTypeCode<curl_xferinfo_callback> : OptionFunctionPtrCode { };
277  template <> struct OptionTypeCode<curl_write_callback> : OptionFunctionPtrCode { };
278  template <> struct OptionTypeCode<curl_chunk_bgn_callback> : OptionFunctionPtrCode { };
279  template <> struct OptionTypeCode<curl_chunk_end_callback> : OptionFunctionPtrCode { };
280  template <> struct OptionTypeCode<curl_fnmatch_callback> : OptionFunctionPtrCode { };
281  template <> struct OptionTypeCode<curl_seek_callback> : OptionFunctionPtrCode { };
282  template <> struct OptionTypeCode<curl_sockopt_callback> : OptionFunctionPtrCode { };
283  template <> struct OptionTypeCode<curl_opensocket_callback> : OptionFunctionPtrCode { };
284  template <> struct OptionTypeCode<curl_closesocket_callback> : OptionFunctionPtrCode { };
285  template <> struct OptionTypeCode<curl_ioctl_callback> : OptionFunctionPtrCode { };
286  template <> struct OptionTypeCode<curl_debug_callback> : OptionFunctionPtrCode { };
287  template <> struct OptionTypeCode<curl_conv_callback> : OptionFunctionPtrCode { };
288  template <> struct OptionTypeCode<curl_ssl_ctx_callback> : OptionFunctionPtrCode { };
289  template <> struct OptionTypeCode<curl_formget_callback> : OptionFunctionPtrCode { };
290  template <> struct OptionTypeCode<std::nullptr_t> : OptionNullPtrCode { };
291  // disable specialization if curl_off_t and long is the same
292  template <> struct OptionTypeCode<std::conditional<std::is_same<long, curl_off_t>::value, void, curl_off_t>::type> : OptionOffsetCode { };
293 
294 #pragma GCC diagnostic push
295 #pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
296  template <class ValueType>
297  bool Easy::set( CURLoption key, ValueType value )
298  {
299  static_assert( int(OptionTypeCode<ValueType>::value) != int(OptionInvalidCode::value), "the type is not supported by curl_easy_setopt" );
300 
301  auto err = CURLE_OK;
302 
303  // realtime argument check
304  auto keyTypeCode = key / kCurlOptTypeInterval * kCurlOptTypeInterval;
305  bool isValueAllowedNullPtr = std::is_same<ValueType, std::nullptr_t>::value &&
306  keyTypeCode != CURLOPTTYPE_LONG;
307 
308  if( OptionTypeCode<ValueType>::value != keyTypeCode && !isValueAllowedNullPtr ) {
309  err = CURLE_BAD_FUNCTION_ARGUMENT;
310  } else {
311  err = curl_easy_setopt( get(), key, value );
312  }
313 
314  return handleError( err );
315  }
316 #pragma GCC diagnostic pop
317 
318  inline bool Easy::set( CURLoption key, int value )
319  {
320  return set( key, static_cast<long>( value ) );
321  }
322 
323  inline bool Easy::set( CURLoption key, bool value )
324  {
325  return set( key, static_cast<long>( value ) );
326  }
327 
328  inline bool Easy::set( CURLoption key, std::string const &value )
329  {
330  return set( key, value.c_str() );
331  }
332 
333  // -- getInfo() stuff
334  template <class Type> struct InfoTypeCode { enum { value = -1 }; };
335  template <> struct InfoTypeCode<char*> { enum { value = CURLINFO_STRING }; };
336  template <> struct InfoTypeCode<long> { enum { value = CURLINFO_LONG }; };
337  template <> struct InfoTypeCode<double> { enum { value = CURLINFO_DOUBLE }; };
338  template <> struct InfoTypeCode<curl_slist*> { enum { value = CURLINFO_SLIST }; };
339  template <> struct InfoTypeCode<curl_certinfo*> { enum { value = CURLINFO_SLIST }; };
340  template <> struct InfoTypeCode<curl_tlssessioninfo*> { enum { value = CURLINFO_SLIST }; };
341 
342  template <class ValueType>
343  ValueType Easy::getInfo( CURLINFO key, ValueType const &defaultValue )
344  {
345  ValueType value;
346  auto err = CURLE_OK;
347 
348  static_assert( InfoTypeCode<ValueType>::value != -1, "the type is not supported by curl_easy_getinfo" );
349 
350  if( InfoTypeCode<ValueType>::value != (key & CURLINFO_TYPEMASK) ) {
351  err = CURLE_BAD_FUNCTION_ARGUMENT;
352  } else {
353  err = curl_easy_getinfo( get(), key, &value );
354  }
355 
356  return handleError( err ) ? value : defaultValue;
357  }
358 
359  template <>
360  inline std::string Easy::getInfo( CURLINFO key, std::string const &defaultValue )
361  {
362  const char* value = getInfo<char*>( key, nullptr );
363  return value ? value : defaultValue;
364  }
365 
366  std::ostream &operator << ( std::ostream &stream, Easy &curlite );
367  std::istream &operator >> ( std::istream &stream, Easy &curlite );
368 
369  /* Wrapper arround curl list (curl_slist)
370  *
371  * Example:
372  * List list ({{
373  * "pragma:"
374  * }});
375  */
376 
377  class List
378  {
379  curl_slist *_list;
380 
381  List( List const &other );
382  void operator = ( List const &other );
383  public:
384  List( curl_slist *list = nullptr );
385  List( std::vector<std::string> const &values );
386  List( List &&other );
387 
388  ~List();
389 
390  List &operator = ( List &&other );
391 
392  /* Returns pointer to the managed curl_slist object or nullptr.
393  */
394 
395  curl_slist *get() const;
396 
397  /* Release the ownership of the managed curl_httppost object if any.
398  *
399  * Returns pointer to the managed curl_slist object or nullptr.
400  */
401  curl_slist *release();
402 
403  /* Add new item to the list.
404  */
405 
406  List &append( char const *s );
407  List &append( std::vector<std::string> const &values );
408 
409  /* Just an alias for append().
410  */
411  List &operator << ( char const *s );
412  };
413 
414  /* Wrapper arround curl forms (curl_httppost)
415  *
416  * Example:
417  * Form form ({
418  * { CURLFORM_COPYNAME, "name" },
419  * { CURLFORM_COPYCONTENTS, "contents" }
420  * });
421  */
422 
423  class Form
424  {
425  curl_httppost *_first;
426  curl_httppost *_last;
427 
428  Form( Form const &other );
429  void operator = ( Form const &other );
430  public:
431 
432  Form();
433  Form( std::vector<curl_forms> const &forms );
434  Form( Form &&other );
435 
436  ~Form();
437 
438  Form &operator = ( Form &&other );
439 
440  /* Returns pointer to the first item of managed curl_httppost object or nullptr.
441  */
442 
443  curl_httppost *get() const;
444 
445  /* Release the ownership of the managed curl_httppost object if any.
446  *
447  * Returns std::pair with pointers to the managed curl_httppost object:
448  * pair.first pointer to first curl_httppost item
449  * pair.second pointer to last curl_httppost item
450  */
451 
452  std::pair<curl_httppost*, curl_httppost*> release();
453 
454  /* Add a section to the form. Supported all CURLFORM_* options except CURLFORM_ARRAY.
455  *
456  * Note: It's up to you to manage resources passed to the function. Be careful.
457  */
458 
459  bool add( std::vector<curl_forms> const &forms );
460  };
461 
462  /* Synonym for curl_global_init(). Returns true on success.
463  */
464 
465  bool global_init( long flags = CURL_GLOBAL_ALL );
466 
467  /* Synonym for curl_global_cleanup().
468  */
469 
470  void global_cleanup();
471 
472  /* Synonym for curl_version(). Returns cURL version string.
473  *
474  * Note: using versionInfo() should be preferred, if possible.
475  */
476 
477  std::string version();
478 
479  /* Synonym for curl_version_info(). Returns pointer to static curl_version_info_data structure.
480  *
481  * See cURL function curl_version_info() for more details.
482  */
483 
484  curl_version_info_data *versionInfo( CURLversion type = CURLVERSION_NOW );
485 
486  /* Download resource at a particular URL
487  *
488  * url resource to download
489  * ostr stream to write the resource data to
490  * followRedirect internally sets CURLOPT_FOLLOWLOCATION option to 1, if true
491  */
492 
493  Easy download( std::string const &url, std::ostream &ostr, bool followRedirect = true, bool throwExceptions = true );
494 
495  /* Upload resource to a particular URL
496  *
497  * istr stream to read the resource data from
498  * url url to upload input stream to
499  * username username to use in authentication
500  * password password to use in authentication
501  * size total size of the upload (if known)
502  */
503 
504  Easy upload( std::istream &istr,
505  std::string const &url,
506  std::string const &username = "",
507  std::string const &password = "",
508  curl_off_t size = -1,
509  bool throwExceptions = true );
510 
511 
512 
513 } // end of namespace
514 
515 #endif
Handler< curl_opensocket_callback >::type OpenSocketHandler
Definition: curlite.hpp:58
Handler< curl_ssl_ctx_callback >::type SslContextHandler
Definition: curlite.hpp:63
Exception(char const *message)
Definition: curlite.hpp:71
Handler< curl_fnmatch_callback >::type FnMatchHandler
Definition: curlite.hpp:54
std::function< bool(char *, size_t)> SimplifiedDataHandler
Definition: curlite.hpp:102
std::function< bool(curl_off_t, curl_off_t, curl_off_t, curl_off_t)> SimplifiedProgressHandler
Definition: curlite.hpp:103
Handler< curl_chunk_end_callback >::type ChunkEndHandler
Definition: curlite.hpp:53
Handler< curl_debug_callback >::type DebugHandler
Definition: curlite.hpp:61
Easy upload(std::istream &istr, std::string const &url, std::string const &username="", std::string const &password="", curl_off_t size=-1, bool throwExceptions=true)
Definition: curlite.cpp:860
Handler< curl_ioctl_callback >::type IoctlHandler
Definition: curlite.hpp:60
curl_version_info_data * versionInfo(CURLversion type=CURLVERSION_NOW)
Definition: curlite.cpp:843
std::ostream & operator<<(std::ostream &stream, Easy &curlite)
Definition: curlite.cpp:678
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
Handler< curl_read_callback >::type ReadHandler
Definition: curlite.hpp:56
Handler< curl_write_callback >::type WriteHandler
Definition: curlite.hpp:51
Handler< curl_seek_callback >::type SeekHandler
Definition: curlite.hpp:55
curl_slist * _list
Definition: curlite.hpp:379
bool global_init(long flags=CURL_GLOBAL_ALL)
Definition: curlite.cpp:828
std::unique_ptr< Pimpl > _impl
Definition: curlite.hpp:92
std::istream & operator>>(std::istream &stream, Easy &curlite)
Definition: curlite.cpp:684
Handler< curl_closesocket_callback >::type CloseSocketHandler
Definition: curlite.hpp:59
std::function< typename std::remove_pointer< FunctionPtr >::type > type
Definition: curlite.hpp:47
ValueType getInfo(CURLINFO key, ValueType const &defaultValue=ValueType())
Definition: curlite.hpp:343
Handler< curl_conv_callback >::type ConvHandler
Definition: curlite.hpp:62
std::string version()
Definition: curlite.cpp:838
Handler< curl_xferinfo_callback >::type XferInfoHandler
Definition: curlite.hpp:50
curl_httppost * _last
Definition: curlite.hpp:426
Easy download(std::string const &url, std::ostream &ostr, bool followRedirect=true, bool throwExceptions=true)
Definition: curlite.cpp:848
bool set(CURLoption opt, ValueType value)
Definition: curlite.hpp:297
static const int kCurlOptTypeInterval
Definition: curlite.hpp:258
curl_httppost * _first
Definition: curlite.hpp:425
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
Handler< curl_progress_callback >::type ProgressHandler
Definition: curlite.hpp:49
void global_cleanup()
Definition: curlite.cpp:833
Handler< curl_chunk_bgn_callback >::type ChunkBeginHandler
Definition: curlite.hpp:52
Handler< curl_formget_callback >::type FormGetHandler
Definition: curlite.hpp:64
Handler< curl_sockopt_callback >::type SockOptHandler
Definition: curlite.hpp:57


fanuc_post_processor
Author(s): Victor Lamoine - Institut Maupertuis
autogenerated on Mon Jun 10 2019 13:16:56