require 'ethon/easy/informations' require 'ethon/easy/callbacks' require 'ethon/easy/options' require 'ethon/easy/header' require 'ethon/easy/util' require 'ethon/easy/params' require 'ethon/easy/form' require 'ethon/easy/http' require 'ethon/easy/operations' require 'ethon/easy/response_callbacks' module Ethon # This is the class representing the libcurl easy interface # See http://curl.haxx.se/libcurl/c/libcurl-easy.html for more informations. # # @example You can access the libcurl easy interface through this class, every request is based on it. The simplest setup looks like that: # # e = Ethon::Easy.new(url: "www.example.com") # e.prepare # e.perform # #=> :ok # # @example You can the reuse this Easy for the next request: # # e.reset # reset easy handle # e.url = "www.google.com" # e.followlocation = true # e.prepare # e.perform # #=> :ok # # @see initialize class Easy include Ethon::Easy::Informations include Ethon::Easy::Callbacks include Ethon::Easy::Options include Ethon::Easy::Header include Ethon::Easy::Http include Ethon::Easy::Operations include Ethon::Easy::ResponseCallbacks # Returns the curl return code. # # @return [ Symbol ] The return code. # * :ok: All fine. Proceed as usual. # * :unsupported_protocol: The URL you passed to libcurl used a # protocol that this libcurl does not support. The support # might be a compile-time option that you didn't use, it can # be a misspelled protocol string or just a protocol # libcurl has no code for. # * :failed_init: Very early initialization code failed. This # is likely to be an internal error or problem, or a # resource problem where something fundamental couldn't # get done at init time. # * :url_malformat: The URL was not properly formatted. # * :not_built_in: A requested feature, protocol or option # was not found built-in in this libcurl due to a build-time # decision. This means that a feature or option was not enabled # or explicitly disabled when libcurl was built and in # order to get it to function you have to get a rebuilt libcurl. # * :couldnt_resolve_proxy: Couldn't resolve proxy. The given # proxy host could not be resolved. # * :couldnt_resolve_host: Couldn't resolve host. The given remote # host was not resolved. # * :couldnt_connect: Failed to connect() to host or proxy. # * :ftp_weird_server_reply: After connecting to a FTP server, # libcurl expects to get a certain reply back. This error # code implies that it got a strange or bad reply. The given # remote server is probably not an OK FTP server. # * :remote_access_denied: We were denied access to the resource # given in the URL. For FTP, this occurs while trying to # change to the remote directory. # * :ftp_accept_failed: While waiting for the server to connect # back when an active FTP session is used, an error code was # sent over the control connection or similar. # * :ftp_weird_pass_reply: After having sent the FTP password to # the server, libcurl expects a proper reply. This error code # indicates that an unexpected code was returned. # * :ftp_accept_timeout: During an active FTP session while # waiting for the server to connect, the CURLOPT_ACCEPTTIMOUT_MS # (or the internal default) timeout expired. # * :ftp_weird_pasv_reply: libcurl failed to get a sensible result # back from the server as a response to either a PASV or a # EPSV command. The server is flawed. # * :ftp_weird_227_format: FTP servers return a 227-line as a response # to a PASV command. If libcurl fails to parse that line, # this return code is passed back. # * :ftp_cant_get_host: An internal failure to lookup the host used # for the new connection. # * :ftp_couldnt_set_type: Received an error when trying to set # the transfer mode to binary or ASCII. # * :partial_file: A file transfer was shorter or larger than # expected. This happens when the server first reports an expected # transfer size, and then delivers data that doesn't match the # previously given size. # * :ftp_couldnt_retr_file: This was either a weird reply to a # 'RETR' command or a zero byte transfer complete. # * :quote_error: When sending custom "QUOTE" commands to the # remote server, one of the commands returned an error code that # was 400 or higher (for FTP) or otherwise indicated unsuccessful # completion of the command. # * :http_returned_error: This is returned if CURLOPT_FAILONERROR is # set TRUE and the HTTP server returns an error code that is >= 400. # * :write_error: An error occurred when writing received data to a # local file, or an error was returned to libcurl from a write callback. # * :upload_failed: Failed starting the upload. For FTP, the server # typically denied the STOR command. The error buffer usually # contains the server's explanation for this. # * :read_error: There was a problem reading a local file or an error # returned by the read callback. # * :out_of_memory: A memory allocation request failed. This is serious # badness and things are severely screwed up if this ever occurs. # * :operation_timedout: Operation timeout. The specified time-out # period was reached according to the conditions. # * :ftp_port_failed: The FTP PORT command returned error. This mostly # happens when you haven't specified a good enough address for # libcurl to use. See CURLOPT_FTPPORT. # * :ftp_couldnt_use_rest: The FTP REST command returned error. This # should never happen if the server is sane. # * :range_error: The server does not support or accept range requests. # * :http_post_error: This is an odd error that mainly occurs due to # internal confusion. # * :ssl_connect_error: A problem occurred somewhere in the SSL/TLS # handshake. You really want the error buffer and read the message # there as it pinpoints the problem slightly more. Could be # certificates (file formats, paths, permissions), passwords, and others. # * :bad_download_resume: The download could not be resumed because # the specified offset was out of the file boundary. # * :file_couldnt_read_file: A file given with FILE:// couldn't be # opened. Most likely because the file path doesn't identify an # existing file. Did you check file permissions? # * :ldap_cannot_bind: LDAP cannot bind. LDAP bind operation failed. # * :ldap_search_failed: LDAP search failed. # * :function_not_found: Function not found. A required zlib function was not found. # * :aborted_by_callback: Aborted by callback. A callback returned # "abort" to libcurl. # * :bad_function_argument: Internal error. A function was called with # a bad parameter. # * :interface_failed: Interface error. A specified outgoing interface # could not be used. Set which interface to use for outgoing # connections' source IP address with CURLOPT_INTERFACE. # * :too_many_redirects: Too many redirects. When following redirects, # libcurl hit the maximum amount. Set your limit with CURLOPT_MAXREDIRS. # * :unknown_option: An option passed to libcurl is not recognized/known. # Refer to the appropriate documentation. This is most likely a # problem in the program that uses libcurl. The error buffer might # contain more specific information about which exact option it concerns. # * :telnet_option_syntax: A telnet option string was Illegally formatted. # * :peer_failed_verification: The remote server's SSL certificate or # SSH md5 fingerprint was deemed not OK. # * :got_nothing: Nothing was returned from the server, and under the # circumstances, getting nothing is considered an error. # * :ssl_engine_notfound: The specified crypto engine wasn't found. # * :ssl_engine_setfailed: Failed setting the selected SSL crypto engine as default! # * :send_error: Failed sending network data. # * :recv_error: Failure with receiving network data. # * :ssl_certproblem: problem with the local client certificate. # * :ssl_cipher: Couldn't use specified cipher. # * :ssl_cacert: Peer certificate cannot be authenticated with known CA certificates. # * :bad_content_encoding: Unrecognized transfer encoding. # * :ldap_invalid_url: Invalid LDAP URL. # * :filesize_exceeded: Maximum file size exceeded. # * :use_ssl_failed: Requested FTP SSL level failed. # * :send_fail_rewind: When doing a send operation curl had to rewind the data to # retransmit, but the rewinding operation failed. # * :ssl_engine_initfailed: Initiating the SSL Engine failed. # * :login_denied: The remote server denied curl to login # * :tftp_notfound: File not found on TFTP server. # * :tftp_perm: Permission problem on TFTP server. # * :remote_disk_full: Out of disk space on the server. # * :tftp_illegal: Illegal TFTP operation. # * :tftp_unknownid: Unknown TFTP transfer ID. # * :remote_file_exists: File already exists and will not be overwritten. # * :tftp_nosuchuser: This error should never be returned by a properly # functioning TFTP server. # * :conv_failed: Character conversion failed. # * :conv_reqd: Caller must register conversion callbacks. # * :ssl_cacert_badfile: Problem with reading the SSL CA cert (path? access rights?): # * :remote_file_not_found: The resource referenced in the URL does not exist. # * :ssh: An unspecified error occurred during the SSH session. # * :ssl_shutdown_failed: Failed to shut down the SSL connection. # * :again: Socket is not ready for send/recv wait till it's ready and try again. # This return code is only returned from curl_easy_recv(3) and curl_easy_send(3) # * :ssl_crl_badfile: Failed to load CRL file # * :ssl_issuer_error: Issuer check failed # * :ftp_pret_failed: The FTP server does not understand the PRET command at # all or does not support the given argument. Be careful when # using CURLOPT_CUSTOMREQUEST, a custom LIST command will be sent with PRET CMD # before PASV as well. # * :rtsp_cseq_error: Mismatch of RTSP CSeq numbers. # * :rtsp_session_error: Mismatch of RTSP Session Identifiers. # * :ftp_bad_file_list: Unable to parse FTP file list (during FTP wildcard downloading). # * :chunk_failed: Chunk callback reported error. # * :obsolete: These error codes will never be returned. They were used in an old # libcurl version and are currently unused. # # # @see http://curl.haxx.se/libcurl/c/libcurl-errors.html attr_accessor :return_code class << self # Free libcurl representation from an easy handle. # # @example Free easy handle. # Easy.finalizer(easy) # # @param [ Easy ] easy The easy to free. def finalizer(easy) proc { Curl.slist_free_all(easy.header_list) if easy.header_list Curl.easy_cleanup(easy.handle) } end end # Initialize a new Easy. # It initializes curl, if not already done and applies the provided options. # # @example Create a new Easy. # Easy.new(:url => "www.google.de") # # @param [ Hash ] options The options to set. # # @option options :cainfo [String] Pass a char * to a zero terminated # string naming a file holding one or more certificates to verify # the peer with. This makes sense only when used in combination with # the CURLOPT_SSL_VERIFYPEER option. If CURLOPT_SSL_VERIFYPEER is # zero, CURLOPT_CAINFO need not even indicate an accessible file. # This option is by default set to the system path where libcurl's # cacert bundle is assumed to be stored, as established at build time. # When built against NSS, this is the directory that the NSS certificate # database resides in. # @option options :capath [String] # Pass a char * to a zero terminated string naming a directory holding # multiple CA certificates to verify the peer with. If libcurl is built # against OpenSSL, the certificate directory must be prepared using the # openssl c_rehash utility. This makes sense only when used in # combination with the CURLOPT_SSL_VERIFYPEER option. If # CURLOPT_SSL_VERIFYPEER is zero, CURLOPT_CAPATH need not even indicate # an accessible path. The CURLOPT_CAPATH function apparently does not # work in Windows due to some limitation in openssl. This option is # OpenSSL-specific and does nothing if libcurl is built to use GnuTLS. # NSS-powered libcurl provides the option only for backward # compatibility. # @option options :connecttimeout [Integer] # Pass a long. It should contain the maximum time in seconds that you # allow the connection to the server to take. This only limits the # connection phase, once it has connected, this option is of no more # use. Set to zero to switch to the default built-in connection timeout # \- 300 seconds. See also the CURLOPT_TIMEOUT option. # In unix-like systems, this might cause signals to be used unless # CURLOPT_NOSIGNAL is set. # @option options :connecttimeout_ms [Integer] # Like CURLOPT_CONNECTTIMEOUT but takes the number of milliseconds # instead. If libcurl is built to use the standard system name # resolver, that portion of the connect will still use full-second # resolution for timeouts with a minimum timeout allowed of one second. # (Added in 7.16.2) # @option options :copypostfields [String] # Pass a char * as parameter, which should be the full data to post in # a HTTP POST operation. It behaves as the CURLOPT_POSTFIELDS option, # but the original data are copied by the library, allowing the # application to overwrite the original data after setting this option. # Because data are copied, care must be taken when using this option in # conjunction with CURLOPT_POSTFIELDSIZE or # CURLOPT_POSTFIELDSIZE_LARGE: If the size has not been set prior to # CURLOPT_COPYPOSTFIELDS, the data are assumed to be a NUL-terminated # string; else the stored size informs the library about the data byte # count to copy. In any case, the size must not be changed after # CURLOPT_COPYPOSTFIELDS, unless another CURLOPT_POSTFIELDS or # CURLOPT_COPYPOSTFIELDS option is issued. (Added in 7.17.1) # @option options :customrequest [String] # Pass a pointer to a zero terminated string as parameter. It can be # used to specify the request instead of GET or HEAD when performing # HTTP based requests, instead of LIST and NLST when performing FTP # directory listings and instead of LIST and RETR when issuing POP3 # based commands. This is particularly useful, for example, for # performing a HTTP DELETE request or a POP3 DELE command. # Please don't perform this at will, on HTTP based requests, by making # sure your server supports the command you are sending first. # When you change the request method by setting CURLOPT_CUSTOMREQUEST # to something, you don't actually change how libcurl behaves or acts # in regards to the particular request method, it will only change the # actual string sent in the request. # For example: # With the HTTP protocol when you tell libcurl to do a HEAD request, # but then specify a GET though a custom request libcurl will still act # as if it sent a HEAD. To switch to a proper HEAD use CURLOPT_NOBODY, # to switch to a proper POST use CURLOPT_POST or CURLOPT_POSTFIELDS and # to switch to a proper GET use CURLOPT_HTTPGET. # With the POP3 protocol when you tell libcurl to use a custom request # it will behave like a LIST or RETR command was sent where it expects # data to be returned by the server. As such CURLOPT_NOBODY should be # used when specifying commands such as DELE and NOOP for example. # Restore to the internal default by setting this to NULL. # Many people have wrongly used this option to replace the entire # request with their own, including multiple headers and POST contents. # While that might work in many cases, it will cause libcurl to send # invalid requests and it could possibly confuse the remote server # badly. Use CURLOPT_POST and CURLOPT_POSTFIELDS to set POST data. Use # CURLOPT_HTTPHEADER to replace or extend the set of headers sent by # libcurl. Use CURLOPT_HTTP_VERSION to change HTTP version. # (Support for POP3 added in 7.26.0) # @option options :dns_cache_timeout [Integer] # Pass a long, this sets the timeout in seconds. Name resolves will be # kept in memory for this number of seconds. Set to zero to completely # disable caching, or set to -1 to make the cached entries remain # forever. By default, libcurl caches this info for 60 seconds. # The name resolve functions of various libc implementations don't # re-read name server information unless explicitly told so (for # example, by calling res_init(3)). This may cause libcurl to keep # using the older server even if DHCP has updated the server info, and # this may look like a DNS cache issue to the casual libcurl-app user. # @option options :followlocation [Boolean] # A parameter set to 1 tells the library to follow any Location: header # that the server sends as part of a HTTP header. # This means that the library will re-send the same request on the new # location and follow new Location: headers all the way until no more # such headers are returned. CURLOPT_MAXREDIRS can be used to limit the # number of redirects libcurl will follow. # Since 7.19.4, libcurl can limit what protocols it will automatically # follow. The accepted protocols are set with CURLOPT_REDIR_PROTOCOLS # and it excludes the FILE protocol by default. # @option options :forbid_reuse [Boolean] # Pass a long. Set to 1 to make the next transfer explicitly close the # connection when done. Normally, libcurl keeps all connections alive # when done with one transfer in case a succeeding one follows that can # re-use them. This option should be used with caution and only if you # understand what it does. Set to 0 to have libcurl keep the connection # open for possible later re-use (default behavior). # @option options :httpauth [String] # Pass a long as parameter, which is set to a bitmask, to tell libcurl # which authentication method(s) you want it to use. The available bits # are listed below. If more than one bit is set, libcurl will first # query the site to see which authentication methods it supports and # then pick the best one you allow it to use. For some methods, this # will induce an extra network round-trip. Set the actual name and # password with the CURLOPT_USERPWD option or with the CURLOPT_USERNAME # and the CURLOPT_PASSWORD options. (Added in 7.10.6) # @option options :httpget [Boolean] # Pass a long. If the long is 1, this forces the HTTP request to get # back to GET. Usable if a POST, HEAD, PUT, or a custom request has # been used previously using the same curl handle. # When setting CURLOPT_HTTPGET to 1, it will automatically set # CURLOPT_NOBODY to 0 (since 7.14.1). # @option options :httppost [String] # Tells libcurl you want a multipart/formdata HTTP POST to be made and # you instruct what data to pass on to the server. Pass a pointer to a # linked list of curl_httppost structs as parameter. The easiest way to # create such a list, is to use curl_formadd(3) as documented. The data # in this list must remain intact until you close this curl handle # again with curl_easy_cleanup(3). # Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" # header. You can disable this header with CURLOPT_HTTPHEADER as usual. # When setting CURLOPT_HTTPPOST, it will automatically set # CURLOPT_NOBODY to 0 (since 7.14.1). # @option options :infilesize [Integer] # When uploading a file to a remote site, this option should be used to # tell libcurl what the expected size of the infile is. This value # should be passed as a long. See also CURLOPT_INFILESIZE_LARGE. # For uploading using SCP, this option or CURLOPT_INFILESIZE_LARGE is # mandatory. # When sending emails using SMTP, this command can be used to specify # the optional SIZE parameter for the MAIL FROM command. (Added in # 7.23.0) # This option does not limit how much data libcurl will actually send, # as that is controlled entirely by what the read callback returns. # @option options :interface [String] # Pass a char * as parameter. This sets the interface name to use as # outgoing network interface. The name can be an interface name, an IP # address, or a host name. # Starting with 7.24.0: If the parameter starts with "if!" then it is # treated as only as interface name and no attempt will ever be named # to do treat it as an IP address or to do name resolution on it. If # the parameter starts with "host!" it is treated as either an IP # address or a hostname. Hostnames are resolved synchronously. Using # the if! format is highly recommended when using the multi interfaces # to avoid allowing the code to block. If "if!" is specified but the # parameter does not match an existing interface, # CURLE_INTERFACE_FAILED is returned. # @option options :maxredirs [Integer] # Pass a long. The set number will be the redirection limit. If that # many redirections have been followed, the next redirect will cause an # error (CURLE_TOO_MANY_REDIRECTS). This option only makes sense if the # CURLOPT_FOLLOWLOCATION is used at the same time. Added in 7.15.1: # Setting the limit to 0 will make libcurl refuse any redirect. Set it # to -1 for an infinite number of redirects (which is the default) # @option options :nobody [Boolean] # A parameter set to 1 tells the library to not include the body-part # in the output. This is only relevant for protocols that have separate # header and body parts. On HTTP(S) servers, this will make libcurl do # a HEAD request. # To change request to GET, you should use CURLOPT_HTTPGET. Change # request to POST with CURLOPT_POST etc. # @option options :nosignal [Boolean] # Pass a long. If it is 1, libcurl will not use any functions that # install signal handlers or any functions that cause signals to be # sent to the process. This option is mainly here to allow # multi-threaded unix applications to still set/use all timeout options # etc, without risking getting signals. (Added in 7.10) # If this option is set and libcurl has been built with the standard # name resolver, timeouts will not occur while the name resolve takes # place. Consider building libcurl with c-ares support to enable # asynchronous DNS lookups, which enables nice timeouts for name # resolves without signals. # Setting CURLOPT_NOSIGNAL to 1 makes libcurl NOT ask the system to # ignore SIGPIPE signals, which otherwise are sent by the system when # trying to send data to a socket which is closed in the other end. # libcurl makes an effort to never cause such SIGPIPEs to trigger, but # some operating systems have no way to avoid them and even on those # that have there are some corner cases when they may still happen, # contrary to our desire. In addition, using CURLAUTH_NTLM_WB # authentication could cause a SIGCHLD signal to be raised. # @option options :postfieldsize [Integer] # If you want to post data to the server without letting libcurl do a # strlen() to measure the data size, this option must be used. When # this option is used you can post fully binary data, which otherwise # is likely to fail. If this size is set to -1, the library will use # strlen() to get the size. # @option options :proxy [String] # Set HTTP proxy to use. The parameter should be a char * to a zero # terminated string holding the host name or dotted IP address. To # specify port number in this string, append :[port] to the end of the # host name. The proxy string may be prefixed with [protocol]:// since # any such prefix will be ignored. The proxy's port number may # optionally be specified with the separate option. If not specified, # libcurl will default to using port 1080 for proxies. # CURLOPT_PROXYPORT. # When you tell the library to use a HTTP proxy, libcurl will # transparently convert operations to HTTP even if you specify an FTP # URL etc. This may have an impact on what other features of the # library you can use, such as CURLOPT_QUOTE and similar FTP specifics # that don't work unless you tunnel through the HTTP proxy. Such # tunneling is activated with CURLOPT_HTTPPROXYTUNNEL. # libcurl respects the environment variables http_proxy, ftp_proxy, # all_proxy etc, if any of those are set. The CURLOPT_PROXY option does # however override any possibly set environment variables. # Setting the proxy string to "" (an empty string) will explicitly # disable the use of a proxy, even if there is an environment variable # set for it. # Since 7.14.1, the proxy host string given in environment variables # can be specified the exact same way as the proxy can be set with # CURLOPT_PROXY, include protocol prefix (http://) and embedded user + # password. # Since 7.21.7, the proxy string may be specified with a protocol:// # prefix to specify alternative proxy protocols. Use socks4://, # socks4a://, socks5:// or socks5h:// (the last one to enable socks5 # and asking the proxy to do the resolving, also known as # CURLPROXY_SOCKS5_HOSTNAME type) to request the specific SOCKS version # to be used. No protocol specified, http:// and all others will be # treated as HTTP proxies. # @option options :proxyauth [String] # Pass a long as parameter, which is set to a bitmask, to tell libcurl # which authentication method(s) you want it to use for your proxy # authentication. If more than one bit is set, libcurl will first query # the site to see what authentication methods it supports and then pick # the best one you allow it to use. For some methods, this will induce # an extra network round-trip. Set the actual name and password with # the CURLOPT_PROXYUSERPWD option. The bitmask can be constructed by # or'ing together the bits listed above for the CURLOPT_HTTPAUTH # option. As of this writing, only Basic, Digest and NTLM work. (Added # in 7.10.7) # @option options :proxytype [String] # Pass a long with this option to set type of the proxy. Available # options for this are CURLPROXY_HTTP, CURLPROXY_HTTP_1_0 (added in # 7.19.4), CURLPROXY_SOCKS4 (added in 7.10), CURLPROXY_SOCKS5, # CURLPROXY_SOCKS4A (added in 7.18.0) and CURLPROXY_SOCKS5_HOSTNAME # (added in 7.18.0). The HTTP type is default. (Added in 7.10) # If you set CURLOPT_PROXYTYPE to CURLPROXY_HTTP_1_0, it will only # affect how libcurl speaks to a proxy when CONNECT is used. The HTTP # version used for "regular" HTTP requests is instead controlled with # CURLOPT_HTTP_VERSION. # @option options :proxyport [Integer] # Pass a long with this option to set the proxy port to connect to # unless it is specified in the proxy string CURLOPT_PROXY. # @option options :readdata [String] # Data pointer to pass to the file read function. If you use the # CURLOPT_READFUNCTION option, this is the pointer you'll get as input. # If you don't specify a read callback but instead rely on the default # internal read function, this data must be a valid readable FILE *. # If you're using libcurl as a win32 DLL, you MUST use a # CURLOPT_READFUNCTION if you set this option. # This option was also known by the older name CURLOPT_INFILE, # the name CURLOPT_READDATA was introduced in 7.9.7. # @option options :readfunction [String] # Pass a pointer to a function that matches the following prototype: # size_t function( void *ptr, size_t size, size_t nmemb, void # *userdata); This function gets called by libcurl as soon as it needs # to read data in order to send it to the peer. The data area pointed # at by the pointer ptr may be filled with at most size multiplied with # nmemb number of bytes. Your function must return the actual number of # bytes that you stored in that memory area. Returning 0 will signal # end-of-file to the library and cause it to stop the current transfer. # If you stop the current transfer by returning 0 "pre-maturely" (i.e # before the server expected it, like when you've said you will upload # N bytes and you upload less than N bytes), you may experience that # the server "hangs" waiting for the rest of the data that won't come. # The read callback may return CURL_READFUNC_ABORT to stop the current # operation immediately, resulting in a CURLE_ABORTED_BY_CALLBACK error # code from the transfer (Added in 7.12.1) # From 7.18.0, the function can return CURL_READFUNC_PAUSE which then # will cause reading from this connection to become paused. See # curl_easy_pause(3) for further details. # Bugs: when doing TFTP uploads, you must return the exact amount of # data that the callback wants, or it will be considered the final # packet by the server end and the transfer will end there. # If you set this callback pointer to NULL, or don't set it at all, the # default internal read function will be used. It is doing an fread() # on the FILE * userdata set with CURLOPT_READDATA. # @option options :ssl_verifyhost [Integer] # Pass a long as parameter. # This option determines whether libcurl verifies that the server cert # is for the server it is known as. # When negotiating a SSL connection, the server sends a certificate # indicating its identity. # When CURLOPT_SSL_VERIFYHOST is 2, that certificate must indicate that # the server is the server to which you meant to connect, or the # connection fails. # Curl considers the server the intended one when the Common Name field # or a Subject Alternate Name field in the certificate matches the host # name in the URL to which you told Curl to connect. # When the value is 1, the certificate must contain a Common Name # field, but it doesn't matter what name it says. (This is not # ordinarily a useful setting). # When the value is 0, the connection succeeds regardless of the names # in the certificate. # The default value for this option is 2. # This option controls checking the server's certificate's claimed # identity. The server could be lying. To control lying, see # CURLOPT_SSL_VERIFYPEER. If libcurl is built against NSS and # CURLOPT_SSL_VERIFYPEER is zero, CURLOPT_SSL_VERIFYHOST is ignored. # @option options :ssl_verifypeer [Boolean] # Pass a long as parameter. By default, curl assumes a value of 1. # This option determines whether curl verifies the authenticity of the # peer's certificate. A value of 1 means curl verifies; 0 (zero) means # it doesn't. # When negotiating a SSL connection, the server sends a certificate # indicating its identity. Curl verifies whether the certificate is # authentic, i.e. that you can trust that the server is who the # certificate says it is. This trust is based on a chain of digital # signatures, rooted in certification authority (CA) certificates you # supply. curl uses a default bundle of CA certificates (the path for # that is determined at build time) and you can specify alternate # certificates with the CURLOPT_CAINFO option or the CURLOPT_CAPATH # option. # When CURLOPT_SSL_VERIFYPEER is nonzero, and the verification fails to # prove that the certificate is authentic, the connection fails. When # the option is zero, the peer certificate verification succeeds # regardless. # Authenticating the certificate is not by itself very useful. You # typically want to ensure that the server, as authentically identified # by its certificate, is the server you mean to be talking to. Use # CURLOPT_SSL_VERIFYHOST to control that. The check that the host name # in the certificate is valid for the host name you're connecting to is # done independently of the CURLOPT_SSL_VERIFYPEER option. # @option options :sslcert [String] # Pass a pointer to a zero terminated string as parameter. The string # should be the file name of your certificate. The default format is # "PEM" and can be changed with CURLOPT_SSLCERTTYPE. # With NSS this can also be the nickname of the certificate you wish to # authenticate with. If you want to use a file from the current # directory, please precede it with "./" prefix, in order to avoid # confusion with a nickname. # @option options :sslcerttype [String] # Pass a pointer to a zero terminated string as parameter. The string # should be the format of your certificate. Supported formats are "PEM" # and "DER". (Added in 7.9.3) # @option options :sslkey [String] # Pass a pointer to a zero terminated string as parameter. The string # should be the file name of your private key. The default format is # "PEM" and can be changed with CURLOPT_SSLKEYTYPE. # @option options :sslkeytype [String] # Pass a pointer to a zero terminated string as parameter. The string # should be the format of your private key. Supported formats are # "PEM", "DER" and "ENG". # The format "ENG" enables you to load the private key from a crypto # engine. In this case CURLOPT_SSLKEY is used as an identifier passed # to the engine. You have to set the crypto engine with # CURLOPT_SSLENGINE. "DER" format key file currently does not work # because of a bug in OpenSSL. # @option options :sslversion [String] # Pass a long as parameter to control what version of SSL/TLS to # attempt to use. The available options are: # @option options :timeout [Integer] # Pass a long as parameter containing the maximum time in seconds that # you allow the libcurl transfer operation to take. Normally, name # lookups can take a considerable time and limiting operations to less # than a few minutes risk aborting perfectly normal operations. This # option will cause curl to use the SIGALRM to enable time-outing # system calls. # In unix-like systems, this might cause signals to be used unless # CURLOPT_NOSIGNAL is set. # Default timeout is 0 (zero) which means it never times out. # @option options :timeout_ms [Integer] # Like CURLOPT_TIMEOUT but takes number of milliseconds instead. If # libcurl is built to use the standard system name resolver, that # portion of the transfer will still use full-second resolution for # timeouts with a minimum timeout allowed of one second. (Added in # 7.16.2) # @option options :upload [Boolean] # A parameter set to 1 tells the library to prepare for an upload. The # CURLOPT_READDATA and CURLOPT_INFILESIZE or CURLOPT_INFILESIZE_LARGE # options are also interesting for uploads. If the protocol is HTTP, # uploading means using the PUT request unless you tell libcurl # otherwise. # Using PUT with HTTP 1.1 implies the use of a "Expect: 100-continue" # header. You can disable this header with CURLOPT_HTTPHEADER as usual. # If you use PUT to a HTTP 1.1 server, you can upload data without # knowing the size before starting the transfer if you use chunked # encoding. You enable this by adding a header like "Transfer-Encoding: # chunked" with CURLOPT_HTTPHEADER. With HTTP 1.0 or without chunked # transfer, you must specify the size. # @option options :url [String] # Pass in a pointer to the actual URL to deal with. The parameter # should be a char * to a zero terminated string which must be # URL-encoded in the following format: # scheme://host:port/path # For a greater explanation of the format please see RFC 3986. # If the given URL lacks the scheme, or protocol, part ("http://" or # "ftp://" etc), libcurl will attempt to resolve which protocol to use # based on the given host mame. If the protocol is not supported, # libcurl will return (CURLE_UNSUPPORTED_PROTOCOL) when you call # curl_easy_perform(3) or curl_multi_perform(3). Use # curl_version_info(3) for detailed information on which protocols are # supported. # The host part of the URL contains the address of the server that you # want to connect to. This can be the fully qualified domain name of # the server, the local network name of the machine on your network or # the IP address of the server or machine represented by either an IPv4 # or IPv6 address. For example: # http://www.example.com/ # http://hostname/ # http://192.168.0.1/ # http://[2001:1890:1112:1::20]/ # It is also possible to specify the user name and password as part of # the host, for some protocols, when connecting to servers that require # authentication. # For example the following types of authentication support this: # http://user:password@www.example.com # ftp://user:password@ftp.example.com # pop3://user:password@mail.example.com # The port is optional and when not specified libcurl will use the # default port based on the determined or specified protocol: 80 for # HTTP, 21 for FTP and 25 for SMTP, etc. The following examples show # how to specify the port: # http://www.example.com:8080/ - This will connect to a web server # using port 8080 rather than 80. # smtp://mail.example.com:587/ - This will connect to a SMTP server on # the alternative mail port. # The path part of the URL is protocol specific and whilst some # examples are given below this list is not conclusive: # HTTP # The path part of a HTTP request specifies the file to retrieve and # from what directory. If the directory is not specified then the web # server's root directory is used. If the file is omitted then the # default document will be retrieved for either the directory specified # or the root directory. The exact resource returned for each URL is # entirely dependent on the server's configuration. # http://www.example.com - This gets the main page from the web server. # http://www.example.com/index.html - This returns the main page by # explicitly requesting it. # http://www.example.com/contactus/ - This returns the default document # from the contactus directory. # FTP # The path part of an FTP request specifies the file to retrieve and # from what directory. If the file part is omitted then libcurl # downloads the directory listing for the directory specified. If the # directory is omitted then the directory listing for the root / home # directory will be returned. # ftp://ftp.example.com - This retrieves the directory listing for the # root directory. # ftp://ftp.example.com/readme.txt - This downloads the file readme.txt # from the root directory. # ftp://ftp.example.com/libcurl/readme.txt - This downloads readme.txt # from the libcurl directory. # ftp://user:password@ftp.example.com/readme.txt - This retrieves the # readme.txt file from the user's home directory. When a username and # password is specified, everything that is specified in the path part # is relative to the user's home directory. To retrieve files from the # root directory or a directory underneath the root directory then the # absolute path must be specified by prepending an additional forward # slash to the beginning of the path. # ftp://user:password@ftp.example.com//readme.txt - This retrieves the # readme.txt from the root directory when logging in as a specified # user. # SMTP # The path part of a SMTP request specifies the host name to present # during communication with the mail server. If the path is omitted # then libcurl will attempt to resolve the local computer's host name. # However, this may not return the fully qualified domain name that is # required by some mail servers and specifying this path allows you to # set an alternative name, such as your machine's fully qualified # domain name, which you might have obtained from an external function # such as gethostname or getaddrinfo. # smtp://mail.example.com - This connects to the mail server at # example.com and sends your local computer's host name in the HELO / # EHLO command. # smtp://mail.example.com/client.example.com - This will send # client.example.com in the HELO / EHLO command to the mail server at # example.com. # POP3 # The path part of a POP3 request specifies the mailbox (message) to # retrieve. If the mailbox is not specified then a list of waiting # messages is returned instead. # pop3://user:password@mail.example.com - This lists the available # messages pop3://user:password@mail.example.com/1 - This retrieves the # first message # SCP # The path part of a SCP request specifies the file to retrieve and # from what directory. The file part may not be omitted. The file is # taken as an absolute path from the root directory on the server. To # specify a path relative to the user's home directory on the server, # prepend ~/ to the path portion. If the user name is not embedded in # the URL, it can be set with the CURLOPT_USERPWD or CURLOPT_USERNAME # option. # scp://user@example.com/etc/issue - This specifies the file /etc/issue # scp://example.com/~/my-file - This specifies the file my-file in the # user's home directory on the server # SFTP # The path part of a SFTP request specifies the file to retrieve and # from what directory. If the file part is omitted then libcurl # downloads the directory listing for the directory specified. If the # path ends in a / then a directory listing is returned instead of a # file. If the path is omitted entirely then the directory listing for # the root / home directory will be returned. If the user name is not # embedded in the URL, it can be set with the CURLOPT_USERPWD or # CURLOPT_USERNAME option. # sftp://user:password@example.com/etc/issue - This specifies the file # /etc/issue # sftp://user@example.com/~/my-file - This specifies the file my-file # in the user's home directory # sftp://ssh.example.com/~/Documents/ - This requests a directory # listing of the Documents directory under the user's home directory # LDAP # The path part of a LDAP request can be used to specify the: # Distinguished Name, Attributes, Scope, Filter and Extension for a # LDAP search. Each field is separated by a question mark and when that # field is not required an empty string with the question mark # separator should be included. # ldap://ldap.example.com/o=My%20Organisation - This will perform a # LDAP search with the DN as My Organisation. # ldap://ldap.example.com/o=My%20Organisation?postalAddress - This will # perform the same search but will only return postalAddress attributes. # ldap://ldap.example.com/?rootDomainNamingContext - This specifies an # empty DN and requests information about the rootDomainNamingContext # attribute for an Active Directory server. # For more information about the individual components of a LDAP URL # please see RFC 4516. # NOTES # Starting with version 7.20.0, the fragment part of the URI will not # be sent as part of the path, which was previously the case. # CURLOPT_URL is the only option that must be set before # curl_easy_perform(3) is called. # CURLOPT_PROTOCOLS can be used to limit what protocols libcurl will # use for this transfer, independent of what libcurl has been compiled # to support. That may be useful if you accept the URL from an external # source and want to limit the accessibility. # @option options :useragent [String] # Pass a pointer to a zero terminated string as parameter. It will be # used to set the User-Agent: header in the http request sent to the # remote server. This can be used to fool servers or scripts. You can # also set any custom header with CURLOPT_HTTPHEADER. # @option options :userpwd [String] # Pass a char * as parameter, which should be [user name]:[password] to # use for the connection. Use CURLOPT_HTTPAUTH to decide the # authentication method. # When using NTLM, you can set the domain by prepending it to the user # name and separating the domain and name with a forward (/) or # backward slash (\). Like this: "domain/user:password" or # "domain\user:password". Some HTTP servers (on Windows) support this # style even for Basic authentication. # When using HTTP and CURLOPT_FOLLOWLOCATION, libcurl might perform # several requests to possibly different hosts. libcurl will only send # this user and password information to hosts using the initial host # name (unless CURLOPT_UNRESTRICTED_AUTH is set), so if libcurl follows # locations to other hosts it will not send the user and password to # those. This is enforced to prevent accidental information leakage. # @option options :verbose [Boolean] # Set the parameter to 1 to get the library to display a lot of verbose # information about its operations. Very useful for libcurl and/or # protocol debugging and understanding. The verbose information will be # sent to stderr, or the stream set with CURLOPT_STDERR. # You hardly ever want this set in production use, you will almost # always want this when you debug/report problems. Another neat option # for debugging is the CURLOPT_DEBUGFUNCTION. # # @return [ Easy ] A new Easy. # # @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html def initialize(options = {}) Curl.init ObjectSpace.define_finalizer(self, self.class.finalizer(self)) set_attributes(options) end # Set given options. # # @example Set options. # easy.set_attributes(options) # # @param [ Hash ] options The options. # # @raise InvalidOption # # @see initialize def set_attributes(options) options.each_pair do |key, value| unless respond_to?("#{key}=") raise Errors::InvalidOption.new(key) end method("#{key}=").call(value) end end # Reset easy. This means resetting all options and instance variables. # Also the easy handle is resetted. # # @example Reset. # easy.reset def reset (instance_variables - [:@handle, :@header_list]).each do |ivar| instance_variable_set(ivar, nil) end Curl.easy_reset(handle) end # Url escapes the value. # # @example Url escape. # easy.escape(value) # # @param [ String ] value The value to escape. # # @return [ String ] The escaped value. def escape(value) Curl.easy_escape(handle, value, 0) end # Returns the informations available through libcurl as # a hash. # # @return [ Hash ] The informations hash. def to_hash return @hash if defined?(@hash) && @hash @hash = { :return_code => return_code, :response_header => response_header, :response_body => response_body } Easy::Informations::AVAILABLE_INFORMATIONS.keys.each do |info| @hash[info] = method(info).call end @hash end # Return pretty log out. # # @example Return log out. # easy.log_inspect # # @return [ String ] The log out. def log_inspect hash = { :url => url, :response_code => response_code, :return_code => return_code, :total_time => total_time } "EASY #{hash.map{|k, v| "#{k}=#{v}"}.flatten.join(' ')}" end end end