34 struct CurlGlobalInitializer
40 #ifndef CURLITE_NO_AUTOMATIC_GLOBAL_INITIALIZATION 41 CurlGlobalInitializer globalInitializer;
49 template <
class HandlerType>
84 static size_t read(
char *data,
size_t size,
size_t n,
void *userPtr );
85 static size_t write(
char *data,
size_t size,
size_t n,
void *userPtr );
86 static size_t header(
char *data,
size_t size,
size_t n,
void *userPtr );
87 static int seek(
void *userPtr, curl_off_t offset,
int origin );
88 static int fnMatch(
void *userPtr,
const char *pattern,
const char *
string );
89 static curlioerr ioctl( CURL *handle,
int cmd,
void *userPtr );
91 static int progress(
void *userPtr,
double dTotal,
double dCurrent,
double uTotal,
double uCurrent );
92 static int xferInfo(
void *userPtr, curl_off_t dTotal, curl_off_t dCurrent, curl_off_t uTotal, curl_off_t uCurrent );
94 static long chunkBegin(
const void *transferInfo,
void *userPtr,
int remains );
95 static long chunkEnd(
void *userPtr );
97 static curl_socket_t openSocket(
void *userPtr, curlsocktype purpose, curl_sockaddr *address );
98 static int closeSocket(
void *userPtr, curl_socket_t socket );
99 static int sockOpt(
void *userPtr, curl_socket_t socket, curlsocktype purpose );
101 static CURLcode sslContext( CURL *curl,
void *sslCtx,
void *userPtr );
102 static int debug( CURL *, curl_infotype type,
char *data,
size_t size,
void *userPtr );
113 throwExceptions =
true;
116 size_t Easy::Pimpl::read(
char *data,
size_t size,
size_t n,
void *userPtr )
118 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
120 auto &ev = impl->onRead;
122 return ev.handler( (
char*) data, size, n, ev.data );
126 return CURL_READFUNC_ABORT;
129 size_t Easy::Pimpl::write(
char *data,
size_t size,
size_t n,
void *userPtr )
131 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
133 auto &ev = impl->onWrite;
135 return ev.handler( (
char*) data, size, n, ev.data );
142 size_t Easy::Pimpl::header(
char *data,
size_t size,
size_t n,
void *userPtr )
144 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
146 auto &ev = impl->onHeader;
148 return ev.handler( (
char*) data, size, n, ev.data );
155 int Easy::Pimpl::fnMatch(
void *userPtr,
const char *pattern,
const char *
string )
157 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
159 auto &ev = impl->onFnMatch;
161 return ev.handler( ev.data, pattern,
string );
165 return CURL_FNMATCHFUNC_FAIL;
168 int Easy::Pimpl::seek(
void *userPtr, curl_off_t offset,
int origin )
170 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
172 auto &ev = impl->onSeek;
174 return ev.handler( ev.data, offset, origin );
181 curlioerr Easy::Pimpl::ioctl( CURL *handle,
int cmd,
void *userPtr )
183 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
185 auto &ev = impl->onIoctl;
187 return ev.handler( handle, cmd, ev.data );
191 return CURLIOE_UNKNOWNCMD;
194 int Easy::Pimpl::progress(
void *userPtr,
double dTotal,
double dCurrent,
double uTotal,
double uCurrent )
196 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
198 auto &ev = impl->onProgress;
200 return ev.handler( ev.data, dTotal, dCurrent, uTotal, uCurrent );
207 int Easy::Pimpl::xferInfo(
void *userPtr, curl_off_t dTotal, curl_off_t dCurrent, curl_off_t uTotal, curl_off_t uCurrent )
209 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
211 auto &ev = impl->onXferInfo;
213 return ev.handler( ev.data, dTotal, dCurrent, uTotal, uCurrent );
220 long Easy::Pimpl::chunkBegin(
const void *transferInfo,
void *userPtr,
int remains )
222 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
224 auto &ev = impl->onChunkBegin;
226 return ev.handler( transferInfo, ev.data, remains );
230 return CURL_CHUNK_BGN_FUNC_FAIL;
233 long Easy::Pimpl::chunkEnd(
void *userPtr )
235 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
237 auto &ev = impl->onChunkEnd;
239 return ev.handler( ev.data );
243 return CURL_CHUNK_END_FUNC_FAIL;
246 curl_socket_t Easy::Pimpl::openSocket(
void *userPtr, curlsocktype purpose, curl_sockaddr *address )
248 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
250 auto &ev = impl->onOpenSocket;
252 return ev.handler( ev.data, purpose, address );
256 return CURL_SOCKET_BAD;
259 int Easy::Pimpl::closeSocket(
void *userPtr, curl_socket_t socket )
261 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
263 auto &ev = impl->onCloseSocket;
265 return ev.handler( ev.data, socket );
272 int Easy::Pimpl::sockOpt(
void *userPtr, curl_socket_t socket, curlsocktype purpose )
274 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
276 auto &ev = impl->onSockOpt;
278 return ev.handler( ev.data, socket, purpose );
285 CURLcode Easy::Pimpl::sslContext( CURL *curl,
void *sslCtx,
void *userPtr )
287 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
289 auto &ev = impl->onSslContext;
291 return ev.handler( curl, sslCtx, ev.data );
295 return CURLE_ABORTED_BY_CALLBACK;
298 int Easy::Pimpl::debug( CURL *, curl_infotype type,
char *data,
size_t size,
void *userPtr )
300 if(
auto impl = reinterpret_cast<Easy::Pimpl*>( userPtr ) )
302 auto &ev = impl->onDebug;
304 ev.handler(
nullptr, type, data, size, ev.data );
315 : _impl( new
Pimpl() )
317 _impl->curl = curl_easy_init();
319 if(
_impl->curl ==
nullptr ) {
320 throw Exception(
"can't init curl_easy interface" );
324 set( CURLOPT_USERAGENT,
"curlite::Easy" );
329 *
this = std::move( other );
335 curl_easy_cleanup( ptr );
344 curl_easy_cleanup( ptr );
347 _impl.swap( other._impl );
353 Easy::operator bool()
const 355 return _impl->err == CURLE_OK;
360 onRead( [&stream] (
char *data,
size_t size,
size_t n,
void *) ->
size_t 362 stream.read( (
char*) data, size * n );
363 return size_t( stream.gcount() );
371 onWrite( [&stream] (
char *data,
size_t size,
size_t n,
void *) ->
size_t 373 stream.write( (
char*) data, size * n );
374 return stream ? size * n : 0;
382 CURL *curl =
nullptr;
384 std::swap(
_impl->curl, curl );
392 curl_easy_reset(
_impl->curl );
394 _impl->err = CURLE_OK;
406 curl_easy_perform(
_impl->curl )
413 auto err = curl_easy_send(
_impl->curl, buffer, bufferSize, &sent );
420 auto err = curl_easy_recv(
_impl->curl, buffer, bufferSize, &received );
427 curl_easy_pause(
_impl->curl, bitmask )
438 _impl->throwExceptions = throwExceptions;
443 return _impl->throwExceptions;
453 return curl_easy_strerror(
_impl->err );
460 if(
_impl->err != CURLE_OK &&
_impl->throwExceptions ) {
464 return _impl->err == CURLE_OK;
469 _impl->userData = data;
474 return _impl->userData;
481 char *str = curl_easy_escape(
_impl->curl, url.data(), url.size() );
492 std::string unescaped;
495 char *str = curl_easy_unescape(
_impl->curl, url.data(), url.size(), &outLength );
497 unescaped.assign( str, str + outLength );
506 auto wrapper = [f](
char *data,
size_t size,
size_t n,
void * ) ->
size_t {
507 return f( data, size * n ) ? size * n : CURL_READFUNC_ABORT;
515 auto wrapper = [f](
char *data,
size_t size,
size_t n,
void * ) ->
size_t {
516 return f( data, size * n ) ? size * n : 0;
524 auto wrapper = [f](
char *data,
size_t size,
size_t n,
void * ) ->
size_t {
525 return f( data, size * n ) ? size * n : 0;
533 auto wrapper = [f](
void *, curl_off_t dTotal, curl_off_t dCurrent, curl_off_t uTotal, curl_off_t uCurrent ) ->
int {
534 return !f( dTotal, dCurrent, uTotal, uCurrent );
542 _impl->onRead.handler = f;
543 _impl->onRead.data = data;
545 set( CURLOPT_READFUNCTION, f ? &
Pimpl::read : nullptr );
546 set( CURLOPT_READDATA, f ? (
void*) this->
_impl.get() : nullptr );
551 _impl->onWrite.handler = f;
552 _impl->onWrite.data = data;
554 set( CURLOPT_WRITEFUNCTION, f ? &
Pimpl::write : nullptr );
555 set( CURLOPT_WRITEDATA, f ? (
void*) this->
_impl.get() : nullptr );
560 _impl->onHeader.handler = f;
561 _impl->onHeader.data = data;
564 set( CURLOPT_HEADERDATA, f ? (
void*) this->
_impl.get() : nullptr );
569 _impl->onProgress.handler = f;
570 _impl->onProgress.data = data;
573 set( CURLOPT_PROGRESSDATA, f ? (
void*) this->
_impl.get() : nullptr );
574 set( CURLOPT_NOPROGRESS, f ?
false : true );
579 _impl->onDebug.handler = f;
580 _impl->onDebug.data = data;
582 set( CURLOPT_DEBUGFUNCTION, f ? &
Pimpl::debug : nullptr );
583 set( CURLOPT_DEBUGDATA, f ? (
void*) this->
_impl.get() : nullptr );
584 set( CURLOPT_VERBOSE, f ?
true : false );
589 _impl->onIoctl.handler = f;
590 _impl->onIoctl.data = data;
592 set( CURLOPT_IOCTLFUNCTION, f ? &
Pimpl::ioctl : nullptr );
593 set( CURLOPT_IOCTLDATA, f ? (
void*) this->
_impl.get() : nullptr );
598 _impl->onSeek.handler = f;
599 _impl->onSeek.data = data;
601 set( CURLOPT_SEEKFUNCTION, f ? &
Pimpl::seek : nullptr );
602 set( CURLOPT_SEEKDATA, f ? (
void*) this->
_impl.get() : nullptr );
607 _impl->onFnMatch.handler = f;
608 _impl->onFnMatch.data = data;
611 set( CURLOPT_FNMATCH_DATA, f ? (
void*) this->
_impl.get() : nullptr );
616 _impl->onXferInfo.handler = f;
617 _impl->onXferInfo.data = data;
620 set( CURLOPT_XFERINFODATA, f ? (
void*) this->
_impl.get() : nullptr );
621 set( CURLOPT_NOPROGRESS, f ?
false : true );
626 _impl->onOpenSocket.handler = f;
627 _impl->onOpenSocket.data = data;
630 set( CURLOPT_OPENSOCKETDATA, f ? (
void*) this->
_impl.get() : nullptr );
635 _impl->onCloseSocket.handler = f;
636 _impl->onCloseSocket.data = data;
639 set( CURLOPT_CLOSESOCKETDATA, f ? (
void*) this->
_impl.get() : nullptr );
644 _impl->onSockOpt.handler = f;
645 _impl->onSockOpt.data = data;
648 set( CURLOPT_SOCKOPTDATA, f ? (
void*) this->
_impl.get() : nullptr );
653 _impl->onChunkBegin.handler = f;
654 _impl->onChunkBegin.data = data;
657 set( CURLOPT_CHUNK_DATA, f ? (
void*) this->
_impl.get() : nullptr );
662 _impl->onChunkEnd.handler = f;
663 _impl->onChunkEnd.data = data;
666 set( CURLOPT_CHUNK_DATA, f ? (
void*) this->
_impl.get() : nullptr );
671 _impl->onSslContext.handler = f;
672 _impl->onSslContext.data = data;
675 set( CURLOPT_SSL_CTX_DATA, f ? (
void*) this->
_impl.get() : nullptr );
706 curl_slist_free_all( ptr );
713 *
this = std::move( other );
721 curl_slist_free_all( ptr );
724 std::swap(
_list, other._list );
737 curl_slist *list =
nullptr;
738 std::swap( list,
_list );
750 for(
auto it = values.begin(); it != values.end(); ++it ) {
778 std::swap(
_first, other._first );
779 std::swap(
_last, other._last );
784 if(
auto ptr =
release().first ) {
785 curl_formfree( ptr );
793 if(
auto ptr =
release().first ) {
794 curl_formfree( ptr );
797 std::swap(
_first, other._first );
798 std::swap(
_last, other._last );
811 auto r = std::make_pair<curl_httppost*, curl_httppost*>(
nullptr, nullptr );
813 std::swap( r.first,
_first );
814 std::swap( r.second,
_last );
821 auto err = curl_formadd( &
_first, &
_last, CURLFORM_ARRAY, forms.data(), CURLFORM_END );
822 return err == CURL_FORMADD_OK;
830 return curl_global_init( flags ) == 0;
835 curl_global_cleanup();
840 return std::string( curl_version() );
845 return curl_version_info( type );
848 Easy download( std::string
const &url, std::ostream &ostr,
bool followRedirect,
bool throwExceptions )
852 c.
set( CURLOPT_URL, url );
853 c.
set( CURLOPT_FOLLOWLOCATION, followRedirect );
857 return std::move( c );
861 std::string
const &url,
862 std::string
const &username,
863 std::string
const &password,
865 bool throwExceptions )
869 c.
set( CURLOPT_URL, url );
870 c.
set( CURLOPT_USERNAME, username );
871 c.
set( CURLOPT_PASSWORD, password );
872 c.
set( CURLOPT_INFILESIZE_LARGE, size );
873 c.
set( CURLOPT_UPLOAD,
true );
877 headers <<
"Transfer-Encoding: chunked";
878 headers <<
"Expect:";
881 c.
set( CURLOPT_HTTPHEADER, headers.
get() );
887 c.
set( CURLOPT_HTTPHEADER,
nullptr );
889 return std::move( c );
static int xferInfo(void *userPtr, curl_off_t dTotal, curl_off_t dCurrent, curl_off_t uTotal, curl_off_t uCurrent)
Event< XferInfoHandler > onXferInfo
Handler< curl_opensocket_callback >::type OpenSocketHandler
Handler< curl_ssl_ctx_callback >::type SslContextHandler
static int sockOpt(void *userPtr, curl_socket_t socket, curlsocktype purpose)
void onWrite_(SimplifiedDataHandler f)
Handler< curl_fnmatch_callback >::type FnMatchHandler
Event< CloseSocketHandler > onCloseSocket
void onWrite(WriteHandler f=WriteHandler(), void *data=nullptr)
bool exceptionMode() const
Event< OpenSocketHandler > onOpenSocket
void onProgress(ProgressHandler f=ProgressHandler(), void *data=nullptr)
std::function< bool(char *, size_t)> SimplifiedDataHandler
static curl_socket_t openSocket(void *userPtr, curlsocktype purpose, curl_sockaddr *address)
std::function< bool(curl_off_t, curl_off_t, curl_off_t, curl_off_t)> SimplifiedProgressHandler
Handler< curl_chunk_end_callback >::type ChunkEndHandler
Handler< curl_debug_callback >::type DebugHandler
void setUserData(void *data)
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)
void onSslContext(SslContextHandler f=SslContextHandler(), void *data=nullptr)
Handler< curl_ioctl_callback >::type IoctlHandler
curl_version_info_data * versionInfo(CURLversion type=CURLVERSION_NOW)
bool handleError(CURLcode code)
static int progress(void *userPtr, double dTotal, double dCurrent, double uTotal, double uCurrent)
void onSeek(SeekHandler f=SeekHandler(), void *data=nullptr)
void onOpenSocket(OpenSocketHandler f=OpenSocketHandler(), void *data=nullptr)
static long chunkBegin(const void *transferInfo, void *userPtr, int remains)
static CURLcode sslContext(CURL *curl, void *sslCtx, void *userPtr)
void onProgress_(SimplifiedProgressHandler f)
Handler< curl_read_callback >::type ReadHandler
Handler< curl_write_callback >::type WriteHandler
size_t send(const char *buffer, size_t bufferSize)
Handler< curl_seek_callback >::type SeekHandler
void onCloseSocket(CloseSocketHandler f=CloseSocketHandler(), void *data=nullptr)
List & operator<<(char const *s)
bool global_init(long flags=CURL_GLOBAL_ALL)
std::unique_ptr< Pimpl > _impl
Event< SockOptHandler > onSockOpt
void onHeader_(SimplifiedDataHandler f)
Handler< curl_closesocket_callback >::type CloseSocketHandler
Event< SslContextHandler > onSslContext
Event< FnMatchHandler > onFnMatch
bool operator<<(std::istream &stream)
Event< ReadHandler > onRead
void operator=(Easy const &other)
static int fnMatch(void *userPtr, const char *pattern, const char *string)
static size_t header(char *data, size_t size, size_t n, void *userPtr)
void onRead(ReadHandler f=ReadHandler(), void *data=nullptr)
void setExceptionMode(bool throwExceptions)
Handler< curl_xferinfo_callback >::type XferInfoHandler
static size_t read(char *data, size_t size, size_t n, void *userPtr)
void onDebug(DebugHandler f=DebugHandler(), void *data=nullptr)
Easy download(std::string const &url, std::ostream &ostr, bool followRedirect=true, bool throwExceptions=true)
void onHeader(WriteHandler f=WriteHandler(), void *data=nullptr)
bool operator>>(std::ostream &stream)
size_t recv(char *buffer, size_t bufferSize)
bool set(CURLoption opt, ValueType value)
static long chunkEnd(void *userPtr)
std::string escape(std::string const &url)
Event< IoctlHandler > onIoctl
std::string errorString() const
void onIoctl(IoctlHandler f=IoctlHandler(), void *data=nullptr)
std::string unescape(std::string const &url)
void operator=(List const &other)
void onXferInfo(XferInfoHandler f=XferInfoHandler(), void *data=nullptr)
void onRead_(SimplifiedDataHandler f)
Event< ChunkEndHandler > onChunkEnd
static size_t write(char *data, size_t size, size_t n, void *userPtr)
void onSockOpt(SockOptHandler f=SockOptHandler(), void *data=nullptr)
Handler< curl_progress_callback >::type ProgressHandler
Event< SeekHandler > onSeek
static int seek(void *userPtr, curl_off_t offset, int origin)
Event< ChunkBeginHandler > onChunkBegin
static int closeSocket(void *userPtr, curl_socket_t socket)
Event< DebugHandler > onDebug
static int debug(CURL *, curl_infotype type, char *data, size_t size, void *userPtr)
void onChunkBegin(ChunkBeginHandler f=ChunkBeginHandler(), void *data=nullptr)
void onFnMatch(FnMatchHandler f=FnMatchHandler(), void *data=nullptr)
static curlioerr ioctl(CURL *handle, int cmd, void *userPtr)
void onChunkEnd(ChunkEndHandler f=ChunkEndHandler(), void *data=nullptr)
Handler< curl_chunk_bgn_callback >::type ChunkBeginHandler
List & append(char const *s)
Event< WriteHandler > onHeader
Event< ProgressHandler > onProgress
Event< WriteHandler > onWrite
Handler< curl_sockopt_callback >::type SockOptHandler