curb 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18ca81b9cb8fd33720ab17ba3eff9e9ae4fa1a10542feb60897ac94d7cd801ac
4
- data.tar.gz: e8747cc63a63ca1561288dd9480b6c30c9dda0a371a6909eb1e2ad2a9a8b6947
3
+ metadata.gz: 805549f6e3fe9190d76c507fa67bf6f6e2a6bbe65bde611cb3aeee6c78cad51f
4
+ data.tar.gz: 7f6cab9c618e4535e7ff46b48d11bb5f307158d850b95bd560432dfeb9ea3144
5
5
  SHA512:
6
- metadata.gz: 112d4c34fd70b3b77a58e133b9c873d5ac7f850d2644fe02a9713771b47be636cfbc2c66b44bbf59e047cc84d83aa496c2e67cbfd8f2987509577589a87d20f0
7
- data.tar.gz: a593f46d71b17af90cb9244ee7a92c133eca76024146d9097806f91ec70f34b4611988141063a7624fd51ea103d872495e1efa94b2b6d718ee0a700ca86ef325
6
+ metadata.gz: 98f411070f4c3ef1646de29052a2c9a37e7aa2c9009102a7f4e483d1d1188d8bbdae50647e6dd4c8c7439120619e22df5f8c90bba6e1a088e2762cc29109c63d
7
+ data.tar.gz: bb8ad84d03972d1e42ce61622060019edc4d6286bab9ab459d2fe9e8ccd3cdc04490a8ba58715fd4efa30e3babf82ac96afce3f5b80fddd1d0bd4d47b197a5f1
data/ext/curb.h CHANGED
@@ -28,11 +28,11 @@
28
28
  #include "curb_macros.h"
29
29
 
30
30
  // These should be managed from the Rake 'release' task.
31
- #define CURB_VERSION "1.0.6"
32
- #define CURB_VER_NUM 1006
31
+ #define CURB_VERSION "1.0.7"
32
+ #define CURB_VER_NUM 1007
33
33
  #define CURB_VER_MAJ 1
34
34
  #define CURB_VER_MIN 0
35
- #define CURB_VER_MIC 6
35
+ #define CURB_VER_MIC 7
36
36
  #define CURB_VER_PATCH 0
37
37
 
38
38
 
data/ext/curb_easy.c CHANGED
@@ -31,6 +31,7 @@ static FILE * rb_io_stdio_file(rb_io_t *fptr) {
31
31
  return fptr->f;
32
32
  }
33
33
  #endif
34
+ static struct curl_slist *duplicate_curl_slist(struct curl_slist *list);
34
35
 
35
36
  /* ================== CURL HANDLER FUNCS ==============*/
36
37
 
@@ -264,7 +265,7 @@ void curl_easy_free(ruby_curl_easy *rbce) {
264
265
  static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
265
266
  rbce->opts = rb_hash_new();
266
267
 
267
- memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
268
+ memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
268
269
 
269
270
  rbce->curl_headers = NULL;
270
271
  rbce->curl_proxy_headers = NULL;
@@ -370,6 +371,16 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
370
371
  return self;
371
372
  }
372
373
 
374
+ /* Helper to duplicate a curl_slist */
375
+ static struct curl_slist *duplicate_curl_slist(struct curl_slist *list) {
376
+ struct curl_slist *dup = NULL;
377
+ struct curl_slist *tmp;
378
+ for (tmp = list; tmp; tmp = tmp->next) {
379
+ dup = curl_slist_append(dup, tmp->data);
380
+ }
381
+ return dup;
382
+ }
383
+
373
384
  /*
374
385
  * call-seq:
375
386
  * easy.clone => <easy clone>
@@ -384,14 +395,22 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
384
395
  Data_Get_Struct(self, ruby_curl_easy, rbce);
385
396
 
386
397
  newrbce = ALLOC(ruby_curl_easy);
398
+ /* shallow copy */
387
399
  memcpy(newrbce, rbce, sizeof(ruby_curl_easy));
400
+
401
+ /* now deep copy */
388
402
  newrbce->curl = curl_easy_duphandle(rbce->curl);
389
- newrbce->curl_headers = NULL;
390
- newrbce->curl_proxy_headers = NULL;
391
- newrbce->curl_ftp_commands = NULL;
392
- newrbce->curl_resolve = NULL;
403
+ newrbce->curl_headers = (rbce->curl_headers) ? duplicate_curl_slist(rbce->curl_headers) : NULL;
404
+ newrbce->curl_proxy_headers = (rbce->curl_proxy_headers) ? duplicate_curl_slist(rbce->curl_proxy_headers) : NULL;
405
+ newrbce->curl_ftp_commands = (rbce->curl_ftp_commands) ? duplicate_curl_slist(rbce->curl_ftp_commands) : NULL;
406
+ newrbce->curl_resolve = (rbce->curl_resolve) ? duplicate_curl_slist(rbce->curl_resolve) : NULL;
393
407
 
394
- curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
408
+ if (rbce->opts != Qnil) {
409
+ newrbce->opts = rb_funcall(rbce->opts, rb_intern("dup"), 0);
410
+ }
411
+
412
+ /* Set the error buffer on the new curl handle using the new err_buf */
413
+ curl_easy_setopt(newrbce->curl, CURLOPT_ERRORBUFFER, newrbce->err_buf);
395
414
 
396
415
  return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
397
416
  }
@@ -2614,7 +2633,7 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
2614
2633
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2615
2634
  curl = rbce->curl;
2616
2635
 
2617
- memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
2636
+ memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
2618
2637
 
2619
2638
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
2620
2639
 
