rhack 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. data/.gemtest +0 -0
  2. data/CURB-LICENSE +51 -0
  3. data/Gemfile +4 -0
  4. data/History.txt +4 -0
  5. data/LICENSE +51 -0
  6. data/License.txt +17 -0
  7. data/Manifest.txt +61 -0
  8. data/README.txt +12 -0
  9. data/Rakefile +34 -0
  10. data/ext/curb-original/curb.c +977 -0
  11. data/ext/curb-original/curb.h +52 -0
  12. data/ext/curb-original/curb_config.h +235 -0
  13. data/ext/curb-original/curb_easy.c +3455 -0
  14. data/ext/curb-original/curb_easy.h +90 -0
  15. data/ext/curb-original/curb_errors.c +647 -0
  16. data/ext/curb-original/curb_errors.h +129 -0
  17. data/ext/curb-original/curb_macros.h +159 -0
  18. data/ext/curb-original/curb_multi.c +704 -0
  19. data/ext/curb-original/curb_multi.h +26 -0
  20. data/ext/curb-original/curb_postfield.c +523 -0
  21. data/ext/curb-original/curb_postfield.h +40 -0
  22. data/ext/curb-original/curb_upload.c +80 -0
  23. data/ext/curb-original/curb_upload.h +30 -0
  24. data/ext/curb/Makefile +157 -0
  25. data/ext/curb/curb.c +977 -0
  26. data/ext/curb/curb.h +52 -0
  27. data/ext/curb/curb_config.h +235 -0
  28. data/ext/curb/curb_easy.c +3430 -0
  29. data/ext/curb/curb_easy.h +94 -0
  30. data/ext/curb/curb_errors.c +647 -0
  31. data/ext/curb/curb_errors.h +129 -0
  32. data/ext/curb/curb_macros.h +159 -0
  33. data/ext/curb/curb_multi.c +710 -0
  34. data/ext/curb/curb_multi.h +26 -0
  35. data/ext/curb/curb_postfield.c +523 -0
  36. data/ext/curb/curb_postfield.h +40 -0
  37. data/ext/curb/curb_upload.c +80 -0
  38. data/ext/curb/curb_upload.h +30 -0
  39. data/ext/curb/extconf.rb +399 -0
  40. data/lib/cache.rb +44 -0
  41. data/lib/curl-global.rb +151 -0
  42. data/lib/extensions/browser/env.js +697 -0
  43. data/lib/extensions/browser/jquery.js +7180 -0
  44. data/lib/extensions/browser/xmlsax.js +1564 -0
  45. data/lib/extensions/browser/xmlw3cdom_1.js +1444 -0
  46. data/lib/extensions/browser/xmlw3cdom_2.js +2744 -0
  47. data/lib/extensions/curb.rb +125 -0
  48. data/lib/extensions/declarative.rb +153 -0
  49. data/lib/extensions/johnson.rb +63 -0
  50. data/lib/frame.rb +766 -0
  51. data/lib/init.rb +36 -0
  52. data/lib/rhack.rb +16 -0
  53. data/lib/rhack.yml.template +19 -0
  54. data/lib/rhack/proxy/checker.rb +226 -0
  55. data/lib/rhack/proxy/list.rb +196 -0
  56. data/lib/rhack/services.rb +445 -0
  57. data/lib/rhack_in.rb +2 -0
  58. data/lib/scout.rb +591 -0
  59. data/lib/words.rb +37 -0
  60. data/test/test_frame.rb +107 -0
  61. data/test/test_rhack.rb +5 -0
  62. data/test/test_scout.rb +53 -0
  63. metadata +195 -0
