Advertisement
Guest User

Untitled

a guest
Apr 10th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.54 KB | None | 0 0
  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.  
  49. typedef Handler<curl_progress_callback>::type ProgressHandler;
  50. typedef Handler<curl_xferinfo_callback>::type XferInfoHandler;
  51. typedef Handler<curl_write_callback>::type WriteHandler;
  52. typedef Handler<curl_chunk_bgn_callback>::type ChunkBeginHandler;
  53. typedef Handler<curl_chunk_end_callback>::type ChunkEndHandler;
  54. typedef Handler<curl_fnmatch_callback>::type FnMatchHandler;
  55. typedef Handler<curl_seek_callback>::type SeekHandler;
  56. typedef Handler<curl_read_callback>::type ReadHandler;
  57. typedef Handler<curl_sockopt_callback>::type SockOptHandler;
  58. typedef Handler<curl_opensocket_callback>::type OpenSocketHandler;
  59. typedef Handler<curl_closesocket_callback>::type CloseSocketHandler;
  60. typedef Handler<curl_ioctl_callback>::type IoctlHandler;
  61. typedef Handler<curl_debug_callback>::type DebugHandler;
  62. typedef Handler<curl_conv_callback>::type ConvHandler;
  63. typedef Handler<curl_ssl_ctx_callback>::type SslContextHandler;
  64. typedef Handler<curl_formget_callback>::type FormGetHandler;
  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.  
  295. template <class ValueType>
  296. bool Easy::set( CURLoption key, ValueType value )
  297. {
  298. static_assert( int(OptionTypeCode<ValueType>::value) != int(OptionInvalidCode::value), "the type is not supported by curl_easy_setopt" );
  299.  
  300. auto err = CURLE_OK;
  301.  
  302. // realtime argument check
  303. auto keyTypeCode = key / kCurlOptTypeInterval * kCurlOptTypeInterval;
  304. bool isValueAllowedNullPtr = std::is_same<ValueType, std::nullptr_t>::value &&
  305. keyTypeCode != CURLOPTTYPE_LONG;
  306.  
  307. if( OptionTypeCode<ValueType>::value != keyTypeCode && !isValueAllowedNullPtr ) {
  308. err = CURLE_BAD_FUNCTION_ARGUMENT;
  309. } else {
  310. err = curl_easy_setopt( get(), key, value );
  311. }
  312.  
  313. return handleError( err );
  314. }
  315.  
  316. inline bool Easy::set( CURLoption key, int value )
  317. {
  318. return set( key, static_cast<long>( value ) );
  319. }
  320.  
  321. inline bool Easy::set( CURLoption key, bool value )
  322. {
  323. return set( key, static_cast<long>( value ) );
  324. }
  325.  
  326. inline bool Easy::set( CURLoption key, std::string const &value )
  327. {
  328. return set( key, value.c_str() );
  329. }
  330.  
  331. // -- getInfo() stuff
  332. template <class Type> struct InfoTypeCode { enum { value = -1 }; };
  333. template <> struct InfoTypeCode<char*> { enum { value = CURLINFO_STRING }; };
  334. template <> struct InfoTypeCode<long> { enum { value = CURLINFO_LONG }; };
  335. template <> struct InfoTypeCode<double> { enum { value = CURLINFO_DOUBLE }; };
  336. template <> struct InfoTypeCode<curl_slist*> { enum { value = CURLINFO_SLIST }; };
  337. template <> struct InfoTypeCode<curl_certinfo*> { enum { value = CURLINFO_SLIST }; };
  338. template <> struct InfoTypeCode<curl_tlssessioninfo*> { enum { value = CURLINFO_SLIST }; };
  339.  
  340. template <class ValueType>
  341. ValueType Easy::getInfo( CURLINFO key, ValueType const &defaultValue )
  342. {
  343. ValueType value;
  344. auto err = CURLE_OK;
  345.  
  346. static_assert( InfoTypeCode<ValueType>::value != -1, "the type is not supported by curl_easy_getinfo" );
  347.  
  348. if( InfoTypeCode<ValueType>::value != (key & CURLINFO_TYPEMASK) ) {
  349. err = CURLE_BAD_FUNCTION_ARGUMENT;
  350. } else {
  351. err = curl_easy_getinfo( get(), key, &value );
  352. }
  353.  
  354. return handleError( err ) ? value : defaultValue;
  355. }
  356.  
  357. template <>
  358. inline std::string Easy::getInfo( CURLINFO key, std::string const &defaultValue )
  359. {
  360. const char* value = getInfo<char*>( key, nullptr );
  361. return value ? value : defaultValue;
  362. }
  363.  
  364. std::ostream &operator << ( std::ostream &stream, Easy &curlite );
  365. std::istream &operator >> ( std::istream &stream, Easy &curlite );
  366.  
  367. /* Wrapper arround curl list (curl_slist)
  368. *
  369. * Example:
  370. * List list ({{
  371. * "pragma:"
  372. * }});
  373. */
  374.  
  375. class List
  376. {
  377. curl_slist *_list;
  378.  
  379. List( List const &other );
  380. void operator = ( List const &other );
  381. public:
  382. List( curl_slist *list = nullptr );
  383. List( std::vector<std::string> const &values );
  384. List( List &&other );
  385.  
  386. ~List();
  387.  
  388. List &operator = ( List &&other );
  389.  
  390. /* Returns pointer to the managed curl_slist object or nullptr.
  391. */
  392.  
  393. curl_slist *get() const;
  394.  
  395. /* Release the ownership of the managed curl_httppost object if any.
  396. *
  397. * Returns pointer to the managed curl_slist object or nullptr.
  398. */
  399. curl_slist *release();
  400.  
  401. /* Add new item to the list.
  402. */
  403.  
  404. List &append( char const *s );
  405. List &append( std::vector<std::string> const &values );
  406.  
  407. /* Just an alias for append().
  408. */
  409. List &operator << ( char const *s );
  410. };
  411.  
  412. /* Wrapper arround curl forms (curl_httppost)
  413. *
  414. * Example:
  415. * Form form ({
  416. * { CURLFORM_COPYNAME, "name" },
  417. * { CURLFORM_COPYCONTENTS, "contents" }
  418. * });
  419. */
  420.  
  421. class Form
  422. {
  423. curl_httppost *_first;
  424. curl_httppost *_last;
  425.  
  426. Form( Form const &other );
  427. void operator = ( Form const &other );
  428. public:
  429.  
  430. Form();
  431. Form( std::vector<curl_forms> const &forms );
  432. Form( Form &&other );
  433.  
  434. ~Form();
  435.  
  436. Form &operator = ( Form &&other );
  437.  
  438. /* Returns pointer to the first item of managed curl_httppost object or nullptr.
  439. */
  440.  
  441. curl_httppost *get() const;
  442.  
  443. /* Release the ownership of the managed curl_httppost object if any.
  444. *
  445. * Returns std::pair with pointers to the managed curl_httppost object:
  446. * pair.first pointer to first curl_httppost item
  447. * pair.second pointer to last curl_httppost item
  448. */
  449.  
  450. std::pair<curl_httppost*, curl_httppost*> release();
  451.  
  452. /* Add a section to the form. Supported all CURLFORM_* options except CURLFORM_ARRAY.
  453. *
  454. * Note: It's up to you to manage resources passed to the function. Be careful.
  455. */
  456.  
  457. bool add( std::vector<curl_forms> const &forms );
  458. };
  459.  
  460. /* Synonym for curl_global_init(). Returns true on success.
  461. */
  462.  
  463. bool global_init( long flags = CURL_GLOBAL_ALL );
  464.  
  465. /* Synonym for curl_global_cleanup().
  466. */
  467.  
  468. void global_cleanup();
  469.  
  470. /* Synonym for curl_version(). Returns cURL version string.
  471. *
  472. * Note: using versionInfo() should be preferred, if possible.
  473. */
  474.  
  475. std::string version();
  476.  
  477. /* Synonym for curl_version_info(). Returns pointer to static curl_version_info_data structure.
  478. *
  479. * See cURL function curl_version_info() for more details.
  480. */
  481.  
  482. curl_version_info_data *versionInfo( CURLversion type = CURLVERSION_NOW );
  483.  
  484. /* Download resource at a particular URL
  485. *
  486. * url resource to download
  487. * ostr stream to write the resource data to
  488. * followRedirect internally sets CURLOPT_FOLLOWLOCATION option to 1, if true
  489. */
  490.  
  491. Easy download( std::string const &url, std::ostream &ostr, bool followRedirect = true, bool throwExceptions = true );
  492.  
  493. /* Upload resource to a particular URL
  494. *
  495. * istr stream to read the resource data from
  496. * url url to upload input stream to
  497. * username username to use in authentication
  498. * password password to use in authentication
  499. * size total size of the upload (if known)
  500. */
  501.  
  502. Easy upload( std::istream &istr,
  503. std::string const &url,
  504. std::string const &username = "",
  505. std::string const &password = "",
  506. curl_off_t size = -1,
  507. bool throwExceptions = true );
  508.  
  509.  
  510.  
  511. } // end of namespace
  512.  
  513. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement