curb 0.6.2.1 → 0.6.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of curb might be problematic. Click here for more details.
- data/ext/curb.h +4 -4
- data/ext/curb_easy.c +141 -185
- data/ext/curb_easy.h +3 -52
- data/ext/curb_macros.h +41 -0
- data/ext/curb_multi.c +10 -12
- data/ext/curb_postfield.c +3 -3
- data/tests/bug_postfields_crash.rb +26 -0
- data/tests/mem_check.rb +65 -0
- data/tests/s.rb +4 -0
- data/tests/tc_curl_multi.rb +1 -1
- metadata +19 -16
data/ext/curb.h
CHANGED
@@ -20,12 +20,12 @@
|
|
20
20
|
#include "curb_macros.h"
|
21
21
|
|
22
22
|
// These should be managed from the Rake 'release' task.
|
23
|
-
#define CURB_VERSION "0.6.
|
24
|
-
#define CURB_VER_NUM
|
23
|
+
#define CURB_VERSION "0.6.4.0"
|
24
|
+
#define CURB_VER_NUM 640
|
25
25
|
#define CURB_VER_MAJ 0
|
26
26
|
#define CURB_VER_MIN 6
|
27
|
-
#define CURB_VER_MIC
|
28
|
-
#define CURB_VER_PATCH
|
27
|
+
#define CURB_VER_MIC 4
|
28
|
+
#define CURB_VER_PATCH 0
|
29
29
|
|
30
30
|
|
31
31
|
// Maybe not yet defined in Ruby
|
data/ext/curb_easy.c
CHANGED
@@ -42,8 +42,9 @@ static size_t read_data_handler(void *ptr,
|
|
42
42
|
size_t size,
|
43
43
|
size_t nmemb,
|
44
44
|
ruby_curl_easy *rbce) {
|
45
|
+
VALUE upload = rb_easy_get("upload");
|
45
46
|
size_t read_bytes = (size*nmemb);
|
46
|
-
VALUE stream = ruby_curl_upload_stream_get(
|
47
|
+
VALUE stream = ruby_curl_upload_stream_get(upload);
|
47
48
|
|
48
49
|
if (rb_respond_to(stream, rb_intern("read"))) {//if (rb_respond_to(stream, rb_intern("to_s"))) {
|
49
50
|
/* copy read_bytes from stream into ptr */
|
@@ -62,7 +63,7 @@ static size_t read_data_handler(void *ptr,
|
|
62
63
|
size_t len;
|
63
64
|
size_t remaining;
|
64
65
|
char *str_ptr;
|
65
|
-
Data_Get_Struct(
|
66
|
+
Data_Get_Struct(upload, ruby_curl_upload, rbcu);
|
66
67
|
str = rb_funcall(stream, rb_intern("to_s"), 0);
|
67
68
|
len = RSTRING_LEN(str);
|
68
69
|
remaining = len - rbcu->offset;
|
@@ -133,6 +134,7 @@ static int proc_debug_handler(CURL *curl,
|
|
133
134
|
|
134
135
|
/* ================== MARK/FREE FUNC ==================*/
|
135
136
|
void curl_easy_mark(ruby_curl_easy *rbce) {
|
137
|
+
#if 0
|
136
138
|
rb_gc_mark(rbce->url);
|
137
139
|
rb_gc_mark(rbce->proxy_url);
|
138
140
|
rb_gc_mark(rbce->body_proc);
|
@@ -171,6 +173,8 @@ void curl_easy_mark(ruby_curl_easy *rbce) {
|
|
171
173
|
if( rbce->upload != Qnil ) {
|
172
174
|
rb_gc_mark(rbce->upload);
|
173
175
|
}
|
176
|
+
#endif
|
177
|
+
rb_gc_mark(rbce->opts);
|
174
178
|
}
|
175
179
|
|
176
180
|
void curl_easy_free(ruby_curl_easy *rbce) {
|
@@ -207,37 +211,11 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
|
|
207
211
|
/* handler */
|
208
212
|
rbce->curl = curl_easy_init();
|
209
213
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
rbce->
|
215
|
-
rbce->header_data = Qnil;
|
216
|
-
rbce->header_proc = Qnil;
|
217
|
-
rbce->progress_proc = Qnil;
|
218
|
-
rbce->debug_proc = Qnil;
|
219
|
-
rbce->interface_hm = Qnil;
|
220
|
-
rbce->userpwd = Qnil;
|
221
|
-
#if HAVE_CURLOPT_USERNAME
|
222
|
-
rbce->username = Qnil;
|
223
|
-
#endif
|
224
|
-
#if HAVE_CURLOPT_PASSWORD
|
225
|
-
rbce->password = Qnil;
|
226
|
-
#endif
|
227
|
-
rbce->proxypwd = Qnil;
|
228
|
-
rbce->headers = rb_hash_new();
|
229
|
-
rbce->cookies = Qnil;
|
230
|
-
rbce->cookiefile = Qnil;
|
231
|
-
rbce->cookiejar = Qnil;
|
232
|
-
rbce->cert = Qnil;
|
233
|
-
rbce->cacert = Qnil;
|
234
|
-
rbce->certpassword = Qnil;
|
235
|
-
rbce->certtype = rb_str_new2("PEM");
|
236
|
-
rbce->encoding = Qnil;
|
237
|
-
rbce->useragent = Qnil;
|
238
|
-
rbce->success_proc = Qnil;
|
239
|
-
rbce->failure_proc = Qnil;
|
240
|
-
rbce->complete_proc = Qnil;
|
214
|
+
rbce->opts = rb_hash_new();
|
215
|
+
|
216
|
+
rb_easy_set("url", url);
|
217
|
+
|
218
|
+
rbce->curl_headers = NULL;
|
241
219
|
|
242
220
|
/* various-typed opts */
|
243
221
|
rbce->local_port = 0;
|
@@ -265,14 +243,6 @@ static VALUE ruby_curl_easy_new(int argc, VALUE *argv, VALUE klass) {
|
|
265
243
|
rbce->multipart_form_post = 0;
|
266
244
|
rbce->enable_cookies = 0;
|
267
245
|
|
268
|
-
/* buffers */
|
269
|
-
rbce->postdata_buffer = Qnil;
|
270
|
-
rbce->bodybuf = Qnil;
|
271
|
-
rbce->headerbuf = Qnil;
|
272
|
-
rbce->curl_headers = NULL;
|
273
|
-
|
274
|
-
rbce->upload = Qnil;
|
275
|
-
|
276
246
|
new_curl = Data_Wrap_Struct(klass, curl_easy_mark, curl_easy_free, rbce);
|
277
247
|
|
278
248
|
/* set the new_curl pointer to the curl handle */
|
@@ -321,7 +291,7 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
321
291
|
* the URL between calls to +perform+.
|
322
292
|
*/
|
323
293
|
static VALUE ruby_curl_easy_url_set(VALUE self, VALUE url) {
|
324
|
-
|
294
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, url);
|
325
295
|
}
|
326
296
|
|
327
297
|
/*
|
@@ -331,7 +301,7 @@ static VALUE ruby_curl_easy_url_set(VALUE self, VALUE url) {
|
|
331
301
|
* Obtain the URL that will be used by subsequent calls to +perform+.
|
332
302
|
*/
|
333
303
|
static VALUE ruby_curl_easy_url_get(VALUE self) {
|
334
|
-
|
304
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, url);
|
335
305
|
}
|
336
306
|
|
337
307
|
/*
|
@@ -360,7 +330,7 @@ static VALUE ruby_curl_easy_url_get(VALUE self) {
|
|
360
330
|
* proxy_url, including protocol prefix (http://) and embedded user + password.
|
361
331
|
*/
|
362
332
|
static VALUE ruby_curl_easy_proxy_url_set(VALUE self, VALUE proxy_url) {
|
363
|
-
|
333
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, proxy_url);
|
364
334
|
}
|
365
335
|
|
366
336
|
/*
|
@@ -370,7 +340,7 @@ static VALUE ruby_curl_easy_proxy_url_set(VALUE self, VALUE proxy_url) {
|
|
370
340
|
* Obtain the HTTP Proxy URL that will be used by subsequent calls to +perform+.
|
371
341
|
*/
|
372
342
|
static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
|
373
|
-
|
343
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, proxy_url);
|
374
344
|
}
|
375
345
|
|
376
346
|
/*
|
@@ -396,7 +366,7 @@ static VALUE ruby_curl_easy_proxy_url_get(VALUE self) {
|
|
396
366
|
* the perform step.
|
397
367
|
*/
|
398
368
|
static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
|
399
|
-
|
369
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, headers);
|
400
370
|
}
|
401
371
|
|
402
372
|
/*
|
@@ -406,7 +376,12 @@ static VALUE ruby_curl_easy_headers_set(VALUE self, VALUE headers) {
|
|
406
376
|
* Obtain the custom HTTP headers for following requests.
|
407
377
|
*/
|
408
378
|
static VALUE ruby_curl_easy_headers_get(VALUE self) {
|
409
|
-
|
379
|
+
ruby_curl_easy *rbce;
|
380
|
+
VALUE headers;
|
381
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
382
|
+
headers = rb_easy_get("headers");//rb_hash_aref(rbce->opts, rb_intern("headers"));
|
383
|
+
if (headers == Qnil) { headers = rb_easy_set("headers", rb_hash_new()); }
|
384
|
+
return headers;
|
410
385
|
}
|
411
386
|
|
412
387
|
/*
|
@@ -417,7 +392,7 @@ static VALUE ruby_curl_easy_headers_get(VALUE self) {
|
|
417
392
|
* The name can be an interface name, an IP address or a host name.
|
418
393
|
*/
|
419
394
|
static VALUE ruby_curl_easy_interface_set(VALUE self, VALUE interface_hm) {
|
420
|
-
|
395
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, interface_hm);
|
421
396
|
}
|
422
397
|
|
423
398
|
/*
|
@@ -428,7 +403,7 @@ static VALUE ruby_curl_easy_interface_set(VALUE self, VALUE interface_hm) {
|
|
428
403
|
* The name can be an interface name, an IP address or a host name.
|
429
404
|
*/
|
430
405
|
static VALUE ruby_curl_easy_interface_get(VALUE self) {
|
431
|
-
|
406
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, interface_hm);
|
432
407
|
}
|
433
408
|
|
434
409
|
/*
|
@@ -439,7 +414,7 @@ static VALUE ruby_curl_easy_interface_get(VALUE self) {
|
|
439
414
|
* The supplied string should have the form "username:password"
|
440
415
|
*/
|
441
416
|
static VALUE ruby_curl_easy_userpwd_set(VALUE self, VALUE userpwd) {
|
442
|
-
|
417
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, userpwd);
|
443
418
|
}
|
444
419
|
|
445
420
|
/*
|
@@ -450,7 +425,7 @@ static VALUE ruby_curl_easy_userpwd_set(VALUE self, VALUE userpwd) {
|
|
450
425
|
* calls to +perform+.
|
451
426
|
*/
|
452
427
|
static VALUE ruby_curl_easy_userpwd_get(VALUE self) {
|
453
|
-
|
428
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, userpwd);
|
454
429
|
}
|
455
430
|
|
456
431
|
/*
|
@@ -462,7 +437,7 @@ static VALUE ruby_curl_easy_userpwd_get(VALUE self) {
|
|
462
437
|
* form "username:password"
|
463
438
|
*/
|
464
439
|
static VALUE ruby_curl_easy_proxypwd_set(VALUE self, VALUE proxypwd) {
|
465
|
-
|
440
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, proxypwd);
|
466
441
|
}
|
467
442
|
|
468
443
|
/*
|
@@ -474,7 +449,7 @@ static VALUE ruby_curl_easy_proxypwd_set(VALUE self, VALUE proxypwd) {
|
|
474
449
|
* should have the form "username:password"
|
475
450
|
*/
|
476
451
|
static VALUE ruby_curl_easy_proxypwd_get(VALUE self) {
|
477
|
-
|
452
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, proxypwd);
|
478
453
|
}
|
479
454
|
|
480
455
|
|
@@ -487,7 +462,7 @@ static VALUE ruby_curl_easy_proxypwd_get(VALUE self) {
|
|
487
462
|
* Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
|
488
463
|
*/
|
489
464
|
static VALUE ruby_curl_easy_cookies_set(VALUE self, VALUE cookies) {
|
490
|
-
|
465
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, cookies);
|
491
466
|
}
|
492
467
|
|
493
468
|
/*
|
@@ -497,7 +472,7 @@ static VALUE ruby_curl_easy_cookies_set(VALUE self, VALUE cookies) {
|
|
497
472
|
* Obtain the cookies for this Curl::Easy instance.
|
498
473
|
*/
|
499
474
|
static VALUE ruby_curl_easy_cookies_get(VALUE self) {
|
500
|
-
|
475
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, cookies);
|
501
476
|
}
|
502
477
|
|
503
478
|
/*
|
@@ -510,7 +485,7 @@ static VALUE ruby_curl_easy_cookies_get(VALUE self) {
|
|
510
485
|
* engine, or this option will be ignored.
|
511
486
|
*/
|
512
487
|
static VALUE ruby_curl_easy_cookiefile_set(VALUE self, VALUE cookiefile) {
|
513
|
-
|
488
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, cookiefile);
|
514
489
|
}
|
515
490
|
|
516
491
|
/*
|
@@ -520,7 +495,7 @@ static VALUE ruby_curl_easy_cookiefile_set(VALUE self, VALUE cookiefile) {
|
|
520
495
|
* Obtain the cookiefile file for this Curl::Easy instance.
|
521
496
|
*/
|
522
497
|
static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
|
523
|
-
|
498
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, cookiefile);
|
524
499
|
}
|
525
500
|
|
526
501
|
/*
|
@@ -534,7 +509,7 @@ static VALUE ruby_curl_easy_cookiefile_get(VALUE self) {
|
|
534
509
|
* engine, or this option will be ignored.
|
535
510
|
*/
|
536
511
|
static VALUE ruby_curl_easy_cookiejar_set(VALUE self, VALUE cookiejar) {
|
537
|
-
|
512
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, cookiejar);
|
538
513
|
}
|
539
514
|
|
540
515
|
/*
|
@@ -544,7 +519,7 @@ static VALUE ruby_curl_easy_cookiejar_set(VALUE self, VALUE cookiejar) {
|
|
544
519
|
* Obtain the cookiejar file to use for this Curl::Easy instance.
|
545
520
|
*/
|
546
521
|
static VALUE ruby_curl_easy_cookiejar_get(VALUE self) {
|
547
|
-
|
522
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, cookiejar);
|
548
523
|
}
|
549
524
|
|
550
525
|
/*
|
@@ -556,7 +531,7 @@ static VALUE ruby_curl_easy_cookiejar_get(VALUE self) {
|
|
556
531
|
*
|
557
532
|
*/
|
558
533
|
static VALUE ruby_curl_easy_cert_set(VALUE self, VALUE cert) {
|
559
|
-
|
534
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, cert);
|
560
535
|
}
|
561
536
|
|
562
537
|
/*
|
@@ -566,7 +541,7 @@ static VALUE ruby_curl_easy_cert_set(VALUE self, VALUE cert) {
|
|
566
541
|
* Obtain the cert file to use for this Curl::Easy instance.
|
567
542
|
*/
|
568
543
|
static VALUE ruby_curl_easy_cert_get(VALUE self) {
|
569
|
-
|
544
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, cert);
|
570
545
|
}
|
571
546
|
|
572
547
|
/*
|
@@ -578,7 +553,7 @@ static VALUE ruby_curl_easy_cert_get(VALUE self) {
|
|
578
553
|
*
|
579
554
|
*/
|
580
555
|
static VALUE ruby_curl_easy_cacert_set(VALUE self, VALUE cacert) {
|
581
|
-
|
556
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, cacert);
|
582
557
|
}
|
583
558
|
|
584
559
|
/*
|
@@ -588,7 +563,7 @@ static VALUE ruby_curl_easy_cacert_set(VALUE self, VALUE cacert) {
|
|
588
563
|
* Obtain the cacert file to use for this Curl::Easy instance.
|
589
564
|
*/
|
590
565
|
static VALUE ruby_curl_easy_cacert_get(VALUE self) {
|
591
|
-
|
566
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, cacert);
|
592
567
|
}
|
593
568
|
|
594
569
|
/*
|
@@ -598,7 +573,7 @@ static VALUE ruby_curl_easy_cacert_get(VALUE self) {
|
|
598
573
|
* Set a password used to open the specified cert
|
599
574
|
*/
|
600
575
|
static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
|
601
|
-
|
576
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, certpassword);
|
602
577
|
}
|
603
578
|
|
604
579
|
/*
|
@@ -610,7 +585,7 @@ static VALUE ruby_curl_easy_certpassword_set(VALUE self, VALUE certpassword) {
|
|
610
585
|
*
|
611
586
|
*/
|
612
587
|
static VALUE ruby_curl_easy_certtype_set(VALUE self, VALUE certtype) {
|
613
|
-
|
588
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, certtype);
|
614
589
|
}
|
615
590
|
|
616
591
|
/*
|
@@ -620,7 +595,7 @@ static VALUE ruby_curl_easy_certtype_set(VALUE self, VALUE certtype) {
|
|
620
595
|
* Obtain the cert type used for this Curl::Easy instance
|
621
596
|
*/
|
622
597
|
static VALUE ruby_curl_easy_certtype_get(VALUE self) {
|
623
|
-
|
598
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, certtype);
|
624
599
|
}
|
625
600
|
|
626
601
|
/*
|
@@ -631,7 +606,7 @@ static VALUE ruby_curl_easy_certtype_get(VALUE self) {
|
|
631
606
|
*
|
632
607
|
*/
|
633
608
|
static VALUE ruby_curl_easy_encoding_set(VALUE self, VALUE encoding) {
|
634
|
-
|
609
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, encoding);
|
635
610
|
}
|
636
611
|
/*
|
637
612
|
* call-seq:
|
@@ -641,7 +616,7 @@ static VALUE ruby_curl_easy_encoding_set(VALUE self, VALUE encoding) {
|
|
641
616
|
*
|
642
617
|
*/
|
643
618
|
static VALUE ruby_curl_easy_encoding_get(VALUE self) {
|
644
|
-
|
619
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, encoding);
|
645
620
|
}
|
646
621
|
|
647
622
|
/*
|
@@ -652,7 +627,7 @@ static VALUE ruby_curl_easy_encoding_get(VALUE self) {
|
|
652
627
|
*
|
653
628
|
*/
|
654
629
|
static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
|
655
|
-
|
630
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, useragent);
|
656
631
|
}
|
657
632
|
|
658
633
|
/*
|
@@ -662,7 +637,7 @@ static VALUE ruby_curl_easy_useragent_set(VALUE self, VALUE useragent) {
|
|
662
637
|
* Obtain the user agent string used for this Curl::Easy instance
|
663
638
|
*/
|
664
639
|
static VALUE ruby_curl_easy_useragent_get(VALUE self) {
|
665
|
-
|
640
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, useragent);
|
666
641
|
}
|
667
642
|
|
668
643
|
/*
|
@@ -687,7 +662,8 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
|
|
687
662
|
curl = rbce->curl;
|
688
663
|
|
689
664
|
if ( post_body == Qnil ) {
|
690
|
-
rbce->postdata_buffer = Qnil;
|
665
|
+
//rbce->postdata_buffer = Qnil;
|
666
|
+
rb_easy_del("postdata_buffer");
|
691
667
|
|
692
668
|
} else {
|
693
669
|
data = StringValuePtr(post_body);
|
@@ -695,7 +671,8 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
|
|
695
671
|
|
696
672
|
// Store the string, since it has to hang around for the duration of the
|
697
673
|
// request. See CURLOPT_POSTFIELDS in the libcurl docs.
|
698
|
-
rbce->postdata_buffer = post_body;
|
674
|
+
//rbce->postdata_buffer = post_body;
|
675
|
+
rb_easy_set("postdata_buffer", post_body);
|
699
676
|
|
700
677
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
701
678
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
|
@@ -714,7 +691,7 @@ static VALUE ruby_curl_easy_post_body_set(VALUE self, VALUE post_body) {
|
|
714
691
|
* Obtain the POST body used in this Curl::Easy instance.
|
715
692
|
*/
|
716
693
|
static VALUE ruby_curl_easy_post_body_get(VALUE self) {
|
717
|
-
|
694
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, postdata_buffer);
|
718
695
|
}
|
719
696
|
|
720
697
|
/*
|
@@ -736,9 +713,9 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
|
|
736
713
|
ruby_curl_upload_stream_set(upload,data);
|
737
714
|
|
738
715
|
curl = rbce->curl;
|
739
|
-
|
740
|
-
|
741
|
-
|
716
|
+
rb_easy_set("upload", upload); /* keep the upload object alive as long as
|
717
|
+
the easy handle is active or until the upload
|
718
|
+
is complete or terminated... */
|
742
719
|
|
743
720
|
curl_easy_setopt(curl, CURLOPT_NOBODY,0);
|
744
721
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
|
@@ -749,35 +726,40 @@ static VALUE ruby_curl_easy_put_data_set(VALUE self, VALUE data) {
|
|
749
726
|
* we need to set specific headers for the PUT to work... so
|
750
727
|
* convert the internal headers structure to a HASH if one is set
|
751
728
|
*/
|
752
|
-
if (
|
753
|
-
if (
|
729
|
+
if (!rb_easy_nil("headers")) {
|
730
|
+
if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_STRING)) {
|
754
731
|
rb_raise(rb_eRuntimeError, "Must set headers as a HASH to modify the headers in an PUT request");
|
755
732
|
}
|
756
733
|
}
|
757
734
|
|
735
|
+
VALUE headers = rb_easy_get("headers");
|
736
|
+
if( headers == Qnil ) {
|
737
|
+
headers = rb_hash_new();
|
738
|
+
}
|
758
739
|
if (rb_respond_to(data, rb_intern("read"))) {
|
759
740
|
VALUE stat = rb_funcall(data, rb_intern("stat"), 0);
|
760
741
|
if( stat ) {
|
761
742
|
VALUE size;
|
762
|
-
if( rb_hash_aref(
|
763
|
-
rb_hash_aset(
|
743
|
+
if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
|
744
|
+
rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
|
764
745
|
}
|
765
746
|
size = rb_funcall(stat, rb_intern("size"), 0);
|
766
747
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, FIX2INT(size));
|
767
748
|
}
|
768
|
-
else if( rb_hash_aref(
|
769
|
-
rb_hash_aset(
|
749
|
+
else if( rb_hash_aref(headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
|
750
|
+
rb_hash_aset(headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
|
770
751
|
}
|
771
752
|
}
|
772
753
|
else if (rb_respond_to(data, rb_intern("to_s"))) {
|
773
754
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, RSTRING_LEN(data));
|
774
|
-
if( rb_hash_aref(
|
775
|
-
rb_hash_aset(
|
755
|
+
if( rb_hash_aref(headers, rb_str_new2("Expect")) == Qnil ) {
|
756
|
+
rb_hash_aset(headers, rb_str_new2("Expect"), rb_str_new2(""));
|
776
757
|
}
|
777
758
|
}
|
778
759
|
else {
|
779
760
|
rb_raise(rb_eRuntimeError, "PUT data must respond to read or to_s");
|
780
761
|
}
|
762
|
+
rb_easy_set("headers",headers);
|
781
763
|
|
782
764
|
// if we made it this far, all should be well.
|
783
765
|
return data;
|
@@ -1107,7 +1089,7 @@ static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self, VALUE ftp_respo
|
|
1107
1089
|
|
1108
1090
|
static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
|
1109
1091
|
#if HAVE_CURLOPT_USERNAME
|
1110
|
-
|
1092
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, username);
|
1111
1093
|
#else
|
1112
1094
|
return Qnil;
|
1113
1095
|
#endif
|
@@ -1115,7 +1097,7 @@ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
|
|
1115
1097
|
|
1116
1098
|
static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
|
1117
1099
|
#if HAVE_CURLOPT_USERNAME
|
1118
|
-
|
1100
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, username);
|
1119
1101
|
#else
|
1120
1102
|
return Qnil;
|
1121
1103
|
#endif
|
@@ -1123,7 +1105,7 @@ static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
|
|
1123
1105
|
|
1124
1106
|
static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
|
1125
1107
|
#if HAVE_CURLOPT_PASSWORD
|
1126
|
-
|
1108
|
+
CURB_OBJECT_HSETTER(ruby_curl_easy, password);
|
1127
1109
|
#else
|
1128
1110
|
return Qnil;
|
1129
1111
|
#endif
|
@@ -1131,7 +1113,7 @@ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
|
|
1131
1113
|
|
1132
1114
|
static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
|
1133
1115
|
#if HAVE_CURLOPT_PASSWORD
|
1134
|
-
|
1116
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, password);
|
1135
1117
|
#else
|
1136
1118
|
return Qnil;
|
1137
1119
|
#endif
|
@@ -1420,7 +1402,7 @@ static VALUE ruby_curl_easy_enable_cookies_q(VALUE self) {
|
|
1420
1402
|
* the processing with a Curl::Err::AbortedByCallbackError.
|
1421
1403
|
*/
|
1422
1404
|
static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
|
1423
|
-
|
1405
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, body_proc);
|
1424
1406
|
}
|
1425
1407
|
|
1426
1408
|
/*
|
@@ -1435,7 +1417,7 @@ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
|
|
1435
1417
|
* status of 20x
|
1436
1418
|
*/
|
1437
1419
|
static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
|
1438
|
-
|
1420
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, success_proc);
|
1439
1421
|
}
|
1440
1422
|
|
1441
1423
|
/*
|
@@ -1450,7 +1432,7 @@ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
|
|
1450
1432
|
* status of 50x
|
1451
1433
|
*/
|
1452
1434
|
static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
|
1453
|
-
|
1435
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, failure_proc);
|
1454
1436
|
}
|
1455
1437
|
|
1456
1438
|
/*
|
@@ -1464,7 +1446,7 @@ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
|
|
1464
1446
|
* The +on_complete+ handler is called when the request is finished.
|
1465
1447
|
*/
|
1466
1448
|
static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
|
1467
|
-
|
1449
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, complete_proc);
|
1468
1450
|
}
|
1469
1451
|
|
1470
1452
|
/*
|
@@ -1480,7 +1462,7 @@ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
|
|
1480
1462
|
* block supplied to +on_body+.
|
1481
1463
|
*/
|
1482
1464
|
static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
|
1483
|
-
|
1465
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, header_proc);
|
1484
1466
|
}
|
1485
1467
|
|
1486
1468
|
/*
|
@@ -1501,7 +1483,7 @@ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
|
|
1501
1483
|
* throwing a Curl::Err::AbortedByCallbackError.
|
1502
1484
|
*/
|
1503
1485
|
static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
|
1504
|
-
|
1486
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, progress_proc);
|
1505
1487
|
}
|
1506
1488
|
|
1507
1489
|
/*
|
@@ -1522,7 +1504,7 @@ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
|
|
1522
1504
|
* data. The data is passed as a String.
|
1523
1505
|
*/
|
1524
1506
|
static VALUE ruby_curl_easy_on_debug_set(int argc, VALUE *argv, VALUE self) {
|
1525
|
-
|
1507
|
+
CURB_HANDLER_PROC_HSETTER(ruby_curl_easy, debug_proc);
|
1526
1508
|
}
|
1527
1509
|
|
1528
1510
|
|
@@ -1563,103 +1545,105 @@ static VALUE cb_each_http_header(VALUE header, struct curl_slist **list) {
|
|
1563
1545
|
*
|
1564
1546
|
* Always returns Qtrue, rb_raise on error.
|
1565
1547
|
*/
|
1566
|
-
VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce,
|
1548
|
+
VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, struct curl_slist **hdrs ) {
|
1567
1549
|
// TODO this could do with a bit of refactoring...
|
1568
1550
|
CURL *curl;
|
1569
|
-
VALUE url;
|
1551
|
+
VALUE url, _url = rb_easy_get("url");
|
1570
1552
|
|
1571
1553
|
curl = rbce->curl;
|
1572
1554
|
|
1573
|
-
if (
|
1555
|
+
if (_url == Qnil) {
|
1574
1556
|
rb_raise(eCurlErrError, "No URL supplied");
|
1575
1557
|
}
|
1576
1558
|
|
1577
|
-
url = rb_check_string_type(
|
1559
|
+
url = rb_check_string_type(_url);
|
1578
1560
|
|
1579
1561
|
// Need to configure the handler as per settings in rbce
|
1580
1562
|
curl_easy_setopt(curl, CURLOPT_URL, StringValuePtr(url));
|
1581
1563
|
|
1582
1564
|
// network stuff and auth
|
1583
|
-
if (
|
1584
|
-
curl_easy_setopt(curl, CURLOPT_INTERFACE,
|
1565
|
+
if (!rb_easy_nil("interface_hm")) {
|
1566
|
+
curl_easy_setopt(curl, CURLOPT_INTERFACE, rb_easy_get_str("interface_hm"));
|
1585
1567
|
} else {
|
1586
1568
|
curl_easy_setopt(curl, CURLOPT_INTERFACE, NULL);
|
1587
1569
|
}
|
1588
1570
|
|
1589
1571
|
#if HAVE_CURLOPT_USERNAME == 1 && HAVE_CURLOPT_PASSWORD == 1
|
1590
|
-
if (
|
1591
|
-
curl_easy_setopt(curl, CURLOPT_USERNAME,
|
1572
|
+
if (!rb_easy_nil("username")) {
|
1573
|
+
curl_easy_setopt(curl, CURLOPT_USERNAME, rb_easy_get_str("username"));
|
1592
1574
|
} else {
|
1593
1575
|
curl_easy_setopt(curl, CURLOPT_USERNAME, NULL);
|
1594
1576
|
}
|
1595
|
-
if (
|
1596
|
-
curl_easy_setopt(curl, CURLOPT_PASSWORD,
|
1577
|
+
if (!rb_easy_nil("password")) {
|
1578
|
+
curl_easy_setopt(curl, CURLOPT_PASSWORD, rb_easy_get_str("password"));
|
1597
1579
|
}
|
1598
1580
|
else {
|
1599
1581
|
curl_easy_setopt(curl, CURLOPT_PASSWORD, NULL);
|
1600
1582
|
}
|
1601
1583
|
#endif
|
1602
1584
|
|
1603
|
-
if (
|
1604
|
-
curl_easy_setopt(curl, CURLOPT_USERPWD,
|
1605
|
-
#if HAVE_CURLOPT_USERNAME
|
1606
|
-
} else if (
|
1585
|
+
if (!rb_easy_nil("userpwd")) {
|
1586
|
+
curl_easy_setopt(curl, CURLOPT_USERPWD, rb_easy_get_str("userpwd"));
|
1587
|
+
#if HAVE_CURLOPT_USERNAME == 1
|
1588
|
+
} else if (rb_easy_nil("username") && rb_easy_nil("password")) { /* don't set this even to NULL if we have set username and password */
|
1607
1589
|
#else
|
1608
1590
|
} else {
|
1609
1591
|
#endif
|
1610
1592
|
curl_easy_setopt(curl, CURLOPT_USERPWD, NULL);
|
1611
1593
|
}
|
1612
1594
|
|
1613
|
-
if (
|
1614
|
-
curl_easy_setopt(curl, CURLOPT_PROXY,
|
1595
|
+
if (!rb_easy_nil("proxy_url")) {
|
1596
|
+
curl_easy_setopt(curl, CURLOPT_PROXY, rb_easy_get_str("proxy_url"));
|
1615
1597
|
} else {
|
1616
1598
|
curl_easy_setopt(curl, CURLOPT_PROXY, NULL);
|
1617
1599
|
}
|
1618
1600
|
|
1619
|
-
if (
|
1620
|
-
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
|
1601
|
+
if (!rb_easy_nil("proxypwd")) {
|
1602
|
+
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, rb_easy_get_str("proxy_pwd"));
|
1621
1603
|
} else {
|
1622
1604
|
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, NULL);
|
1623
1605
|
}
|
1624
1606
|
|
1625
1607
|
// body/header procs
|
1626
|
-
if (
|
1627
|
-
*body_buffer = Qnil;
|
1608
|
+
if (!rb_easy_nil("body_proc")) {
|
1628
1609
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&proc_data_handler);
|
1629
|
-
curl_easy_setopt(curl, CURLOPT_WRITEDATA, rbce->body_proc);
|
1610
|
+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, rb_easy_get("body_proc"));//rbce->body_proc);
|
1611
|
+
/* clear out the body_data if it was set */
|
1612
|
+
rb_easy_del("body_data");
|
1630
1613
|
} else {
|
1631
|
-
|
1614
|
+
VALUE body_buffer = rb_easy_set("body_data", rb_str_buf_new(32768));
|
1632
1615
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)&default_data_handler);
|
1633
|
-
curl_easy_setopt(curl, CURLOPT_WRITEDATA,
|
1616
|
+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
|
1634
1617
|
}
|
1635
1618
|
|
1636
|
-
if (
|
1637
|
-
*header_buffer = Qnil;
|
1619
|
+
if (!rb_easy_nil("header_proc")) {
|
1638
1620
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&proc_data_handler);
|
1639
|
-
curl_easy_setopt(curl, CURLOPT_HEADERDATA,
|
1621
|
+
curl_easy_setopt(curl, CURLOPT_HEADERDATA, rb_easy_get("header_proc"));
|
1622
|
+
/* clear out the header_data if it was set */
|
1623
|
+
rb_easy_del("header_data");
|
1640
1624
|
} else {
|
1641
|
-
|
1625
|
+
VALUE header_buffer = rb_easy_set("header_data", rb_str_buf_new(16384));
|
1642
1626
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)&default_data_handler);
|
1643
|
-
curl_easy_setopt(curl, CURLOPT_HEADERDATA,
|
1627
|
+
curl_easy_setopt(curl, CURLOPT_HEADERDATA, header_buffer);
|
1644
1628
|
}
|
1645
1629
|
|
1646
1630
|
/* encoding */
|
1647
|
-
if (
|
1648
|
-
curl_easy_setopt(curl, CURLOPT_ENCODING,
|
1631
|
+
if (!rb_easy_nil("encoding")) {
|
1632
|
+
curl_easy_setopt(curl, CURLOPT_ENCODING, rb_easy_get_str("encoding"));
|
1649
1633
|
}
|
1650
1634
|
|
1651
1635
|
// progress and debug procs
|
1652
|
-
if (
|
1636
|
+
if (!rb_easy_nil("progress_proc")) {
|
1653
1637
|
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback)&proc_progress_handler);
|
1654
|
-
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA,
|
1638
|
+
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, rb_easy_get("progress_proc"));
|
1655
1639
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
|
1656
1640
|
} else {
|
1657
1641
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
1658
1642
|
}
|
1659
1643
|
|
1660
|
-
if (
|
1644
|
+
if (!rb_easy_nil("debug_proc")) {
|
1661
1645
|
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, (curl_debug_callback)&proc_debug_handler);
|
1662
|
-
curl_easy_setopt(curl, CURLOPT_DEBUGDATA,
|
1646
|
+
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, rb_easy_get("debug_proc"));
|
1663
1647
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
1664
1648
|
} else {
|
1665
1649
|
// have to remove handler to re-enable standard verbosity
|
@@ -1756,30 +1740,30 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
|
|
1756
1740
|
FIXME this may not get disabled if it's enabled, the disabled again from ruby.
|
1757
1741
|
*/
|
1758
1742
|
if (rbce->enable_cookies) {
|
1759
|
-
if (
|
1760
|
-
curl_easy_setopt(curl, CURLOPT_COOKIEJAR,
|
1743
|
+
if (!rb_easy_nil("cookiejar")) {
|
1744
|
+
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, rb_easy_get_str("cookiejar"));
|
1761
1745
|
}
|
1762
1746
|
|
1763
|
-
if (
|
1764
|
-
curl_easy_setopt(curl, CURLOPT_COOKIEFILE,
|
1747
|
+
if (!rb_easy_nil("cookiefile")) {
|
1748
|
+
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, rb_easy_get_str("cookiefile"));
|
1765
1749
|
} else {
|
1766
1750
|
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* "" = magic to just enable */
|
1767
1751
|
}
|
1768
1752
|
}
|
1769
1753
|
|
1770
|
-
if (
|
1771
|
-
curl_easy_setopt(curl, CURLOPT_COOKIE,
|
1754
|
+
if (!rb_easy_nil("cookies")) {
|
1755
|
+
curl_easy_setopt(curl, CURLOPT_COOKIE, rb_easy_get_str("cookies"));
|
1772
1756
|
}
|
1773
1757
|
|
1774
1758
|
/* Set up HTTPS cert handling if necessary */
|
1775
|
-
if (
|
1776
|
-
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE,
|
1777
|
-
curl_easy_setopt(curl, CURLOPT_SSLCERT,
|
1778
|
-
if (
|
1779
|
-
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD,
|
1759
|
+
if (!rb_easy_nil("cert")) {
|
1760
|
+
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, rb_easy_get_str("certtype"));
|
1761
|
+
curl_easy_setopt(curl, CURLOPT_SSLCERT, rb_easy_get_str("cert"));
|
1762
|
+
if (!rb_easy_nil("certpassword")) {
|
1763
|
+
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, rb_easy_get_str("certpassword"));
|
1780
1764
|
}
|
1781
1765
|
}
|
1782
|
-
if (
|
1766
|
+
if (!rb_easy_nil("cacert")) {
|
1783
1767
|
#ifdef HAVE_CURL_CONFIG_CA
|
1784
1768
|
curl_easy_setopt(curl, CURLOPT_CAINFO, CURL_CONFIG_CA);
|
1785
1769
|
#else
|
@@ -1788,18 +1772,18 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
|
|
1788
1772
|
}
|
1789
1773
|
|
1790
1774
|
/* Set the user-agent string if specified */
|
1791
|
-
if (
|
1792
|
-
curl_easy_setopt(curl, CURLOPT_USERAGENT,
|
1775
|
+
if (!rb_easy_nil("useragent")) {
|
1776
|
+
curl_easy_setopt(curl, CURLOPT_USERAGENT, rb_easy_get_str("useragent"));
|
1793
1777
|
}
|
1794
1778
|
|
1795
1779
|
/* Setup HTTP headers if necessary */
|
1796
1780
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); // XXX: maybe we shouldn't be clearing this?
|
1797
1781
|
|
1798
|
-
if (
|
1799
|
-
if ((
|
1800
|
-
rb_iterate(rb_each,
|
1782
|
+
if (!rb_easy_nil("headers")) {
|
1783
|
+
if (rb_easy_type_check("headers", T_ARRAY) || rb_easy_type_check("headers", T_HASH)) {
|
1784
|
+
rb_iterate(rb_each, rb_easy_get("headers"), cb_each_http_header, (VALUE)hdrs);
|
1801
1785
|
} else {
|
1802
|
-
VALUE headers_str = rb_obj_as_string(
|
1786
|
+
VALUE headers_str = rb_obj_as_string(rb_easy_get("headers"));
|
1803
1787
|
*hdrs = curl_slist_append(*hdrs, StringValuePtr(headers_str));
|
1804
1788
|
}
|
1805
1789
|
|
@@ -1816,7 +1800,7 @@ VALUE ruby_curl_easy_setup( ruby_curl_easy *rbce, VALUE *body_buffer, VALUE *hea
|
|
1816
1800
|
*
|
1817
1801
|
* Always returns Qtrue.
|
1818
1802
|
*/
|
1819
|
-
VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce,
|
1803
|
+
VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, struct curl_slist *headers ) {
|
1820
1804
|
|
1821
1805
|
CURL *curl = rbce->curl;
|
1822
1806
|
|
@@ -1826,38 +1810,9 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, V
|
|
1826
1810
|
rbce->curl_headers = NULL;
|
1827
1811
|
}
|
1828
1812
|
|
1829
|
-
// Sort out the built-in body/header data.
|
1830
|
-
if (bodybuf != Qnil) {
|
1831
|
-
if (TYPE(bodybuf) == T_STRING) {
|
1832
|
-
rbce->body_data = rb_str_to_str(bodybuf);
|
1833
|
-
}
|
1834
|
-
else if (rb_respond_to(bodybuf, rb_intern("to_s"))) {
|
1835
|
-
rbce->body_data = rb_funcall(bodybuf, rb_intern("to_s"), 0);
|
1836
|
-
}
|
1837
|
-
else {
|
1838
|
-
rbce->body_data = Qnil;
|
1839
|
-
}
|
1840
|
-
} else {
|
1841
|
-
rbce->body_data = Qnil;
|
1842
|
-
}
|
1843
|
-
|
1844
|
-
if (headerbuf != Qnil) {
|
1845
|
-
if (TYPE(headerbuf) == T_STRING) {
|
1846
|
-
rbce->header_data = rb_str_to_str(headerbuf);
|
1847
|
-
}
|
1848
|
-
else if (rb_respond_to(headerbuf, rb_intern("to_s"))) {
|
1849
|
-
rbce->header_data = rb_funcall(headerbuf, rb_intern("to_s"), 0);
|
1850
|
-
}
|
1851
|
-
else {
|
1852
|
-
rbce->header_data = Qnil;
|
1853
|
-
}
|
1854
|
-
} else {
|
1855
|
-
rbce->header_data = Qnil;
|
1856
|
-
}
|
1857
|
-
|
1858
1813
|
// clean up a PUT request's curl options.
|
1859
|
-
if (
|
1860
|
-
|
1814
|
+
if (!rb_easy_nil("upload")) {
|
1815
|
+
rb_easy_del("upload"); // set the upload object to Qnil to let the GC clean up
|
1861
1816
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 0);
|
1862
1817
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
|
1863
1818
|
curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
|
@@ -1886,7 +1841,7 @@ static VALUE handle_perform(VALUE self, ruby_curl_easy *rbce) {
|
|
1886
1841
|
ret = rb_funcall(multi, rb_intern("perform"), 0);
|
1887
1842
|
|
1888
1843
|
/* check for errors in the easy response and raise exceptions if anything went wrong and their is no on_failure handler */
|
1889
|
-
if(
|
1844
|
+
if (rbce->last_result != 0 && rb_easy_nil("failure_proc")) {
|
1890
1845
|
raise_curl_easy_error_exception(rbce->last_result);
|
1891
1846
|
}
|
1892
1847
|
|
@@ -2134,7 +2089,7 @@ static VALUE ruby_curl_easy_class_perform_put(VALUE klass, VALUE url, VALUE data
|
|
2134
2089
|
* your own body handler, this string will be empty.
|
2135
2090
|
*/
|
2136
2091
|
static VALUE ruby_curl_easy_body_str_get(VALUE self) {
|
2137
|
-
|
2092
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
|
2138
2093
|
}
|
2139
2094
|
|
2140
2095
|
/*
|
@@ -2146,7 +2101,7 @@ static VALUE ruby_curl_easy_body_str_get(VALUE self) {
|
|
2146
2101
|
* your own header handler, this string will be empty.
|
2147
2102
|
*/
|
2148
2103
|
static VALUE ruby_curl_easy_header_str_get(VALUE self) {
|
2149
|
-
|
2104
|
+
CURB_OBJECT_HGETTER(ruby_curl_easy, header_data);
|
2150
2105
|
}
|
2151
2106
|
|
2152
2107
|
|
@@ -2691,11 +2646,12 @@ static VALUE ruby_curl_easy_inspect(VALUE self) {
|
|
2691
2646
|
ruby_curl_easy *rbce;
|
2692
2647
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2693
2648
|
/* if we don't have a url set... we'll crash... */
|
2694
|
-
if(
|
2695
|
-
|
2649
|
+
if( !rb_easy_nil("url") && rb_easy_type_check("url", T_STRING)) {
|
2650
|
+
VALUE url = rb_easy_get("url");
|
2651
|
+
size_t len = 13+((RSTRING_LEN(url) > 50) ? 50 : RSTRING_LEN(url));
|
2696
2652
|
/* "#<Net::HTTP http://www.google.com/:80 open=false>" */
|
2697
2653
|
memcpy(buf,"#<Curl::Easy ", 13);
|
2698
|
-
memcpy(buf+13,RSTRING_PTR(
|
2654
|
+
memcpy(buf+13,RSTRING_PTR(url), (len - 13));
|
2699
2655
|
buf[len-1] = '>';
|
2700
2656
|
return rb_str_new(buf,len);
|
2701
2657
|
}
|
data/ext/curb_easy.h
CHANGED
@@ -18,33 +18,7 @@ typedef struct {
|
|
18
18
|
/* The handler */
|
19
19
|
CURL *curl;
|
20
20
|
|
21
|
-
/*
|
22
|
-
VALUE url;
|
23
|
-
VALUE proxy_url;
|
24
|
-
|
25
|
-
VALUE body_proc;
|
26
|
-
VALUE header_proc;
|
27
|
-
VALUE body_data; /* Holds the response body from the last call to curl_easy_perform */
|
28
|
-
VALUE header_data; /* unless a block is supplied (they'll be nil) */
|
29
|
-
VALUE progress_proc;
|
30
|
-
VALUE debug_proc;
|
31
|
-
VALUE interface_hm;
|
32
|
-
VALUE userpwd;
|
33
|
-
VALUE proxypwd;
|
34
|
-
VALUE headers; /* ruby array of strings with headers to set */
|
35
|
-
VALUE cookies; /* string */
|
36
|
-
VALUE cookiefile; /* filename */
|
37
|
-
VALUE cookiejar; /* filename */
|
38
|
-
VALUE cert;
|
39
|
-
VALUE cacert;
|
40
|
-
VALUE certpassword;
|
41
|
-
VALUE certtype;
|
42
|
-
VALUE encoding;
|
43
|
-
VALUE useragent;
|
44
|
-
|
45
|
-
VALUE success_proc;
|
46
|
-
VALUE failure_proc;
|
47
|
-
VALUE complete_proc;
|
21
|
+
VALUE opts; /* rather then allocate everything we might need to store, allocate a Hash and only store objects we actually use... */
|
48
22
|
|
49
23
|
/* Other opts */
|
50
24
|
unsigned short local_port; // 0 is no port
|
@@ -71,39 +45,16 @@ typedef struct {
|
|
71
45
|
char verbose;
|
72
46
|
char multipart_form_post;
|
73
47
|
char enable_cookies;
|
74
|
-
|
75
|
-
/* this is sometimes used as a buffer for a form data string,
|
76
|
-
* which we alloc in C and need to hang around for the call,
|
77
|
-
* and in case it's asked for before the next call.
|
78
|
-
*/
|
79
|
-
VALUE postdata_buffer;
|
80
|
-
|
81
|
-
/* when added to a multi handle these buffers are needed
|
82
|
-
* when the easy handle isn't supplied the body proc
|
83
|
-
* or a custom http header is passed.
|
84
|
-
*/
|
85
|
-
VALUE bodybuf;
|
86
|
-
VALUE headerbuf;
|
87
48
|
struct curl_slist *curl_headers;
|
88
49
|
|
89
|
-
// VALUE self; /* pointer to self, used by multi interface */
|
90
|
-
VALUE upload; /* pointer to an active upload otherwise Qnil */
|
91
|
-
|
92
50
|
int last_result; /* last result code from multi loop */
|
93
51
|
|
94
|
-
#if HAVE_CURLOPT_USERNAME == 1
|
95
|
-
VALUE username;
|
96
|
-
#endif
|
97
|
-
#if HAVE_CURLOPT_PASSWORD == 1
|
98
|
-
VALUE password;
|
99
|
-
#endif
|
100
|
-
|
101
52
|
} ruby_curl_easy;
|
102
53
|
|
103
54
|
extern VALUE cCurlEasy;
|
104
55
|
|
105
|
-
VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce,
|
106
|
-
VALUE ruby_curl_easy_cleanup(VALUE self, ruby_curl_easy *rbce,
|
56
|
+
VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce, struct curl_slist **headers);
|
57
|
+
VALUE ruby_curl_easy_cleanup(VALUE self, ruby_curl_easy *rbce, struct curl_slist *headers);
|
107
58
|
|
108
59
|
void init_curb_easy();
|
109
60
|
|
data/ext/curb_macros.h
CHANGED
@@ -8,6 +8,17 @@
|
|
8
8
|
#ifndef __CURB_MACROS_H
|
9
9
|
#define __CURB_MACROS_H
|
10
10
|
|
11
|
+
#define rb_easy_hkey(key) ID2SYM(rb_intern(key))
|
12
|
+
#define rb_easy_set(key,val) rb_hash_aset(rbce->opts, rb_easy_hkey(key) , val)
|
13
|
+
#define rb_easy_get(key) rb_hash_aref(rbce->opts, rb_easy_hkey(key))
|
14
|
+
#define rb_easy_del(key) rb_hash_delete(rbce->opts, rb_easy_hkey(key))
|
15
|
+
#define rb_easy_nil(key) (rb_hash_lookup(rbce->opts, rb_easy_hkey(key)) == Qnil)
|
16
|
+
#define rb_easy_type_check(key,type) (rb_type(rb_hash_aref(rbce->opts, rb_easy_hkey(key))) == type)
|
17
|
+
|
18
|
+
// TODO: rb_sym_to_s may not be defined?
|
19
|
+
#define rb_easy_get_str(key) \
|
20
|
+
RSTRING_PTR((rb_easy_type_check(key,T_STRING) ? rb_easy_get(key) : rb_str_to_str(rb_easy_get(key))))
|
21
|
+
|
11
22
|
/* getter/setter macros for various things */
|
12
23
|
/* setter for anything that stores a ruby VALUE in the struct */
|
13
24
|
#define CURB_OBJECT_SETTER(type, attr) \
|
@@ -25,6 +36,22 @@
|
|
25
36
|
Data_Get_Struct(self, type, ptr); \
|
26
37
|
return ptr->attr;
|
27
38
|
|
39
|
+
/* setter for anything that stores a ruby VALUE in the struct opts hash */
|
40
|
+
#define CURB_OBJECT_HSETTER(type, attr) \
|
41
|
+
type *ptr; \
|
42
|
+
\
|
43
|
+
Data_Get_Struct(self, type, ptr); \
|
44
|
+
rb_hash_aset(ptr->opts, rb_easy_hkey(#attr), attr); \
|
45
|
+
\
|
46
|
+
return attr;
|
47
|
+
|
48
|
+
/* getter for anything that stores a ruby VALUE in the struct opts hash */
|
49
|
+
#define CURB_OBJECT_HGETTER(type, attr) \
|
50
|
+
type *ptr; \
|
51
|
+
\
|
52
|
+
Data_Get_Struct(self, type, ptr); \
|
53
|
+
return rb_hash_aref(ptr->opts, rb_easy_hkey(#attr));
|
54
|
+
|
28
55
|
/* setter for bool flags */
|
29
56
|
#define CURB_BOOLEAN_SETTER(type, attr) \
|
30
57
|
type *ptr; \
|
@@ -57,6 +84,20 @@
|
|
57
84
|
\
|
58
85
|
return oldproc; \
|
59
86
|
|
87
|
+
/* special setter for on_event handlers that take a block, same as above but stores int he opts hash */
|
88
|
+
#define CURB_HANDLER_PROC_HSETTER(type, handler) \
|
89
|
+
type *ptr; \
|
90
|
+
VALUE oldproc, newproc; \
|
91
|
+
\
|
92
|
+
Data_Get_Struct(self, type, ptr); \
|
93
|
+
\
|
94
|
+
oldproc = rb_hash_aref(ptr->opts, rb_easy_hkey(#handler)); \
|
95
|
+
rb_scan_args(argc, argv, "0&", &newproc); \
|
96
|
+
\
|
97
|
+
rb_hash_aset(ptr->opts, rb_easy_hkey(#handler), newproc); \
|
98
|
+
\
|
99
|
+
return oldproc;
|
100
|
+
|
60
101
|
/* setter for numerics that are kept in c ints */
|
61
102
|
#define CURB_IMMED_SETTER(type, attr, nilval) \
|
62
103
|
type *ptr; \
|
data/ext/curb_multi.c
CHANGED
@@ -200,7 +200,7 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
|
|
200
200
|
}
|
201
201
|
|
202
202
|
/* setup the easy handle */
|
203
|
-
ruby_curl_easy_setup( rbce, &(rbce->
|
203
|
+
ruby_curl_easy_setup( rbce, &(rbce->curl_headers) );
|
204
204
|
|
205
205
|
rbcm->active++;
|
206
206
|
|
@@ -253,9 +253,7 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
|
|
253
253
|
|
254
254
|
rbcm->active--;
|
255
255
|
|
256
|
-
ruby_curl_easy_cleanup( easy, rbce, rbce->
|
257
|
-
rbce->headerbuf = Qnil;
|
258
|
-
rbce->bodybuf = Qnil;
|
256
|
+
ruby_curl_easy_cleanup( easy, rbce, rbce->curl_headers );
|
259
257
|
|
260
258
|
// active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
|
261
259
|
r = rb_hash_delete( rbcm->requests, easy );
|
@@ -306,25 +304,25 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
306
304
|
|
307
305
|
ruby_curl_multi_remove( self, easy );
|
308
306
|
|
309
|
-
if (
|
310
|
-
rb_funcall(
|
307
|
+
if (!rb_easy_nil("complete_proc")) {
|
308
|
+
rb_funcall( rb_easy_get("complete_proc"), idCall, 1, easy );
|
311
309
|
}
|
312
310
|
|
313
311
|
curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &response_code);
|
314
312
|
|
315
313
|
if (result != 0) {
|
316
|
-
if (
|
317
|
-
rb_funcall(
|
314
|
+
if (!rb_easy_nil("failure_proc")) {
|
315
|
+
rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
|
318
316
|
}
|
319
317
|
}
|
320
|
-
else if (
|
318
|
+
else if (!rb_easy_nil("success_proc") &&
|
321
319
|
((response_code >= 200 && response_code < 300) || response_code == 0)) {
|
322
320
|
/* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
|
323
|
-
rb_funcall(
|
321
|
+
rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
|
324
322
|
}
|
325
|
-
else if (
|
323
|
+
else if (!rb_easy_nil("failure_proc") &&
|
326
324
|
(response_code >= 300 && response_code <= 999)) {
|
327
|
-
rb_funcall(
|
325
|
+
rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
|
328
326
|
}
|
329
327
|
}
|
330
328
|
|
data/ext/curb_postfield.c
CHANGED
@@ -41,7 +41,7 @@ void append_to_form(VALUE self,
|
|
41
41
|
// is a file upload field
|
42
42
|
if (rbcpf->content_proc != Qnil) {
|
43
43
|
// with content proc
|
44
|
-
rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, self);
|
44
|
+
rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, 1, self);
|
45
45
|
|
46
46
|
if (rbcpf->remote_file == Qnil) {
|
47
47
|
rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field with no filename");
|
@@ -468,10 +468,10 @@ static VALUE ruby_curl_postfield_to_str(VALUE self) {
|
|
468
468
|
}
|
469
469
|
}
|
470
470
|
} else {
|
471
|
-
rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string");
|
471
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string %s:%d", __FILE__, __LINE__);
|
472
472
|
}
|
473
473
|
} else {
|
474
|
-
rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string");
|
474
|
+
rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string %s:%d", __FILE__, __LINE__);
|
475
475
|
}
|
476
476
|
|
477
477
|
return result;
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# From GICodeWarrior:
|
2
|
+
#
|
3
|
+
# $ ruby crash_curb.rb
|
4
|
+
# crash_curb.rb:7: [BUG] Segmentation fault
|
5
|
+
# ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
|
6
|
+
#
|
7
|
+
# Aborted
|
8
|
+
# crash_curb.rb:
|
9
|
+
# #!/usr/bin/ruby
|
10
|
+
# require 'rubygems'
|
11
|
+
# require 'curb'
|
12
|
+
#
|
13
|
+
# curl = Curl::Easy.new('http://example.com/')
|
14
|
+
# curl.multipart_form_post = true
|
15
|
+
# curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
16
|
+
# Ubuntu 9.10
|
17
|
+
# curb gem version 0.6.2.1
|
18
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
19
|
+
|
20
|
+
class BugPostFieldsCrash < Test::Unit::TestCase
|
21
|
+
def test_crash
|
22
|
+
curl = Curl::Easy.new('http://example.com/')
|
23
|
+
curl.multipart_form_post = true
|
24
|
+
curl.http_post(Curl::PostField.file('test', 'test.xml'){'example data'})
|
25
|
+
end
|
26
|
+
end
|
data/tests/mem_check.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
#require 'rubygems'
|
3
|
+
#require 'rmem'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Run some tests to measure the memory usage of curb, these tests require fork and ps
|
7
|
+
#
|
8
|
+
class TestCurbMemory < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_easy_memory
|
11
|
+
easy_avg, easy_std = measure_object_memory(Curl::Easy)
|
12
|
+
printf "Easy average: %.2f kilobytes +/- %.2f kilobytes\n", easy_avg.to_f, easy_std.to_f
|
13
|
+
|
14
|
+
multi_avg, multi_std = measure_object_memory(Curl::Multi)
|
15
|
+
printf "Multi average: %.2f kilobytes +/- %.2f kilobytes\n", multi_avg.to_f, multi_std.to_f
|
16
|
+
|
17
|
+
# now that we have the average size of an easy handle lets see how much a multi request consumes with 10 requests
|
18
|
+
end
|
19
|
+
|
20
|
+
def c_avg(report)
|
21
|
+
sum = 0
|
22
|
+
report.each {|r| sum += r.last }
|
23
|
+
(sum.to_f / report.size)
|
24
|
+
end
|
25
|
+
|
26
|
+
def c_std(report,avg)
|
27
|
+
var = 0
|
28
|
+
report.each {|r| var += (r.last-avg)*(r.last-avg) }
|
29
|
+
Math.sqrt(var / (report.size-1))
|
30
|
+
end
|
31
|
+
|
32
|
+
def measure_object_memory(klass)
|
33
|
+
report = []
|
34
|
+
200.times do
|
35
|
+
res = mem_check do
|
36
|
+
obj = klass.new
|
37
|
+
end
|
38
|
+
report << res
|
39
|
+
end
|
40
|
+
avg = c_avg(report)
|
41
|
+
std = c_std(report,avg)
|
42
|
+
[avg,std]
|
43
|
+
end
|
44
|
+
|
45
|
+
def mem_check
|
46
|
+
# see: http://gist.github.com/264060 for inspiration of ps command line
|
47
|
+
rd, wr = IO.pipe
|
48
|
+
memory_usage = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
49
|
+
fork do
|
50
|
+
before = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
51
|
+
rd.close
|
52
|
+
yield
|
53
|
+
after = `ps -o rss= -p #{Process.pid}`.to_i # in kilobytes
|
54
|
+
wr.write((after - before))
|
55
|
+
wr.flush
|
56
|
+
wr.close
|
57
|
+
end
|
58
|
+
wr.close
|
59
|
+
total = rd.read.to_i
|
60
|
+
rd.close
|
61
|
+
Process.wait
|
62
|
+
# return the delta and the total
|
63
|
+
[memory_usage, total]
|
64
|
+
end
|
65
|
+
end
|
data/tests/s.rb
ADDED
data/tests/tc_curl_multi.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: curb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ross Bamford
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2010-01-14 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -32,18 +32,18 @@ files:
|
|
32
32
|
- lib/curb.rb
|
33
33
|
- lib/curl.rb
|
34
34
|
- ext/curb.c
|
35
|
-
- ext/curb_easy.c
|
36
|
-
- ext/curb_errors.c
|
37
|
-
- ext/curb_multi.c
|
38
35
|
- ext/curb_postfield.c
|
36
|
+
- ext/curb_multi.c
|
37
|
+
- ext/curb_errors.c
|
38
|
+
- ext/curb_easy.c
|
39
39
|
- ext/curb_upload.c
|
40
|
-
- ext/curb.h
|
41
40
|
- ext/curb_easy.h
|
42
41
|
- ext/curb_errors.h
|
42
|
+
- ext/curb_upload.h
|
43
43
|
- ext/curb_macros.h
|
44
|
-
- ext/
|
44
|
+
- ext/curb.h
|
45
45
|
- ext/curb_postfield.h
|
46
|
-
- ext/
|
46
|
+
- ext/curb_multi.h
|
47
47
|
has_rdoc: true
|
48
48
|
homepage: http://curb.rubyforge.org/
|
49
49
|
licenses: []
|
@@ -75,15 +75,18 @@ signing_key:
|
|
75
75
|
specification_version: 3
|
76
76
|
summary: Ruby libcurl bindings
|
77
77
|
test_files:
|
78
|
-
- tests/
|
78
|
+
- tests/tc_curl_multi.rb
|
79
|
+
- tests/tc_curl_postfield.rb
|
79
80
|
- tests/bug_curb_easy_blocks_ruby_threads.rb
|
80
|
-
- tests/
|
81
|
-
- tests/
|
81
|
+
- tests/unittests.rb
|
82
|
+
- tests/mem_check.rb
|
82
83
|
- tests/bug_require_last_or_segfault.rb
|
83
|
-
- tests/
|
84
|
-
- tests/require_last_or_segfault_script.rb
|
84
|
+
- tests/bug_instance_post_differs_from_class_post.rb
|
85
85
|
- tests/tc_curl_download.rb
|
86
|
+
- tests/alltests.rb
|
87
|
+
- tests/helper.rb
|
86
88
|
- tests/tc_curl_easy.rb
|
87
|
-
- tests/
|
88
|
-
- tests/
|
89
|
-
- tests/
|
89
|
+
- tests/bug_multi_segfault.rb
|
90
|
+
- tests/require_last_or_segfault_script.rb
|
91
|
+
- tests/bug_postfields_crash.rb
|
92
|
+
- tests/s.rb
|