curb 0.5.8.0-x86-linux → 0.7.7-x86-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of curb might be problematic. Click here for more details.

data/README CHANGED
@@ -144,12 +144,13 @@ documentation with:
144
144
  c = Curl::Easy.new(url) do|curl|
145
145
  curl.follow_location = true
146
146
  curl.on_body{|data| responses[url] << data; data.size }
147
+ curl.on_success {|easy| puts "success, add more easy handles" }
147
148
  end
148
149
  m.add(c)
149
150
  end
150
151
 
151
152
  m.perform do
152
- puts "idling... can do some work here, including add new requests"
153
+ puts "idling... can do some work here"
153
154
  end
154
155
 
155
156
  requests.each do|url|
data/Rakefile CHANGED
@@ -100,7 +100,7 @@ Rake::TestTask.new(:bugtests) do |t|
100
100
  t.test_files = FileList['tests/bug_*.rb']
101
101
  t.verbose = false
102
102
  end
103
-
103
+
104
104
  #Rake::TestTask.new(:funtests) do |t|
105
105
  # t.test_files = FileList['test/func_*.rb']
106
106
  #t.warning = true
@@ -110,6 +110,25 @@ end
110
110
  task :unittests => :compile
111
111
  task :bugtests => :compile
112
112
 
113
+ def has_gem?(file,name)
114
+ begin
115
+ require file
116
+ has_http_persistent = true
117
+ rescue LoadError => e
118
+ puts "Skipping #{name}"
119
+ end
120
+ end
121
+
122
+ desc "Benchmark curl against http://127.0.0.1/zeros-2k - will fail if /zeros-2k or 127.0.0.1 are missing"
123
+ task :bench do
124
+ sh "ruby bench/curb_easy.rb"
125
+ sh "ruby bench/curb_multi.rb"
126
+ sh "ruby bench/nethttp_test.rb" if has_gem?("net/http/persistent","net-http-persistent")
127
+ sh "ruby bench/patron_test.rb" if has_gem?("patron","patron")
128
+ sh "ruby bench/typhoeus_test.rb" if has_gem?("typhoeus","typhoeus")
129
+ sh "ruby bench/typhoeus_hydra_test.rb" if has_gem?("typhoeus","typhoeus")
130
+ end
131
+
113
132
  # RDoc Tasks ---------------------------------------------------------
114
133
  desc "Create the RDOC documentation"
115
134
  task :doc do
data/ext/curb.c CHANGED
@@ -255,6 +255,10 @@ void Init_curb_core() {
255
255
  /* Passed to on_debug handler to indicate that the data is protocol data sent to the peer. */
256
256
  rb_define_const(mCurl, "CURLINFO_DATA_OUT", INT2FIX(CURLINFO_DATA_OUT));
257
257
 
258
+ rb_define_const(mCurl, "CURL_MULTICWD", INT2FIX(CURLFTPMETHOD_MULTICWD));
259
+ rb_define_const(mCurl, "CURL_NOCWD", INT2FIX(CURLFTPMETHOD_NOCWD));
260
+ rb_define_const(mCurl, "CURL_SINGLECWD", INT2FIX(CURLFTPMETHOD_SINGLECWD));
261
+
258
262
  /* When passed to Curl::Easy#proxy_type , indicates that the proxy is an HTTP proxy. (libcurl >= 7.10) */
259
263
  #ifdef HAVE_CURLPROXY_HTTP
260
264
  rb_define_const(mCurl, "CURLPROXY_HTTP", INT2FIX(CURLPROXY_HTTP));
@@ -262,6 +266,28 @@ void Init_curb_core() {
262
266
  rb_define_const(mCurl, "CURLPROXY_HTTP", INT2FIX(-1));
263
267
  #endif
264
268
 
269
+ #ifdef CURL_VERSION_SSL
270
+ rb_define_const(mCurl, "CURL_SSLVERSION_DEFAULT", INT2FIX(CURL_SSLVERSION_DEFAULT));
271
+ rb_define_const(mCurl, "CURL_SSLVERSION_TLSv1", INT2FIX(CURL_SSLVERSION_TLSv1));
272
+ rb_define_const(mCurl, "CURL_SSLVERSION_SSLv2", INT2FIX(CURL_SSLVERSION_SSLv2));
273
+ rb_define_const(mCurl, "CURL_SSLVERSION_SSLv3", INT2FIX(CURL_SSLVERSION_SSLv3));
274
+
275
+ rb_define_const(mCurl, "CURL_USESSL_CONTROL", INT2FIX(CURB_FTPSSL_CONTROL));
276
+ rb_define_const(mCurl, "CURL_USESSL_NONE", INT2FIX(CURB_FTPSSL_NONE));
277
+ rb_define_const(mCurl, "CURL_USESSL_TRY", INT2FIX(CURB_FTPSSL_TRY));
278
+ rb_define_const(mCurl, "CURL_USESSL_ALL", INT2FIX(CURB_FTPSSL_ALL));
279
+ #else
280
+ rb_define_const(mCurl, "CURL_SSLVERSION_DEFAULT", INT2FIX(-1));
281
+ rb_define_const(mCurl, "CURL_SSLVERSION_TLSv1", INT2FIX(-1));
282
+ rb_define_const(mCurl, "CURL_SSLVERSION_SSLv2", INT2FIX(-1));
283
+ rb_define_const(mCurl, "CURL_SSLVERSION_SSLv3", INT2FIX(-1));
284
+
285
+ rb_define_const(mCurl, "CURL_USESSL_CONTROL", INT2FIX(-1));
286
+ rb_define_const(mCurl, "CURL_USESSL_NONE", INT2FIX(-1));
287
+ rb_define_const(mCurl, "CURL_USESSL_TRY", INT2FIX(-1));
288
+ rb_define_const(mCurl, "CURL_USESSL_ALL", INT2FIX(-1));
289
+ #endif
290
+
265
291
  /* When passed to Curl::Easy#proxy_type , indicates that the proxy is a SOCKS4 proxy. (libcurl >= 7.15.2) */
266
292
  #ifdef HAVE_CURLPROXY_SOCKS4
267
293
  rb_define_const(mCurl, "CURLPROXY_SOCKS4", INT2FIX(CURLPROXY_SOCKS4));
data/ext/curb.h CHANGED
@@ -20,11 +20,11 @@
20
20
  #include "curb_macros.h"
21
21
 
22
22
  // These should be managed from the Rake 'release' task.
23
- #define CURB_VERSION "0.5.8.0"
24
- #define CURB_VER_NUM 580
23
+ #define CURB_VERSION "0.7.7"
24
+ #define CURB_VER_NUM 707
25
25
  #define CURB_VER_MAJ 0
26
- #define CURB_VER_MIN 5
27
- #define CURB_VER_MIC 8
26
+ #define CURB_VER_MIN 7
27
+ #define CURB_VER_MIC 7
28
28
  #define CURB_VER_PATCH 0
29
29
 
30
30
 
@@ -37,11 +37,13 @@
37
37
  #define RSTRING_PTR(x) RSTRING(x)->ptr
38
38
  #endif
39
39
 
40
+ #ifndef RHASH_LEN
40
41
  #ifdef HAVE_RUBY19_HASH
41
42
  #define RHASH_LEN(hash) RHASH(hash)->ntbl->num_entries
42
43
  #else
43
44
  #define RHASH_LEN(hash) RHASH(hash)->tbl->num_entries
44
45
  #endif
46
+ #endif
45
47
 
46
48
  extern VALUE mCurl;
47
49
 
data/ext/curb.o CHANGED
Binary file
Binary file
@@ -42,8 +42,9 @@ static size_t read_data_handler(void *ptr,
42
42
  size_t size,
43
43
  size_t nmemb,
44
44
  ruby_curl_easy *rbce) {
45
+ VALUE upload = rb_easy_get("upload");
45
46
  size_t read_bytes = (size*nmemb);
46
- VALUE stream = ruby_curl_upload_stream_get(rbce->upload);
47
+ VALUE stream = ruby_curl_upload_stream_get(upload);
47
48
 
48
49
  if (rb_respond_to(stream, rb_intern("read"))) {//if (rb_respond_to(stream, rb_intern("to_s"))) {
49
50
  /* copy read_bytes from stream into ptr */
@@ -62,7 +63,7 @@ static size_t read_data_handler(void *ptr,
62
63
  size_t len;
63
64
  size_t remaining;
64
65
  char *str_ptr;
65
- Data_Get_Struct(rbce->upload, ruby_curl_upload, rbcu);
66
+ Data_Get_Struct(upload, ruby_curl_upload, rbcu);
66
67
  str = rb_funcall(stream, rb_intern("to_s"), 0);
67
68
  len = RSTRING_LEN(str);
68
69
  remaining = len - rbcu->offset;
@@ -133,103 +134,37 @@ static int proc_debug_handler(CURL *curl,
133
134
 
134
135
  /* ================== MARK/FREE FUNC ==================*/
135
136
  void curl_easy_mark(ruby_curl_easy *rbce) {
136
- rb_gc_mark(rbce->url);
137
- rb_gc_mark(rbce->proxy_url);
138
- rb_gc_mark(rbce->body_proc);
139
- rb_gc_mark(rbce->body_data);
140
- rb_gc_mark(rbce->header_proc);
141
- rb_gc_mark(rbce->header_data);
142
- rb_gc_mark(rbce->progress_proc);
143
- rb_gc_mark(rbce->debug_proc);
144
- rb_gc_mark(rbce->interface_hm);
145
- rb_gc_mark(rbce->userpwd);
146
- rb_gc_mark(rbce->proxypwd);
147
- rb_gc_mark(rbce->headers);
148
- rb_gc_mark(rbce->cookies);
149
- rb_gc_mark(rbce->cookiefile);
150
- rb_gc_mark(rbce->cookiejar);
151
- rb_gc_mark(rbce->cert);
152
- rb_gc_mark(rbce->cacert);
153
- rb_gc_mark(rbce->certpassword);
154
- rb_gc_mark(rbce->certtype);
155
- rb_gc_mark(rbce->encoding);
156
- rb_gc_mark(rbce->useragent);
157
- rb_gc_mark(rbce->success_proc);
158
- rb_gc_mark(rbce->failure_proc);
159
- rb_gc_mark(rbce->complete_proc);
160
-
161
- rb_gc_mark(rbce->postdata_buffer);
162
- rb_gc_mark(rbce->bodybuf);
163
- rb_gc_mark(rbce->headerbuf);
164
-
165
- if( rbce->self != Qnil ) {
166
- rb_gc_mark(rbce->self);
167
- }
168
-
169
- if( rbce->upload != Qnil ) {
170
- rb_gc_mark(rbce->upload);
171
- }
137
+ rb_gc_mark(rbce->opts);
138
+ if (!NIL_P(rbce->multi)) { rb_gc_mark(rbce->multi); }
172
139
  }
173
140
 
174
- void curl_easy_free(ruby_curl_easy *rbce) {
141
+ static void ruby_curl_easy_free(ruby_curl_easy *rbce) {
175
142
  if (rbce->curl_headers) {
176
143
  curl_slist_free_all(rbce->curl_headers);
177
144
  }
178
- curl_easy_cleanup(rbce->curl);
179
- free(rbce);
180
- }
181
145
 
146
+ if (rbce->curl_ftp_commands) {
147
+ curl_slist_free_all(rbce->curl_ftp_commands);
148
+ }
182
149
 
183
- /* ================= ALLOC METHODS ====================*/
150
+ if (rbce->curl) {
151
+ curl_easy_cleanup(rbce->curl);
152
+ }
153
+ }
184
154
 
185
- /*
186
- * call-seq:
187
- * Curl::Easy.new => #&lt;Curl::Easy...&gt;
188
- * Curl::Easy.new(url = nil) => #&lt;Curl::Easy...&gt;
189
- * Curl::Easy.new(url = nil) { |self| ... } => #&lt;Curl::Easy...&gt;
190
- *
191
- * Create a new Curl::Easy instance, optionally supplying the URL.
192
- * The block form allows further configuration to be supplied before
193
- * the instance is returned.
194
- */
195
- static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
196
- CURLcode ecode;
197
- VALUE url, blk;
198
- VALUE new_curl;
199
- ruby_curl_easy *rbce;
155
+ void curl_easy_free(ruby_curl_easy *rbce) {
156
+ ruby_curl_easy_free(rbce);
157
+ free(rbce);
158
+ }
200
159
 
201
- rb_scan_args(argc, argv, "01&", &url, &blk);
202
160
 
203
- rbce = ALLOC(ruby_curl_easy);
161
+ /* ================= ALLOC METHODS ====================*/
204
162
 
205
- /* handler */
206
- rbce->curl = curl_easy_init();
163
+ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
164
+ rbce->opts = rb_hash_new();
207
165
 
208
- /* assoc objects */
209
- rbce->url = url;
210
- rbce->proxy_url = Qnil;
211
- rbce->body_data = Qnil;
212
- rbce->body_proc = Qnil;
213
- rbce->header_data = Qnil;
214
- rbce->header_proc = Qnil;
215
- rbce->progress_proc = Qnil;
216
- rbce->debug_proc = Qnil;
217
- rbce->interface_hm = Qnil;
218
- rbce->userpwd = Qnil;
219
- rbce->proxypwd = Qnil;
220
- rbce->headers = rb_hash_new();
221
- rbce->cookies = Qnil;
222
- rbce->cookiefile = Qnil;
223
- rbce->cookiejar = Qnil;
224
- rbce->cert = Qnil;
225
- rbce->cacert = Qnil;
226
- rbce->certpassword = Qnil;
227
- rbce->certtype = rb_str_new2("PEM");
228
- rbce->encoding = Qnil;
229
- rbce->useragent = Qnil;
230
- rbce->success_proc = Qnil;
231
- rbce->failure_proc = Qnil;
232
- rbce->complete_proc = Qnil;
166
+ rbce->curl_headers = NULL;
167
+ rbce->curl_ftp_commands = NULL;
233
168
 
234
169
  /* various-typed opts */
235
170
  rbce->local_port = 0;
@@ -243,6 +178,9 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
243
178
  rbce->connect_timeout = 0;
244
179
  rbce->dns_cache_timeout = 60;
245
180
  rbce->ftp_response_timeout = 0;
181
+ rbce->ssl_version = -1;
182
+ rbce->use_ssl = -1;
183
+ rbce->ftp_filemethod = -1;
246
184
 
247
185
  /* bool opts */
248
186
  rbce->proxy_tunnel = 0;
@@ -256,20 +194,44 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
256
194
  rbce->verbose = 0;
257
195
  rbce->multipart_form_post = 0;
258
196
  rbce->enable_cookies = 0;
197
+ }
259
198
 
260
- /* buffers */
261
- rbce->postdata_buffer = Qnil;
262
- rbce->bodybuf = Qnil;
263
- rbce->headerbuf = Qnil;
264
- rbce->curl_headers = NULL;
199
+ /*
200
+ * call-seq:
201
+ * Curl::Easy.new => #&lt;Curl::Easy...&gt;
202
+ * Curl::Easy.new(url = nil) => #&lt;Curl::Easy...&gt;
203
+ * Curl::Easy.new(url = nil) { |self| ... } => #&lt;Curl::Easy...&gt;
204
+ *
205
+ * Create a new Curl::Easy instance, optionally supplying the URL.
206
+ * The block form allows further configuration to be supplied before
207
+ * the instance is returned.
208
+ */
209
+ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
210
+ CURLcode ecode;
211
+ VALUE url, blk;
212
+ VALUE new_curl;
213
+ ruby_curl_easy *rbce;
265
214
 
266
- rbce->self = Qnil;
267
- rbce->upload = Qnil;
215
+ rb_scan_args(argc, argv, "01&", &url, &blk);
216
+
217
+ rbce = ALLOC(ruby_curl_easy);
218
+
219
+ /* handler */
220
+ rbce->curl = curl_easy_init();
221
+ if (!rbce->curl) {
222
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
223
+ }
224
+
225
+ rbce->multi = Qnil;
226
+
227
+ ruby_curl_easy_zero(rbce);
228
+
229
+ rb_easy_set("url", url);
268
230
 
269
231
  new_curl = Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
270
232
 
271
- /* set the rbce pointer to the curl handle */
272
- ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)rbce);
233
+ /* set the new_curl pointer to the curl handle */
234
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)new_curl);
273
235
  if (ecode != CURLE_OK) {
274
236
  raise_curl_easy_error_exception(ecode);
275
237
  }
@@ -298,10 +260,77 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
298
260
  memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
299
261
  newrbce->curl = curl_easy_duphandle(rbce->curl);
300
262
  newrbce->curl_headers = NULL;
263
+ newrbce->curl_ftp_commands = NULL;
301
264
 
302
265
  return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
303
266
  }
304
267
 
268
+ /*
269
+ * call-seq:
270
+ * easy.close => nil
271
+ *
272
+ * Close the Curl::Easy instance. Any open connections are closed
273
+ * The easy handle is reinitialized. If a previous multi handle was
274
+ * open it is set to nil and will be cleared after a GC.
275
+ */
276
+ static VALUE ruby_curl_easy_close(VALUE self) {
277
+ CURLcode ecode;
278
+ ruby_curl_easy *rbce;
279
+
280
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
281
+
282
+ ruby_curl_easy_free(rbce);
283
+
284
+ /* reinit the handle */
285
+ rbce->curl = curl_easy_init();
286
+ if (!rbce->curl) {
287
+ rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
288
+ }
289
+
290
+ rbce->multi = Qnil;
291
+
292
+ ruby_curl_easy_zero(rbce);
293
+
294
+ /* give the new curl handle a reference back to the ruby object */
295
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
296
+ if (ecode != CURLE_OK) {
297
+ raise_curl_easy_error_exception(ecode);
298
+ }
299
+
300
+ return Qnil;
301
+ }
302
+
303
+ /*
304
+ * call-seq:
305
+ * easy.reset => Hash
306
+ *
307
+ * Reset the Curl::Easy instance, clears out all settings.
308
+ *
309
+ * from http://curl.haxx.se/libcurl/c/curl_easy_reset.html
310
+ * 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).
311
+ * It does not change the following information kept in the handle: live connections, the Session ID cache, the DNS cache, the cookies and shares.
312
+ *
313
+ * The return value contains all settings stored.
314
+ */
315
+ static VALUE ruby_curl_easy_reset(VALUE self) {
316
+ CURLcode ecode;
317
+ ruby_curl_easy *rbce;
318
+ VALUE opts_dup;
319
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
320
+ opts_dup = rb_funcall(rbce->opts, rb_intern("dup"), 0);
321
+
322
+ curl_easy_reset(rbce->curl);
323
+ ruby_curl_easy_zero(rbce);
324
+
325
+ /* rest clobbers the private setting, so reset it to self */
326
+ ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
327
+ if (ecode != CURLE_OK) {
328
+ raise_curl_easy_error_exception(ecode);
329
+ }
330
+
331
+ return opts_dup;
332
+ }
333
+
305
334
 
306
335
  /* ================ OBJ ATTRIBUTES ==================*/
307
336
 
@@ -314,22 +343,22 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
314
343
  * the URL between calls to +perform+.
315
344
  */
316
345
  static VALUE ruby_curl_easy_url_set(VALUE self, VALUE url) {
317
- CURB_OBJECT_SETTER(ruby_curl_easy, url);
346
+ CURB_OBJECT_HSETTER(ruby_curl_easy, url);
318
347
  }
319
348
 
320
349
  /*
321
350
  * call-seq:
322
- * easy.url => "http://some.url/"
351
+ * easy.url => string
323
352
  *
324
353
  * Obtain the URL that will be used by subsequent calls to +perform+.
325
354
  */
326
355
  static VALUE ruby_curl_easy_url_get(VALUE self) {
327
- CURB_OBJECT_GETTER(ruby_curl_easy, url);
356
+ CURB_OBJECT_HGETTER(ruby_curl_easy, url);
328
357
  }
329
358
 
330
359
  /*
331
360
  * call-seq:
332
- * easy.proxy_url = "some.url" => "some.url"
361
+ * easy.proxy_url = string => string
333
362
  *
334
363
  * Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
335
364
  * The URL should specify the the host name or dotted IP address. To specify
@@ -353,23 +382,23 @@ static VALUE ruby_curl_easy_url_get(VALUE self) {
353
382
  * proxy_url, including protocol prefix (http://) and embedded user + password.
354
383
  */
355
384
  static VALUE ruby_curl_easy_proxy_url_set(VALUE self, VALUE proxy_url) {
356
- CURB_OBJECT_SETTER(ruby_curl_easy, proxy_url);
385
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxy_url);
357
386
  }
358
387
 
359
388
  /*
360
389
  * call-seq:
361
- * easy.proxy_url => "some.url"
390
+ * easy.proxy_url => string
362
391
  *
363
392
  * Obtain the HTTP Proxy URL that will be used by subsequent calls to +perform+.
364
393
  */
365
394
  static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
366
- CURB_OBJECT_GETTER(ruby_curl_easy, proxy_url);
395
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxy_url);
367
396
  }
368
397
 
369
398
  /*
370
399
  * call-seq:
371
- * easy.headers = "Header: val" => ["Header: val", ...]
372
- * easy.headers = {"Header" => "val" ..., "Header" => "val"} => ["Header: val", ...]
400
+ * easy.headers = "Header: val" => "Header: val"
401
+ * easy.headers = {"Header" => "val" ..., "Header" => "val"} => {"Header: val", ...}
373
402
  * easy.headers = ["Header: val" ..., "Header: val"] => ["Header: val", ...]
374
403
  *
375
404
  * Set custom HTTP headers for following requests. This can be used to add
@@ -389,113 +418,118 @@ static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
389
418
  * the perform step.
390
419
  */
391
420
  static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
392
- CURB_OBJECT_SETTER(ruby_curl_easy, headers);
421
+ CURB_OBJECT_HSETTER(ruby_curl_easy, headers);
393
422
  }
394
423
 
395
424
  /*
396
425
  * call-seq:
397
- * easy.headers => Hash, Array or Str
426
+ * easy.headers => Hash, Array or Str
398
427
  *
399
428
  * Obtain the custom HTTP headers for following requests.
400
429
  */
401
430
  static VALUE ruby_curl_easy_headers_get(VALUE self) {
402
- CURB_OBJECT_GETTER(ruby_curl_easy, headers);
431
+ ruby_curl_easy *rbce;
432
+ VALUE headers;
433
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
434
+ headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
435
+ if (headers == Qnil) { headers = rb_easy_set("headers", rb_hash_new()); }
436
+ return headers;
403
437
  }
404
438
 
405
439
  /*
406
440
  * call-seq:
407
- * easy.interface = "interface" => "interface"
441
+ * easy.interface = string => string
408
442
  *
409
443
  * Set the interface name to use as the outgoing network interface.
410
444
  * The name can be an interface name, an IP address or a host name.
411
445
  */
412
446
  static VALUE ruby_curl_easy_interface_set(VALUE self, VALUE interface_hm) {
413
- CURB_OBJECT_SETTER(ruby_curl_easy, interface_hm);
447
+ CURB_OBJECT_HSETTER(ruby_curl_easy, interface_hm);
414
448
  }
415
449
 
416
450
  /*
417
451
  * call-seq:
418
- * easy.interface => "interface"
452
+ * easy.interface => string
419
453
  *
420
454
  * Obtain the interface name that is used as the outgoing network interface.
421
455
  * The name can be an interface name, an IP address or a host name.
422
456
  */
423
457
  static VALUE ruby_curl_easy_interface_get(VALUE self) {
424
- CURB_OBJECT_GETTER(ruby_curl_easy, interface_hm);
458
+ CURB_OBJECT_HGETTER(ruby_curl_easy, interface_hm);
425
459
  }
426
460
 
427
461
  /*
428
462
  * call-seq:
429
- * easy.userpwd = "pwd string" => "pwd string"
463
+ * easy.userpwd = string => string
430
464
  *
431
465
  * Set the username/password string to use for subsequent calls to +perform+.
432
466
  * The supplied string should have the form "username:password"
433
467
  */
434
468
  static VALUE ruby_curl_easy_userpwd_set(VALUE self, VALUE userpwd) {
435
- CURB_OBJECT_SETTER(ruby_curl_easy, userpwd);
469
+ CURB_OBJECT_HSETTER(ruby_curl_easy, userpwd);
436
470
  }
437
471
 
438
472
  /*
439
473
  * call-seq:
440
- * easy.userpwd => "pwd string"
474
+ * easy.userpwd => string
441
475
  *
442
476
  * Obtain the username/password string that will be used for subsequent
443
477
  * calls to +perform+.
444
478
  */
445
479
  static VALUE ruby_curl_easy_userpwd_get(VALUE self) {
446
- CURB_OBJECT_GETTER(ruby_curl_easy, userpwd);
480
+ CURB_OBJECT_HGETTER(ruby_curl_easy, userpwd);
447
481
  }
448
482
 
449
483
  /*
450
484
  * call-seq:
451
- * easy.proxypwd = "pwd string" => "pwd string"
485
+ * easy.proxypwd = string => string
452
486
  *
453
487
  * Set the username/password string to use for proxy connection during
454
488
  * subsequent calls to +perform+. The supplied string should have the
455
489
  * form "username:password"
456
490
  */
457
491
  static VALUE ruby_curl_easy_proxypwd_set(VALUE self, VALUE proxypwd) {
458
- CURB_OBJECT_SETTER(ruby_curl_easy, proxypwd);
492
+ CURB_OBJECT_HSETTER(ruby_curl_easy, proxypwd);
459
493
  }
