rhack 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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
data/ext/curb/curb.h ADDED
@@ -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,3430 @@
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 idFlatten;
21
+ static VALUE rbstrAmp;
22
+
23
+ #ifdef RDOC_NEVER_DEFINED
24
+ mCurl = rb_define_module("Curl");
25
+ #endif
26
+
27
+ VALUE cCurlEasy;
28
+
29
+
30
+ /* ================== CURL HANDLER FUNCS ==============*/
31
+
32
+ static VALUE callback_exception(VALUE unused) {
33
+ return Qfalse;
34
+ }
35
+
36
+ /* These handle both body and header data */
37
+ static size_t default_data_handler(char *stream,
38
+ size_t size,
39
+ size_t nmemb,
40
+ VALUE out) {
41
+ rb_str_buf_cat(out, stream, size * nmemb);
42
+ return size * nmemb;
43
+ }
44
+
45
+ // size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
46
+ static size_t read_data_handler(void *ptr,
47
+ size_t size,
48
+ size_t nmemb,
49
+ ruby_curl_easy *rbce) {
50
+ VALUE upload = rb_easy_get("upload");
51
+ size_t read_bytes = (size*nmemb);
52
+ VALUE stream = ruby_curl_upload_stream_get(upload);
53
+
54
+ if (rb_respond_to(stream, rb_intern("read"))) {//if (rb_respond_to(stream, rb_intern("to_s"))) {
55
+ /* copy read_bytes from stream into ptr */
56
+ VALUE str = rb_funcall(stream, rb_intern("read"), 1, rb_int_new(read_bytes) );
57
+ if( str != Qnil ) {
58
+ memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
59
+ return RSTRING_LEN(str);
60
+ }
61
+ else {
62
+ return 0;
63
+ }
64
+ }
65
+ else if (rb_respond_to(stream, rb_intern("to_s"))) {
66
+ ruby_curl_upload *rbcu;
67
+ VALUE str;
68
+ size_t len;
69
+ size_t remaining;
70
+ char *str_ptr;
71
+ Data_Get_Struct(upload, ruby_curl_upload, rbcu);
72
+ str = rb_funcall(stream, rb_intern("to_s"), 0);
73
+ len = RSTRING_LEN(str);
74
+ remaining = len - rbcu->offset;
75
+ str_ptr = RSTRING_PTR(str);
76
+
77
+ if( remaining < read_bytes ) {
78
+ if( remaining > 0 ) {
79
+ memcpy(ptr, str_ptr+rbcu->offset, remaining);
80
+ read_bytes = remaining;
81
+ rbcu->offset += remaining;
82
+ }
83
+ return remaining;
84
+ }
85
+ else if( remaining > read_bytes ) { // read_bytes <= remaining - send what we can fit in the buffer(ptr)
86
+ memcpy(ptr, str_ptr+rbcu->offset, read_bytes);
87
+ rbcu->offset += read_bytes;
88
+ }
89
+ else { // they're equal
90
+ memcpy(ptr, str_ptr+rbcu->offset, --read_bytes);
91
+ rbcu->offset += read_bytes;
92
+ }
93
+ return read_bytes;
94
+ }
95
+ else {
96
+ return 0;
97
+ }
98
+ }
99
+
100
+ static size_t proc_data_handler(char *stream,
101
+ size_t size,
102
+ size_t nmemb,
103
+ VALUE proc) {
104
+ VALUE procret;
105
+
106
+ procret = rb_funcall(proc, idCall, 1, rb_str_new(stream, size * nmemb));
107
+
108
+ switch (rb_type(procret)) {
109
+ case T_FIXNUM:
110
+ return FIX2LONG(procret);
111
+ case T_BIGNUM:
112
+ return NUM2LONG(procret);
113
+ default:
114
+ rb_warn("Curl data handlers should return the number of bytes read as an Integer");
115
+ return size * nmemb;
116
+ }
117
+ }
118
+
119
+ static size_t proc_data_handler_body(char *stream,
120
+ size_t size,
121
+ size_t nmemb,
122
+ ruby_curl_easy *rbce)
123
+ {
124
+ size_t ret;
125
+ rbce->callback_active = 1;
126
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("body_proc"));
127
+ rbce->callback_active = 0;
128
+ return ret;
129
+ }
130
+ static size_t proc_data_handler_header(char *stream,
131
+ size_t size,
132
+ size_t nmemb,
133
+ ruby_curl_easy *rbce)
134
+ {
135
+ size_t ret;
136
+ rbce->callback_active = 1;
137
+ ret = proc_data_handler(stream, size, nmemb, rb_easy_get("header_proc"));
138
+ rbce->callback_active = 0;
139
+ return ret;
140
+ }
141
+
142
+
143
+ static VALUE call_progress_handler(VALUE ary) {
144
+ return rb_funcall(rb_ary_entry(ary, 0), idCall, 4,
145
+ rb_ary_entry(ary, 1), // rb_float_new(dltotal),
146
+ rb_ary_entry(ary, 2), // rb_float_new(dlnow),
147
+ rb_ary_entry(ary, 3), // rb_float_new(ultotal),
148
+ rb_ary_entry(ary, 4)); // rb_float_new(ulnow));
149
+ }
150
+
151
+ static int proc_progress_handler(VALUE proc,
152
+ double dltotal,
153
+ double dlnow,
154
+ double ultotal,
155
+ double ulnow) {
156
+ VALUE procret;
157
+ VALUE callargs = rb_ary_new2(5);
158
+
159
+ rb_ary_store(callargs, 0, proc);
160
+ rb_ary_store(callargs, 1, rb_float_new(dltotal));
161
+ rb_ary_store(callargs, 2, rb_float_new(dlnow));
162
+ rb_ary_store(callargs, 3, rb_float_new(ultotal));
163
+ rb_ary_store(callargs, 4, rb_float_new(ulnow));
164
+
165
+ //v = rb_rescue(range_check, (VALUE)args, range_failed, 0);
166
+ //procret = rb_funcall(proc, idCall, 4, rb_float_new(dltotal),
167
+ // rb_float_new(dlnow),
168
+ // rb_float_new(ultotal),
169
+ // rb_float_new(ulnow));
170
+ procret = rb_rescue(call_progress_handler, callargs, callback_exception, Qnil);
171
+
172
+ return(((procret == Qfalse) || (procret == Qnil)) ? -1 : 0);
173
+ }
174
+
175
+ static VALUE call_debug_handler(VALUE ary) {
176
+ return rb_funcall(rb_ary_entry(ary, 0), idCall, 2,
177
+ rb_ary_entry(ary, 1), // INT2FIX(type),
178
+ rb_ary_entry(ary, 2)); // rb_str_new(data, data_len)
179
+ }
180
+ static int proc_debug_handler(CURL *curl,
181
+ curl_infotype type,
182
+ char *data,
183
+ size_t data_len,
184
+ VALUE proc) {
185
+ VALUE callargs = rb_ary_new2(3);
186
+ rb_ary_store(callargs, 0, proc);
187
+ rb_ary_store(callargs, 1, INT2FIX(type));
188
+ rb_ary_store(callargs, 2, rb_str_new(data, data_len));
189
+ rb_rescue(call_debug_handler, callargs, callback_exception, Qnil);
190
+ /* no way to indicate to libcurl that we should break out given an exception in the on_debug handler...
191
+ * this means exceptions will be swallowed
192
+ */
193
+ //rb_funcall(proc, idCall, 2, INT2FIX(type), rb_str_new(data, data_len));
194
+ return 0;
195
+ }
196
+
197
+ /* ================== MARK/FREE FUNC ==================*/
198
+ void curl_easy_mark(ruby_curl_easy *rbce) {
199
+ if (!NIL_P(rbce->opts)) { rb_gc_mark(rbce->opts); }
200
+ if (!NIL_P(rbce->multi)) { rb_gc_mark(rbce->multi); }
201
+ }
202
+
203
+ static void ruby_curl_easy_free(ruby_curl_easy *rbce) {
204
+ if (rbce->curl_headers) {
205
+ curl_slist_free_all(rbce->curl_headers);
206
+ }
207
+
208
+ if (rbce->curl_ftp_commands) {
209
+ curl_slist_free_all(rbce->curl_ftp_commands);
210
+ }
211
+
212
+ if (rbce->curl) {
213
+ curl_easy_cleanup(rbce->curl);
214
+ }
215
+ }
216
+
217
+ void curl_easy_free(ruby_curl_easy *rbce) {
218
+ ruby_curl_easy_free(rbce);
219
+ free(rbce);
220
+ }
221
+
222
+
223
+ /* ================= ALLOC METHODS ====================*/
224
+
225
+ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
226
+ rbce->opts = rb_hash_new();
227
+
228
+ rbce->curl_headers = NULL;
229
+ rbce->curl_ftp_commands = NULL;
230
+
231
+ /* various-typed opts */
232
+ rbce->local_port = 0;
233
+ rbce->local_port_range = 0;
234
+ rbce->proxy_port = 0;
235
+ rbce->proxy_type = -1;
236
+ rbce->http_auth_types = 0;
237
+ rbce->proxy_auth_types = 0;
238
+ rbce->max_redirs = -1;
239
+ rbce->timeout = 0;
240
+ rbce->connect_timeout = 0;
241
+ rbce->dns_cache_timeout = 60;
242
+ rbce->ftp_response_timeout = 0;
243
+ rbce->low_speed_limit = 0;
244
+ rbce->low_speed_time = 0;
245
+ rbce->ssl_version = -1;
246
+ rbce->use_ssl = -1;
247
+ rbce->ftp_filemethod = -1;
248
+ rbce->resolve_mode = CURL_IPRESOLVE_WHATEVER;
249
+
250
+ /* bool opts */
251
+ rbce->proxy_tunnel = 0;
252
+ rbce->fetch_file_time = 0;
253
+ rbce->ssl_verify_peer = 1;
254
+ rbce->ssl_verify_host = 2;
255
+ rbce->header_in_body = 0;
256
+ rbce->use_netrc = 0;
257
+ rbce->follow_location = 0;
258
+ rbce->unrestricted_auth = 0;
259
+ rbce->verbose = 0;
260
+ rbce->multipart_form_post = 0;
261
+ rbce->enable_cookies = 0;
262
+ rbce->ignore_content_length = 0;
263
+ rbce->callback_active = 0;
264
+ }
265
+
266
+ /*
267
+ * call-seq:
268
+ * Curl::Easy.new => #&lt;Curl::Easy...&gt;
269
+ * Curl::Easy.new(url = nil) => #&lt;Curl::Easy...&gt;
270
+ * Curl::Easy.new(url = nil) { |self| ... } => #&lt;Curl::Easy...&gt;
271
+ *
272
+ * Create a new Curl::Easy instance, optionally supplying the URL.
273
+ * The block form allows further configuration to be supplied before
274
+ * the instance is returned.
275
+ */
276
+ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
277
+ CURLcode ecode;
278
+ VALUE url, blk;
279
+ VALUE new_curl;
280
+ ruby_curl_easy *rbce;
281
+
282
+ rb_scan_args(argc, argv, "01&", &url, &blk);
283
+
284
+ rbce = ALLOC(ruby_curl_easy);
285
+
286
+ /* handler */
287
+ rbce->curl = curl_easy_init();
288
+ if (!rbce->curl) {
289
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
290
+ }
291
+
292
+ new_curl = Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
293
+
294
+ rbce->multi = Qnil;
295
+ rbce->opts = Qnil;
296
+
297
+ ruby_curl_easy_zero(rbce);
298
+
299
+ rb_easy_set("url", url);
300
+
301
+ /* set the new_curl pointer to the curl handle */
302
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)new_curl);
303
+ if (ecode != CURLE_OK) {
304
+ raise_curl_easy_error_exception(ecode);
305
+ }
306
+
307
+ if (blk != Qnil) {
308
+ rb_funcall(blk, idCall, 1, new_curl);
309
+ }
310
+
311
+ return new_curl;
312
+ }
313
+
314
+ /*
315
+ * call-seq:
316
+ * easy.clone => #&lt;easy clone&gt;
317
+ * easy.dup => #&lt;easy clone&gt;
318
+ *
319
+ * Clone this Curl::Easy instance, creating a new instance.
320
+ * This method duplicates the underlying CURL* handle.
321
+ */
322
+ static VALUE ruby_curl_easy_clone(VALUE self) {
323
+ ruby_curl_easy *rbce, *newrbce;
324
+
325
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
326
+
327
+ newrbce = ALLOC(ruby_curl_easy);
328
+ memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
329
+ newrbce->curl = curl_easy_duphandle(rbce->curl);
330
+ newrbce->curl_headers = NULL;
331
+ newrbce->curl_ftp_commands = NULL;
332
+
333
+ return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * easy.close => nil
339
+ *
340
+ * Close the Curl::Easy instance. Any open connections are closed
341
+ * The easy handle is reinitialized. If a previous multi handle was
342
+ * open it is set to nil and will be cleared after a GC.
343
+ */
344
+ static VALUE ruby_curl_easy_close(VALUE self) {
345
+ CURLcode ecode;
346
+ ruby_curl_easy *rbce;
347
+
348
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
349
+
350
+ if (rbce->callback_active) {
351
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
352
+ }
353
+
354
+ ruby_curl_easy_free(rbce);
355
+
356
+ /* reinit the handle */
357
+ rbce->curl = curl_easy_init();
358
+ if (!rbce->curl) {
359
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
360
+ }
361
+
362
+ rbce->multi = Qnil;
363
+
364
+ ruby_curl_easy_zero(rbce);
365
+
366
+ /* give the new curl handle a reference back to the ruby object */
367
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
368
+ if (ecode != CURLE_OK) {
369
+ raise_curl_easy_error_exception(ecode);
370
+ }
371
+
372
+ return Qnil;
373
+ }
374
+
375
+ /*
376
+ * call-seq:
377
+ * easy.reset => Hash
378
+ *
379
+ * Reset the Curl::Easy instance, clears out all settings.
380
+ *
381
+ * from http://curl.haxx.se/libcurl/c/curl_easy_reset.html
382
+ * 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).
383
+ * It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares.
384
+ *
385
+ * The return value contains all settings stored.
386
+ */
387
+ static VALUE ruby_curl_easy_reset(VALUE self) {
388
+ CURLcode ecode;
389
+ ruby_curl_easy *rbce;
390
+ VALUE opts_dup;
391
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
392
+
393
+ if (rbce->callback_active) {
394
+ rb_raise(rb_eRuntimeError, "Cannot close an active curl handle within a callback");
395
+ }
396
+
397
+ opts_dup = rb_funcall(rbce->opts, rb_intern("dup"), 0);
398
+
399
+ curl_easy_reset(rbce->curl);
400
+ ruby_curl_easy_zero(rbce);
401
+
402
+ /* rest clobbers the private setting, so reset it to self */
403
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
404
+ if (ecode != CURLE_OK) {
405
+ raise_curl_easy_error_exception(ecode);
406
+ }
407
+
408
+ /* Free everything up */
409
+ if (rbce->curl_headers) {
410
+ curl_slist_free_all(rbce->curl_headers);
411
+ rbce->curl_headers = NULL;
412
+ }
413
+
414
+ return opts_dup;
415
+ }
416
+
417
+
418
+ /* ================ OBJ ATTRIBUTES ==================*/
419
+
420
+ /*
421
+ * call-seq:
422
+ * easy.url => string
423
+ *
424
+ * Obtain the URL that will be used by subsequent calls to +perform+.
425
+ */
426
+ static VALUE ruby_curl_easy_url_get(VALUE self) {
427
+ CURB_OBJECT_HGETTER(ruby_curl_easy, url);
428
+ }
429
+
430
+ /*
431
+ * call-seq:
432
+ * easy.proxy_url => string
433
+ *
434
+ * Obtain the HTTP Proxy URL that will be used by subsequent calls to +perform+.
435
+ */
436
+ static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
437
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxy_url);
438
+ }
439
+
440
+ /*
441
+ * call-seq:
442
+ * easy.headers = "Header: val" => "Header: val"
443
+ * easy.headers = {"Header" => "val" ..., "Header" => "val"} => {"Header: val", ...}
444
+ * easy.headers = ["Header: val" ..., "Header: val"] => ["Header: val", ...]
445
+ *
446
+ * Set custom HTTP headers for following requests. This can be used to add
447
+ * custom headers, or override standard headers used by libcurl. It defaults to a
448
+ * Hash.
449
+ *
450
+ * For example to set a standard or custom header:
451
+ *
452
+ * easy.headers["MyHeader"] = "myval"
453
+ *
454
+ * To remove a standard header (this is useful when removing libcurls default
455
+ * 'Expect: 100-Continue' header when using HTTP form posts):
456
+ *
457
+ * easy.headers["Expect"] = ''
458
+ *
459
+ * Anything passed to libcurl as a header will be converted to a string during
460
+ * the perform step.
461
+ */
462
+ static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
463
+ CURB_OBJECT_HSETTER(ruby_curl_easy, headers);
464
+ }
465
+
466
+ /*
467
+ * call-seq:
468
+ * easy.headers => Hash, Array or Str
469
+ *
470
+ * Obtain the custom HTTP headers for following requests.
471
+ */
472
+ static VALUE ruby_curl_easy_headers_get(VALUE self) {
473
+ ruby_curl_easy *rbce;
474
+ VALUE headers;
475
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
476
+ headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
477
+ if (headers == Qnil) { headers = rb_easy_set("headers", rb_hash_new()); }
478
+ return headers;
479
+ }
480
+
481
+ /*
482
+ * call-seq:
483
+ * easy.interface => string
484
+ *
485
+ * Obtain the interface name that is used as the outgoing network interface.
486
+ * The name can be an interface name, an IP address or a host name.
487
+ */
488
+ static VALUE ruby_curl_easy_interface_get(VALUE self) {
489
+ CURB_OBJECT_HGETTER(ruby_curl_easy, interface_hm);
490
+ }
491
+
492
+ /*
493
+ * call-seq:
494
+ * easy.userpwd => string
495
+ *
496
+ * Obtain the username/password string that will be used for subsequent
497
+ * calls to +perform+.
498
+ */
499
+ static VALUE ruby_curl_easy_userpwd_get(VALUE self) {
500
+ CURB_OBJECT_HGETTER(ruby_curl_easy, userpwd);
501
+ }
502
+
503
+ /*
504
+ * call-seq:
505
+ * easy.proxypwd => string
506
+ *
507
+ * Obtain the username/password string that will be used for proxy
508
+ * connection during subsequent calls to +perform+. The supplied string
509
+ * should have the form "username:password"
510
+ */
511
+ static VALUE ruby_curl_easy_proxypwd_get(VALUE self) {
512
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxypwd);
513
+ }
514
+
515
+ /*
516
+ * call-seq:
517
+ * easy.cookies => "name1=content1; name2=content2;"
518
+ *
519
+ * Obtain the cookies for this Curl::Easy instance.
520
+ */
521
+ static VALUE ruby_curl_easy_cookies_get(VALUE self) {
522
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookies);
523
+ }
524
+
525
+ /*
526
+ * call-seq:
527
+ * easy.cookiefile => string
528
+ *
529
+ * Obtain the cookiefile file for this Curl::Easy instance.
530
+ */
531
+ static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
532
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiefile);
533
+ }
534
+
535
+ /*
536
+ * call-seq:
537
+ * easy.cookiejar => string
538
+ *
539
+ * Obtain the cookiejar file to use for this Curl::Easy instance.
540
+ */
541
+ static VALUE ruby_curl_easy_cookiejar_get(VALUE self) {
542
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiejar);
543
+ }
544
+
545
+ /*
546
+ * call-seq:
547
+ * easy.cert = string => ""
548
+ *
549
+ * Set a cert file to use for this Curl::Easy instance. This file
550
+ * will be used to validate SSL connections.
551
+ *
552
+ */
553
+ static VALUE ruby_curl_easy_cert_set(VALUE self, VALUE cert) {
554
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert);
555
+ }
556
+
557
+ /*
558
+ * call-seq:
559
+ * easy.cert => string
560
+ *
561
+ * Obtain the cert file to use for this Curl::Easy instance.
562
+ */
563
+ static VALUE ruby_curl_easy_cert_get(VALUE self) {
564
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert);
565
+ }
566
+
567
+ /*
568
+ * call-seq:
569
+ * easy.cert_key = "cert_key.file" => ""
570
+ *
571
+ * Set a cert key to use for this Curl::Easy instance. This file
572
+ * will be used to validate SSL certificates.
573
+ *
574
+ */
575
+ static VALUE ruby_curl_easy_cert_key_set(VALUE self, VALUE cert_key) {
576
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert_key);
577
+ }
578
+
579
+ /*
580
+ * call-seq:
581
+ * easy.cert_key => "cert_key.file"
582
+ *
583
+ * Obtain the cert key file to use for this Curl::Easy instance.
584
+ */
585
+ static VALUE ruby_curl_easy_cert_key_get(VALUE self) {
586
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert_key);
587
+ }
588
+
589
+ /*
590
+ * call-seq:
591
+ * easy.cacert = string => ""
592
+ *
593
+ * Set a cacert bundle to use for this Curl::Easy instance. This file
594
+ * will be used to validate SSL certificates.
595
+ *
596
+ */
597
+ static VALUE ruby_curl_easy_cacert_set(VALUE self, VALUE cacert) {
598
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cacert);
599
+ }
600
+
601
+ /*
602
+ * call-seq:
603
+ * easy.cacert => string
604
+ *
605
+ * Obtain the cacert file to use for this Curl::Easy instance.
606
+ */
607
+ static VALUE ruby_curl_easy_cacert_get(VALUE self) {
608
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cacert);
609
+ }
610
+
611
+ /*
612
+ * call-seq:
613
+ * easy.certpassword = string => ""
614
+ *
615
+ * Set a password used to open the specified cert
616
+ */
617
+ static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
618
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certpassword);
619
+ }
620
+
621
+ /*
622
+ * call-seq:
623
+ * easy.certtype = "PEM|DER" => ""
624
+ *
625
+ * Set a cert type to use for this Curl::Easy instance.
626
+ * Default is PEM
627
+ *
628
+ */
629
+ static VALUE ruby_curl_easy_certtype_set(VALUE self, VALUE certtype) {
630
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certtype);
631
+ }
632
+
633
+ /*
634
+ * call-seq:
635
+ * easy.certtype => string
636
+ *
637
+ * Obtain the cert type used for this Curl::Easy instance
638
+ */
639
+ static VALUE ruby_curl_easy_certtype_get(VALUE self) {
640
+ CURB_OBJECT_HGETTER(ruby_curl_easy, certtype);
641
+ }
642
+
643
+ /*
644
+ * call-seq:
645
+ * easy.encoding = string => string
646
+ *
647
+ * Set the accepted encoding types, curl will handle all of the decompression
648
+ *
649
+ */
650
+ static VALUE ruby_curl_easy_encoding_set(VALUE self, VALUE encoding) {
651
+ CURB_OBJECT_HSETTER(ruby_curl_easy, encoding);
652
+ }
653
+ /*
654
+ * call-seq:
655
+ * easy.encoding => string
656
+ *
657
+ * Get the set encoding types
658
+ *
659
+ */
660
+ static VALUE ruby_curl_easy_encoding_get(VALUE self) {
661
+ CURB_OBJECT_HGETTER(ruby_curl_easy, encoding);
662
+ }
663
+
664
+ /*
665
+ * call-seq:
666
+ * easy.useragent = "Ruby/Curb" => ""
667
+ *
668
+ * Set the user agent string for this Curl::Easy instance
669
+ *
670
+ */
671
+ static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
672
+ CURB_OBJECT_HSETTER(ruby_curl_easy, useragent);
673
+ }
674
+
675
+ /*
676
+ * call-seq:
677
+ * easy.useragent => "Ruby/Curb"
678
+ *
679
+ * Obtain the user agent string used for this Curl::Easy instance
680
+ */
681
+ static VALUE ruby_curl_easy_useragent_get(VALUE self) {
682
+ CURB_OBJECT_HGETTER(ruby_curl_easy, useragent);
683
+ }
684
+
685
+ /*
686
+ * call-seq:
687
+ * easy.post_body = "some=form%20data&to=send" => string or nil
688
+ *
689
+ * Sets the POST body of this Curl::Easy instance. This is expected to be
690
+ * URL encoded; no additional processing or encoding is done on the string.
691
+ * The content-type header will be set to application/x-www-form-urlencoded.
692
+ *
693
+ * This is handy if you want to perform a POST against a Curl::Multi instance.
694
+ */
695
+ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
696
+ ruby_curl_easy *rbce;
697
+ CURL *curl;
698
+
699
+ char *data;
700
+ long len;
701
+
702
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
703
+
704
+ curl = rbce->curl;
705
+ if (rbce->first != NULL) {
706
+ curl_formfree(rbce->first);
707
+ rbce->first = NULL;
708
+ rbce->last = NULL;
709
+ }
710
+ rbce->multipart_form_post = 0;
711
+ if ( post_body == Qnil ) {
712
+ //rbce->postdata_buffer = Qnil;
713
+ rb_easy_del("postdata_buffer");
714
+ } else {
715
+ if (rb_type(post_body) == T_STRING) {
716
+ data = StringValuePtr(post_body);
717
+ len = RSTRING_LEN(post_body);
718
+ }
719
+ else if (rb_respond_to(post_body, rb_intern("to_s"))) {
720
+ VALUE str_body = rb_funcall(post_body, rb_intern("to_s"), 0);
721
+ data = StringValuePtr(str_body);
722
+ len = RSTRING_LEN(post_body);
723
+ }
724
+ else {
725
+ rb_raise(rb_eRuntimeError, "post data must respond_to .to_s");
726
+ }
727
+
728
+ // Store the string, since it has to hang around for the duration of the
729
+ // request. See CURLOPT_POSTFIELDS in the libcurl docs.
730
+ //rbce->postdata_buffer = post_body;
731
+ rb_easy_set("postdata_buffer", post_body);
732
+
733
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
734
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
735
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
736
+
737
+ return post_body;
738
+ }
739
+
740
+ return Qnil;
741
+ }
742
+ static VALUE ruby_curl_easy_multipart_post_body_set(VALUE self, VALUE ary) {
743
+ ruby_curl_easy *rbce;
744
+ CURL *curl;
745
+ int i;
746
+
747
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
748
+ curl = rbce->curl;
749
+ if (rbce->first != NULL) {
750
+ curl_formfree(rbce->first);
751
+ rbce->first = NULL;
752
+ rbce->last = NULL;
753
+ }
754
+
755
+ // Make the multipart form
756
+ rbce->multipart_form_post = 1;
757
+ for (i=0; i<RARRAY_LEN(ary); i++) {
758
+ if (rb_obj_is_instance_of(RARRAY_PTR(ary)[i], cCurlPostField)) {
759
+ append_to_form(RARRAY_PTR(ary)[i], &(rbce->first), &(rbce->last));
760
+ }
761
+ else {
762
+ if (rbce->first != NULL) {
763
+ curl_formfree(rbce->first);
764
+ rbce->first = NULL;
765
+ rbce->last = NULL;
766
+ }
767
+ rb_raise(eCurlErrInvalidPostField, "You must use only PostFields with multipart form posts");
768
+ return Qnil;
769
+ }
770
+ }
771
+ //rbce->postdata_buffer = ary;
772
+ rb_easy_set("postdata_buffer", ary);
773
+
774
+ curl_easy_setopt(curl, CURLOPT_POST, 0);
775
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, rbce->first);
776
+ return Qnil;
777
+ }
778
+
779
+ /*
780
+ * call-seq:
781
+ * easy.post_body => string or nil
782
+ *
783
+ * Obtain the POST body used in this Curl::Easy instance.
784
+ */
785
+ static VALUE ruby_curl_easy_post_body_get(VALUE self) {
786
+ CURB_OBJECT_HGETTER(ruby_curl_easy, postdata_buffer);
787
+ }
788
+
789
+ /*
790
+ * call-seq:
791
+ * easy.put_data = data => ""
792
+ *
793
+ * Points this Curl::Easy instance to data to be uploaded via PUT. This
794
+ * sets the request to a PUT type request - useful if you want to PUT via
795
+ * a multi handle.
796
+ */
797
+ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
798
+ ruby_curl_easy *rbce;
799
+ CURL *curl;
800
+ VALUE upload;
801
+ VALUE headers;
802
+
803
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
804
+
805
+ upload = ruby_curl_upload_new(cCurlUpload);
806
+ ruby_curl_upload_stream_set(upload,data);
807
+
808
+ curl = rbce->curl;
809
+ rb_easy_set("upload", upload); /* keep the upload object alive as long as
810
+ the easy handle is active or until the upload
811
+ is complete or terminated... */
812
+
813
+ curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
814
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
815
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)read_data_handler);
816
+ curl_easy_setopt(curl, CURLOPT_READDATA, rbce);
817
+
818
+ /*
819
+ * we need to set specific headers for the PUT to work... so
820
+ * convert the internal headers structure to a HASH if one is set
821
+ */
822
+ if (!rb_easy_nil("headers")) {
823
+ if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_STRING)) {
824
+ rb_raise(rb_eRuntimeError, "Must set headers as a HASH to modify the headers in an PUT request");
825
+ }
826
+ }
827
+
828
+ // exit fast if the payload is empty
829
+ if (NIL_P(data)) { return data; }
830
+
831
+ headers = rb_easy_get("headers");
832
+ if( headers == Qnil ) {
833
+ headers = rb_hash_new();
834
+ }
835
+
836
+ if (rb_respond_to(data, rb_intern("read"))) {
837
+ VALUE stat = rb_funcall(data, rb_intern("stat"), 0);
838
+ if( stat && rb_hash_aref(headers, rb_str_new2("Content-Length")) == Qnil) {
839
+ VALUE size;
840
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
841
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
842
+ }
843
+ size = rb_funcall(stat, rb_intern("size"), 0);
844
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2LONG(size));
845
+ }
846
+ else if( rb_hash_aref(headers, rb_str_new2("Content-Length")) == Qnil && rb_hash_aref(headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
847
+ rb_hash_aset(headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
848
+ }
849
+ else if( rb_hash_aref(headers, rb_str_new2("Content-Length")) ) {
850
+ VALUE size = rb_funcall(rb_hash_aref(headers, rb_str_new2("Content-Length")), rb_intern("to_i"), 0);
851
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2LONG(size));
852
+ }
853
+ }
854
+ else if (rb_respond_to(data, rb_intern("to_s"))) {
855
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
856
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
857
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
858
+ }
859
+ }
860
+ else {
861
+ rb_raise(rb_eRuntimeError, "PUT data must respond to read or to_s");
862
+ }
863
+ rb_easy_set("headers",headers);
864
+
865
+ // if we made it this far, all should be well.
866
+ return data;
867
+ }
868
+
869
+ /*
870
+ * call-seq:
871
+ * easy.ftp_commands = ["CWD /", "MKD directory"] => ["CWD /", ...]
872
+ *
873
+ * Explicitly sets the list of commands to execute on the FTP server when calling perform
874
+ */
875
+ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
876
+ CURB_OBJECT_HSETTER(ruby_curl_easy, ftp_commands);
877
+ }
878
+
879
+ /*
880
+ * call-seq
881
+ * easy.ftp_commands => array or nil
882
+ */
883
+ static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
884
+ CURB_OBJECT_HGETTER(ruby_curl_easy, ftp_commands);
885
+ }
886
+
887
+ /* ================== IMMED ATTRS ==================*/
888
+
889
+ /*
890
+ * call-seq:
891
+ * easy.local_port = fixnum or nil => fixnum or nil
892
+ *
893
+ * Set the local port that will be used for the following +perform+ calls.
894
+ *
895
+ * Passing +nil+ will return to the default behaviour (no local port
896
+ * preference).
897
+ *
898
+ * This option is ignored if compiled against libcurl < 7.15.2.
899
+ */
900
+ static VALUE ruby_curl_easy_local_port_set(VALUE self, VALUE local_port) {
901
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, local_port, "port");
902
+ }
903
+
904
+ /*
905
+ * call-seq:
906
+ * easy.local_port => fixnum or nil
907
+ *
908
+ * Obtain the local port that will be used for the following +perform+ calls.
909
+ *
910
+ * This option is ignored if compiled against libcurl < 7.15.2.
911
+ */
912
+ static VALUE ruby_curl_easy_local_port_get(VALUE self) {
913
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, local_port);
914
+ }
915
+
916
+ /*
917
+ * call-seq:
918
+ * easy.local_port_range = fixnum or nil => fixnum or nil
919
+ *
920
+ * Set the local port range that will be used for the following +perform+
921
+ * calls. This is a number (between 0 and 65535) that determines how far
922
+ * libcurl may deviate from the supplied +local_port+ in order to find
923
+ * an available port.
924
+ *
925
+ * If you set +local_port+ it's also recommended that you set this, since
926
+ * it is fairly likely that your specified port will be unavailable.
927
+ *
928
+ * This option is ignored if compiled against libcurl < 7.15.2.
929
+ */
930
+ static VALUE ruby_curl_easy_local_port_range_set(VALUE self, VALUE local_port_range) {
931
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, local_port_range, "port range");
932
+ }
933
+
934
+ /*
935
+ * call-seq:
936
+ * easy.local_port_range => fixnum or nil
937
+ *
938
+ * Obtain the local port range that will be used for the following +perform+
939
+ * calls.
940
+ *
941
+ * This option is ignored if compiled against libcurl < 7.15.2.
942
+ */
943
+ static VALUE ruby_curl_easy_local_port_range_get(VALUE self) {
944
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, local_port_range);
945
+ }
946
+
947
+ /*
948
+ * call-seq:
949
+ * easy.proxy_port = fixnum or nil => fixnum or nil
950
+ *
951
+ * Set the proxy port that will be used for the following +perform+ calls.
952
+ */
953
+ static VALUE ruby_curl_easy_proxy_port_set(VALUE self, VALUE proxy_port) {
954
+ CURB_IMMED_PORT_SETTER(ruby_curl_easy, proxy_port, "port");
955
+ }
956
+
957
+ /*
958
+ * call-seq:
959
+ * easy.proxy_port => fixnum or nil
960
+ *
961
+ * Obtain the proxy port that will be used for the following +perform+ calls.
962
+ */
963
+ static VALUE ruby_curl_easy_proxy_port_get(VALUE self) {
964
+ CURB_IMMED_PORT_GETTER(ruby_curl_easy, proxy_port);
965
+ }
966
+
967
+ /*
968
+ * call-seq:
969
+ * easy.proxy_type = fixnum or nil => fixnum or nil
970
+ *
971
+ * Set the proxy type that will be used for the following +perform+ calls.
972
+ * This should be one of the Curl::CURLPROXY constants.
973
+ */
974
+ static VALUE ruby_curl_easy_proxy_type_set(VALUE self, VALUE proxy_type) {
975
+ CURB_IMMED_SETTER(ruby_curl_easy, proxy_type, -1);
976
+ }
977
+
978
+ /*
979
+ * call-seq:
980
+ * easy.proxy_type => fixnum or nil
981
+ *
982
+ * Obtain the proxy type that will be used for the following +perform+ calls.
983
+ */
984
+ static VALUE ruby_curl_easy_proxy_type_get(VALUE self) {
985
+ CURB_IMMED_GETTER(ruby_curl_easy, proxy_type, -1);
986
+ }
987
+
988
+ #if defined(HAVE_CURLAUTH_DIGEST_IE)
989
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
990
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
991
+ (!strncmp("digest_ie",node,9)) ? CURLAUTH_DIGEST_IE : \
992
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
993
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
994
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
995
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
996
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
997
+ #else
998
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
999
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
1000
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
1001
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
1002
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
1003
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
1004
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
1005
+ #endif
1006
+ /*
1007
+ * call-seq:
1008
+ * easy.http_auth_types = fixnum or nil => fixnum or nil
1009
+ * easy.http_auth_types = [:basic,:digest,:digest_ie,:gssnegotiate, :ntlm, :any, :anysafe]
1010
+ *
1011
+ * Set the HTTP authentication types that may be used for the following
1012
+ * +perform+ calls. This is a bitmap made by ORing together the
1013
+ * Curl::CURLAUTH constants.
1014
+ */
1015
+ static VALUE ruby_curl_easy_http_auth_types_set(int argc, VALUE *argv, VALUE self) {//VALUE self, VALUE http_auth_types) {
1016
+ ruby_curl_easy *rbce;
1017
+ VALUE args_ary;
1018
+ int i, len;
1019
+ char* node = NULL;
1020
+ long mask = 0x000000;
1021
+
1022
+ rb_scan_args(argc, argv, "*", &args_ary);
1023
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1024
+
1025
+ len = (int)RARRAY_LEN(args_ary);
1026
+
1027
+ if (len == 1 && (TYPE(rb_ary_entry(args_ary,0)) == T_FIXNUM || rb_ary_entry(args_ary,0) == Qnil)) {
1028
+ if (rb_ary_entry(args_ary,0) == Qnil) {
1029
+ rbce->http_auth_types = 0;
1030
+ }
1031
+ else {
1032
+ rbce->http_auth_types = NUM2INT(rb_ary_entry(args_ary,0));
1033
+ }
1034
+ }
1035
+ else {
1036
+ // we could have multiple values, but they should be symbols
1037
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,0),rb_intern("to_s"),0));
1038
+ mask = CURL_HTTPAUTH_STR_TO_NUM(node);
1039
+ for( i = 1; i < len; ++i ) {
1040
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,i),rb_intern("to_s"),0));
1041
+ mask |= CURL_HTTPAUTH_STR_TO_NUM(node);
1042
+ }
1043
+ rbce->http_auth_types = mask;
1044
+ }
1045
+ return INT2NUM(rbce->http_auth_types);
1046
+ }
1047
+
1048
+ /*
1049
+ * call-seq:
1050
+ * easy.http_auth_types => fixnum or nil
1051
+ *
1052
+ * Obtain the HTTP authentication types that may be used for the following
1053
+ * +perform+ calls.
1054
+ */
1055
+ static VALUE ruby_curl_easy_http_auth_types_get(VALUE self) {
1056
+ CURB_IMMED_GETTER(ruby_curl_easy, http_auth_types, 0);
1057
+ }
1058
+
1059
+ /*
1060
+ * call-seq:
1061
+ * easy.proxy_auth_types = fixnum or nil => fixnum or nil
1062
+ *
1063
+ * Set the proxy authentication types that may be used for the following
1064
+ * +perform+ calls. This is a bitmap made by ORing together the
1065
+ * Curl::CURLAUTH constants.
1066
+ */
1067
+ static VALUE ruby_curl_easy_proxy_auth_types_set(VALUE self, VALUE proxy_auth_types) {
1068
+ CURB_IMMED_SETTER(ruby_curl_easy, proxy_auth_types, 0);
1069
+ }
1070
+
1071
+ /*
1072
+ * call-seq:
1073
+ * easy.proxy_auth_types => fixnum or nil
1074
+ *
1075
+ * Obtain the proxy authentication types that may be used for the following
1076
+ * +perform+ calls.
1077
+ */
1078
+ static VALUE ruby_curl_easy_proxy_auth_types_get(VALUE self) {
1079
+ CURB_IMMED_GETTER(ruby_curl_easy, proxy_auth_types, 0);
1080
+ }
1081
+
1082
+ /*
1083
+ * call-seq:
1084
+ * easy.max_redirects = fixnum or nil => fixnum or nil
1085
+ *
1086
+ * Set the maximum number of redirections to follow in the following +perform+
1087
+ * calls. Set to nil or -1 allow an infinite number (the default). Setting this
1088
+ * option only makes sense if +follow_location+ is also set true.
1089
+ *
1090
+ * With libcurl >= 7.15.1, setting this to 0 will cause libcurl to refuse any
1091
+ * redirect.
1092
+ */
1093
+ static VALUE ruby_curl_easy_max_redirects_set(VALUE self, VALUE max_redirs) {
1094
+ CURB_IMMED_SETTER(ruby_curl_easy, max_redirs, -1);
1095
+ }
1096
+
1097
+ /*
1098
+ * call-seq:
1099
+ * easy.max_redirects => fixnum or nil
1100
+ *
1101
+ * Obtain the maximum number of redirections to follow in the following
1102
+ * +perform+ calls.
1103
+ */
1104
+ static VALUE ruby_curl_easy_max_redirects_get(VALUE self) {
1105
+ CURB_IMMED_GETTER(ruby_curl_easy, max_redirs, -1);
1106
+ }
1107
+
1108
+ /*
1109
+ * call-seq:
1110
+ * easy.timeout = fixnum or nil => fixnum or nil
1111
+ *
1112
+ * Set the maximum time in seconds that you allow the libcurl transfer
1113
+ * operation to take. Normally, name lookups can take a considerable time
1114
+ * and limiting operations to less than a few minutes risk aborting
1115
+ * perfectly normal operations.
1116
+ *
1117
+ * Set to nil (or zero) to disable timeout (it will then only timeout
1118
+ * on the system's internal timeouts).
1119
+ */
1120
+ static VALUE ruby_curl_easy_timeout_set(VALUE self, VALUE timeout) {
1121
+ CURB_IMMED_SETTER(ruby_curl_easy, timeout, 0);
1122
+ }
1123
+
1124
+ /*
1125
+ * call-seq:
1126
+ * easy.timeout => fixnum or nil
1127
+ *
1128
+ * Obtain the maximum time in seconds that you allow the libcurl transfer
1129
+ * operation to take.
1130
+ */
1131
+ static VALUE ruby_curl_easy_timeout_get(VALUE self, VALUE timeout) {
1132
+ CURB_IMMED_GETTER(ruby_curl_easy, timeout, 0);
1133
+ }
1134
+
1135
+ /*
1136
+ * call-seq:
1137
+ * easy.connect_timeout = fixnum or nil => fixnum or nil
1138
+ *
1139
+ * Set the maximum time in seconds that you allow the connection to the
1140
+ * server to take. This only limits the connection phase, once it has
1141
+ * connected, this option is of no more use.
1142
+ *
1143
+ * Set to nil (or zero) to disable connection timeout (it will then only
1144
+ * timeout on the system's internal timeouts).
1145
+ */
1146
+ static VALUE ruby_curl_easy_connect_timeout_set(VALUE self, VALUE connect_timeout) {
1147
+ CURB_IMMED_SETTER(ruby_curl_easy, connect_timeout, 0);
1148
+ }
1149
+
1150
+ /*
1151
+ * call-seq:
1152
+ * easy.connect_timeout => fixnum or nil
1153
+ *
1154
+ * Obtain the maximum time in seconds that you allow the connection to the
1155
+ * server to take.
1156
+ */
1157
+ static VALUE ruby_curl_easy_connect_timeout_get(VALUE self, VALUE connect_timeout) {
1158
+ CURB_IMMED_GETTER(ruby_curl_easy, connect_timeout, 0);
1159
+ }
1160
+
1161
+ /*
1162
+ * call-seq:
1163
+ * easy.dns_cache_timeout = fixnum or nil => fixnum or nil
1164
+ *
1165
+ * Set the dns cache timeout in seconds. Name resolves will be kept in
1166
+ * memory for this number of seconds. Set to zero (0) to completely disable
1167
+ * caching, or set to nil (or -1) to make the cached entries remain forever.
1168
+ * By default, libcurl caches this info for 60 seconds.
1169
+ */
1170
+ static VALUE ruby_curl_easy_dns_cache_timeout_set(VALUE self, VALUE dns_cache_timeout) {
1171
+ CURB_IMMED_SETTER(ruby_curl_easy, dns_cache_timeout, -1);
1172
+ }
1173
+
1174
+ /*
1175
+ * call-seq:
1176
+ * easy.dns_cache_timeout => fixnum or nil
1177
+ *
1178
+ * Obtain the dns cache timeout in seconds.
1179
+ */
1180
+ static VALUE ruby_curl_easy_dns_cache_timeout_get(VALUE self, VALUE dns_cache_timeout) {
1181
+ CURB_IMMED_GETTER(ruby_curl_easy, dns_cache_timeout, -1);
1182
+ }
1183
+
1184
+ /*
1185
+ * call-seq:
1186
+ * easy.ftp_response_timeout = fixnum or nil => fixnum or nil
1187
+ *
1188
+ * Set a timeout period (in seconds) on the amount of time that the server
1189
+ * is allowed to take in order to generate a response message for a command
1190
+ * before the session is considered hung. While curl is waiting for a
1191
+ * response, this value overrides +timeout+. It is recommended that if used
1192
+ * in conjunction with +timeout+, you set +ftp_response_timeout+ to a value
1193
+ * smaller than +timeout+.
1194
+ *
1195
+ * Ignored if libcurl version is < 7.10.8.
1196
+ */
1197
+ static VALUE ruby_curl_easy_ftp_response_timeout_set(VALUE self, VALUE ftp_response_timeout) {
1198
+ CURB_IMMED_SETTER(ruby_curl_easy, ftp_response_timeout, 0);
1199
+ }
1200
+
1201
+ /*
1202
+ * call-seq:
1203
+ * easy.ftp_response_timeout => fixnum or nil
1204
+ *
1205
+ * Obtain the maximum time that libcurl will wait for FTP command responses.
1206
+ */
1207
+ static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self, VALUE ftp_response_timeout) {
1208
+ CURB_IMMED_GETTER(ruby_curl_easy, ftp_response_timeout, 0);
1209
+ }
1210
+
1211
+ /*
1212
+ * call-seq:
1213
+ * easy.low_speed_limit = fixnum or nil => fixnum or nil
1214
+ *
1215
+ * Set the transfer speed (in bytes per second) that the transfer should be
1216
+ * below during +low_speed_time+ seconds for the library to consider it too
1217
+ * slow and abort.
1218
+ */
1219
+ static VALUE ruby_curl_easy_low_speed_limit_set(VALUE self, VALUE low_speed_limit) {
1220
+ CURB_IMMED_SETTER(ruby_curl_easy, low_speed_limit, 0);
1221
+ }
1222
+
1223
+ /*
1224
+ * call-seq:
1225
+ * easy.low_speed_limit => fixnum or nil
1226
+ *
1227
+ * Obtain the minimum transfer speed over +low_speed+time+ below which the
1228
+ * transfer will be aborted.
1229
+ */
1230
+ static VALUE ruby_curl_easy_low_speed_limit_get(VALUE self, VALUE low_speed_limit) {
1231
+ CURB_IMMED_GETTER(ruby_curl_easy, low_speed_limit, 0);
1232
+ }
1233
+
1234
+ /*
1235
+ * call-seq:
1236
+ * easy.low_speed_time = fixnum or nil => fixnum or nil
1237
+ *
1238
+ * Set the time (in seconds) that the transfer should be below the
1239
+ * +low_speed_limit+ for the library to consider it too slow and abort.
1240
+ */
1241
+ static VALUE ruby_curl_easy_low_speed_time_set(VALUE self, VALUE low_speed_time) {
1242
+ CURB_IMMED_SETTER(ruby_curl_easy, low_speed_time, 0);
1243
+ }
1244
+
1245
+ /*
1246
+ * call-seq:
1247
+ * easy.low_speed_time => fixnum or nil
1248
+ *
1249
+ * Obtain the time that the transfer should be below +low_speed_limit+ for
1250
+ * the library to abort it.
1251
+ */
1252
+ static VALUE ruby_curl_easy_low_speed_time_get(VALUE self, VALUE low_speed_time) {
1253
+ CURB_IMMED_GETTER(ruby_curl_easy, low_speed_time, 0);
1254
+ }
1255
+
1256
+ /*
1257
+ * call-seq:
1258
+ * easy.username = string => string
1259
+ *
1260
+ * Set the HTTP Authentication username.
1261
+ */
1262
+ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
1263
+ #if HAVE_CURLOPT_USERNAME
1264
+ CURB_OBJECT_HSETTER(ruby_curl_easy, username);
1265
+ #else
1266
+ return Qnil;
1267
+ #endif
1268
+ }
1269
+
1270
+ /*
1271
+ * call-seq:
1272
+ * easy.username => string
1273
+ *
1274
+ * Get the current username
1275
+ */
1276
+ static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
1277
+ #if HAVE_CURLOPT_USERNAME
1278
+ CURB_OBJECT_HGETTER(ruby_curl_easy, username);
1279
+ #else
1280
+ return Qnil;
1281
+ #endif
1282
+ }
1283
+
1284
+ /*
1285
+ * call-seq:
1286
+ * easy.password = string => string
1287
+ *
1288
+ * Set the HTTP Authentication password.
1289
+ */
1290
+ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
1291
+ #if HAVE_CURLOPT_PASSWORD
1292
+ CURB_OBJECT_HSETTER(ruby_curl_easy, password);
1293
+ #else
1294
+ return Qnil;
1295
+ #endif
1296
+ }
1297
+
1298
+ /*
1299
+ * call-seq:
1300
+ * easy.password => string
1301
+ *
1302
+ * Get the current password
1303
+ */
1304
+ static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
1305
+ #if HAVE_CURLOPT_PASSWORD
1306
+ CURB_OBJECT_HGETTER(ruby_curl_easy, password);
1307
+ #else
1308
+ return Qnil;
1309
+ #endif
1310
+ }
1311
+
1312
+ /*
1313
+ * call-seq:
1314
+ * easy.ssl_version = value => fixnum or nil
1315
+ *
1316
+ * Sets the version of SSL/TLS that libcurl will attempt to use. Valid
1317
+ * options are Curl::CURL_SSLVERSION_TLSv1, Curl::CURL_SSLVERSION::SSLv2,
1318
+ * Curl::CURL_SSLVERSION_SSLv3 and Curl::CURL_SSLVERSION_DEFAULT
1319
+ */
1320
+ static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
1321
+ CURB_IMMED_SETTER(ruby_curl_easy, ssl_version, -1);
1322
+ }
1323
+
1324
+ /*
1325
+ * call-seq:
1326
+ * easy.ssl_version => fixnum
1327
+ *
1328
+ * Get the version of SSL/TLS that libcurl will attempt to use.
1329
+ */
1330
+ static VALUE ruby_curl_easy_ssl_version_get(VALUE self, VALUE ssl_version) {
1331
+ CURB_IMMED_GETTER(ruby_curl_easy, ssl_version, -1);
1332
+ }
1333
+
1334
+ /*
1335
+ * call-seq:
1336
+ * easy.use_ssl = value => fixnum or nil
1337
+ *
1338
+ * Ensure libcurl uses SSL for FTP connections. Valid options are Curl::CURL_USESSL_NONE,
1339
+ * Curl::CURL_USESSL_TRY, Curl::CURL_USESSL_CONTROL, and Curl::CURL_USESSL_ALL.
1340
+ */
1341
+ static VALUE ruby_curl_easy_use_ssl_set(VALUE self, VALUE use_ssl) {
1342
+ CURB_IMMED_SETTER(ruby_curl_easy, use_ssl, -1);
1343
+ }
1344
+
1345
+ /*
1346
+ * call-seq:
1347
+ * easy.use_ssl => fixnum
1348
+ *
1349
+ * Get the desired level for using SSL on FTP connections.
1350
+ */
1351
+ static VALUE ruby_curl_easy_use_ssl_get(VALUE self, VALUE use_ssl) {
1352
+ CURB_IMMED_GETTER(ruby_curl_easy, use_ssl, -1);
1353
+ }
1354
+
1355
+ /*
1356
+ * call-seq:
1357
+ * easy.ftp_filemethod = value => fixnum or nil
1358
+ *
1359
+ * Controls how libcurl reaches files on the server. Valid options are Curl::CURL_MULTICWD,
1360
+ * Curl::CURL_NOCWD, and Curl::CURL_SINGLECWD (see libcurl docs for CURLOPT_FTP_METHOD).
1361
+ */
1362
+ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod) {
1363
+ CURB_IMMED_SETTER(ruby_curl_easy, ftp_filemethod, -1);
1364
+ }
1365
+
1366
+ /*
1367
+ * call-seq
1368
+ * easy.ftp_filemethod => fixnum
1369
+ *
1370
+ * Get the configuration for how libcurl will reach files on the server.
1371
+ */
1372
+ static VALUE ruby_curl_easy_ftp_filemethod_get(VALUE self, VALUE ftp_filemethod) {
1373
+ CURB_IMMED_GETTER(ruby_curl_easy, ftp_filemethod, -1);
1374
+ }
1375
+
1376
+ /* ================== BOOL ATTRS ===================*/
1377
+
1378
+ /*
1379
+ * call-seq:
1380
+ * easy.proxy_tunnel = boolean => boolean
1381
+ *
1382
+ * Configure whether this Curl instance will use proxy tunneling.
1383
+ */
1384
+ static VALUE ruby_curl_easy_proxy_tunnel_set(VALUE self, VALUE proxy_tunnel) {
1385
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, proxy_tunnel);
1386
+ }
1387
+
1388
+ /*
1389
+ * call-seq:
1390
+ * easy.proxy_tunnel? => boolean
1391
+ *
1392
+ * Determine whether this Curl instance will use proxy tunneling.
1393
+ */
1394
+ static VALUE ruby_curl_easy_proxy_tunnel_q(VALUE self) {
1395
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, proxy_tunnel);
1396
+ }
1397
+
1398
+ /*
1399
+ * call-seq:
1400
+ * easy.fetch_file_time = boolean => boolean
1401
+ *
1402
+ * Configure whether this Curl instance will fetch remote file
1403
+ * times, if available.
1404
+ */
1405
+ static VALUE ruby_curl_easy_fetch_file_time_set(VALUE self, VALUE fetch_file_time) {
1406
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, fetch_file_time);
1407
+ }
1408
+
1409
+ /*
1410
+ * call-seq:
1411
+ * easy.fetch_file_time? => boolean
1412
+ *
1413
+ * Determine whether this Curl instance will fetch remote file
1414
+ * times, if available.
1415
+ */
1416
+ static VALUE ruby_curl_easy_fetch_file_time_q(VALUE self) {
1417
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, fetch_file_time);
1418
+ }
1419
+
1420
+ /*
1421
+ * call-seq:
1422
+ * easy.ssl_verify_peer = boolean => boolean
1423
+ *
1424
+ * Configure whether this Curl instance will verify the SSL peer
1425
+ * certificate. When true (the default), and the verification fails to
1426
+ * prove that the certificate is authentic, the connection fails. When
1427
+ * false, the connection succeeds regardless.
1428
+ *
1429
+ * Authenticating the certificate is not by itself very useful. You
1430
+ * typically want to ensure that the server, as authentically identified
1431
+ * by its certificate, is the server you mean to be talking to.
1432
+ * The ssl_verify_host? options controls that.
1433
+ */
1434
+ static VALUE ruby_curl_easy_ssl_verify_peer_set(VALUE self, VALUE ssl_verify_peer) {
1435
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, ssl_verify_peer);
1436
+ }
1437
+
1438
+ /*
1439
+ * call-seq:
1440
+ * easy.ssl_verify_peer? => boolean
1441
+ *
1442
+ * Determine whether this Curl instance will verify the SSL peer
1443
+ * certificate.
1444
+ */
1445
+ static VALUE ruby_curl_easy_ssl_verify_peer_q(VALUE self) {
1446
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, ssl_verify_peer);
1447
+ }
1448
+
1449
+ /*
1450
+ * call-seq:
1451
+ * easy.ssl_verify_host = [0, 1, 2] => [0, 1, 2]
1452
+ *
1453
+ * Configure whether this Curl instance will verify that the server cert
1454
+ * is for the server it is known as. When true (the default) the server
1455
+ * certificate must indicate that the server is the server to which you
1456
+ * meant to connect, or the connection fails. When false, the connection
1457
+ * will succeed regardless of the names in the certificate.
1458
+ *
1459
+ * this option controls is of the identity that the server claims.
1460
+ * The server could be lying. To control lying, see ssl_verify_peer? .
1461
+ */
1462
+ static VALUE ruby_curl_easy_ssl_verify_host_set(VALUE self, VALUE ssl_verify_host) {
1463
+ CURB_IMMED_SETTER(ruby_curl_easy, ssl_verify_host, 0);
1464
+ }
1465
+
1466
+ /*
1467
+ * call-seq:
1468
+ * easy.ssl_verify_host => number
1469
+ *
1470
+ * Determine whether this Curl instance will verify that the server cert
1471
+ * is for the server it is known as.
1472
+ */
1473
+ static VALUE ruby_curl_easy_ssl_verify_host_get(VALUE self) {
1474
+ CURB_IMMED_GETTER(ruby_curl_easy, ssl_verify_host, 0);
1475
+ }
1476
+
1477
+ /*
1478
+ * call-seq:
1479
+ * easy.header_in_body = boolean => boolean
1480
+ *
1481
+ * Configure whether this Curl instance will return HTTP headers
1482
+ * combined with body data. If this option is set true, both header
1483
+ * and body data will go to +body_str+ (or the configured +on_body+ handler).
1484
+ */
1485
+ static VALUE ruby_curl_easy_header_in_body_set(VALUE self, VALUE header_in_body) {
1486
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, header_in_body);
1487
+ }
1488
+
1489
+ /*
1490
+ * call-seq:
1491
+ * easy.header_in_body? => boolean
1492
+ *
1493
+ * Determine whether this Curl instance will return HTTP headers
1494
+ * combined with body data.
1495
+ */
1496
+ static VALUE ruby_curl_easy_header_in_body_q(VALUE self) {
1497
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, header_in_body);
1498
+ }
1499
+
1500
+ /*
1501
+ * call-seq:
1502
+ * easy.use_netrc = boolean => boolean
1503
+ *
1504
+ * Configure whether this Curl instance will use data from the user's
1505
+ * .netrc file for FTP connections.
1506
+ */
1507
+ static VALUE ruby_curl_easy_use_netrc_set(VALUE self, VALUE use_netrc) {
1508
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, use_netrc);
1509
+ }
1510
+
1511
+ /*
1512
+ * call-seq:
1513
+ * easy.use_netrc? => boolean
1514
+ *
1515
+ * Determine whether this Curl instance will use data from the user's
1516
+ * .netrc file for FTP connections.
1517
+ */
1518
+ static VALUE ruby_curl_easy_use_netrc_q(VALUE self) {
1519
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, use_netrc);
1520
+ }
1521
+
1522
+ /*
1523
+ * call-seq:
1524
+ *
1525
+ * easy = Curl::Easy.new
1526
+ * easy.autoreferer=true
1527
+ */
1528
+ static VALUE ruby_curl_easy_autoreferer_set(VALUE self, VALUE autoreferer) {
1529
+ ruby_curl_easy *rbce;
1530
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1531
+
1532
+ if (Qtrue == autoreferer) {
1533
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 1);
1534
+ }
1535
+ else {
1536
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 0);
1537
+ }
1538
+
1539
+ return autoreferer;
1540
+ }
1541
+
1542
+ /*
1543
+ * call-seq:
1544
+ * easy.follow_location? => boolean
1545
+ *
1546
+ * Determine whether this Curl instance will follow Location: headers
1547
+ * in HTTP responses.
1548
+ */
1549
+ static VALUE ruby_curl_easy_follow_location_q(VALUE self) {
1550
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, follow_location);
1551
+ }
1552
+
1553
+ /*
1554
+ * call-seq:
1555
+ * easy.unrestricted_auth = boolean => boolean
1556
+ *
1557
+ * Configure whether this Curl instance may use any HTTP authentication
1558
+ * method available when necessary.
1559
+ */
1560
+ static VALUE ruby_curl_easy_unrestricted_auth_set(VALUE self, VALUE unrestricted_auth) {
1561
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, unrestricted_auth);
1562
+ }
1563
+
1564
+ /*
1565
+ * call-seq:
1566
+ * easy.unrestricted_auth? => boolean
1567
+ *
1568
+ * Determine whether this Curl instance may use any HTTP authentication
1569
+ * method available when necessary.
1570
+ */
1571
+ static VALUE ruby_curl_easy_unrestricted_auth_q(VALUE self) {
1572
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, unrestricted_auth);
1573
+ }
1574
+
1575
+ /*
1576
+ * call-seq:
1577
+ * easy.verbose = boolean => boolean
1578
+ *
1579
+ * Configure whether this Curl instance gives verbose output to STDERR
1580
+ * during transfers. Ignored if this instance has an on_debug handler.
1581
+ */
1582
+ static VALUE ruby_curl_easy_verbose_set(VALUE self, VALUE verbose) {
1583
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, verbose);
1584
+ }
1585
+
1586
+ /*
1587
+ * call-seq:
1588
+ * easy.verbose? => boolean
1589
+ *
1590
+ * Determine whether this Curl instance gives verbose output to STDERR
1591
+ * during transfers.
1592
+ */
1593
+ static VALUE ruby_curl_easy_verbose_q(VALUE self) {
1594
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, verbose);
1595
+ }
1596
+
1597
+ /*
1598
+ * call-seq:
1599
+ * easy.multipart_form_post = boolean => boolean
1600
+ *
1601
+ * Configure whether this Curl instance uses multipart/formdata content
1602
+ * type for HTTP POST requests. If this is false (the default), then the
1603
+ * application/x-www-form-urlencoded content type is used for the form
1604
+ * data.
1605
+ *
1606
+ * If this is set true, you must pass one or more PostField instances
1607
+ * to the http_post method - no support for posting multipart forms from
1608
+ * a string is provided.
1609
+ */
1610
+ static VALUE ruby_curl_easy_multipart_form_post_set(VALUE self, VALUE multipart_form_post)
1611
+ {
1612
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, multipart_form_post);
1613
+ }
1614
+
1615
+ /*
1616
+ * call-seq:
1617
+ * easy.multipart_form_post? => boolean
1618
+ *
1619
+ * Determine whether this Curl instance uses multipart/formdata content
1620
+ * type for HTTP POST requests.
1621
+ */
1622
+ static VALUE ruby_curl_easy_multipart_form_post_q(VALUE self) {
1623
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, multipart_form_post);
1624
+ }
1625
+
1626
+ /*
1627
+ * call-seq:
1628
+ * easy.enable_cookies = boolean => boolean
1629
+ *
1630
+ * Configure whether the libcurl cookie engine is enabled for this Curl::Easy
1631
+ * instance.
1632
+ */
1633
+ static VALUE ruby_curl_easy_enable_cookies_set(VALUE self, VALUE enable_cookies)
1634
+ {
1635
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, enable_cookies);
1636
+ }
1637
+
1638
+ /*
1639
+ * call-seq:
1640
+ * easy.enable_cookies? => boolean
1641
+ *
1642
+ * Determine whether the libcurl cookie engine is enabled for this
1643
+ * Curl::Easy instance.
1644
+ */
1645
+ static VALUE ruby_curl_easy_enable_cookies_q(VALUE self) {
1646
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, enable_cookies);
1647
+ }
1648
+
1649
+ /*
1650
+ * call-seq:
1651
+ * easy.ignore_content_length = boolean
1652
+ *
1653
+ * Configure whether this Curl::Easy instance should ignore the content
1654
+ * length header.
1655
+ */
1656
+ static VALUE ruby_curl_easy_ignore_content_length_set(VALUE self, VALUE ignore_content_length)
1657
+ {
1658
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, ignore_content_length);
1659
+ }
1660
+
1661
+ /*
1662
+ * call-seq:
1663
+ * easy.ignore_content_length? => boolean
1664
+ *
1665
+ * Determine whether this Curl::Easy instance ignores the content
1666
+ * length header.
1667
+ */
1668
+ static VALUE ruby_curl_easy_ignore_content_length_q(VALUE self) {
1669
+ CURB_BOOLEAN_GETTER(ruby_curl_easy, ignore_content_length);
1670
+ }
1671
+
1672
+ /*
1673
+ * call-seq:
1674
+ * easy.resolve_mode => symbol
1675
+ *
1676
+ * Determines what type of IP address this Curl::Easy instance
1677
+ * resolves DNS names to.
1678
+ */
1679
+ static VALUE ruby_curl_easy_resolve_mode(VALUE self) {
1680
+ ruby_curl_easy *rbce;
1681
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1682
+
1683
+ unsigned short rm = rbce->resolve_mode;
1684
+
1685
+ switch(rm) {
1686
+ case CURL_IPRESOLVE_V4:
1687
+ return rb_easy_sym("ipv4");
1688
+ case CURL_IPRESOLVE_V6:
1689
+ return rb_easy_sym("ipv6");
1690
+ default:
1691
+ return rb_easy_sym("auto");
1692
+ }
1693
+ }
1694
+
1695
+ /*
1696
+ * call-seq:
1697
+ * easy.resolve_mode = symbol => symbol
1698
+ *
1699
+ * Configures what type of IP address this Curl::Easy instance
1700
+ * resolves DNS names to. Valid options are:
1701
+ *
1702
+ * [:auto] resolves DNS names to all IP versions your system allows
1703
+ * [:ipv4] resolves DNS names to IPv4 only
1704
+ * [:ipv6] resolves DNS names to IPv6 only
1705
+ */
1706
+ static VALUE ruby_curl_easy_resolve_mode_set(VALUE self, VALUE resolve_mode) {
1707
+ if (TYPE(resolve_mode) != T_SYMBOL) {
1708
+ rb_raise(rb_eTypeError, "Must pass a symbol");
1709
+ return Qnil;
1710
+ } else {
1711
+ ruby_curl_easy *rbce;
1712
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1713
+
1714
+ ID resolve_mode_id = rb_to_id(resolve_mode);
1715
+
1716
+ if (resolve_mode_id == rb_intern("auto")) {
1717
+ rbce->resolve_mode = CURL_IPRESOLVE_WHATEVER;
1718
+ return resolve_mode;
1719
+ } else if (resolve_mode_id == rb_intern("ipv4")) {
1720
+ rbce->resolve_mode = CURL_IPRESOLVE_V4;
1721
+ return resolve_mode;
1722
+ } else if (resolve_mode_id == rb_intern("ipv6")) {
1723
+ rbce->resolve_mode = CURL_IPRESOLVE_V6;
1724
+ return resolve_mode;
1725
+ } else {
1726
+ rb_raise(rb_eArgError, "Must set to one of :auto, :ipv4, :ipv6");
1727
+ return Qnil;
1728
+ }
1729
+ }
1730
+ }
1731
+
1732
+
1733
+ /* ================= EVENT PROCS ================== */
1734
+
1735
+ /*
1736
+ * call-seq:
1737
+ * easy.on_body { |body_data| ... } => &lt;old handler&gt;
1738
+ *
1739
+ * Assign or remove the +on_body+ handler for this Curl::Easy instance.
1740
+ * To remove a previously-supplied handler, call this method with no
1741
+ * attached block.
1742
+ *
1743
+ * The +on_body+ handler is called for each chunk of response body passed back
1744
+ * by libcurl during +perform+. It should perform any processing necessary,
1745
+ * and return the actual number of bytes handled. Normally, this will
1746
+ * equal the length of the data string, and CURL will continue processing.
1747
+ * If the returned length does not equal the input length, CURL will abort
1748
+ * the processing with a Curl::Err::AbortedByCallbackError.
1749
+ */
1750
+ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
1751
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, body_proc);
1752
+ }
1753
+
1754
+ /*
1755
+ * call-seq:
1756
+ * easy.on_success { |easy| ... } => &lt;old handler&gt;
1757
+ *
1758
+ * Assign or remove the +on_success+ handler for this Curl::Easy instance.
1759
+ * To remove a previously-supplied handler, call this method with no
1760
+ * attached block.
1761
+ *
1762
+ * The +on_success+ handler is called when the request is finished with a
1763
+ * status of 20x
1764
+ */
1765
+ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
1766
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, success_proc);
1767
+ }
1768
+
1769
+ /*
1770
+ * call-seq:
1771
+ * easy.on_failure {|easy,code| ... } => &lt;old handler&gt;
1772
+ *
1773
+ * Assign or remove the +on_failure+ handler for this Curl::Easy instance.
1774
+ * To remove a previously-supplied handler, call this method with no
1775
+ * attached block.
1776
+ *
1777
+ * The +on_failure+ handler is called when the request is finished with a
1778
+ * status of 50x
1779
+ */
1780
+ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
1781
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, failure_proc);
1782
+ }
1783
+
1784
+ /*
1785
+ * call-seq:
1786
+ * easy.on_missing {|easy,code| ... } => &lt;old handler;&gt;
1787
+ *
1788
+ * Assign or remove the on_missing handler for this Curl::Easy instance.
1789
+ * To remove a previously-supplied handler, call this method with no attached
1790
+ * block.
1791
+ *
1792
+ * The +on_missing+ handler is called when request is finished with a
1793
+ * status of 40x
1794
+ */
1795
+ static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
1796
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, missing_proc);
1797
+ }
1798
+
1799
+ /*
1800
+ * call-seq:
1801
+ * easy.on_redirect {|easy,code| ... } => &lt;old handler;&gt;
1802
+ *
1803
+ * Assign or remove the on_redirect handler for this Curl::Easy instance.
1804
+ * To remove a previously-supplied handler, call this method with no attached
1805
+ * block.
1806
+ *
1807
+ * The +on_redirect+ handler is called when request is finished with a
1808
+ * status of 30x
1809
+ */
1810
+ static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
1811
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, redirect_proc);
1812
+ }
1813
+
1814
+ /*
1815
+ * call-seq:
1816
+ * easy.on_complete {|easy| ... } => &lt;old handler&gt;
1817
+ *
1818
+ * Assign or remove the +on_complete+ handler for this Curl::Easy instance.
1819
+ * To remove a previously-supplied handler, call this method with no
1820
+ * attached block.
1821
+ *
1822
+ * The +on_complete+ handler is called when the request is finished.
1823
+ */
1824
+ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
1825
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, complete_proc);
1826
+ }
1827
+ static VALUE ruby_curl_easy_optional_callback_set(int argc, VALUE *argv, VALUE self) {
1828
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, callback);
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
+ VALUE args_ary;
2342
+ VALUE post_body = Qnil;
2343
+ rb_scan_args(argc, argv, "*", &args_ary);
2344
+
2345
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2346
+ curl = rbce->curl;
2347
+
2348
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2349
+
2350
+ if (rbce->multipart_form_post) {
2351
+ VALUE ret;
2352
+ if ((post_body = rb_funcall(args_ary, idFlatten, 0)) == Qnil) {
2353
+ rb_raise(eCurlErrError, "Failed to flatten arguments");
2354
+ return Qnil;
2355
+ } else {
2356
+ ruby_curl_easy_multipart_post_body_set(self, post_body);
2357
+ ret = rb_funcall(self, rb_intern("perform"), 0);
2358
+ curl_formfree(rbce->first);
2359
+
2360
+ return ret;
2361
+ }
2362
+ } else {
2363
+ /* TODO: check for PostField.file and raise error before to_s fails */
2364
+ if ((post_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp)) == Qnil) {
2365
+ rb_raise(eCurlErrError, "Failed to join arguments");
2366
+ return Qnil;
2367
+ } else {
2368
+ /* if the function call above returns an empty string because no additional arguments were passed this makes sure
2369
+ a previously set easy.post_body = "arg=foo&bar=bin" will be honored */
2370
+ if( post_body != Qnil && rb_type(post_body) == T_STRING && RSTRING_LEN(post_body) > 0 ) {
2371
+ ruby_curl_easy_post_body_set(self, post_body);
2372
+ }
2373
+
2374
+ /* if post body is not defined, set it so we enable POST header, even though the request body is empty */
2375
+ if( rb_easy_nil("postdata_buffer") ) {
2376
+ ruby_curl_easy_post_body_set(self, post_body);
2377
+ }
2378
+
2379
+ return rb_funcall(self, rb_intern("perform"), 0);
2380
+ }
2381
+ }
2382
+ }
2383
+
2384
+ /*
2385
+ * call-seq:
2386
+ * easy.http_put(data) => true
2387
+ *
2388
+ * PUT the supplied data to the currently configured URL using the
2389
+ * current options set for this Curl::Easy instance. This method always
2390
+ * returns true, or raises an exception (defined under Curl::Err) on error.
2391
+ */
2392
+ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2393
+ ruby_curl_easy *rbce;
2394
+ CURL *curl;
2395
+
2396
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2397
+ curl = rbce->curl;
2398
+
2399
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2400
+ ruby_curl_easy_put_data_set(self, data);
2401
+
2402
+ return rb_funcall(self, rb_intern("perform"), 0);
2403
+ }
2404
+
2405
+
2406
+ /* =================== DATA FUNCS =============== */
2407
+
2408
+ /*
2409
+ * call-seq:
2410
+ * easy.body_str => "response body"
2411
+ *
2412
+ * Return the response body from the previous call to +perform+. This
2413
+ * is populated by the default +on_body+ handler - if you supply
2414
+ * your own body handler, this string will be empty.
2415
+ */
2416
+ static VALUE ruby_curl_easy_body_str_get(VALUE self) {
2417
+ CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
2418
+ }
2419
+
2420
+ /*
2421
+ * call-seq:
2422
+ * easy.header_str => "response header"
2423
+ *
2424
+ * Return the response header from the previous call to +perform+. This
2425
+ * is populated by the default +on_header+ handler - if you supply
2426
+ * your own header handler, this string will be empty.
2427
+ */
2428
+ static VALUE ruby_curl_easy_header_str_get(VALUE self) {
2429
+ CURB_OBJECT_HGETTER(ruby_curl_easy, header_data);
2430
+ }
2431
+
2432
+
2433
+ /* ============== LASTCONN INFO FUNCS ============ */
2434
+
2435
+ /*
2436
+ * call-seq:
2437
+ * easy.last_effective_url => "http://some.url" or nil
2438
+ *
2439
+ * Retrieve the last effective URL used by this instance.
2440
+ * This is the URL used in the last +perform+ call,
2441
+ * and may differ from the value of easy.url.
2442
+ */
2443
+ static VALUE ruby_curl_easy_last_effective_url_get(VALUE self) {
2444
+ ruby_curl_easy *rbce;
2445
+ char* url;
2446
+
2447
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2448
+ curl_easy_getinfo(rbce->curl, CURLINFO_EFFECTIVE_URL, &url);
2449
+
2450
+ if (url && url[0]) { // curl returns empty string if none
2451
+ return rb_str_new2(url);
2452
+ } else {
2453
+ return Qnil;
2454
+ }
2455
+ }
2456
+
2457
+ /*
2458
+ * call-seq:
2459
+ * easy.response_code => fixnum
2460
+ *
2461
+ * Retrieve the last received HTTP or FTP code. This will be zero
2462
+ * if no server response code has been received. Note that a proxy's
2463
+ * CONNECT response should be read with +http_connect_code+
2464
+ * and not this method.
2465
+ */
2466
+ static VALUE ruby_curl_easy_response_code_get(VALUE self) {
2467
+ ruby_curl_easy *rbce;
2468
+ long code;
2469
+
2470
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2471
+ #ifdef HAVE_CURLINFO_RESPONSE_CODE
2472
+ curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &code);
2473
+ #else
2474
+ // old libcurl
2475
+ curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &code);
2476
+ #endif
2477
+
2478
+ return LONG2NUM(code);
2479
+ }
2480
+
2481
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
2482
+ /*
2483
+ * call-seq:
2484
+ * easy.primary_ip => "xx.xx.xx.xx" or nil
2485
+ *
2486
+ * Retrieve the resolved IP of the most recent connection
2487
+ * done with this curl handle. This string may be IPv6 if
2488
+ * that's enabled. This feature requires curl 7.19.x and above
2489
+ */
2490
+ static VALUE ruby_curl_easy_primary_ip_get(VALUE self) {
2491
+ ruby_curl_easy *rbce;
2492
+ char* ip;
2493
+
2494
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2495
+ curl_easy_getinfo(rbce->curl, CURLINFO_PRIMARY_IP, &ip);
2496
+
2497
+ if (ip && ip[0]) { // curl returns empty string if none
2498
+ return rb_str_new2(ip);
2499
+ } else {
2500
+ return Qnil;
2501
+ }
2502
+ }
2503
+ #endif
2504
+
2505
+ /*
2506
+ * call-seq:
2507
+ * easy.http_connect_code => fixnum
2508
+ *
2509
+ * Retrieve the last received proxy response code to a CONNECT request.
2510
+ */
2511
+ static VALUE ruby_curl_easy_http_connect_code_get(VALUE self) {
2512
+ ruby_curl_easy *rbce;
2513
+ long code;
2514
+
2515
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2516
+ curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CONNECTCODE, &code);
2517
+
2518
+ return LONG2NUM(code);
2519
+ }
2520
+
2521
+ /*
2522
+ * call-seq:
2523
+ * easy.file_time => fixnum
2524
+ *
2525
+ * Retrieve the remote time of the retrieved document (in number of
2526
+ * seconds since 1 jan 1970 in the GMT/UTC time zone). If you get -1,
2527
+ * it can be because of many reasons (unknown, the server hides it
2528
+ * or the server doesn't support the command that tells document time
2529
+ * etc) and the time of the document is unknown.
2530
+ *
2531
+ * Note that you must tell the server to collect this information
2532
+ * before the transfer is made, by setting +fetch_file_time?+ to true,
2533
+ * or you will unconditionally get a -1 back.
2534
+ *
2535
+ * This requires libcurl 7.5 or higher - otherwise -1 is unconditionally
2536
+ * returned.
2537
+ */
2538
+ static VALUE ruby_curl_easy_file_time_get(VALUE self) {
2539
+ #ifdef HAVE_CURLINFO_FILETIME
2540
+ ruby_curl_easy *rbce;
2541
+ long time;
2542
+
2543
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2544
+ curl_easy_getinfo(rbce->curl, CURLINFO_FILETIME, &time);
2545
+
2546
+ return LONG2NUM(time);
2547
+ #else
2548
+ rb_warn("Installed libcurl is too old to support file_time");
2549
+ return INT2FIX(0);
2550
+ #endif
2551
+ }
2552
+
2553
+ /*
2554
+ * call-seq:
2555
+ * easy.total_time => float
2556
+ *
2557
+ * Retrieve the total time in seconds for the previous transfer,
2558
+ * including name resolving, TCP connect etc.
2559
+ */
2560
+ static VALUE ruby_curl_easy_total_time_get(VALUE self) {
2561
+ ruby_curl_easy *rbce;
2562
+ double time;
2563
+
2564
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2565
+ curl_easy_getinfo(rbce->curl, CURLINFO_TOTAL_TIME, &time);
2566
+
2567
+ return rb_float_new(time);
2568
+ }
2569
+
2570
+ /*
2571
+ * call-seq:
2572
+ * easy.name_lookup_time => float
2573
+ *
2574
+ * Retrieve the time, in seconds, it took from the start until the
2575
+ * name resolving was completed.
2576
+ */
2577
+ static VALUE ruby_curl_easy_name_lookup_time_get(VALUE self) {
2578
+ ruby_curl_easy *rbce;
2579
+ double time;
2580
+
2581
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2582
+ curl_easy_getinfo(rbce->curl, CURLINFO_NAMELOOKUP_TIME, &time);
2583
+
2584
+ return rb_float_new(time);
2585
+ }
2586
+
2587
+ /*
2588
+ * call-seq:
2589
+ * easy.connect_time => float
2590
+ *
2591
+ * Retrieve the time, in seconds, it took from the start until the
2592
+ * connect to the remote host (or proxy) was completed.
2593
+ */
2594
+ static VALUE ruby_curl_easy_connect_time_get(VALUE self) {
2595
+ ruby_curl_easy *rbce;
2596
+ double time;
2597
+
2598
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2599
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONNECT_TIME, &time);
2600
+
2601
+ return rb_float_new(time);
2602
+ }
2603
+
2604
+ /*
2605
+ * call-seq:
2606
+ * easy.pre_transfer_time => float
2607
+ *
2608
+ * Retrieve the time, in seconds, it took from the start until the
2609
+ * file transfer is just about to begin. This includes all pre-transfer
2610
+ * commands and negotiations that are specific to the particular protocol(s)
2611
+ * involved.
2612
+ */
2613
+ static VALUE ruby_curl_easy_pre_transfer_time_get(VALUE self) {
2614
+ ruby_curl_easy *rbce;
2615
+ double time;
2616
+
2617
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2618
+ curl_easy_getinfo(rbce->curl, CURLINFO_PRETRANSFER_TIME, &time);
2619
+
2620
+ return rb_float_new(time);
2621
+ }
2622
+
2623
+ /*
2624
+ * call-seq:
2625
+ * easy.start_transfer_time => float
2626
+ *
2627
+ * Retrieve the time, in seconds, it took from the start until the first byte
2628
+ * is just about to be transferred. This includes the +pre_transfer_time+ and
2629
+ * also the time the server needs to calculate the result.
2630
+ */
2631
+ static VALUE ruby_curl_easy_start_transfer_time_get(VALUE self) {
2632
+ ruby_curl_easy *rbce;
2633
+ double time;
2634
+
2635
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2636
+ curl_easy_getinfo(rbce->curl, CURLINFO_STARTTRANSFER_TIME, &time);
2637
+
2638
+ return rb_float_new(time);
2639
+ }
2640
+
2641
+ /*
2642
+ * call-seq:
2643
+ * easy.redirect_time => float
2644
+ *
2645
+ * Retrieve the total time, in seconds, it took for all redirection steps
2646
+ * include name lookup, connect, pretransfer and transfer before final
2647
+ * transaction was started. +redirect_time+ contains the complete
2648
+ * execution time for multiple redirections.
2649
+ *
2650
+ * Requires libcurl 7.9.7 or higher, otherwise -1 is always returned.
2651
+ */
2652
+ static VALUE ruby_curl_easy_redirect_time_get(VALUE self) {
2653
+ #ifdef HAVE_CURLINFO_REDIRECT_TIME
2654
+ ruby_curl_easy *rbce;
2655
+ double time;
2656
+
2657
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2658
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_TIME, &time);
2659
+
2660
+ return rb_float_new(time);
2661
+ #else
2662
+ rb_warn("Installed libcurl is too old to support redirect_time");
2663
+ return rb_float_new(-1);
2664
+ #endif
2665
+ }
2666
+
2667
+ /*
2668
+ * call-seq:
2669
+ * easy.redirect_count => integer
2670
+ *
2671
+ * Retrieve the total number of redirections that were actually followed.
2672
+ *
2673
+ * Requires libcurl 7.9.7 or higher, otherwise -1 is always returned.
2674
+ */
2675
+ static VALUE ruby_curl_easy_redirect_count_get(VALUE self) {
2676
+ #ifdef HAVE_CURLINFO_REDIRECT_COUNT
2677
+ ruby_curl_easy *rbce;
2678
+ long count;
2679
+
2680
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2681
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_COUNT, &count);
2682
+
2683
+ return LONG2NUM(count);
2684
+ #else
2685
+ rb_warn("Installed libcurl is too old to support redirect_count");
2686
+ return INT2FIX(-1);
2687
+ #endif
2688
+
2689
+ }
2690
+
2691
+ /*
2692
+ * call-seq:
2693
+ * easy.redirect_url => "http://some.url" or nil
2694
+ *
2695
+ * Retrieve the URL a redirect would take you to if you
2696
+ * would enable CURLOPT_FOLLOWLOCATION.
2697
+ *
2698
+ * Requires libcurl 7.18.2 or higher, otherwise -1 is always returned.
2699
+ */
2700
+ static VALUE ruby_curl_easy_redirect_url_get(VALUE self) {
2701
+ #ifdef HAVE_CURLINFO_REDIRECT_URL
2702
+ ruby_curl_easy *rbce;
2703
+ char* url;
2704
+
2705
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2706
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_URL, &url);
2707
+
2708
+ if (url && url[0]) { // curl returns empty string if none
2709
+ return rb_str_new2(url);
2710
+ } else {
2711
+ return Qnil;
2712
+ }
2713
+ #else
2714
+ rb_warn("Installed libcurl is too old to support redirect_url");
2715
+ return INT2FIX(-1);
2716
+ #endif
2717
+ }
2718
+
2719
+
2720
+
2721
+ /*
2722
+ * call-seq:
2723
+ * easy.uploaded_bytes => float
2724
+ *
2725
+ * Retrieve the total amount of bytes that were uploaded in the
2726
+ * preceeding transfer.
2727
+ */
2728
+ static VALUE ruby_curl_easy_uploaded_bytes_get(VALUE self) {
2729
+ ruby_curl_easy *rbce;
2730
+ double bytes;
2731
+
2732
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2733
+ curl_easy_getinfo(rbce->curl, CURLINFO_SIZE_UPLOAD, &bytes);
2734
+
2735
+ return rb_float_new(bytes);
2736
+ }
2737
+
2738
+ /*
2739
+ * call-seq:
2740
+ * easy.downloaded_bytes => float
2741
+ *
2742
+ * Retrieve the total amount of bytes that were downloaded in the
2743
+ * preceeding transfer.
2744
+ */
2745
+ static VALUE ruby_curl_easy_downloaded_bytes_get(VALUE self) {
2746
+ ruby_curl_easy *rbce;
2747
+ double bytes;
2748
+
2749
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2750
+ curl_easy_getinfo(rbce->curl, CURLINFO_SIZE_DOWNLOAD, &bytes);
2751
+
2752
+ return rb_float_new(bytes);
2753
+ }
2754
+
2755
+ /*
2756
+ * call-seq:
2757
+ * easy.upload_speed => float
2758
+ *
2759
+ * Retrieve the average upload speed that curl measured for the
2760
+ * preceeding complete upload.
2761
+ */
2762
+ static VALUE ruby_curl_easy_upload_speed_get(VALUE self) {
2763
+ ruby_curl_easy *rbce;
2764
+ double bytes;
2765
+
2766
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2767
+ curl_easy_getinfo(rbce->curl, CURLINFO_SPEED_UPLOAD, &bytes);
2768
+
2769
+ return rb_float_new(bytes);
2770
+ }
2771
+
2772
+ /*
2773
+ * call-seq:
2774
+ * easy.download_speed => float
2775
+ *
2776
+ * Retrieve the average download speed that curl measured for
2777
+ * the preceeding complete download.
2778
+ */
2779
+ static VALUE ruby_curl_easy_download_speed_get(VALUE self) {
2780
+ ruby_curl_easy *rbce;
2781
+ double bytes;
2782
+
2783
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2784
+ curl_easy_getinfo(rbce->curl, CURLINFO_SPEED_DOWNLOAD, &bytes);
2785
+
2786
+ return rb_float_new(bytes);
2787
+ }
2788
+
2789
+ /*
2790
+ * call-seq:
2791
+ * easy.header_size => fixnum
2792
+ *
2793
+ * Retrieve the total size of all the headers received in the
2794
+ * preceeding transfer.
2795
+ */
2796
+ static VALUE ruby_curl_easy_header_size_get(VALUE self) {
2797
+ ruby_curl_easy *rbce;
2798
+ long size;
2799
+
2800
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2801
+ curl_easy_getinfo(rbce->curl, CURLINFO_HEADER_SIZE, &size);
2802
+
2803
+ return LONG2NUM(size);
2804
+ }
2805
+
2806
+ /*
2807
+ * call-seq:
2808
+ * easy.request_size => fixnum
2809
+ *
2810
+ * Retrieve the total size of the issued requests. This is so far
2811
+ * only for HTTP requests. Note that this may be more than one request
2812
+ * if +follow_location?+ is true.
2813
+ */
2814
+ static VALUE ruby_curl_easy_request_size_get(VALUE self) {
2815
+ ruby_curl_easy *rbce;
2816
+ long size;
2817
+
2818
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2819
+ curl_easy_getinfo(rbce->curl, CURLINFO_REQUEST_SIZE, &size);
2820
+
2821
+ return LONG2NUM(size);
2822
+ }
2823
+
2824
+ /*
2825
+ * call-seq:
2826
+ * easy.ssl_verify_result => integer
2827
+ *
2828
+ * Retrieve the result of the certification verification that was requested
2829
+ * (by setting +ssl_verify_peer?+ to +true+).
2830
+ */
2831
+ static VALUE ruby_curl_easy_ssl_verify_result_get(VALUE self) {
2832
+ ruby_curl_easy *rbce;
2833
+ long result;
2834
+
2835
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2836
+ curl_easy_getinfo(rbce->curl, CURLINFO_SSL_VERIFYRESULT, &result);
2837
+
2838
+ return LONG2NUM(result);
2839
+ }
2840
+
2841
+ /* TODO CURLINFO_SSL_ENGINES
2842
+
2843
+ Pass the address of a 'struct curl_slist *' to receive a linked-list of OpenSSL crypto-engines supported.
2844
+ Note that engines are normally implemented in separate dynamic libraries.
2845
+ Hence not all the returned engines may be available at run-time.
2846
+ 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)
2847
+ */
2848
+
2849
+ /*
2850
+ * call-seq:
2851
+ * easy.downloaded_content_length => float
2852
+ *
2853
+ * Retrieve the content-length of the download. This is the value read
2854
+ * from the Content-Length: field.
2855
+ */
2856
+ static VALUE ruby_curl_easy_downloaded_content_length_get(VALUE self) {
2857
+ ruby_curl_easy *rbce;
2858
+ double bytes;
2859
+
2860
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2861
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &bytes);
2862
+
2863
+ return rb_float_new(bytes);
2864
+ }
2865
+
2866
+ /*
2867
+ * call-seq:
2868
+ * easy.uploaded_content_length => float
2869
+ *
2870
+ * Retrieve the content-length of the upload.
2871
+ */
2872
+ static VALUE ruby_curl_easy_uploaded_content_length_get(VALUE self) {
2873
+ ruby_curl_easy *rbce;
2874
+ double bytes;
2875
+
2876
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2877
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &bytes);
2878
+
2879
+ return rb_float_new(bytes);
2880
+ }
2881
+
2882
+ /*
2883
+ * call-seq:
2884
+ * easy.content_type => "content/type" or nil
2885
+ *
2886
+ * Retrieve the content-type of the downloaded object. This is the value read
2887
+ * from the Content-Type: field. If you get +nil+, it means that the server
2888
+ * didn't send a valid Content-Type header or that the protocol used doesn't
2889
+ * support this.
2890
+ */
2891
+ static VALUE ruby_curl_easy_content_type_get(VALUE self) {
2892
+ ruby_curl_easy *rbce;
2893
+ char* type;
2894
+
2895
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2896
+ curl_easy_getinfo(rbce->curl, CURLINFO_CONTENT_TYPE, &type);
2897
+
2898
+ if (type && type[0]) { // curl returns empty string if none
2899
+ return rb_str_new2(type);
2900
+ } else {
2901
+ return Qnil;
2902
+ }
2903
+ }
2904
+
2905
+
2906
+ /* NOT REQUIRED?
2907
+ CURLINFO_PRIVATE
2908
+
2909
+ 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)
2910
+ */
2911
+
2912
+ /* TODO these will need constants setting up too for checking the bits.
2913
+ *
2914
+ * Alternatively, could return an object that wraps the long, and has
2915
+ * question methods to query the auth types. Could return long from to_i(nt)
2916
+ *
2917
+ CURLINFO_HTTPAUTH_AVAIL
2918
+
2919
+ 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)
2920
+
2921
+ CURLINFO_PROXYAUTH_AVAIL
2922
+
2923
+ 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)
2924
+ */
2925
+
2926
+ /*
2927
+ * call-seq:
2928
+ * easy.os_errno => integer
2929
+ *
2930
+ * Retrieve the errno variable from a connect failure (requires
2931
+ * libcurl 7.12.2 or higher, otherwise 0 is always returned).
2932
+ */
2933
+ static VALUE ruby_curl_easy_os_errno_get(VALUE self) {
2934
+ #ifdef HAVE_CURLINFO_OS_ERRNO
2935
+ ruby_curl_easy *rbce;
2936
+ long result;
2937
+
2938
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2939
+ curl_easy_getinfo(rbce->curl, CURLINFO_OS_ERRNO, &result);
2940
+
2941
+ return LONG2NUM(result);
2942
+ #else
2943
+ rb_warn("Installed libcurl is too old to support os_errno");
2944
+ return INT2FIX(0);
2945
+ #endif
2946
+ }
2947
+
2948
+ /*
2949
+ * call-seq:
2950
+ * easy.num_connects => integer
2951
+ *
2952
+ * Retrieve the number of new connections libcurl had to create to achieve
2953
+ * the previous transfer (only the successful connects are counted).
2954
+ * Combined with +redirect_count+ you are able to know how many times libcurl
2955
+ * successfully reused existing connection(s) or not.
2956
+ *
2957
+ * See the Connection Options of curl_easy_setopt(3) to see how libcurl tries
2958
+ * to make persistent connections to save time.
2959
+ *
2960
+ * (requires libcurl 7.12.3 or higher, otherwise -1 is always returned).
2961
+ */
2962
+ static VALUE ruby_curl_easy_num_connects_get(VALUE self) {
2963
+ #ifdef HAVE_CURLINFO_NUM_CONNECTS
2964
+ ruby_curl_easy *rbce;
2965
+ long result;
2966
+
2967
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2968
+ curl_easy_getinfo(rbce->curl, CURLINFO_NUM_CONNECTS, &result);
2969
+
2970
+ return LONG2NUM(result);
2971
+ #else
2972
+ rb_warn("Installed libcurl is too old to support num_connects");
2973
+ return INT2FIX(-1);
2974
+ #endif
2975
+ }
2976
+
2977
+
2978
+ /* TODO this needs to be implemented.
2979
+
2980
+ CURLINFO_COOKIELIST
2981
+
2982
+ 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)
2983
+ */
2984
+
2985
+ /* TODO this needs to be implemented. Could probably support CONNECT_ONLY by having this
2986
+ * return an open Socket or something.
2987
+ *
2988
+ CURLINFO_LASTSOCKET
2989
+
2990
+ 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)
2991
+ */
2992
+
2993
+ /*
2994
+ * call-seq:
2995
+ * easy.ftp_entry_path => "C:\ftp\root\" or nil
2996
+ *
2997
+ * Retrieve the path of the entry path. That is the initial path libcurl ended
2998
+ * up in when logging on to the remote FTP server. This returns +nil+ if
2999
+ * something is wrong.
3000
+ *
3001
+ * (requires libcurl 7.15.4 or higher, otherwise +nil+ is always returned).
3002
+ */
3003
+ static VALUE ruby_curl_easy_ftp_entry_path_get(VALUE self) {
3004
+ #ifdef HAVE_CURLINFO_FTP_ENTRY_PATH
3005
+ ruby_curl_easy *rbce;
3006
+ char* path = NULL;
3007
+
3008
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3009
+ curl_easy_getinfo(rbce->curl, CURLINFO_FTP_ENTRY_PATH, &path);
3010
+
3011
+ if (path && path[0]) { // curl returns NULL or empty string if none
3012
+ return rb_str_new2(path);
3013
+ } else {
3014
+ return Qnil;
3015
+ }
3016
+ #else
3017
+ rb_warn("Installed libcurl is too old to support num_connects");
3018
+ return Qnil;
3019
+ #endif
3020
+ }
3021
+
3022
+ /*
3023
+ * call-seq:
3024
+ * easy.multi => "#<Curl::Multi>"
3025
+ */
3026
+ static VALUE ruby_curl_easy_multi_get(VALUE self) {
3027
+ ruby_curl_easy *rbce;
3028
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3029
+ return rbce->multi;
3030
+ }
3031
+
3032
+ /*
3033
+ * call-seq:
3034
+ * easy.multi=multi => "#<Curl::Multi>"
3035
+ */
3036
+ static VALUE ruby_curl_easy_multi_set(VALUE self, VALUE multi) {
3037
+ ruby_curl_easy *rbce;
3038
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3039
+ rbce->multi = multi;
3040
+ return rbce->multi;
3041
+ }
3042
+
3043
+ /*
3044
+ * call-seq:
3045
+ * easy.last_result => 0
3046
+ */
3047
+ static VALUE ruby_curl_easy_last_result(VALUE self) {
3048
+ ruby_curl_easy *rbce;
3049
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3050
+ return INT2FIX(rbce->last_result);
3051
+ }
3052
+
3053
+ /*
3054
+ * call-seq:
3055
+ * easy.setopt Fixnum, value => value
3056
+ *
3057
+ * Iniital access to libcurl curl_easy_setopt
3058
+ */
3059
+ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3060
+ ruby_curl_easy *rbce;
3061
+ long option = FIX2LONG(opt);
3062
+
3063
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3064
+
3065
+ switch (option) {
3066
+ /* BEHAVIOR OPTIONS */
3067
+ case CURLOPT_VERBOSE: {
3068
+ VALUE verbose = val;
3069
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, verbose);
3070
+ } break;
3071
+ case CURLOPT_FOLLOWLOCATION: {
3072
+ VALUE follow_location = val;
3073
+ CURB_BOOLEAN_SETTER(ruby_curl_easy, follow_location);
3074
+ } break;
3075
+ /* TODO: CALLBACK OPTIONS */
3076
+ /* TODO: ERROR OPTIONS */
3077
+ /* NETWORK OPTIONS */
3078
+ case CURLOPT_URL: {
3079
+ VALUE url = val;
3080
+ CURB_OBJECT_HSETTER(ruby_curl_easy, url);
3081
+ } break;
3082
+ case CURLOPT_CUSTOMREQUEST:
3083
+ curl_easy_setopt(rbce->curl, CURLOPT_CUSTOMREQUEST, NIL_P(val) ? NULL : StringValueCStr(val));
3084
+ break;
3085
+ case CURLOPT_HTTP_VERSION:
3086
+ curl_easy_setopt(rbce->curl, CURLOPT_HTTP_VERSION, FIX2INT(val));
3087
+ break;
3088
+ case CURLOPT_PROXY: {
3089
+ VALUE proxy_url = val;
3090
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxy_url);
3091
+ } break;
3092
+ case CURLOPT_INTERFACE: {
3093
+ VALUE interface_hm = val;
3094
+ CURB_OBJECT_HSETTER(ruby_curl_easy, interface_hm);
3095
+ } break;
3096
+ case CURLOPT_HEADER:
3097
+ case CURLOPT_NOPROGRESS:
3098
+ case CURLOPT_NOSIGNAL:
3099
+ case CURLOPT_HTTPGET:
3100
+ case CURLOPT_NOBODY: {
3101
+ int type = rb_type(val);
3102
+ VALUE value;
3103
+ if (type == T_TRUE) {
3104
+ value = rb_int_new(1);
3105
+ } else if (type == T_FALSE) {
3106
+ value = rb_int_new(0);
3107
+ } else {
3108
+ value = rb_funcall(val, rb_intern("to_i"), 0);
3109
+ }
3110
+ curl_easy_setopt(rbce->curl, option, FIX2INT(value));
3111
+ } break;
3112
+ case CURLOPT_USERPWD: {
3113
+ VALUE userpwd = val;
3114
+ CURB_OBJECT_HSETTER(ruby_curl_easy, userpwd);
3115
+ } break;
3116
+ case CURLOPT_PROXYUSERPWD: {
3117
+ VALUE proxypwd = val;
3118
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxypwd);
3119
+ } break;
3120
+ case CURLOPT_COOKIE: {
3121
+ VALUE cookies = val;
3122
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookies);
3123
+ } break;
3124
+ case CURLOPT_COOKIEFILE: {
3125
+ VALUE cookiefile = val;
3126
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiefile);
3127
+ } break;
3128
+ case CURLOPT_COOKIEJAR: {
3129
+ VALUE cookiejar = val;
3130
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiejar);
3131
+ } break;
3132
+ case CURLOPT_RESUME_FROM: {
3133
+ curl_easy_setopt(rbce->curl, CURLOPT_RESUME_FROM, FIX2LONG(val));
3134
+ } break;
3135
+ case CURLOPT_FAILONERROR: {
3136
+ curl_easy_setopt(rbce->curl, CURLOPT_FAILONERROR, FIX2LONG(val));
3137
+ } break;
3138
+ default:
3139
+ break;
3140
+ }
3141
+
3142
+ return val;
3143
+ }
3144
+
3145
+ /*
3146
+ * call-seq:
3147
+ * easy.getinfo Fixnum => value
3148
+ *
3149
+ * Iniital access to libcurl curl_easy_getinfo, remember getinfo doesn't return the same values as setopt
3150
+ */
3151
+ static VALUE ruby_curl_easy_get_opt(VALUE self, VALUE opt) {
3152
+ return Qnil;
3153
+ }
3154
+
3155
+ /*
3156
+ * call-seq:
3157
+ * easy.inspect => "#<Curl::Easy http://google.com/>"
3158
+ */
3159
+ static VALUE ruby_curl_easy_inspect(VALUE self) {
3160
+ char buf[64];
3161
+ ruby_curl_easy *rbce;
3162
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3163
+ /* if we don't have a url set... we'll crash... */
3164
+ if( !rb_easy_nil("url") && rb_easy_type_check("url", T_STRING)) {
3165
+ VALUE url = rb_easy_get("url");
3166
+ size_t len = 13+((RSTRING_LEN(url) > 50) ? 50 : RSTRING_LEN(url));
3167
+ /* "#<Net::HTTP http://www.google.com/:80 open=false>" */
3168
+ memcpy(buf,"#<Curl::Easy ", 13);
3169
+ memcpy(buf+13,StringValueCStr(url), (len - 13));
3170
+ buf[len++] = '>';
3171
+ return rb_str_new(buf,len);
3172
+ }
3173
+ return rb_str_new2("#<Curl::Easy>");
3174
+ }
3175
+
3176
+
3177
+ /* ================== ESCAPING FUNCS ==============*/
3178
+
3179
+ /*
3180
+ * call-seq:
3181
+ * easy.escape("some text") => "some%20text"
3182
+ *
3183
+ * Convert the given input string to a URL encoded string and return
3184
+ * the result. All input characters that are not a-z, A-Z or 0-9 are
3185
+ * converted to their "URL escaped" version (%NN where NN is a
3186
+ * two-digit hexadecimal number).
3187
+ */
3188
+ static VALUE ruby_curl_easy_escape(VALUE self, VALUE svalue) {
3189
+ ruby_curl_easy *rbce;
3190
+ char *result;
3191
+ VALUE rresult;
3192
+ VALUE str = svalue;
3193
+
3194
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3195
+
3196
+ /* NOTE: make sure the value is a string, if not call to_s */
3197
+ if( rb_type(str) != T_STRING ) { str = rb_funcall(str,rb_intern("to_s"),0); }
3198
+
3199
+ #if (LIBCURL_VERSION_NUM >= 0x070f04)
3200
+ result = (char*)curl_easy_escape(rbce->curl, StringValuePtr(str), (int)RSTRING_LEN(str));
3201
+ #else
3202
+ result = (char*)curl_escape(StringValuePtr(str), (int)RSTRING_LEN(str));
3203
+ #endif
3204
+
3205
+ rresult = rb_str_new2(result);
3206
+ curl_free(result);
3207
+
3208
+ return rresult;
3209
+ }
3210
+
3211
+ /*
3212
+ * call-seq:
3213
+ * easy.unescape("some%20text") => "some text"
3214
+ *
3215
+ * Convert the given URL encoded input string to a "plain string" and return
3216
+ * the result. All input characters that are URL encoded (%XX where XX is a
3217
+ * two-digit hexadecimal number) are converted to their binary versions.
3218
+ */
3219
+ static VALUE ruby_curl_easy_unescape(VALUE self, VALUE str) {
3220
+ ruby_curl_easy *rbce;
3221
+ int rlen;
3222
+ char *result;
3223
+ VALUE rresult;
3224
+
3225
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
3226
+
3227
+ #if (LIBCURL_VERSION_NUM >= 0x070f04)
3228
+ result = (char*)curl_easy_unescape(rbce->curl, StringValuePtr(str), (int)RSTRING_LEN(str), &rlen);
3229
+ #else
3230
+ result = (char*)curl_unescape(StringValuePtr(str), RSTRING_LEN(str));
3231
+ rlen = strlen(result);
3232
+ #endif
3233
+
3234
+ rresult = rb_str_new(result, rlen);
3235
+ curl_free(result);
3236
+
3237
+ return rresult;
3238
+ }
3239
+
3240
+
3241
+ /* ================= CLASS METHODS ==================*/
3242
+
3243
+ /*
3244
+ * call-seq:
3245
+ * Curl::Easy.error(code) => String
3246
+ *
3247
+ * translate an internal libcurl error to ruby error class
3248
+ */
3249
+ static VALUE ruby_curl_easy_error_message(VALUE klass, VALUE code) {
3250
+ return rb_curl_easy_error(FIX2INT(code));
3251
+ }
3252
+
3253
+ /* =================== INIT LIB =====================*/
3254
+ void init_curb_easy() {
3255
+ idCall = rb_intern("call");
3256
+ idJoin = rb_intern("join");
3257
+ idFlatten = rb_intern("flatten");
3258
+
3259
+ rbstrAmp = rb_str_new2("&");
3260
+ rb_global_variable(&rbstrAmp);
3261
+
3262
+ cCurlEasy = rb_define_class_under(mCurl, "Easy", rb_cObject);
3263
+
3264
+ /* Class methods */
3265
+ rb_define_singleton_method(cCurlEasy, "new", ruby_curl_easy_new, -1);
3266
+ rb_define_singleton_method(cCurlEasy, "error", ruby_curl_easy_error_message, 1);
3267
+
3268
+ /* Attributes for config next perform */
3269
+ rb_define_method(cCurlEasy, "url", ruby_curl_easy_url_get, 0);
3270
+ rb_define_method(cCurlEasy, "proxy_url", ruby_curl_easy_proxy_url_get, 0);
3271
+ rb_define_method(cCurlEasy, "headers=", ruby_curl_easy_headers_set, 1);
3272
+ rb_define_method(cCurlEasy, "headers", ruby_curl_easy_headers_get, 0);
3273
+ rb_define_method(cCurlEasy, "interface", ruby_curl_easy_interface_get, 0);
3274
+ rb_define_method(cCurlEasy, "userpwd", ruby_curl_easy_userpwd_get, 0);
3275
+ rb_define_method(cCurlEasy, "proxypwd", ruby_curl_easy_proxypwd_get, 0);
3276
+ rb_define_method(cCurlEasy, "cookies", ruby_curl_easy_cookies_get, 0);
3277
+ rb_define_method(cCurlEasy, "cookiefile", ruby_curl_easy_cookiefile_get, 0);
3278
+ rb_define_method(cCurlEasy, "cookiejar", ruby_curl_easy_cookiejar_get, 0);
3279
+ rb_define_method(cCurlEasy, "cert=", ruby_curl_easy_cert_set, 1);
3280
+ rb_define_method(cCurlEasy, "cert", ruby_curl_easy_cert_get, 0);
3281
+ rb_define_method(cCurlEasy, "cert_key=", ruby_curl_easy_cert_key_set, 1);
3282
+ rb_define_method(cCurlEasy, "cert_key", ruby_curl_easy_cert_key_get, 0);
3283
+ rb_define_method(cCurlEasy, "cacert=", ruby_curl_easy_cacert_set, 1);
3284
+ rb_define_method(cCurlEasy, "cacert", ruby_curl_easy_cacert_get, 0);
3285
+ rb_define_method(cCurlEasy, "certpassword=", ruby_curl_easy_certpassword_set, 1);
3286
+ rb_define_method(cCurlEasy, "certtype=", ruby_curl_easy_certtype_set, 1);
3287
+ rb_define_method(cCurlEasy, "certtype", ruby_curl_easy_certtype_get, 0);
3288
+ rb_define_method(cCurlEasy, "encoding=", ruby_curl_easy_encoding_set, 1);
3289
+ rb_define_method(cCurlEasy, "encoding", ruby_curl_easy_encoding_get, 0);
3290
+ rb_define_method(cCurlEasy, "useragent=", ruby_curl_easy_useragent_set, 1);
3291
+ rb_define_method(cCurlEasy, "useragent", ruby_curl_easy_useragent_get, 0);
3292
+ rb_define_method(cCurlEasy, "multipart_post_body=", ruby_curl_easy_multipart_post_body_set, 1);
3293
+ rb_define_method(cCurlEasy, "post_body=", ruby_curl_easy_post_body_set, 1);
3294
+ rb_define_method(cCurlEasy, "post_body", ruby_curl_easy_post_body_get, 0);
3295
+ rb_define_method(cCurlEasy, "put_data=", ruby_curl_easy_put_data_set, 1);
3296
+ rb_define_method(cCurlEasy, "ftp_commands=", ruby_curl_easy_ftp_commands_set, 1);
3297
+ rb_define_method(cCurlEasy, "ftp_commands", ruby_curl_easy_ftp_commands_get, 0);
3298
+
3299
+ rb_define_method(cCurlEasy, "local_port=", ruby_curl_easy_local_port_set, 1);
3300
+ rb_define_method(cCurlEasy, "local_port", ruby_curl_easy_local_port_get, 0);
3301
+ rb_define_method(cCurlEasy, "local_port_range=", ruby_curl_easy_local_port_range_set, 1);
3302
+ rb_define_method(cCurlEasy, "local_port_range", ruby_curl_easy_local_port_range_get, 0);
3303
+ rb_define_method(cCurlEasy, "proxy_port=", ruby_curl_easy_proxy_port_set, 1);
3304
+ rb_define_method(cCurlEasy, "proxy_port", ruby_curl_easy_proxy_port_get, 0);
3305
+ rb_define_method(cCurlEasy, "proxy_type=", ruby_curl_easy_proxy_type_set, 1);
3306
+ rb_define_method(cCurlEasy, "proxy_type", ruby_curl_easy_proxy_type_get, 0);
3307
+ rb_define_method(cCurlEasy, "http_auth_types=", ruby_curl_easy_http_auth_types_set, -1);
3308
+ rb_define_method(cCurlEasy, "http_auth_types", ruby_curl_easy_http_auth_types_get, 0);
3309
+ rb_define_method(cCurlEasy, "proxy_auth_types=", ruby_curl_easy_proxy_auth_types_set, 1);
3310
+ rb_define_method(cCurlEasy, "proxy_auth_types", ruby_curl_easy_proxy_auth_types_get, 0);
3311
+ rb_define_method(cCurlEasy, "max_redirects=", ruby_curl_easy_max_redirects_set, 1);
3312
+ rb_define_method(cCurlEasy, "max_redirects", ruby_curl_easy_max_redirects_get, 0);
3313
+ rb_define_method(cCurlEasy, "timeout=", ruby_curl_easy_timeout_set, 1);
3314
+ rb_define_method(cCurlEasy, "timeout", ruby_curl_easy_timeout_get, 0);
3315
+ rb_define_method(cCurlEasy, "connect_timeout=", ruby_curl_easy_connect_timeout_set, 1);
3316
+ rb_define_method(cCurlEasy, "connect_timeout", ruby_curl_easy_connect_timeout_get, 0);
3317
+ rb_define_method(cCurlEasy, "dns_cache_timeout=", ruby_curl_easy_dns_cache_timeout_set, 1);
3318
+ rb_define_method(cCurlEasy, "dns_cache_timeout", ruby_curl_easy_dns_cache_timeout_get, 0);
3319
+ rb_define_method(cCurlEasy, "ftp_response_timeout=", ruby_curl_easy_ftp_response_timeout_set, 1);
3320
+ rb_define_method(cCurlEasy, "ftp_response_timeout", ruby_curl_easy_ftp_response_timeout_get, 0);
3321
+ rb_define_method(cCurlEasy, "low_speed_limit=", ruby_curl_easy_low_speed_limit_set, 1);
3322
+ rb_define_method(cCurlEasy, "low_speed_limit", ruby_curl_easy_low_speed_limit_get, 0);
3323
+ rb_define_method(cCurlEasy, "low_speed_time=", ruby_curl_easy_low_speed_time_set, 1);
3324
+ rb_define_method(cCurlEasy, "low_speed_time", ruby_curl_easy_low_speed_time_get, 0);
3325
+ rb_define_method(cCurlEasy, "ssl_version=", ruby_curl_easy_ssl_version_set, 1);
3326
+ rb_define_method(cCurlEasy, "ssl_version", ruby_curl_easy_ssl_version_get, 0);
3327
+ rb_define_method(cCurlEasy, "use_ssl=", ruby_curl_easy_use_ssl_set, 1);
3328
+ rb_define_method(cCurlEasy, "use_ssl", ruby_curl_easy_use_ssl_get, 0);
3329
+ rb_define_method(cCurlEasy, "ftp_filemethod=", ruby_curl_easy_ftp_filemethod_set, 1);
3330
+ rb_define_method(cCurlEasy, "ftp_filemethod", ruby_curl_easy_ftp_filemethod_get, 0);
3331
+
3332
+ rb_define_method(cCurlEasy, "username=", ruby_curl_easy_username_set, 1);
3333
+ rb_define_method(cCurlEasy, "username", ruby_curl_easy_username_get, 0);
3334
+ rb_define_method(cCurlEasy, "password=", ruby_curl_easy_password_set, 1);
3335
+ rb_define_method(cCurlEasy, "password", ruby_curl_easy_password_get, 0);
3336
+
3337
+ rb_define_method(cCurlEasy, "proxy_tunnel=", ruby_curl_easy_proxy_tunnel_set, 1);
3338
+ rb_define_method(cCurlEasy, "proxy_tunnel?", ruby_curl_easy_proxy_tunnel_q, 0);
3339
+ rb_define_method(cCurlEasy, "fetch_file_time=", ruby_curl_easy_fetch_file_time_set, 1);
3340
+ rb_define_method(cCurlEasy, "fetch_file_time?", ruby_curl_easy_fetch_file_time_q, 0);
3341
+ rb_define_method(cCurlEasy, "ssl_verify_peer=", ruby_curl_easy_ssl_verify_peer_set, 1);
3342
+ rb_define_method(cCurlEasy, "ssl_verify_peer?", ruby_curl_easy_ssl_verify_peer_q, 0);
3343
+ rb_define_method(cCurlEasy, "ssl_verify_host_integer=", ruby_curl_easy_ssl_verify_host_set, 1);
3344
+ rb_define_method(cCurlEasy, "ssl_verify_host", ruby_curl_easy_ssl_verify_host_get, 0);
3345
+ rb_define_method(cCurlEasy, "header_in_body=", ruby_curl_easy_header_in_body_set, 1);
3346
+ rb_define_method(cCurlEasy, "header_in_body?", ruby_curl_easy_header_in_body_q, 0);
3347
+ rb_define_method(cCurlEasy, "use_netrc=", ruby_curl_easy_use_netrc_set, 1);
3348
+ rb_define_method(cCurlEasy, "use_netrc?", ruby_curl_easy_use_netrc_q, 0);
3349
+ rb_define_method(cCurlEasy, "follow_location?", ruby_curl_easy_follow_location_q, 0);
3350
+ rb_define_method(cCurlEasy, "autoreferer=", ruby_curl_easy_autoreferer_set, 1);
3351
+ rb_define_method(cCurlEasy, "unrestricted_auth=", ruby_curl_easy_unrestricted_auth_set, 1);
3352
+ rb_define_method(cCurlEasy, "unrestricted_auth?", ruby_curl_easy_unrestricted_auth_q, 0);
3353
+ rb_define_method(cCurlEasy, "verbose=", ruby_curl_easy_verbose_set, 1);
3354
+ rb_define_method(cCurlEasy, "verbose?", ruby_curl_easy_verbose_q, 0);
3355
+ rb_define_method(cCurlEasy, "multipart_form_post=", ruby_curl_easy_multipart_form_post_set, 1);
3356
+ rb_define_method(cCurlEasy, "multipart_form_post?", ruby_curl_easy_multipart_form_post_q, 0);
3357
+ rb_define_method(cCurlEasy, "enable_cookies=", ruby_curl_easy_enable_cookies_set, 1);
3358
+ rb_define_method(cCurlEasy, "enable_cookies?", ruby_curl_easy_enable_cookies_q, 0);
3359
+ rb_define_method(cCurlEasy, "ignore_content_length=", ruby_curl_easy_ignore_content_length_set, 1);
3360
+ rb_define_method(cCurlEasy, "ignore_content_length?", ruby_curl_easy_ignore_content_length_q, 0);
3361
+ rb_define_method(cCurlEasy, "resolve_mode", ruby_curl_easy_resolve_mode, 0);
3362
+ rb_define_method(cCurlEasy, "resolve_mode=", ruby_curl_easy_resolve_mode_set, 1);
3363
+
3364
+ rb_define_method(cCurlEasy, "on_body", ruby_curl_easy_on_body_set, -1);
3365
+ rb_define_method(cCurlEasy, "on_header", ruby_curl_easy_on_header_set, -1);
3366
+ rb_define_method(cCurlEasy, "on_progress", ruby_curl_easy_on_progress_set, -1);
3367
+ rb_define_method(cCurlEasy, "on_debug", ruby_curl_easy_on_debug_set, -1);
3368
+ rb_define_method(cCurlEasy, "on_success", ruby_curl_easy_on_success_set, -1);
3369
+ rb_define_method(cCurlEasy, "on_failure", ruby_curl_easy_on_failure_set, -1);
3370
+ rb_define_method(cCurlEasy, "on_missing", ruby_curl_easy_on_missing_set, -1);
3371
+ rb_define_method(cCurlEasy, "on_redirect", ruby_curl_easy_on_redirect_set, -1);
3372
+ rb_define_method(cCurlEasy, "on_complete", ruby_curl_easy_on_complete_set, -1);
3373
+ rb_define_method(cCurlEasy, "callback", ruby_curl_easy_optional_callback_set, -1);
3374
+
3375
+ rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
3376
+ rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
3377
+ rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
3378
+
3379
+ /* Post-perform info methods */
3380
+ rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
3381
+ rb_define_method(cCurlEasy, "header_str", ruby_curl_easy_header_str_get, 0);
3382
+
3383
+ rb_define_method(cCurlEasy, "last_effective_url", ruby_curl_easy_last_effective_url_get, 0);
3384
+ rb_define_method(cCurlEasy, "response_code", ruby_curl_easy_response_code_get, 0);
3385
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
3386
+ rb_define_method(cCurlEasy, "primary_ip", ruby_curl_easy_primary_ip_get, 0);
3387
+ #endif
3388
+ rb_define_method(cCurlEasy, "http_connect_code", ruby_curl_easy_http_connect_code_get, 0);
3389
+ rb_define_method(cCurlEasy, "file_time", ruby_curl_easy_file_time_get, 0);
3390
+ rb_define_method(cCurlEasy, "total_time", ruby_curl_easy_total_time_get, 0);
3391
+ rb_define_method(cCurlEasy, "name_lookup_time", ruby_curl_easy_name_lookup_time_get, 0);
3392
+ rb_define_method(cCurlEasy, "connect_time", ruby_curl_easy_connect_time_get, 0);
3393
+ rb_define_method(cCurlEasy, "pre_transfer_time", ruby_curl_easy_pre_transfer_time_get, 0);
3394
+ rb_define_method(cCurlEasy, "start_transfer_time", ruby_curl_easy_start_transfer_time_get, 0);
3395
+ rb_define_method(cCurlEasy, "redirect_time", ruby_curl_easy_redirect_time_get, 0);
3396
+ rb_define_method(cCurlEasy, "redirect_count", ruby_curl_easy_redirect_count_get, 0);
3397
+ rb_define_method(cCurlEasy, "redirect_url", ruby_curl_easy_redirect_url_get, 0);
3398
+ rb_define_method(cCurlEasy, "downloaded_bytes", ruby_curl_easy_downloaded_bytes_get, 0);
3399
+ rb_define_method(cCurlEasy, "uploaded_bytes", ruby_curl_easy_uploaded_bytes_get, 0);
3400
+ rb_define_method(cCurlEasy, "download_speed", ruby_curl_easy_download_speed_get, 0);
3401
+ rb_define_method(cCurlEasy, "upload_speed", ruby_curl_easy_upload_speed_get, 0);
3402
+ rb_define_method(cCurlEasy, "header_size", ruby_curl_easy_header_size_get, 0);
3403
+ rb_define_method(cCurlEasy, "request_size", ruby_curl_easy_request_size_get, 0);
3404
+ rb_define_method(cCurlEasy, "ssl_verify_result", ruby_curl_easy_ssl_verify_result_get, 0);
3405
+ rb_define_method(cCurlEasy, "downloaded_content_length", ruby_curl_easy_downloaded_content_length_get, 0);
3406
+ rb_define_method(cCurlEasy, "uploaded_content_length", ruby_curl_easy_uploaded_content_length_get, 0);
3407
+ rb_define_method(cCurlEasy, "content_type", ruby_curl_easy_content_type_get, 0);
3408
+ rb_define_method(cCurlEasy, "os_errno", ruby_curl_easy_os_errno_get, 0);
3409
+ rb_define_method(cCurlEasy, "num_connects", ruby_curl_easy_num_connects_get, 0);
3410
+ rb_define_method(cCurlEasy, "ftp_entry_path", ruby_curl_easy_ftp_entry_path_get, 0);
3411
+
3412
+ rb_define_method(cCurlEasy, "close", ruby_curl_easy_close, 0);
3413
+ rb_define_method(cCurlEasy, "reset", ruby_curl_easy_reset, 0);
3414
+
3415
+ /* Curl utils */
3416
+ rb_define_method(cCurlEasy, "escape", ruby_curl_easy_escape, 1);
3417
+ rb_define_method(cCurlEasy, "unescape", ruby_curl_easy_unescape, 1);
3418
+
3419
+ /* Runtime support */
3420
+ rb_define_method(cCurlEasy, "clone", ruby_curl_easy_clone, 0);
3421
+ rb_define_alias(cCurlEasy, "dup", "clone");
3422
+ rb_define_method(cCurlEasy, "inspect", ruby_curl_easy_inspect, 0);
3423
+
3424
+ rb_define_method(cCurlEasy, "multi", ruby_curl_easy_multi_get, 0);
3425
+ rb_define_method(cCurlEasy, "multi=", ruby_curl_easy_multi_set, 1);
3426
+ rb_define_method(cCurlEasy, "last_result", ruby_curl_easy_last_result, 0);
3427
+
3428
+ rb_define_method(cCurlEasy, "setopt", ruby_curl_easy_set_opt, 2);
3429
+ rb_define_method(cCurlEasy, "getinfo", ruby_curl_easy_get_opt, 1);
3430
+ }