curb 0.9.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.markdown +76 -21
- data/Rakefile +33 -20
- data/ext/banned.h +32 -0
- data/ext/curb.c +186 -14
- data/ext/curb.h +18 -5
- data/ext/curb_easy.c +493 -84
- data/ext/curb_easy.h +7 -0
- data/ext/curb_errors.c +86 -0
- data/ext/curb_multi.c +141 -218
- data/ext/curb_multi.h +0 -1
- data/ext/curb_postfield.c +7 -7
- data/ext/extconf.rb +74 -6
- data/lib/curb.rb +1 -0
- data/lib/curl/easy.rb +16 -9
- data/lib/curl/multi.rb +52 -13
- data/lib/curl.rb +20 -12
- data/tests/bug_issue277.rb +32 -0
- data/tests/helper.rb +96 -13
- data/tests/tc_curl.rb +31 -1
- data/tests/tc_curl_download.rb +3 -3
- data/tests/tc_curl_easy.rb +163 -42
- data/tests/tc_curl_easy_resolve.rb +16 -0
- data/tests/tc_curl_maxfilesize.rb +12 -0
- data/tests/tc_curl_multi.rb +118 -15
- data/tests/tc_curl_postfield.rb +29 -29
- data/tests/tc_curl_protocols.rb +37 -0
- data/tests/timeout.rb +21 -5
- metadata +33 -25
data/ext/curb_easy.c
CHANGED
@@ -25,12 +25,18 @@ static VALUE rbstrAmp;
|
|
25
25
|
|
26
26
|
VALUE cCurlEasy;
|
27
27
|
|
28
|
+
// for Ruby 1.8
|
29
|
+
#ifndef HAVE_RB_IO_STDIO_FILE
|
30
|
+
static FILE * rb_io_stdio_file(rb_io_t *fptr) {
|
31
|
+
return fptr->f;
|
32
|
+
}
|
33
|
+
#endif
|
28
34
|
|
29
35
|
/* ================== CURL HANDLER FUNCS ==============*/
|
30
36
|
|
31
37
|
static VALUE callback_exception(VALUE unused) {
|
32
38
|
return Qfalse;
|
33
|
-
}
|
39
|
+
}
|
34
40
|
|
35
41
|
/* These handle both body and header data */
|
36
42
|
static size_t default_data_handler(char *stream,
|
@@ -223,12 +229,31 @@ static void ruby_curl_easy_free(ruby_curl_easy *rbce) {
|
|
223
229
|
curl_slist_free_all(rbce->curl_headers);
|
224
230
|
}
|
225
231
|
|
232
|
+
if (rbce->curl_proxy_headers) {
|
233
|
+
curl_slist_free_all(rbce->curl_proxy_headers);
|
234
|
+
}
|
235
|
+
|
226
236
|
if (rbce->curl_ftp_commands) {
|
227
237
|
curl_slist_free_all(rbce->curl_ftp_commands);
|
228
238
|
}
|
229
239
|
|
240
|
+
if (rbce->curl_resolve) {
|
241
|
+
curl_slist_free_all(rbce->curl_resolve);
|
242
|
+
}
|
243
|
+
|
230
244
|
if (rbce->curl) {
|
245
|
+
/* disable any progress or debug events */
|
246
|
+
curl_easy_setopt(rbce->curl, CURLOPT_WRITEFUNCTION, NULL);
|
247
|
+
curl_easy_setopt(rbce->curl, CURLOPT_WRITEDATA, NULL);
|
248
|
+
curl_easy_setopt(rbce->curl, CURLOPT_HEADERFUNCTION, NULL);
|
249
|
+
curl_easy_setopt(rbce->curl, CURLOPT_HEADERDATA, NULL);
|
250
|
+
curl_easy_setopt(rbce->curl, CURLOPT_DEBUGFUNCTION, NULL);
|
251
|
+
curl_easy_setopt(rbce->curl, CURLOPT_DEBUGDATA, NULL);
|
252
|
+
curl_easy_setopt(rbce->curl, CURLOPT_VERBOSE, 0);
|
253
|
+
curl_easy_setopt(rbce->curl, CURLOPT_PROGRESSFUNCTION, NULL);
|
254
|
+
curl_easy_setopt(rbce->curl, CURLOPT_NOPROGRESS, 1);
|
231
255
|
curl_easy_cleanup(rbce->curl);
|
256
|
+
rbce->curl = NULL;
|
232
257
|
}
|
233
258
|
}
|
234
259
|
|
@@ -243,8 +268,12 @@ void curl_easy_free(ruby_curl_easy *rbce) {
|
|
243
268
|
static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
244
269
|
rbce->opts = rb_hash_new();
|
245
270
|
|
271
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
272
|
+
|
246
273
|
rbce->curl_headers = NULL;
|
274
|
+
rbce->curl_proxy_headers = NULL;
|
247
275
|
rbce->curl_ftp_commands = NULL;
|
276
|
+
rbce->curl_resolve = NULL;
|
248
277
|
|
249
278
|
/* various-typed opts */
|
250
279
|
rbce->local_port = 0;
|
@@ -262,6 +291,8 @@ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
|
262
291
|
rbce->ftp_response_timeout = 0;
|
263
292
|
rbce->low_speed_limit = 0;
|
264
293
|
rbce->low_speed_time = 0;
|
294
|
+
rbce->max_send_speed_large = 0;
|
295
|
+
rbce->max_recv_speed_large = 0;
|
265
296
|
rbce->ssl_version = -1;
|
266
297
|
rbce->use_ssl = -1;
|
267
298
|
rbce->ftp_filemethod = -1;
|
@@ -283,25 +314,37 @@ static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
|
283
314
|
rbce->callback_active = 0;
|
284
315
|
}
|
285
316
|
|
317
|
+
/*
|
318
|
+
* Allocate space for a Curl::Easy instance.
|
319
|
+
*/
|
320
|
+
static VALUE ruby_curl_easy_allocate(VALUE klass) {
|
321
|
+
ruby_curl_easy *rbce;
|
322
|
+
rbce = ALLOC(ruby_curl_easy);
|
323
|
+
rbce->curl = NULL;
|
324
|
+
rbce->opts = Qnil;
|
325
|
+
rbce->multi = Qnil;
|
326
|
+
ruby_curl_easy_zero(rbce);
|
327
|
+
return Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
|
328
|
+
}
|
329
|
+
|
286
330
|
/*
|
287
331
|
* call-seq:
|
288
|
-
* Curl::Easy.new =>
|
289
|
-
* Curl::Easy.new(url = nil) =>
|
290
|
-
* Curl::Easy.new(url = nil) { |self| ... } =>
|
332
|
+
* Curl::Easy.new => #<Curl::Easy...>
|
333
|
+
* Curl::Easy.new(url = nil) => #<Curl::Easy...>
|
334
|
+
* Curl::Easy.new(url = nil) { |self| ... } => #<Curl::Easy...>
|
291
335
|
*
|
292
|
-
*
|
336
|
+
* Initialize a new Curl::Easy instance, optionally supplying the URL.
|
293
337
|
* The block form allows further configuration to be supplied before
|
294
338
|
* the instance is returned.
|
295
339
|
*/
|
296
|
-
static VALUE
|
340
|
+
static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
|
297
341
|
CURLcode ecode;
|
298
342
|
VALUE url, blk;
|
299
|
-
VALUE new_curl;
|
300
343
|
ruby_curl_easy *rbce;
|
301
344
|
|
302
345
|
rb_scan_args(argc, argv, "01&", &url, &blk);
|
303
346
|
|
304
|
-
|
347
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
305
348
|
|
306
349
|
/* handler */
|
307
350
|
rbce->curl = curl_easy_init();
|
@@ -309,32 +352,32 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
|
|
309
352
|
rb_raise(eCurlErrFailedInit, "Failed to initialize easy handle");
|
310
353
|
}
|
311
354
|
|
312
|
-
new_curl = Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
|
313
|
-
|
314
355
|
rbce->multi = Qnil;
|
315
356
|
rbce->opts = Qnil;
|
316
357
|
|
317
358
|
ruby_curl_easy_zero(rbce);
|
318
359
|
|
360
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
361
|
+
|
319
362
|
rb_easy_set("url", url);
|
320
363
|
|
321
|
-
/* set the
|
322
|
-
ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)
|
364
|
+
/* set the pointer to the curl handle */
|
365
|
+
ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
|
323
366
|
if (ecode != CURLE_OK) {
|
324
367
|
raise_curl_easy_error_exception(ecode);
|
325
368
|
}
|
326
369
|
|
327
370
|
if (blk != Qnil) {
|
328
|
-
rb_funcall(blk, idCall, 1,
|
371
|
+
rb_funcall(blk, idCall, 1, self);
|
329
372
|
}
|
330
373
|
|
331
|
-
return
|
374
|
+
return self;
|
332
375
|
}
|
333
376
|
|
334
377
|
/*
|
335
378
|
* call-seq:
|
336
|
-
* easy.clone =>
|
337
|
-
* easy.dup =>
|
379
|
+
* easy.clone => <easy clone>
|
380
|
+
* easy.dup => <easy clone>
|
338
381
|
*
|
339
382
|
* Clone this Curl::Easy instance, creating a new instance.
|
340
383
|
* This method duplicates the underlying CURL* handle.
|
@@ -348,7 +391,11 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
348
391
|
memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
|
349
392
|
newrbce->curl = curl_easy_duphandle(rbce->curl);
|
350
393
|
newrbce->curl_headers = NULL;
|
394
|
+
newrbce->curl_proxy_headers = NULL;
|
351
395
|
newrbce->curl_ftp_commands = NULL;
|
396
|
+
newrbce->curl_resolve = NULL;
|
397
|
+
|
398
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
352
399
|
|
353
400
|
return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
|
354
401
|
}
|
@@ -358,7 +405,7 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
358
405
|
* easy.close => nil
|
359
406
|
*
|
360
407
|
* Close the Curl::Easy instance. Any open connections are closed
|
361
|
-
* The easy handle is reinitialized. If a previous multi handle was
|
408
|
+
* The easy handle is reinitialized. If a previous multi handle was
|
362
409
|
* open it is set to nil and will be cleared after a GC.
|
363
410
|
*/
|
364
411
|
static VALUE ruby_curl_easy_close(VALUE self) {
|
@@ -419,7 +466,9 @@ static VALUE ruby_curl_easy_reset(VALUE self) {
|
|
419
466
|
curl_easy_reset(rbce->curl);
|
420
467
|
ruby_curl_easy_zero(rbce);
|
421
468
|
|
422
|
-
|
469
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
470
|
+
|
471
|
+
/* reset clobbers the private setting, so reset it to self */
|
423
472
|
ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
|
424
473
|
if (ecode != CURLE_OK) {
|
425
474
|
raise_curl_easy_error_exception(ecode);
|
@@ -431,6 +480,12 @@ static VALUE ruby_curl_easy_reset(VALUE self) {
|
|
431
480
|
rbce->curl_headers = NULL;
|
432
481
|
}
|
433
482
|
|
483
|
+
/* Free everything up */
|
484
|
+
if (rbce->curl_proxy_headers) {
|
485
|
+
curl_slist_free_all(rbce->curl_proxy_headers);
|
486
|
+
rbce->curl_proxy_headers = NULL;
|
487
|
+
}
|
488
|
+
|
434
489
|
return opts_dup;
|
435
490
|
}
|
436
491
|
|
@@ -483,6 +538,10 @@ static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
|
|
483
538
|
CURB_OBJECT_HSETTER(ruby_curl_easy, headers);
|
484
539
|
}
|
485
540
|
|
541
|
+
static VALUE ruby_curl_easy_proxy_headers_set(VALUE self, VALUE proxy_headers) {
|
542
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, proxy_headers);
|
543
|
+
}
|
544
|
+
|
486
545
|
/*
|
487
546
|
* call-seq:
|
488
547
|
* easy.headers => Hash, Array or Str
|
@@ -493,11 +552,46 @@ static VALUE ruby_curl_easy_headers_get(VALUE self) {
|
|
493
552
|
ruby_curl_easy *rbce;
|
494
553
|
VALUE headers;
|
495
554
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
496
|
-
headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
|
555
|
+
headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
|
497
556
|
if (headers == Qnil) { headers = rb_easy_set("headers", rb_hash_new()); }
|
498
557
|
return headers;
|
499
558
|
}
|
500
559
|
|
560
|
+
/*
|
561
|
+
* call-seq:
|
562
|
+
* easy.proxy_headers = "Header: val" => "Header: val"
|
563
|
+
* easy.proxy_headers = {"Header" => "val" ..., "Header" => "val"} => {"Header: val", ...}
|
564
|
+
* easy.proxy_headers = ["Header: val" ..., "Header: val"] => ["Header: val", ...]
|
565
|
+
*
|
566
|
+
*
|
567
|
+
* For example to set a standard or custom header:
|
568
|
+
*
|
569
|
+
* easy.proxy_headers["MyHeader"] = "myval"
|
570
|
+
*
|
571
|
+
* To remove a standard header (this is useful when removing libcurls default
|
572
|
+
* 'Expect: 100-Continue' header when using HTTP form posts):
|
573
|
+
*
|
574
|
+
* easy.proxy_headers["Expect"] = ''
|
575
|
+
*
|
576
|
+
* Anything passed to libcurl as a header will be converted to a string during
|
577
|
+
* the perform step.
|
578
|
+
*/
|
579
|
+
|
580
|
+
/*
|
581
|
+
* call-seq:
|
582
|
+
* easy.proxy_headers => Hash, Array or Str
|
583
|
+
*
|
584
|
+
* Obtain the custom HTTP proxy_headers for following requests.
|
585
|
+
*/
|
586
|
+
static VALUE ruby_curl_easy_proxy_headers_get(VALUE self) {
|
587
|
+
ruby_curl_easy *rbce;
|
588
|
+
VALUE proxy_headers;
|
589
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
590
|
+
proxy_headers = rb_easy_get("proxy_headers");//rb_hash_aref(rbce->opts, rb_intern("proxy_headers"));
|
591
|
+
if (proxy_headers == Qnil) { proxy_headers = rb_easy_set("proxy_headers", rb_hash_new()); }
|
592
|
+
return proxy_headers;
|
593
|
+
}
|
594
|
+
|
501
595
|
/*
|
502
596
|
* call-seq:
|
503
597
|
* easy.interface => string
|
@@ -705,29 +799,29 @@ static VALUE ruby_curl_easy_useragent_get(VALUE self) {
|
|
705
799
|
/*
|
706
800
|
* call-seq:
|
707
801
|
* easy.post_body = "some=form%20data&to=send" => string or nil
|
708
|
-
*
|
802
|
+
*
|
709
803
|
* Sets the POST body of this Curl::Easy instance. This is expected to be
|
710
804
|
* URL encoded; no additional processing or encoding is done on the string.
|
711
805
|
* The content-type header will be set to application/x-www-form-urlencoded.
|
712
|
-
*
|
806
|
+
*
|
713
807
|
* This is handy if you want to perform a POST against a Curl::Multi instance.
|
714
808
|
*/
|
715
809
|
static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
|
716
810
|
ruby_curl_easy *rbce;
|
717
811
|
CURL *curl;
|
718
|
-
|
812
|
+
|
719
813
|
char *data;
|
720
814
|
long len;
|
721
815
|
|
722
816
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
723
|
-
|
817
|
+
|
724
818
|
curl = rbce->curl;
|
725
|
-
|
819
|
+
|
726
820
|
if ( post_body == Qnil ) {
|
727
821
|
rb_easy_del("postdata_buffer");
|
728
822
|
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
729
|
-
|
730
|
-
} else {
|
823
|
+
|
824
|
+
} else {
|
731
825
|
if (rb_type(post_body) == T_STRING) {
|
732
826
|
data = StringValuePtr(post_body);
|
733
827
|
len = RSTRING_LEN(post_body);
|
@@ -740,19 +834,19 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
|
|
740
834
|
else {
|
741
835
|
rb_raise(rb_eRuntimeError, "post data must respond_to .to_s");
|
742
836
|
}
|
743
|
-
|
744
|
-
// Store the string, since it has to hang around for the duration of the
|
837
|
+
|
838
|
+
// Store the string, since it has to hang around for the duration of the
|
745
839
|
// request. See CURLOPT_POSTFIELDS in the libcurl docs.
|
746
840
|
//rbce->postdata_buffer = post_body;
|
747
841
|
rb_easy_set("postdata_buffer", post_body);
|
748
|
-
|
842
|
+
|
749
843
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
750
844
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
|
751
845
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
|
752
|
-
|
846
|
+
|
753
847
|
return post_body;
|
754
848
|
}
|
755
|
-
|
849
|
+
|
756
850
|
return Qnil;
|
757
851
|
}
|
758
852
|
|
@@ -769,7 +863,7 @@ static VALUE ruby_curl_easy_post_body_get(VALUE self) {
|
|
769
863
|
/*
|
770
864
|
* call-seq:
|
771
865
|
* easy.put_data = data => ""
|
772
|
-
*
|
866
|
+
*
|
773
867
|
* Points this Curl::Easy instance to data to be uploaded via PUT. This
|
774
868
|
* sets the request to a PUT type request - useful if you want to PUT via
|
775
869
|
* a multi handle.
|
@@ -801,7 +895,7 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
|
|
801
895
|
curl_easy_setopt(curl, CURLOPT_SEEKDATA, rbce);
|
802
896
|
#endif
|
803
897
|
|
804
|
-
/*
|
898
|
+
/*
|
805
899
|
* we need to set specific headers for the PUT to work... so
|
806
900
|
* convert the internal headers structure to a HASH if one is set
|
807
901
|
*/
|
@@ -815,7 +909,7 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
|
|
815
909
|
if (NIL_P(data)) { return data; }
|
816
910
|
|
817
911
|
headers = rb_easy_get("headers");
|
818
|
-
if( headers == Qnil ) {
|
912
|
+
if( headers == Qnil ) {
|
819
913
|
headers = rb_hash_new();
|
820
914
|
}
|
821
915
|
|
@@ -863,13 +957,32 @@ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
|
|
863
957
|
}
|
864
958
|
|
865
959
|
/*
|
866
|
-
* call-seq
|
960
|
+
* call-seq:
|
867
961
|
* easy.ftp_commands => array or nil
|
868
962
|
*/
|
869
963
|
static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
|
870
964
|
CURB_OBJECT_HGETTER(ruby_curl_easy, ftp_commands);
|
871
965
|
}
|
872
966
|
|
967
|
+
/*
|
968
|
+
* call-seq:
|
969
|
+
* easy.resolve = [ "example.com:80:127.0.0.1" ] => [ "example.com:80:127.0.0.1" ]
|
970
|
+
*
|
971
|
+
* Set the resolve list to statically resolve hostnames to IP addresses,
|
972
|
+
* bypassing DNS for matching hostname/port combinations.
|
973
|
+
*/
|
974
|
+
static VALUE ruby_curl_easy_resolve_set(VALUE self, VALUE resolve) {
|
975
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, resolve);
|
976
|
+
}
|
977
|
+
|
978
|
+
/*
|
979
|
+
* call-seq:
|
980
|
+
* easy.resolve => array or nil
|
981
|
+
*/
|
982
|
+
static VALUE ruby_curl_easy_resolve_get(VALUE self) {
|
983
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, resolve);
|
984
|
+
}
|
985
|
+
|
873
986
|
/* ================== IMMED ATTRS ==================*/
|
874
987
|
|
875
988
|
/*
|
@@ -980,7 +1093,7 @@ static VALUE ruby_curl_easy_proxy_type_get(VALUE self) {
|
|
980
1093
|
(!strncmp("ntlm",node,4)) ? CURLAUTH_NTLM : \
|
981
1094
|
(!strncmp("anysafe",node,7)) ? CURLAUTH_ANYSAFE : \
|
982
1095
|
(!strncmp("any",node,3)) ? CURLAUTH_ANY : 0
|
983
|
-
#else
|
1096
|
+
#else
|
984
1097
|
#define CURL_HTTPAUTH_STR_TO_NUM(node) \
|
985
1098
|
(!strncmp("basic",node,5)) ? CURLAUTH_BASIC : \
|
986
1099
|
(!strncmp("digest",node,6)) ? CURLAUTH_DIGEST : \
|
@@ -1012,7 +1125,7 @@ static VALUE ruby_curl_easy_http_auth_types_set(int argc, VALUE *argv, VALUE sel
|
|
1012
1125
|
|
1013
1126
|
if (len == 1 && (rb_ary_entry(args_ary,0) == Qnil || TYPE(rb_ary_entry(args_ary,0)) == T_FIXNUM ||
|
1014
1127
|
TYPE(rb_ary_entry(args_ary,0)) == T_BIGNUM)) {
|
1015
|
-
if (rb_ary_entry(args_ary,0) == Qnil) {
|
1128
|
+
if (rb_ary_entry(args_ary,0) == Qnil) {
|
1016
1129
|
rbce->http_auth_types = 0;
|
1017
1130
|
}
|
1018
1131
|
else {
|
@@ -1094,7 +1207,7 @@ static VALUE ruby_curl_easy_max_redirects_get(VALUE self) {
|
|
1094
1207
|
|
1095
1208
|
/*
|
1096
1209
|
* call-seq:
|
1097
|
-
* easy.timeout = fixnum or nil
|
1210
|
+
* easy.timeout = float, fixnum or nil => numeric
|
1098
1211
|
*
|
1099
1212
|
* Set the maximum time in seconds that you allow the libcurl transfer
|
1100
1213
|
* operation to take. Normally, name lookups can take a considerable time
|
@@ -1103,20 +1216,39 @@ static VALUE ruby_curl_easy_max_redirects_get(VALUE self) {
|
|
1103
1216
|
*
|
1104
1217
|
* Set to nil (or zero) to disable timeout (it will then only timeout
|
1105
1218
|
* on the system's internal timeouts).
|
1219
|
+
*
|
1220
|
+
* Uses timeout_ms internally instead of timeout because it allows for
|
1221
|
+
* better precision and libcurl will use the last set value when both
|
1222
|
+
* timeout and timeout_ms are set.
|
1223
|
+
*
|
1106
1224
|
*/
|
1107
|
-
static VALUE ruby_curl_easy_timeout_set(VALUE self, VALUE
|
1108
|
-
|
1225
|
+
static VALUE ruby_curl_easy_timeout_set(VALUE self, VALUE timeout_s) {
|
1226
|
+
ruby_curl_easy *rbce;
|
1227
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
1228
|
+
|
1229
|
+
if (Qnil == timeout_s || NUM2DBL(timeout_s) <= 0.0) {
|
1230
|
+
rbce->timeout_ms = 0;
|
1231
|
+
} else {
|
1232
|
+
rbce->timeout_ms = (unsigned long)(NUM2DBL(timeout_s) * 1000);
|
1233
|
+
}
|
1234
|
+
|
1235
|
+
return DBL2NUM(rbce->timeout_ms / 1000.0);
|
1109
1236
|
}
|
1110
1237
|
|
1111
1238
|
/*
|
1112
1239
|
* call-seq:
|
1113
|
-
* easy.timeout =>
|
1240
|
+
* easy.timeout => numeric
|
1114
1241
|
*
|
1115
1242
|
* Obtain the maximum time in seconds that you allow the libcurl transfer
|
1116
1243
|
* operation to take.
|
1244
|
+
*
|
1245
|
+
* Uses timeout_ms internally instead of timeout.
|
1246
|
+
*
|
1117
1247
|
*/
|
1118
|
-
static VALUE ruby_curl_easy_timeout_get(VALUE self
|
1119
|
-
|
1248
|
+
static VALUE ruby_curl_easy_timeout_get(VALUE self) {
|
1249
|
+
ruby_curl_easy *rbce;
|
1250
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
1251
|
+
return DBL2NUM(rbce->timeout_ms / 1000.0);
|
1120
1252
|
}
|
1121
1253
|
|
1122
1254
|
/*
|
@@ -1132,7 +1264,16 @@ static VALUE ruby_curl_easy_timeout_get(VALUE self, VALUE timeout) {
|
|
1132
1264
|
* on the system's internal timeouts).
|
1133
1265
|
*/
|
1134
1266
|
static VALUE ruby_curl_easy_timeout_ms_set(VALUE self, VALUE timeout_ms) {
|
1135
|
-
|
1267
|
+
ruby_curl_easy *rbce;
|
1268
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
1269
|
+
|
1270
|
+
if (Qnil == timeout_ms || NUM2DBL(timeout_ms) <= 0.0) {
|
1271
|
+
rbce->timeout_ms = 0;
|
1272
|
+
} else {
|
1273
|
+
rbce->timeout_ms = NUM2ULONG(timeout_ms);
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
return ULONG2NUM(rbce->timeout_ms);
|
1136
1277
|
}
|
1137
1278
|
|
1138
1279
|
/*
|
@@ -1142,8 +1283,10 @@ static VALUE ruby_curl_easy_timeout_ms_set(VALUE self, VALUE timeout_ms) {
|
|
1142
1283
|
* Obtain the maximum time in milliseconds that you allow the libcurl transfer
|
1143
1284
|
* operation to take.
|
1144
1285
|
*/
|
1145
|
-
static VALUE ruby_curl_easy_timeout_ms_get(VALUE self
|
1146
|
-
|
1286
|
+
static VALUE ruby_curl_easy_timeout_ms_get(VALUE self) {
|
1287
|
+
ruby_curl_easy *rbce;
|
1288
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
1289
|
+
return LONG2NUM(rbce->timeout_ms);
|
1147
1290
|
}
|
1148
1291
|
|
1149
1292
|
/*
|
@@ -1293,6 +1436,46 @@ static VALUE ruby_curl_easy_low_speed_time_get(VALUE self, VALUE low_speed_time)
|
|
1293
1436
|
CURB_IMMED_GETTER(ruby_curl_easy, low_speed_time, 0);
|
1294
1437
|
}
|
1295
1438
|
|
1439
|
+
/*
|
1440
|
+
* call-seq:
|
1441
|
+
* easy.max_send_speed_large = fixnum or nil => fixnum or nil
|
1442
|
+
*
|
1443
|
+
* Set the maximal sending transfer speed (in bytes per second)
|
1444
|
+
*/
|
1445
|
+
static VALUE ruby_curl_easy_max_send_speed_large_set(VALUE self, VALUE max_send_speed_large) {
|
1446
|
+
CURB_IMMED_SETTER(ruby_curl_easy, max_send_speed_large, 0);
|
1447
|
+
}
|
1448
|
+
|
1449
|
+
/*
|
1450
|
+
* call-seq:
|
1451
|
+
* easy.max_send_speed_large = fixnum or nil => fixnum or nil
|
1452
|
+
*
|
1453
|
+
* Get the maximal sending transfer speed (in bytes per second)
|
1454
|
+
*/
|
1455
|
+
static VALUE ruby_curl_easy_max_send_speed_large_get(VALUE self, VALUE max_send_speed_large) {
|
1456
|
+
CURB_IMMED_GETTER(ruby_curl_easy, max_send_speed_large, 0);
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
/*
|
1460
|
+
* call-seq:
|
1461
|
+
* easy.max_recv_speed_large = fixnum or nil => fixnum or nil
|
1462
|
+
*
|
1463
|
+
* Set the maximal receiving transfer speed (in bytes per second)
|
1464
|
+
*/
|
1465
|
+
static VALUE ruby_curl_easy_max_recv_speed_large_set(VALUE self, VALUE max_recv_speed_large) {
|
1466
|
+
CURB_IMMED_SETTER(ruby_curl_easy, max_recv_speed_large, 0);
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
/*
|
1470
|
+
* call-seq:
|
1471
|
+
* easy.max_recv_speed_large = fixnum or nil => fixnum or nil
|
1472
|
+
*
|
1473
|
+
* Get the maximal receiving transfer speed (in bytes per second)
|
1474
|
+
*/
|
1475
|
+
static VALUE ruby_curl_easy_max_recv_speed_large_get(VALUE self, VALUE max_recv_speed_large) {
|
1476
|
+
CURB_IMMED_GETTER(ruby_curl_easy, max_recv_speed_large, 0);
|
1477
|
+
}
|
1478
|
+
|
1296
1479
|
/*
|
1297
1480
|
* call-seq:
|
1298
1481
|
* easy.username = string => string
|
@@ -1310,7 +1493,7 @@ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
|
|
1310
1493
|
/*
|
1311
1494
|
* call-seq:
|
1312
1495
|
* easy.username => string
|
1313
|
-
*
|
1496
|
+
*
|
1314
1497
|
* Get the current username
|
1315
1498
|
*/
|
1316
1499
|
static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
|
@@ -1338,7 +1521,7 @@ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
|
|
1338
1521
|
/*
|
1339
1522
|
* call-seq:
|
1340
1523
|
* easy.password => string
|
1341
|
-
*
|
1524
|
+
*
|
1342
1525
|
* Get the current password
|
1343
1526
|
*/
|
1344
1527
|
static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
|
@@ -1363,6 +1546,7 @@ static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
|
|
1363
1546
|
* Curl::CURL_SSLVERSION_TLSv1_0
|
1364
1547
|
* Curl::CURL_SSLVERSION_TLSv1_1
|
1365
1548
|
* Curl::CURL_SSLVERSION_TLSv1_2
|
1549
|
+
* Curl::CURL_SSLVERSION_TLSv1_3
|
1366
1550
|
*/
|
1367
1551
|
static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
|
1368
1552
|
CURB_IMMED_SETTER(ruby_curl_easy, ssl_version, -1);
|
@@ -1381,7 +1565,7 @@ static VALUE ruby_curl_easy_ssl_version_get(VALUE self, VALUE ssl_version) {
|
|
1381
1565
|
/*
|
1382
1566
|
* call-seq:
|
1383
1567
|
* easy.use_ssl = value => fixnum or nil
|
1384
|
-
*
|
1568
|
+
*
|
1385
1569
|
* Ensure libcurl uses SSL for FTP connections. Valid options are Curl::CURL_USESSL_NONE,
|
1386
1570
|
* Curl::CURL_USESSL_TRY, Curl::CURL_USESSL_CONTROL, and Curl::CURL_USESSL_ALL.
|
1387
1571
|
*/
|
@@ -1411,7 +1595,7 @@ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod)
|
|
1411
1595
|
}
|
1412
1596
|
|
1413
1597
|
/*
|
1414
|
-
* call-seq
|
1598
|
+
* call-seq:
|
1415
1599
|
* easy.ftp_filemethod => fixnum
|
1416
1600
|
*
|
1417
1601
|
* Get the configuration for how libcurl will reach files on the server.
|
@@ -1783,7 +1967,7 @@ static VALUE ruby_curl_easy_resolve_mode_set(VALUE self, VALUE resolve_mode) {
|
|
1783
1967
|
|
1784
1968
|
/*
|
1785
1969
|
* call-seq:
|
1786
|
-
* easy.on_body { |body_data| ... } =>
|
1970
|
+
* easy.on_body { |body_data| ... } => <old handler>
|
1787
1971
|
*
|
1788
1972
|
* Assign or remove the +on_body+ handler for this Curl::Easy instance.
|
1789
1973
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1802,7 +1986,7 @@ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
|
|
1802
1986
|
|
1803
1987
|
/*
|
1804
1988
|
* call-seq:
|
1805
|
-
* easy.on_success { |easy| ... } =>
|
1989
|
+
* easy.on_success { |easy| ... } => <old handler>
|
1806
1990
|
*
|
1807
1991
|
* Assign or remove the +on_success+ handler for this Curl::Easy instance.
|
1808
1992
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1817,7 +2001,7 @@ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
|
|
1817
2001
|
|
1818
2002
|
/*
|
1819
2003
|
* call-seq:
|
1820
|
-
* easy.on_failure {|easy,code| ... } =>
|
2004
|
+
* easy.on_failure {|easy,code| ... } => <old handler>
|
1821
2005
|
*
|
1822
2006
|
* Assign or remove the +on_failure+ handler for this Curl::Easy instance.
|
1823
2007
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1832,13 +2016,13 @@ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
|
|
1832
2016
|
|
1833
2017
|
/*
|
1834
2018
|
* call-seq:
|
1835
|
-
* easy.on_missing {|easy,code| ... } =>
|
2019
|
+
* easy.on_missing {|easy,code| ... } => <old handler;>
|
1836
2020
|
*
|
1837
2021
|
* Assign or remove the on_missing handler for this Curl::Easy instance.
|
1838
2022
|
* To remove a previously-supplied handler, call this method with no attached
|
1839
2023
|
* block.
|
1840
2024
|
*
|
1841
|
-
* The +on_missing+ handler is called when request is finished with a
|
2025
|
+
* The +on_missing+ handler is called when request is finished with a
|
1842
2026
|
* status of 40x
|
1843
2027
|
*/
|
1844
2028
|
static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
|
@@ -1847,13 +2031,13 @@ static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
|
|
1847
2031
|
|
1848
2032
|
/*
|
1849
2033
|
* call-seq:
|
1850
|
-
* easy.on_redirect {|easy,code| ... } =>
|
2034
|
+
* easy.on_redirect {|easy,code| ... } => <old handler;>
|
1851
2035
|
*
|
1852
2036
|
* Assign or remove the on_redirect handler for this Curl::Easy instance.
|
1853
2037
|
* To remove a previously-supplied handler, call this method with no attached
|
1854
2038
|
* block.
|
1855
2039
|
*
|
1856
|
-
* The +on_redirect+ handler is called when request is finished with a
|
2040
|
+
* The +on_redirect+ handler is called when request is finished with a
|
1857
2041
|
* status of 30x
|
1858
2042
|
*/
|
1859
2043
|
static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
|
@@ -1862,7 +2046,7 @@ static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
|
|
1862
2046
|
|
1863
2047
|
/*
|
1864
2048
|
* call-seq:
|
1865
|
-
* easy.on_complete {|easy| ... } =>
|
2049
|
+
* easy.on_complete {|easy| ... } => <old handler>
|
1866
2050
|
*
|
1867
2051
|
* Assign or remove the +on_complete+ handler for this Curl::Easy instance.
|
1868
2052
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1876,7 +2060,7 @@ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
|
|
1876
2060
|
|
1877
2061
|
/*
|
1878
2062
|
* call-seq:
|
1879
|
-
* easy.on_header { |header_data| ... } =>
|
2063
|
+
* easy.on_header { |header_data| ... } => <old handler>
|
1880
2064
|
*
|
1881
2065
|
* Assign or remove the +on_header+ handler for this Curl::Easy instance.
|
1882
2066
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1892,7 +2076,7 @@ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
|
|
1892
2076
|
|
1893
2077
|
/*
|
1894
2078
|
* call-seq:
|
1895
|
-
* easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } =>
|
2079
|
+
* easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } => <old handler>
|
1896
2080
|
*
|
1897
2081
|
* Assign or remove the +on_progress+ handler for this Curl::Easy instance.
|
1898
2082
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1913,7 +2097,7 @@ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
|
|
1913
2097
|
|
1914
2098
|
/*
|
1915
2099
|
* call-seq:
|
1916
|
-
* easy.on_debug { |type, data| ... } =>
|
2100
|
+
* easy.on_debug { |type, data| ... } => <old handler>
|
1917
2101
|
*
|
1918
2102
|
* Assign or remove the +on_debug+ handler for this Curl::Easy instance.
|
1919
2103
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1952,11 +2136,14 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
|
|
1952
2136
|
|
1953
2137
|
name = rb_obj_as_string(rb_ary_entry(header, 0));
|
1954
2138
|
value = rb_obj_as_string(rb_ary_entry(header, 1));
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
2139
|
+
if (rb_str_strlen(value) == 0) { // removing the header e.g. Accept: with nothing trailing should remove it see: https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html
|
2140
|
+
header_str = rb_str_plus(name, rb_str_new2(":"));
|
2141
|
+
} else {
|
2142
|
+
// This is a bit inefficient, but we don't want to be modifying
|
2143
|
+
// the actual values in the original hash.
|
2144
|
+
header_str = rb_str_plus(name, rb_str_new2(": "));
|
2145
|
+
header_str = rb_str_plus(header_str, value);
|
2146
|
+
}
|
1960
2147
|
} else {
|
1961
2148
|
header_str = rb_obj_as_string(header);
|
1962
2149
|
}
|
@@ -1967,6 +2154,38 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
|
|
1967
2154
|
return header_str;
|
1968
2155
|
}
|
1969
2156
|
|
2157
|
+
/***********************************************
|
2158
|
+
* This is an rb_iterate callback used to set up http proxy headers.
|
2159
|
+
*/
|
2160
|
+
static VALUE cb_each_http_proxy_header(VALUE proxy_header, VALUE wrap) {
|
2161
|
+
struct curl_slist **list;
|
2162
|
+
VALUE proxy_header_str = Qnil;
|
2163
|
+
|
2164
|
+
Data_Get_Struct(wrap, struct curl_slist *, list);
|
2165
|
+
|
2166
|
+
//rb_p(proxy_header);
|
2167
|
+
|
2168
|
+
if (rb_type(proxy_header) == T_ARRAY) {
|
2169
|
+
// we're processing a hash, proxy header is [name, val]
|
2170
|
+
VALUE name, value;
|
2171
|
+
|
2172
|
+
name = rb_obj_as_string(rb_ary_entry(proxy_header, 0));
|
2173
|
+
value = rb_obj_as_string(rb_ary_entry(proxy_header, 1));
|
2174
|
+
|
2175
|
+
// This is a bit inefficient, but we don't want to be modifying
|
2176
|
+
// the actual values in the original hash.
|
2177
|
+
proxy_header_str = rb_str_plus(name, rb_str_new2(": "));
|
2178
|
+
proxy_header_str = rb_str_plus(proxy_header_str, value);
|
2179
|
+
} else {
|
2180
|
+
proxy_header_str = rb_obj_as_string(proxy_header);
|
2181
|
+
}
|
2182
|
+
|
2183
|
+
//rb_p(header_str);
|
2184
|
+
|
2185
|
+
*list = curl_slist_append(*list, StringValuePtr(proxy_header_str));
|
2186
|
+
return proxy_header_str;
|
2187
|
+
}
|
2188
|
+
|
1970
2189
|
/***********************************************
|
1971
2190
|
* This is an rb_iterate callback used to set up ftp commands.
|
1972
2191
|
*/
|
@@ -1981,6 +2200,20 @@ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap) {
|
|
1981
2200
|
return ftp_command_string;
|
1982
2201
|
}
|
1983
2202
|
|
2203
|
+
/***********************************************
|
2204
|
+
* This is an rb_iterate callback used to set up the resolve list.
|
2205
|
+
*/
|
2206
|
+
static VALUE cb_each_resolve(VALUE resolve, VALUE wrap) {
|
2207
|
+
struct curl_slist **list;
|
2208
|
+
VALUE resolve_string;
|
2209
|
+
Data_Get_Struct(wrap, struct curl_slist *, list);
|
2210
|
+
|
2211
|
+
resolve_string = rb_obj_as_string(resolve);
|
2212
|
+
*list = curl_slist_append(*list, StringValuePtr(resolve));
|
2213
|
+
|
2214
|
+
return resolve_string;
|
2215
|
+
}
|
2216
|
+
|
1984
2217
|
/***********************************************
|
1985
2218
|
*
|
1986
2219
|
* Setup a connection
|
@@ -1992,7 +2225,9 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
1992
2225
|
CURL *curl;
|
1993
2226
|
VALUE url, _url = rb_easy_get("url");
|
1994
2227
|
struct curl_slist **hdrs = &(rbce->curl_headers);
|
2228
|
+
struct curl_slist **phdrs = &(rbce->curl_proxy_headers);
|
1995
2229
|
struct curl_slist **cmds = &(rbce->curl_ftp_commands);
|
2230
|
+
struct curl_slist **rslv = &(rbce->curl_resolve);
|
1996
2231
|
|
1997
2232
|
curl = rbce->curl;
|
1998
2233
|
|
@@ -2001,7 +2236,6 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2001
2236
|
}
|
2002
2237
|
|
2003
2238
|
url = rb_check_string_type(_url);
|
2004
|
-
|
2005
2239
|
curl_easy_setopt(curl, CURLOPT_URL, StringValuePtr(url));
|
2006
2240
|
|
2007
2241
|
// network stuff and auth
|
@@ -2114,15 +2348,14 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2114
2348
|
|
2115
2349
|
curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, rbce->unrestricted_auth);
|
2116
2350
|
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
if (rbce->timeout_ms && rbce->timeout_ms > 0) {
|
2122
|
-
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, rbce->timeout_ms);
|
2123
|
-
}
|
2351
|
+
#if HAVE_CURLOPT_TIMEOUT_MS
|
2352
|
+
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, rbce->timeout_ms);
|
2353
|
+
#endif
|
2354
|
+
|
2124
2355
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, rbce->connect_timeout);
|
2356
|
+
#if HAVE_CURLOPT_CONNECTTIMEOUT_MS
|
2125
2357
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, rbce->connect_timeout_ms);
|
2358
|
+
#endif
|
2126
2359
|
curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, rbce->dns_cache_timeout);
|
2127
2360
|
|
2128
2361
|
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, rbce->ignore_content_length);
|
@@ -2141,6 +2374,9 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2141
2374
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, rbce->low_speed_limit);
|
2142
2375
|
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, rbce->low_speed_time);
|
2143
2376
|
|
2377
|
+
curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, rbce->max_recv_speed_large);
|
2378
|
+
curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, rbce->max_send_speed_large);
|
2379
|
+
|
2144
2380
|
// Set up localport / proxy port
|
2145
2381
|
// FIXME these won't get returned to default if they're unset Ruby
|
2146
2382
|
if (rbce->proxy_port > 0) {
|
@@ -2247,7 +2483,7 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2247
2483
|
rb_warn("libcurl is not configured with SSL support");
|
2248
2484
|
}
|
2249
2485
|
#endif
|
2250
|
-
|
2486
|
+
|
2251
2487
|
if (rbce->ftp_filemethod > 0) {
|
2252
2488
|
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, rbce->ftp_filemethod);
|
2253
2489
|
}
|
@@ -2274,6 +2510,25 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2274
2510
|
}
|
2275
2511
|
}
|
2276
2512
|
|
2513
|
+
#if HAVE_CURLOPT_PROXYHEADER
|
2514
|
+
/* Setup HTTP proxy headers if necessary */
|
2515
|
+
curl_easy_setopt(curl, CURLOPT_PROXYHEADER, NULL); // XXX: maybe we shouldn't be clearing this?
|
2516
|
+
|
2517
|
+
if (!rb_easy_nil("proxy_headers")) {
|
2518
|
+
if (rb_easy_type_check("proxy_headers", T_ARRAY) || rb_easy_type_check("proxy_headers", T_HASH)) {
|
2519
|
+
VALUE wrap = Data_Wrap_Struct(rb_cObject, 0, 0, phdrs);
|
2520
|
+
rb_iterate(rb_each, rb_easy_get("proxy_headers"), cb_each_http_proxy_header, wrap);
|
2521
|
+
} else {
|
2522
|
+
VALUE proxy_headers_str = rb_obj_as_string(rb_easy_get("proxy_headers"));
|
2523
|
+
*phdrs = curl_slist_append(*hdrs, StringValuePtr(proxy_headers_str));
|
2524
|
+
}
|
2525
|
+
|
2526
|
+
if (*phdrs) {
|
2527
|
+
curl_easy_setopt(curl, CURLOPT_PROXYHEADER, *phdrs);
|
2528
|
+
}
|
2529
|
+
}
|
2530
|
+
#endif
|
2531
|
+
|
2277
2532
|
/* Setup FTP commands if necessary */
|
2278
2533
|
if (!rb_easy_nil("ftp_commands")) {
|
2279
2534
|
if (rb_easy_type_check("ftp_commands", T_ARRAY)) {
|
@@ -2286,18 +2541,33 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
|
|
2286
2541
|
}
|
2287
2542
|
}
|
2288
2543
|
|
2544
|
+
#if HAVE_CURLOPT_RESOLVE
|
2545
|
+
/* Setup resolve list if necessary */
|
2546
|
+
if (!rb_easy_nil("resolve")) {
|
2547
|
+
if (rb_easy_type_check("resolve", T_ARRAY)) {
|
2548
|
+
VALUE wrap = Data_Wrap_Struct(rb_cObject, 0, 0, rslv);
|
2549
|
+
rb_iterate(rb_each, rb_easy_get("resolve"), cb_each_resolve, wrap);
|
2550
|
+
}
|
2551
|
+
|
2552
|
+
if (*rslv) {
|
2553
|
+
curl_easy_setopt(curl, CURLOPT_RESOLVE, *rslv);
|
2554
|
+
}
|
2555
|
+
}
|
2556
|
+
#endif
|
2557
|
+
|
2289
2558
|
return Qnil;
|
2290
2559
|
}
|
2291
2560
|
/***********************************************
|
2292
2561
|
*
|
2293
2562
|
* Clean up a connection
|
2294
2563
|
*
|
2295
|
-
* Always returns
|
2564
|
+
* Always returns Qnil.
|
2296
2565
|
*/
|
2297
2566
|
VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
|
2298
2567
|
|
2299
2568
|
CURL *curl = rbce->curl;
|
2300
2569
|
struct curl_slist *ftp_commands;
|
2570
|
+
struct curl_slist *resolve;
|
2301
2571
|
|
2302
2572
|
/* Free everything up */
|
2303
2573
|
if (rbce->curl_headers) {
|
@@ -2305,12 +2575,23 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
|
|
2305
2575
|
rbce->curl_headers = NULL;
|
2306
2576
|
}
|
2307
2577
|
|
2578
|
+
if (rbce->curl_proxy_headers) {
|
2579
|
+
curl_slist_free_all(rbce->curl_proxy_headers);
|
2580
|
+
rbce->curl_proxy_headers = NULL;
|
2581
|
+
}
|
2582
|
+
|
2308
2583
|
ftp_commands = rbce->curl_ftp_commands;
|
2309
2584
|
if (ftp_commands) {
|
2310
2585
|
curl_slist_free_all(ftp_commands);
|
2311
2586
|
rbce->curl_ftp_commands = NULL;
|
2312
2587
|
}
|
2313
2588
|
|
2589
|
+
resolve = rbce->curl_resolve;
|
2590
|
+
if (resolve) {
|
2591
|
+
curl_slist_free_all(resolve);
|
2592
|
+
rbce->curl_resolve = NULL;
|
2593
|
+
}
|
2594
|
+
|
2314
2595
|
/* clean up a PUT request's curl options. */
|
2315
2596
|
if (!rb_easy_nil("upload")) {
|
2316
2597
|
rb_easy_del("upload"); // set the upload object to Qnil to let the GC clean up
|
@@ -2320,6 +2601,9 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
|
|
2320
2601
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0);
|
2321
2602
|
}
|
2322
2603
|
|
2604
|
+
// set values on cleanup to nil
|
2605
|
+
rb_easy_del("multi");
|
2606
|
+
|
2323
2607
|
return Qnil;
|
2324
2608
|
}
|
2325
2609
|
|
@@ -2334,6 +2618,8 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
|
|
2334
2618
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2335
2619
|
curl = rbce->curl;
|
2336
2620
|
|
2621
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2622
|
+
|
2337
2623
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
|
2338
2624
|
|
2339
2625
|
retval = rb_funcall(self, rb_intern("perform"), 0);
|
@@ -2399,6 +2685,8 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
|
|
2399
2685
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2400
2686
|
curl = rbce->curl;
|
2401
2687
|
|
2688
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2689
|
+
|
2402
2690
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2403
2691
|
|
2404
2692
|
if (rbce->multipart_form_post) {
|
@@ -2470,6 +2758,8 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
|
2470
2758
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2471
2759
|
curl = rbce->curl;
|
2472
2760
|
|
2761
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2762
|
+
|
2473
2763
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2474
2764
|
ruby_curl_easy_put_data_set(self, data);
|
2475
2765
|
|
@@ -2488,6 +2778,10 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
|
2488
2778
|
* your own body handler, this string will be empty.
|
2489
2779
|
*/
|
2490
2780
|
static VALUE ruby_curl_easy_body_str_get(VALUE self) {
|
2781
|
+
/*
|
2782
|
+
TODO: can we force_encoding on the return here if we see charset=utf-8 in the content-type header?
|
2783
|
+
Content-Type: application/json; charset=utf-8
|
2784
|
+
*/
|
2491
2785
|
CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
|
2492
2786
|
}
|
2493
2787
|
|
@@ -2564,7 +2858,7 @@ static VALUE ruby_curl_easy_response_code_get(VALUE self) {
|
|
2564
2858
|
static VALUE ruby_curl_easy_primary_ip_get(VALUE self) {
|
2565
2859
|
ruby_curl_easy *rbce;
|
2566
2860
|
char* ip;
|
2567
|
-
|
2861
|
+
|
2568
2862
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2569
2863
|
curl_easy_getinfo(rbce->curl, CURLINFO_PRIMARY_IP, &ip);
|
2570
2864
|
|
@@ -2682,7 +2976,7 @@ static VALUE ruby_curl_easy_connect_time_get(VALUE self) {
|
|
2682
2976
|
* Retrieve the time, in seconds, it took from the start until the SSL/SSH
|
2683
2977
|
* connect/handshake to the remote host was completed. This time is most often
|
2684
2978
|
* very near to the pre transfer time, except for cases such as HTTP
|
2685
|
-
*
|
2979
|
+
* pipelining where the pretransfer time can be delayed due to waits in line
|
2686
2980
|
* for the pipeline and more.
|
2687
2981
|
*/
|
2688
2982
|
#if defined(HAVE_CURLINFO_APPCONNECT_TIME)
|
@@ -2789,7 +3083,7 @@ static VALUE ruby_curl_easy_redirect_count_get(VALUE self) {
|
|
2789
3083
|
* call-seq:
|
2790
3084
|
* easy.redirect_url => "http://some.url" or nil
|
2791
3085
|
*
|
2792
|
-
* Retrieve the URL a redirect would take you to if you
|
3086
|
+
* Retrieve the URL a redirect would take you to if you
|
2793
3087
|
* would enable CURLOPT_FOLLOWLOCATION.
|
2794
3088
|
*
|
2795
3089
|
* Requires libcurl 7.18.2 or higher, otherwise -1 is always returned.
|
@@ -3072,12 +3366,40 @@ static VALUE ruby_curl_easy_num_connects_get(VALUE self) {
|
|
3072
3366
|
}
|
3073
3367
|
|
3074
3368
|
|
3075
|
-
/*
|
3369
|
+
/*
|
3370
|
+
* call-seq:
|
3371
|
+
* easy.cookielist => array
|
3372
|
+
*
|
3373
|
+
* Retrieves the cookies curl knows in an array of strings.
|
3374
|
+
* Returned strings are in Netscape cookiejar format or in Set-Cookie format.
|
3375
|
+
*
|
3376
|
+
* See also option CURLINFO_COOKIELIST of curl_easy_getopt(3) to see how libcurl behaves.
|
3377
|
+
*
|
3378
|
+
* (requires libcurl 7.14.1 or higher, otherwise -1 is always returned).
|
3379
|
+
*/
|
3380
|
+
static VALUE ruby_curl_easy_cookielist_get(VALUE self) {
|
3381
|
+
#ifdef HAVE_CURLINFO_COOKIELIST
|
3382
|
+
ruby_curl_easy *rbce;
|
3383
|
+
struct curl_slist *cookies;
|
3384
|
+
struct curl_slist *cookie;
|
3385
|
+
VALUE rb_cookies;
|
3386
|
+
|
3387
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
3388
|
+
curl_easy_getinfo(rbce->curl, CURLINFO_COOKIELIST, &cookies);
|
3389
|
+
if (!cookies)
|
3390
|
+
return Qnil;
|
3391
|
+
rb_cookies = rb_ary_new();
|
3392
|
+
for (cookie = cookies; cookie; cookie = cookie->next)
|
3393
|
+
rb_ary_push(rb_cookies, rb_str_new2(cookie->data));
|
3394
|
+
curl_slist_free_all(cookies);
|
3395
|
+
return rb_cookies;
|
3076
3396
|
|
3077
|
-
|
3397
|
+
#else
|
3398
|
+
rb_warn("Installed libcurl is too old to support cookielist");
|
3399
|
+
return INT2FIX(-1);
|
3400
|
+
#endif
|
3401
|
+
}
|
3078
3402
|
|
3079
|
-
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)
|
3080
|
-
*/
|
3081
3403
|
|
3082
3404
|
/* TODO this needs to be implemented. Could probably support CONNECT_ONLY by having this
|
3083
3405
|
* return an open Socket or something.
|
@@ -3147,6 +3469,21 @@ static VALUE ruby_curl_easy_last_result(VALUE self) {
|
|
3147
3469
|
return LONG2NUM(rbce->last_result);
|
3148
3470
|
}
|
3149
3471
|
|
3472
|
+
/*
|
3473
|
+
* call-seq:
|
3474
|
+
* easy.last_error => "Error details" or nil
|
3475
|
+
*/
|
3476
|
+
static VALUE ruby_curl_easy_last_error(VALUE self) {
|
3477
|
+
ruby_curl_easy *rbce;
|
3478
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
3479
|
+
|
3480
|
+
if (rbce->err_buf[0]) { // curl returns NULL or empty string if none
|
3481
|
+
return rb_str_new2(rbce->err_buf);
|
3482
|
+
} else {
|
3483
|
+
return Qnil;
|
3484
|
+
}
|
3485
|
+
}
|
3486
|
+
|
3150
3487
|
/*
|
3151
3488
|
* call-seq:
|
3152
3489
|
* easy.setopt Fixnum, value => value
|
@@ -3156,6 +3493,7 @@ static VALUE ruby_curl_easy_last_result(VALUE self) {
|
|
3156
3493
|
static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
3157
3494
|
ruby_curl_easy *rbce;
|
3158
3495
|
long option = NUM2LONG(opt);
|
3496
|
+
rb_io_t *open_f_ptr;
|
3159
3497
|
|
3160
3498
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
3161
3499
|
|
@@ -3193,6 +3531,12 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3193
3531
|
case CURLOPT_HEADER:
|
3194
3532
|
case CURLOPT_NOPROGRESS:
|
3195
3533
|
case CURLOPT_NOSIGNAL:
|
3534
|
+
#if HAVE_CURLOPT_PATH_AS_IS
|
3535
|
+
case CURLOPT_PATH_AS_IS:
|
3536
|
+
#endif
|
3537
|
+
#if HAVE_CURLOPT_PIPEWAIT
|
3538
|
+
case CURLOPT_PIPEWAIT:
|
3539
|
+
#endif
|
3196
3540
|
case CURLOPT_HTTPGET:
|
3197
3541
|
case CURLOPT_NOBODY: {
|
3198
3542
|
int type = rb_type(val);
|
@@ -3238,6 +3582,9 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3238
3582
|
case CURLOPT_TCP_NODELAY: {
|
3239
3583
|
curl_easy_setopt(rbce->curl, CURLOPT_TCP_NODELAY, NUM2LONG(val));
|
3240
3584
|
} break;
|
3585
|
+
case CURLOPT_RANGE: {
|
3586
|
+
curl_easy_setopt(rbce->curl, CURLOPT_RANGE, StringValueCStr(val));
|
3587
|
+
} break;
|
3241
3588
|
case CURLOPT_RESUME_FROM: {
|
3242
3589
|
curl_easy_setopt(rbce->curl, CURLOPT_RESUME_FROM, NUM2LONG(val));
|
3243
3590
|
} break;
|
@@ -3259,6 +3606,53 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3259
3606
|
case CURLOPT_UNIX_SOCKET_PATH: {
|
3260
3607
|
curl_easy_setopt(rbce->curl, CURLOPT_UNIX_SOCKET_PATH, StringValueCStr(val));
|
3261
3608
|
} break;
|
3609
|
+
#endif
|
3610
|
+
#if HAVE_CURLOPT_MAX_SEND_SPEED_LARGE
|
3611
|
+
case CURLOPT_MAX_SEND_SPEED_LARGE: {
|
3612
|
+
curl_easy_setopt(rbce->curl, CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) NUM2LL(val));
|
3613
|
+
} break;
|
3614
|
+
#endif
|
3615
|
+
#if HAVE_CURLOPT_MAX_RECV_SPEED_LARGE
|
3616
|
+
case CURLOPT_MAX_RECV_SPEED_LARGE: {
|
3617
|
+
curl_easy_setopt(rbce->curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) NUM2LL(val));
|
3618
|
+
} break;
|
3619
|
+
#endif
|
3620
|
+
#if HAVE_CURLOPT_MAXFILESIZE
|
3621
|
+
case CURLOPT_MAXFILESIZE:
|
3622
|
+
curl_easy_setopt(rbce->curl, CURLOPT_MAXFILESIZE, NUM2LONG(val));
|
3623
|
+
break;
|
3624
|
+
#endif
|
3625
|
+
#if HAVE_CURLOPT_TCP_KEEPALIVE
|
3626
|
+
case CURLOPT_TCP_KEEPALIVE:
|
3627
|
+
curl_easy_setopt(rbce->curl, CURLOPT_TCP_KEEPALIVE, NUM2LONG(val));
|
3628
|
+
break;
|
3629
|
+
case CURLOPT_TCP_KEEPIDLE:
|
3630
|
+
curl_easy_setopt(rbce->curl, CURLOPT_TCP_KEEPIDLE, NUM2LONG(val));
|
3631
|
+
break;
|
3632
|
+
case CURLOPT_TCP_KEEPINTVL:
|
3633
|
+
curl_easy_setopt(rbce->curl, CURLOPT_TCP_KEEPINTVL, NUM2LONG(val));
|
3634
|
+
break;
|
3635
|
+
#endif
|
3636
|
+
#if HAVE_CURLOPT_HAPROXYPROTOCOL
|
3637
|
+
case CURLOPT_HAPROXYPROTOCOL:
|
3638
|
+
curl_easy_setopt(rbce->curl, CURLOPT_HAPROXYPROTOCOL, NUM2LONG(val));
|
3639
|
+
break;
|
3640
|
+
#endif
|
3641
|
+
case CURLOPT_STDERR:
|
3642
|
+
// libcurl requires raw FILE pointer and this should be IO object in Ruby.
|
3643
|
+
// Tempfile or StringIO won't work.
|
3644
|
+
Check_Type(val, T_FILE);
|
3645
|
+
GetOpenFile(val, open_f_ptr);
|
3646
|
+
curl_easy_setopt(rbce->curl, CURLOPT_STDERR, rb_io_stdio_file(open_f_ptr));
|
3647
|
+
break;
|
3648
|
+
case CURLOPT_PROTOCOLS:
|
3649
|
+
case CURLOPT_REDIR_PROTOCOLS:
|
3650
|
+
curl_easy_setopt(rbce->curl, option, NUM2LONG(val));
|
3651
|
+
break;
|
3652
|
+
#if HAVE_CURLOPT_SSL_SESSIONID_CACHE
|
3653
|
+
case CURLOPT_SSL_SESSIONID_CACHE:
|
3654
|
+
curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
|
3655
|
+
break;
|
3262
3656
|
#endif
|
3263
3657
|
default:
|
3264
3658
|
rb_raise(rb_eTypeError, "Curb unsupported option");
|
@@ -3386,12 +3780,19 @@ void init_curb_easy() {
|
|
3386
3780
|
cCurlEasy = rb_define_class_under(mCurl, "Easy", rb_cObject);
|
3387
3781
|
|
3388
3782
|
/* Class methods */
|
3389
|
-
|
3783
|
+
rb_define_alloc_func(cCurlEasy, ruby_curl_easy_allocate);
|
3390
3784
|
rb_define_singleton_method(cCurlEasy, "error", ruby_curl_easy_error_message, 1);
|
3391
3785
|
|
3786
|
+
/* Initialize method */
|
3787
|
+
rb_define_method(cCurlEasy, "initialize", ruby_curl_easy_initialize, -1);
|
3788
|
+
|
3392
3789
|
/* Attributes for config next perform */
|
3393
3790
|
rb_define_method(cCurlEasy, "url", ruby_curl_easy_url_get, 0);
|
3394
3791
|
rb_define_method(cCurlEasy, "proxy_url", ruby_curl_easy_proxy_url_get, 0);
|
3792
|
+
|
3793
|
+
rb_define_method(cCurlEasy, "proxy_headers=", ruby_curl_easy_proxy_headers_set, 1);
|
3794
|
+
rb_define_method(cCurlEasy, "proxy_headers", ruby_curl_easy_proxy_headers_get, 0);
|
3795
|
+
|
3395
3796
|
rb_define_method(cCurlEasy, "headers=", ruby_curl_easy_headers_set, 1);
|
3396
3797
|
rb_define_method(cCurlEasy, "headers", ruby_curl_easy_headers_get, 0);
|
3397
3798
|
rb_define_method(cCurlEasy, "interface", ruby_curl_easy_interface_get, 0);
|
@@ -3418,6 +3819,8 @@ void init_curb_easy() {
|
|
3418
3819
|
rb_define_method(cCurlEasy, "put_data=", ruby_curl_easy_put_data_set, 1);
|
3419
3820
|
rb_define_method(cCurlEasy, "ftp_commands=", ruby_curl_easy_ftp_commands_set, 1);
|
3420
3821
|
rb_define_method(cCurlEasy, "ftp_commands", ruby_curl_easy_ftp_commands_get, 0);
|
3822
|
+
rb_define_method(cCurlEasy, "resolve=", ruby_curl_easy_resolve_set, 1);
|
3823
|
+
rb_define_method(cCurlEasy, "resolve", ruby_curl_easy_resolve_get, 0);
|
3421
3824
|
|
3422
3825
|
rb_define_method(cCurlEasy, "local_port=", ruby_curl_easy_local_port_set, 1);
|
3423
3826
|
rb_define_method(cCurlEasy, "local_port", ruby_curl_easy_local_port_get, 0);
|
@@ -3449,6 +3852,10 @@ void init_curb_easy() {
|
|
3449
3852
|
rb_define_method(cCurlEasy, "low_speed_limit", ruby_curl_easy_low_speed_limit_get, 0);
|
3450
3853
|
rb_define_method(cCurlEasy, "low_speed_time=", ruby_curl_easy_low_speed_time_set, 1);
|
3451
3854
|
rb_define_method(cCurlEasy, "low_speed_time", ruby_curl_easy_low_speed_time_get, 0);
|
3855
|
+
rb_define_method(cCurlEasy, "max_send_speed_large=", ruby_curl_easy_max_send_speed_large_set, 1);
|
3856
|
+
rb_define_method(cCurlEasy, "max_send_speed_large", ruby_curl_easy_max_send_speed_large_get, 0);
|
3857
|
+
rb_define_method(cCurlEasy, "max_recv_speed_large=", ruby_curl_easy_max_recv_speed_large_set, 1);
|
3858
|
+
rb_define_method(cCurlEasy, "max_recv_speed_large", ruby_curl_easy_max_recv_speed_large_get, 0);
|
3452
3859
|
rb_define_method(cCurlEasy, "ssl_version=", ruby_curl_easy_ssl_version_set, 1);
|
3453
3860
|
rb_define_method(cCurlEasy, "ssl_version", ruby_curl_easy_ssl_version_get, 0);
|
3454
3861
|
rb_define_method(cCurlEasy, "use_ssl=", ruby_curl_easy_use_ssl_set, 1);
|
@@ -3536,6 +3943,7 @@ void init_curb_easy() {
|
|
3536
3943
|
rb_define_method(cCurlEasy, "content_type", ruby_curl_easy_content_type_get, 0);
|
3537
3944
|
rb_define_method(cCurlEasy, "os_errno", ruby_curl_easy_os_errno_get, 0);
|
3538
3945
|
rb_define_method(cCurlEasy, "num_connects", ruby_curl_easy_num_connects_get, 0);
|
3946
|
+
rb_define_method(cCurlEasy, "cookielist", ruby_curl_easy_cookielist_get, 0);
|
3539
3947
|
rb_define_method(cCurlEasy, "ftp_entry_path", ruby_curl_easy_ftp_entry_path_get, 0);
|
3540
3948
|
|
3541
3949
|
rb_define_method(cCurlEasy, "close", ruby_curl_easy_close, 0);
|
@@ -3553,6 +3961,7 @@ void init_curb_easy() {
|
|
3553
3961
|
rb_define_method(cCurlEasy, "multi", ruby_curl_easy_multi_get, 0);
|
3554
3962
|
rb_define_method(cCurlEasy, "multi=", ruby_curl_easy_multi_set, 1);
|
3555
3963
|
rb_define_method(cCurlEasy, "last_result", ruby_curl_easy_last_result, 0);
|
3964
|
+
rb_define_method(cCurlEasy, "last_error", ruby_curl_easy_last_error, 0);
|
3556
3965
|
|
3557
3966
|
rb_define_method(cCurlEasy, "setopt", ruby_curl_easy_set_opt, 2);
|
3558
3967
|
rb_define_method(cCurlEasy, "getinfo", ruby_curl_easy_get_opt, 1);
|