460
494
 
461
495
  /*
462
496
  * call-seq:
463
- * easy.proxypwd => "pwd string"
497
+ * easy.proxypwd => string
464
498
  *
465
499
  * Obtain the username/password string that will be used for proxy
466
500
  * connection during subsequent calls to +perform+. The supplied string
467
501
  * should have the form "username:password"
468
502
  */
469
503
  static VALUE ruby_curl_easy_proxypwd_get(VALUE self) {
470
- CURB_OBJECT_GETTER(ruby_curl_easy, proxypwd);
504
+ CURB_OBJECT_HGETTER(ruby_curl_easy, proxypwd);
471
505
  }
472
506
 
473
507
 
474
508
  /*
475
509
  * call-seq:
476
- * easy.cookies = "name1=content1; name2=content2;" => "pwd string"
510
+ * easy.cookies = "name1=content1; name2=content2;" => string
477
511
  *
478
512
  * Set cookies to be sent by this Curl::Easy instance. The format of the string should
479
513
  * be NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie should contain.
480
514
  * Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
481
515
  */
482
516
  static VALUE ruby_curl_easy_cookies_set(VALUE self, VALUE cookies) {
483
- CURB_OBJECT_SETTER(ruby_curl_easy, cookies);
517
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookies);
484
518
  }
485
519
 
486
520
  /*
487
521
  * call-seq:
488
- * easy.cookies => "name1=content1; name2=content2;"
522
+ * easy.cookies => "name1=content1; name2=content2;"
489
523
  *
490
524
  * Obtain the cookies for this Curl::Easy instance.
491
525
  */
492
526
  static VALUE ruby_curl_easy_cookies_get(VALUE self) {
493
- CURB_OBJECT_GETTER(ruby_curl_easy, cookies);
527
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookies);
494
528
  }
495
529
 
496
530
  /*
497
531
  * call-seq:
498
- * easy.cookiefile = "cookies.txt" => "pwd string"
532
+ * easy.cookiefile = string => string
499
533
  *
500
534
  * Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
501
535
  *
@@ -503,22 +537,22 @@ static VALUE ruby_curl_easy_cookies_get(VALUE self) {
503
537
  * engine, or this option will be ignored.
504
538
  */
505
539
  static VALUE ruby_curl_easy_cookiefile_set(VALUE self, VALUE cookiefile) {
506
- CURB_OBJECT_SETTER(ruby_curl_easy, cookiefile);
540
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiefile);
507
541
  }
508
542
 
509
543
  /*
510
544
  * call-seq:
511
- * easy.cookiefile => "cookies.txt"
545
+ * easy.cookiefile => string
512
546
  *
513
547
  * Obtain the cookiefile file for this Curl::Easy instance.
514
548
  */
515
549
  static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
516
- CURB_OBJECT_GETTER(ruby_curl_easy, cookiefile);
550
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiefile);
517
551
  }
518
552
 
519
553
  /*
520
554
  * call-seq:
521
- * easy.cookiejar = "cookiejar.file" => "pwd string"
555
+ * easy.cookiejar = string => string
522
556
  *
523
557
  * Set a cookiejar file to use for this Curl::Easy instance.
524
558
  * Cookies from the response will be written into this file.
@@ -527,71 +561,93 @@ static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
527
561
  * engine, or this option will be ignored.
528
562
  */
529
563
  static VALUE ruby_curl_easy_cookiejar_set(VALUE self, VALUE cookiejar) {
530
- CURB_OBJECT_SETTER(ruby_curl_easy, cookiejar);
564
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cookiejar);
531
565
  }
532
566
 
533
567
  /*
534
568
  * call-seq:
535
- * easy.cookiejar => "cookiejar.file"
569
+ * easy.cookiejar => string
536
570
  *
537
571
  * Obtain the cookiejar file to use for this Curl::Easy instance.
538
572
  */
539
573
  static VALUE ruby_curl_easy_cookiejar_get(VALUE self) {
540
- CURB_OBJECT_GETTER(ruby_curl_easy, cookiejar);
574
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cookiejar);
541
575
  }
542
576
 
543
577
  /*
544
578
  * call-seq:
545
- * easy.cert = "cert.file" => ""
579
+ * easy.cert = string => ""
546
580
  *
547
581
  * Set a cert file to use for this Curl::Easy instance. This file
548
582
  * will be used to validate SSL connections.
549
583
  *
550
584
  */
551
585
  static VALUE ruby_curl_easy_cert_set(VALUE self, VALUE cert) {
552
- CURB_OBJECT_SETTER(ruby_curl_easy, cert);
586
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert);
553
587
  }
554
588
 
555
589
  /*
556
590
  * call-seq:
557
- * easy.cert => "cert.file"
591
+ * easy.cert => string
558
592
  *
559
593
  * Obtain the cert file to use for this Curl::Easy instance.
560
594
  */
561
595
  static VALUE ruby_curl_easy_cert_get(VALUE self) {
562
- CURB_OBJECT_GETTER(ruby_curl_easy, cert);
596
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert);
563
597
  }
564
598
 
565
599
  /*
566
600
  * call-seq:
567
- * easy.cacert = "cacert.file" => ""
601
+ * easy.cert_key = "cert_key.file" => ""
602
+ *
603
+ * Set a cert key to use for this Curl::Easy instance. This file
604
+ * will be used to validate SSL certificates.
605
+ *
606
+ */
607
+ static VALUE ruby_curl_easy_cert_key_set(VALUE self, VALUE cert_key) {
608
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cert_key);
609
+ }
610
+
611
+ /*
612
+ * call-seq:
613
+ * easy.cert_key => "cert_key.file"
614
+ *
615
+ * Obtain the cert key file to use for this Curl::Easy instance.
616
+ */
617
+ static VALUE ruby_curl_easy_cert_key_get(VALUE self) {
618
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cert_key);
619
+ }
620
+
621
+ /*
622
+ * call-seq:
623
+ * easy.cacert = string => ""
568
624
  *
569
625
  * Set a cacert bundle to use for this Curl::Easy instance. This file
570
626
  * will be used to validate SSL certificates.
571
627
  *
572
628
  */
573
629
  static VALUE ruby_curl_easy_cacert_set(VALUE self, VALUE cacert) {
574
- CURB_OBJECT_SETTER(ruby_curl_easy, cacert);
630
+ CURB_OBJECT_HSETTER(ruby_curl_easy, cacert);
575
631
  }
576
632
 
577
633
  /*
578
634
  * call-seq:
579
- * easy.cacert => "cacert.file"
635
+ * easy.cacert => string
580
636
  *
581
637
  * Obtain the cacert file to use for this Curl::Easy instance.
582
638
  */
583
639
  static VALUE ruby_curl_easy_cacert_get(VALUE self) {
584
- CURB_OBJECT_GETTER(ruby_curl_easy, cacert);
640
+ CURB_OBJECT_HGETTER(ruby_curl_easy, cacert);
585
641
  }
586
642
 
587
643
  /*
588
644
  * call-seq:
589
- * easy.certpassword = "cert password" => ""
645
+ * easy.certpassword = string => ""
590
646
  *
591
647
  * Set a password used to open the specified cert
592
648
  */
593
649
  static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
594
- CURB_OBJECT_SETTER(ruby_curl_easy, certpassword);
650
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certpassword);
595
651
  }
596
652
 
597
653
  /*
@@ -603,49 +659,49 @@ static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
603
659
  *
604
660
  */
605
661
  static VALUE ruby_curl_easy_certtype_set(VALUE self, VALUE certtype) {
606
- CURB_OBJECT_SETTER(ruby_curl_easy, certtype);
662
+ CURB_OBJECT_HSETTER(ruby_curl_easy, certtype);
607
663
  }
608
664
 
609
665
  /*
610
666
  * call-seq:
611
- * easy.certtype => "cert.type"
667
+ * easy.certtype => string
612
668
  *
613
669
  * Obtain the cert type used for this Curl::Easy instance
614
670
  */
615
671
  static VALUE ruby_curl_easy_certtype_get(VALUE self) {
616
- CURB_OBJECT_GETTER(ruby_curl_easy, certtype);
672
+ CURB_OBJECT_HGETTER(ruby_curl_easy, certtype);
617
673
  }
618
674
 
619
675
  /*
620
676
  * call-seq:
621
- * easy.encoding= => "string"
677
+ * easy.encoding = string => string
622
678
  *
623
679
  * Set the accepted encoding types, curl will handle all of the decompression
624
680
  *
625
681
  */
626
682
  static VALUE ruby_curl_easy_encoding_set(VALUE self, VALUE encoding) {
627
- CURB_OBJECT_SETTER(ruby_curl_easy, encoding);
683
+ CURB_OBJECT_HSETTER(ruby_curl_easy, encoding);
628
684
  }
629
685
  /*
630
686
  * call-seq:
631
- * easy.encoding => "string"
687
+ * easy.encoding => string
632
688
  *
633
689
  * Get the set encoding types
634
690
  *
635
691
  */
636
692
  static VALUE ruby_curl_easy_encoding_get(VALUE self) {
637
- CURB_OBJECT_GETTER(ruby_curl_easy, encoding);
693
+ CURB_OBJECT_HGETTER(ruby_curl_easy, encoding);
638
694
  }
639
695
 
640
696
  /*
641
697
  * call-seq:
642
- * easy.useragent = "Ruby/Curb" => ""
698
+ * easy.useragent = "Ruby/Curb" => ""
643
699
  *
644
700
  * Set the user agent string for this Curl::Easy instance
645
701
  *
646
702
  */
647
703
  static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
648
- CURB_OBJECT_SETTER(ruby_curl_easy, useragent);
704
+ CURB_OBJECT_HSETTER(ruby_curl_easy, useragent);
649
705
  }
650
706
 
651
707
  /*
@@ -655,12 +711,12 @@ static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
655
711
  * Obtain the user agent string used for this Curl::Easy instance
656
712
  */
657
713
  static VALUE ruby_curl_easy_useragent_get(VALUE self) {
658
- CURB_OBJECT_GETTER(ruby_curl_easy, useragent);
714
+ CURB_OBJECT_HGETTER(ruby_curl_easy, useragent);
659
715
  }
660
716
 
661
717
  /*
662
718
  * call-seq:
663
- * easy.post_body = "some=form%20data&to=send" => string or nil
719
+ * easy.post_body = "some=form%20data&to=send" => string or nil
664
720
  *
665
721
  * Sets the POST body of this Curl::Easy instance. This is expected to be
666
722
  * URL encoded; no additional processing or encoding is done on the string.
@@ -674,13 +730,14 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
674
730
 
675
731
  char *data;
676
732
  long len;
677
-
733
+
678
734
  Data_Get_Struct(self, ruby_curl_easy, rbce);
679
735
 
680
736
  curl = rbce->curl;
681
737
 
682
738
  if ( post_body == Qnil ) {
683
- rbce->postdata_buffer = Qnil;
739
+ //rbce->postdata_buffer = Qnil;
740
+ rb_easy_del("postdata_buffer");
684
741
 
685
742
  } else {
686
743
  data = StringValuePtr(post_body);
@@ -688,7 +745,8 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
688
745
 
689
746
  // Store the string, since it has to hang around for the duration of the
690
747
  // request. See CURLOPT_POSTFIELDS in the libcurl docs.
691
- rbce->postdata_buffer = post_body;
748
+ //rbce->postdata_buffer = post_body;
749
+ rb_easy_set("postdata_buffer", post_body);
692
750
 
693
751
  curl_easy_setopt(curl, CURLOPT_POST, 1);
694
752
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
@@ -702,12 +760,12 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
702
760
 
703
761
  /*
704
762
  * call-seq:
705
- * easy.post_body => "string" or nil
763
+ * easy.post_body => string or nil
706
764
  *
707
765
  * Obtain the POST body used in this Curl::Easy instance.
708
766
  */
709
767
  static VALUE ruby_curl_easy_post_body_get(VALUE self) {
710
- CURB_OBJECT_GETTER(ruby_curl_easy, postdata_buffer);
768
+ CURB_OBJECT_HGETTER(ruby_curl_easy, postdata_buffer);
711
769
  }
712
770
 
713
771
  /*
@@ -722,6 +780,7 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
722
780
  ruby_curl_easy *rbce;
723
781
  CURL *curl;
724
782
  VALUE upload;
783
+ VALUE headers;
725
784
 
726
785
  Data_Get_Struct(self, ruby_curl_easy, rbce);
727
786
 
@@ -729,9 +788,9 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
729
788
  ruby_curl_upload_stream_set(upload,data);
730
789
 
731
790
  curl = rbce->curl;
732
- rbce->upload = upload; /* keep the upload object alive as long as
733
- the easy handle is active or until the upload
734
- is complete or terminated... */
791
+ rb_easy_set("upload", upload); /* keep the upload object alive as long as
792
+ the easy handle is active or until the upload
793
+ is complete or terminated... */
735
794
 