@@ -2681,7 +2700,7 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
2681
2700
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2682
2701
  curl = rbce->curl;
2683
2702
 
2684
- memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
2703
+ memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
2685
2704
 
2686
2705
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2687
2706
 
@@ -2754,7 +2773,7 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
2754
2773
  Data_Get_Struct(self, ruby_curl_easy, rbce);
2755
2774
  curl = rbce->curl;
2756
2775
 
2757
- memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
2776
+ memset(rbce->err_buf, 0, CURL_ERROR_SIZE);
2758
2777
 
2759
2778
  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
2760
2779
  ruby_curl_easy_put_data_set(self, data);
@@ -3364,14 +3383,16 @@ static VALUE ruby_curl_easy_num_connects_get(VALUE self) {
3364
3383
 
3365
3384
  /*
3366
3385
  * call-seq:
3367
- * easy.cookielist => array
3386
+ * easy.cookielist => cookielist
3368
3387
  *
3369
3388
  * Retrieves the cookies curl knows in an array of strings.
3370
3389
  * Returned strings are in Netscape cookiejar format or in Set-Cookie format.
3390
+ * Since 7.43.0 cookies in the Set-Cookie format without a domain name are not exported.
3371
3391
  *
3372
- * See also option CURLINFO_COOKIELIST of curl_easy_getopt(3) to see how libcurl behaves.
3373
- *
3374
- * (requires libcurl 7.14.1 or higher, otherwise -1 is always returned).
3392
+ * @see https://curl.se/libcurl/c/CURLINFO_COOKIELIST.html option <code>CURLINFO_COOKIELIST</code> of
3393
+ * <code>curl_easy_getopt(3)</code> to see how libcurl behaves.
3394
+ * @note requires libcurl 7.14.1 or higher, otherwise +-1+ is always returned
3395
+ * @return [Array<String>, nil, -1] array of strings, or +nil+ if there are no cookies, or +-1+ if the libcurl version is too old
3375
3396
  */
3376
3397
  static VALUE ruby_curl_easy_cookielist_get(VALUE self) {
3377
3398
  #ifdef HAVE_CURLINFO_COOKIELIST
@@ -3482,9 +3503,16 @@ static VALUE ruby_curl_easy_last_error(VALUE self) {
3482
3503
 
3483
3504
  /*
3484
3505
  * call-seq:
3485
- * easy.setopt Fixnum, value => value
3506
+ * easy.setopt(opt, val) => val
3486
3507
  *
3487
3508
  * Initial access to libcurl curl_easy_setopt
3509
+ *
3510
+ * @param [Fixnum] opt The option to set, see +Curl::CURLOPT_*+ constants
3511
+ * @param [Object] val
3512
+ * @return [Object] val
3513
+ * @raise [TypeError] if the option is not supported
3514
+ * @note Some options - like url or cookie - aren't set directly throught +curl_easy_setopt+, but stored in the Ruby object state.
3515
+ * @note When +curl_easy_setopt+ is called, return value is not checked here.
3488
3516
  */
3489
3517
  static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3490
3518
  ruby_curl_easy *rbce;
@@ -3650,6 +3678,11 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3650
3678
  curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
3651
3679
  break;
3652
3680
  #endif
3681
+ #if HAVE_CURLOPT_COOKIELIST
3682
+ case CURLOPT_COOKIELIST: {
3683
+ curl_easy_setopt(rbce->curl, CURLOPT_COOKIELIST, StringValueCStr(val));
3684
+ } break;
3685
+ #endif
3653
3686
  #if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
3654
3687
  case CURLOPT_PROXY_SSL_VERIFYHOST:
3655
3688
  curl_easy_setopt(rbce->curl, CURLOPT_PROXY_SSL_VERIFYHOST, NUM2LONG(val));
@@ -3664,9 +3697,13 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3664
3697
 
3665
3698
  /*
3666
3699
  * call-seq:
3667
- * easy.getinfo Fixnum => value
3700
+ * easy.getinfo(opt) => nil
3668
3701
  *
3669
3702
  * Iniital access to libcurl curl_easy_getinfo, remember getinfo doesn't return the same values as setopt
3703
+ *
3704
+ * @note This method is not implemented yet.
3705
+ * @param [Fixnum] code Constant +CURLINFO_*+ from libcurl
3706
+ * @return [nil]
3670
3707
  */
3671
3708
  static VALUE ruby_curl_easy_get_opt(VALUE self, VALUE opt) {
3672
3709
  return Qnil;
data/ext/curb_multi.c CHANGED
@@ -27,6 +27,21 @@
27
27
  #include <fcntl.h>
28
28
  #endif
29
29
 
30
+ #ifdef HAVE_CURL_MULTI_WAIT
31
+ #include <stdint.h> /* for intptr_t */
32
+
33
+ struct wait_args {
34
+ CURLM *handle;
35
+ long timeout_ms;
36
+ int numfds;
37
+ };
38
+ static void *curl_multi_wait_wrapper(void *p) {
39
+ struct wait_args *args = p;
40
+ CURLMcode code = curl_multi_wait(args->handle, NULL, 0, args->timeout_ms, &args->numfds);
41
+ return (void *)(intptr_t)code;
42
+ }
43
+ #endif
44
+
30
45
  extern VALUE mCurl;
31
46
  static VALUE idCall;
32
47
 
@@ -226,6 +241,8 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
226
241
 
227
242
  mcode = curl_multi_add_handle(rbcm->handle, rbce->curl);
228
243
  if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
244
+ ruby_curl_easy_cleanup(easy, rbce);
245
+
229
246
  raise_curl_multi_error_exception(mcode);
230
247
  }
231
248
 
@@ -264,6 +281,7 @@ VALUE ruby_curl_multi_remove(VALUE self, VALUE rb_easy_handle) {
264
281
 
265
282
  return self;
266
283
  }
284
+
267
285
  static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
268
286
  CURLMcode result;
269
287
  ruby_curl_easy *rbce;
@@ -528,7 +546,6 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
528
546
 
529
547
  do {
530
548
  while (rbcm->running) {
531
-
532
549
  #ifdef HAVE_CURL_MULTI_TIMEOUT
533
550
  /* get the curl suggested time out */
534
551
  mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
@@ -552,6 +569,31 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
552
569
  /* or buggy versions libcurl sometimes reports huge timeouts... let's cap it */
553
570
  }
554
571
 
572
+ #ifdef HAVE_CURL_MULTI_WAIT
573
+ {
574
+ struct wait_args wait_args;
575
+ wait_args.handle = rbcm->handle;
576
+ wait_args.timeout_ms = timeout_milliseconds;
577
+ wait_args.numfds = 0;
578
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
579
+ CURLMcode wait_rc = (CURLMcode)(intptr_t)
580
+ rb_thread_call_without_gvl(curl_multi_wait_wrapper, &wait_args, RUBY_UBF_IO, NULL);
581
+ #else
582
+ CURLMcode wait_rc = curl_multi_wait(rbcm->handle, NULL, 0, timeout_milliseconds, &wait_args.numfds);
583
+ #endif
584
+ if (wait_rc != CURLM_OK) {
585
+ raise_curl_multi_error_exception(wait_rc);
586
+ }
587
+ if (wait_args.numfds == 0) {
588
+ rb_thread_wait_for(tv_100ms);
589
+ }
590
+ /* Process pending transfers after waiting */
591
+ rb_curl_multi_run(self, rbcm->handle, &(rbcm->running));
592
+ rb_curl_multi_read_info(self, rbcm->handle);
593
+ if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
594
+ }
595
+ #else
596
+
555
597
  tv.tv_sec = 0; /* never wait longer than 1 second */
556
598
  tv.tv_usec = (int)(timeout_milliseconds * 1000); /* XXX: int is the right type for OSX, what about linux? */
557
599
 
@@ -618,6 +660,7 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
618
660
  if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
619
661
  break;
620
662
  }
663
+ #endif /* HAVE_CURL_MULTI_WAIT */
621
664
  }
622
665
 
623
666
  } while( rbcm->running );
data/ext/curb_postfield.c CHANGED
@@ -421,71 +421,108 @@ static VALUE ruby_curl_postfield_content_proc_set(int argc, VALUE *argv, VALUE s
421
421
  * Only content fields may be converted to strings.
422
422
  */
423
423
  static VALUE ruby_curl_postfield_to_str(VALUE self) {
424
- // FIXME This is using the deprecated curl_escape func
425
424
  ruby_curl_postfield *rbcpf;
426
425
  VALUE result = Qnil;
427
426
  VALUE name = Qnil;
428
427
  char *tmpchrs;
429
-
428
+ #ifdef HAVE_CURL_EASY_ESCAPE
429
+ CURL *curl_handle = NULL;
430
+ #endif
431
+
430
432
  Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
431
433
 
432
- if (rbcpf->name != Qnil) {
433
- name = rbcpf->name;
434
- if (rb_type(name) == T_STRING) {
435
- name = rbcpf->name;
436
- } else if (rb_respond_to(name,rb_intern("to_s"))) {
434
+ if (rbcpf->name != Qnil) {
435
+ name = rbcpf->name;
436
+ if (TYPE(name) != T_STRING) {
437
+ if (rb_respond_to(name, rb_intern("to_s")))
437
438
  name = rb_funcall(name, rb_intern("to_s"), 0);
438
- }
439
- else {
440
- name = Qnil; // we can't handle this object
441
- }
442
- }
443
- if (name == Qnil) {
444
- rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s", __FILE__, __LINE__);
439
+ else
440
+ name = Qnil;
445
441
  }
442
+ }
443
+ if (name == Qnil) {
444
+ rb_raise(eCurlErrInvalidPostField,
445
+ "Cannot convert unnamed field to string %s:%d, make sure your field name responds_to :to_s",
446
+ __FILE__, __LINE__);
447
+ }
448
+ /* Force field name to UTF-8 before escaping */
449
+ VALUE name_utf8 = rb_str_export_to_enc(name, rb_utf8_encoding());
446
450
 
447
- tmpchrs = curl_escape(StringValuePtr(name), (int)RSTRING_LEN(name));
448
-
449
- if (!tmpchrs) {
450
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
451
- } else {
452
- VALUE tmpcontent = Qnil;
453
- VALUE escd_name = rb_str_new2(tmpchrs);
454
- curl_free(tmpchrs);
455
-
456
- if (rbcpf->content_proc != Qnil) {
457
- tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
458
- } else if (rbcpf->content != Qnil) {
459
- tmpcontent = rbcpf->content;
460
- } else if (rbcpf->local_file != Qnil) {
461
- tmpcontent = rbcpf->local_file;
462
- } else if (rbcpf->remote_file != Qnil) {
463
- tmpcontent = rbcpf->remote_file;
464
- } else {
465
- tmpcontent = rb_str_new2("");
466
- }
467
- if (TYPE(tmpcontent) != T_STRING) {
468
- if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
469
- tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
470
- }
471
- else {
472
- rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
473
- }
474
- }
475
- //fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
476
- tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), (int)RSTRING_LEN(tmpcontent));
477
- if (!tmpchrs) {
478
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
479
- } else {
480
- VALUE escd_content = rb_str_new2(tmpchrs);
481
- curl_free(tmpchrs);
482
-
483
- result = escd_name;
484
- rb_str_cat(result, "=", 1);
485
- rb_str_concat(result, escd_content);
486
- }
451
+ #ifdef HAVE_CURL_EASY_ESCAPE
452
+ curl_handle = curl_easy_init();
453
+ if (!curl_handle) {
454
+ rb_raise(eCurlErrInvalidPostField, "Failed to initialize curl handle for escaping");
455
+ }
456
+ tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
457
+ if (!tmpchrs) {
458
+ curl_easy_cleanup(curl_handle);
459
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
460
+ }
461
+ #else
462
+ tmpchrs = curl_escape(StringValuePtr(name_utf8), (int)RSTRING_LEN(name_utf8));
463
+ if (!tmpchrs) {
464
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name");
465
+ }
466
+ #endif
467
+
468
+ VALUE escd_name = rb_str_new2(tmpchrs);
469
+ #ifdef HAVE_CURL_EASY_ESCAPE
470
+ curl_free(tmpchrs);
471
+ #else
472
+ curl_free(tmpchrs);
473
+ #endif
474
+
475
+ VALUE tmpcontent = Qnil;
476
+ if (rbcpf->content_proc != Qnil) {
477
+ tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
478
+ } else if (rbcpf->content != Qnil) {
479
+ tmpcontent = rbcpf->content;
480
+ } else if (rbcpf->local_file != Qnil) {
481
+ tmpcontent = rbcpf->local_file;
482
+ } else if (rbcpf->remote_file != Qnil) {
483
+ tmpcontent = rbcpf->remote_file;
484
+ } else {
485
+ tmpcontent = rb_str_new2("");
486
+ }
487
+ if (TYPE(tmpcontent) != T_STRING) {
488
+ if (rb_respond_to(tmpcontent, rb_intern("to_s")))
489
+ tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
490
+ else {
491
+ #ifdef HAVE_CURL_EASY_ESCAPE
492
+ curl_easy_cleanup(curl_handle);
493
+ #endif
494
+ rb_raise(rb_eRuntimeError,
495
+ "postfield(%s) is not a string and does not respond_to to_s",
496
+ RSTRING_PTR(escd_name));
487
497
  }
488
-
498
+ }
499
+ /* Force content to UTF-8 before escaping */
500
+ VALUE content_utf8 = rb_str_export_to_enc(tmpcontent, rb_utf8_encoding());
501
+ #ifdef HAVE_CURL_EASY_ESCAPE
502
+ tmpchrs = curl_easy_escape(curl_handle, StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
503
+ if (!tmpchrs) {
504
+ curl_easy_cleanup(curl_handle);
505
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
506
+ }
507
+ #else
508
+ tmpchrs = curl_escape(StringValuePtr(content_utf8), (int)RSTRING_LEN(content_utf8));
509
+ if (!tmpchrs) {
510
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content");
511
+ }
512
+ #endif
513
+
514
+ VALUE escd_content = rb_str_new2(tmpchrs);
515
+ #ifdef HAVE_CURL_EASY_ESCAPE
516
+ curl_free(tmpchrs);
517
+ curl_easy_cleanup(curl_handle);
518
+ #else
519
+ curl_free(tmpchrs);
520
+ #endif
521
+
522
+ result = escd_name;
523
+ rb_str_cat(result, "=", 1);
524
+ rb_str_concat(result, escd_content);
525
+
489
526
  return result;
490
527
  }
491
528
 
data/ext/extconf.rb CHANGED
@@ -467,6 +467,8 @@ have_func('rb_thread_blocking_region')
467
467
  have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
468
468
  have_header('ruby/io.h')
469
469
  have_func('rb_io_stdio_file')
470
+ have_func('curl_multi_wait')
471
+ have_func('curl_easy_duphandle')
470
472
 
471
473
  create_header('curb_config.h')
472
474
  create_makefile('curb_core')
data/lib/curl/multi.rb CHANGED
@@ -95,7 +95,7 @@ module Curl
95
95
 
96
96
  # configure the multi handle
97
97
  multi_options.each { |k,v| m.send("#{k}=", v) }
98
- callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_redirect,:on_body,:on_header]
98
+ callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_redirect,:on_missing,:on_body,:on_header]
99
99
 
