ghazel-curb 0.6.2.3 → 0.7.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/curb_easy.h CHANGED
@@ -11,6 +11,24 @@
11
11
 
12
12
  #include <curl/easy.h>
13
13
 
14
+ #ifdef CURL_VERSION_SSL
15
+ #if LIBCURL_VERSION_NUM >= 0x070b00
16
+ # if LIBCURL_VERSION_NUM <= 0x071004
17
+ # define CURB_FTPSSL CURLOPT_FTP_SSL
18
+ # define CURB_FTPSSL_ALL CURLFTPSSL_ALL
19
+ # define CURB_FTPSSL_TRY CURLFTPSSL_TRY
20
+ # define CURB_FTPSSL_CONTROL CURLFTPSSL_CONTROL
21
+ # define CURB_FTPSSL_NONE CURLFTPSSL_NONE
22
+ # else
23
+ # define CURB_FTPSSL CURLOPT_USE_SSL
24
+ # define CURB_FTPSSL_ALL CURLUSESSL_ALL
25
+ # define CURB_FTPSSL_TRY CURLUSESSL_TRY
26
+ # define CURB_FTPSSL_CONTROL CURLUSESSL_CONTROL
27
+ # define CURB_FTPSSL_NONE CURLUSESSL_NONE
28
+ # endif
29
+ #endif
30
+ #endif
31
+
14
32
  /* a lot of this *could* be kept in the handler itself,
15
33
  * but then we lose the ability to query it's status.
16
34
  */
