ghazel-curb 0.5.9.0

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