100
100
  add_free_handle = proc do|conf, easy|
101
101
  c = conf.dup # avoid being destructive to input
data/tests/helper.rb CHANGED
@@ -80,6 +80,10 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
80
80
  res.status = 404
81
81
  elsif req.path.match(/error$/)
82
82
  res.status = 500
83
+ elsif req.path.match(/get_cookies$/)
84
+ res['Content-Type'] = "text/plain"
85
+ res.body = req['Cookie']
86
+ return
83
87
  end
84
88
  respond_with("GET#{req.query_string}",req,res)
85
89
  end
@@ -90,7 +94,18 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
90
94
  end
91
95
 
92
96
  def do_POST(req,res)
93
- if req.query['filename'].nil?
97
+ if req.path.match(/set_cookies$/)
98
+ JSON.parse(req.body || '[]', symbolize_names: true).each do |hash|
99
+ cookie = WEBrick::Cookie.new(hash.fetch(:name), hash.fetch(:value))
100
+ cookie.domain = hash[:domain] if hash.key?(:domain)
101
+ cookie.expires = hash[:expires] if hash.key?(:expires)
102
+ cookie.path = hash[:path] if hash.key?(:path)
103
+ cookie.secure = hash[:secure] if hash.key?(:secure)
104
+ cookie.max_age = hash[:max_age] if hash.key?(:max_age)
105
+ res.cookies.push(cookie)
106
+ end
107
+ respond_with('OK', req, res)
108
+ elsif req.query['filename'].nil?
94
109
  if req.body