@@ -0,0 +1,52 @@
1
+ /* Curb - Libcurl(3) bindings for Ruby.
2
+ * Copyright (c)2006 Ross Bamford.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ *
5
+ * $Id: curb.h 39 2006-12-23 15:28:45Z roscopeco $
6
+ */
7
+
8
+ #ifndef __CURB_H
9
+ #define __CURB_H
10
+
11
+ #include <ruby.h>
12
+ #include <curl/curl.h>
13
+
14
+ #include "curb_config.h"
15
+ #include "curb_easy.h"
16
+ #include "curb_errors.h"
17
+ #include "curb_postfield.h"
18
+ #include "curb_multi.h"
19
+
20
+ #include "curb_macros.h"
21
+
22
+ // These should be managed from the Rake 'release' task.
23
+ #define CURB_VERSION "0.8.1"
24
+ #define CURB_VER_NUM 801
25
+ #define CURB_VER_MAJ 0
26
+ #define CURB_VER_MIN 8
27
+ #define CURB_VER_MIC 1
28
+ #define CURB_VER_PATCH 0
29
+
30
+
31
+ // Maybe not yet defined in Ruby
32
+ #ifndef RSTRING_LEN
33
+ #define RSTRING_LEN(x) RSTRING(x)->len
34
+ #endif
35
+
36
+ #ifndef RSTRING_PTR
37
+ #define RSTRING_PTR(x) RSTRING(x)->ptr
38
+ #endif
39
+
40
+ #ifndef RHASH_LEN
41
+ #ifdef HAVE_RUBY19_HASH
42
+ #define RHASH_LEN(hash) RHASH(hash)->ntbl->num_entries
43
+ #else
44
+ #define RHASH_LEN(hash) RHASH(hash)->tbl->num_entries
45
+ #endif
46
+ #endif
47
+
48
+ extern VALUE mCurl;
49
+
50
+ extern void Init_curb_core();
51
+
52
+ #endif
@@ -0,0 +1,235 @@
1
+ #ifndef CURB_CONFIG_H
2
+ #define CURB_CONFIG_H
3
+ #define HAVE_CURL_CONFIG_CA 1
4
+ #define CURL_CONFIG_CA "/etc/ssl/certs/ca-certificates.crt"
5
+ #define HAVE_CURLINFO_REDIRECT_TIME 1
6
+ #define HAVE_CURLINFO_RESPONSE_CODE 1
7
+ #define HAVE_CURLINFO_FILETIME 1
8
+ #define HAVE_CURLINFO_REDIRECT_COUNT 1
9
+ #define HAVE_CURLINFO_OS_ERRNO 1
10
+ #define HAVE_CURLINFO_NUM_CONNECTS 1
11
+ #define HAVE_CURLINFO_FTP_ENTRY_PATH 1
12
+ #define HAVE_CURL_VERSION_SSL 1
13
+ #define HAVE_CURL_VERSION_LIBZ 1
14
+ #define HAVE_CURL_VERSION_NTLM 1
15
+ #define HAVE_CURL_VERSION_GSSNEGOTIATE 1
16
+ #define HAVE_CURL_VERSION_DEBUG 1
17
+ #define HAVE_CURL_VERSION_ASYNCHDNS 1
18
+ #define HAVE_CURL_VERSION_SPNEGO 1
19
+ #define HAVE_CURL_VERSION_LARGEFILE 1
20
+ #define HAVE_CURL_VERSION_IDN 1
21
+ #define HAVE_CURL_VERSION_SSPI 1
22
+ #define HAVE_CURL_VERSION_CONV 1
23
+ #define HAVE_CURLPROXY_HTTP 1
24
+ #define HAVE_CURLPROXY_SOCKS4 1
25
+ #define HAVE_CURLPROXY_SOCKS5 1
26
+ #define HAVE_CURLAUTH_BASIC 1
27
+ #define HAVE_CURLAUTH_DIGEST 1
28
+ #define HAVE_CURLAUTH_GSSNEGOTIATE 1
29
+ #define HAVE_CURLAUTH_NTLM 1
30
+ #define HAVE_CURLAUTH_ANYSAFE 1
31
+ #define HAVE_CURLAUTH_ANY 1
32
+ #define HAVE_CURLE_TFTP_NOTFOUND 1
33
+ #define HAVE_CURLE_TFTP_PERM 1
34
+ #define HAVE_CURLE_TFTP_DISKFULL 1
35
+ #define HAVE_CURLE_TFTP_ILLEGAL 1
36
+ #define HAVE_CURLE_TFTP_UNKNOWNID 1
37
+ #define HAVE_CURLE_TFTP_EXISTS 1
38
+ #define HAVE_CURLE_TFTP_NOSUCHUSER 1
39
+ #define HAVE_CURLE_SEND_FAIL_REWIND 1
40
+ #define HAVE_CURLE_SSL_ENGINE_INITFAILED 1
41
+ #define HAVE_CURLE_LOGIN_DENIED 1
42
+ #define HAVE_CURLMOPT_MAXCONNECTS 1
43
+ #define HAVE_CURLOPT_SEEKFUNCTION 1
44
+ #define HAVE_CURLOPT_SEEKDATA 1
45
+ #define HAVE_CURLOPT_SOCKOPTFUNCTION 1
46
+ #define HAVE_CURLOPT_SOCKOPTDATA 1
47
+ #define HAVE_CURLOPT_OPENSOCKETFUNCTION 1
48
+ #define HAVE_CURLOPT_OPENSOCKETDATA 1
49
+ #define HAVE_CURLE_CONV_FAILED 1
50
+ #define HAVE_CURLE_CONV_REQD 1
51
+ #define HAVE_CURLE_SSL_CACERT_BADFILE 1
52
+ #define HAVE_CURLE_REMOTE_FILE_NOT_FOUND 1
53
+ #define HAVE_CURLE_SSH 1
54
+ #define HAVE_CURLE_SSL_SHUTDOWN_FAILED 1
55
+ #define HAVE_CURLE_AGAIN 1
56
+ #define HAVE_CURLE_SSL_CRL_BADFILE 1
57
+ #define HAVE_CURLE_SSL_ISSUER_ERROR 1
58
+ #define HAVE_CURLINFO_REDIRECT_URL 1
59
+ #define HAVE_CURLOPT_USERNAME 1
60
+ #define HAVE_CURLOPT_PASSWORD 1
61
+ #define HAVE_CURLINFO_PRIMARY_IP 1
62
+ #define HAVE_CURLAUTH_DIGEST_IE 1
63
+ #define HAVE_CURLFTPMETHOD_MULTICWD 1
64
+ #define HAVE_CURLFTPMETHOD_NOCWD 1
65
+ #define HAVE_CURLFTPMETHOD_SINGLECWD 1
66
+ #define HAVE_CURLM_BAD_SOCKET 1
67
+ #define HAVE_CURLM_UNKNOWN_OPTION 1
68
+ #define HAVE_CURL_MULTI_TIMEOUT 1
69
+ #define HAVE_CURL_MULTI_FDSET 1
70
+ #define HAVE_CURL_MULTI_PERFORM 1
71
+ #define HAVE_CURLOPT_ERRORBUFFER 1
72
+ #define HAVE_CURLOPT_STDERR 1
73
+ #define HAVE_CURLOPT_FAILONERROR 1
74
+ #define HAVE_CURLOPT_URL 1
75
+ #define HAVE_CURLOPT_PROTOCOLS 1
76
+ #define HAVE_CURLOPT_REDIR_PROTOCOLS 1
77
+ #define HAVE_CURLOPT_PROXY 1
78
+ #define HAVE_CURLOPT_PROXYPORT 1
79
+ #define HAVE_CURLOPT_PROXYTYPE 1
80
+ #define HAVE_CURLOPT_NOPROXY 1
81
+ #define HAVE_CURLOPT_HTTPPROXYTUNNEL 1
82
+ #define HAVE_CURLOPT_SOCKS5_GSSAPI_SERVICE 1
83
+ #define HAVE_CURLOPT_SOCKS5_GSSAPI_NEC 1
84
+ #define HAVE_CURLOPT_INTERFACE 1
85
+ #define HAVE_CURLOPT_LOCALPORT 1
86
+ #define HAVE_CURLOPT_DNS_CACHE_TIMEOUT 1
87
+ #define HAVE_CURLOPT_DNS_USE_GLOBAL_CACHE 1
88
+ #define HAVE_CURLOPT_BUFFERSIZE 1
89
+ #define HAVE_CURLOPT_PORT 1
90
+ #define HAVE_CURLOPT_TCP_NODELAY 1
91
+ #define HAVE_CURLOPT_ADDRESS_SCOPE 1
92
+ #define HAVE_CURLOPT_NETRC 1
93
+ #define HAVE_CURL_NETRC_OPTIONAL 1
94
+ #define HAVE_CURL_NETRC_IGNORED 1
95
+ #define HAVE_CURL_NETRC_REQUIRED 1
96
+ #define HAVE_CURLOPT_NETRC_FILE 1
97
+ #define HAVE_CURLOPT_USERPWD 1
98
+ #define HAVE_CURLOPT_PROXYUSERPWD 1
99
+ #define HAVE_CURLOPT_USERNAME 1
100
+ #define HAVE_CURLOPT_PASSWORD 1
101
+ #define HAVE_CURLOPT_PASSWORD 1
102
+ #define HAVE_CURLOPT_PASSWORD 1
103
+ #define HAVE_CURLOPT_HTTPAUTH 1
104
+ #define HAVE_CURLAUTH_DIGEST_IE 1
105
+ #define HAVE_CURLOPT_PROXYAUTH 1
106
+ #define HAVE_CURLOPT_AUTOREFERER 1
107
+ #define HAVE_CURLOPT_ENCODING 1
108
+ #define HAVE_CURLOPT_FOLLOWLOCATION 1
109
+ #define HAVE_CURLOPT_UNRESTRICTED_AUTH 1
110
+ #define HAVE_CURLOPT_MAXREDIRS 1
111
+ #define HAVE_CURLOPT_POSTREDIR 1
112
+ #define HAVE_CURLOPT_PUT 1
113
+ #define HAVE_CURLOPT_POST 1
114
+ #define HAVE_CURLOPT_POSTFIELDS 1
115
+ #define HAVE_CURLOPT_POSTFIELDSIZE 1
116
+ #define HAVE_CURLOPT_POSTFIELDSIZE_LARGE 1
117
+ #define HAVE_CURLOPT_COPYPOSTFIELDS 1
118
+ #define HAVE_CURLOPT_HTTPPOST 1
119
+ #define HAVE_CURLOPT_REFERER 1
120
+ #define HAVE_CURLOPT_USERAGENT 1
121
+ #define HAVE_CURLOPT_HTTPHEADER 1
122
+ #define HAVE_CURLOPT_HTTP200ALIASES 1
123
+ #define HAVE_CURLOPT_COOKIE 1
124
+ #define HAVE_CURLOPT_COOKIEFILE 1
125
+ #define HAVE_CURLOPT_COOKIEJAR 1
126
+ #define HAVE_CURLOPT_COOKIESESSION 1
127
+ #define HAVE_CURLOPT_COOKIELIST 1
128
+ #define HAVE_CURLOPT_HTTPGET 1
129
+ #define HAVE_CURLOPT_HTTP_VERSION 1
130
+ #define HAVE_CURL_HTTP_VERSION_NONE 1
131
+ #define HAVE_CURL_HTTP_VERSION_1_0 1
132
+ #define HAVE_CURL_HTTP_VERSION_1_1 1
133
+ #define HAVE_CURLOPT_IGNORE_CONTENT_LENGTH 1
134
+ #define HAVE_CURLOPT_HTTP_CONTENT_DECODING 1
135
+ #define HAVE_CURLOPT_HTTP_TRANSFER_DECODING 1
136
+ #define HAVE_CURLOPT_TFTP_BLKSIZE 1
137
+ #define HAVE_CURLOPT_FTPPORT 1
138
+ #define HAVE_CURLOPT_QUOTE 1
139
+ #define HAVE_CURLOPT_POSTQUOTE 1
140
+ #define HAVE_CURLOPT_PREQUOTE 1
141
+ #define HAVE_CURLOPT_DIRLISTONLY 1
142
+ #define HAVE_CURLOPT_APPEND 1
143
+ #define HAVE_CURLOPT_FTP_USE_EPRT 1
144
+ #define HAVE_CURLOPT_FTP_USE_EPSV 1
145
+ #define HAVE_CURLOPT_FTP_CREATE_MISSING_DIRS 1
146
+ #define HAVE_CURLOPT_FTP_RESPONSE_TIMEOUT 1
147
+ #define HAVE_CURLOPT_FTP_ALTERNATIVE_TO_USER 1
148
+ #define HAVE_CURLOPT_FTP_SKIP_PASV_IP 1
149
+ #define HAVE_CURLOPT_FTPSSLAUTH 1
150
+ #define HAVE_CURLFTPAUTH_DEFAULT 1
151
+ #define HAVE_CURLFTPAUTH_SSL 1
152
+ #define HAVE_CURLFTPAUTH_TLS 1
153
+ #define HAVE_CURLOPT_FTP_SSL_CCC 1
154
+ #define HAVE_CURLFTPSSL_CCC_NONE 1
155
+ #define HAVE_CURLFTPSSL_CCC_PASSIVE 1
156
+ #define HAVE_CURLFTPSSL_CCC_ACTIVE 1
157
+ #define HAVE_CURLOPT_FTP_ACCOUNT 1
158
+ #define HAVE_CURLOPT_FTP_FILEMETHOD 1
159
+ #define HAVE_CURLFTPMETHOD_MULTICWD 1
160
+ #define HAVE_CURLFTPMETHOD_NOCWD 1
161
+ #define HAVE_CURLFTPMETHOD_SINGLECWD 1
162
+ #define HAVE_CURLOPT_TRANSFERTEXT 1
163
+ #define HAVE_CURLOPT_PROXY_TRANSFER_MODE 1
164
+ #define HAVE_CURLOPT_CRLF 1
165
+ #define HAVE_CURLOPT_RANGE 1
166
+ #define HAVE_CURLOPT_RESUME_FROM 1
167
+ #define HAVE_CURLOPT_RESUME_FROM_LARGE 1
168
+ #define HAVE_CURLOPT_CUSTOMREQUEST 1
169
+ #define HAVE_CURLOPT_FILETIME 1
170
+ #define HAVE_CURLOPT_NOBODY 1
171
+ #define HAVE_CURLOPT_INFILESIZE 1
172
+ #define HAVE_CURLOPT_INFILESIZE_LARGE 1
173
+ #define HAVE_CURLOPT_UPLOAD 1
174
+ #define HAVE_CURLOPT_MAXFILESIZE 1
175
+ #define HAVE_CURLOPT_MAXFILESIZE_LARGE 1
176
+ #define HAVE_CURLOPT_TIMECONDITION 1
177
+ #define HAVE_CURLOPT_TIMEVALUE 1
178
+ #define HAVE_CURLOPT_TIMEOUT 1
179
+ #define HAVE_CURLOPT_TIMEOUT_MS 1
180
+ #define HAVE_CURLOPT_LOW_SPEED_LIMIT 1
181
+ #define HAVE_CURLOPT_LOW_SPEED_TIME 1
182
+ #define HAVE_CURLOPT_MAX_SEND_SPEED_LARGE 1
183
+ #define HAVE_CURLOPT_MAX_RECV_SPEED_LARGE 1
184
+ #define HAVE_CURLOPT_MAXCONNECTS 1
185
+ #define HAVE_CURLOPT_CLOSEPOLICY 1
186
+ #define HAVE_CURLOPT_FRESH_CONNECT 1
187
+ #define HAVE_CURLOPT_FORBID_REUSE 1
188
+ #define HAVE_CURLOPT_CONNECTTIMEOUT 1
189
+ #define HAVE_CURLOPT_CONNECTTIMEOUT_MS 1
190
+ #define HAVE_CURLOPT_IPRESOLVE 1
191
+ #define HAVE_CURL_IPRESOLVE_WHATEVER 1
192
+ #define HAVE_CURL_IPRESOLVE_V4 1
193
+ #define HAVE_CURL_IPRESOLVE_V6 1
194
+ #define HAVE_CURLOPT_CONNECT_ONLY 1
195
+ #define HAVE_CURLOPT_USE_SSL 1
196
+ #define HAVE_CURLUSESSL_NONE 1
197
+ #define HAVE_CURLUSESSL_TRY 1
198
+ #define HAVE_CURLUSESSL_CONTROL 1
199
+ #define HAVE_CURLUSESSL_ALL 1
200
+ #define HAVE_CURLOPT_SSLCERT 1
201
+ #define HAVE_CURLOPT_SSLCERTTYPE 1
202
+ #define HAVE_CURLOPT_SSLKEY 1
203
+ #define HAVE_CURLOPT_SSLKEYTYPE 1
204
+ #define HAVE_CURLOPT_KEYPASSWD 1
205
+ #define HAVE_CURLOPT_SSLENGINE 1
206
+ #define HAVE_CURLOPT_SSLENGINE_DEFAULT 1
207
+ #define HAVE_CURLOPT_SSLVERSION 1
208
+ #define HAVE_CURL_SSLVERSION_DEFAULT 1
209
+ #define HAVE_CURL_SSLVERSION_TLSV1 1
210
+ #define HAVE_CURL_SSLVERSION_SSLV2 1
211
+ #define HAVE_CURL_SSLVERSION_SSLV3 1
212
+ #define HAVE_CURLOPT_SSL_VERIFYPEER 1
213
+ #define HAVE_CURLOPT_CAINFO 1
214
+ #define HAVE_CURLOPT_ISSUERCERT 1
215
+ #define HAVE_CURLOPT_CAPATH 1
216
+ #define HAVE_CURLOPT_CRLFILE 1
217
+ #define HAVE_CURLOPT_SSL_VERIFYHOST 1
218
+ #define HAVE_CURLOPT_CERTINFO 1
219
+ #define HAVE_CURLOPT_RANDOM_FILE 1
220
+ #define HAVE_CURLOPT_EGDSOCKET 1
221
+ #define HAVE_CURLOPT_SSL_CIPHER_LIST 1
222
+ #define HAVE_CURLOPT_SSL_SESSIONID_CACHE 1
223
+ #define HAVE_CURLOPT_KRBLEVEL 1
224
+ #define HAVE_CURLOPT_SSH_AUTH_TYPES 1
225
+ #define HAVE_CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 1
226
+ #define HAVE_CURLOPT_SSH_PUBLIC_KEYFILE 1
227
+ #define HAVE_CURLOPT_SSH_PRIVATE_KEYFILE 1
228
+ #define HAVE_CURLOPT_PRIVATE 1
229
+ #define HAVE_CURLOPT_SHARE 1
230
+ #define HAVE_CURLOPT_NEW_FILE_PERMS 1
231
+ #define HAVE_CURLOPT_NEW_DIRECTORY_PERMS 1
232
+ #define HAVE_CURLOPT_TELNETOPTIONS 1
233
+ #define HAVE_CURLE_OBSOLETE 1
234
+ #define HAVE_CURL_EASY_ESCAPE 1
235
+ #endif
@@ -0,0 +1,3455 @@
1
+ /* curb_easy.c - Curl easy mode
2
+ * Copyright (c)2006 Ross Bamford.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ *
5
+ * $Id: curb_easy.c 30 2006-12-09 12:30:24Z roscopeco $
6
+ */
7
+ #include "curb_easy.h"
8
+ #include "curb_errors.h"
9
+ #include "curb_postfield.h"
10
+ #include "curb_upload.h"
11
+ #include "curb_multi.h"
12
+
13
+ #include <errno.h>
14
+ #include <string.h>
15
+
16
+ extern VALUE mCurl;
17
+
18
+ static VALUE idCall;
19
+ static VALUE idJoin;
20
+ static VALUE rbstrAmp;
21
+
22
+ #ifdef RDOC_NEVER_DEFINED
23
+ mCurl = rb_define_module("Curl");
24
+ #endif
25
+
26
+ VALUE cCurlEasy;
27
+
28
+
29
+ /* ================== CURL HANDLER FUNCS ==============*/
30
+
31
+ static VALUE callback_exception(VALUE unused) {
32
+ return Qfalse;
33
+ }
34
+
35
+ /* These handle both body and header data */
36
+ static size_t default_data_handler(char *stream,
37
+ size_t size,
38
+ size_t nmemb,
39
+ VALUE out) {
40
+ rb_str_buf_cat(out, stream, size * nmemb);
41
+ return size * nmemb;
42
+ }
43
+
44
+ // size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
45
+ static size_t read_data_handler(void *ptr,
46
+ size_t size,
47
+ size_t nmemb,
48
+ ruby_curl_easy *rbce) {
49
+ VALUE upload = rb_easy_get("upload");
50
+ size_t read_bytes = (size*nmemb);
51
+ VALUE stream = ruby_curl_upload_stream_get(upload);
52
+
53
+ if (rb_respond_to(stream, rb_intern("read"))) {//if (rb_respond_to(stream, rb_intern("to_s"))) {
54
+ /* copy read_bytes from stream into ptr */
55
+ VALUE str = rb_funcall(stream, rb_intern("read"), 1, rb_int_new(read_bytes) );
56
+ if( str != Qnil ) {
57
+ memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
58
+ return RSTRING_LEN(str);
59
+ }
60
+ else {
61
+ return 0;
62
+ }
63
+ }
64
+ else if (rb_respond_to(stream, rb_intern("to_s"))) {
65
+ ruby_curl_upload *rbcu;
66
+ VALUE str;
67
+ size_t len;
68
+ size_t remaining;
69
+ char *str_ptr;
70
+ Data_Get_Struct(upload, ruby_curl_upload, rbcu);
71
+ str = rb_funcall(stream, rb_intern("to_s"), 0);
72
+ len = RSTRING_LEN(str);
73
+ remaining = len - rbcu->offset;
74
+ str_ptr = RSTRING_PTR(str);
75
+
76
+ if( remaining < read_bytes ) {
77
+ if( remaining > 0 ) {
78
+ memcpy(ptr, str_ptr+rbcu->offset, remaining);
79
+ read_bytes = remaining;
80
+ rbcu->offset += remaining;
81
+ }
82
+ return remaining;
83
+ }
84
+ else if( remaining > read_bytes ) { // read_bytes <= remaining - send what we can fit in the buffer(ptr)
85
+ memcpy(ptr, str_ptr+rbcu->offset, read_bytes);
86
+ rbcu->offset += read_bytes;
87
+ }
88
+ else { // they're equal
89
+ memcpy(ptr, str_ptr+rbcu->offset, --read_bytes);
90
+ rbcu->offset += read_bytes;
91
+ }
92
+ return read_bytes;
93
+ }
94
+ else {
95
+ return 0;
96
+ }
97
+ }
98
+
99
+ static size_t proc_data_handler(char *stream,
100
+ size_t size,
101
+ size_t nmemb,
102
+ VALUE proc) {
103
+ VALUE procret;
104
+
105
+ procret = rb_funcall(proc, idCall, 1, rb_str_new(stream, size * nmemb));
106
+
107
+ switch (rb_type(procret)) {
108
+ case T_FIXNUM:
109
+ return FIX2LONG(procret);
110
+ case T_BIGNUM:
111
+ return NUM2LONG(procret);
112
+ default:
113
+ rb_warn("Curl data handlers should return the number of bytes read as an Integer");
114
+ return size * nmemb;
115
+ }
116
+ }
117
+
118
+ static size_t proc_data_handler_body(char *stream,
119
+ size_t size,
120
+ size_t nmemb,
121
+ ruby_curl_easy *rbce)
122
+ {
123
+ size_t ret;
124
+ rbce->callback_active = 1;
125
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("body_proc"));
126
+ rbce->callback_active = 0;
127
+ return ret;
128
+ }
129
+ static size_t proc_data_handler_header(char *stream,
130
+ size_t size,
131
+ size_t nmemb,
132
+ ruby_curl_easy *rbce)
133
+ {
134
+ size_t ret;
135
+ rbce->callback_active = 1;
136
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("header_proc"));
137
+ rbce->callback_active = 0;
138
+ return ret;
139
+ }
140
+
141
+
142
+ static VALUE call_progress_handler(VALUE ary) {
143
+ return rb_funcall(rb_ary_entry(ary, 0), idCall, 4,
144
+ rb_ary_entry(ary, 1), // rb_float_new(dltotal),
145
+ rb_ary_entry(ary, 2), // rb_float_new(dlnow),
146
+ rb_ary_entry(ary, 3), // rb_float_new(ultotal),
147
+ rb_ary_entry(ary, 4)); // rb_float_new(ulnow));
148
+ }
149
+
150
+ static int proc_progress_handler(VALUE proc,
151
+ double dltotal,
152
+ double dlnow,
153
+ double ultotal,
154
+ double ulnow) {
155
+ VALUE procret;
156
+ VALUE callargs = rb_ary_new2(5);
157
+
158
+ rb_ary_store(callargs, 0, proc);
159
+ rb_ary_store(callargs, 1, rb_float_new(dltotal));
160
+ rb_ary_store(callargs, 2, rb_float_new(dlnow));
161
+ rb_ary_store(callargs, 3, rb_float_new(ultotal));
162
+ rb_ary_store(callargs, 4, rb_float_new(ulnow));
163
+
164
+ //v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
165
+ //procret = rb_funcall(proc, idCall, 4, rb_float_new(dltotal),
166
+ // rb_float_new(dlnow),
167
+ // rb_float_new(ultotal),
168
+ // rb_float_new(ulnow));
169
+ procret = rb_rescue(call_progress_handler, callargs, callback_exception, Qnil);
170
+
171
+ return(((procret == Qfalse) || (procret == Qnil)) ? -1 : 0);
172
+ }
173
+
174
+ static VALUE call_debug_handler(VALUE ary) {
175
+ return rb_funcall(rb_ary_entry(ary, 0), idCall, 2,
176
+ rb_ary_entry(ary, 1), // INT2FIX(type),
177
+ rb_ary_entry(ary, 2)); // rb_str_new(data, data_len)
178
+ }
179
+ static int proc_debug_handler(CURL *curl,
180
+ curl_infotype type,
181
+ char *data,
182
+ size_t data_len,
183
+ VALUE proc) {
184
+ VALUE callargs = rb_ary_new2(3);
185
+ rb_ary_store(callargs, 0, proc);
186
+ rb_ary_store(callargs, 1, INT2FIX(type));
187
+ rb_ary_store(callargs, 2, rb_str_new(data, data_len));
188
+ rb_rescue(call_debug_handler, callargs, callback_exception, Qnil);
189
+ /* no way to indicate to libcurl that we should break out given an exception in the on_debug handler...
190
+ * this means exceptions will be swallowed
191
+ */
192
+ //rb_funcall(proc, idCall, 2, INT2FIX(type), rb_str_new(data, data_len));
193
+ return 0;
194
+ }
195
+
196
+ /* ================== MARK/FREE FUNC ==================*/
197
+ void curl_easy_mark(ruby_curl_easy *rbce) {
198
+ if (!NIL_P(rbce->opts)) { rb_gc_mark(rbce->opts); }
199
+ if (!NIL_P(rbce->multi)) { rb_gc_mark(rbce->multi); }
200
+ }
201
+
202
+ static void ruby_curl_easy_free(ruby_curl_easy *rbce) {
203
+ if (rbce->curl_headers) {
204
+ curl_slist_free_all(rbce->curl_headers);
205
+ }
206
+
207
+ if (rbce->curl_ftp_commands) {
208
+ curl_slist_free_all(rbce->curl_ftp_commands);
209
+ }
210
+
211
+ if (rbce->curl) {
212
+ curl_easy_cleanup(rbce->curl);
213
+ }
214
+
215
+ if (rbce->first) {
216
+ curl_formfree(rbce->first);
217
+ }
218
+ }
219
+
220
+ void curl_easy_free(ruby_curl_easy *rbce) {
221
+ ruby_curl_easy_free(rbce);
222
+ free(rbce);
223
+ }
224
+
225
+
226
+ /* ================= ALLOC METHODS ====================*/
227
+
228
+ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
229
+ rbce->opts = rb_hash_new();
230
+
231
+ rbce->curl_headers = NULL;
232
+ rbce->curl_ftp_commands = NULL;
233
+
234
+ /* various-typed opts */
235
+ rbce->local_port = 0;
236
+ rbce->local_port_range = 0;
237
+ rbce->proxy_port = 0;
238
+ rbce->proxy_type = -1;
239
+ rbce->http_auth_types = 0;
240
+ rbce->proxy_auth_types = 0;
241
+ rbce->max_redirs = -1;
242
+ rbce->timeout = 0;
243
+ rbce->connect_timeout = 0;
244
+ rbce->dns_cache_timeout = 60;
245
+ rbce->ftp_response_timeout = 0;
246
+ rbce->low_speed_limit = 0;
247
+ rbce->low_speed_time = 0;
248
+ rbce->ssl_version = -1;
249
+ rbce->use_ssl = -1;
250
+ rbce->ftp_filemethod = -1;
251
+ rbce->resolve_mode = CURL_IPRESOLVE_WHATEVER;
252
+
253
+ /* bool opts */
254
+ rbce->proxy_tunnel = 0;
255
+ rbce->fetch_file_time = 0;
256
+ rbce->ssl_verify_peer = 1;
257
+ rbce->ssl_verify_host = 2;
258
+ rbce->header_in_body = 0;
259
+ rbce->use_netrc = 0;
260
+ rbce->follow_location = 0;
261
+ rbce->unrestricted_auth = 0;
262
+ rbce->verbose = 0;
263
+ rbce->multipart_form_post = 0;
264
+ rbce->enable_cookies = 0;
265
+ rbce->ignore_content_length = 0;
266
+ rbce->callback_active = 0;
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * Curl::Easy.new => #&lt;Curl::Easy...&gt;
272
+ * Curl::Easy.new(url = nil) => #&lt;Curl::Easy...&gt;
273
+ * Curl::Easy.new(url = nil) { |self| ... } => #&lt;Curl::Easy...&gt;
274
+ *
275
+ * Create a new Curl::Easy instance, optionally supplying the URL.
276
+ * The block form allows further configuration to be supplied before
277
+ * the instance is returned.
278
+ */
279
+ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
280
+ CURLcode ecode;
281
+ VALUE url, blk;
282
+ VALUE new_curl;
283
+ ruby_curl_easy *rbce;
284
+
285
+ rb_scan_args(argc, argv, "01&", &url, &blk);
286
+
287
+ rbce = ALLOC(ruby_curl_easy);
288
+
289
+ /* handler */
290
+ rbce->curl = curl_easy_init();
291
+ if (!rbce->curl) {
292
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
293
+ }
294
+
295
+ new_curl = Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
296
+
297
+ rbce->multi = Qnil;
298
+ rbce->opts = Qnil;
299
+
300
+ ruby_curl_easy_zero(rbce);
301
+
302
+ rb_easy_set("url", url);
303
+
304
+ /* set the new_curl pointer to the curl handle */
305
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)new_curl);
306
+ if (ecode != CURLE_OK) {
307
+ raise_curl_easy_error_exception(ecode);
308
+ }
309
+
310
+ if (blk != Qnil) {
311
+ rb_funcall(blk, idCall, 1, new_curl);
312
+ }
313
+
314
+ return new_curl;
315
+ }
316
+
317
+ /*
318
+ * call-seq:
319
+ * easy.clone => #&lt;easy clone&gt;
320
+ * easy.dup => #&lt;easy clone&gt;
321
+ *
322
+ * Clone this Curl::Easy instance, creating a new instance.
323
+ * This method duplicates the underlying CURL* handle.
324
+ */
325
+ static VALUE ruby_curl_easy_clone(VALUE self) {
326
+ ruby_curl_easy *rbce, *newrbce;
327
+
328
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
329
+
330
+ newrbce = ALLOC(ruby_curl_easy);
331
+ memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
332
+ newrbce->curl = curl_easy_duphandle(rbce->curl);
333
+ newrbce->curl_headers = NULL;
334
+ newrbce->curl_ftp_commands = NULL;
335
+
336
+ return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
337
+ }
338
+
339
+ /*
340
+ * call-seq:
341
+ * easy.close => nil
342
+ *
343
+ * Close the Curl::Easy instance. Any open connections are closed
344
+ * The easy handle is reinitialized. If a previous multi handle was
345
+ * open it is set to nil and will be cleared after a GC.
346
+ */
347
+ static VALUE ruby_curl_easy_close(VALUE self) {
348
+ CURLcode ecode;
349
+ ruby_curl_easy *rbce;
350
+
351
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
352
+
353
+ if (rbce->callback_active) {
354
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
355
+ }
356
+
357
+ ruby_curl_easy_free(rbce);
358
+
359
+ /* reinit the handle */
360
+ rbce->curl = curl_easy_init();
361
+ if (!rbce->curl) {
362
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
363
+ }
364
+
365
+ rbce->multi = Qnil;
366
+
367
+ ruby_curl_easy_zero(rbce);
368
+
369
+ /* give the new curl handle a reference back to the ruby object */
370
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
371
+ if (ecode != CURLE_OK) {
372
+ raise_curl_easy_error_exception(ecode);
373
+ }
374
+
375
+ return Qnil;
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * easy.reset => Hash
381
+ *
382
+ * Reset the Curl::Easy instance, clears out all settings.
383
+ *
384
+ * from http://curl.haxx.se/libcurl/c/curl_easy_reset.html
385
+ * Re-initializes all options previously set on a specified CURL handle to the default values. This puts back the handle to the same state as it was in when it was just created with curl_easy_init(3).
386
+ * It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares.
387
+ *
388
+ * The return value contains all settings stored.
389
+ */
390
+ static VALUE ruby_curl_easy_reset(VALUE self) {
391
+ CURLcode ecode;
392
+ ruby_curl_easy *rbce;
393
+ VALUE opts_dup;
394
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
395
+
396
+ if (rbce->callback_active) {
397
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
398
+ }
399
+
400
+ opts_dup = rb_funcall(rbce->opts, rb_intern("dup"), 0);
401
+
402
+ curl_easy_reset(rbce->curl);
403
+ ruby_curl_easy_zero(rbce);
404
+
405
+ /* rest clobbers the private setting, so reset it to self */
406
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
407
+ if (ecode != CURLE_OK) {
408
+ raise_curl_easy_error_exception(ecode);
409
+ }
410
+
411
+ /* Free everything up */
412
+ if (rbce->curl_headers) {
413
+ curl_slist_free_all(rbce->curl_headers);
414
+ rbce->curl_headers = NULL;
415
+ }
416
+
417
+ return opts_dup;
418
+ }
419
+
420
+
421
+ /* ================ OBJ ATTRIBUTES ==================*/
422
+
423
+ /*
424
+ * call-seq:
425
+ * easy.url => string
426
+ *
427
+ * Obtain the URL that will be used by subsequent calls to +perform+.
428
+ */
429
+ static VALUE ruby_curl_easy_url_get(VALUE self) {
430
+ CURB_OBJECT_HGETTER(ruby_curl_easy, url);
431
+ }
432
+
433
+ /*
434
+ * call-seq:
435
+ * easy.proxy_url => string
436
+ *
437
+ * Obtain the HTTP Proxy URL that will be used by subsequent calls to +perform+.
438
+ */
439
+ static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
440
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxy_url);
441
+ }
442
+
443
+ /*
444
+ * call-seq:
445
+ * easy.headers = "Header: val" => "Header: val"
446
+ * easy.headers = {"Header" => "val" ..., "Header" => "val"} => {"Header: val", ...}
447
+ * easy.headers = ["Header: val" ..., "Header: val"] => ["Header: val", ...]
448
+ *
449
+ * Set custom HTTP headers for following requests. This can be used to add
450
+ * custom headers, or override standard headers used by libcurl. It defaults to a
451
+ * Hash.
452
+ *
453
+ * For example to set a standard or custom header:
454
+ *
455
+ * easy.headers["MyHeader"] = "myval"
456
+ *
457
+ * To remove a standard header (this is useful when removing libcurls default
458
+ * 'Expect: 100-Continue' header when using HTTP form posts):
459
+ *
460
+ * easy.headers["Expect"] = ''
461
+ *
462
+ * Anything passed to libcurl as a header will be converted to a string during
463
+ * the perform step.
464
+ */
465
+ static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
466
+ CURB_OBJECT_HSETTER(ruby_curl_easy, headers);
467
+ }
468
+
469
+ /*
470
+ * call-seq:
471
+ * easy.headers => Hash, Array or Str
472
+ *
473
+ * Obtain the custom HTTP headers for following requests.
474
+ */
475
+ static VALUE ruby_curl_easy_headers_get(VALUE self) {
476
+ ruby_curl_easy *rbce;
477
+ VALUE headers;
478
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
479
+ headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
480
+ if (headers == Qnil) { headers = rb_easy_set("headers", rb_hash_new()); }
481
+ return headers;
482
+ }
483
+
484
+ /*
485
+ * call-seq:
486
+ * easy.interface => string
487
+ *
488
+ * Obtain the interface name that is used as the outgoing network interface.
489
+ * The name can be an interface name, an IP address or a host name.
490
+ */
491
+ static VALUE ruby_curl_easy_interface_get(VALUE self) {
492
+ CURB_OBJECT_HGETTER(ruby_curl_easy, interface_hm);
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * easy.userpwd => string
498
+ *
499
+ * Obtain the username/password string that will be used for subsequent
500
+ * calls to +perform+.
501
+ */
502
+ static VALUE ruby_curl_easy_userpwd_get(VALUE self) {
503
+ CURB_OBJECT_HGETTER(ruby_curl_easy, userpwd);
504
+ }
505
+
506
+ /*
507
+ * call-seq:
508
+ * easy.proxypwd => string
509
+ *
510
+ * Obtain the username/password string that will be used for proxy
511
+ * connection during subsequent calls to +perform+. The supplied string
512
+ * should have the form "username:password"
513
+ */
514
+ static VALUE ruby_curl_easy_proxypwd_get(VALUE self) {
515
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxypwd);
516
+ }
517
+
518
+ /*
519
+ * call-seq:
520
+ * easy.cookies => "name1=content1; name2=content2;"
521
+ *
522
+ * Obtain the cookies for this Curl::Easy instance.
523
+ */
524
+ static VALUE ruby_curl_easy_cookies_get(VALUE self) {
525
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookies);
526
+ }
527
+
528
+ /*
529
+ * call-seq:
530
+ * easy.cookiefile => string
531
+ *
532
+ * Obtain the cookiefile file for this Curl::Easy instance.
533
+ */
534
+ static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
535
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiefile);
536
+ }
537
+
538
+ /*
539
+ * call-seq:
540
+ * easy.cookiejar => string
541
+ *
542
+ * Obtain the cookiejar file to use for this Curl::Easy instance.
543
+ */
544
+ static VALUE ruby_curl_easy_cookiejar_get(VALUE self) {
545
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiejar);
546
+ }
547
+
548
+ /*
549
+ * call-seq:
550
+ * easy.cert = string => ""
551
+ *
552
+ * Set a cert file to use for this Curl::Easy instance. This file
553
+ * will be used to validate SSL connections.
554
+ *
555
+ */
556
+ static VALUE ruby_curl_easy_cert_set(VALUE self, VALUE cert) {
557
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert);
558
+ }
559
+
560
+ /*
561
+ * call-seq:
562
+ * easy.cert => string
563
+ *
564
+ * Obtain the cert file to use for this Curl::Easy instance.
565
+ */
566
+ static VALUE ruby_curl_easy_cert_get(VALUE self) {
567
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert);
568
+ }
569
+
570
+ /*
571
+ * call-seq:
572
+ * easy.cert_key = "cert_key.file" => ""
573
+ *
574
+ * Set a cert key to use for this Curl::Easy instance. This file
575
+ * will be used to validate SSL certificates.
576
+ *
577
+ */
578
+ static VALUE ruby_curl_easy_cert_key_set(VALUE self, VALUE cert_key) {
579
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert_key);
580
+ }
581
+
582
+ /*
583
+ * call-seq:
584
+ * easy.cert_key => "cert_key.file"
585
+ *
586
+ * Obtain the cert key file to use for this Curl::Easy instance.
587
+ */
588
+ static VALUE ruby_curl_easy_cert_key_get(VALUE self) {
589
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert_key);
590
+ }
591
+
592
+ /*
593
+ * call-seq:
594
+ * easy.cacert = string => ""
595
+ *
596
+ * Set a cacert bundle to use for this Curl::Easy instance. This file
597
+ * will be used to validate SSL certificates.
598
+ *
599
+ */
600
+ static VALUE ruby_curl_easy_cacert_set(VALUE self, VALUE cacert) {
601
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cacert);
602
+ }
603
+
604
+ /*
605
+ * call-seq:
606
+ * easy.cacert => string
607
+ *
608
+ * Obtain the cacert file to use for this Curl::Easy instance.
609
+ */
610
+ static VALUE ruby_curl_easy_cacert_get(VALUE self) {
611
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cacert);
612
+ }
613
+
614
+ /*
615
+ * call-seq:
616
+ * easy.certpassword = string => ""
617
+ *
618
+ * Set a password used to open the specified cert
619
+ */
620
+ static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
621
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certpassword);
622
+ }
623
+
624
+ /*
625
+ * call-seq:
626
+ * easy.certtype = "PEM|DER" => ""
627
+ *
628
+ * Set a cert type to use for this Curl::Easy instance.
629
+ * Default is PEM
630
+ *
631
+ */
632
+ static VALUE ruby_curl_easy_certtype_set(VALUE self, VALUE certtype) {
633
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certtype);
634
+ }
635
+
636
+ /*
637
+ * call-seq:
638
+ * easy.certtype => string
639
+ *
640
+ * Obtain the cert type used for this Curl::Easy instance
641
+ */
642
+ static VALUE ruby_curl_easy_certtype_get(VALUE self) {
643
+ CURB_OBJECT_HGETTER(ruby_curl_easy, certtype);
644
+ }
645
+
646
+ /*
647
+ * call-seq:
648
+ * easy.encoding = string => string
649
+ *
650
+ * Set the accepted encoding types, curl will handle all of the decompression
651
+ *
652
+ */
653
+ static VALUE ruby_curl_easy_encoding_set(VALUE self, VALUE encoding) {
654
+ CURB_OBJECT_HSETTER(ruby_curl_easy, encoding);
655
+ }
656
+ /*
657
+ * call-seq:
658
+ * easy.encoding => string
659
+ *
660
+ * Get the set encoding types
661
+ *
662
+ */
663
+ static VALUE ruby_curl_easy_encoding_get(VALUE self) {
664
+ CURB_OBJECT_HGETTER(ruby_curl_easy, encoding);
665
+ }
666
+
667
+ /*
668
+ * call-seq:
669
+ * easy.useragent = "Ruby/Curb" => ""
670
+ *
671
+ * Set the user agent string for this Curl::Easy instance
672
+ *
673
+ */
674
+ static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
675
+ CURB_OBJECT_HSETTER(ruby_curl_easy, useragent);
676
+ }
677
+
678
+ /*
679
+ * call-seq:
680
+ * easy.useragent => "Ruby/Curb"
681
+ *
682
+ * Obtain the user agent string used for this Curl::Easy instance
683
+ */
684
+ static VALUE ruby_curl_easy_useragent_get(VALUE self) {
685
+ CURB_OBJECT_HGETTER(ruby_curl_easy, useragent);
686
+ }
687
+
688
+ /*
689
+ * call-seq:
690
+ * easy.post_body = "some=form%20data&to=send" => string or nil
691
+ *
692
+ * Sets the POST body of this Curl::Easy instance. This is expected to be
693
+ * URL encoded; no additional processing or encoding is done on the string.
694
+ * The content-type header will be set to application/x-www-form-urlencoded.
695
+ *
696
+ * This is handy if you want to perform a POST against a Curl::Multi instance.
697
+ */
698
+ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
699
+ ruby_curl_easy *rbce;
700
+ CURL *curl;
701
+
702
+ char *data;
703
+ long len;
704
+
705
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
706
+
707
+ curl = rbce->curl;
708
+ if (rbce->first) {
709
+ curl_formfree(rbce->first);
710
+ rbce->first = NULL;
711
+ rbce->last = NULL;
712
+ }
713
+ rbce->multipart_form_post = 0;
714
+ if ( post_body == Qnil ) {
715
+ //rbce->postdata_buffer = Qnil;
716
+ rb_easy_del("postdata_buffer");
717
+ } else {
718
+ if (rb_type(post_body) == T_STRING) {
719
+ data = StringValuePtr(post_body);
720
+ len = RSTRING_LEN(post_body);
721
+ }
722
+ else if (rb_respond_to(post_body, rb_intern("to_s"))) {
723
+ VALUE str_body = rb_funcall(post_body, rb_intern("to_s"), 0);
724
+ data = StringValuePtr(str_body);
725
+ len = RSTRING_LEN(post_body);
726
+ }
727
+ else {
728
+ rb_raise(rb_eRuntimeError, "post data must respond_to .to_s");
729
+ }
730
+
731
+ // Store the string, since it has to hang around for the duration of the
732
+ // request. See CURLOPT_POSTFIELDS in the libcurl docs.
733
+ //rbce->postdata_buffer = post_body;
734
+ rb_easy_set("postdata_buffer", post_body);
735
+
736
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
737
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
738
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
739
+
740
+ return post_body;
741
+ }
742
+
743
+ return Qnil;
744
+ }
745
+ static VALUE ruby_curl_easy_multipart_post_body_set(VALUE self, VALUE ary) {
746
+ ruby_curl_easy *rbce;
747
+ CURL *curl;
748
+ int i;
749
+
750
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
751
+ curl = rbce->curl;
752
+ if (rbce->first) {
753
+ curl_formfree(rbce->first);
754
+ rbce->first = NULL;
755
+ rbce->last = NULL;
756
+ }
757
+
758
+ // Make the multipart form
759
+ rbce->multipart_form_post = 1;
760
+ for (i=0; i<RARRAY_LEN(ary); i++) {
761
+ if (rb_obj_is_instance_of(RARRAY_PTR(ary)[i], cCurlPostField)) {
762
+ append_to_form(RARRAY_PTR(ary)[i], &(rbce->first), &(rbce->last));
763
+ }
764
+ else {
765
+ if (rbce->first) {
766
+ curl_formfree(rbce->first);
767
+ rbce->first = NULL;
768
+ rbce->last = NULL;
769
+ }
770
+ rb_raise(eCurlErrInvalidPostField, "You must use only PostFields with multipart form posts");
771
+ return Qnil;
772
+ }
773
+ }
774
+ //rbce->postdata_buffer = ary;
775
+ rb_easy_set("postdata_buffer", post_body);
776
+
777
+ curl_easy_setopt(curl, CURLOPT_POST, 0);
778
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, rbce->first);
779
+ return Qnil;
780
+ }
781
+
782
+ /*
783
+ * call-seq:
784
+ * easy.post_body => string or nil
785
+ *
786
+ * Obtain the POST body used in this Curl::Easy instance.
787
+ */
788
+ static VALUE ruby_curl_easy_post_body_get(VALUE self) {
789
+ CURB_OBJECT_HGETTER(ruby_curl_easy, postdata_buffer);
790
+ }
791
+
792
+ /*
793
+ * call-seq:
794
+ * easy.put_data = data => ""
795
+ *
796
+ * Points this Curl::Easy instance to data to be uploaded via PUT. This
797
+ * sets the request to a PUT type request - useful if you want to PUT via
798
+ * a multi handle.
799
+ */
800
+ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
801
+ ruby_curl_easy *rbce;
802
+ CURL *curl;
803
+ VALUE upload;
804
+ VALUE headers;
805
+
806
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
807
+
808
+ upload = ruby_curl_upload_new(cCurlUpload);
809
+ ruby_curl_upload_stream_set(upload,data);
810
+
811
+ curl = rbce->curl;
812
+ rb_easy_set("upload", upload); /* keep the upload object alive as long as
813
+ the easy handle is active or until the upload
814
+ is complete or terminated... */
815
+
816
+ curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
817
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
818
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)read_data_handler);
819
+ curl_easy_setopt(curl, CURLOPT_READDATA, rbce);
820
+
821
+ /*
822
+ * we need to set specific headers for the PUT to work... so
823
+ * convert the internal headers structure to a HASH if one is set
824
+ */
825
+ if (!rb_easy_nil("headers")) {
826
+ if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_STRING)) {
827
+ rb_raise(rb_eRuntimeError, "Must set headers as a HASH to modify the headers in an PUT request");
828
+ }
829
+ }
830
+
831
+ // exit fast if the payload is empty
832
+ if (NIL_P(data)) { return data; }
833
+
834
+ headers = rb_easy_get("headers");
835
+ if( headers == Qnil ) {
836
+ headers = rb_hash_new();
837
+ }
838
+
839
+ if (rb_respond_to(data, rb_intern("read"))) {
840
+ VALUE stat = rb_funcall(data, rb_intern("stat"), 0);
841
+ if( stat && rb_hash_aref(headers, rb_str_new2("Content-Length")) == Qnil) {
842
+ VALUE size;
843
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
844
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
845
+ }
846
+ size = rb_funcall(stat, rb_intern("size"), 0);
847
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2LONG(size));
848
+ }
849
+ else if( rb_hash_aref(headers, rb_str_new2("Content-Length")) == Qnil && rb_hash_aref(headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
850
+ rb_hash_aset(headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
851
+ }
852
+ else if( rb_hash_aref(headers, rb_str_new2("Content-Length")) ) {
853
+ VALUE size = rb_funcall(rb_hash_aref(headers, rb_str_new2("Content-Length")), rb_intern("to_i"), 0);
854
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2LONG(size));
855
+ }
856
+ }
857
+ else if (rb_respond_to(data, rb_intern("to_s"))) {
858
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
859
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
860
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
861
+ }
862
+ }
863
+ else {
864
+ rb_raise(rb_eRuntimeError, "PUT data must respond to read or to_s");
865
+ }
866
+ rb_easy_set("headers",headers);
867
+
868
+ // if we made it this far, all should be well.
869
+ return data;
870
+ }
871
+
872
+ /*
873
+ * call-seq:
874
+ * easy.ftp_commands = ["CWD /", "MKD directory"] => ["CWD /", ...]
875
+ *
876
+ * Explicitly sets the list of commands to execute on the FTP server when calling perform
877
+ */
878
+ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
879
+ CURB_OBJECT_HSETTER(ruby_curl_easy, ftp_commands);
880
+ }
881
+
882
+ /*
883
+ * call-seq
884
+ * easy.ftp_commands => array or nil
885
+ */
886
+ static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
887
+ CURB_OBJECT_HGETTER(ruby_curl_easy, ftp_commands);
888
+ }
889
+
890
+ /* ================== IMMED ATTRS ==================*/
891
+
892
+ /*
893
+ * call-seq:
894
+ * easy.local_port = fixnum or nil => fixnum or nil
895
+ *
896
+ * Set the local port that will be used for the following +perform+ calls.
897
+ *
898
+ * Passing +nil+ will return to the default behaviour (no local port
899
+ * preference).
900
+ *
901
+ * This option is ignored if compiled against libcurl < 7.15.2.
902
+ */
903
+ static VALUE ruby_curl_easy_local_port_set(VALUE self, VALUE local_port) {
904
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, local_port, "port");
905
+ }
906
+
907
+ /*
908
+ * call-seq:
909
+ * easy.local_port => fixnum or nil
910
+ *
911
+ * Obtain the local port that will be used for the following +perform+ calls.
912
+ *
913
+ * This option is ignored if compiled against libcurl < 7.15.2.
914
+ */
915
+ static VALUE ruby_curl_easy_local_port_get(VALUE self) {
916
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, local_port);
917
+ }
918
+
919
+ /*
920
+ * call-seq:
921
+ * easy.local_port_range = fixnum or nil => fixnum or nil
922
+ *
923
+ * Set the local port range that will be used for the following +perform+
924
+ * calls. This is a number (between 0 and 65535) that determines how far
925
+ * libcurl may deviate from the supplied +local_port+ in order to find
926
+ * an available port.
927
+ *
928
+ * If you set +local_port+ it's also recommended that you set this, since
929
+ * it is fairly likely that your specified port will be unavailable.
930
+ *
931
+ * This option is ignored if compiled against libcurl < 7.15.2.
932
+ */
933
+ static VALUE ruby_curl_easy_local_port_range_set(VALUE self, VALUE local_port_range) {
934
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, local_port_range, "port range");
935
+ }
936
+
937
+ /*
938
+ * call-seq:
939
+ * easy.local_port_range => fixnum or nil
940
+ *
941
+ * Obtain the local port range that will be used for the following +perform+
942
+ * calls.
943
+ *
944
+ * This option is ignored if compiled against libcurl < 7.15.2.
945
+ */
946
+ static VALUE ruby_curl_easy_local_port_range_get(VALUE self) {
947
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, local_port_range);
948
+ }
949
+
950
+ /*
951
+ * call-seq:
952
+ * easy.proxy_port = fixnum or nil => fixnum or nil
953
+ *
954
+ * Set the proxy port that will be used for the following +perform+ calls.
955
+ */
956
+ static VALUE ruby_curl_easy_proxy_port_set(VALUE self, VALUE proxy_port) {
957
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, proxy_port, "port");
958
+ }
959
+
960
+ /*
961
+ * call-seq:
962
+ * easy.proxy_port => fixnum or nil
963
+ *
964
+ * Obtain the proxy port that will be used for the following +perform+ calls.
965
+ */
966
+ static VALUE ruby_curl_easy_proxy_port_get(VALUE self) {
967
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, proxy_port);
968
+ }
969
+
970
+ /*
971
+ * call-seq:
972
+ * easy.proxy_type = fixnum or nil => fixnum or nil
973
+ *
974
+ * Set the proxy type that will be used for the following +perform+ calls.
975
+ * This should be one of the Curl::CURLPROXY constants.
976
+ */
977
+ static VALUE ruby_curl_easy_proxy_type_set(VALUE self, VALUE proxy_type) {
978
+ CURB_IMMED_SETTER(ruby_curl_easy, proxy_type, -1);
979
+ }
980
+
981
+ /*
982
+ * call-seq:
983
+ * easy.proxy_type => fixnum or nil
984
+ *
985
+ * Obtain the proxy type that will be used for the following +perform+ calls.
986
+ */
987
+ static VALUE ruby_curl_easy_proxy_type_get(VALUE self) {
988
+ CURB_IMMED_GETTER(ruby_curl_easy, proxy_type, -1);
989
+ }
990
+
991
+ #if defined(HAVE_CURLAUTH_DIGEST_IE)
992
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
993
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
994
+ (!strncmp("digest_ie",node,9)) ? CURLAUTH_DIGEST_IE : \
995
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
996
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
997
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
998
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
999
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
1000
+ #else
1001
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
1002
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
1003
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
1004
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
1005
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
1006
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
1007
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
1008
+ #endif
1009
+ /*
1010
+ * call-seq:
1011
+ * easy.http_auth_types = fixnum or nil => fixnum or nil
1012
+ * easy.http_auth_types = [:basic,:digest,:digest_ie,:gssnegotiate, :ntlm, :any, :anysafe]
1013
+ *
1014
+ * Set the HTTP authentication types that may be used for the following
1015
+ * +perform+ calls. This is a bitmap made by ORing together the
1016
+ * Curl::CURLAUTH constants.
1017
+ */
1018
+ static VALUE ruby_curl_easy_http_auth_types_set(int argc, VALUE *argv, VALUE self) {//VALUE self, VALUE http_auth_types) {
1019
+ ruby_curl_easy *rbce;
1020
+ VALUE args_ary;
1021
+ int i, len;
1022
+ char* node = NULL;
1023
+ long mask = 0x000000;
1024
+
1025
+ rb_scan_args(argc, argv, "*", &args_ary);
1026
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1027
+
1028
+ len = (int)RARRAY_LEN(args_ary);
1029
+
1030
+ if (len == 1 && (TYPE(rb_ary_entry(args_ary,0)) == T_FIXNUM || rb_ary_entry(args_ary,0) == Qnil)) {
1031
+ if (rb_ary_entry(args_ary,0) == Qnil) {
1032
+ rbce->http_auth_types = 0;
1033
+ }
1034
+ else {
1035
+ rbce->http_auth_types = NUM2INT(rb_ary_entry(args_ary,0));
1036
+ }
1037
+ }
1038
+ else {
1039
+ // we could have multiple values, but they should be symbols
1040
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,0),rb_intern("to_s"),0));
1041
+ mask = CURL_HTTPAUTH_STR_TO_NUM(node);
1042
+ for( i = 1; i < len; ++i ) {
1043
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,i),rb_intern("to_s"),0));
1044
+ mask |= CURL_HTTPAUTH_STR_TO_NUM(node);
1045
+ }
1046
+ rbce->http_auth_types = mask;
1047
+ }
1048
+ return INT2NUM(rbce->http_auth_types);
1049
+ }
1050
+
1051
+ /*
1052
+ * call-seq:
1053
+ * easy.http_auth_types => fixnum or nil
1054
+ *
1055
+ * Obtain the HTTP authentication types that may be used for the following
1056
+ * +perform+ calls.
1057
+ */
1058
+ static VALUE ruby_curl_easy_http_auth_types_get(VALUE self) {
1059
+ CURB_IMMED_GETTER(ruby_curl_easy, http_auth_types, 0);
1060
+ }
1061
+
1062
+ /*
1063
+ * call-seq:
1064
+ * easy.proxy_auth_types = fixnum or nil => fixnum or nil
1065
+ *
1066
+ * Set the proxy authentication types that may be used for the following
1067
+ * +perform+ calls. This is a bitmap made by ORing together the
1068
+ * Curl::CURLAUTH constants.
1069
+ */
1070
+ static VALUE ruby_curl_easy_proxy_auth_types_set(VALUE self, VALUE proxy_auth_types) {
1071
+ CURB_IMMED_SETTER(ruby_curl_easy, proxy_auth_types, 0);
1072
+ }
1073
+
1074
+ /*
1075
+ * call-seq:
1076
+ * easy.proxy_auth_types => fixnum or nil
1077
+ *
1078
+ * Obtain the proxy authentication types that may be used for the following
1079
+ * +perform+ calls.
1080
+ */
1081
+ static VALUE ruby_curl_easy_proxy_auth_types_get(VALUE self) {
1082
+ CURB_IMMED_GETTER(ruby_curl_easy, proxy_auth_types, 0);
1083
+ }
1084
+
1085
+ /*
1086
+ * call-seq:
1087
+ * easy.max_redirects = fixnum or nil => fixnum or nil
1088
+ *
1089
+ * Set the maximum number of redirections to follow in the following +perform+
1090
+ * calls. Set to nil or -1 allow an infinite number (the default). Setting this
1091
+ * option only makes sense if +follow_location+ is also set true.
1092
+ *
1093
+ * With libcurl >= 7.15.1, setting this to 0 will cause libcurl to refuse any
1094
+ * redirect.
1095
+ */
1096
+ static VALUE ruby_curl_easy_max_redirects_set(VALUE self, VALUE max_redirs) {
1097
+ CURB_IMMED_SETTER(ruby_curl_easy, max_redirs, -1);
1098
+ }
1099
+
1100
+ /*
1101
+ * call-seq:
1102
+ * easy.max_redirects => fixnum or nil
1103
+ *
1104
+ * Obtain the maximum number of redirections to follow in the following
1105
+ * +perform+ calls.
1106
+ */
1107
+ static VALUE ruby_curl_easy_max_redirects_get(VALUE self) {
1108
+ CURB_IMMED_GETTER(ruby_curl_easy, max_redirs, -1);
1109
+ }
1110
+
1111
+ /*
1112
+ * call-seq:
1113
+ * easy.timeout = fixnum or nil => fixnum or nil
1114
+ *
1115
+ * Set the maximum time in seconds that you allow the libcurl transfer
1116
+ * operation to take. Normally, name lookups can take a considerable time
1117
+ * and limiting operations to less than a few minutes risk aborting
1118
+ * perfectly normal operations.
1119
+ *
1120
+ * Set to nil (or zero) to disable timeout (it will then only timeout
1121
+ * on the system's internal timeouts).
1122
+ */
1123
+ static VALUE ruby_curl_easy_timeout_set(VALUE self, VALUE timeout) {
1124
+ CURB_IMMED_SETTER(ruby_curl_easy, timeout, 0);
1125
+ }
1126
+
1127
+ /*
1128
+ * call-seq:
1129
+ * easy.timeout => fixnum or nil
1130
+ *
1131
+ * Obtain the maximum time in seconds that you allow the libcurl transfer
1132
+ * operation to take.
1133
+ */
1134
+ static VALUE ruby_curl_easy_timeout_get(VALUE self, VALUE timeout) {
1135
+ CURB_IMMED_GETTER(ruby_curl_easy, timeout, 0);
1136
+ }
1137
+
1138
+ /*
1139
+ * call-seq:
1140
+ * easy.connect_timeout = fixnum or nil => fixnum or nil
1141
+ *
1142
+ * Set the maximum time in seconds that you allow the connection to the
1143
+ * server to take. This only limits the connection phase, once it has
1144
+ * connected, this option is of no more use.
1145
+ *
1146
+ * Set to nil (or zero) to disable connection timeout (it will then only
1147
+ * timeout on the system's internal timeouts).
1148
+ */
1149
+ static VALUE ruby_curl_easy_connect_timeout_set(VALUE self, VALUE connect_timeout) {
1150
+ CURB_IMMED_SETTER(ruby_curl_easy, connect_timeout, 0);
1151
+ }
1152
+
1153
+ /*
1154
+ * call-seq:
1155
+ * easy.connect_timeout => fixnum or nil
1156
+ *
1157
+ * Obtain the maximum time in seconds that you allow the connection to the
1158
+ * server to take.
1159
+ */
1160
+ static VALUE ruby_curl_easy_connect_timeout_get(VALUE self, VALUE connect_timeout) {
1161
+ CURB_IMMED_GETTER(ruby_curl_easy, connect_timeout, 0);
1162
+ }
1163
+
1164
+ /*
1165
+ * call-seq:
1166
+ * easy.dns_cache_timeout = fixnum or nil => fixnum or nil
1167
+ *
1168
+ * Set the dns cache timeout in seconds. Name resolves will be kept in
1169
+ * memory for this number of seconds. Set to zero (0) to completely disable
1170
+ * caching, or set to nil (or -1) to make the cached entries remain forever.
1171
+ * By default, libcurl caches this info for 60 seconds.
1172
+ */
1173
+ static VALUE ruby_curl_easy_dns_cache_timeout_set(VALUE self, VALUE dns_cache_timeout) {
1174
+ CURB_IMMED_SETTER(ruby_curl_easy, dns_cache_timeout, -1);
1175
+ }
1176
+
1177
+ /*
1178
+ * call-seq:
1179
+ * easy.dns_cache_timeout => fixnum or nil
1180
+ *
1181
+ * Obtain the dns cache timeout in seconds.
1182
+ */
1183
+ static VALUE ruby_curl_easy_dns_cache_timeout_get(VALUE self, VALUE dns_cache_timeout) {
1184
+ CURB_IMMED_GETTER(ruby_curl_easy, dns_cache_timeout, -1);
1185
+ }
1186
+
1187
+ /*
1188
+ * call-seq:
1189
+ * easy.ftp_response_timeout = fixnum or nil => fixnum or nil
1190
+ *
1191
+ * Set a timeout period (in seconds) on the amount of time that the server
1192
+ * is allowed to take in order to generate a response message for a command
1193
+ * before the session is considered hung. While curl is waiting for a
1194
+ * response, this value overrides +timeout+. It is recommended that if used
1195
+ * in conjunction with +timeout+, you set +ftp_response_timeout+ to a value
1196
+ * smaller than +timeout+.
1197
+ *
1198
+ * Ignored if libcurl version is < 7.10.8.
1199
+ */
1200
+ static VALUE ruby_curl_easy_ftp_response_timeout_set(VALUE self, VALUE ftp_response_timeout) {
1201
+ CURB_IMMED_SETTER(ruby_curl_easy, ftp_response_timeout, 0);
1202
+ }
1203
+
1204
+ /*
1205
+ * call-seq:
1206
+ * easy.ftp_response_timeout => fixnum or nil
1207
+ *
1208
+ * Obtain the maximum time that libcurl will wait for FTP command responses.
1209
+ */
1210
+ static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self, VALUE ftp_response_timeout) {
1211
+ CURB_IMMED_GETTER(ruby_curl_easy, ftp_response_timeout, 0);
1212
+ }
1213
+
1214
+ /*
1215
+ * call-seq:
1216
+ * easy.low_speed_limit = fixnum or nil => fixnum or nil
1217
+ *
1218
+ * Set the transfer speed (in bytes per second) that the transfer should be
1219
+ * below during +low_speed_time+ seconds for the library to consider it too
1220
+ * slow and abort.
1221
+ */
1222
+ static VALUE ruby_curl_easy_low_speed_limit_set(VALUE self, VALUE low_speed_limit) {
1223
+ CURB_IMMED_SETTER(ruby_curl_easy, low_speed_limit, 0);
1224
+ }
1225
+
1226
+ /*
1227
+ * call-seq:
1228
+ * easy.low_speed_limit => fixnum or nil
1229
+ *
1230
+ * Obtain the minimum transfer speed over +low_speed+time+ below which the
1231
+ * transfer will be aborted.
1232
+ */
1233
+ static VALUE ruby_curl_easy_low_speed_limit_get(VALUE self, VALUE low_speed_limit) {
1234
+ CURB_IMMED_GETTER(ruby_curl_easy, low_speed_limit, 0);
1235
+ }
1236
+
1237
+ /*
1238
+ * call-seq:
1239
+ * easy.low_speed_time = fixnum or nil => fixnum or nil
1240
+ *
1241
+ * Set the time (in seconds) that the transfer should be below the
1242
+ * +low_speed_limit+ for the library to consider it too slow and abort.
1243
+ */
1244
+ static VALUE ruby_curl_easy_low_speed_time_set(VALUE self, VALUE low_speed_time) {
1245
+ CURB_IMMED_SETTER(ruby_curl_easy, low_speed_time, 0);
1246
+ }
1247
+
1248
+ /*
1249
+ * call-seq:
1250
+ * easy.low_speed_time => fixnum or nil
1251
+ *
1252
+ * Obtain the time that the transfer should be below +low_speed_limit+ for
1253
+ * the library to abort it.
1254
+ */
1255
+ static VALUE ruby_curl_easy_low_speed_time_get(VALUE self, VALUE low_speed_time) {
1256
+ CURB_IMMED_GETTER(ruby_curl_easy, low_speed_time, 0);
1257
+ }
1258
+
1259
+ /*
1260
+ * call-seq:
1261
+ * easy.username = string => string
1262
+ *
1263
+ * Set the HTTP Authentication username.
1264
+ */
1265
+ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
1266
+ #if HAVE_CURLOPT_USERNAME
1267
+ CURB_OBJECT_HSETTER(ruby_curl_easy, username);
1268
+ #else
1269
+ return Qnil;
1270
+ #endif
1271
+ }
1272
+
1273
+ /*
1274
+ * call-seq:
1275
+ * easy.username => string
1276
+ *
1277
+ * Get the current username
1278
+ */
1279
+ static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
1280
+ #if HAVE_CURLOPT_USERNAME
1281
+ CURB_OBJECT_HGETTER(ruby_curl_easy, username);
1282
+ #else
1283
+ return Qnil;
1284
+ #endif
1285
+ }
1286
+
1287
+ /*
1288
+ * call-seq:
1289
+ * easy.password = string => string
1290
+ *
1291
+ * Set the HTTP Authentication password.
1292
+ */
1293
+ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
1294
+ #if HAVE_CURLOPT_PASSWORD
1295
+ CURB_OBJECT_HSETTER(ruby_curl_easy, password);
1296
+ #else
1297
+ return Qnil;
1298
+ #endif
1299
+ }
1300
+
1301
+ /*
1302
+ * call-seq:
1303
+ * easy.password => string
1304
+ *
1305
+ * Get the current password
1306
+ */
1307
+ static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
1308
+ #if HAVE_CURLOPT_PASSWORD
1309
+ CURB_OBJECT_HGETTER(ruby_curl_easy, password);
1310
+ #else
1311
+ return Qnil;
1312
+ #endif
1313
+ }
1314
+
1315
+ /*
1316
+ * call-seq:
1317
+ * easy.ssl_version = value => fixnum or nil
1318
+ *
1319
+ * Sets the version of SSL/TLS that libcurl will attempt to use. Valid
1320
+ * options are Curl::CURL_SSLVERSION_TLSv1, Curl::CURL_SSLVERSION::SSLv2,
1321
+ * Curl::CURL_SSLVERSION_SSLv3 and Curl::CURL_SSLVERSION_DEFAULT
1322
+ */
1323
+ static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
1324
+ CURB_IMMED_SETTER(ruby_curl_easy, ssl_version, -1);
1325
+ }
1326
+
1327
+ /*
1328
+ * call-seq:
1329
+ * easy.ssl_version => fixnum
1330
+ *
1331
+ * Get the version of SSL/TLS that libcurl will attempt to use.
1332
+ */
1333
+ static VALUE ruby_curl_easy_ssl_version_get(VALUE self, VALUE ssl_version) {
1334
+ CURB_IMMED_GETTER(ruby_curl_easy, ssl_version, -1);
1335
+ }
1336
+
1337
+ /*
1338
+ * call-seq:
1339
+ * easy.use_ssl = value => fixnum or nil
1340
+ *
1341
+ * Ensure libcurl uses SSL for FTP connections. Valid options are Curl::CURL_USESSL_NONE,
1342
+ * Curl::CURL_USESSL_TRY, Curl::CURL_USESSL_CONTROL, and Curl::CURL_USESSL_ALL.
1343
+ */
1344
+ static VALUE ruby_curl_easy_use_ssl_set(VALUE self, VALUE use_ssl) {
1345
+ CURB_IMMED_SETTER(ruby_curl_easy, use_ssl, -1);
1346
+ }
1347
+
1348
+ /*
1349
+ * call-seq:
1350
+ * easy.use_ssl => fixnum
1351
+ *
1352
+ * Get the desired level for using SSL on FTP connections.
1353
+ */
1354
+ static VALUE ruby_curl_easy_use_ssl_get(VALUE self, VALUE use_ssl) {
1355
+ CURB_IMMED_GETTER(ruby_curl_easy, use_ssl, -1);
1356
+ }
1357
+
1358
+ /*
1359
+ * call-seq:
1360
+ * easy.ftp_filemethod = value => fixnum or nil
1361
+ *
1362
+ * Controls how libcurl reaches files on the server. Valid options are Curl::CURL_MULTICWD,
1363
+ * Curl::CURL_NOCWD, and Curl::CURL_SINGLECWD (see libcurl docs for CURLOPT_FTP_METHOD).
1364
+ */
1365
+ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod) {
1366
+ CURB_IMMED_SETTER(ruby_curl_easy, ftp_filemethod, -1);
1367
+ }
1368
+
1369
+ /*
1370
+ * call-seq
1371
+ * easy.ftp_filemethod => fixnum
1372
+ *
1373
+ * Get the configuration for how libcurl will reach files on the server.
1374
+ */
1375
+ static VALUE ruby_curl_easy_ftp_filemethod_get(VALUE self, VALUE ftp_filemethod) {
1376
+ CURB_IMMED_GETTER(ruby_curl_easy, ftp_filemethod, -1);
1377
+ }
1378
+
1379
+ /* ================== BOOL ATTRS ===================*/
1380
+
1381
+ /*
1382
+ * call-seq:
1383
+ * easy.proxy_tunnel = boolean => boolean
1384
+ *
1385
+ * Configure whether this Curl instance will use proxy tunneling.
1386
+ */
1387
+ static VALUE ruby_curl_easy_proxy_tunnel_set(VALUE self, VALUE proxy_tunnel) {
1388
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, proxy_tunnel);
1389
+ }
1390
+
1391
+ /*
1392
+ * call-seq:
1393
+ * easy.proxy_tunnel? => boolean
1394
+ *
1395
+ * Determine whether this Curl instance will use proxy tunneling.
1396
+ */
1397
+ static VALUE ruby_curl_easy_proxy_tunnel_q(VALUE self) {
1398
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, proxy_tunnel);
1399
+ }
1400
+
1401
+ /*
1402
+ * call-seq:
1403
+ * easy.fetch_file_time = boolean => boolean
1404
+ *
1405
+ * Configure whether this Curl instance will fetch remote file
1406
+ * times, if available.
1407
+ */
1408
+ static VALUE ruby_curl_easy_fetch_file_time_set(VALUE self, VALUE fetch_file_time) {
1409
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, fetch_file_time);
1410
+ }
1411
+
1412
+ /*
1413
+ * call-seq:
1414
+ * easy.fetch_file_time? => boolean
1415
+ *
1416
+ * Determine whether this Curl instance will fetch remote file
1417
+ * times, if available.
1418
+ */
1419
+ static VALUE ruby_curl_easy_fetch_file_time_q(VALUE self) {
1420
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, fetch_file_time);
1421
+ }
1422
+
1423
+ /*
1424
+ * call-seq:
1425
+ * easy.ssl_verify_peer = boolean => boolean
1426
+ *
1427
+ * Configure whether this Curl instance will verify the SSL peer
1428
+ * certificate. When true (the default), and the verification fails to
1429
+ * prove that the certificate is authentic, the connection fails. When
1430
+ * false, the connection succeeds regardless.
1431
+ *
1432
+ * Authenticating the certificate is not by itself very useful. You
1433
+ * typically want to ensure that the server, as authentically identified
1434
+ * by its certificate, is the server you mean to be talking to.
1435
+ * The ssl_verify_host? options controls that.
1436
+ */
1437
+ static VALUE ruby_curl_easy_ssl_verify_peer_set(VALUE self, VALUE ssl_verify_peer) {
1438
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, ssl_verify_peer);
1439
+ }
1440
+
1441
+ /*
1442
+ * call-seq:
1443
+ * easy.ssl_verify_peer? => boolean
1444
+ *
1445
+ * Determine whether this Curl instance will verify the SSL peer
1446
+ * certificate.
1447
+ */
1448
+ static VALUE ruby_curl_easy_ssl_verify_peer_q(VALUE self) {
1449
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, ssl_verify_peer);
1450
+ }
1451
+
1452
+ /*
1453
+ * call-seq:
1454
+ * easy.ssl_verify_host = [0, 1, 2] => [0, 1, 2]
1455
+ *
1456
+ * Configure whether this Curl instance will verify that the server cert
1457
+ * is for the server it is known as. When true (the default) the server
1458
+ * certificate must indicate that the server is the server to which you
1459
+ * meant to connect, or the connection fails. When false, the connection
1460
+ * will succeed regardless of the names in the certificate.
1461
+ *
1462
+ * this option controls is of the identity that the server claims.
1463
+ * The server could be lying. To control lying, see ssl_verify_peer? .
1464
+ */
1465
+ static VALUE ruby_curl_easy_ssl_verify_host_set(VALUE self, VALUE ssl_verify_host) {
1466
+ CURB_IMMED_SETTER(ruby_curl_easy, ssl_verify_host, 0);
1467
+ }
1468
+
1469
+ /*
1470
+ * call-seq:
1471
+ * easy.ssl_verify_host => number
1472
+ *
1473
+ * Determine whether this Curl instance will verify that the server cert
1474
+ * is for the server it is known as.
1475
+ */
1476
+ static VALUE ruby_curl_easy_ssl_verify_host_get(VALUE self) {
1477
+ CURB_IMMED_GETTER(ruby_curl_easy, ssl_verify_host, 0);
1478
+ }
1479
+
1480
+ /*
1481
+ * call-seq:
1482
+ * easy.header_in_body = boolean => boolean
1483
+ *
1484
+ * Configure whether this Curl instance will return HTTP headers
1485
+ * combined with body data. If this option is set true, both header
1486
+ * and body data will go to +body_str+ (or the configured +on_body+ handler).
1487
+ */
1488
+ static VALUE ruby_curl_easy_header_in_body_set(VALUE self, VALUE header_in_body) {
1489
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, header_in_body);
1490
+ }
1491
+
1492
+ /*
1493
+ * call-seq:
1494
+ * easy.header_in_body? => boolean
1495
+ *
1496
+ * Determine whether this Curl instance will return HTTP headers
1497
+ * combined with body data.
1498
+ */
1499
+ static VALUE ruby_curl_easy_header_in_body_q(VALUE self) {
1500
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, header_in_body);
1501
+ }
1502
+
1503
+ /*
1504
+ * call-seq:
1505
+ * easy.use_netrc = boolean => boolean
1506
+ *
1507
+ * Configure whether this Curl instance will use data from the user's
1508
+ * .netrc file for FTP connections.
1509
+ */
1510
+ static VALUE ruby_curl_easy_use_netrc_set(VALUE self, VALUE use_netrc) {
1511
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, use_netrc);
1512
+ }
1513
+
1514
+ /*
1515
+ * call-seq:
1516
+ * easy.use_netrc? => boolean
1517
+ *
1518
+ * Determine whether this Curl instance will use data from the user's
1519
+ * .netrc file for FTP connections.
1520
+ */
1521
+ static VALUE ruby_curl_easy_use_netrc_q(VALUE self) {
1522
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, use_netrc);
1523
+ }
1524
+
1525
+ /*
1526
+ * call-seq:
1527
+ *
1528
+ * easy = Curl::Easy.new
1529
+ * easy.autoreferer=true
1530
+ */
1531
+ static VALUE ruby_curl_easy_autoreferer_set(VALUE self, VALUE autoreferer) {
1532
+ ruby_curl_easy *rbce;
1533
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1534
+
1535
+ if (Qtrue == autoreferer) {
1536
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 1);
1537
+ }
1538
+ else {
1539
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 0);
1540
+ }
1541
+
1542
+ return autoreferer;
1543
+ }
1544
+
1545
+ /*
1546
+ * call-seq:
1547
+ * easy.follow_location? => boolean
1548
+ *
1549
+ * Determine whether this Curl instance will follow Location: headers
1550
+ * in HTTP responses.
1551
+ */
1552
+ static VALUE ruby_curl_easy_follow_location_q(VALUE self) {
1553
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, follow_location);
1554
+ }
1555
+
1556
+ /*
1557
+ * call-seq:
1558
+ * easy.unrestricted_auth = boolean => boolean
1559
+ *
1560
+ * Configure whether this Curl instance may use any HTTP authentication
1561
+ * method available when necessary.
1562
+ */
1563
+ static VALUE ruby_curl_easy_unrestricted_auth_set(VALUE self, VALUE unrestricted_auth) {
1564
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, unrestricted_auth);
1565
+ }
1566
+
1567
+ /*
1568
+ * call-seq:
1569
+ * easy.unrestricted_auth? => boolean
1570
+ *
1571
+ * Determine whether this Curl instance may use any HTTP authentication
1572
+ * method available when necessary.
1573
+ */
1574
+ static VALUE ruby_curl_easy_unrestricted_auth_q(VALUE self) {
1575
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, unrestricted_auth);
1576
+ }
1577
+
1578
+ /*
1579
+ * call-seq:
1580
+ * easy.verbose = boolean => boolean
1581
+ *
1582
+ * Configure whether this Curl instance gives verbose output to STDERR
1583
+ * during transfers. Ignored if this instance has an on_debug handler.
1584
+ */
1585
+ static VALUE ruby_curl_easy_verbose_set(VALUE self, VALUE verbose) {
1586
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, verbose);
1587
+ }
1588
+
1589
+ /*
1590
+ * call-seq:
1591
+ * easy.verbose? => boolean
1592
+ *
1593
+ * Determine whether this Curl instance gives verbose output to STDERR
1594
+ * during transfers.
1595
+ */
1596
+ static VALUE ruby_curl_easy_verbose_q(VALUE self) {
1597
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, verbose);
1598
+ }
1599
+
1600
+ /*
1601
+ * call-seq:
1602
+ * easy.multipart_form_post = boolean => boolean
1603
+ *
1604
+ * Configure whether this Curl instance uses multipart/formdata content
1605
+ * type for HTTP POST requests. If this is false (the default), then the
1606
+ * application/x-www-form-urlencoded content type is used for the form
1607
+ * data.
1608
+ *
1609
+ * If this is set true, you must pass one or more PostField instances
1610
+ * to the http_post method - no support for posting multipart forms from
1611
+ * a string is provided.
1612
+ */
1613
+ static VALUE ruby_curl_easy_multipart_form_post_set(VALUE self, VALUE multipart_form_post)
1614
+ {
1615
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, multipart_form_post);
1616
+ }
1617
+
1618
+ /*
1619
+ * call-seq:
1620
+ * easy.multipart_form_post? => boolean
1621
+ *
1622
+ * Determine whether this Curl instance uses multipart/formdata content
1623
+ * type for HTTP POST requests.
1624
+ */
1625
+ static VALUE ruby_curl_easy_multipart_form_post_q(VALUE self) {
1626
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, multipart_form_post);
1627
+ }
1628
+
1629
+ /*
1630
+ * call-seq:
1631
+ * easy.enable_cookies = boolean => boolean
1632
+ *
1633
+ * Configure whether the libcurl cookie engine is enabled for this Curl::Easy
1634
+ * instance.
1635
+ */
1636
+ static VALUE ruby_curl_easy_enable_cookies_set(VALUE self, VALUE enable_cookies)
1637
+ {
1638
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, enable_cookies);
1639
+ }
1640
+
1641
+ /*
1642
+ * call-seq:
1643
+ * easy.enable_cookies? => boolean
1644
+ *
1645
+ * Determine whether the libcurl cookie engine is enabled for this
1646
+ * Curl::Easy instance.
1647
+ */
1648
+ static VALUE ruby_curl_easy_enable_cookies_q(VALUE self) {
1649
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, enable_cookies);
1650
+ }
1651
+
1652
+ /*
1653
+ * call-seq:
1654
+ * easy.ignore_content_length = boolean
1655
+ *
1656
+ * Configure whether this Curl::Easy instance should ignore the content
1657
+ * length header.
1658
+ */
1659
+ static VALUE ruby_curl_easy_ignore_content_length_set(VALUE self, VALUE ignore_content_length)
1660
+ {
1661
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, ignore_content_length);
1662
+ }
1663
+
1664
+ /*
1665
+ * call-seq:
1666
+ * easy.ignore_content_length? => boolean
1667
+ *
1668
+ * Determine whether this Curl::Easy instance ignores the content
1669
+ * length header.
1670
+ */
1671
+ static VALUE ruby_curl_easy_ignore_content_length_q(VALUE self) {
1672
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, ignore_content_length);
1673
+ }
1674
+
1675
+ /*
1676
+ * call-seq:
1677
+ * easy.resolve_mode => symbol
1678
+ *
1679
+ * Determines what type of IP address this Curl::Easy instance
1680
+ * resolves DNS names to.
1681
+ */
1682
+ static VALUE ruby_curl_easy_resolve_mode(VALUE self) {
1683
+ ruby_curl_easy *rbce;
1684
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1685
+
1686
+ unsigned short rm = rbce->resolve_mode;
1687
+
1688
+ switch(rm) {
1689
+ case CURL_IPRESOLVE_V4:
1690
+ return rb_easy_sym("ipv4");
1691
+ case CURL_IPRESOLVE_V6:
1692
+ return rb_easy_sym("ipv6");
1693
+ default:
1694
+ return rb_easy_sym("auto");
1695
+ }
1696
+ }
1697
+
1698
+ /*
1699
+ * call-seq:
1700
+ * easy.resolve_mode = symbol => symbol
1701
+ *
1702
+ * Configures what type of IP address this Curl::Easy instance
1703
+ * resolves DNS names to. Valid options are:
1704
+ *
1705
+ * [:auto] resolves DNS names to all IP versions your system allows
1706
+ * [:ipv4] resolves DNS names to IPv4 only
1707
+ * [:ipv6] resolves DNS names to IPv6 only
1708
+ */
1709
+ static VALUE ruby_curl_easy_resolve_mode_set(VALUE self, VALUE resolve_mode) {
1710
+ if (TYPE(resolve_mode) != T_SYMBOL) {
1711
+ rb_raise(rb_eTypeError, "Must pass a symbol");
1712
+ return Qnil;
1713
+ } else {
1714
+ ruby_curl_easy *rbce;
1715
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1716
+
1717
+ ID resolve_mode_id = rb_to_id(resolve_mode);
1718
+
1719
+ if (resolve_mode_id == rb_intern("auto")) {
1720
+ rbce->resolve_mode = CURL_IPRESOLVE_WHATEVER;
1721
+ return resolve_mode;
1722
+ } else if (resolve_mode_id == rb_intern("ipv4")) {
1723
+ rbce->resolve_mode = CURL_IPRESOLVE_V4;
1724
+ return resolve_mode;
1725
+ } else if (resolve_mode_id == rb_intern("ipv6")) {
1726
+ rbce->resolve_mode = CURL_IPRESOLVE_V6;
1727
+ return resolve_mode;
1728
+ } else {
1729
+ rb_raise(rb_eArgError, "Must set to one of :auto, :ipv4, :ipv6");
1730
+ return Qnil;
1731
+ }
1732
+ }
1733
+ }
1734
+
1735
+
1736
+ /* ================= EVENT PROCS ================== */
1737
+
1738
+ /*
1739
+ * call-seq:
1740
+ * easy.on_body { |body_data| ... } => &lt;old handler&gt;
1741
+ *
1742
+ * Assign or remove the +on_body+ handler for this Curl::Easy instance.
1743
+ * To remove a previously-supplied handler, call this method with no
1744
+ * attached block.
1745
+ *
1746
+ * The +on_body+ handler is called for each chunk of response body passed back
1747
+ * by libcurl during +perform+. It should perform any processing necessary,
1748
+ * and return the actual number of bytes handled. Normally, this will
1749
+ * equal the length of the data string, and CURL will continue processing.
1750
+ * If the returned length does not equal the input length, CURL will abort
1751
+ * the processing with a Curl::Err::AbortedByCallbackError.
1752
+ */
1753
+ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
1754
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, body_proc);
1755
+ }
1756
+
1757
+ /*
1758
+ * call-seq:
1759
+ * easy.on_success { |easy| ... } => &lt;old handler&gt;
1760
+ *
1761
+ * Assign or remove the +on_success+ handler for this Curl::Easy instance.
1762
+ * To remove a previously-supplied handler, call this method with no
1763
+ * attached block.
1764
+ *
1765
+ * The +on_success+ handler is called when the request is finished with a
1766
+ * status of 20x
1767
+ */
1768
+ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
1769
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, success_proc);
1770
+ }
1771
+
1772
+ /*
1773
+ * call-seq:
1774
+ * easy.on_failure {|easy,code| ... } => &lt;old handler&gt;
1775
+ *
1776
+ * Assign or remove the +on_failure+ handler for this Curl::Easy instance.
1777
+ * To remove a previously-supplied handler, call this method with no
1778
+ * attached block.
1779
+ *
1780
+ * The +on_failure+ handler is called when the request is finished with a
1781
+ * status of 50x
1782
+ */
1783
+ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
1784
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, failure_proc);
1785
+ }
1786
+
1787
+ /*
1788
+ * call-seq:
1789
+ * easy.on_missing {|easy,code| ... } => &lt;old handler;&gt;
1790
+ *
1791
+ * Assign or remove the on_missing handler for this Curl::Easy instance.
1792
+ * To remove a previously-supplied handler, call this method with no attached
1793
+ * block.
1794
+ *
1795
+ * The +on_missing+ handler is called when request is finished with a
1796
+ * status of 40x
1797
+ */
1798
+ static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
1799
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, missing_proc);
1800
+ }
1801
+
1802
+ /*
1803
+ * call-seq:
1804
+ * easy.on_redirect {|easy,code| ... } => &lt;old handler;&gt;
1805
+ *
1806
+ * Assign or remove the on_redirect handler for this Curl::Easy instance.
1807
+ * To remove a previously-supplied handler, call this method with no attached
1808
+ * block.
1809
+ *
1810
+ * The +on_redirect+ handler is called when request is finished with a
1811
+ * status of 30x
1812
+ */
1813
+ static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
1814
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, redirect_proc);
1815
+ }
1816
+
1817
+ /*
1818
+ * call-seq:
1819
+ * easy.on_complete {|easy| ... } => &lt;old handler&gt;
1820
+ *
1821
+ * Assign or remove the +on_complete+ handler for this Curl::Easy instance.
1822
+ * To remove a previously-supplied handler, call this method with no
1823
+ * attached block.
1824
+ *
1825
+ * The +on_complete+ handler is called when the request is finished.
1826
+ */
1827
+ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
1828
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, complete_proc);
1829
+ }
1830
+
1831
+ /*
1832
+ * call-seq:
1833
+ * easy.on_header { |header_data| ... } => &lt;old handler&gt;
1834
+ *
1835
+ * Assign or remove the +on_header+ handler for this Curl::Easy instance.
1836
+ * To remove a previously-supplied handler, call this method with no
1837
+ * attached block.
1838
+ *
1839
+ * The +on_header+ handler is called for each chunk of response header passed
1840
+ * back by libcurl during +perform+. The semantics are the same as for the
1841
+ * block supplied to +on_body+.
1842
+ */
1843
+ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
1844
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, header_proc);
1845
+ }
1846
+
1847
+ /*
1848
+ * call-seq:
1849
+ * easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } => &lt;old handler&gt;
1850
+ *
1851
+ * Assign or remove the +on_progress+ handler for this Curl::Easy instance.
1852
+ * To remove a previously-supplied handler, call this method with no
1853
+ * attached block.
1854
+ *
1855
+ * The +on_progress+ handler is called regularly by libcurl (approximately once
1856
+ * per second) during transfers to allow the application to receive progress
1857
+ * information. There is no guarantee that the reported progress will change
1858
+ * between calls.
1859
+ *
1860
+ * The result of the block call determines whether libcurl continues the transfer.
1861
+ * Returning a non-true value (i.e. nil or false) will cause the transfer to abort,
1862
+ * throwing a Curl::Err::AbortedByCallbackError.
1863
+ */
1864
+ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
1865
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, progress_proc);
1866
+ }
1867
+
1868
+ /*
1869
+ * call-seq:
1870
+ * easy.on_debug { |type, data| ... } => &lt;old handler&gt;
1871
+ *
1872
+ * Assign or remove the +on_debug+ handler for this Curl::Easy instance.
1873
+ * To remove a previously-supplied handler, call this method with no
1874
+ * attached block.
1875
+ *
1876
+ * The +on_debug+ handler, if configured, will receive detailed information
1877
+ * from libcurl during the perform call. This can be useful for debugging.
1878
+ * Setting a debug handler overrides libcurl's internal handler, disabling
1879
+ * any output from +verbose+, if set.
1880
+ *
1881
+ * The type argument will match one of the Curl::Easy::CURLINFO_XXXX
1882
+ * constants, and specifies the kind of information contained in the
1883
+ * data. The data is passed as a String.
1884
+ */
1885
+ static VALUE ruby_curl_easy_on_debug_set(int argc, VALUE *argv, VALUE self) {
1886
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, debug_proc);
1887
+ }
1888
+
1889
+
1890
+ /* =================== PERFORM =====================*/
1891
+
1892
+ /***********************************************
1893
+ * This is an rb_iterate callback used to set up http headers.
1894
+ */
1895
+ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
1896
+ struct curl_slist **list;
1897
+ Data_Get_Struct(wrap, struct curl_slist *, list);
1898
+
1899
+ VALUE header_str = Qnil;
1900
+
1901
+ //rb_p(header);
1902
+
1903
+ if (rb_type(header) == T_ARRAY) {
1904
+ // we're processing a hash, header is [name, val]
1905
+ VALUE name, value;
1906
+
1907
+ name = rb_obj_as_string(rb_ary_entry(header, 0));
1908
+ value = rb_obj_as_string(rb_ary_entry(header, 1));
1909
+
1910
+ // This is a bit inefficient, but we don't want to be modifying
1911
+ // the actual values in the original hash.
1912
+ header_str = rb_str_plus(name, rb_str_new2(": "));
1913
+ header_str = rb_str_plus(header_str, value);
1914
+ } else {
1915
+ header_str = rb_obj_as_string(header);
1916
+ }
1917
+
1918
+ //rb_p(header_str);
1919
+
1920
+ *list = curl_slist_append(*list, StringValuePtr(header_str));
1921
+ return header_str;
1922
+ }
1923
+
1924
+ /***********************************************
1925
+ * This is an rb_iterate callback used to set up ftp commands.
1926
+ */
1927
+ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap) {
1928
+ struct curl_slist **list;
1929
+ Data_Get_Struct(wrap, struct curl_slist *, list);
1930
+
1931
+ VALUE ftp_command_string = rb_obj_as_string(ftp_command);
1932
+ *list = curl_slist_append(*list, StringValuePtr(ftp_command));
1933
+
1934
+ return ftp_command_string;
1935
+ }
1936
+
1937
+ /***********************************************
1938
+ *
1939
+ * Setup a connection
1940
+ *
1941
+ * Always returns Qtrue, rb_raise on error.
1942
+ */
1943
+ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
1944
+ // TODO this could do with a bit of refactoring...
1945
+ CURL *curl;
1946
+ VALUE url, _url = rb_easy_get("url");
1947
+ struct curl_slist **hdrs = &(rbce->curl_headers);
1948
+ struct curl_slist **cmds = &(rbce->curl_ftp_commands);
1949
+
1950
+ curl = rbce->curl;
1951
+
1952
+ if (_url == Qnil) {
1953
+ rb_raise(eCurlErrError, "No URL supplied");
1954
+ }
1955
+
1956
+ url = rb_check_string_type(_url);
1957
+
1958
+ curl_easy_setopt(curl, CURLOPT_URL, StringValuePtr(url));
1959
+
1960
+ // network stuff and auth
1961
+ if (!rb_easy_nil("interface_hm")) {
1962
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, rb_easy_get_str("interface_hm"));
1963
+ } else {
1964
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, NULL);
1965
+ }
1966
+
1967
+ #if HAVE_CURLOPT_USERNAME == 1 && HAVE_CURLOPT_PASSWORD == 1
1968
+ if (!rb_easy_nil("username")) {
1969
+ curl_easy_setopt(curl, CURLOPT_USERNAME, rb_easy_get_str("username"));
1970
+ } else {
1971
+ curl_easy_setopt(curl, CURLOPT_USERNAME, NULL);
1972
+ }
1973
+ if (!rb_easy_nil("password")) {
1974
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, rb_easy_get_str("password"));
1975
+ }
1976
+ else {
1977
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, NULL);
1978
+ }
1979
+ #endif
1980
+
1981
+ if (!rb_easy_nil("userpwd")) {
1982
+ curl_easy_setopt(curl, CURLOPT_USERPWD, rb_easy_get_str("userpwd"));
1983
+ #if HAVE_CURLOPT_USERNAME == 1
1984
+ } else if (rb_easy_nil("username") && rb_easy_nil("password")) { /* don't set this even to NULL if we have set username and password */
1985
+ #else
1986
+ } else {
1987
+ #endif
1988
+ curl_easy_setopt(curl, CURLOPT_USERPWD, NULL);
1989
+ }
1990
+
1991
+ if (rb_easy_nil("proxy_url")) {
1992
+ curl_easy_setopt(curl, CURLOPT_PROXY, NULL);
1993
+ } else {
1994
+ curl_easy_setopt(curl, CURLOPT_PROXY, rb_easy_get_str("proxy_url"));
1995
+ }
1996
+
1997
+ if (rb_easy_nil("proxypwd")) {
1998
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, NULL);
1999
+ } else {
2000
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, rb_easy_get_str("proxypwd"));
2001
+ }
2002
+
2003
+ // body/header procs
2004
+ if (!rb_easy_nil("body_proc")) {
2005
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler_body);
2006
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbce);
2007
+ /* clear out the body_data if it was set */
2008
+ rb_easy_del("body_data");
2009
+ } else {
2010
+ VALUE body_buffer = rb_easy_set("body_data", rb_str_buf_new(32768));
2011
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&default_data_handler);
2012
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
2013
+ }
2014
+
2015
+ if (!rb_easy_nil("header_proc")) {
2016
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&proc_data_handler_header);
2017
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, rbce);
2018
+ /* clear out the header_data if it was set */
2019
+ rb_easy_del("header_data");
2020
+ } else {
2021
+ VALUE header_buffer = rb_easy_set("header_data", rb_str_buf_new(16384));
2022
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&default_data_handler);
2023
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, header_buffer);
2024
+ }
2025
+
2026
+ /* encoding */
2027
+ if (!rb_easy_nil("encoding")) {
2028
+ curl_easy_setopt(curl, CURLOPT_ENCODING, rb_easy_get_str("encoding"));
2029
+ }
2030
+
2031
+ // progress and debug procs
2032
+ if (!rb_easy_nil("progress_proc")) {
2033
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&proc_progress_handler);
2034
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, rb_easy_get("progress_proc"));
2035
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
2036
+ } else {
2037
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
2038
+ }
2039
+
2040
+ if (!rb_easy_nil("debug_proc")) {
2041
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, (curl_debug_callback)&proc_debug_handler);
2042
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, rb_easy_get("debug_proc"));
2043
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
2044
+ } else {
2045
+ // have to remove handler to re-enable standard verbosity
2046
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, NULL);
2047
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, NULL);
2048
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, rbce->verbose);
2049
+ }
2050
+
2051
+ /* general opts */
2052
+
2053
+ curl_easy_setopt(curl, CURLOPT_HEADER, rbce->header_in_body);
2054
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, rbce->follow_location);
2055
+ curl_easy_setopt(curl, CURLOPT_MAXREDIRS, rbce->max_redirs);
2056
+
2057
+ curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, rbce->proxy_tunnel);
2058
+ curl_easy_setopt(curl, CURLOPT_FILETIME, rbce->fetch_file_time);
2059
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, rbce->ssl_verify_peer);
2060
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, rbce->ssl_verify_host);
2061
+
2062
+ if ((rbce->use_netrc != Qnil) && (rbce->use_netrc != Qfalse)) {
2063
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
2064
+ } else {
2065
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
2066
+ }
2067
+
2068
+ curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, rbce->unrestricted_auth);
2069
+
2070
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, rbce->timeout);
2071
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, rbce->connect_timeout);
2072
+ curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, rbce->dns_cache_timeout);
2073
+
2074
+ curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, rbce->ignore_content_length);
2075
+
2076
+ curl_easy_setopt(curl, CURLOPT_IPRESOLVE, rbce->resolve_mode);
2077
+
2078
+
2079
+ #if LIBCURL_VERSION_NUM >= 0x070a08
2080
+ curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, rbce->ftp_response_timeout);
2081
+ #else
2082
+ if (rbce->ftp_response_timeout > 0) {
2083
+ rb_warn("Installed libcurl is too old to support ftp_response_timeout");
2084
+ }
2085
+ #endif
2086
+
2087
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, rbce->low_speed_limit);
2088
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, rbce->low_speed_time);
2089
+
2090
+ // Set up localport / proxy port
2091
+ // FIXME these won't get returned to default if they're unset Ruby
2092
+ if (rbce->proxy_port > 0) {
2093
+ curl_easy_setopt(curl, CURLOPT_PROXYPORT, rbce->proxy_port);
2094
+ }
2095
+
2096
+ if (rbce->local_port > 0) {
2097
+ #if LIBCURL_VERSION_NUM >= 0x070f02
2098
+ curl_easy_setopt(curl, CURLOPT_LOCALPORT, rbce->local_port);
2099
+
2100
+ if (rbce->local_port_range > 0) {
2101
+ curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, rbce->local_port_range);
2102
+ }
2103
+ #else
2104
+ rb_warn("Installed libcurl is too old to support local_port");
2105
+ #endif
2106
+ }
2107
+
2108
+ if (rbce->proxy_type != -1) {
2109
+ #if LIBCURL_VERSION_NUM >= 0x070a00
2110
+ if (rbce->proxy_type == -2) {
2111
+ rb_warn("Installed libcurl is too old to support the selected proxy type");
2112
+ } else {
2113
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, rbce->proxy_type);
2114
+ }
2115
+ } else {
2116
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
2117
+ #else
2118
+ rb_warn("Installed libcurl is too old to support proxy_type");
2119
+ #endif
2120
+ }
2121
+
2122
+ if (rbce->http_auth_types > 0) {
2123
+ #if LIBCURL_VERSION_NUM >= 0x070a06
2124
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, rbce->http_auth_types);
2125
+ } else {
2126
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
2127
+ #else
2128
+ rb_warn("Installed libcurl is too old to support http_auth_types");
2129
+ #endif
2130
+ }
2131
+
2132
+ if (rbce->proxy_auth_types > 0) {
2133
+ #if LIBCURL_VERSION_NUM >= 0x070a07
2134
+ curl_easy_setopt(curl, CURLOPT_PROXYAUTH, rbce->proxy_auth_types);
2135
+ } else {
2136
+ curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
2137
+ #else
2138
+ rb_warn("Installed libcurl is too old to support proxy_auth_types");
2139
+ #endif
2140
+ }
2141
+
2142
+ /* Set up HTTP cookie handling if necessary
2143
+ FIXME this may not get disabled if it's enabled, the disabled again from ruby.
2144
+ */
2145
+ if (rbce->enable_cookies) {
2146
+ if (!rb_easy_nil("cookiejar")) {
2147
+ curl_easy_setopt(curl, CURLOPT_COOKIEJAR, rb_easy_get_str("cookiejar"));
2148
+ }
2149
+
2150
+ if (!rb_easy_nil("cookiefile")) {
2151
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, rb_easy_get_str("cookiefile"));
2152
+ } else {
2153
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* "" = magic to just enable */
2154
+ }
2155
+ }
2156
+
2157
+ if (!rb_easy_nil("cookies")) {
2158
+ curl_easy_setopt(curl, CURLOPT_COOKIE, rb_easy_get_str("cookies"));
2159
+ }
2160
+
2161
+ /* Set up HTTPS cert handling if necessary */
2162
+ if (!rb_easy_nil("cert")) {
2163
+ if (!rb_easy_nil("certtype")) {
2164
+ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, rb_easy_get_str("certtype"));
2165
+ }
2166
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, rb_easy_get_str("cert"));
2167
+ if (!rb_easy_nil("certpassword")) {
2168
+ curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, rb_easy_get_str("certpassword"));
2169
+ }
2170
+ if (!rb_easy_nil("cert_key")) {
2171
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, rb_easy_get_str("cert_key"));
2172
+ }
2173
+ }
2174
+
2175
+ if (!rb_easy_nil("cacert")) {
2176
+ curl_easy_setopt(curl, CURLOPT_CAINFO, rb_easy_get_str("cacert"));
2177
+ }
2178
+ #ifdef HAVE_CURL_CONFIG_CA
2179
+ else {
2180
+ curl_easy_setopt(curl, CURLOPT_CAINFO, CURL_CONFIG_CA);
2181
+ }
2182
+ #endif
2183
+
2184
+ #ifdef CURL_VERSION_SSL
2185
+ if (rbce->ssl_version > 0) {
2186
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, rbce->ssl_version);
2187
+ }
2188
+
2189
+ if (rbce->use_ssl > 0) {
2190
+ curl_easy_setopt(curl, CURB_FTPSSL, rbce->use_ssl);
2191
+ }
2192
+ #else
2193
+ if (rbce->ssl_version > 0 || rbce->use_ssl > 0) {
2194
+ rb_warn("libcurl is not configured with SSL support");
2195
+ }
2196
+ #endif
2197
+
2198
+ if (rbce->ftp_filemethod > 0) {
2199
+ curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, rbce->ftp_filemethod);
2200
+ }
2201
+
2202
+ /* Set the user-agent string if specified */
2203
+ if (!rb_easy_nil("useragent")) {
2204
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, rb_easy_get_str("useragent"));
2205
+ }
2206
+
2207
+ /* Setup HTTP headers if necessary */
2208
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); // XXX: maybe we shouldn't be clearing this?
2209
+
2210
+ if (!rb_easy_nil("headers")) {
2211
+ if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_HASH)) {
2212
+ VALUE wrap = Data_Wrap_Struct(rb_cObject, 0, 0, hdrs);
2213
+ rb_iterate(rb_each, rb_easy_get("headers"), cb_each_http_header, wrap);
2214
+ } else {
2215
+ VALUE headers_str = rb_obj_as_string(rb_easy_get("headers"));
2216
+ *hdrs = curl_slist_append(*hdrs, StringValuePtr(headers_str));
2217
+ }
2218
+
2219
+ if (*hdrs) {
2220
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *hdrs);
2221
+ }
2222
+ }
2223
+
2224
+ /* Setup FTP commands if necessary */
2225
+ if (!rb_easy_nil("ftp_commands")) {
2226
+ if (rb_easy_type_check("ftp_commands", T_ARRAY)) {
2227
+ VALUE wrap = Data_Wrap_Struct(rb_cObject, 0, 0, cmds);
2228
+ rb_iterate(rb_each, rb_easy_get("ftp_commands"), cb_each_ftp_command, wrap);
2229
+ }
2230
+
2231
+ if (*cmds) {
2232
+ curl_easy_setopt(curl, CURLOPT_QUOTE, *cmds);
2233
+ }
2234
+ }
2235
+
2236
+ return Qnil;
2237
+ }
2238
+ /***********************************************
2239
+ *
2240
+ * Clean up a connection
2241
+ *
2242
+ * Always returns Qtrue.
2243
+ */
2244
+ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
2245
+
2246
+ CURL *curl = rbce->curl;
2247
+ struct curl_slist *ftp_commands;
2248
+
2249
+ /* Free everything up */
2250
+ if (rbce->curl_headers) {
2251
+ curl_slist_free_all(rbce->curl_headers);
2252
+ rbce->curl_headers = NULL;
2253
+ }
2254
+
2255
+ ftp_commands = rbce->curl_ftp_commands;
2256
+ if (ftp_commands) {
2257
+ curl_slist_free_all(ftp_commands);
2258
+ rbce->curl_ftp_commands = NULL;
2259
+ }
2260
+
2261
+ /* clean up a PUT request's curl options. */
2262
+ if (!rb_easy_nil("upload")) {
2263
+ rb_easy_del("upload"); // set the upload object to Qnil to let the GC clean up
2264
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 0);
2265
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
2266
+ curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
2267
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0);
2268
+ }
2269
+
2270
+ return Qnil;
2271
+ }
2272
+
2273
+ /*
2274
+ * Common implementation of easy.http(verb) and easy.http_delete
2275
+ */
2276
+ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
2277
+ ruby_curl_easy *rbce;
2278
+ CURL *curl;
2279
+ VALUE retval;
2280
+
2281
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2282
+ curl = rbce->curl;
2283
+
2284
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
2285
+
2286
+ retval = rb_funcall(self, rb_intern("perform"), 0);
2287
+
2288
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2289
+
2290
+ return retval;
2291
+ }
2292
+
2293
+ /*
2294
+ * call-seq:
2295
+ * easy.http(verb)
2296
+ *
2297
+ * Send an HTTP request with method set to verb, using the current options set for this Curl::Easy instance.
2298
+ * This method always returns true or raises an exception (defined under Curl::Err) on error.
2299
+ */
2300
+ static VALUE ruby_curl_easy_perform_verb(VALUE self, VALUE verb) {
2301
+ VALUE str_verb;
2302
+ if (rb_type(verb) == T_STRING) {
2303
+ return ruby_curl_easy_perform_verb_str(self, StringValueCStr(verb));
2304
+ }
2305
+ else if (rb_respond_to(verb,rb_intern("to_s"))) {
2306
+ str_verb = rb_funcall(verb, rb_intern("to_s"), 0);
2307
+ return ruby_curl_easy_perform_verb_str(self, StringValueCStr(str_verb));
2308
+ }
2309
+ else {
2310
+ rb_raise(rb_eRuntimeError, "Invalid HTTP VERB, must response to 'to_s'");
2311
+ }
2312
+ }
2313
+
2314
+ /*
2315
+ * call-seq:
2316
+ * easy.http_post("url=encoded%20form%20data;and=so%20on") => true
2317
+ * easy.http_post("url=encoded%20form%20data", "and=so%20on", ...) => true
2318
+ * easy.http_post("url=encoded%20form%20data", Curl::PostField, "and=so%20on", ...) => true
2319
+ * easy.http_post(Curl::PostField, Curl::PostField ..., Curl::PostField) => true
2320
+ *
2321
+ * POST the specified formdata to the currently configured URL using
2322
+ * the current options set for this Curl::Easy instance. This method
2323
+ * always returns true, or raises an exception (defined under
2324
+ * Curl::Err) on error.
2325
+ *
2326
+ * The Content-type of the POST is determined by the current setting
2327
+ * of multipart_form_post? , according to the following rules:
2328
+ * * When false (the default): the form will be POSTed with a
2329
+ * content-type of 'application/x-www-form-urlencoded', and any of the
2330
+ * four calling forms may be used.
2331
+ * * When true: the form will be POSTed with a content-type of
2332
+ * 'multipart/formdata'. Only the last calling form may be used,
2333
+ * i.e. only PostField instances may be POSTed. In this mode,
2334
+ * individual fields' content-types are recognised, and file upload
2335
+ * fields are supported.
2336
+ *
2337
+ */
2338
+ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
2339
+ ruby_curl_easy *rbce;
2340
+ CURL *curl;
2341
+ int i;
2342
+ VALUE args_ary;
2343
+
2344
+ rb_scan_args(argc, argv, "*", &args_ary);
2345
+
2346
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2347
+ curl = rbce->curl;
2348
+
2349
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2350
+
2351
+ if (rbce->multipart_form_post) {
2352
+ VALUE ret;
2353
+ struct curl_httppost *first = NULL, *last = NULL;
2354
+
2355
+ // Make the multipart form
2356
+ for (i = 0; i < argc; i++) {
2357
+ if (rb_obj_is_instance_of(argv[i], cCurlPostField)) {
2358
+ append_to_form(argv[i], &first, &last);
2359
+ } else if (rb_type(argv[i]) == T_ARRAY) {
2360
+ // see: https://github.com/rvanlieshout/curb/commit/8bcdefddc0162484681ebd1a92d52a642666a445
2361
+ int c = 0, argv_len = (int)RARRAY_LEN(argv[i]);
2362
+ for (; c < argv_len; ++c) {
2363
+ if (rb_obj_is_instance_of(rb_ary_entry(argv[i],c), cCurlPostField)) {
2364
+ append_to_form(rb_ary_entry(argv[i],c), &first, &last);
2365
+ } else {
2366
+ rb_raise(eCurlErrInvalidPostField, "You must use PostFields only with multipart form posts");
2367
+ return Qnil;
2368
+ }
2369
+ }
2370
+ } else {
2371
+ rb_raise(eCurlErrInvalidPostField, "You must use PostFields only with multipart form posts");
2372
+ return Qnil;
2373
+ }
2374
+ }
2375
+
2376
+ curl_easy_setopt(curl, CURLOPT_POST, 0);
2377
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, first);
2378
+ ret = rb_funcall(self, rb_intern("perform"), 0);
2379
+ curl_formfree(first);
2380
+
2381
+ return ret;
2382
+ } else {
2383
+ VALUE post_body = Qnil;
2384
+ /* TODO: check for PostField.file and raise error before to_s fails */
2385
+ if ((post_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp)) == Qnil) {
2386
+ rb_raise(eCurlErrError, "Failed to join arguments");
2387
+ return Qnil;
2388
+ } else {
2389
+ /* if the function call above returns an empty string because no additional arguments were passed this makes sure
2390
+ a previously set easy.post_body = "arg=foo&bar=bin" will be honored */
2391
+ if( post_body != Qnil && rb_type(post_body) == T_STRING && RSTRING_LEN(post_body) > 0 ) {
2392
+ ruby_curl_easy_post_body_set(self, post_body);
2393
+ }
2394
+
2395
+ /* if post body is not defined, set it so we enable POST header, even though the request body is empty */
2396
+ if( rb_easy_nil("postdata_buffer") ) {
2397
+ ruby_curl_easy_post_body_set(self, post_body);
2398
+ }
2399
+
2400
+ return rb_funcall(self, rb_intern("perform"), 0);
2401
+ }
2402
+ }
2403
+ }
2404
+ static VALUE ruby_curl_easy_set_method_get(VALUE self, VALUE onoff) {
2405
+ ruby_curl_easy *rbce;
2406
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2407
+ curl_easy_setopt(rbce->curl, CURLOPT_HTTPGET, RTEST(onoff));
2408
+ return onoff;
2409
+ }
2410
+
2411
+ /*
2412
+ * call-seq:
2413
+ * easy.http_put(data) => true
2414
+ *
2415
+ * PUT the supplied data to the currently configured URL using the
2416
+ * current options set for this Curl::Easy instance. This method always
2417
+ * returns true, or raises an exception (defined under Curl::Err) on error.
2418
+ */
2419
+ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2420
+ ruby_curl_easy *rbce;
2421
+ CURL *curl;
2422
+
2423
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2424
+ curl = rbce->curl;
2425
+
2426
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2427
+ ruby_curl_easy_put_data_set(self, data);
2428
+
2429
+ return rb_funcall(self, rb_intern("perform"), 0);
2430
+ }
2431
+
2432
+
2433
+ /* =================== DATA FUNCS =============== */
2434
+
2435
+ /*
2436
+ * call-seq:
2437
+ * easy.body_str => "response body"
2438
+ *
2439
+ * Return the response body from the previous call to +perform+. This
2440
+ * is populated by the default +on_body+ handler - if you supply
2441
+ * your own body handler, this string will be empty.
2442
+ */
2443
+ static VALUE ruby_curl_easy_body_str_get(VALUE self) {
2444
+ CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
2445
+ }
2446
+
2447
+ /*
2448
+ * call-seq:
2449
+ * easy.header_str => "response header"
2450
+ *
2451
+ * Return the response header from the previous call to +perform+. This
2452
+ * is populated by the default +on_header+ handler - if you supply
2453
+ * your own header handler, this string will be empty.
2454
+ */
2455
+ static VALUE ruby_curl_easy_header_str_get(VALUE self) {
2456
+ CURB_OBJECT_HGETTER(ruby_curl_easy, header_data);
2457
+ }
2458
+
2459
+
2460
+ /* ============== LASTCONN INFO FUNCS ============ */
2461
+
2462
+ /*
2463
+ * call-seq:
2464
+ * easy.last_effective_url => "http://some.url" or nil
2465
+ *
2466
+ * Retrieve the last effective URL used by this instance.
2467
+ * This is the URL used in the last +perform+ call,
2468
+ * and may differ from the value of easy.url.
2469
+ */
2470
+ static VALUE ruby_curl_easy_last_effective_url_get(VALUE self) {
2471
+ ruby_curl_easy *rbce;
2472
+ char* url;
2473
+
2474
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2475
+ curl_easy_getinfo(rbce->curl, CURLINFO_EFFECTIVE_URL, &url);
2476
+
2477
+ if (url && url[0]) { // curl returns empty string if none
2478
+ return rb_str_new2(url);
2479
+ } else {
2480
+ return Qnil;
2481
+ }
2482
+ }
2483
+
2484
+ /*
2485
+ * call-seq:
2486
+ * easy.response_code => fixnum
2487
+ *
2488
+ * Retrieve the last received HTTP or FTP code. This will be zero
2489
+ * if no server response code has been received. Note that a proxy's
2490
+ * CONNECT response should be read with +http_connect_code+
2491
+ * and not this method.
2492
+ */
2493
+ static VALUE ruby_curl_easy_response_code_get(VALUE self) {
2494
+ ruby_curl_easy *rbce;
2495
+ long code;
2496
+
2497
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2498
+ #ifdef HAVE_CURLINFO_RESPONSE_CODE
2499
+ curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &code);
2500
+ #else
2501
+ // old libcurl
2502
+ curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &code);
2503
+ #endif
2504
+
2505
+ return LONG2NUM(code);
2506
+ }
2507
+
2508
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
2509
+ /*
2510
+ * call-seq:
2511
+ * easy.primary_ip => "xx.xx.xx.xx" or nil
2512
+ *
2513
+ * Retrieve the resolved IP of the most recent connection
2514
+ * done with this curl handle. This string may be IPv6 if
2515
+ * that's enabled. This feature requires curl 7.19.x and above
2516
+ */
2517
+ static VALUE ruby_curl_easy_primary_ip_get(VALUE self) {
2518
+ ruby_curl_easy *rbce;
2519
+ char* ip;
2520
+
2521
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2522
+ curl_easy_getinfo(rbce->curl, CURLINFO_PRIMARY_IP, &ip);
2523
+
2524
+ if (ip && ip[0]) { // curl returns empty string if none
2525
+ return rb_str_new2(ip);
2526
+ } else {
2527
+ return Qnil;
2528
+ }
2529
+ }
2530
+ #endif
2531
+
2532
+ /*
2533
+ * call-seq:
2534
+ * easy.http_connect_code => fixnum
2535
+ *
2536
+ * Retrieve the last received proxy response code to a CONNECT request.
2537
+ */
2538
+ static VALUE ruby_curl_easy_http_connect_code_get(VALUE self) {
2539
+ ruby_curl_easy *rbce;
2540
+ long code;
2541
+
2542
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2543
+ curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CONNECTCODE, &code);
2544
+
2545
+ return LONG2NUM(code);
2546
+ }
2547
+
2548
+ /*
2549
+ * call-seq:
2550
+ * easy.file_time => fixnum
2551
+ *
2552
+ * Retrieve the remote time of the retrieved document (in number of
2553
+ * seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1,
2554
+ * it can be because of many reasons (unknown, the server hides it
2555
+ * or the server doesn't support the command that tells document time
2556
+ * etc) and the time of the document is unknown.
2557
+ *
2558
+ * Note that you must tell the server to collect this information
2559
+ * before the transfer is made, by setting +fetch_file_time?+ to true,
2560
+ * or you will unconditionally get a -1 back.
2561
+ *
2562
+ * This requires libcurl 7.5 or higher - otherwise -1 is unconditionally
2563
+ * returned.
2564
+ */
2565
+ static VALUE ruby_curl_easy_file_time_get(VALUE self) {
2566
+ #ifdef HAVE_CURLINFO_FILETIME
2567
+ ruby_curl_easy *rbce;
2568
+ long time;
2569
+
2570
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2571
+ curl_easy_getinfo(rbce->curl, CURLINFO_FILETIME, &time);
2572
+
2573
+ return LONG2NUM(time);
2574
+ #else
2575
+ rb_warn("Installed libcurl is too old to support file_time");
2576
+ return INT2FIX(0);
2577
+ #endif
2578
+ }
2579
+
2580
+ /*
2581
+ * call-seq:
2582
+ * easy.total_time => float
2583
+ *
2584
+ * Retrieve the total time in seconds for the previous transfer,
2585
+ * including name resolving, TCP connect etc.
2586
+ */
2587
+ static VALUE ruby_curl_easy_total_time_get(VALUE self) {
2588
+ ruby_curl_easy *rbce;
2589
+ double time;
2590
+
2591
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2592
+ curl_easy_getinfo(rbce->curl, CURLINFO_TOTAL_TIME, &time);
2593
+
2594
+ return rb_float_new(time);
2595
+ }
2596
+
2597
+ /*
2598
+ * call-seq:
2599
+ * easy.name_lookup_time => float
2600
+ *
2601
+ * Retrieve the time, in seconds, it took from the start until the
2602
+ * name resolving was completed.
2603
+ */
2604
+ static VALUE ruby_curl_easy_name_lookup_time_get(VALUE self) {
2605
+ ruby_curl_easy *rbce;
2606
+ double time;
2607
+
2608
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2609
+ curl_easy_getinfo(rbce->curl, CURLINFO_NAMELOOKUP_TIME, &time);
2610
+
2611
+ return rb_float_new(time);
2612
+ }
2613
+
2614
+ /*
2615
+ * call-seq:
2616
+ * easy.connect_time => float
2617
+ *
2618
+ * Retrieve the time, in seconds, it took from the start until the
2619
+ * connect to the remote host (or proxy) was completed.
2620
+ */
2621
+ static VALUE ruby_curl_easy_connect_time_get(VALUE self) {
2622
+ ruby_curl_easy *rbce;
2623
+ double time;
2624
+
2625
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2626
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONNECT_TIME, &time);
2627
+
2628
+ return rb_float_new(time);
2629
+ }
2630
+
2631
+ /*
2632
+ * call-seq:
2633
+ * easy.pre_transfer_time => float
2634
+ *
2635
+ * Retrieve the time, in seconds, it took from the start until the
2636
+ * file transfer is just about to begin. This includes all pre-transfer
2637
+ * commands and negotiations that are specific to the particular protocol(s)
2638
+ * involved.
2639
+ */
2640
+ static VALUE ruby_curl_easy_pre_transfer_time_get(VALUE self) {
2641
+ ruby_curl_easy *rbce;
2642
+ double time;
2643
+
2644
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2645
+ curl_easy_getinfo(rbce->curl, CURLINFO_PRETRANSFER_TIME, &time);
2646
+
2647
+ return rb_float_new(time);
2648
+ }
2649
+
2650
+ /*
2651
+ * call-seq:
2652
+ * easy.start_transfer_time => float
2653
+ *
2654
+ * Retrieve the time, in seconds, it took from the start until the first byte
2655
+ * is just about to be transferred. This includes the +pre_transfer_time+ and
2656
+ * also the time the server needs to calculate the result.
2657
+ */
2658
+ static VALUE ruby_curl_easy_start_transfer_time_get(VALUE self) {
2659
+ ruby_curl_easy *rbce;
2660
+ double time;
2661
+
2662
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2663
+ curl_easy_getinfo(rbce->curl, CURLINFO_STARTTRANSFER_TIME, &time);
2664
+
2665
+ return rb_float_new(time);
2666
+ }
2667
+
2668
+ /*
2669
+ * call-seq:
2670
+ * easy.redirect_time => float
2671
+ *
2672
+ * Retrieve the total time, in seconds, it took for all redirection steps
2673
+ * include name lookup, connect, pretransfer and transfer before final
2674
+ * transaction was started. +redirect_time+ contains the complete
2675
+ * execution time for multiple redirections.
2676
+ *
2677
+ * Requires libcurl 7.9.7 or higher, otherwise -1 is always returned.
2678
+ */
2679
+ static VALUE ruby_curl_easy_redirect_time_get(VALUE self) {
2680
+ #ifdef HAVE_CURLINFO_REDIRECT_TIME
2681
+ ruby_curl_easy *rbce;
2682
+ double time;
2683
+
2684
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2685
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_TIME, &time);
2686
+
2687
+ return rb_float_new(time);
2688
+ #else
2689
+ rb_warn("Installed libcurl is too old to support redirect_time");
2690
+ return rb_float_new(-1);
2691
+ #endif
2692
+ }
2693
+
2694
+ /*
2695
+ * call-seq:
2696
+ * easy.redirect_count => integer
2697
+ *
2698
+ * Retrieve the total number of redirections that were actually followed.
2699
+ *
2700
+ * Requires libcurl 7.9.7 or higher, otherwise -1 is always returned.
2701
+ */
2702
+ static VALUE ruby_curl_easy_redirect_count_get(VALUE self) {
2703
+ #ifdef HAVE_CURLINFO_REDIRECT_COUNT
2704
+ ruby_curl_easy *rbce;
2705
+ long count;
2706
+
2707
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2708
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_COUNT, &count);
2709
+
2710
+ return LONG2NUM(count);
2711
+ #else
2712
+ rb_warn("Installed libcurl is too old to support redirect_count");
2713
+ return INT2FIX(-1);
2714
+ #endif
2715
+
2716
+ }
2717
+
2718
+ /*
2719
+ * call-seq:
2720
+ * easy.redirect_url => "http://some.url" or nil
2721
+ *
2722
+ * Retrieve the URL a redirect would take you to if you
2723
+ * would enable CURLOPT_FOLLOWLOCATION.
2724
+ *
2725
+ * Requires libcurl 7.18.2 or higher, otherwise -1 is always returned.
2726
+ */
2727
+ static VALUE ruby_curl_easy_redirect_url_get(VALUE self) {
2728
+ #ifdef HAVE_CURLINFO_REDIRECT_URL
2729
+ ruby_curl_easy *rbce;
2730
+ char* url;
2731
+
2732
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2733
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_URL, &url);
2734
+
2735
+ if (url && url[0]) { // curl returns empty string if none
2736
+ return rb_str_new2(url);
2737
+ } else {
2738
+ return Qnil;
2739
+ }
2740
+ #else
2741
+ rb_warn("Installed libcurl is too old to support redirect_url");
2742
+ return INT2FIX(-1);
2743
+ #endif
2744
+ }
2745
+
2746
+
2747
+
2748
+ /*
2749
+ * call-seq:
2750
+ * easy.uploaded_bytes => float
2751
+ *
2752
+ * Retrieve the total amount of bytes that were uploaded in the
2753
+ * preceeding transfer.
2754
+ */
2755
+ static VALUE ruby_curl_easy_uploaded_bytes_get(VALUE self) {
2756
+ ruby_curl_easy *rbce;
2757
+ double bytes;
2758
+
2759
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2760
+ curl_easy_getinfo(rbce->curl, CURLINFO_SIZE_UPLOAD, &bytes);
2761
+
2762
+ return rb_float_new(bytes);
2763
+ }
2764
+
2765
+ /*
2766
+ * call-seq:
2767
+ * easy.downloaded_bytes => float
2768
+ *
2769
+ * Retrieve the total amount of bytes that were downloaded in the
2770
+ * preceeding transfer.
2771
+ */
2772
+ static VALUE ruby_curl_easy_downloaded_bytes_get(VALUE self) {
2773
+ ruby_curl_easy *rbce;
2774
+ double bytes;
2775
+
2776
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2777
+ curl_easy_getinfo(rbce->curl, CURLINFO_SIZE_DOWNLOAD, &bytes);
2778
+
2779
+ return rb_float_new(bytes);
2780
+ }
2781
+
2782
+ /*
2783
+ * call-seq:
2784
+ * easy.upload_speed => float
2785
+ *
2786
+ * Retrieve the average upload speed that curl measured for the
2787
+ * preceeding complete upload.
2788
+ */
2789
+ static VALUE ruby_curl_easy_upload_speed_get(VALUE self) {
2790
+ ruby_curl_easy *rbce;
2791
+ double bytes;
2792
+
2793
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2794
+ curl_easy_getinfo(rbce->curl, CURLINFO_SPEED_UPLOAD, &bytes);
2795
+
2796
+ return rb_float_new(bytes);
2797
+ }
2798
+
2799
+ /*
2800
+ * call-seq:
2801
+ * easy.download_speed => float
2802
+ *
2803
+ * Retrieve the average download speed that curl measured for
2804
+ * the preceeding complete download.
2805
+ */
2806
+ static VALUE ruby_curl_easy_download_speed_get(VALUE self) {
2807
+ ruby_curl_easy *rbce;
2808
+ double bytes;
2809
+
2810
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2811
+ curl_easy_getinfo(rbce->curl, CURLINFO_SPEED_DOWNLOAD, &bytes);
2812
+
2813
+ return rb_float_new(bytes);
2814
+ }
2815
+
2816
+ /*
2817
+ * call-seq:
2818
+ * easy.header_size => fixnum
2819
+ *
2820
+ * Retrieve the total size of all the headers received in the
2821
+ * preceeding transfer.
2822
+ */
2823
+ static VALUE ruby_curl_easy_header_size_get(VALUE self) {
2824
+ ruby_curl_easy *rbce;
2825
+ long size;
2826
+
2827
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2828
+ curl_easy_getinfo(rbce->curl, CURLINFO_HEADER_SIZE, &size);
2829
+
2830
+ return LONG2NUM(size);
2831
+ }
2832
+
2833
+ /*
2834
+ * call-seq:
2835
+ * easy.request_size => fixnum
2836
+ *
2837
+ * Retrieve the total size of the issued requests. This is so far
2838
+ * only for HTTP requests. Note that this may be more than one request
2839
+ * if +follow_location?+ is true.
2840
+ */
2841
+ static VALUE ruby_curl_easy_request_size_get(VALUE self) {
2842
+ ruby_curl_easy *rbce;
2843
+ long size;
2844
+
2845
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2846
+ curl_easy_getinfo(rbce->curl, CURLINFO_REQUEST_SIZE, &size);
2847
+
2848
+ return LONG2NUM(size);
2849
+ }
2850
+
2851
+ /*
2852
+ * call-seq:
2853
+ * easy.ssl_verify_result => integer
2854
+ *
2855
+ * Retrieve the result of the certification verification that was requested
2856
+ * (by setting +ssl_verify_peer?+ to +true+).
2857
+ */
2858
+ static VALUE ruby_curl_easy_ssl_verify_result_get(VALUE self) {
2859
+ ruby_curl_easy *rbce;
2860
+ long result;
2861
+
2862
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2863
+ curl_easy_getinfo(rbce->curl, CURLINFO_SSL_VERIFYRESULT, &result);
2864
+
2865
+ return LONG2NUM(result);
2866
+ }
2867
+
2868
+ /* TODO CURLINFO_SSL_ENGINES
2869
+
2870
+ Pass the address of a 'struct curl_slist *' to receive a linked-list of OpenSSL crypto-engines supported.
2871
+ Note that engines are normally implemented in separate dynamic libraries.
2872
+ Hence not all the returned engines may be available at run-time.
2873
+ NOTE: you must call curl_slist_free_all(3) on the list pointer once you're done with it, as libcurl will not free the data for you. (Added in 7.12.3)
2874
+ */
2875
+
2876
+ /*
2877
+ * call-seq:
2878
+ * easy.downloaded_content_length => float
2879
+ *
2880
+ * Retrieve the content-length of the download. This is the value read
2881
+ * from the Content-Length: field.
2882
+ */
2883
+ static VALUE ruby_curl_easy_downloaded_content_length_get(VALUE self) {
2884
+ ruby_curl_easy *rbce;
2885
+ double bytes;
2886
+
2887
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2888
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &bytes);
2889
+
2890
+ return rb_float_new(bytes);
2891
+ }
2892
+
2893
+ /*
2894
+ * call-seq:
2895
+ * easy.uploaded_content_length => float
2896
+ *
2897
+ * Retrieve the content-length of the upload.
2898
+ */
2899
+ static VALUE ruby_curl_easy_uploaded_content_length_get(VALUE self) {
2900
+ ruby_curl_easy *rbce;
2901
+ double bytes;
2902
+
2903
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2904
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &bytes);
2905
+
2906
+ return rb_float_new(bytes);
2907
+ }
2908
+
2909
+ /*
2910
+ * call-seq:
2911
+ * easy.content_type => "content/type" or nil
2912
+ *
2913
+ * Retrieve the content-type of the downloaded object. This is the value read
2914
+ * from the Content-Type: field. If you get +nil+, it means that the server
2915
+ * didn't send a valid Content-Type header or that the protocol used doesn't
2916
+ * support this.
2917
+ */
2918
+ static VALUE ruby_curl_easy_content_type_get(VALUE self) {
2919
+ ruby_curl_easy *rbce;
2920
+ char* type;
2921
+
2922
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2923
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_TYPE, &type);
2924
+
2925
+ if (type && type[0]) { // curl returns empty string if none
2926
+ return rb_str_new2(type);
2927
+ } else {
2928
+ return Qnil;
2929
+ }
2930
+ }
2931
+
2932
+
2933
+ /* NOT REQUIRED?
2934
+ CURLINFO_PRIVATE
2935
+
2936
+ Pass a pointer to a 'char *' to receive the pointer to the private data associated with the curl handle (set with the CURLOPT_PRIVATE option to curl_easy_setopt(3)). (Added in 7.10.3)
2937
+ */
2938
+
2939
+ /* TODO these will need constants setting up too for checking the bits.
2940
+ *
2941
+ * Alternatively, could return an object that wraps the long, and has
2942
+ * question methods to query the auth types. Could return long from to_i(nt)
2943
+ *
2944
+ CURLINFO_HTTPAUTH_AVAIL
2945
+
2946
+ Pass a pointer to a long to receive a bitmask indicating the authentication method(s) available. The meaning of the bits is explained in the CURLOPT_HTTPAUTH option for curl_easy_setopt(3). (Added in 7.10.8)
2947
+
2948
+ CURLINFO_PROXYAUTH_AVAIL
2949
+
2950
+ Pass a pointer to a long to receive a bitmask indicating the authentication method(s) available for your proxy authentication. (Added in 7.10.8)
2951
+ */
2952
+
2953
+ /*
2954
+ * call-seq:
2955
+ * easy.os_errno => integer
2956
+ *
2957
+ * Retrieve the errno variable from a connect failure (requires
2958
+ * libcurl 7.12.2 or higher, otherwise 0 is always returned).
2959
+ */
2960
+ static VALUE ruby_curl_easy_os_errno_get(VALUE self) {
2961
+ #ifdef HAVE_CURLINFO_OS_ERRNO
2962
+ ruby_curl_easy *rbce;
2963
+ long result;
2964
+
2965
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2966
+ curl_easy_getinfo(rbce->curl, CURLINFO_OS_ERRNO, &result);
2967
+
2968
+ return LONG2NUM(result);
2969
+ #else
2970
+ rb_warn("Installed libcurl is too old to support os_errno");
2971
+ return INT2FIX(0);
2972
+ #endif
2973
+ }
2974
+
2975
+ /*
2976
+ * call-seq:
2977
+ * easy.num_connects => integer
2978
+ *
2979
+ * Retrieve the number of new connections libcurl had to create to achieve
2980
+ * the previous transfer (only the successful connects are counted).
2981
+ * Combined with +redirect_count+ you are able to know how many times libcurl
2982
+ * successfully reused existing connection(s) or not.
2983
+ *
2984
+ * See the Connection Options of curl_easy_setopt(3) to see how libcurl tries
2985
+ * to make persistent connections to save time.
2986
+ *
2987
+ * (requires libcurl 7.12.3 or higher, otherwise -1 is always returned).
2988
+ */
2989
+ static VALUE ruby_curl_easy_num_connects_get(VALUE self) {
2990
+ #ifdef HAVE_CURLINFO_NUM_CONNECTS
2991
+ ruby_curl_easy *rbce;
2992
+ long result;
2993
+
2994
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2995
+ curl_easy_getinfo(rbce->curl, CURLINFO_NUM_CONNECTS, &result);
2996
+
2997
+ return LONG2NUM(result);
2998
+ #else
2999
+ rb_warn("Installed libcurl is too old to support num_connects");
3000
+ return INT2FIX(-1);
3001
+ #endif
3002
+ }
3003
+
3004
+
3005
+ /* TODO this needs to be implemented.
3006
+
3007
+ CURLINFO_COOKIELIST
3008
+
3009
+ Pass a pointer to a 'struct curl_slist *' to receive a linked-list of all cookies cURL knows (expired ones, too). Don't forget to curl_slist_free_all(3) the list after it has been used. If there are no cookies (cookies for the handle have not been enabled or simply none have been received) 'struct curl_slist *' will be set to point to NULL. (Added in 7.14.1)
3010
+ */
3011
+
3012
+ /* TODO this needs to be implemented. Could probably support CONNECT_ONLY by having this
3013
+ * return an open Socket or something.
3014
+ *
3015
+ CURLINFO_LASTSOCKET
3016
+
3017
+ Pass a pointer to a long to receive the last socket used by this curl session. If the socket is no longer valid, -1 is returned. When you finish working with the socket, you must call curl_easy_cleanup() as usual and let libcurl close the socket and cleanup other resources associated with the handle. This is typically used in combination with CURLOPT_CONNECT_ONLY. (Added in 7.15.2)
3018
+ */
3019
+
3020
+ /*
3021
+ * call-seq:
3022
+ * easy.ftp_entry_path => "C:\ftp\root\" or nil
3023
+ *
3024
+ * Retrieve the path of the entry path. That is the initial path libcurl ended
3025
+ * up in when logging on to the remote FTP server. This returns +nil+ if
3026
+ * something is wrong.
3027
+ *
3028
+ * (requires libcurl 7.15.4 or higher, otherwise +nil+ is always returned).
3029
+ */
3030
+ static VALUE ruby_curl_easy_ftp_entry_path_get(VALUE self) {
3031
+ #ifdef HAVE_CURLINFO_FTP_ENTRY_PATH
3032
+ ruby_curl_easy *rbce;
3033
+ char* path = NULL;
3034
+
3035
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3036
+ curl_easy_getinfo(rbce->curl, CURLINFO_FTP_ENTRY_PATH, &path);
3037
+
3038
+ if (path && path[0]) { // curl returns NULL or empty string if none
3039
+ return rb_str_new2(path);
3040
+ } else {
3041
+ return Qnil;
3042
+ }
3043
+ #else
3044
+ rb_warn("Installed libcurl is too old to support num_connects");
3045
+ return Qnil;
3046
+ #endif
3047
+ }
3048
+
3049
+ /*
3050
+ * call-seq:
3051
+ * easy.multi => "#<Curl::Multi>"
3052
+ */
3053
+ static VALUE ruby_curl_easy_multi_get(VALUE self) {
3054
+ ruby_curl_easy *rbce;
3055
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3056
+ return rbce->multi;
3057
+ }
3058
+
3059
+ /*
3060
+ * call-seq:
3061
+ * easy.multi=multi => "#<Curl::Multi>"
3062
+ */
3063
+ static VALUE ruby_curl_easy_multi_set(VALUE self, VALUE multi) {
3064
+ ruby_curl_easy *rbce;
3065
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3066
+ rbce->multi = multi;
3067
+ return rbce->multi;
3068
+ }
3069
+
3070
+ /*
3071
+ * call-seq:
3072
+ * easy.last_result => 0
3073
+ */
3074
+ static VALUE ruby_curl_easy_last_result(VALUE self) {
3075
+ ruby_curl_easy *rbce;
3076
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3077
+ return INT2FIX(rbce->last_result);
3078
+ }
3079
+
3080
+ /*
3081
+ * call-seq:
3082
+ * easy.setopt Fixnum, value => value
3083
+ *
3084
+ * Iniital access to libcurl curl_easy_setopt
3085
+ */
3086
+ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3087
+ ruby_curl_easy *rbce;
3088
+ long option = FIX2LONG(opt);
3089
+
3090
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3091
+
3092
+ switch (option) {
3093
+ /* BEHAVIOR OPTIONS */
3094
+ case CURLOPT_VERBOSE: {
3095
+ VALUE verbose = val;
3096
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, verbose);
3097
+ } break;
3098
+ case CURLOPT_FOLLOWLOCATION: {
3099
+ VALUE follow_location = val;
3100
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, follow_location);
3101
+ } break;
3102
+ /* TODO: CALLBACK OPTIONS */
3103
+ /* TODO: ERROR OPTIONS */
3104
+ /* NETWORK OPTIONS */
3105
+ case CURLOPT_URL: {
3106
+ VALUE url = val;
3107
+ CURB_OBJECT_HSETTER(ruby_curl_easy, url);
3108
+ } break;
3109
+ case CURLOPT_CUSTOMREQUEST:
3110
+ curl_easy_setopt(rbce->curl, CURLOPT_CUSTOMREQUEST, NIL_P(val) ? NULL : StringValueCStr(val));
3111
+ break;
3112
+ case CURLOPT_HTTP_VERSION:
3113
+ curl_easy_setopt(rbce->curl, CURLOPT_HTTP_VERSION, FIX2INT(val));
3114
+ break;
3115
+ case CURLOPT_PROXY: {
3116
+ VALUE proxy_url = val;
3117
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxy_url);
3118
+ } break;
3119
+ case CURLOPT_INTERFACE: {
3120
+ VALUE interface_hm = val;
3121
+ CURB_OBJECT_HSETTER(ruby_curl_easy, interface_hm);
3122
+ } break;
3123
+ case CURLOPT_HEADER:
3124
+ case CURLOPT_NOPROGRESS:
3125
+ case CURLOPT_NOSIGNAL:
3126
+ case CURLOPT_HTTPGET:
3127
+ case CURLOPT_NOBODY: {
3128
+ int type = rb_type(val);
3129
+ VALUE value;
3130
+ if (type == T_TRUE) {
3131
+ value = rb_int_new(1);
3132
+ } else if (type == T_FALSE) {
3133
+ value = rb_int_new(0);
3134
+ } else {
3135
+ value = rb_funcall(val, rb_intern("to_i"), 0);
3136
+ }
3137
+ curl_easy_setopt(rbce->curl, option, FIX2INT(value));
3138
+ } break;
3139
+ case CURLOPT_USERPWD: {
3140
+ VALUE userpwd = val;
3141
+ CURB_OBJECT_HSETTER(ruby_curl_easy, userpwd);
3142
+ } break;
3143
+ case CURLOPT_PROXYUSERPWD: {
3144
+ VALUE proxypwd = val;
3145
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxypwd);
3146
+ } break;
3147
+ case CURLOPT_COOKIE: {
3148
+ VALUE cookies = val;
3149
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookies);
3150
+ } break;
3151
+ case CURLOPT_COOKIEFILE: {
3152
+ VALUE cookiefile = val;
3153
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiefile);
3154
+ } break;
3155
+ case CURLOPT_COOKIEJAR: {
3156
+ VALUE cookiejar = val;
3157
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiejar);
3158
+ } break;
3159
+ case CURLOPT_RESUME_FROM: {
3160
+ curl_easy_setopt(rbce->curl, CURLOPT_RESUME_FROM, FIX2LONG(val));
3161
+ } break;
3162
+ case CURLOPT_FAILONERROR: {
3163
+ curl_easy_setopt(rbce->curl, CURLOPT_FAILONERROR, FIX2LONG(val));
3164
+ } break;
3165
+ default:
3166
+ break;
3167
+ }
3168
+
3169
+ return val;
3170
+ }
3171
+
3172
+ /*
3173
+ * call-seq:
3174
+ * easy.getinfo Fixnum => value
3175
+ *
3176
+ * Iniital access to libcurl curl_easy_getinfo, remember getinfo doesn't return the same values as setopt
3177
+ */
3178
+ static VALUE ruby_curl_easy_get_opt(VALUE self, VALUE opt) {
3179
+ return Qnil;
3180
+ }
3181
+
3182
+ /*
3183
+ * call-seq:
3184
+ * easy.inspect => "#<Curl::Easy http://google.com/>"
3185
+ */
3186
+ static VALUE ruby_curl_easy_inspect(VALUE self) {
3187
+ char buf[64];
3188
+ ruby_curl_easy *rbce;
3189
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3190
+ /* if we don't have a url set... we'll crash... */
3191
+ if( !rb_easy_nil("url") && rb_easy_type_check("url", T_STRING)) {
3192
+ VALUE url = rb_easy_get("url");
3193
+ size_t len = 13+((RSTRING_LEN(url) > 50) ? 50 : RSTRING_LEN(url));
3194
+ /* "#<Net::HTTP http://www.google.com/:80 open=false>" */
3195
+ memcpy(buf,"#<Curl::Easy ", 13);
3196
+ memcpy(buf+13,StringValueCStr(url), (len - 13));
3197
+ buf[len++] = '>';
3198
+ return rb_str_new(buf,len);
3199
+ }
3200
+ return rb_str_new2("#<Curl::Easy>");
3201
+ }
3202
+
3203
+
3204
+ /* ================== ESCAPING FUNCS ==============*/
3205
+
3206
+ /*
3207
+ * call-seq:
3208
+ * easy.escape("some text") => "some%20text"
3209
+ *
3210
+ * Convert the given input string to a URL encoded string and return
3211
+ * the result. All input characters that are not a-z, A-Z or 0-9 are
3212
+ * converted to their "URL escaped" version (%NN where NN is a
3213
+ * two-digit hexadecimal number).
3214
+ */
3215
+ static VALUE ruby_curl_easy_escape(VALUE self, VALUE svalue) {
3216
+ ruby_curl_easy *rbce;
3217
+ char *result;
3218
+ VALUE rresult;
3219
+ VALUE str = svalue;
3220
+
3221
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3222
+
3223
+ /* NOTE: make sure the value is a string, if not call to_s */
3224
+ if( rb_type(str) != T_STRING ) { str = rb_funcall(str,rb_intern("to_s"),0); }
3225
+
3226
+ #if (LIBCURL_VERSION_NUM >= 0x070f04)
3227
+ result = (char*)curl_easy_escape(rbce->curl, StringValuePtr(str), (int)RSTRING_LEN(str));
3228
+ #else
3229
+ result = (char*)curl_escape(StringValuePtr(str), (int)RSTRING_LEN(str));
3230
+ #endif
3231
+
3232
+ rresult = rb_str_new2(result);
3233
+ curl_free(result);
3234
+
3235
+ return rresult;
3236
+ }
3237
+
3238
+ /*
3239
+ * call-seq:
3240
+ * easy.unescape("some%20text") => "some text"
3241
+ *
3242
+ * Convert the given URL encoded input string to a "plain string" and return
3243
+ * the result. All input characters that are URL encoded (%XX where XX is a
3244
+ * two-digit hexadecimal number) are converted to their binary versions.
3245
+ */
3246
+ static VALUE ruby_curl_easy_unescape(VALUE self, VALUE str) {
3247
+ ruby_curl_easy *rbce;
3248
+ int rlen;
3249
+ char *result;
3250
+ VALUE rresult;
3251
+
3252
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3253
+
3254
+ #if (LIBCURL_VERSION_NUM >= 0x070f04)
3255
+ result = (char*)curl_easy_unescape(rbce->curl, StringValuePtr(str), (int)RSTRING_LEN(str), &rlen);
3256
+ #else
3257
+ result = (char*)curl_unescape(StringValuePtr(str), RSTRING_LEN(str));
3258
+ rlen = strlen(result);
3259
+ #endif
3260
+
3261
+ rresult = rb_str_new(result, rlen);
3262
+ curl_free(result);
3263
+
3264
+ return rresult;
3265
+ }
3266
+
3267
+
3268
+ /* ================= CLASS METHODS ==================*/
3269
+
3270
+ /*
3271
+ * call-seq:
3272
+ * Curl::Easy.error(code) => String
3273
+ *
3274
+ * translate an internal libcurl error to ruby error class
3275
+ */
3276
+ static VALUE ruby_curl_easy_error_message(VALUE klass, VALUE code) {
3277
+ return rb_curl_easy_error(FIX2INT(code));
3278
+ }
3279
+
3280
+ /* =================== INIT LIB =====================*/
3281
+ void init_curb_easy() {
3282
+ idCall = rb_intern("call");
3283
+ idJoin = rb_intern("join");
3284
+
3285
+ rbstrAmp = rb_str_new2("&");
3286
+ rb_global_variable(&rbstrAmp);
3287
+
3288
+ cCurlEasy = rb_define_class_under(mCurl, "Easy", rb_cObject);
3289
+
3290
+ /* Class methods */
3291
+ rb_define_singleton_method(cCurlEasy, "new", ruby_curl_easy_new, -1);
3292
+ rb_define_singleton_method(cCurlEasy, "error", ruby_curl_easy_error_message, 1);
3293
+
3294
+ /* Attributes for config next perform */
3295
+ rb_define_method(cCurlEasy, "url", ruby_curl_easy_url_get, 0);
3296
+ rb_define_method(cCurlEasy, "proxy_url", ruby_curl_easy_proxy_url_get, 0);
3297
+ rb_define_method(cCurlEasy, "headers=", ruby_curl_easy_headers_set, 1);
3298
+ rb_define_method(cCurlEasy, "headers", ruby_curl_easy_headers_get, 0);
3299
+ rb_define_method(cCurlEasy, "interface", ruby_curl_easy_interface_get, 0);
3300
+ rb_define_method(cCurlEasy, "userpwd", ruby_curl_easy_userpwd_get, 0);
3301
+ rb_define_method(cCurlEasy, "proxypwd", ruby_curl_easy_proxypwd_get, 0);
3302
+ rb_define_method(cCurlEasy, "cookies", ruby_curl_easy_cookies_get, 0);
3303
+ rb_define_method(cCurlEasy, "cookiefile", ruby_curl_easy_cookiefile_get, 0);
3304
+ rb_define_method(cCurlEasy, "cookiejar", ruby_curl_easy_cookiejar_get, 0);
3305
+ rb_define_method(cCurlEasy, "cert=", ruby_curl_easy_cert_set, 1);
3306
+ rb_define_method(cCurlEasy, "cert", ruby_curl_easy_cert_get, 0);
3307
+ rb_define_method(cCurlEasy, "cert_key=", ruby_curl_easy_cert_key_set, 1);
3308
+ rb_define_method(cCurlEasy, "cert_key", ruby_curl_easy_cert_key_get, 0);
3309
+ rb_define_method(cCurlEasy, "cacert=", ruby_curl_easy_cacert_set, 1);
3310
+ rb_define_method(cCurlEasy, "cacert", ruby_curl_easy_cacert_get, 0);
3311
+ rb_define_method(cCurlEasy, "certpassword=", ruby_curl_easy_certpassword_set, 1);
3312
+ rb_define_method(cCurlEasy, "certtype=", ruby_curl_easy_certtype_set, 1);
3313
+ rb_define_method(cCurlEasy, "certtype", ruby_curl_easy_certtype_get, 0);
3314
+ rb_define_method(cCurlEasy, "encoding=", ruby_curl_easy_encoding_set, 1);
3315
+ rb_define_method(cCurlEasy, "encoding", ruby_curl_easy_encoding_get, 0);
3316
+ rb_define_method(cCurlEasy, "useragent=", ruby_curl_easy_useragent_set, 1);
3317
+ rb_define_method(cCurlEasy, "useragent", ruby_curl_easy_useragent_get, 0);
3318
+ rb_define_method(cCurlEasy, "multipart_post_body=", ruby_curl_easy_multipart_post_body_set, 1);
3319
+ rb_define_method(cCurlEasy, "post_body=", ruby_curl_easy_post_body_set, 1);
3320
+ rb_define_method(cCurlEasy, "post_body", ruby_curl_easy_post_body_get, 0);
3321
+ rb_define_method(cCurlEasy, "put_data=", ruby_curl_easy_put_data_set, 1);
3322
+ rb_define_method(cCurlEasy, "ftp_commands=", ruby_curl_easy_ftp_commands_set, 1);
3323
+ rb_define_method(cCurlEasy, "ftp_commands", ruby_curl_easy_ftp_commands_get, 0);
3324
+
3325
+ rb_define_method(cCurlEasy, "local_port=", ruby_curl_easy_local_port_set, 1);
3326
+ rb_define_method(cCurlEasy, "local_port", ruby_curl_easy_local_port_get, 0);
3327
+ rb_define_method(cCurlEasy, "local_port_range=", ruby_curl_easy_local_port_range_set, 1);
3328
+ rb_define_method(cCurlEasy, "local_port_range", ruby_curl_easy_local_port_range_get, 0);
3329
+ rb_define_method(cCurlEasy, "proxy_port=", ruby_curl_easy_proxy_port_set, 1);
3330
+ rb_define_method(cCurlEasy, "proxy_port", ruby_curl_easy_proxy_port_get, 0);
3331
+ rb_define_method(cCurlEasy, "proxy_type=", ruby_curl_easy_proxy_type_set, 1);
3332
+ rb_define_method(cCurlEasy, "proxy_type", ruby_curl_easy_proxy_type_get, 0);
3333
+ rb_define_method(cCurlEasy, "http_auth_types=", ruby_curl_easy_http_auth_types_set, -1);
3334
+ rb_define_method(cCurlEasy, "http_auth_types", ruby_curl_easy_http_auth_types_get, 0);
3335
+ rb_define_method(cCurlEasy, "proxy_auth_types=", ruby_curl_easy_proxy_auth_types_set, 1);
3336
+ rb_define_method(cCurlEasy, "proxy_auth_types", ruby_curl_easy_proxy_auth_types_get, 0);
3337
+ rb_define_method(cCurlEasy, "max_redirects=", ruby_curl_easy_max_redirects_set, 1);
3338
+ rb_define_method(cCurlEasy, "max_redirects", ruby_curl_easy_max_redirects_get, 0);
3339
+ rb_define_method(cCurlEasy, "timeout=", ruby_curl_easy_timeout_set, 1);
3340
+ rb_define_method(cCurlEasy, "timeout", ruby_curl_easy_timeout_get, 0);
3341
+ rb_define_method(cCurlEasy, "connect_timeout=", ruby_curl_easy_connect_timeout_set, 1);
3342
+ rb_define_method(cCurlEasy, "connect_timeout", ruby_curl_easy_connect_timeout_get, 0);
3343
+ rb_define_method(cCurlEasy, "dns_cache_timeout=", ruby_curl_easy_dns_cache_timeout_set, 1);
3344
+ rb_define_method(cCurlEasy, "dns_cache_timeout", ruby_curl_easy_dns_cache_timeout_get, 0);
3345
+ rb_define_method(cCurlEasy, "ftp_response_timeout=", ruby_curl_easy_ftp_response_timeout_set, 1);
3346
+ rb_define_method(cCurlEasy, "ftp_response_timeout", ruby_curl_easy_ftp_response_timeout_get, 0);
3347
+ rb_define_method(cCurlEasy, "low_speed_limit=", ruby_curl_easy_low_speed_limit_set, 1);
3348
+ rb_define_method(cCurlEasy, "low_speed_limit", ruby_curl_easy_low_speed_limit_get, 0);
3349
+ rb_define_method(cCurlEasy, "low_speed_time=", ruby_curl_easy_low_speed_time_set, 1);
3350
+ rb_define_method(cCurlEasy, "low_speed_time", ruby_curl_easy_low_speed_time_get, 0);
3351
+ rb_define_method(cCurlEasy, "ssl_version=", ruby_curl_easy_ssl_version_set, 1);
3352
+ rb_define_method(cCurlEasy, "ssl_version", ruby_curl_easy_ssl_version_get, 0);
3353
+ rb_define_method(cCurlEasy, "use_ssl=", ruby_curl_easy_use_ssl_set, 1);
3354
+ rb_define_method(cCurlEasy, "use_ssl", ruby_curl_easy_use_ssl_get, 0);
3355
+ rb_define_method(cCurlEasy, "ftp_filemethod=", ruby_curl_easy_ftp_filemethod_set, 1);
3356
+ rb_define_method(cCurlEasy, "ftp_filemethod", ruby_curl_easy_ftp_filemethod_get, 0);
3357
+
3358
+ rb_define_method(cCurlEasy, "username=", ruby_curl_easy_username_set, 1);
3359
+ rb_define_method(cCurlEasy, "username", ruby_curl_easy_username_get, 0);
3360
+ rb_define_method(cCurlEasy, "password=", ruby_curl_easy_password_set, 1);
3361
+ rb_define_method(cCurlEasy, "password", ruby_curl_easy_password_get, 0);
3362
+
3363
+ rb_define_method(cCurlEasy, "proxy_tunnel=", ruby_curl_easy_proxy_tunnel_set, 1);
3364
+ rb_define_method(cCurlEasy, "proxy_tunnel?", ruby_curl_easy_proxy_tunnel_q, 0);
3365
+ rb_define_method(cCurlEasy, "fetch_file_time=", ruby_curl_easy_fetch_file_time_set, 1);
3366
+ rb_define_method(cCurlEasy, "fetch_file_time?", ruby_curl_easy_fetch_file_time_q, 0);
3367
+ rb_define_method(cCurlEasy, "ssl_verify_peer=", ruby_curl_easy_ssl_verify_peer_set, 1);
3368
+ rb_define_method(cCurlEasy, "ssl_verify_peer?", ruby_curl_easy_ssl_verify_peer_q, 0);
3369
+ rb_define_method(cCurlEasy, "ssl_verify_host_integer=", ruby_curl_easy_ssl_verify_host_set, 1);
3370
+ rb_define_method(cCurlEasy, "ssl_verify_host", ruby_curl_easy_ssl_verify_host_get, 0);
3371
+ rb_define_method(cCurlEasy, "header_in_body=", ruby_curl_easy_header_in_body_set, 1);
3372
+ rb_define_method(cCurlEasy, "header_in_body?", ruby_curl_easy_header_in_body_q, 0);
3373
+ rb_define_method(cCurlEasy, "use_netrc=", ruby_curl_easy_use_netrc_set, 1);
3374
+ rb_define_method(cCurlEasy, "use_netrc?", ruby_curl_easy_use_netrc_q, 0);
3375
+ rb_define_method(cCurlEasy, "follow_location?", ruby_curl_easy_follow_location_q, 0);
3376
+ rb_define_method(cCurlEasy, "autoreferer=", ruby_curl_easy_autoreferer_set, 1);
3377
+ rb_define_method(cCurlEasy, "unrestricted_auth=", ruby_curl_easy_unrestricted_auth_set, 1);
3378
+ rb_define_method(cCurlEasy, "unrestricted_auth?", ruby_curl_easy_unrestricted_auth_q, 0);
3379
+ rb_define_method(cCurlEasy, "verbose=", ruby_curl_easy_verbose_set, 1);
3380
+ rb_define_method(cCurlEasy, "verbose?", ruby_curl_easy_verbose_q, 0);
3381
+ rb_define_method(cCurlEasy, "multipart_form_post=", ruby_curl_easy_multipart_form_post_set, 1);
3382
+ rb_define_method(cCurlEasy, "multipart_form_post?", ruby_curl_easy_multipart_form_post_q, 0);
3383
+ rb_define_method(cCurlEasy, "enable_cookies=", ruby_curl_easy_enable_cookies_set, 1);
3384
+ rb_define_method(cCurlEasy, "enable_cookies?", ruby_curl_easy_enable_cookies_q, 0);
3385
+ rb_define_method(cCurlEasy, "ignore_content_length=", ruby_curl_easy_ignore_content_length_set, 1);
3386
+ rb_define_method(cCurlEasy, "ignore_content_length?", ruby_curl_easy_ignore_content_length_q, 0);
3387
+ rb_define_method(cCurlEasy, "resolve_mode", ruby_curl_easy_resolve_mode, 0);
3388
+ rb_define_method(cCurlEasy, "resolve_mode=", ruby_curl_easy_resolve_mode_set, 1);
3389
+
3390
+ rb_define_method(cCurlEasy, "on_body", ruby_curl_easy_on_body_set, -1);
3391
+ rb_define_method(cCurlEasy, "on_header", ruby_curl_easy_on_header_set, -1);
3392
+ rb_define_method(cCurlEasy, "on_progress", ruby_curl_easy_on_progress_set, -1);
3393
+ rb_define_method(cCurlEasy, "on_debug", ruby_curl_easy_on_debug_set, -1);
3394
+ rb_define_method(cCurlEasy, "on_success", ruby_curl_easy_on_success_set, -1);
3395
+ rb_define_method(cCurlEasy, "on_failure", ruby_curl_easy_on_failure_set, -1);
3396
+ rb_define_method(cCurlEasy, "on_missing", ruby_curl_easy_on_missing_set, -1);
3397
+ rb_define_method(cCurlEasy, "on_redirect", ruby_curl_easy_on_redirect_set, -1);
3398
+ rb_define_method(cCurlEasy, "on_complete", ruby_curl_easy_on_complete_set, -1);
3399
+
3400
+ rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
3401
+ rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
3402
+ rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
3403
+
3404
+ /* Post-perform info methods */
3405
+ rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
3406
+ rb_define_method(cCurlEasy, "header_str", ruby_curl_easy_header_str_get, 0);
3407
+
3408
+ rb_define_method(cCurlEasy, "last_effective_url", ruby_curl_easy_last_effective_url_get, 0);
3409
+ rb_define_method(cCurlEasy, "response_code", ruby_curl_easy_response_code_get, 0);
3410
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
3411
+ rb_define_method(cCurlEasy, "primary_ip", ruby_curl_easy_primary_ip_get, 0);
3412
+ #endif
3413
+ rb_define_method(cCurlEasy, "http_connect_code", ruby_curl_easy_http_connect_code_get, 0);
3414
+ rb_define_method(cCurlEasy, "file_time", ruby_curl_easy_file_time_get, 0);
3415
+ rb_define_method(cCurlEasy, "total_time", ruby_curl_easy_total_time_get, 0);
3416
+ rb_define_method(cCurlEasy, "name_lookup_time", ruby_curl_easy_name_lookup_time_get, 0);
3417
+ rb_define_method(cCurlEasy, "connect_time", ruby_curl_easy_connect_time_get, 0);
3418
+ rb_define_method(cCurlEasy, "pre_transfer_time", ruby_curl_easy_pre_transfer_time_get, 0);
3419
+ rb_define_method(cCurlEasy, "start_transfer_time", ruby_curl_easy_start_transfer_time_get, 0);
3420
+ rb_define_method(cCurlEasy, "redirect_time", ruby_curl_easy_redirect_time_get, 0);
3421
+ rb_define_method(cCurlEasy, "redirect_count", ruby_curl_easy_redirect_count_get, 0);
3422
+ rb_define_method(cCurlEasy, "redirect_url", ruby_curl_easy_redirect_url_get, 0);
3423
+ rb_define_method(cCurlEasy, "downloaded_bytes", ruby_curl_easy_downloaded_bytes_get, 0);
3424
+ rb_define_method(cCurlEasy, "uploaded_bytes", ruby_curl_easy_uploaded_bytes_get, 0);
3425
+ rb_define_method(cCurlEasy, "download_speed", ruby_curl_easy_download_speed_get, 0);
3426
+ rb_define_method(cCurlEasy, "upload_speed", ruby_curl_easy_upload_speed_get, 0);
3427
+ rb_define_method(cCurlEasy, "header_size", ruby_curl_easy_header_size_get, 0);
3428
+ rb_define_method(cCurlEasy, "request_size", ruby_curl_easy_request_size_get, 0);
3429
+ rb_define_method(cCurlEasy, "ssl_verify_result", ruby_curl_easy_ssl_verify_result_get, 0);
3430
+ rb_define_method(cCurlEasy, "downloaded_content_length", ruby_curl_easy_downloaded_content_length_get, 0);
3431
+ rb_define_method(cCurlEasy, "uploaded_content_length", ruby_curl_easy_uploaded_content_length_get, 0);
3432
+ rb_define_method(cCurlEasy, "content_type", ruby_curl_easy_content_type_get, 0);
3433
+ rb_define_method(cCurlEasy, "os_errno", ruby_curl_easy_os_errno_get, 0);
3434
+ rb_define_method(cCurlEasy, "num_connects", ruby_curl_easy_num_connects_get, 0);
3435
+ rb_define_method(cCurlEasy, "ftp_entry_path", ruby_curl_easy_ftp_entry_path_get, 0);
3436
+
3437
+ rb_define_method(cCurlEasy, "close", ruby_curl_easy_close, 0);
3438
+ rb_define_method(cCurlEasy, "reset", ruby_curl_easy_reset, 0);
3439
+
3440
+ /* Curl utils */
3441
+ rb_define_method(cCurlEasy, "escape", ruby_curl_easy_escape, 1);
3442
+ rb_define_method(cCurlEasy, "unescape", ruby_curl_easy_unescape, 1);
3443
+
3444
+ /* Runtime support */
3445
+ rb_define_method(cCurlEasy, "clone", ruby_curl_easy_clone, 0);
3446
+ rb_define_alias(cCurlEasy, "dup", "clone");
3447
+ rb_define_method(cCurlEasy, "inspect", ruby_curl_easy_inspect, 0);
3448
+
3449
+ rb_define_method(cCurlEasy, "multi", ruby_curl_easy_multi_get, 0);
3450
+ rb_define_method(cCurlEasy, "multi=", ruby_curl_easy_multi_set, 1);
3451
+ rb_define_method(cCurlEasy, "last_result", ruby_curl_easy_last_result, 0);
3452
+
3453
+ rb_define_method(cCurlEasy, "setopt", ruby_curl_easy_set_opt, 2);
3454
+ rb_define_method(cCurlEasy, "getinfo", ruby_curl_easy_get_opt, 1);
3455
+ }