736
795
  curl_easy_setopt(curl, CURLOPT_NOBODY,0);
737
796
  curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
@@ -742,40 +801,63 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
742
801
  * we need to set specific headers for the PUT to work... so
743
802
  * convert the internal headers structure to a HASH if one is set
744
803
  */
745
- if (rbce->headers != Qnil) {
746
- if (rb_type(rbce->headers) == T_ARRAY || rb_type(rbce->headers) == T_STRING) {
804
+ if (!rb_easy_nil("headers")) {
805
+ if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_STRING)) {
747
806
  rb_raise(rb_eRuntimeError, "Must set headers as a HASH to modify the headers in an PUT request");
748
807
  }
749
808
  }
750
809
 
810
+ headers = rb_easy_get("headers");
811
+ if( headers == Qnil ) {
812
+ headers = rb_hash_new();
813
+ }
751
814
  if (rb_respond_to(data, rb_intern("read"))) {
752
815
  VALUE stat = rb_funcall(data, rb_intern("stat"), 0);
753
816
  if( stat ) {
754
817
  VALUE size;
755
- if( rb_hash_aref(rbce->headers, rb_str_new2("Expect")) == Qnil ) {
756
- rb_hash_aset(rbce->headers, rb_str_new2("Expect"), rb_str_new2(""));
818
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
819
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
757
820
  }
758
821
  size = rb_funcall(stat, rb_intern("size"), 0);
759
822
  curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2INT(size));
760
823
  }
761
- else if( rb_hash_aref(rbce->headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
762
- rb_hash_aset(rbce->headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
824
+ else if( rb_hash_aref(headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
825
+ rb_hash_aset(headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
763
826
  }
764
827
  }
765
828
  else if (rb_respond_to(data, rb_intern("to_s"))) {
766
829
  curl_easy_setopt(curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
767
- if( rb_hash_aref(rbce->headers, rb_str_new2("Expect")) == Qnil ) {
768
- rb_hash_aset(rbce->headers, rb_str_new2("Expect"), rb_str_new2(""));
830
+ if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
831
+ rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
769
832
  }
770
833
  }
771
834
  else {
772
835
  rb_raise(rb_eRuntimeError, "PUT data must respond to read or to_s");
773
836
  }
837
+ rb_easy_set("headers",headers);
774
838
 
775
839
  // if we made it this far, all should be well.
776
840
  return data;
777
841
  }
778
842
 
843
+ /*
844
+ * call-seq:
845
+ * easy.ftp_commands = ["CWD /", "MKD directory"] => ["CWD /", ...]
846
+ *
847
+ * Explicitly sets the list of commands to execute on the FTP server when calling perform
848
+ */
849
+ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
850
+ CURB_OBJECT_HSETTER(ruby_curl_easy, ftp_commands);
851
+ }
852
+
853
+ /*
854
+ * call-seq
855
+ * easy.ftp_commands => array or nil
856
+ */
857
+ static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
858
+ CURB_OBJECT_HGETTER(ruby_curl_easy, ftp_commands);
859
+ }
860
+
779
861
  /* ================== IMMED ATTRS ==================*/
780
862
 
781
863
  /*
@@ -877,16 +959,63 @@ static VALUE ruby_curl_easy_proxy_type_get(VALUE self) {
877
959
  CURB_IMMED_GETTER(ruby_curl_easy, proxy_type, -1);
878
960
  }
879
961
 
962
+ #if defined(HAVE_CURLAUTH_DIGEST_IE)
963
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
964
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
965
+ (!strncmp("digest_ie",node,9)) ? CURLAUTH_DIGEST_IE : \
966
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
967
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
968
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
969
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
970
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
971
+ #else
972
+ #define CURL_HTTPAUTH_STR_TO_NUM(node) \
973
+ (!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
974
+ (!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
975
+ (!strncmp("gssnegotiate",node,12)) ? CURLAUTH_GSSNEGOTIATE : \
976
+ (!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
977
+ (!strncmp("any",node,3)) ? CURLAUTH_ANY : \
978
+ (!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : 0
979
+ #endif
880
980
  /*
881
981
  * call-seq:
882
982
  * easy.http_auth_types = fixnum or nil => fixnum or nil
983
+ * easy.http_auth_types = [:basic,:digest,:digest_ie,:gssnegotiate, :ntlm, :any, :anysafe]
883
984
  *
884
985
  * Set the HTTP authentication types that may be used for the following
885
986
  * +perform+ calls. This is a bitmap made by ORing together the
886
987
  * Curl::CURLAUTH constants.
887
988
  */
888
- static VALUE ruby_curl_easy_http_auth_types_set(VALUE self, VALUE http_auth_types) {
889
- CURB_IMMED_SETTER(ruby_curl_easy, http_auth_types, 0);
989
+ static VALUE ruby_curl_easy_http_auth_types_set(int argc, VALUE *argv, VALUE self) {//VALUE self, VALUE http_auth_types) {
990
+ ruby_curl_easy *rbce;
991
+ VALUE args_ary;
992
+ int i, len;
993
+ char* node = NULL;
994
+ long mask = 0x000000;
995
+
996
+ rb_scan_args(argc, argv, "*", &args_ary);
997
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
998
+ len = RARRAY_LEN(args_ary);
999
+
1000
+ if (len == 1 && (TYPE(rb_ary_entry(args_ary,0)) == T_FIXNUM || rb_ary_entry(args_ary,0) == Qnil)) {
1001
+ if (rb_ary_entry(args_ary,0) == Qnil) {
1002
+ rbce->http_auth_types = 0;
1003
+ }
1004
+ else {
1005
+ rbce->http_auth_types = NUM2INT(rb_ary_entry(args_ary,0));
1006
+ }
1007
+ }
1008
+ else {
1009
+ // we could have multiple values, but they should be symbols
1010
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,0),rb_intern("to_s"),0));
1011
+ mask = CURL_HTTPAUTH_STR_TO_NUM(node);
1012
+ for( i = 1; i < len; ++i ) {
1013
+ node = RSTRING_PTR(rb_funcall(rb_ary_entry(args_ary,i),rb_intern("to_s"),0));
1014
+ mask |= CURL_HTTPAUTH_STR_TO_NUM(node);
1015
+ }
1016
+ rbce->http_auth_types = mask;
1017
+ }
1018
+ return INT2NUM(rbce->http_auth_types);
890
1019
  }
891
1020
 
892
1021
  /*
@@ -1052,11 +1181,131 @@ static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self, VALUE ftp_respo
1052
1181
  CURB_IMMED_GETTER(ruby_curl_easy, ftp_response_timeout, 0);
1053
1182
  }
1054
1183
 
1184
+ /*
1185
+ * call-seq:
1186
+ * easy.username = string => string
1187
+ *
1188
+ * Set the HTTP Authentication username.
1189
+ */
1190
+ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
1191
+ #if HAVE_CURLOPT_USERNAME
1192
+ CURB_OBJECT_HSETTER(ruby_curl_easy, username);
1193
+ #else
1194
+ return Qnil;
1195
+ #endif
1196
+ }
1197
+
1198
+ /*
1199
+ * call-seq:
1200
+ * easy.username => string
1201
+ *
1202
+ * Get the current username
1203
+ */
1204
+ static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
1205
+ #if HAVE_CURLOPT_USERNAME
1206
+ CURB_OBJECT_HGETTER(ruby_curl_easy, username);
1207
+ #else
1208
+ return Qnil;
1209
+ #endif
1210
+ }
1211
+
1212
+ /*
1213
+ * call-seq:
1214
+ * easy.password = string => string
1215
+ *
1216
+ * Set the HTTP Authentication password.
1217
+ */
1218
+ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
1219
+ #if HAVE_CURLOPT_PASSWORD
1220
+ CURB_OBJECT_HSETTER(ruby_curl_easy, password);
1221
+ #else
1222
+ return Qnil;
1223
+ #endif
1224
+ }
1225
+
1226
+ /*
1227
+ * call-seq:
1228
+ * easy.password => string
1229
+ *
1230
+ * Get the current password
1231
+ */
1232
+ static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
1233
+ #if HAVE_CURLOPT_PASSWORD
1234
+ CURB_OBJECT_HGETTER(ruby_curl_easy, password);
1235
+ #else
1236
+ return Qnil;
1237
+ #endif
1238
+ }
1239
+
1240
+ /*
1241
+ * call-seq:
1242
+ * easy.ssl_version = value => fixnum or nil
1243
+ *
1244
+ * Sets the version of SSL/TLS that libcurl will attempt to use. Valid
1245
+ * options are Curl::CURL_SSLVERSION_TLSv1, Curl::CURL_SSLVERSION::SSLv2,
1246
+ * Curl::CURL_SSLVERSION_SSLv3 and Curl::CURL_SSLVERSION_DEFAULT
1247
+ */
1248
+ static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
1249
+ CURB_IMMED_SETTER(ruby_curl_easy, ssl_version, -1);
1250
+ }
1251
+
1252
+ /*
1253
+ * call-seq:
1254
+ * easy.ssl_version => fixnum
1255
+ *
1256
+ * Get the version of SSL/TLS that libcurl will attempt to use.
1257
+ */
1258
+ static VALUE ruby_curl_easy_ssl_version_get(VALUE self, VALUE ssl_version) {
1259
+ CURB_IMMED_GETTER(ruby_curl_easy, ssl_version, -1);
1260
+ }
1261
+
1262
+ /*
1263
+ * call-seq:
1264
+ * easy.use_ssl = value => fixnum or nil
1265
+ *
1266
+ * Ensure libcurl uses SSL for FTP connections. Valid options are Curl::CURL_USESSL_NONE,
1267
+ * Curl::CURL_USESSL_TRY, Curl::CURL_USESSL_CONTROL, and Curl::CURL_USESSL_ALL.
1268
+ */
1269
+ static VALUE ruby_curl_easy_use_ssl_set(VALUE self, VALUE use_ssl) {
1270
+ CURB_IMMED_SETTER(ruby_curl_easy, use_ssl, -1);
1271
+ }
1272
+
1273
+ /*
1274
+ * call-seq:
1275
+ * easy.use_ssl => fixnum
1276
+ *
1277
+ * Get the desired level for using SSL on FTP connections.
1278
+ */
1279
+ static VALUE ruby_curl_easy_use_ssl_get(VALUE self, VALUE use_ssl) {
1280
+ CURB_IMMED_GETTER(ruby_curl_easy, use_ssl, -1);
1281
+ }
1282
+
1283
+ /*
1284
+ * call-seq:
1285
+ * easy.ftp_filemethod = value => fixnum or nil
1286
+ *
1287
+ * Controls how libcurl reaches files on the server. Valid options are Curl::CURL_MULTICWD,
1288
+ * Curl::CURL_NOCWD, and Curl::CURL_SINGLECWD (see libcurl docs for CURLOPT_FTP_METHOD).
1289
+ */
1290
+ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod) {
1291
+ CURB_IMMED_SETTER(ruby_curl_easy, ftp_filemethod, -1);
1292
+ }
1293
+
1294
+ /*
1295
+ * call-seq
1296
+ * easy.ftp_filemethod => fixnum
1297
+ *
1298
+ * Get the configuration for how libcurl will reach files on the server.
1299
+ */
1300
+ static VALUE ruby_curl_easy_ftp_filemethod_get(VALUE self, VALUE ftp_filemethod) {
1301
+ CURB_IMMED_GETTER(ruby_curl_easy, ftp_filemethod, -1);
1302
+ }
1303
+
1055
1304
  /* ================== BOOL ATTRS ===================*/
1056
1305
 
1057
1306
  /*
1058
1307
  * call-seq:
1059
- * proxy_tunnel = boolean => boolean
1308
+ * easy.proxy_tunnel = boolean => boolean
1060
1309
  *
1061
1310
  * Configure whether this Curl instance will use proxy tunneling.
1062
1311
  */