95
110
  params = {}
96
111
  req.body.split('&').map{|s| k,v=s.split('='); params[k] = v }
@@ -110,7 +110,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
110
110
  end
111
111
 
112
112
  def test_class_perform_02
113
- data = ""
113
+ data = String.new
114
114
  assert_instance_of Curl::Easy, c = Curl::Easy.perform($TEST_URL) { |curl| curl.on_body { |d| data << d; d.length } }
115
115
 
116
116
  assert_nil c.body_str
@@ -211,7 +211,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
211
211
  end
212
212
 
213
213
  def test_get_02
214
- data = ""
214
+ data = String.new
215
215
  c = Curl::Easy.new($TEST_URL) do |curl|
216
216
  curl.on_body { |d| data << d; d.length }
217
217
  end
@@ -1068,13 +1068,13 @@ class TestCurbCurlEasy < Test::Unit::TestCase
1068
1068
  end
1069
1069
 
1070
1070
  def test_easy_http_verbs_must_respond_to_str
1071
- # issue http://github.com/taf2/curb/issues#issue/45
1071
+ # issue http://github.com/taf2/curb/issues/45
1072
1072
  assert_nothing_raised do
1073
- c = Curl::Easy.new ; c.url = 'http://example.com' ; c.http(:get)
1073
+ c = Curl::Easy.new ; c.url = TestServlet.url ; c.http(:get)
1074
1074
  end
