fotonauts-curb 0.7.7

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