gus-curb 0.8.7

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