1075
1075
 
1076
1076
  assert_raise RuntimeError do
1077
- c = Curl::Easy.new ; c.url = 'http://example.com' ; c.http(FooNoToS.new)
1077
+ c = Curl::Easy.new ; c.url = TestServlet.url ; c.http(FooNoToS.new)
1078
1078
  end
1079
1079
 
1080
1080
  end
@@ -0,0 +1,277 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+ require 'json'
3
+
4
+ class TestCurbCurlEasyCookielist < Test::Unit::TestCase
5
+ def test_setopt_cookielist
6
+ easy = Curl::Easy.new
7
+ # DateTime handles time zone correctly
8
+ expires = (Date.today + 2).to_datetime
9
+ easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c1=v1; domain=localhost; expires=#{expires.httpdate};")
10
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c2=v2; domain=localhost')
11
+ easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c3=v3; expires=#{expires.httpdate};")
12
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c4=v4;')
13
+ easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c5=v5; domain=127.0.0.1; expires=#{expires.httpdate};")
14
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: c6=v6; domain=127.0.0.1;;')
15
+
16
+ # Since 7.43.0 cookies that were imported in the Set-Cookie format without a domain name are not exported by this option.
17
+ # So, before 7.43.0, c3 and c4 will be exported too; but that version is far too old for current curb version, so it's not handled here.
18
+ if Curl::CURL_VERSION.to_f > 8
19
+ expected_cookielist = [
20
+ ".127.0.0.1\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc5\tv5",
21
+ ".127.0.0.1\tTRUE\t/\tFALSE\t0\tc6\tv6",
22
+ ".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1",
23
+ ".localhost\tTRUE\t/\tFALSE\t0\tc2\tv2",
24
+ ]
25
+ else
26
+ expected_cookielist = [
27
+ "127.0.0.1\tFALSE\t/\tFALSE\t#{expires.to_time.to_i}\tc5\tv5",
28
+ "127.0.0.1\tFALSE\t/\tFALSE\t0\tc6\tv6",
29
+ ".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1",
30
+ ".localhost\tTRUE\t/\tFALSE\t0\tc2\tv2",
31
+ ]
32
+ end
33
+ assert_equal expected_cookielist, easy.cookielist
34
+
35
+ easy.url = "#{TestServlet.url}/get_cookies"
36
+ easy.perform
37
+ assert_equal 'c6=v6; c5=v5; c4=v4; c3=v3', easy.body_str
38
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
39
+ easy.perform
40
+ assert_equal 'c2=v2; c1=v1', easy.body_str
41
+ end
42
+
43
+ # libcurl documentation says: "This option also enables the cookie engine", but it's not tracked on the curb level
44
+ def test_setopt_cookielist_enables_cookie_engine
45
+ easy = Curl::Easy.new
46
+ expires = (Date.today + 2).to_datetime
47
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
48
+ easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: c1=v1; domain=localhost; expires=#{expires.httpdate};")
49
+ easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
50
+ easy.perform
51
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
52
+ easy.post_body = nil
53
+ easy.perform
54
+
55
+ assert !easy.enable_cookies?
56
+ assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc1\tv1", ".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc2\tv2"], easy.cookielist
57
+ assert_equal 'c2=v2; c1=v1', easy.body_str
58
+ end
59
+
60
+ def test_setopt_cookielist_invalid_format
61
+ easy = Curl::Easy.new
62
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
63
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'Not a cookie')
64
+ assert_nil easy.cookielist
65
+ easy.perform
66
+ assert_equal '', easy.body_str
67
+ end
68
+
69
+ def test_setopt_cookielist_netscape_format
70
+ easy = Curl::Easy.new
71
+ expires = (Date.today + 2).to_datetime
72
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
73
+ # Note domain changes for include subdomains
74
+ [
75
+ ['localhost', 'FALSE', '/', 'TRUE', 0, 'session_http_only', '42'].join("\t"),
76
+ ['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '43'].join("\t"),
77
+ ['localhost', 'TRUE', '/', 'FALSE', expires.to_time.to_i, 'permanent', '44'].join("\t"),
78
+ ['.localhost', 'FALSE', '/', 'TRUE', expires.to_time.to_i, 'permanent_http_only', '45'].join("\t"),
79
+ ].each { |cookie| easy.setopt(Curl::CURLOPT_COOKIELIST, cookie) }
80
+
81
+ expected_cookielist = [
82
+ ['localhost', 'FALSE', '/', 'TRUE', 0, 'session_http_only', '42'].join("\t"),
83
+ ['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '43'].join("\t"),
84
+ ['.localhost', 'TRUE', '/', 'FALSE', expires.to_time.to_i, 'permanent', '44'].join("\t"),
85
+ ['localhost', 'FALSE', '/', 'TRUE', expires.to_time.to_i, 'permanent_http_only', '45'].join("\t"),
86
+ ]
87
+ assert_equal expected_cookielist, easy.cookielist
88
+ easy.perform
89
+ assert_equal 'permanent_http_only=45; session_http_only=42; permanent=44; session=43', easy.body_str
90
+ end
91
+
92
+ # Multiple cookies and comments are not supported
93
+ def test_setopt_cookielist_netscape_format_mutliline
94
+ easy = Curl::Easy.new
95
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
96
+ easy.setopt(
97
+ Curl::CURLOPT_COOKIELIST,
98
+ [
99
+ '# Netscape HTTP Cookie File',
100
+ ['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '42'].join("\t"),
101
+ '',
102
+ ].join("\n"),
103
+ )
104
+ assert_nil easy.cookielist
105
+ easy.perform
106
+ assert_equal '', easy.body_str
107
+
108
+ easy.setopt(
109
+ Curl::CURLOPT_COOKIELIST,
110
+ [
111
+ ['.localhost', 'TRUE', '/', 'FALSE', 0, 'session', '42'].join("\t"),
112
+ ['.localhost', 'TRUE', '/', 'FALSE', 0, 'session2', '84'].join("\t"),
113
+ '',
114
+ ].join("\n"),
115
+ )
116
+ # Only first cookie is set
117
+ assert_equal [".localhost\tTRUE\t/\tFALSE\t0\tsession\t42"], easy.cookielist
118
+ easy.perform
119
+ assert_equal 'session=42', easy.body_str
120
+ end
121
+
122
+ # ALL erases all cookies held in memory
123
+ # ALL was added in 7.14.1
124
+ def test_setopt_cookielist_command_all
125
+ expires = (Date.today + 2).to_datetime
126
+ with_permanent_and_session_cookies(expires) do |easy|
127
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'ALL')
128
+ assert_nil easy.cookielist
129
+ easy.perform
130
+ assert_equal '', easy.body_str
131
+ end
132
+ end
133
+
134
+ # SESS erases all session cookies held in memory
135
+ # SESS was added in 7.15.4
136
+ def test_setopt_cookielist_command_sess
137
+ expires = (Date.today + 2).to_datetime
138
+ with_permanent_and_session_cookies(expires) do |easy|
139
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'SESS')
140
+ assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42"], easy.cookielist
141
+ easy.perform
142
+ assert_equal 'permanent=42', easy.body_str
143
+ end
144
+ end
145
+
146
+ # FLUSH writes all known cookies to the file specified by CURLOPT_COOKIEJAR
147
+ # FLUSH was added in 7.17.1
148
+ def test_setopt_cookielist_command_flush
149
+ expires = (Date.today + 2).to_datetime
150
+ with_permanent_and_session_cookies(expires) do |easy|
151
+ cookiejar = File.join(Dir.tmpdir, 'curl_test_cookiejar')
152
+ assert !File.exist?(cookiejar)
153
+ begin
154
+ easy.cookiejar = cookiejar
155
+ # trick to actually set CURLOPT_COOKIEJAR
156
+ easy.enable_cookies = true
157
+ easy.perform
158
+ assert !File.exist?(cookiejar)
159
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'FLUSH')
160
+ expected_cookiejar = <<~COOKIEJAR
161
+ # Netscape HTTP Cookie File
162
+ # https://curl.se/docs/http-cookies.html
163
+ # This file was generated by libcurl! Edit at your own risk.
164
+
165
+ .localhost TRUE / FALSE 0 session 420
166
+ .localhost TRUE / FALSE #{expires.to_time.to_i} permanent 42
167
+ COOKIEJAR
168
+ assert_equal expected_cookiejar, File.read(cookiejar)
169
+ ensure
170
+ # Otherwise it'll create this file again
171
+ easy.close
172
+ File.unlink(cookiejar) if File.exist?(cookiejar)
173
+ end
174
+ end
175
+ end
176
+
177
+ # RELOAD loads all cookies from the files specified by CURLOPT_COOKIEFILE
178
+ # RELOAD was added in 7.39.0
179
+ def test_setopt_cookielist_command_reload
180
+ expires = (Date.today + 2).to_datetime
181
+ expires_file = (Date.today + 4).to_datetime
182
+ with_permanent_and_session_cookies(expires) do |easy|
183
+ cookiefile = File.join(Dir.tmpdir, 'curl_test_cookiefile')
184
+ assert !File.exist?(cookiefile)
185
+ begin
186
+ cookielist = [
187
+ # Won't be updated, added instead
188
+ ".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent\t84",
189
+ ".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent_file\t84",
190
+ # Won't be updated, added instead
191
+ ".localhost\tTRUE\t/\tFALSE\t0\tsession\t840",
192
+ ".localhost\tTRUE\t/\tFALSE\t0\tsession_file\t840",
193
+ '',
194
+ ]
195
+ File.write(cookiefile, cookielist.join("\n"))
196
+ easy.cookiefile = cookiefile
197
+ # trick to actually set CURLOPT_COOKIEFILE
198
+ easy.enable_cookies = true
199
+ easy.perform
200
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'RELOAD')
201
+ expected_cookielist = [
202
+ ".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42",
203
+ ".localhost\tTRUE\t/\tFALSE\t0\tsession\t420",
204
+ ".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent\t84",
205
+ ".localhost\tTRUE\t/\tFALSE\t#{expires_file.to_time.to_i}\tpermanent_file\t84",
206
+ ".localhost\tTRUE\t/\tFALSE\t0\tsession\t840",
207
+ ".localhost\tTRUE\t/\tFALSE\t0\tsession_file\t840",
208
+ ]
209
+ assert_equal expected_cookielist, easy.cookielist
210
+ easy.perform
211
+ # Be careful, duplicates are not removed
212
+ assert_equal 'permanent_file=84; session_file=840; permanent=84; session=840; permanent=42; session=420', easy.body_str
213
+ ensure
214
+ File.unlink(cookiefile) if File.exist?(cookiefile)
215
+ end
216
+ end
217
+ end
218
+
219
+ def test_commands_do_not_enable_cookie_engine
220
+ %w[ALL SESS FLUSH RELOAD].each do |command|
221
+ easy = Curl::Easy.new
222
+ expires = (Date.today + 2).to_datetime
223
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
224
+ easy.setopt(Curl::CURLOPT_COOKIELIST, command)
225
+ easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
226
+ easy.perform
227
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
228
+ easy.post_body = nil
229
+ easy.perform
230
+
231
+ assert !easy.enable_cookies?
232
+ assert_nil easy.cookielist
233
+ assert_equal '', easy.body_str
234
+ end
235
+ end
236
+
237
+
238
+ def test_strings_without_cookie_enable_cookie_engine
239
+ [
240
+ '',
241
+ '# Netscape HTTP Cookie File',
242
+ 'no_a_cookie',
243
+ ].each do |command|
244
+ easy = Curl::Easy.new
245
+ expires = (Date.today + 2).to_datetime
246
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/set_cookies"
247
+ easy.setopt(Curl::CURLOPT_COOKIELIST, command)
248
+ easy.post_body = JSON.generate([{ name: 'c2', value: 'v2', domain: 'localhost', expires: expires.httpdate, path: '/' }])
249
+ easy.perform
250
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
251
+ easy.post_body = nil
252
+ easy.perform
253
+
254
+ assert !easy.enable_cookies?
255
+ assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tc2\tv2"], easy.cookielist
256
+ assert_equal 'c2=v2', easy.body_str
257
+ end
258
+ end
259
+
260
+ def with_permanent_and_session_cookies(expires)
261
+ easy = Curl::Easy.new
262
+ easy.url = "http://localhost:#{TestServlet.port}#{TestServlet.path}/get_cookies"
263
+ easy.setopt(Curl::CURLOPT_COOKIELIST, "Set-Cookie: permanent=42; domain=localhost; expires=#{expires.httpdate};")
264
+ easy.setopt(Curl::CURLOPT_COOKIELIST, 'Set-Cookie: session=420; domain=localhost;')
265
+ assert_equal [".localhost\tTRUE\t/\tFALSE\t#{expires.to_time.to_i}\tpermanent\t42", ".localhost\tTRUE\t/\tFALSE\t0\tsession\t420"], easy.cookielist
266
+ easy.perform
267
+ assert_equal 'permanent=42; session=420', easy.body_str
268
+
269
+ yield easy
270
+ end
271
+
272
+ include TestServerMethods
273
+
274
+ def setup
275
+ server_setup
276
+ end
277
+ end
@@ -13,7 +13,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
13
13
  # this test fails with libcurl 7.22.0. I didn't investigate, but it may be related
