curb 0.1.4 → 0.7.15

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_postfield.c CHANGED
@@ -41,7 +41,7 @@ void append_to_form(VALUE self,
41
41
  // is a file upload field
42
42
  if (rbcpf->content_proc != Qnil) {
43
43
  // with content proc
44
- rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, self);
44
+ rbcpf->buffer_str = rb_funcall(rbcpf->content_proc, idCall, 1, self);
45
45
 
46
46
  if (rbcpf->remote_file == Qnil) {
47
47
  rb_raise(eCurlErrInvalidPostField, "Cannot post file upload field with no filename");
@@ -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),
@@ -143,7 +143,7 @@ void append_to_form(VALUE self,
143
143
  }
144
144
 
145
145
  if (result != 0) {
146
- char *reason;
146
+ const char *reason = NULL;
147
147
 
148
148
  switch (result) {
149
149
  case CURL_FORMADD_MEMORY:
@@ -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,45 +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) {
432
- char *tmpchrs;
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
+ }
446
+
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);
433
455
 
434
- if ((tmpchrs = curl_escape(StringValuePtr(rbcpf->name), RSTRING_LEN(rbcpf->name))) == NULL) {
435
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode name `%s'", tmpchrs);
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;
436
464
  } else {
437
- VALUE tmpcontent = Qnil;
438
- VALUE escd_name = rb_str_new2(tmpchrs);
439
- curl_free(tmpchrs);
440
-
441
- if (rbcpf->content_proc != Qnil) {
442
- tmpcontent = rb_funcall(rbcpf->content_proc, idCall, 1, self);
443
- } else if (rbcpf->content != Qnil) {
444
- tmpcontent = rbcpf->content;
445
- } else {
446
- tmpcontent = rb_str_new2("");
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) );
447
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);
448
482
 
449
- if ((tmpchrs = curl_escape(StringValuePtr(tmpcontent), RSTRING_LEN(tmpcontent))) == NULL) {
450
- rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
451
- } else {
452
- VALUE escd_content = rb_str_new2(tmpchrs);
453
- curl_free(tmpchrs);
454
-
455
- result = escd_name;
456
- rb_str_cat(result, "=", 1);
457
- rb_str_concat(result, escd_content);
458
- }
483
+ result = escd_name;
484
+ rb_str_cat(result, "=", 1);
485
+ rb_str_concat(result, escd_content);
459
486
  }
460
- } else {
461
- rb_raise(eCurlErrInvalidPostField, "Cannot convert unnamed field to string");
462
- }
463
- } else {
464
- rb_raise(eCurlErrInvalidPostField, "Cannot convert non-content field to string");
465
- }
487
+ }
466
488
 
467
489
  return result;
468
490
  }
@@ -470,6 +492,8 @@ static VALUE ruby_curl_postfield_to_str(VALUE self) {
470
492
 
471
493
  /* =================== INIT LIB =====================*/
472
494
  void init_curb_postfield() {
495
+ VALUE sc;
496
+
473
497
  idCall = rb_intern("call");
474
498
 
475
499
  cCurlPostField = rb_define_class_under(mCurl, "PostField", rb_cObject);
@@ -478,7 +502,7 @@ void init_curb_postfield() {
478
502
  rb_define_singleton_method(cCurlPostField, "content", ruby_curl_postfield_new_content, -1);
479
503
  rb_define_singleton_method(cCurlPostField, "file", ruby_curl_postfield_new_file, -1);
480
504
 
481
- VALUE sc = rb_singleton_class(cCurlPostField);
505
+ sc = rb_singleton_class(cCurlPostField);
482
506
  rb_undef(sc, rb_intern("new"));
483
507
 
484
508
  rb_define_method(cCurlPostField, "name=", ruby_curl_postfield_name_set, 1);
data/ext/curb_upload.c ADDED
@@ -0,0 +1,80 @@
1
+ /* curb_upload.c - Curl upload handle
2
+ * Copyright (c)2009 Todd A Fisher.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ */
5
+ #include "curb_upload.h"
6
+ extern VALUE mCurl;
7
+ VALUE cCurlUpload;
8
+
9
+ #ifdef RDOC_NEVER_DEFINED
10
+ mCurl = rb_define_module("Curl");
11
+ #endif
12
+
13
+ static void curl_upload_mark(ruby_curl_upload *rbcu) {
14
+ if (rbcu->stream && !NIL_P(rbcu->stream)) rb_gc_mark(rbcu->stream);
15
+ }
16
+ static void curl_upload_free(ruby_curl_upload *rbcu) {
17
+ free(rbcu);
18
+ }
19
+
20
+ /*
21
+ * call-seq:
22
+ * internal class for sending large file uploads
23
+ */
24
+ VALUE ruby_curl_upload_new(VALUE klass) {
25
+ VALUE upload;
26
+ ruby_curl_upload *rbcu = ALLOC(ruby_curl_upload);
27
+ rbcu->stream = Qnil;
28
+ rbcu->offset = 0;
29
+ upload = Data_Wrap_Struct(klass, curl_upload_mark, curl_upload_free, rbcu);
30
+ return upload;
31
+ }
32
+
33
+ /*
34
+ * call-seq:
35
+ * internal class for sending large file uploads
36
+ */
37
+ VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream) {
38
+ ruby_curl_upload *rbcu;
39
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
40
+ rbcu->stream = stream;
41
+ return stream;
42
+ }
43
+ /*
44
+ * call-seq:
45
+ * internal class for sending large file uploads
46
+ */
47
+ VALUE ruby_curl_upload_stream_get(VALUE self) {
48
+ ruby_curl_upload *rbcu;
49
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
50
+ return rbcu->stream;
51
+ }
52
+ /*
53
+ * call-seq:
54
+ * internal class for sending large file uploads
55
+ */
56
+ VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset) {
57
+ ruby_curl_upload *rbcu;
58
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
59
+ rbcu->offset = FIX2LONG(offset);
60
+ return offset;
61
+ }
62
+ /*
63
+ * call-seq:
64
+ * internal class for sending large file uploads
65
+ */
66
+ VALUE ruby_curl_upload_offset_get(VALUE self) {
67
+ ruby_curl_upload *rbcu;
68
+ Data_Get_Struct(self, ruby_curl_upload, rbcu);
69
+ return INT2FIX(rbcu->offset);
70
+ }
71
+
72
+ /* =================== INIT LIB =====================*/
73
+ void init_curb_upload() {
74
+ cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
75
+ rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
76
+ rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
77
+ rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
78
+ rb_define_method(cCurlUpload, "offset=", ruby_curl_upload_offset_set, 1);
79
+ rb_define_method(cCurlUpload, "offset", ruby_curl_upload_offset_get, 0);
80
+ }
data/ext/curb_upload.h ADDED
@@ -0,0 +1,30 @@
1
+ /* curb_upload.h - Curl upload handle
2
+ * Copyright (c)2009 Todd A Fisher.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ */
5
+ #ifndef __CURB_UPLOAD_H
6
+ #define __CURB_UPLOAD_H
7
+
8
+ #include "curb.h"
9
+
10
+ #include <curl/easy.h>
11
+
12
+ /*
13
+ * Maintain the state of an upload e.g. for putting large streams with very little memory
14
+ * out to a server. via PUT requests
15
+ */
16
+ typedef struct {
17
+ VALUE stream;
18
+ size_t offset;
19
+ } ruby_curl_upload;
20
+
21
+ extern VALUE cCurlUpload;
22
+ void init_curb_upload();
23
+
24
+ VALUE ruby_curl_upload_new(VALUE klass);
25
+ VALUE ruby_curl_upload_stream_set(VALUE self, VALUE stream);
26
+ VALUE ruby_curl_upload_stream_get(VALUE self);
27
+ VALUE ruby_curl_upload_offset_set(VALUE self, VALUE offset);
28
+ VALUE ruby_curl_upload_offset_get(VALUE self);
29
+
30
+ #endif
data/ext/extconf.rb CHANGED
@@ -2,23 +2,175 @@ require 'mkmf'
2
2
 
3
3
  dir_config('curl')
4
4
 
5
- unless have_library('curl') &&
6
- have_header('curl/curl.h')
5
+ if find_executable('curl-config')
6
+ $CFLAGS << " #{`curl-config --cflags`.strip} -g"
7
+ if ENV['STATIC_BUILD']
8
+ $LIBS << " #{`curl-config --static-libs`.strip}"
9
+ else
10
+ $LIBS << " #{`curl-config --libs`.strip}"
11
+ end
12
+ ca_bundle_path=`curl-config --ca`.strip
13
+ if !ca_bundle_path.nil? and ca_bundle_path != ''
14
+ $defs.push( %{-D HAVE_CURL_CONFIG_CA} )
15
+ $defs.push( %{-D CURL_CONFIG_CA='#{ca_bundle_path.inspect}'} )
16
+ end
17
+ elsif !have_library('curl') or !have_header('curl/curl.h')
7
18
  fail <<-EOM
8
19
  Can't find libcurl or curl/curl.h
9
-
20
+
10
21
  Try passing --with-curl-dir or --with-curl-lib and --with-curl-include
11
22
  options to extconf.
12
23
  EOM
13
24
  end
14
25
 
15
- #install_rb("curb.rb", "$(RUBYLIBDIR)", '../lib')
16
- #install_rb("curl.rb", "$(RUBYLIBDIR)", '../lib')
17
- $INSTALLFILES = [["curb.rb", "$(RUBYLIBDIR)", "../ext"], ["curl.rb", "$(RUBYLIBDIR)", "../ext"]]
26
+ # Check arch flags
27
+ # TODO: detect mismatched arch types when libcurl mac ports is mixed with native mac ruby or vice versa
28
+ #archs = $CFLAGS.scan(/-arch\s(.*?)\s/).first # get the first arch flag
29
+ #if archs and archs.size >= 1
30
+ # # need to reduce the number of archs...
31
+ # # guess the first one is correct... at least the first one is probably the ruby installed arch...
32
+ # # this could lead to compiled binaries that crash at runtime...
33
+ # $CFLAGS.gsub!(/-arch\s(.*?)\s/,' ')
34
+ # $CFLAGS << " -arch #{archs.first}"
35
+ # puts "Selected arch: #{archs.first}"
36
+ #end
37
+
38
+ def define(s)
39
+ $defs.push( format("-D HAVE_%s", s.to_s.upcase) )
40
+ end
41
+
42
+ def have_constant(name)
43
+ checking_for name do
44
+ src = %{
45
+ #include <curl/curl.h>
46
+ int main() {
47
+ int test = (int)#{name.upcase};
48
+ return 0;
49
+ }
50
+ }
51
+ if try_compile(src,"#{$CFLAGS} #{$LIBS}")
52
+ define name
53
+ true
54
+ else
55
+ false
56
+ end
57
+ end
58
+ end
59
+
60
+ have_constant "curlinfo_redirect_time"
61
+ have_constant "curlinfo_response_code"
62
+ have_constant "curlinfo_filetime"
63
+ have_constant "curlinfo_redirect_count"
64
+ have_constant "curlinfo_os_errno"
65
+ have_constant "curlinfo_num_connects"
66
+ have_constant "curlinfo_ftp_entry_path"
67
+ have_constant "curl_version_ssl"
68
+ have_constant "curl_version_libz"
69
+ have_constant "curl_version_ntlm"
70
+ have_constant "curl_version_gssnegotiate"
71
+ have_constant "curl_version_debug"
72
+ have_constant "curl_version_asynchdns"
73
+ have_constant "curl_version_spnego"
74
+ have_constant "curl_version_largefile"
75
+ have_constant "curl_version_idn"
76
+ have_constant "curl_version_sspi"
77
+ have_constant "curl_version_conv"
78
+ have_constant "curlproxy_http"
79
+ have_constant "curlproxy_socks4"
80
+ have_constant "curlproxy_socks5"
81
+ have_constant "curlauth_basic"
82
+ have_constant "curlauth_digest"
83
+ have_constant "curlauth_gssnegotiate"
84
+ have_constant "curlauth_ntlm"
85
+ have_constant "curlauth_anysafe"
86
+ have_constant "curlauth_any"
87
+ have_constant "curle_tftp_notfound"
88
+ have_constant "curle_tftp_perm"
89
+ have_constant "curle_tftp_diskfull"
90
+ have_constant "curle_tftp_illegal"
91
+ have_constant "curle_tftp_unknownid"
92
+ have_constant "curle_tftp_exists"
93
+ have_constant "curle_tftp_nosuchuser"
94
+ # older versions of libcurl 7.12
95
+ have_constant "curle_send_fail_rewind"
96
+ have_constant "curle_ssl_engine_initfailed"
97
+ have_constant "curle_login_denied"
98
+
99
+ # older than 7.16.3
100
+ have_constant "curlmopt_maxconnects"
101
+
102
+ # additional consts
103
+ have_constant "curle_conv_failed"
104
+ have_constant "curle_conv_reqd"
105
+ have_constant "curle_ssl_cacert_badfile"
106
+ have_constant "curle_remote_file_not_found"
107
+ have_constant "curle_ssh"
108
+ have_constant "curle_ssl_shutdown_failed"
109
+ have_constant "curle_again"
110
+ have_constant "curle_ssl_crl_badfile"
111
+ have_constant "curle_ssl_issuer_error"
112
+
113
+ # username/password added in 7.19.1
114
+ have_constant "curlopt_username"
115
+ have_constant "curlopt_password"
116
+ have_constant "curlinfo_primary_ip"
117
+
118
+ # ie quirk added in 7.19.3
119
+ have_constant "curlauth_digest_ie"
120
+
121
+ # added in 7.15.1
122
+ have_constant "curlftpmethod_multicwd"
123
+ have_constant "curlftpmethod_nocwd"
124
+ have_constant "curlftpmethod_singlecwd"
125
+
126
+ # centos 4.5 build of libcurl
127
+ have_constant "curlm_bad_socket"
128
+ have_constant "curlm_unknown_option"
129
+ have_func("curl_multi_timeout")
130
+ have_func("curl_multi_fdset")
131
+ have_func("curl_multi_perform")
18
132
 
19
133
  if try_compile('int main() { return 0; }','-Wall')
20
134
  $CFLAGS << ' -Wall'
21
135
  end
22
136
 
23
- create_makefile('curb_core')
137
+ # do some checking to detect ruby 1.8 hash.c vs ruby 1.9 hash.c
138
+ def test_for(name, const, src)
139
+ checking_for name do
140
+ if try_compile(src,"#{$CFLAGS} #{$LIBS}")
141
+ define const
142
+ true
143
+ else
144
+ false
145
+ end
146
+ end
147
+ end
148
+ test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
149
+ #include <ruby.h>
150
+ int main() {
151
+ VALUE hash = rb_hash_new();
152
+ if( RHASH(hash)->ntbl->num_entries ) {
153
+ return 0;
154
+ }
155
+ return 1;
156
+ }
157
+ })
158
+ test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
159
+ #include <ruby.h>
160
+ #include <ruby/st.h>
161
+ int main() {
162
+ return 0;
163
+ }
164
+ })
24
165
 
166
+ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
167
+ #include <curl/curl.h>
168
+ int main() {
169
+ CURL *easy = curl_easy_init();
170
+ curl_easy_escape(easy,"hello",5);
171
+ return 0;
172
+ }
173
+ })
174
+
175
+ create_header('curb_config.h')
176
+ create_makefile('curb_core')