@@ -1066,7 +1315,7 @@ static VALUE ruby_curl_easy_proxy_tunnel_set(VALUE self, VALUE proxy_tunnel) {
1066
1315
 
1067
1316
  /*
1068
1317
  * call-seq:
1069
- * proxy_tunnel? => boolean
1318
+ * easy.proxy_tunnel? => boolean
1070
1319
  *
1071
1320
  * Determine whether this Curl instance will use proxy tunneling.
1072
1321
  */
@@ -1076,7 +1325,7 @@ static VALUE ruby_curl_easy_proxy_tunnel_q(VALUE self) {
1076
1325
 
1077
1326
  /*
1078
1327
  * call-seq:
1079
- * fetch_file_time = boolean => boolean
1328
+ * easy.fetch_file_time = boolean => boolean
1080
1329
  *
1081
1330
  * Configure whether this Curl instance will fetch remote file
1082
1331
  * times, if available.
@@ -1087,7 +1336,7 @@ static VALUE ruby_curl_easy_fetch_file_time_set(VALUE self, VALUE fetch_file_tim
1087
1336
 
1088
1337
  /*
1089
1338
  * call-seq:
1090
- * fetch_file_time? => boolean
1339
+ * easy.fetch_file_time? => boolean
1091
1340
  *
1092
1341
  * Determine whether this Curl instance will fetch remote file
1093
1342
  * times, if available.
@@ -1098,7 +1347,7 @@ static VALUE ruby_curl_easy_fetch_file_time_q(VALUE self) {
1098
1347
 
1099
1348
  /*
1100
1349
  * call-seq:
1101
- * ssl_verify_peer = boolean => boolean
1350
+ * easy.ssl_verify_peer = boolean => boolean
1102
1351
  *
1103
1352
  * Configure whether this Curl instance will verify the SSL peer
1104
1353
  * certificate. When true (the default), and the verification fails to
@@ -1116,7 +1365,7 @@ static VALUE ruby_curl_easy_ssl_verify_peer_set(VALUE self, VALUE ssl_verify_pee
1116
1365
 
1117
1366
  /*
1118
1367
  * call-seq:
1119
- * ssl_verify_peer? => boolean
1368
+ * easy.ssl_verify_peer? => boolean
1120
1369
  *
1121
1370
  * Determine whether this Curl instance will verify the SSL peer
1122
1371
  * certificate.
@@ -1127,7 +1376,7 @@ static VALUE ruby_curl_easy_ssl_verify_peer_q(VALUE self) {
1127
1376
 
1128
1377
  /*
1129
1378
  * call-seq:
1130
- * ssl_verify_host = boolean => boolean
1379
+ * easy.ssl_verify_host = boolean => boolean
1131
1380
  *
1132
1381
  * Configure whether this Curl instance will verify that the server cert
1133
1382
  * is for the server it is known as. When true (the default) the server
@@ -1144,7 +1393,7 @@ static VALUE ruby_curl_easy_ssl_verify_host_set(VALUE self, VALUE ssl_verify_hos
1144
1393
 
1145
1394
  /*
1146
1395
  * call-seq:
1147
- * ssl_verify_host? => boolean
1396
+ * easy.ssl_verify_host? => boolean
1148
1397
  *
1149
1398
  * Determine whether this Curl instance will verify that the server cert
1150
1399
  * is for the server it is known as.
@@ -1155,7 +1404,7 @@ static VALUE ruby_curl_easy_ssl_verify_host_q(VALUE self) {
1155
1404
 
1156
1405
  /*
1157
1406
  * call-seq:
1158
- * header_in_body = boolean => boolean
1407
+ * easy.header_in_body = boolean => boolean
1159
1408
  *
1160
1409
  * Configure whether this Curl instance will return HTTP headers
1161
1410
  * combined with body data. If this option is set true, both header
@@ -1167,7 +1416,7 @@ static VALUE ruby_curl_easy_header_in_body_set(VALUE self, VALUE header_in_body)
1167
1416
 
1168
1417
  /*
1169
1418
  * call-seq:
1170
- * header_in_body? => boolean
1419
+ * easy.header_in_body? => boolean
1171
1420
  *
1172
1421
  * Determine whether this Curl instance will verify the SSL peer
1173
1422
  * certificate.
@@ -1178,7 +1427,7 @@ static VALUE ruby_curl_easy_header_in_body_q(VALUE self) {
1178
1427
 
1179
1428
  /*
1180
1429
  * call-seq:
1181
- * use_netrc = boolean => boolean
1430
+ * easy.use_netrc = boolean => boolean
1182
1431
  *
1183
1432
  * Configure whether this Curl instance will use data from the user's
1184
1433
  * .netrc file for FTP connections.
@@ -1189,7 +1438,7 @@ static VALUE ruby_curl_easy_use_netrc_set(VALUE self, VALUE use_netrc) {
1189
1438
 
1190
1439
  /*
1191
1440
  * call-seq:
1192
- * use_netrc? => boolean
1441
+ * easy.use_netrc? => boolean
1193
1442
  *
1194
1443
  * Determine whether this Curl instance will use data from the user's
1195
1444
  * .netrc file for FTP connections.
@@ -1200,7 +1449,7 @@ static VALUE ruby_curl_easy_use_netrc_q(VALUE self) {
1200
1449
 
1201
1450
  /*
1202
1451
  * call-seq:
1203
- * follow_location = boolean => boolean
1452
+ * easy.follow_location = boolean => boolean
1204
1453
  *
1205
1454
  * Configure whether this Curl instance will follow Location: headers
1206
1455
  * in HTTP responses. Redirects will only be followed to the extent
@@ -1209,10 +1458,29 @@ static VALUE ruby_curl_easy_use_netrc_q(VALUE self) {
1209
1458
  static VALUE ruby_curl_easy_follow_location_set(VALUE self, VALUE follow_location) {
1210
1459
  CURB_BOOLEAN_SETTER(ruby_curl_easy, follow_location);
1211
1460
  }
1461
+ /*
1462
+ * call-seq:
1463
+ *
1464
+ * easy = Curl::Easy.new
1465
+ * easy.autoreferer=true
1466
+ */
1467
+ static VALUE ruby_curl_easy_autoreferer_set(VALUE self, VALUE autoreferer) {
1468
+ ruby_curl_easy *rbce;
1469
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
1470
+
1471
+ if (Qtrue == autoreferer) {
1472
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 1);
1473
+ }
1474
+ else {
1475
+ curl_easy_setopt(rbce->curl, CURLOPT_AUTOREFERER, 0);
1476
+ }
1477
+
1478
+ return autoreferer;
1479
+ }
1212
1480
 
1213
1481
  /*
1214
1482
  * call-seq:
1215
- * follow_location? => boolean
1483
+ * easy.follow_location? => boolean
1216
1484
  *
1217
1485
  * Determine whether this Curl instance will follow Location: headers
1218
1486
  * in HTTP responses.
@@ -1223,7 +1491,7 @@ static VALUE ruby_curl_easy_follow_location_q(VALUE self) {
1223
1491
 
1224
1492
  /*
1225
1493
  * call-seq:
1226
- * unrestricted_auth = boolean => boolean
1494
+ * easy.unrestricted_auth = boolean => boolean
1227
1495
  *
1228
1496
  * Configure whether this Curl instance may use any HTTP authentication
1229
1497
  * method available when necessary.
@@ -1234,7 +1502,7 @@ static VALUE ruby_curl_easy_unrestricted_auth_set(VALUE self, VALUE unrestricted
1234
1502
 
1235
1503
  /*
1236
1504
  * call-seq:
1237
- * unrestricted_auth? => boolean
1505
+ * easy.unrestricted_auth? => boolean
1238
1506
  *
1239
1507
  * Determine whether this Curl instance may use any HTTP authentication
1240
1508
  * method available when necessary.
@@ -1308,7 +1576,7 @@ static VALUE ruby_curl_easy_enable_cookies_set(VALUE self, VALUE enable_cookies)
1308
1576
 
1309
1577
  /*
1310
1578
  * call-seq:
1311
- * easy.enable_cookies? => boolean
1579
+ * easy.enable_cookies? => boolean
1312
1580
  *
1313
1581
  * Determine whether the libcurl cookie engine is enabled for this
1314
1582
  * Curl::Easy instance.
@@ -1335,12 +1603,12 @@ static VALUE ruby_curl_easy_enable_cookies_q(VALUE self) {
1335
1603
  * the processing with a Curl::Err::AbortedByCallbackError.
1336
1604
  */
1337
1605
  static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
1338
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, body_proc);
1606
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, body_proc);
1339
1607
  }
1340
1608
 
1341
1609
  /*
1342
1610
  * call-seq:
1343
- * easy.on_success { ... } => &lt;old handler&gt;
1611
+ * easy.on_success { |easy| ... } => &lt;old handler&gt;
1344
1612
  *
1345
1613
  * Assign or remove the +on_success+ handler for this Curl::Easy instance.
1346
1614
  * To remove a previously-supplied handler, call this method with no
@@ -1350,12 +1618,12 @@ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
1350
1618
  * status of 20x
1351
1619
  */
1352
1620
  static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
1353
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, success_proc);
1621
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, success_proc);
1354
1622
  }
1355
1623
 
1356
1624
  /*
1357
1625
  * call-seq:
1358
- * easy.on_failure { ... } => &lt;old handler&gt;
1626
+ * easy.on_failure {|easy,code| ... } => &lt;old handler&gt;
1359
1627
  *
1360
1628
  * Assign or remove the +on_failure+ handler for this Curl::Easy instance.
1361
1629
  * To remove a previously-supplied handler, call this method with no
@@ -1365,12 +1633,12 @@ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
1365
1633
  * status of 50x
1366
1634
  */
1367
1635
  static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
1368
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, failure_proc);
1636
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, failure_proc);
1369
1637
  }
1370
1638
 
1371
1639
  /*
1372
1640
  * call-seq:
1373
- * easy.on_complete { ... } => &lt;old handler&gt;
1641
+ * easy.on_complete {|easy| ... } => &lt;old handler&gt;
1374
1642
  *
1375
1643
  * Assign or remove the +on_complete+ handler for this Curl::Easy instance.
1376
1644
  * To remove a previously-supplied handler, call this method with no
@@ -1379,7 +1647,7 @@ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
1379
1647
  * The +on_complete+ handler is called when the request is finished.
1380
1648
  */
1381
1649
  static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
1382
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, complete_proc);
1650
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, complete_proc);
1383
1651
  }
1384
1652
 
1385
1653
  /*
@@ -1395,7 +1663,7 @@ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
1395
1663
  * block supplied to +on_body+.
1396
1664
  */
1397
1665
  static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
1398
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, header_proc);
1666
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, header_proc);
1399
1667
  }
1400
1668
 
1401
1669
  /*
@@ -1416,7 +1684,7 @@ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
1416
1684
  * throwing a Curl::Err::AbortedByCallbackError.
1417
1685
  */
1418
1686
  static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
1419
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, progress_proc);
1687
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, progress_proc);
1420
1688
  }
1421
1689
 
1422
1690
  /*
@@ -1437,7 +1705,7 @@ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
1437
1705
  * data. The data is passed as a String.
1438
1706
  */
1439
1707
  static VALUE ruby_curl_easy_on_debug_set(int argc, VALUE *argv, VALUE self) {
1440
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, debug_proc);
1708
+ CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, debug_proc);
1441
1709
  }
1442
1710
 
1443
1711
 
@@ -1472,91 +1740,123 @@ static VALUE cb_each_http_header(VALUE header, struct curl_slist **list) {
1472
1740
  return header_str;
1473
1741
  }
1474
1742
 
1743
+ /***********************************************
1744
+ * This is an rb_iterate callback used to set up ftp commands.
1745
+ */
1746
+ static VALUE cb_each_ftp_command(VALUE ftp_command, struct curl_slist **list) {
1747
+ VALUE ftp_command_string = rb_obj_as_string(ftp_command);
1748
+ *list = curl_slist_append(*list, StringValuePtr(ftp_command));
1749
+
1750
+ return ftp_command_string;
1751
+ }
1752
+
1475
1753
  /***********************************************
1476
1754
  *
1477
1755
  * Setup a connection
1478
1756
  *
1479
1757
  * Always returns Qtrue, rb_raise on error.
1480
1758
  */