14
14
  # to CURLOPT_MAXCONNECTS bug fixed in 7.30.0:
15
15
  # https://github.com/curl/curl/commit/e87e76e2dc108efb1cae87df496416f49c55fca0
16
- omit("Skip, libcurl too old (< 7.22.0)") if Curl::CURL_VERSION.split('.')[1].to_i <= 22
16
+ omit("Skip, libcurl too old (< 7.22.0)") if Curl::CURL_VERSION.to_f < 8 && Curl::CURL_VERSION.split('.')[1].to_i <= 22
17
17
 
18
18
  @server.shutdown if @server
19
19
  @test_thread.kill if @test_thread
@@ -114,13 +114,13 @@ class TestCurbCurlMulti < Test::Unit::TestCase
114
114
  end
115
115
 
116
116
  def test_new_multi_01
117
- d1 = ""
117
+ d1 = String.new
118
118
  c1 = Curl::Easy.new($TEST_URL) do |curl|
119
119
  curl.headers["User-Agent"] = "myapp-0.0"
120
120
  curl.on_body {|d| d1 << d; d.length }
121
121
  end
122
122
 
123
- d2 = ""
123
+ d2 = String.new
124
124
  c2 = Curl::Easy.new($TEST_URL) do |curl|
125
125
  curl.headers["User-Agent"] = "myapp-0.0"
