curb 0.1.4 → 0.7.15

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