@@ -19,6 +37,7 @@ typedef struct {
19
37
  CURL *curl;
20
38
 
21
39
  VALUE opts; /* rather then allocate everything we might need to store, allocate a Hash and only store objects we actually use... */
40
+ VALUE multi; /* keep a multi handle alive for each easy handle not being used by a multi handle. This improves easy performance when not within a multi context */
22
41
 
23
42
  /* Other opts */
24
43
  unsigned short local_port; // 0 is no port
@@ -32,6 +51,11 @@ typedef struct {
32
51
  unsigned long connect_timeout;
33
52
  long dns_cache_timeout;
34
53
  unsigned long ftp_response_timeout;
54
+ long low_speed_limit;
55
+ long low_speed_time;
56
+ long ssl_version;
57
+ long use_ssl;
58
+ long ftp_filemethod;
35
59
 
36
60
  /* bool flags */
37
61
  char proxy_tunnel;
@@ -45,7 +69,9 @@ typedef struct {
45
69
  char verbose;
46
70
  char multipart_form_post;
47
71
  char enable_cookies;
72
+ char ignore_content_length;
48
73
  struct curl_slist *curl_headers;
74
+ struct curl_slist *curl_ftp_commands;
49
75
 
50
76
  int last_result; /* last result code from multi loop */
51
77
 
@@ -53,8 +79,8 @@ typedef struct {
53
79
 
54
80
  extern VALUE cCurlEasy;
55
81
 
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);
82
+ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce);
83
+ VALUE ruby_curl_easy_cleanup(VALUE self, ruby_curl_easy *rbce);
58
84
 
59
85
  void init_curb_easy();
60
86
 
data/ext/curb_errors.c CHANGED
@@ -110,6 +110,7 @@ VALUE eCurlErrSSLCRLBadfile;
110
110
  VALUE eCurlErrSSLIssuerError;
111
111
 
112
112
  /* multi errors */
113
+ VALUE mCurlErrFailedInit;
113
114
  VALUE mCurlErrCallMultiPerform;
114
115
  VALUE mCurlErrBadHandle;
115
116
  VALUE mCurlErrBadEasyHandle;
@@ -605,6 +606,7 @@ void init_curb_errors() {
605
606
  eCurlErrSSLShutdownFailed = rb_define_class_under(mCurlErr, "SSLShutdownFailed", eCurlErrError);
606
607
  eCurlErrSSH = rb_define_class_under(mCurlErr, "SSH", eCurlErrError);
607
608
 
609
+ mCurlErrFailedInit = rb_define_class_under(mCurlErr, "MultiInitError", eCurlErrError);
608
610
  mCurlErrCallMultiPerform = rb_define_class_under(mCurlErr, "MultiPerform", eCurlErrError);
609
611
  mCurlErrBadHandle = rb_define_class_under(mCurlErr, "MultiBadHandle", eCurlErrError);
610
612
  mCurlErrBadEasyHandle = rb_define_class_under(mCurlErr, "MultiBadEasyHandle", eCurlErrError);
data/ext/curb_errors.h CHANGED
@@ -108,6 +108,7 @@ extern VALUE eCurlErrSSLCRLBadfile;
108
108
  extern VALUE eCurlErrSSLIssuerError;
109
109
 
110
110
  /* multi errors */
111
+ extern VALUE mCurlErrFailedInit;
111
112
  extern VALUE mCurlErrCallMultiPerform;
112
113
  extern VALUE mCurlErrBadHandle;
113
114
  extern VALUE mCurlErrBadEasyHandle;
data/ext/curb_macros.h CHANGED
@@ -12,7 +12,7 @@
12
12
  #define rb_easy_set(key,val) rb_hash_aset(rbce->opts, rb_easy_hkey(key) , val)
13
13
  #define rb_easy_get(key) rb_hash_aref(rbce->opts, rb_easy_hkey(key))
14
14
  #define rb_easy_del(key) rb_hash_delete(rbce->opts, rb_easy_hkey(key))
15
- #define rb_easy_nil(key) (rb_hash_lookup_187(rbce->opts, rb_easy_hkey(key)) == Qnil)
15
+ #define rb_easy_nil(key) (rb_hash_aref(rbce->opts, rb_easy_hkey(key)) == Qnil)
16
16
  #define rb_easy_type_check(key,type) (rb_type(rb_hash_aref(rbce->opts, rb_easy_hkey(key))) == type)
17
17
 
18
18
  // TODO: rb_sym_to_s may not be defined?
data/ext/curb_multi.c CHANGED
@@ -19,6 +19,11 @@
19
19
 
20
20
  #include <errno.h>
21
21
 
22
+ #ifdef _WIN32
23
+ // for O_RDWR and O_BINARY
24
+ #include <fcntl.h>
25
+ #endif
26
+
22
27
  extern VALUE mCurl;
23
28
  static VALUE idCall;
24
29
 
@@ -28,8 +33,11 @@ static VALUE idCall;
28
33
 
29
34
  VALUE cCurlMulti;
30
35
 
36
+ static long cCurlMutiDefaulttimeout = 100; /* milliseconds */
37
+
31
38
  static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy);
32
39
  static void rb_curl_multi_read_info(VALUE self, CURLM *mptr);
40
+ static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_running);
33
41
 
34
42
  static void rb_curl_multi_mark_all_easy(VALUE key, VALUE rbeasy, ruby_curl_multi *rbcm) {
35
43
  rb_gc_mark(rbeasy);
@@ -81,6 +89,9 @@ VALUE ruby_curl_multi_new(VALUE klass) {
81
89
  ruby_curl_multi *rbcm = ALLOC(ruby_curl_multi);
82
90
 
83
91
  rbcm->handle = curl_multi_init();
92
+ if (!rbcm->handle) {
93
+ rb_raise(mCurlErrFailedInit, "Failed to initialize multi handle");
94
+ }
84
95
 
85
96
  rbcm->requests = rb_hash_new();
86
97
 
@@ -92,6 +103,30 @@ VALUE ruby_curl_multi_new(VALUE klass) {
92
103
  return new_curlm;
93
104
  }
94
105
 
106
+ /*
107
+ * call-seq:
108
+ * Curl::Multi.default_timeout = 4 => 4
109
+ *
110
+ * Set the global default time out for all Curl::Multi Handles. This value is used
111
+ * when libcurl cannot determine a timeout value when calling curl_multi_timeout.
112
+ *
113
+ */
114
+ VALUE ruby_curl_multi_set_default_timeout(VALUE klass, VALUE timeout) {
115
+ cCurlMutiDefaulttimeout = FIX2LONG(timeout);
116
+ return timeout;
117
+ }
118
+
119
+ /*
120
+ * call-seq:
121
+ * Curl::Multi.default_timeout = 4 => 4
122
+ *
123
+ * Get the global default time out for all Curl::Multi Handles.
124
+ *
125
+ */
126
+ VALUE ruby_curl_multi_get_default_timeout(VALUE klass) {
127
+ return INT2FIX(cCurlMutiDefaulttimeout);
128
+ }
129
+
95
130
  /* Hash#foreach callback for ruby_curl_multi_requests */
96
131
  static int ruby_curl_multi_requests_callback(VALUE key, VALUE value, VALUE result_array) {
97
132
  rb_ary_push(result_array, value);
@@ -194,14 +229,14 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
194
229
  Data_Get_Struct(self, ruby_curl_multi, rbcm);
195
230
  Data_Get_Struct(easy, ruby_curl_easy, rbce);
196
231
 
232
+ /* setup the easy handle */
233
+ ruby_curl_easy_setup( rbce );
234
+
197
235
  mcode = curl_multi_add_handle(rbcm->handle, rbce->curl);
198
236
  if (mcode != CURLM_CALL_MULTI_PERFORM && mcode != CURLM_OK) {
199
237
  raise_curl_multi_error_exception(mcode);
200
238
  }
201
239
 
202
- /* setup the easy handle */
203
- ruby_curl_easy_setup( rbce, &(rbce->curl_headers) );
204
-
205
240
  rbcm->active++;
206
241
 
207
242
  /* Increase the running count, so that the perform loop keeps running.
@@ -210,6 +245,8 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
210
245
 
211
246
  rb_hash_aset( rbcm->requests, easy, easy );
212
247
 
248
+ rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
249
+
213
250
  return self;
214
251
  }
215
252
 
@@ -253,7 +290,7 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
253
290
 
254
291
  rbcm->active--;
255
292
 
256
- ruby_curl_easy_cleanup( easy, rbce, rbce->curl_headers );
293
+ ruby_curl_easy_cleanup( easy, rbce );
257
294
 
258
295
  // active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
259
296
  r = rb_hash_delete( rbcm->requests, easy );
@@ -296,14 +333,20 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
296
333
 
297
334
  Data_Get_Struct(easy, ruby_curl_easy, rbce);
298
335
 
299
- if (ecode != 0) {
300
- raise_curl_easy_error_exception(ecode);
301
- }
302
-
303
336
  rbce->last_result = result; /* save the last easy result code */
304
337
 
305
338
  ruby_curl_multi_remove( self, easy );
306
339
 
340
+ /* after running a request cleanup the headers, these are set before each request */
341
+ if (rbce->curl_headers) {
342
+ curl_slist_free_all(rbce->curl_headers);
343
+ rbce->curl_headers = NULL;
344
+ }
345
+
346
+ if (ecode != 0) {
347
+ raise_curl_easy_error_exception(ecode);
348
+ }
349
+
307
350
  if (!rb_easy_nil("complete_proc")) {
308
351
  rb_funcall( rb_easy_get("complete_proc"), idCall, 1, easy );
309
352
  }
@@ -324,6 +367,7 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
324
367
  (response_code >= 300 && response_code <= 999)) {
325
368
  rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
326
369
  }
370
+
327
371
  }
328
372
 
329
373
  static void rb_curl_multi_read_info(VALUE self, CURLM *multi_handle) {
@@ -354,10 +398,38 @@ static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_runnin
354
398
  if (mcode != CURLM_OK) {
355
399
  raise_curl_multi_error_exception(mcode);
356
400
  }
401
+
402
+ }
357
403
 
358
- rb_curl_multi_read_info( self, multi_handle );
404
+ #ifdef _WIN32
405
+ void create_crt_fd(fd_set *os_set, fd_set *crt_set)
406
+ {
407
+ int i;
408
+ crt_set->fd_count = os_set->fd_count;
409
+ for (i = 0; i < os_set->fd_count; i++) {
410
+ WSAPROTOCOL_INFO wsa_pi;
411
+ // dupicate the SOCKET
412
+ int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
413
+ SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
414
+ // create the CRT fd so ruby can get back to the SOCKET
415
+ int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
416
+ os_set->fd_array[i] = s;
417
+ crt_set->fd_array[i] = fd;
418
+ }
359
419
  }
360
420
 
421
+ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
422
+ {
423
+ int i;
424
+ for (i = 0; i < os_set->fd_count; i++) {
425
+ // cleanup the CRT fd
426
+ _close(crt_set->fd_array[i]);
427
+ // cleanup the duplicated SOCKET
428
+ closesocket(os_set->fd_array[i]);
429
+ }
430
+ }
431
+ #endif
432
+
361
433
  /*
362
434
  * call-seq:
363
435
  * multi = Curl::Multi.new
@@ -378,6 +450,9 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
378
450
  ruby_curl_multi *rbcm;
379
451
  int maxfd, rc;
380
452
  fd_set fdread, fdwrite, fdexcep;
453
+ #ifdef _WIN32
454
+ fd_set crt_fdread, crt_fdwrite, crt_fdexcep;
455
+ #endif
381
456
 
382
457
  long timeout_milliseconds;
383
458
  struct timeval tv = {0, 0};
@@ -387,66 +462,85 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
387
462
 
388
463
  Data_Get_Struct(self, ruby_curl_multi, rbcm);
389
464
 
390
- rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
391
-
392
- while(rbcm->running) {
393
- FD_ZERO(&fdread);
394
- FD_ZERO(&fdwrite);
395
- FD_ZERO(&fdexcep);
465
+ timeout_milliseconds = cCurlMutiDefaulttimeout;
396
466
 
397
- /* load the fd sets from the multi handle */
398
- mcode = curl_multi_fdset(rbcm->handle, &fdread, &fdwrite, &fdexcep, &maxfd);
399
- if (mcode != CURLM_OK) {
400
- raise_curl_multi_error_exception(mcode);
401
- }
467
+ rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
468
+
469
+ do {
470
+ while (rbcm->running) {
402
471
 
403
472
  #ifdef HAVE_CURL_MULTI_TIMEOUT
404
- /* get the curl suggested time out */
405
- mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
406
- if (mcode != CURLM_OK) {
407
- raise_curl_multi_error_exception(mcode);
408
- }
473
+ /* get the curl suggested time out */
474
+ mcode = curl_multi_timeout(rbcm->handle, &timeout_milliseconds);
475
+ if (mcode != CURLM_OK) {
476
+ raise_curl_multi_error_exception(mcode);
477
+ }
409
478
  #else
410
- /* libcurl doesn't have a timeout method defined... make a wild guess */
411
- timeout_milliseconds = -1;
479
+ /* libcurl doesn't have a timeout method defined, initialize to -1 we'll pick up the default later */
480
+ timeout_milliseconds = -1;
412
481
  #endif
413
- //printf("libcurl says wait: %ld ms or %ld s\n", timeout_milliseconds, timeout_milliseconds/1000);
414
482
 
415
- if (timeout_milliseconds == 0) { /* no delay */
416
- rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
417
- continue;
418
- }
419
- else if(timeout_milliseconds < 0) {
420
- timeout_milliseconds = 500; /* wait half a second, libcurl doesn't know how long to wait */
421
- }
422
- #ifdef __APPLE_CC__
423
- if(timeout_milliseconds > 1000) {
424
- timeout_milliseconds = 1000; /* apple libcurl sometimes reports huge timeouts... let's cap it */
425
- }
426
- #endif
483
+ if (timeout_milliseconds == 0) { /* no delay */
484
+ rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
485
+ continue;
486
+ }
487
+ else if (timeout_milliseconds < 0) {
488
+ timeout_milliseconds = cCurlMutiDefaulttimeout; /* libcurl doesn't know how long to wait, use a default timeout */
489
+ }
427
490
 
428
- tv.tv_sec = timeout_milliseconds / 1000; // convert milliseconds to seconds
429
- tv.tv_usec = (timeout_milliseconds % 1000) * 1000; // get the remainder of milliseconds and convert to micro seconds
430
-
431
- rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
432
- switch(rc) {
433
- case -1:
434
- rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
435
- break;
436
- case 0:
437
- if (block != Qnil) {
438
- rb_funcall(block, rb_intern("call"), 1, self);
491
+ if (timeout_milliseconds > cCurlMutiDefaulttimeout) {
492
+ timeout_milliseconds = cCurlMutiDefaulttimeout; /* buggy versions libcurl sometimes reports huge timeouts... let's cap it */
439
493
  }
440
- // if (rb_block_given_p()) {
441
- // rb_yield(self);
442
- // }
443
- default:
444
- rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
445
- break;
446
- }
447
494
 
448
- }
495
+ tv.tv_sec = 0; /* never wait longer than 1 second */
496
+ tv.tv_usec = (int)(timeout_milliseconds * 1000); /* XXX: int is the right type for OSX, what about linux? */
449
497
 
498
+ if (timeout_milliseconds == 0) { /* no delay */
499
+ rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
500
+ continue;
501
+ }
502
+
503
+ if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
504
+
505
+ FD_ZERO(&fdread);
506
+ FD_ZERO(&fdwrite);
507
+ FD_ZERO(&fdexcep);
508
+ /* load the fd sets from the multi handle */
509
+ mcode = curl_multi_fdset(rbcm->handle, &fdread, &fdwrite, &fdexcep, &maxfd);
510
+ if (mcode != CURLM_OK) {
511
+ raise_curl_multi_error_exception(mcode);
512
+ }
513
+
514
+ #ifdef _WIN32
515
+ create_crt_fd(&fdread, &crt_fdread);
516
+ create_crt_fd(&fdwrite, &crt_fdrwrite);
517
+ create_crt_fd(&fdexcep, &crt_fdexcep);
518
+ #endif
519
+
520
+ rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
521
+
522
+ #ifdef _WIN32
523
+ cleanup_crt_fd(&fdread, &crt_fdread);
524
+ cleanup_crt_fd(&fdwrite, &crt_fdrwrite);
525
+ cleanup_crt_fd(&fdexcep, &crt_fdexcep);
526
+ #endif
527
+
528
+ switch(rc) {
529
+ case -1:
530
+ rb_raise(rb_eRuntimeError, "select(): %s", strerror(errno));
531
+ break;
532
+ case 0:
533
+ rb_curl_multi_read_info( self, rbcm->handle );
534
+ if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
535
+ default:
536
+ rb_curl_multi_run( self, rbcm->handle, &(rbcm->running) );
537
+ break;
538
+ }
539
+ }
540
+ rb_curl_multi_read_info( self, rbcm->handle );
541
+ if (block != Qnil) { rb_funcall(block, rb_intern("call"), 1, self); }
542
+ } while( rbcm->running );
543
+
450
544
  return Qtrue;
451
545
  }
452
546
 
@@ -458,6 +552,8 @@ void init_curb_multi() {
458
552
 
459
553
  /* Class methods */
460
554
  rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, 0);
555
+ rb_define_singleton_method(cCurlMulti, "default_timeout=", ruby_curl_multi_set_default_timeout, 1);
556
+ rb_define_singleton_method(cCurlMulti, "default_timeout", ruby_curl_multi_get_default_timeout, 0);
461
557
 
462
558
  /* "Attributes" */
463
559
  rb_define_method(cCurlMulti, "requests", ruby_curl_multi_requests, 0);
data/ext/curb_postfield.c CHANGED
@@ -109,7 +109,7 @@ void append_to_form(VALUE self,
109
109
  } else {
110
110
  // is a content field
111
111
  if (rbcpf->content_proc != Qnil) {
112
- rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, self);
112
+ rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, 1, self);
113
113
 
114
114
  if (rbcpf->content_type == Qnil) {
115
115
  result = curl_formadd(first, last, CURLFORM_PTRNAME, StringValuePtr(rbcpf->name),
@@ -209,11 +209,11 @@ void curl_postfield_free(ruby_curl_postfield *rbcpf) {
209
209
  */
210
210
  static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass) {
211
211
  ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
212
-
212
+
213
213
  // wierdness - we actually require two args, unless a block is provided, but
214
214
  // we have to work that out below.
215
215
  rb_scan_args(argc, argv, "12&", &rbcpf->name, &rbcpf->content, &rbcpf->content_type, &rbcpf->content_proc);
216
-
216
+
217
217
  // special handling if theres a block, second arg is actually content_type
218
218
  if (rbcpf->content_proc != Qnil) {
219
219
  if (rbcpf->content != Qnil) {
@@ -235,7 +235,7 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
235
235
  rbcpf->local_file = Qnil;
236
236
  rbcpf->remote_file = Qnil;
237
237
  rbcpf->buffer_str = Qnil;
238
-
238
+
239
239
  return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
240
240
  }
241
241
 
@@ -253,11 +253,11 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
253
253
  * data.
254
254
  */
255
255
  static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
256
- // TODO needs to handle content-type too
256
+ // TODO needs to handle content-type too
257
257
  ruby_curl_postfield *rbcpf = ALLOC(ruby_curl_postfield);
258
-
258
+
259
259
  rb_scan_args(argc, argv, "21&", &rbcpf->name, &rbcpf->local_file, &rbcpf->remote_file, &rbcpf->content_proc);
260
-
260
+
261
261
  // special handling if theres a block, second arg is actually remote name.
262
262
  if (rbcpf->content_proc != Qnil) {
263
263
  if (rbcpf->local_file != Qnil) {
@@ -267,7 +267,7 @@ static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
267
267
  // (correct block call form)
268
268
  rbcpf->remote_file = rbcpf->local_file;
269
269
  }
270
-
270
+
271
271
  // Shouldn't get a local file, so can ignore it.
272
272
  rbcpf->local_file = Qnil;
273
273
  }
@@ -275,13 +275,13 @@ static VALUE ruby_curl_postfield_new_file(int argc, VALUE *argv, VALUE klass) {
275
275
  if (rbcpf->remote_file == Qnil) {
276
276
  rbcpf->remote_file = rbcpf->local_file;
277
277
  }
278
- }
279
-
278
+ }
279
+
280
280
  /* assoc objects */
281
281
  rbcpf->content = Qnil;
282
282
  rbcpf->content_type = Qnil;
283
283
  rbcpf->buffer_str = Qnil;
284
-
284
+
285
285
  return Data_Wrap_Struct(cCurlPostField, curl_postfield_mark, curl_postfield_free, rbcpf);
286
286
  }
287
287
 
@@ -424,55 +424,67 @@ static VALUE ruby_curl_postfield_to_str(VALUE self) {
424
424
  // FIXME This is using the deprecated curl_escape func
425
425
  ruby_curl_postfield *rbcpf;
426
426
  VALUE result = Qnil;
427
+ VALUE name = Qnil;
428
+ char *tmpchrs;
427
429
 
428
430
  Data_Get_Struct(self, ruby_curl_postfield, rbcpf);
429
431
 
430
- if ((rbcpf->local_file == Qnil) && (rbcpf->remote_file == Qnil)) {
431
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"))) {
437
+ 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__);
445
+ }
432
446
 
433
- char *tmpchrs = curl_escape(RSTRING_PTR(rbcpf->name), RSTRING_LEN(rbcpf->name));
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);
434
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));
435
477
  if (!tmpchrs) {
436
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
478
+ rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
437
479
  } else {
438
- VALUE tmpcontent = Qnil;
439
- VALUE escd_name = rb_str_new2(tmpchrs);
480
+ VALUE escd_content = rb_str_new2(tmpchrs);
440
481
  curl_free(tmpchrs);
441
482
 
442
- if (rbcpf->content_proc != Qnil) {
443
- tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
444
- } else if (rbcpf->content != Qnil) {
445
- tmpcontent = rbcpf->content;
446
- } else {
447
- tmpcontent = rb_str_new2("");
448
- }
449
- if (TYPE(tmpcontent) != T_STRING) {
450
- if (rb_respond_to(tmpcontent, rb_intern("to_s"))) {
451
- tmpcontent = rb_funcall(tmpcontent, rb_intern("to_s"), 0);
452
- }
453
- else {
454
- rb_raise(rb_eRuntimeError, "postfield(%s) is not a string and does not respond_to to_s", RSTRING_PTR(escd_name) );
455
- }
456
- }
457
- //fprintf(stderr, "encoding content: %ld - %s\n", RSTRING_LEN(tmpcontent), RSTRING_PTR(tmpcontent) );
458
- tmpchrs = curl_escape(RSTRING_PTR(tmpcontent), RSTRING_LEN(tmpcontent));
459
- if (!tmpchrs) {
460
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
461
- } else {
462
- VALUE escd_content = rb_str_new2(tmpchrs);
463
- curl_free(tmpchrs);
464
-
465
- result = escd_name;
466
- rb_str_cat(result, "=", 1);
467
- rb_str_concat(result, escd_content);
468
- }
483
+ result = escd_name;
484
+ rb_str_cat(result, "=", 1);
485
+ rb_str_concat(result, escd_content);
469
486
  }