126
126
  curl.on_body {|d| d2 << d; d.length }
@@ -186,7 +186,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
186
186
  rescue Curl::Err::AbortedByCallbackError => e
187
187
  did_raise = true
188
188
  in_file = e.backtrace.detect {|err| err.match?(File.basename(__FILE__)) }
189
- in_file_stack = e.backtrace.select {|err| err.match?(File.basename(__FILE__)) }
189
+ #in_file_stack = e.backtrace.select {|err| err.match?(File.basename(__FILE__)) }
190
190
  assert_match(__FILE__, in_file)
191
191
  in_file.gsub!(__FILE__)
192
192
  parts = in_file.split(':')
@@ -206,7 +206,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
206
206
  m = Curl::Multi.new
207
207
  responses = []
208
208
  n.times do|i|
209
- responses[i] = ""
209
+ responses[i] = String.new
210
210
  c = Curl::Easy.new($TEST_URL) do|curl|
211
211
  curl.on_body{|data| responses[i] << data; data.size }
212
212
  end
@@ -230,7 +230,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
230
230
  5.times do|it|
231
231
  responses = []
232
232
  n.times do|i|
233
- responses[i] = ""
233
+ responses[i] = String.new
234
234
  c = Curl::Easy.new($TEST_URL) do|curl|
