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 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.2.1"
24
- #define CURB_VER_NUM 621
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 2
28
- #define CURB_VER_PATCH 1
27
+ #define CURB_VER_MIC 4
28
+ #define CURB_VER_PATCH 0
29
29
 
30
30
 
31
31
  // Maybe not yet defined in Ruby
@@ -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(rbce->upload);
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(rbce->upload, ruby_curl_upload, rbcu);
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
- /* assoc objects */
211
- rbce->url = url;
212
- rbce->proxy_url = Qnil;
213
- rbce->body_data = Qnil;
214
- rbce->body_proc = Qnil;
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
- CURB_OBJECT_SETTER(ruby_curl_easy, url);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, url);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, proxy_url);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, proxy_url);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, headers);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, headers);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, interface_hm);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, interface_hm);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, userpwd);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, userpwd);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, proxypwd);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, proxypwd);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, cookies);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, cookies);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, cookiefile);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, cookiefile);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, cookiejar);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, cookiejar);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, cert);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, cert);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, cacert);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, cacert);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, certpassword);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, certtype);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, certtype);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, encoding);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, encoding);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, useragent);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, useragent);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, postdata_buffer);
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
- rbce->upload = upload; /* keep the upload object alive as long as
740
- the easy handle is active or until the upload
741
- is complete or terminated... */
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 (rbce->headers != Qnil) {
753
- if (rb_type(rbce->headers) == T_ARRAY || rb_type(rbce->headers) == T_STRING) {
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(rbce->headers, rb_str_new2("Expect")) == Qnil ) {
763
- rb_hash_aset(rbce->headers, rb_str_new2("Expect"), rb_str_new2(""));
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(rbce->headers, rb_str_new2("Transfer-Encoding")) == Qnil ) {
769
- rb_hash_aset(rbce->headers, rb_str_new2("Transfer-Encoding"), rb_str_new2("chunked"));
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(rbce->headers, rb_str_new2("Expect")) == Qnil ) {
775
- rb_hash_aset(rbce->headers, rb_str_new2("Expect"), rb_str_new2(""));
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
- CURB_OBJECT_SETTER(ruby_curl_easy, username);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, username);
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
- CURB_OBJECT_SETTER(ruby_curl_easy, password);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, password);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, body_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, success_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, failure_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, complete_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, header_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, progress_proc);
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
- CURB_HANDLER_PROC_SETTER(ruby_curl_easy, debug_proc);
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, VALUE *body_buffer, VALUE *header_buffer, struct curl_slist **hdrs ) {
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 (rbce->url == Qnil) {
1555
+ if (_url == Qnil) {
1574
1556
  rb_raise(eCurlErrError, "No URL supplied");
1575
1557
  }
1576
1558
 
1577
- url = rb_check_string_type(rbce->url);
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 (rbce->interface_hm != Qnil) {
1584
- curl_easy_setopt(curl, CURLOPT_INTERFACE, StringValuePtr(rbce->interface_hm));
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 (rbce->username != Qnil) {
1591
- curl_easy_setopt(curl, CURLOPT_USERNAME, StringValuePtr(rbce->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 (rbce->password != Qnil) {
1596
- curl_easy_setopt(curl, CURLOPT_PASSWORD, StringValuePtr(rbce->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 (rbce->userpwd != Qnil) {
1604
- curl_easy_setopt(curl, CURLOPT_USERPWD, StringValuePtr(rbce->userpwd));
1605
- #if HAVE_CURLOPT_USERNAME
1606
- } else if (rbce->username == Qnil && rbce->password == Qnil) { /* don't set this even to NULL if we have set username and password */
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 (rbce->proxy_url != Qnil) {
1614
- curl_easy_setopt(curl, CURLOPT_PROXY, StringValuePtr(rbce->proxy_url));
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 (rbce->proxypwd != Qnil) {
1620
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, StringValuePtr(rbce->proxypwd));
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 (rbce->body_proc != Qnil) {
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
- *body_buffer = rb_str_buf_new(32768);
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, *body_buffer);
1616
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, body_buffer);
1634
1617
  }
1635
1618
 
1636
- if (rbce->header_proc != Qnil) {
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, rbce->header_proc);
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
- *header_buffer = rb_str_buf_new(32768);
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, *header_buffer);
1627
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, header_buffer);
1644
1628
  }
1645
1629
 
1646
1630
  /* encoding */
1647
- if (rbce->encoding != Qnil) {
1648
- curl_easy_setopt(curl, CURLOPT_ENCODING, StringValuePtr(rbce->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 (rbce->progress_proc != Qnil) {
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, rbce->progress_proc);
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 (rbce->debug_proc != Qnil) {
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, rbce->debug_proc);
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 (rbce->cookiejar != Qnil) {
1760
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR, StringValuePtr(rbce->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 (rbce->cookiefile != Qnil) {
1764
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, StringValuePtr(rbce->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 (rbce->cookies != Qnil) {
1771
- curl_easy_setopt(curl, CURLOPT_COOKIE, StringValuePtr(rbce->cookies));
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 (rbce->cert != Qnil) {
1776
- curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, StringValuePtr(rbce->certtype));
1777
- curl_easy_setopt(curl, CURLOPT_SSLCERT, StringValuePtr(rbce->cert));
1778
- if (rbce->certpassword != Qnil) {
1779
- curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, StringValuePtr(rbce->certpassword));
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 (rbce->cacert != Qnil) {
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 (rbce->useragent != Qnil) {
1792
- curl_easy_setopt(curl, CURLOPT_USERAGENT, StringValuePtr(rbce->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 (rbce->headers != Qnil) {
1799
- if ((rb_type(rbce->headers) == T_ARRAY) || (rb_type(rbce->headers) == T_HASH)) {
1800
- rb_iterate(rb_each, rbce->headers, cb_each_http_header, (VALUE)hdrs);
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(rbce->headers);
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, VALUE bodybuf, VALUE headerbuf, struct curl_slist *headers ) {
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 (rbce->upload != Qnil) {
1860
- rbce->upload = Qnil; // set the upload object to Qnil to let the GC clean up
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( rbce->last_result != 0 && rbce->failure_proc == Qnil ) {
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
- CURB_OBJECT_GETTER(ruby_curl_easy, body_data);
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
- CURB_OBJECT_GETTER(ruby_curl_easy, header_data);
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(rbce->url != Qnil && rb_type(rbce->url) == T_STRING) {
2695
- size_t len = 13+((RSTRING_LEN(rbce->url) > 50) ? 50 : RSTRING_LEN(rbce->url));
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(rbce->url), (len - 13));
2654
+ memcpy(buf+13,RSTRING_PTR(url), (len - 13));
2699
2655
  buf[len-1] = '>';
2700
2656
  return rb_str_new(buf,len);
2701
2657
  }
@@ -18,33 +18,7 @@ typedef struct {
18
18
  /* The handler */
19
19
  CURL *curl;
20
20
 
21
- /* Objects we associate */
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, VALUE *bodybuf, VALUE *headerbuf, struct curl_slist **headers);
106
- VALUE ruby_curl_easy_cleanup(VALUE self, ruby_curl_easy *rbce, VALUE bodybuf, VALUE headerbuf, struct curl_slist *headers);
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
 
@@ -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; \
@@ -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->bodybuf), &(rbce->headerbuf), &(rbce->curl_headers) );
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->bodybuf, rbce->headerbuf, rbce->curl_headers );
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 (rbce->complete_proc != Qnil) {
310
- rb_funcall( rbce->complete_proc, idCall, 1, easy );
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 (rbce->failure_proc != Qnil) {
317
- rb_funcall( rbce->failure_proc, idCall, 2, easy, rb_curl_easy_error(result) );
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 (rbce->success_proc != Qnil &&
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( rbce->success_proc, idCall, 1, easy );
321
+ rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
324
322
  }
325
- else if (rbce->failure_proc != Qnil &&
323
+ else if (!rb_easy_nil("failure_proc") &&
326
324
  (response_code >= 300 && response_code <= 999)) {
327
- rb_funcall( rbce->failure_proc, idCall, 2, easy, rb_curl_easy_error(result) );
325
+ rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
328
326
  }
329
327
  }
330
328
 
@@ -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
@@ -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
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ c = Curl::Easy.new("http://www.google.com/")
4
+ c.perform
@@ -44,7 +44,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
44
44
 
45
45
  m.perform do
46
46
  # idle
47
- puts "idling..."
47
+ #puts "idling..."
48
48
  end
49
49
 
50
50
  assert_match(/^# DO NOT REMOVE THIS COMMENT/, c1.body_str)
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.2.1
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: 2009-12-26 00:00:00 -05:00
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/curb_multi.h
44
+ - ext/curb.h
45
45
  - ext/curb_postfield.h
46
- - ext/curb_upload.h
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/alltests.rb
78
+ - tests/tc_curl_multi.rb
79
+ - tests/tc_curl_postfield.rb
79
80
  - tests/bug_curb_easy_blocks_ruby_threads.rb
80
- - tests/bug_instance_post_differs_from_class_post.rb
81
- - tests/bug_multi_segfault.rb
81
+ - tests/unittests.rb
82
+ - tests/mem_check.rb
82
83
  - tests/bug_require_last_or_segfault.rb
83
- - tests/helper.rb
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/tc_curl_multi.rb
88
- - tests/tc_curl_postfield.rb
89
- - tests/unittests.rb
89
+ - tests/bug_multi_segfault.rb
90
+ - tests/require_last_or_segfault_script.rb
91
+ - tests/bug_postfields_crash.rb
92
+ - tests/s.rb