1481
- VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *header_buffer, struct curl_slist **hdrs ) {
1759
+ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce ) {
1482
1760
  // TODO this could do with a bit of refactoring...
1483
1761
  CURL *curl;
1484
- VALUE url;
1762
+ VALUE url, _url = rb_easy_get("url");
1763
+ struct curl_slist **hdrs = &(rbce->curl_headers);
1764
+ struct curl_slist **cmds = &(rbce->curl_ftp_commands);
1485
1765
 
1486
1766
  curl = rbce->curl;
1487
1767
 
1488
- if (rbce->url == Qnil) {
1768
+ if (_url == Qnil) {
1489
1769
  rb_raise(eCurlErrError, "No URL supplied");
1490
1770
  }
1491
1771
 
1492
- url = rb_check_string_type(rbce->url);
1772
+ url = rb_check_string_type(_url);
1493
1773
 
1494
1774
  // Need to configure the handler as per settings in rbce
1495
1775
  curl_easy_setopt(curl, CURLOPT_URL, StringValuePtr(url));
1496
1776
 
1497
1777
  // network stuff and auth
1498
- if (rbce->interface_hm != Qnil) {
1499
- curl_easy_setopt(curl, CURLOPT_INTERFACE, StringValuePtr(rbce->interface_hm));
1778
+ if (!rb_easy_nil("interface_hm")) {
1779
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, rb_easy_get_str("interface_hm"));
1500
1780
  } else {
1501
1781
  curl_easy_setopt(curl, CURLOPT_INTERFACE, NULL);
1502
1782
  }
1503
1783
 
1504
- if (rbce->userpwd != Qnil) {
1505
- curl_easy_setopt(curl, CURLOPT_USERPWD, StringValuePtr(rbce->userpwd));
1784
+ #if HAVE_CURLOPT_USERNAME == 1 && HAVE_CURLOPT_PASSWORD == 1
1785
+ if (!rb_easy_nil("username")) {
1786
+ curl_easy_setopt(curl, CURLOPT_USERNAME, rb_easy_get_str("username"));
1787
+ } else {
1788
+ curl_easy_setopt(curl, CURLOPT_USERNAME, NULL);
1789
+ }
1790
+ if (!rb_easy_nil("password")) {
1791
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, rb_easy_get_str("password"));
1792
+ }
1793
+ else {
1794
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, NULL);
1795
+ }
1796
+ #endif
1797
+
1798
+ if (!rb_easy_nil("userpwd")) {
1799
+ curl_easy_setopt(curl, CURLOPT_USERPWD, rb_easy_get_str("userpwd"));
1800
+ #if HAVE_CURLOPT_USERNAME == 1
1801
+ } else if (rb_easy_nil("username") && rb_easy_nil("password")) { /* don't set this even to NULL if we have set username and password */
1802
+ #else
1506
1803
  } else {
1804
+ #endif
1507
1805
  curl_easy_setopt(curl, CURLOPT_USERPWD, NULL);
1508
1806
  }
1509
1807
 
1510
- if (rbce->proxy_url != Qnil) {
1511
- curl_easy_setopt(curl, CURLOPT_PROXY, StringValuePtr(rbce->proxy_url));
1808
+ if (!rb_easy_nil("proxy_url")) {
1809
+ curl_easy_setopt(curl, CURLOPT_PROXY, rb_easy_get_str("proxy_url"));
1512
1810
  } else {
1513
1811
  curl_easy_setopt(curl, CURLOPT_PROXY, NULL);
1514
1812
  }
1515
1813
 
1516
- if (rbce->proxypwd != Qnil) {
1517
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, StringValuePtr(rbce->proxypwd));
1814
+ if (!rb_easy_nil("proxypwd")) {
1815
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, rb_easy_get_str("proxy_pwd"));
1518
1816
  } else {
1519
1817
  curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, NULL);
1520
1818
  }
1521
1819
 
1522
1820
  // body/header procs
1523
- if (rbce->body_proc != Qnil) {
1524
- *body_buffer = Qnil;
1821
+ if (!rb_easy_nil("body_proc")) {
1525
1822
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler);
1526
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbce->body_proc);
1823
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_easy_get("body_proc"));//rbce->body_proc);
1824
+ /* clear out the body_data if it was set */
1825
+ rb_easy_del("body_data");
1527
1826
  } else {
1528
- *body_buffer = rb_str_buf_new(32768);
1827
+ VALUE body_buffer = rb_easy_set("body_data", rb_str_buf_new(32768));
1529
1828
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&default_data_handler);
1530
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, *body_buffer);
1829
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
1531
1830
  }
1532
1831
 
1533
- if (rbce->header_proc != Qnil) {
1534
- *header_buffer = Qnil;
1832
+ if (!rb_easy_nil("header_proc")) {
1535
1833
  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&proc_data_handler);
1536
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, rbce->header_proc);
1834
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_easy_get("header_proc"));
1835
+ /* clear out the header_data if it was set */
1836
+ rb_easy_del("header_data");
1537
1837
  } else {
1538
- *header_buffer = rb_str_buf_new(32768);
1838
+ VALUE header_buffer = rb_easy_set("header_data", rb_str_buf_new(16384));
1539
1839
  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&default_data_handler);
1540
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, *header_buffer);
1840
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, header_buffer);
1541
1841
  }
1542
1842
 
1543
1843
  /* encoding */
1544
- if (rbce->encoding != Qnil) {
1545
- curl_easy_setopt(curl, CURLOPT_ENCODING, StringValuePtr(rbce->encoding));
1844
+ if (!rb_easy_nil("encoding")) {
1845
+ curl_easy_setopt(curl, CURLOPT_ENCODING, rb_easy_get_str("encoding"));
1546
1846
  }
1547
1847
 
1548
1848
  // progress and debug procs
1549
- if (rbce->progress_proc != Qnil) {
1849
+ if (!rb_easy_nil("progress_proc")) {
1550
1850
  curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&proc_progress_handler);
1551
- curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, rbce->progress_proc);
1851
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, rb_easy_get("progress_proc"));
1552
1852
  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
1553
1853
  } else {
1554
1854
  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
1555
1855
  }
1556
1856
 
1557
- if (rbce->debug_proc != Qnil) {
1857
+ if (!rb_easy_nil("debug_proc")) {
1558
1858
  curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, (curl_debug_callback)&proc_debug_handler);
1559
- curl_easy_setopt(curl, CURLOPT_DEBUGDATA, rbce->debug_proc);
1859
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, rb_easy_get("debug_proc"));
1560
1860
  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
1561
1861
  } else {
1562
1862
  // have to remove handler to re-enable standard verbosity
@@ -1568,7 +1868,6 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
1568
1868
  /* general opts */
1569
1869
 
1570
1870
  curl_easy_setopt(curl, CURLOPT_HEADER, rbce->header_in_body);
1571
-
1572
1871
  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, rbce->follow_location);
1573
1872
  curl_easy_setopt(curl, CURLOPT_MAXREDIRS, rbce->max_redirs);
1574
1873
 
@@ -1653,50 +1952,71 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
1653
1952
  FIXME this may not get disabled if it's enabled, the disabled again from ruby.
1654
1953
  */
1655
1954
  if (rbce->enable_cookies) {
1656
- if (rbce->cookiejar != Qnil) {
1657
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR, StringValuePtr(rbce->cookiejar));
1955
+ if (!rb_easy_nil("cookiejar")) {
1956
+ curl_easy_setopt(curl, CURLOPT_COOKIEJAR, rb_easy_get_str("cookiejar"));
1658
1957
  }
1659
1958
 
1660
- if (rbce->cookiefile != Qnil) {
1661
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, StringValuePtr(rbce->cookiefile));
1959
+ if (!rb_easy_nil("cookiefile")) {
1960
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, rb_easy_get_str("cookiefile"));
1662
1961
  } else {
1663
1962
  curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* "" = magic to just enable */
1664
1963
  }
1665
1964
  }
1666
1965
 
1667
- if (rbce->cookies != Qnil) {
1668
- curl_easy_setopt(curl, CURLOPT_COOKIE, StringValuePtr(rbce->cookies));
1966
+ if (!rb_easy_nil("cookies")) {
1967
+ curl_easy_setopt(curl, CURLOPT_COOKIE, rb_easy_get_str("cookies"));
1669
1968
  }
1670
1969
 
1671
1970
  /* Set up HTTPS cert handling if necessary */
1672
- if (rbce->cert != Qnil) {
1673
- curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, StringValuePtr(rbce->certtype));
1674
- curl_easy_setopt(curl, CURLOPT_SSLCERT, StringValuePtr(rbce->cert));
1675
- if (rbce->certpassword != Qnil) {
1676
- curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, StringValuePtr(rbce->certpassword));
1971
+ if (!rb_easy_nil("cert")) {
1972
+ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, rb_easy_get_str("certtype"));
1973
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, rb_easy_get_str("cert"));
1974
+ if (!rb_easy_nil("certpassword")) {
1975
+ curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, rb_easy_get_str("certpassword"));
1976
+ }
1977
+ if (!rb_easy_nil("cert_key")) {
1978
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, rb_easy_get_str("cert_key"));
1677
1979
  }
1678
1980
  }
1679
- if (rbce->cacert != Qnil) {
1981
+ if (!rb_easy_nil("cacert")) {
1680
1982
  #ifdef HAVE_CURL_CONFIG_CA
1681
1983
  curl_easy_setopt(curl, CURLOPT_CAINFO, CURL_CONFIG_CA);
1682
1984
  #else
1683
1985
  curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/local/share/curl/curl-ca-bundle.crt");
1684
1986
  #endif
1685
1987
  }
1988
+
1989
+ #ifdef CURL_VERSION_SSL
1990
+ if (rbce->ssl_version > 0) {
1991
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, rbce->ssl_version);
1992
+ }
1993
+
1994
+ if (rbce->use_ssl > 0) {
1995
+ curl_easy_setopt(curl, CURB_FTPSSL, rbce->use_ssl);
1996
+ }
1997
+ #else
1998
+ if (rbce->ssl_version > 0 || rbce->use_ssl > 0) {
1999
+ rb_warn("libcurl is not configured with SSL support");
2000
+ }
2001
+ #endif
1686
2002
 
2003
+ if (rbce->ftp_filemethod > 0) {
2004
+ curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, rbce->ftp_filemethod);
2005
+ }
2006
+
1687
2007
  /* Set the user-agent string if specified */
1688
- if (rbce->useragent != Qnil) {
1689
- curl_easy_setopt(curl, CURLOPT_USERAGENT, StringValuePtr(rbce->useragent));
2008
+ if (!rb_easy_nil("useragent")) {
2009
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, rb_easy_get_str("useragent"));
1690
2010
  }
1691
2011
 
1692
2012
  /* Setup HTTP headers if necessary */
1693
2013
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); // XXX: maybe we shouldn't be clearing this?
1694
2014
 
1695
- if (rbce->headers != Qnil) {
1696
- if ((rb_type(rbce->headers) == T_ARRAY) || (rb_type(rbce->headers) == T_HASH)) {
1697
- rb_iterate(rb_each, rbce->headers, cb_each_http_header, (VALUE)hdrs);
2015
+ if (!rb_easy_nil("headers")) {
2016
+ if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_HASH)) {
2017
+ rb_iterate(rb_each, rb_easy_get("headers"), cb_each_http_header, (VALUE)hdrs);
1698
2018
  } else {
1699
- VALUE headers_str = rb_obj_as_string(rbce->headers);
2019
+ VALUE headers_str = rb_obj_as_string(rb_easy_get("headers"));
1700
2020
  *hdrs = curl_slist_append(*hdrs, StringValuePtr(headers_str));
1701
2021
  }
1702
2022
 
@@ -1705,6 +2025,17 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
1705
2025
  }
1706
2026
  }
1707
2027
 
2028
+ /* Setup FTP commands if necessary */
2029
+ if (!rb_easy_nil("ftp_commands")) {
2030
+ if (rb_easy_type_check("ftp_commands", T_ARRAY)) {
2031
+ rb_iterate(rb_each, rb_easy_get("ftp_commands"), cb_each_ftp_command, (VALUE)cmds);
2032
+ }
2033
+
2034
+ if (*cmds) {
2035
+ curl_easy_setopt(curl, CURLOPT_QUOTE, *cmds);
2036
+ }
2037
+ }
2038
+
1708
2039
  return Qnil;
1709
2040
  }
1710
2041
  /***********************************************
@@ -1713,48 +2044,25 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
1713
2044
  *
1714
2045
  * Always returns Qtrue.
1715
2046
  */
