ghazel-curb 0.6.2.3 → 0.7.9.1

Sign up to get free protection for your applications and to get access to all the features.
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"