235
235
  curl.on_body{|data| responses[i] << data; data.size }
236
236
  end
@@ -376,7 +376,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
376
376
  attr_reader :buf
377
377
 
378
378
  def t_method
379
- @buf = ""
379
+ @buf = String.new
380
380
  @m = Curl::Multi.new
381
381
  10.times do|i|
382
382
  c = Curl::Easy.new($TEST_URL)
@@ -422,8 +422,8 @@ class TestCurbCurlMulti < Test::Unit::TestCase
422
422
  m = Curl::Multi.new
423
423
  # add a few easy handles
424
424
  requests.each do |url|
425
- responses[url] = ""
426
- responses["#{url}-header"] = ""
425
+ responses[url] = String.new
426
+ responses["#{url}-header"] = String.new
427
427
  c = Curl::Easy.new(url) do|curl|
428
428
  curl.follow_location = true
429
429
  curl.on_header{|data| responses["#{url}-header"] << data; data.size }
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
8
8
  - Todd A. Fisher
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-08-23 00:00:00.000000000 Z
11
+ date: 2025-02-09 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
15
14
  for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
@@ -53,7 +52,6 @@ files:
53
52
  - tests/bug_follow_redirect_288.rb
54
53
  - tests/bug_instance_post_differs_from_class_post.rb
55
54
  - tests/bug_issue102.rb
56
- - tests/bug_issue277.rb
57
55
  - tests/bug_multi_segfault.rb
58
56
  - tests/bug_postfields_crash.rb
59
57
  - tests/bug_postfields_crash2.rb
@@ -67,6 +65,7 @@ files:
67
65
  - tests/tc_curl.rb
68
66
  - tests/tc_curl_download.rb
69
67
  - tests/tc_curl_easy.rb
68
+ - tests/tc_curl_easy_cookielist.rb
70
69
  - tests/tc_curl_easy_resolve.rb
71
70
  - tests/tc_curl_easy_setopt.rb
72
71
  - tests/tc_curl_maxfilesize.rb
@@ -78,9 +77,8 @@ files:
78
77
  - tests/unittests.rb
79
78
  homepage: https://github.com/taf2/curb
80
79
  licenses:
81
- - MIT
80
+ - Ruby
82
81
  metadata: {}
83
- post_install_message:
84
82
  rdoc_options:
85
83
  - "--main"
86
84
  - README.markdown
@@ -98,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
96
  - !ruby/object:Gem::Version
99
97
  version: '0'
100
98
  requirements: []
101
- rubygems_version: 3.4.6
102
- signing_key:
99
+ rubygems_version: 3.6.2
103
100
  specification_version: 4
104
101
  summary: Ruby libcurl bindings
105
102
  test_files:
@@ -111,7 +108,6 @@ test_files:
111
108
  - tests/bug_follow_redirect_288.rb
112
109
  - tests/bug_instance_post_differs_from_class_post.rb
113
110
  - tests/bug_issue102.rb
114
- - tests/bug_issue277.rb
115
111
  - tests/bug_multi_segfault.rb
116
112
  - tests/bug_postfields_crash.rb
117
113
  - tests/bug_postfields_crash2.rb
@@ -125,6 +121,7 @@ test_files:
125
121
  - tests/tc_curl.rb
126
122
  - tests/tc_curl_download.rb
127
123
  - tests/tc_curl_easy.rb
124
+ - tests/tc_curl_easy_cookielist.rb
128
125
  - tests/tc_curl_easy_resolve.rb
129
126
  - tests/tc_curl_easy_setopt.rb
130
127
  - tests/tc_curl_maxfilesize.rb
@@ -1,32 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
-
3
-
4
- require 'curb'
5
-
6
- class BugIssue102 < Test::Unit::TestCase
7
-
8
- def test_gc_closewait
9
- 100.times do
10
- responses = {}
11
- requests = ["http://www.google.co.uk/", "http://www.ruby-lang.org/"]
12
- m = Curl::Multi.new
13
- # add a few easy handles
14
- requests.each do |url|
15
- responses[url] = ""
16
- c = Curl::Easy.new(url) do|curl|
17
- curl.follow_location = true
18
- curl.on_body{|data| responses[url] << data; data.size }
19
- curl.on_success {|easy| #puts "success, add more easy handles"
20
- }
21
- end
22
- m.add(c)
23
- end
24
-
25
- m.perform do
26
- #puts "idling... can do some work here"
27
- end
28
- GC.start
29
- end
30
- end
31
-
32
- end