1716
- VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, VALUE headerbuf, struct curl_slist *headers ) {
2047
+ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
1717
2048
 
1718
2049
  CURL *curl = rbce->curl;
1719
-
2050
+ struct curl_slist *headers = rbce->curl_headers;
1720
2051
  // Free everything up
1721
2052
  if (headers) {
1722
2053
  curl_slist_free_all(headers);
1723
2054
  rbce->curl_headers = NULL;
1724
2055
  }
1725
2056
 
1726
- // Sort out the built-in body/header data.
1727
- if (bodybuf != Qnil) {
1728
- if (TYPE(bodybuf) == T_STRING) {
1729
- rbce->body_data = rb_str_to_str(bodybuf);
1730
- }
1731
- else if (rb_respond_to(bodybuf, rb_intern("to_s"))) {
1732
- rbce->body_data = rb_funcall(bodybuf, rb_intern("to_s"), 0);
1733
- }
1734
- else {
1735
- rbce->body_data = Qnil;
1736
- }
1737
- } else {
1738
- rbce->body_data = Qnil;
2057
+ struct curl_slist *ftp_commands = rbce->curl_ftp_commands;
2058
+ if (ftp_commands) {
2059
+ curl_slist_free_all(ftp_commands);
2060
+ rbce->curl_ftp_commands = NULL;
1739
2061
  }
1740
2062
 
1741
- if (headerbuf != Qnil) {
1742
- if (TYPE(headerbuf) == T_STRING) {
1743
- rbce->header_data = rb_str_to_str(headerbuf);
1744
- }
1745
- else if (rb_respond_to(headerbuf, rb_intern("to_s"))) {
1746
- rbce->header_data = rb_funcall(headerbuf, rb_intern("to_s"), 0);
1747
- }
1748
- else {
1749
- rbce->header_data = Qnil;
1750
- }
1751
- } else {
1752
- rbce->header_data = Qnil;
1753
- }
1754
-
1755
2063
  // clean up a PUT request's curl options.
1756
- if (rbce->upload != Qnil) {
1757
- rbce->upload = Qnil; // set the upload object to Qnil to let the GC clean up
2064
+ if (!rb_easy_nil("upload")) {
2065
+ rb_easy_del("upload"); // set the upload object to Qnil to let the GC clean up
1758
2066
  curl_easy_setopt(curl, CURLOPT_UPLOAD, 0);
1759
2067
  curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
1760
2068
  curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
@@ -1777,13 +2085,16 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, V
1777
2085
  static VALUE handle_perform(VALUE self, ruby_curl_easy *rbce) {
1778
2086
 
1779
2087
  VALUE ret;
1780
- VALUE multi = ruby_curl_multi_new(cCurlMulti);
1781
2088
 
1782
- rb_funcall(multi, rb_intern("add"), 1, self );
1783
- ret = rb_funcall(multi, rb_intern("perform"), 0);
2089
+ /* reuse existing multi handle for this easy handle */
2090
+ if (NIL_P(rbce->multi)) {
2091
+ rbce->multi = ruby_curl_multi_new(cCurlMulti);
2092
+ }
2093
+ rb_funcall(rbce->multi, rb_intern("add"), 1, self );
2094
+ ret = rb_funcall(rbce->multi, rb_intern("perform"), 0);
1784
2095
 
1785
2096
  /* check for errors in the easy response and raise exceptions if anything went wrong and their is no on_failure handler */
1786
- if( rbce->last_result != 0 && rbce->failure_proc == Qnil ) {
2097
+ if (rbce->last_result != 0 && rb_easy_nil("failure_proc")) {
1787
2098
  raise_curl_easy_error_exception(rbce->last_result);
1788
2099
  }
1789
2100
 
@@ -1805,20 +2116,16 @@ static VALUE ruby_curl_easy_perform_get(VALUE self) {
1805
2116
  Data_Get_Struct(self, ruby_curl_easy, rbce);
1806
2117
  curl = rbce->curl;
1807
2118
 
2119
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
1808
2120
  curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
1809
2121
 
1810
2122
  return handle_perform(self,rbce);
1811
2123
  }
1812
2124
 
1813
2125
  /*
1814
- * call-seq:
1815
- * easy.http_delete
1816
- *
1817
- * DELETE the currently configured URL using the current options set for
1818
- * this Curl::Easy instance. This method always returns true, or raises
1819
- * an exception (defined under Curl::Err) on error.
2126
+ * Common implementation of easy.http(verb) and easy.http_delete
1820
2127
  */
1821
- static VALUE ruby_curl_easy_perform_delete(VALUE self) {
2128
+ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, char *verb) {
1822
2129
  ruby_curl_easy *rbce;
1823
2130
  CURL *curl;
1824
2131
  VALUE retval;
@@ -1826,7 +2133,7 @@ static VALUE ruby_curl_easy_perform_delete(VALUE self) {
1826
2133
  Data_Get_Struct(self, ruby_curl_easy, rbce);
1827
2134
  curl = rbce->curl;
1828
2135
 
1829
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
2136
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
1830
2137
 
1831
2138
  retval = handle_perform(self,rbce);
1832
2139
 
@@ -1835,6 +2142,29 @@ static VALUE ruby_curl_easy_perform_delete(VALUE self) {
1835
2142
  return retval;
1836
2143
  }
1837
2144
 
2145
+ /*
2146
+ * call-seq:
2147
+ * easy.http_delete
2148
+ *
2149
+ * DELETE the currently configured URL using the current options set for
2150
+ * this Curl::Easy instance. This method always returns true, or raises
2151
+ * an exception (defined under Curl::Err) on error.
2152
+ */
2153
+ static VALUE ruby_curl_easy_perform_delete(VALUE self) {
2154
+ return ruby_curl_easy_perform_verb_str(self, "DELETE");
2155
+ }
2156
+
2157
+ /*
2158
+ * call-seq:
2159
+ * easy.http(verb)
2160
+ *
2161
+ * Send an HTTP request with method set to verb, using the current options set for this Curl::Easy instance.
2162
+ * This method always returns true or raises an exception (defined under Curl::Err) on error.
2163
+ */
2164
+ static VALUE ruby_curl_easy_perform_verb(VALUE self, VALUE verb) {
2165
+ return ruby_curl_easy_perform_verb_str(self, RSTRING_PTR(verb));
2166
+ }
2167
+
1838
2168
  /*
1839
2169
  * call-seq:
1840
2170
  * easy.perform => true
@@ -1886,6 +2216,8 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
1886
2216
  Data_Get_Struct(self, ruby_curl_easy, rbce);
1887
2217
  curl = rbce->curl;
1888
2218
 
2219
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2220
+
1889
2221
  if (rbce->multipart_form_post) {
1890
2222
  VALUE ret;
1891
2223
  struct curl_httppost *first = NULL, *last = NULL;
@@ -1907,12 +2239,22 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
1907
2239
 
1908
2240
  return ret;
1909
2241
  } else {
1910
- VALUE post_body;
2242
+ VALUE post_body = Qnil;
2243
+ /* TODO: check for PostField.file and raise error before to_s fails */
1911
2244
  if ((post_body = rb_funcall(args_ary, idJoin, 1, rbstrAmp)) == Qnil) {
1912
2245
  rb_raise(eCurlErrError, "Failed to join arguments");
1913
2246
  return Qnil;
1914
2247
  } else {
1915
- ruby_curl_easy_post_body_set(self, post_body);
2248
+ /* if the function call above returns an empty string because no additional arguments were passed this makes sure
2249
+ a previously set easy.post_body = "arg=foo&bar=bin" will be honored */
2250
+ if( post_body != Qnil && rb_type(post_body) == T_STRING && RSTRING_LEN(post_body) > 0 ) {
2251
+ ruby_curl_easy_post_body_set(self, post_body);
2252
+ }
2253
+
2254
+ /* if post body is not defined, set it so we enable POST header, even though the request body is empty */
2255
+ if( rb_easy_nil("postdata_buffer") ) {
2256
+ ruby_curl_easy_post_body_set(self, post_body);
2257
+ }
1916
2258
 
1917
2259
  return handle_perform(self,rbce);
1918
2260
  }
@@ -1966,6 +2308,40 @@ static VALUE ruby_curl_easy_set_head_option(VALUE self, VALUE onoff) {
1966
2308
 
1967
2309
  return onoff;
1968
2310
  }
2311
+ /*
2312
+ *call-seq:
2313
+ *
2314
+ * easy = Curl::Easy.new("url")
2315
+ * easy.version = Curl::HTTP_1_1
2316
+ * easy.version = Curl::HTTP_1_0
2317
+ * easy.version = Curl::HTTP_NONE
2318
+ *
2319
+ */
2320
+ static VALUE ruby_curl_easy_set_version(VALUE self, VALUE version) {
2321
+ ruby_curl_easy *rbce;
2322
+ //fprintf(stderr,"CURL_HTTP_VERSION_1_1: %d, CURL_HTTP_VERSION_1_0: %d, CURL_HTTP_VERSION_NONE: %d\n", CURL_HTTP_VERSION_1_1, CURL_HTTP_VERSION_1_0, CURL_HTTP_VERSION_NONE);
2323
+
2324
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2325
+
2326
+ curl_easy_setopt(rbce->curl, CURLOPT_HTTP_VERSION, FIX2INT(version));
2327
+
2328
+ return version;
2329
+ }
2330
+ /*
2331
+ * call-seq:
2332
+ *
2333
+ * easy = Curl::Easy.new
2334
+ * easy.nosignal = true
2335
+ */
2336
+ static VALUE ruby_curl_easy_set_nosignal(VALUE self, VALUE onoff) {
2337
+ ruby_curl_easy *rbce;
2338
+
2339
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2340
+
2341
+ curl_easy_setopt(rbce->curl, CURLOPT_NOSIGNAL, (Qtrue == onoff) ? 1 : 0);
2342
+
2343
+ return onoff;
2344
+ }
1969
2345
  /*
1970
2346
  *call-seq:
1971
2347
  * easy = Curl::Easy.new("url") do|c|
@@ -2003,6 +2379,7 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2003
2379
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2004
2380
  curl = rbce->curl;
2005
2381
 
2382
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2006
2383
  ruby_curl_easy_put_data_set(self, data);
2007
2384
 
2008
2385
  return handle_perform(self, rbce);
@@ -2031,7 +2408,7 @@ static VALUE ruby_curl_easy_class_perform_put(VALUE klass, VALUE url, VALUE data
2031
2408
  * your own body handler, this string will be empty.
2032
2409
  */
2033
2410
  static VALUE ruby_curl_easy_body_str_get(VALUE self) {
2034
- CURB_OBJECT_GETTER(ruby_curl_easy, body_data);
2411
+ CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
2035
2412
  }
2036
2413
 
2037
2414
  /*
@@ -2043,7 +2420,7 @@ static VALUE ruby_curl_easy_body_str_get(VALUE self) {
2043
2420
  * your own header handler, this string will be empty.
2044
2421
  */
2045
2422
  static VALUE ruby_curl_easy_header_str_get(VALUE self) {
2046
- CURB_OBJECT_GETTER(ruby_curl_easy, header_data);
2423
+ CURB_OBJECT_HGETTER(ruby_curl_easy, header_data);
2047
2424
  }
2048
2425
 
2049
2426
 
@@ -2095,6 +2472,30 @@ static VALUE ruby_curl_easy_response_code_get(VALUE self) {
2095
2472
  return LONG2NUM(code);
2096
2473
  }
2097
2474
 
2475
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
2476
+ /*
2477
+ * call-seq:
2478
+ * easy.primary_ip => "xx.xx.xx.xx" or nil
2479
+ *
2480
+ * Retrieve the resolved IP of the most recent connection
2481
+ * done with this curl handle. This string may be IPv6 if
2482
+ * that's enabled. This feature requires curl 7.19.x and above
2483
+ */
2484
+ static VALUE ruby_curl_easy_primary_ip_get(VALUE self) {
2485
+ ruby_curl_easy *rbce;
2486
+ char* ip;
2487
+
2488
+ Data_Get_Struct(self, ruby_curl_easy, rbce);
2489
+ curl_easy_getinfo(rbce->curl, CURLINFO_PRIMARY_IP, &ip);
2490
+
2491
+ if (ip && ip[0]) { // curl returns empty string if none
2492
+ return rb_str_new2(ip);
2493
+ } else {
2494
+ return Qnil;
2495
+ }
2496
+ }
2497
+ #endif
2498
+
2098
2499
  /*
2099
2500
  * call-seq:
2100
2501
  * easy.http_connect_code => fixnum
@@ -2259,7 +2660,7 @@ static VALUE ruby_curl_easy_redirect_time_get(VALUE self) {
2259
2660
 
2260
2661
  /*
2261
2662
  * call-seq:
2262
- * easy.redirect_count => integer
2663
+ * easy.redirect_count => integer
2263
2664
  *
2264
2665
  * Retrieve the total number of redirections that were actually followed.
2265
2666
  *
@@ -2507,7 +2908,7 @@ static VALUE ruby_curl_easy_os_errno_get(VALUE self) {
2507
2908
 
2508
2909
  /*
2509
2910
  * call-seq:
2510
- * easy.num_connects => integer
2911
+ * easy.num_connects => integer
2511
2912
  *
2512
2913
  * Retrieve the number of new connections libcurl had to create to achieve
2513
2914
  * the previous transfer (only the successful connects are counted).
@@ -2552,7 +2953,7 @@ Pass a pointer to a long to receive the last socket used by this curl session. I
2552
2953
 
2553
2954
  /*
2554
2955
  * call-seq:
2555
- * easy.content_type => "content/type" or nil
2956
+ * easy.ftp_entry_path => "C:\ftp\root\" or nil
2556
2957
  *
2557
2958
  * Retrieve the path of the entry path. That is the initial path libcurl ended
2558
2959
  * up in when logging on to the remote FTP server. This returns +nil+ if
@@ -2581,18 +2982,19 @@ static VALUE ruby_curl_easy_ftp_entry_path_get(VALUE self) {
2581
2982
 
2582
2983
  /*
2583
2984
  * call-seq:
2584
- * easy.inspect => "#<Curl::Easy http://google.com/>"
2985
+ * easy.inspect => "#<Curl::Easy http://google.com/>"
2585
2986
  */
2586
2987
  static VALUE ruby_curl_easy_inspect(VALUE self) {
2587
2988
  char buf[64];
2588
2989
  ruby_curl_easy *rbce;
2589
2990
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2590
2991
  /* if we don't have a url set... we'll crash... */
2591
- if(rbce->url != Qnil && rb_type(rbce->url) == T_STRING) {
2592
- size_t len = 13+((RSTRING_LEN(rbce->url) > 50) ? 50 : RSTRING_LEN(rbce->url));
2992
+ if( !rb_easy_nil("url") && rb_easy_type_check("url", T_STRING)) {
2993
+ VALUE url = rb_easy_get("url");
2994
+ size_t len = 13+((RSTRING_LEN(url) > 50) ? 50 : RSTRING_LEN(url));
2593
2995
  /* "#<Net::HTTP http://www.google.com/:80 open=false>" */
2594
2996
  memcpy(buf,"#<Curl::Easy ", 13);
2595
- memcpy(buf+13,RSTRING_PTR(rbce->url), (len - 13));
2997
+ memcpy(buf+13,RSTRING_PTR(url), (len - 13));
2596
2998
  buf[len-1] = '>';
2597
2999
  return rb_str_new(buf,len);
2598
3000
  }
@@ -2636,7 +3038,7 @@ static VALUE ruby_curl_easy_escape(VALUE self, VALUE svalue) {
2636
3038
 
2637
3039
  /*
2638
3040
  * call-seq:
2639
- * easy.unescape("some text") => "some%20text"
3041
+ * easy.unescape("some%20text") => "some text"
2640
3042
  *
2641
3043
  * Convert the given URL encoded input string to a "plain string" and return
2642
3044
  * the result. All input characters that are URL encoded (%XX where XX is a
@@ -2707,7 +3109,7 @@ static VALUE ruby_curl_easy_class_perform_get(int argc, VALUE *argv, VALUE klass
2707
3109
 
2708
3110
  /*
2709
3111
  * call-seq:
2710
- * Curl::Easy.http_delete(url) { |easy| ... } => #&lt;Curl::Easy...&gt;
3112
+ * Curl::Easy.http_delete(url) { |easy| ... } => #&lt;Curl::Easy...&gt;
2711
3113
  *
2712
3114
  * Convenience method that creates a new Curl::Easy instance with
2713
3115
  * the specified URL and calls +http_delete+, before returning the new instance.
@@ -2724,7 +3126,7 @@ static VALUE ruby_curl_easy_class_perform_delete(int argc, VALUE *argv, VALUE kl
2724
3126
 
2725
3127
  /*
2726
3128
  * call-seq:
2727
- * Curl::Easy.http_head(url) { |easy| ... } => #&lt;Curl::Easy...&gt;
3129
+ * Curl::Easy.http_head(url) { |easy| ... } => #&lt;Curl::Easy...&gt;
2728
3130
  *
2729
3131
  * Convenience method that creates a new Curl::Easy instance with
2730
3132
  * the specified URL and calls +http_head+, before returning the new instance.
@@ -2816,6 +3218,8 @@ void init_curb_easy() {
2816
3218
  rb_define_method(cCurlEasy, "cookiejar", ruby_curl_easy_cookiejar_get, 0);
2817
3219
  rb_define_method(cCurlEasy, "cert=", ruby_curl_easy_cert_set, 1);
2818
3220
  rb_define_method(cCurlEasy, "cert", ruby_curl_easy_cert_get, 0);
3221
+ rb_define_method(cCurlEasy, "cert_key=", ruby_curl_easy_cert_key_set, 1);
3222
+ rb_define_method(cCurlEasy, "cert_key", ruby_curl_easy_cert_key_get, 0);
2819
3223
  rb_define_method(cCurlEasy, "cacert=", ruby_curl_easy_cacert_set, 1);
2820
3224
  rb_define_method(cCurlEasy, "cacert", ruby_curl_easy_cacert_get, 0);
2821
3225
  rb_define_method(cCurlEasy, "certpassword=", ruby_curl_easy_certpassword_set, 1);
@@ -2828,6 +3232,8 @@ void init_curb_easy() {
2828
3232
  rb_define_method(cCurlEasy, "post_body=", ruby_curl_easy_post_body_set, 1);
2829
3233
  rb_define_method(cCurlEasy, "post_body", ruby_curl_easy_post_body_get, 0);
2830
3234
  rb_define_method(cCurlEasy, "put_data=", ruby_curl_easy_put_data_set, 1);
3235
+ rb_define_method(cCurlEasy, "ftp_commands=", ruby_curl_easy_ftp_commands_set, 1);
3236
+ rb_define_method(cCurlEasy, "ftp_commands", ruby_curl_easy_ftp_commands_get, 0);
2831
3237
 
2832
3238
  rb_define_method(cCurlEasy, "local_port=", ruby_curl_easy_local_port_set, 1);
2833
3239
  rb_define_method(cCurlEasy, "local_port", ruby_curl_easy_local_port_get, 0);
@@ -2837,7 +3243,7 @@ void init_curb_easy() {
2837
3243
  rb_define_method(cCurlEasy, "proxy_port", ruby_curl_easy_proxy_port_get, 0);
2838
3244
  rb_define_method(cCurlEasy, "proxy_type=", ruby_curl_easy_proxy_type_set, 1);
2839
3245
  rb_define_method(cCurlEasy, "proxy_type", ruby_curl_easy_proxy_type_get, 0);
2840
- rb_define_method(cCurlEasy, "http_auth_types=", ruby_curl_easy_http_auth_types_set, 1);
3246
+ rb_define_method(cCurlEasy, "http_auth_types=", ruby_curl_easy_http_auth_types_set, -1);
2841
3247
  rb_define_method(cCurlEasy, "http_auth_types", ruby_curl_easy_http_auth_types_get, 0);
2842
3248
  rb_define_method(cCurlEasy, "proxy_auth_types=", ruby_curl_easy_proxy_auth_types_set, 1);
2843
3249
  rb_define_method(cCurlEasy, "proxy_auth_types", ruby_curl_easy_proxy_auth_types_get, 0);
@@ -2851,6 +3257,17 @@ void init_curb_easy() {
2851
3257
  rb_define_method(cCurlEasy, "dns_cache_timeout", ruby_curl_easy_dns_cache_timeout_get, 0);
2852
3258
  rb_define_method(cCurlEasy, "ftp_response_timeout=", ruby_curl_easy_ftp_response_timeout_set, 1);
2853
3259
  rb_define_method(cCurlEasy, "ftp_response_timeout", ruby_curl_easy_ftp_response_timeout_get, 0);
3260
+ rb_define_method(cCurlEasy, "ssl_version=", ruby_curl_easy_ssl_version_set, 1);
3261
+ rb_define_method(cCurlEasy, "ssl_version", ruby_curl_easy_ssl_version_get, 0);
3262
+ rb_define_method(cCurlEasy, "use_ssl=", ruby_curl_easy_use_ssl_set, 1);
3263
+ rb_define_method(cCurlEasy, "use_ssl", ruby_curl_easy_use_ssl_get, 0);
3264
+ rb_define_method(cCurlEasy, "ftp_filemethod=", ruby_curl_easy_ftp_filemethod_set, 1);
3265
+ rb_define_method(cCurlEasy, "ftp_filemethod", ruby_curl_easy_ftp_filemethod_get, 0);
3266
+
3267
+ rb_define_method(cCurlEasy, "username=", ruby_curl_easy_username_set, 1);
3268
+ rb_define_method(cCurlEasy, "username", ruby_curl_easy_username_get, 0);
3269
+ rb_define_method(cCurlEasy, "password=", ruby_curl_easy_password_set, 1);
3270
+ rb_define_method(cCurlEasy, "password", ruby_curl_easy_password_get, 0);
2854
3271
 
2855
3272
  rb_define_method(cCurlEasy, "proxy_tunnel=", ruby_curl_easy_proxy_tunnel_set, 1);
2856
3273
  rb_define_method(cCurlEasy, "proxy_tunnel?", ruby_curl_easy_proxy_tunnel_q, 0);
@@ -2866,6 +3283,7 @@ void init_curb_easy() {
2866
3283
  rb_define_method(cCurlEasy, "use_netrc?", ruby_curl_easy_use_netrc_q, 0);
2867
3284
  rb_define_method(cCurlEasy, "follow_location=", ruby_curl_easy_follow_location_set, 1);
2868
3285
  rb_define_method(cCurlEasy, "follow_location?", ruby_curl_easy_follow_location_q, 0);
3286
+ rb_define_method(cCurlEasy, "autoreferer=", ruby_curl_easy_autoreferer_set, 1);
2869
3287
  rb_define_method(cCurlEasy, "unrestricted_auth=", ruby_curl_easy_unrestricted_auth_set, 1);
2870
3288
  rb_define_method(cCurlEasy, "unrestricted_auth?", ruby_curl_easy_unrestricted_auth_q, 0);
2871
3289
  rb_define_method(cCurlEasy, "verbose=", ruby_curl_easy_verbose_set, 1);
@@ -2884,6 +3302,7 @@ void init_curb_easy() {
2884
3302
  rb_define_method(cCurlEasy, "on_complete", ruby_curl_easy_on_complete_set, -1);
2885
3303
 
2886
3304
  rb_define_method(cCurlEasy, "perform", ruby_curl_easy_perform, 0);
3305
+ rb_define_method(cCurlEasy, "http", ruby_curl_easy_perform_verb, 1);
2887
3306
  rb_define_method(cCurlEasy, "http_delete", ruby_curl_easy_perform_delete, 0);
2888
3307
  rb_define_method(cCurlEasy, "http_get", ruby_curl_easy_perform_get, 0);
2889
3308
  rb_define_method(cCurlEasy, "http_post", ruby_curl_easy_perform_post, -1);
@@ -2891,6 +3310,11 @@ void init_curb_easy() {
2891
3310
  rb_define_method(cCurlEasy, "http_put", ruby_curl_easy_perform_put, 1);
2892
3311
  rb_define_method(cCurlEasy, "head=", ruby_curl_easy_set_head_option, 1);
2893
3312
  rb_define_method(cCurlEasy, "delete=", ruby_curl_easy_set_delete_option, 1);
3313
+ rb_define_method(cCurlEasy, "version=", ruby_curl_easy_set_version, 1);
3314
+ rb_define_const(mCurl, "HTTP_1_1", LONG2NUM(CURL_HTTP_VERSION_1_1));
3315
+ rb_define_const(mCurl, "HTTP_1_0", LONG2NUM(CURL_HTTP_VERSION_1_0));
3316
+ rb_define_const(mCurl, "HTTP_NONE", LONG2NUM(CURL_HTTP_VERSION_NONE));
3317
+ rb_define_method(cCurlEasy, "nosignal=", ruby_curl_easy_set_nosignal, 1);
2894
3318
 
2895
3319
  /* Post-perform info methods */
2896
3320
  rb_define_method(cCurlEasy, "body_str", ruby_curl_easy_body_str_get, 0);
@@ -2898,6 +3322,9 @@ void init_curb_easy() {
2898
3322
 
2899
3323
  rb_define_method(cCurlEasy, "last_effective_url", ruby_curl_easy_last_effective_url_get, 0);
2900
3324
  rb_define_method(cCurlEasy, "response_code", ruby_curl_easy_response_code_get, 0);
3325
+ #if defined(HAVE_CURLINFO_PRIMARY_IP)
3326
+ rb_define_method(cCurlEasy, "primary_ip", ruby_curl_easy_primary_ip_get, 0);
3327
+ #endif
2901
3328
  rb_define_method(cCurlEasy, "http_connect_code", ruby_curl_easy_http_connect_code_get, 0);
2902
3329
  rb_define_method(cCurlEasy, "file_time", ruby_curl_easy_file_time_get, 0);
2903
3330
  rb_define_method(cCurlEasy, "total_time", ruby_curl_easy_total_time_get, 0);
@@ -2920,7 +3347,9 @@ void init_curb_easy() {
2920
3347
  rb_define_method(cCurlEasy, "os_errno", ruby_curl_easy_os_errno_get, 0);
2921
3348
  rb_define_method(cCurlEasy, "num_connects", ruby_curl_easy_num_connects_get, 0);
2922
3349
  rb_define_method(cCurlEasy, "ftp_entry_path", ruby_curl_easy_ftp_entry_path_get, 0);
2923
- rb_define_method(cCurlEasy, "inspect", ruby_curl_easy_inspect, 0);
3350
+
3351
+ rb_define_method(cCurlEasy, "close", ruby_curl_easy_close, 0);
3352
+ rb_define_method(cCurlEasy, "reset", ruby_curl_easy_reset, 0);
2924
3353
 
2925
3354
  /* Curl utils */
2926
3355
  rb_define_method(cCurlEasy, "escape", ruby_curl_easy_escape, 1);
@@ -2929,4 +3358,5 @@ void init_curb_easy() {
2929
3358
  /* Runtime support */
2930
3359
  rb_define_method(cCurlEasy, "clone", ruby_curl_easy_clone, 0);
2931
3360
  rb_define_alias(cCurlEasy, "dup", "clone");
3361
+ rb_define_method(cCurlEasy, "inspect", ruby_curl_easy_inspect, 0);
2932
3362
  }