470
- } else {
471
- rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string %s:%d", __FILE__, __LINE__);
472
- }
473
- } else {
474
- rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string %s:%d", __FILE__, __LINE__);
475
- }
487
+ }
476
488
 
477
489
  return result;
478
490
  }
data/ext/curb_upload.c CHANGED
@@ -11,7 +11,7 @@ VALUE cCurlUpload;
11
11
  #endif
12
12
 
13
13
  static void curl_upload_mark(ruby_curl_upload *rbcu) {
14
- if (rbcu->stream) rb_gc_mark(rbcu->stream);
14
+ if (rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
15
15
  }
16
16
  static void curl_upload_free(ruby_curl_upload *rbcu) {
17
17
  free(rbcu);
@@ -56,7 +56,7 @@ VALUE ruby_curl_upload_stream_get(VALUE self) {
56
56
  VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
57
57
  ruby_curl_upload *rbcu;
58
58
  Data_Get_Struct(self, ruby_curl_upload, rbcu);
59
- rbcu->offset = FIX2INT(offset);
59
+ rbcu->offset = FIX2LONG(offset);
60
60
  return offset;
61
61
  }
62
62
  /*
data/ext/extconf.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  require 'mkmf'
2
- puts $CFLAGS.inspect
3
2
 
4
3
  dir_config('curl')
5
4
 
6
5
  if find_executable('curl-config')
7
- $CFLAGS << " #{`curl-config --cflags`.strip}"
6
+ $CFLAGS << " #{`curl-config --cflags`.strip} -g"
8
7
  if ENV['STATIC_BUILD']
9
8
  $LIBS << " #{`curl-config --static-libs`.strip}"
10
9
  else
@@ -114,10 +113,16 @@ have_constant "curle_ssl_issuer_error"
114
113
  # username/password added in 7.19.1
115
114
  have_constant "curlopt_username"
116
115
  have_constant "curlopt_password"
116
+ have_constant "curlinfo_primary_ip"
117
117
 
118
118
  # ie quirk added in 7.19.3
119
119
  have_constant "curlauth_digest_ie"
120
120
 
121
+ # added in 7.15.1
122
+ have_constant "curlftpmethod_multicwd"
123
+ have_constant "curlftpmethod_nocwd"
124
+ have_constant "curlftpmethod_singlecwd"
125
+
121
126
  # centos 4.5 build of libcurl
122
127
  have_constant "curlm_bad_socket"
123
128
  have_constant "curlm_unknown_option"