curb 0.6.5.0 → 0.8.4
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/README +42 -5
- data/Rakefile +27 -4
- data/ext/curb.c +638 -0
- data/ext/curb.h +6 -4
- data/ext/curb_easy.c +954 -573
- data/ext/curb_easy.h +31 -2
- data/ext/curb_errors.c +16 -2
- data/ext/curb_errors.h +1 -0
- data/ext/curb_macros.h +4 -0
- data/ext/curb_multi.c +229 -67
- data/ext/curb_postfield.c +61 -49
- data/ext/curb_upload.c +2 -2
- data/ext/extconf.rb +232 -4
- data/lib/curb.rb +1 -186
- data/lib/curl/easy.rb +468 -0
- data/lib/curl/multi.rb +248 -0
- data/lib/curl.rb +61 -1
- data/tests/bug_crash_on_debug.rb +39 -0
- data/tests/bug_crash_on_progress.rb +33 -0
- data/tests/bug_curb_easy_blocks_ruby_threads.rb +2 -2
- data/tests/bug_issue102.rb +17 -0
- data/tests/bug_multi_segfault.rb +6 -2
- data/tests/bug_postfields_crash2.rb +57 -0
- data/tests/bug_require_last_or_segfault.rb +1 -1
- data/tests/bugtests.rb +9 -0
- data/tests/helper.rb +40 -10
- data/tests/signals.rb +33 -0
- data/tests/tc_curl.rb +39 -0
- data/tests/tc_curl_download.rb +44 -1
- data/tests/tc_curl_easy.rb +355 -22
- data/tests/tc_curl_easy_setopt.rb +31 -0
- data/tests/tc_curl_multi.rb +57 -5
- data/tests/tc_curl_postfield.rb +3 -1
- data/tests/timeout.rb +100 -0
- data/tests/timeout_server.rb +33 -0
- metadata +87 -48
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
|
-
|
|
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
|
|
478
|
+
rb_raise(eCurlErrInvalidPostField, "Failed to url-encode content `%s'", tmpchrs);
|
|
437
479
|
} else {
|
|
438
|
-
VALUE
|
|
439
|
-
VALUE escd_name = rb_str_new2(tmpchrs);
|
|
480
|
+
VALUE escd_content = rb_str_new2(tmpchrs);
|
|
440
481
|
curl_free(tmpchrs);
|
|
441
482
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
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
|
-
}
|
|
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 =
|
|
59
|
+
rbcu->offset = FIX2LONG(offset);
|
|
60
60
|
return offset;
|
|
61
61
|
}
|
|
62
62
|
/*
|
data/ext/extconf.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'mkmf'
|
|
2
|
-
puts $CFLAGS.inspect
|
|
3
2
|
|
|
4
3
|
dir_config('curl')
|
|
5
4
|
|
|
@@ -36,16 +35,17 @@ end
|
|
|
36
35
|
# puts "Selected arch: #{archs.first}"
|
|
37
36
|
#end
|
|
38
37
|
|
|
39
|
-
def define(s)
|
|
40
|
-
$defs.push( format("-D HAVE_%s", s.to_s.upcase) )
|
|
38
|
+
def define(s, v=1)
|
|
39
|
+
$defs.push( format("-D HAVE_%s=%d", s.to_s.upcase, v) )
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
def have_constant(name)
|
|
43
|
+
sname = name.is_a?(Symbol) ? name.to_s : name.upcase
|
|
44
44
|
checking_for name do
|
|
45
45
|
src = %{
|
|
46
46
|
#include <curl/curl.h>
|
|
47
47
|
int main() {
|
|
48
|
-
int test = (int)#{
|
|
48
|
+
int test = (int)#{sname};
|
|
49
49
|
return 0;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -53,6 +53,7 @@ def have_constant(name)
|
|
|
53
53
|
define name
|
|
54
54
|
true
|
|
55
55
|
else
|
|
56
|
+
#define name, 0
|
|
56
57
|
false
|
|
57
58
|
end
|
|
58
59
|
end
|
|
@@ -100,6 +101,13 @@ have_constant "curle_login_denied"
|
|
|
100
101
|
# older than 7.16.3
|
|
101
102
|
have_constant "curlmopt_maxconnects"
|
|
102
103
|
|
|
104
|
+
have_constant "curlopt_seekfunction"
|
|
105
|
+
have_constant "curlopt_seekdata"
|
|
106
|
+
have_constant "curlopt_sockoptfunction"
|
|
107
|
+
have_constant "curlopt_sockoptdata"
|
|
108
|
+
have_constant "curlopt_opensocketfunction"
|
|
109
|
+
have_constant "curlopt_opensocketdata"
|
|
110
|
+
|
|
103
111
|
# additional consts
|
|
104
112
|
have_constant "curle_conv_failed"
|
|
105
113
|
have_constant "curle_conv_reqd"
|
|
@@ -111,13 +119,22 @@ have_constant "curle_again"
|
|
|
111
119
|
have_constant "curle_ssl_crl_badfile"
|
|
112
120
|
have_constant "curle_ssl_issuer_error"
|
|
113
121
|
|
|
122
|
+
# added in 7.18.2
|
|
123
|
+
have_constant "curlinfo_redirect_url"
|
|
124
|
+
|
|
114
125
|
# username/password added in 7.19.1
|
|
115
126
|
have_constant "curlopt_username"
|
|
116
127
|
have_constant "curlopt_password"
|
|
128
|
+
have_constant "curlinfo_primary_ip"
|
|
117
129
|
|
|
118
130
|
# ie quirk added in 7.19.3
|
|
119
131
|
have_constant "curlauth_digest_ie"
|
|
120
132
|
|
|
133
|
+
# added in 7.15.1
|
|
134
|
+
have_constant "curlftpmethod_multicwd"
|
|
135
|
+
have_constant "curlftpmethod_nocwd"
|
|
136
|
+
have_constant "curlftpmethod_singlecwd"
|
|
137
|
+
|
|
121
138
|
# centos 4.5 build of libcurl
|
|
122
139
|
have_constant "curlm_bad_socket"
|
|
123
140
|
have_constant "curlm_unknown_option"
|
|
@@ -125,6 +142,215 @@ have_func("curl_multi_timeout")
|
|
|
125
142
|
have_func("curl_multi_fdset")
|
|
126
143
|
have_func("curl_multi_perform")
|
|
127
144
|
|
|
145
|
+
# constants
|
|
146
|
+
have_constant "curlopt_interleavefunction"
|
|
147
|
+
have_constant "curlopt_interleavedata"
|
|
148
|
+
have_constant "curlopt_chunk_bgn_function"
|
|
149
|
+
have_constant "curlopt_chunk_end_function"
|
|
150
|
+
have_constant "curlopt_chunk_data"
|
|
151
|
+
have_constant "curlopt_fnmatch_function"
|
|
152
|
+
have_constant "curlopt_fnmatch_data"
|
|
153
|
+
have_constant "curlopt_errorbuffer"
|
|
154
|
+
have_constant "curlopt_stderr"
|
|
155
|
+
have_constant "curlopt_failonerror"
|
|
156
|
+
have_constant "curlopt_url"
|
|
157
|
+
have_constant "curlopt_protocols"
|
|
158
|
+
have_constant "curlopt_redir_protocols"
|
|
159
|
+
have_constant "curlopt_proxy"
|
|
160
|
+
have_constant "curlopt_proxyport"
|
|
161
|
+
have_constant "curlopt_proxytype"
|
|
162
|
+
have_constant "curlopt_noproxy"
|
|
163
|
+
have_constant "curlopt_httpproxytunnel"
|
|
164
|
+
have_constant "curlopt_socks5_gssapi_service"
|
|
165
|
+
have_constant "curlopt_socks5_gssapi_nec"
|
|
166
|
+
have_constant "curlopt_interface"
|
|
167
|
+
have_constant "curlopt_localport"
|
|
168
|
+
have_constant "curlopt_dns_cache_timeout"
|
|
169
|
+
have_constant "curlopt_dns_use_global_cache"
|
|
170
|
+
have_constant "curlopt_buffersize"
|
|
171
|
+
have_constant "curlopt_port"
|
|
172
|
+
have_constant "curlopt_tcp_nodelay"
|
|
173
|
+
have_constant "curlopt_address_scope"
|
|
174
|
+
have_constant "curlopt_netrc"
|
|
175
|
+
have_constant "curl_netrc_optional"
|
|
176
|
+
have_constant "curl_netrc_ignored"
|
|
177
|
+
have_constant "curl_netrc_required"
|
|
178
|
+
have_constant "curlopt_netrc_file"
|
|
179
|
+
have_constant "curlopt_userpwd"
|
|
180
|
+
have_constant "curlopt_proxyuserpwd"
|
|
181
|
+
have_constant "curlopt_username"
|
|
182
|
+
have_constant "curlopt_password"
|
|
183
|
+
have_constant "curlopt_password"
|
|
184
|
+
have_constant "curlopt_password"
|
|
185
|
+
have_constant "curlopt_httpauth"
|
|
186
|
+
have_constant "curlauth_digest_ie"
|
|
187
|
+
have_constant "curlauth_only"
|
|
188
|
+
have_constant "curlopt_tlsauth_type"
|
|
189
|
+
have_constant "curlopt_tlsauth_srp"
|
|
190
|
+
have_constant "curlopt_tlsauth_username"
|
|
191
|
+
have_constant "curlopt_tlsauth_password"
|
|
192
|
+
have_constant "curlopt_proxyauth"
|
|
193
|
+
have_constant "curlopt_autoreferer"
|
|
194
|
+
have_constant "curlopt_encoding"
|
|
195
|
+
have_constant "curlopt_followlocation"
|
|
196
|
+
have_constant "curlopt_unrestricted_auth"
|
|
197
|
+
have_constant "curlopt_maxredirs"
|
|
198
|
+
have_constant "curlopt_postredir"
|
|
199
|
+
have_constant "curlopt_put"
|
|
200
|
+
have_constant "curlopt_post"
|
|
201
|
+
have_constant "curlopt_postfields"
|
|
202
|
+
have_constant "curlopt_postfieldsize"
|
|
203
|
+
have_constant "curlopt_postfieldsize_large"
|
|
204
|
+
have_constant "curlopt_copypostfields"
|
|
205
|
+
have_constant "curlopt_httppost"
|
|
206
|
+
have_constant "curlopt_referer"
|
|
207
|
+
have_constant "curlopt_useragent"
|
|
208
|
+
have_constant "curlopt_httpheader"
|
|
209
|
+
have_constant "curlopt_http200aliases"
|
|
210
|
+
have_constant "curlopt_cookie"
|
|
211
|
+
have_constant "curlopt_cookiefile"
|
|
212
|
+
have_constant "curlopt_cookiejar"
|
|
213
|
+
have_constant "curlopt_cookiesession"
|
|
214
|
+
have_constant "curlopt_cookielist"
|
|
215
|
+
have_constant "curlopt_httpget"
|
|
216
|
+
have_constant "curlopt_http_version"
|
|
217
|
+
have_constant "curl_http_version_none"
|
|
218
|
+
have_constant "curl_http_version_1_0"
|
|
219
|
+
have_constant "curl_http_version_1_1"
|
|
220
|
+
have_constant "curlopt_ignore_content_length"
|
|
221
|
+
have_constant "curlopt_http_content_decoding"
|
|
222
|
+
have_constant "curlopt_http_transfer_decoding"
|
|
223
|
+
have_constant "curlopt_mail_from"
|
|
224
|
+
have_constant "curlopt_mail_rcpt"
|
|
225
|
+
have_constant "curlopt_tftp_blksize"
|
|
226
|
+
have_constant "curlopt_ftpport"
|
|
227
|
+
have_constant "curlopt_quote"
|
|
228
|
+
have_constant "curlopt_postquote"
|
|
229
|
+
have_constant "curlopt_prequote"
|
|
230
|
+
have_constant "curlopt_dirlistonly"
|
|
231
|
+
have_constant "curlopt_append"
|
|
232
|
+
have_constant "curlopt_ftp_use_eprt"
|
|
233
|
+
have_constant "curlopt_ftp_use_epsv"
|
|
234
|
+
have_constant "curlopt_ftp_use_pret"
|
|
235
|
+
have_constant "curlopt_ftp_create_missing_dirs"
|
|
236
|
+
have_constant "curlopt_ftp_response_timeout"
|
|
237
|
+
have_constant "curlopt_ftp_alternative_to_user"
|
|
238
|
+
have_constant "curlopt_ftp_skip_pasv_ip"
|
|
239
|
+
have_constant "curlopt_ftpsslauth"
|
|
240
|
+
have_constant "curlftpauth_default"
|
|
241
|
+
have_constant "curlftpauth_ssl"
|
|
242
|
+
have_constant "curlftpauth_tls"
|
|
243
|
+
have_constant "curlopt_ftp_ssl_ccc"
|
|
244
|
+
have_constant "curlftpssl_ccc_none"
|
|
245
|
+
have_constant "curlftpssl_ccc_passive"
|
|
246
|
+
have_constant "curlftpssl_ccc_active"
|
|
247
|
+
have_constant "curlopt_ftp_account"
|
|
248
|
+
have_constant "curlopt_ftp_filemethod"
|
|
249
|
+
have_constant "curlftpmethod_multicwd"
|
|
250
|
+
have_constant "curlftpmethod_nocwd"
|
|
251
|
+
have_constant "curlftpmethod_singlecwd"
|
|
252
|
+
have_constant "curlopt_rtsp_request"
|
|
253
|
+
have_constant "curl_rtspreq_options"
|
|
254
|
+
have_constant "curl_rtspreq_describe"
|
|
255
|
+
have_constant "curl_rtspreq_announce"
|
|
256
|
+
have_constant "curl_rtspreq_setup"
|
|
257
|
+
have_constant "curl_rtspreq_play"
|
|
258
|
+
have_constant "curl_rtspreq_pause"
|
|
259
|
+
have_constant "curl_rtspreq_teardown"
|
|
260
|
+
have_constant "curl_rtspreq_get_parameter"
|
|
261
|
+
have_constant "curl_rtspreq_set_parameter"
|
|
262
|
+
have_constant "curl_rtspreq_record"
|
|
263
|
+
have_constant "curl_rtspreq_receive"
|
|
264
|
+
have_constant "curlopt_rtsp_session_id"
|
|
265
|
+
have_constant "curlopt_rtsp_stream_uri"
|
|
266
|
+
have_constant "curlopt_rtsp_transport"
|
|
267
|
+
have_constant "curlopt_rtsp_header"
|
|
268
|
+
have_constant "curlopt_rtsp_client_cseq"
|
|
269
|
+
have_constant "curlopt_rtsp_server_cseq"
|
|
270
|
+
have_constant "curlopt_transfertext"
|
|
271
|
+
have_constant "curlopt_proxy_transfer_mode"
|
|
272
|
+
have_constant "curlopt_crlf"
|
|
273
|
+
have_constant "curlopt_range"
|
|
274
|
+
have_constant "curlopt_resume_from"
|
|
275
|
+
have_constant "curlopt_resume_from_large"
|
|
276
|
+
have_constant "curlopt_customrequest"
|
|
277
|
+
have_constant "curlopt_filetime"
|
|
278
|
+
have_constant "curlopt_nobody"
|
|
279
|
+
have_constant "curlopt_infilesize"
|
|
280
|
+
have_constant "curlopt_infilesize_large"
|
|
281
|
+
have_constant "curlopt_upload"
|
|
282
|
+
have_constant "curlopt_maxfilesize"
|
|
283
|
+
have_constant "curlopt_maxfilesize_large"
|
|
284
|
+
have_constant "curlopt_timecondition"
|
|
285
|
+
have_constant "curlopt_timevalue"
|
|
286
|
+
have_constant "curlopt_timeout"
|
|
287
|
+
have_constant "curlopt_timeout_ms"
|
|
288
|
+
have_constant "curlopt_low_speed_limit"
|
|
289
|
+
have_constant "curlopt_low_speed_time"
|
|
290
|
+
have_constant "curlopt_max_send_speed_large"
|
|
291
|
+
have_constant "curlopt_max_recv_speed_large"
|
|
292
|
+
have_constant "curlopt_maxconnects"
|
|
293
|
+
have_constant "curlopt_closepolicy"
|
|
294
|
+
have_constant "curlopt_fresh_connect"
|
|
295
|
+
have_constant "curlopt_forbid_reuse"
|
|
296
|
+
have_constant "curlopt_connecttimeout"
|
|
297
|
+
have_constant "curlopt_connecttimeout_ms"
|
|
298
|
+
have_constant "curlopt_ipresolve"
|
|
299
|
+
have_constant "curl_ipresolve_whatever"
|
|
300
|
+
have_constant "curl_ipresolve_v4"
|
|
301
|
+
have_constant "curl_ipresolve_v6"
|
|
302
|
+
have_constant "curlopt_connect_only"
|
|
303
|
+
have_constant "curlopt_use_ssl"
|
|
304
|
+
have_constant "curlusessl_none"
|
|
305
|
+
have_constant "curlusessl_try"
|
|
306
|
+
have_constant "curlusessl_control"
|
|
307
|
+
have_constant "curlusessl_all"
|
|
308
|
+
have_constant "curlopt_resolve"
|
|
309
|
+
have_constant "curlopt_sslcert"
|
|
310
|
+
have_constant "curlopt_sslcerttype"
|
|
311
|
+
have_constant "curlopt_sslkey"
|
|
312
|
+
have_constant "curlopt_sslkeytype"
|
|
313
|
+
have_constant "curlopt_keypasswd"
|
|
314
|
+
have_constant "curlopt_sslengine"
|
|
315
|
+
have_constant "curlopt_sslengine_default"
|
|
316
|
+
have_constant "curlopt_sslversion"
|
|
317
|
+
have_constant "curl_sslversion_default"
|
|
318
|
+
have_constant :CURL_SSLVERSION_TLSv1
|
|
319
|
+
have_constant :CURL_SSLVERSION_SSLv2
|
|
320
|
+
have_constant :CURL_SSLVERSION_SSLv3
|
|
321
|
+
have_constant "curlopt_ssl_verifypeer"
|
|
322
|
+
have_constant "curlopt_cainfo"
|
|
323
|
+
have_constant "curlopt_issuercert"
|
|
324
|
+
have_constant "curlopt_capath"
|
|
325
|
+
have_constant "curlopt_crlfile"
|
|
326
|
+
have_constant "curlopt_ssl_verifyhost"
|
|
327
|
+
have_constant "curlopt_certinfo"
|
|
328
|
+
have_constant "curlopt_random_file"
|
|
329
|
+
have_constant "curlopt_egdsocket"
|
|
330
|
+
have_constant "curlopt_ssl_cipher_list"
|
|
331
|
+
have_constant "curlopt_ssl_sessionid_cache"
|
|
332
|
+
have_constant "curlopt_krblevel"
|
|
333
|
+
have_constant "curlopt_ssh_auth_types"
|
|
334
|
+
have_constant "curlopt_ssh_host_public_key_md5"
|
|
335
|
+
have_constant "curlopt_ssh_public_keyfile"
|
|
336
|
+
have_constant "curlopt_ssh_private_keyfile"
|
|
337
|
+
have_constant "curlopt_ssh_knownhosts"
|
|
338
|
+
have_constant "curlopt_ssh_keyfunction"
|
|
339
|
+
have_constant "curlkhstat_fine_add_to_file"
|
|
340
|
+
have_constant "curlkhstat_fine"
|
|
341
|
+
have_constant "curlkhstat_reject"
|
|
342
|
+
have_constant "curlkhstat_defer"
|
|
343
|
+
have_constant "curlopt_ssh_keydata"
|
|
344
|
+
have_constant "curlopt_private"
|
|
345
|
+
have_constant "curlopt_share"
|
|
346
|
+
have_constant "curlopt_new_file_perms"
|
|
347
|
+
have_constant "curlopt_new_directory_perms"
|
|
348
|
+
have_constant "curlopt_telnetoptions"
|
|
349
|
+
# was obsoleted in August 2007 for 7.17.0, reused in April 2011 for 7.21.5
|
|
350
|
+
have_constant "curle_not_built_in"
|
|
351
|
+
|
|
352
|
+
have_constant "curle_obsolete" # removed in 7.24 ?
|
|
353
|
+
|
|
128
354
|
if try_compile('int main() { return 0; }','-Wall')
|
|
129
355
|
$CFLAGS << ' -Wall'
|
|
130
356
|
end
|
|
@@ -167,5 +393,7 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
|
|
|
167
393
|
}
|
|
168
394
|
})
|
|
169
395
|
|
|
396
|
+
have_func('rb_thread_blocking_region')
|
|
397
|
+
|
|
170
398
|
create_header('curb_config.h')
|
|
171
399
|
create_makefile('curb_core')
|
data/lib/curb.rb
CHANGED
|
@@ -1,186 +1 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
3
|
-
module Curl
|
|
4
|
-
|
|
5
|
-
class Easy
|
|
6
|
-
class << self
|
|
7
|
-
|
|
8
|
-
# call-seq:
|
|
9
|
-
# Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
|
|
10
|
-
#
|
|
11
|
-
# Stream the specified url (via perform) and save the data directly to the
|
|
12
|
-
# supplied filename (defaults to the last component of the URL path, which will
|
|
13
|
-
# usually be the filename most simple urls).
|
|
14
|
-
#
|
|
15
|
-
# If a block is supplied, it will be passed the curl instance prior to the
|
|
16
|
-
# perform call.
|
|
17
|
-
#
|
|
18
|
-
# *Note* that the semantics of the on_body handler are subtly changed when using
|
|
19
|
-
# download, to account for the automatic routing of data to the specified file: The
|
|
20
|
-
# data string is passed to the handler *before* it is written
|
|
21
|
-
# to the file, allowing the handler to perform mutative operations where
|
|
22
|
-
# necessary. As usual, the transfer will be aborted if the on_body handler
|
|
23
|
-
# returns a size that differs from the data chunk size - in this case, the
|
|
24
|
-
# offending chunk will *not* be written to the file, the file will be closed,
|
|
25
|
-
# and a Curl::Err::AbortedByCallbackError will be raised.
|
|
26
|
-
def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
|
|
27
|
-
curl = Curl::Easy.new(url, &blk)
|
|
28
|
-
|
|
29
|
-
File.open(filename, "wb") do |output|
|
|
30
|
-
old_on_body = curl.on_body do |data|
|
|
31
|
-
result = old_on_body ? old_on_body.call(data) : data.length
|
|
32
|
-
output << data if result == data.length
|
|
33
|
-
result
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
curl.perform
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
return curl
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Allow the incoming cert string to be file:password
|
|
44
|
-
# but be careful to not use a colon from a windows file path
|
|
45
|
-
# as the split point. Mimic what curl's main does
|
|
46
|
-
alias_method :native_cert=, :cert=
|
|
47
|
-
def cert=(cert_file)
|
|
48
|
-
pos = cert_file.rindex(':')
|
|
49
|
-
if pos && pos > 1
|
|
50
|
-
self.native_cert= cert_file[0..pos-1]
|
|
51
|
-
self.certpassword= cert_file[pos+1..-1]
|
|
52
|
-
else
|
|
53
|
-
self.native_cert= cert_file
|
|
54
|
-
end
|
|
55
|
-
self.cert
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
class Multi
|
|
60
|
-
class << self
|
|
61
|
-
# call-seq:
|
|
62
|
-
# Curl::Multi.get('url1','url2','url3','url4','url5', :follow_location => true) do|easy|
|
|
63
|
-
# easy
|
|
64
|
-
# end
|
|
65
|
-
#
|
|
66
|
-
# Blocking call to fetch multiple url's in parallel.
|
|
67
|
-
def get(urls, easy_options={}, multi_options={}, &blk)
|
|
68
|
-
url_confs = []
|
|
69
|
-
urls.each do|url|
|
|
70
|
-
url_confs << {:url => url, :method => :get}.merge(easy_options)
|
|
71
|
-
end
|
|
72
|
-
self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# call-seq:
|
|
76
|
-
#
|
|
77
|
-
# Curl::Multi.post([{:url => 'url1', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
|
|
78
|
-
# {:url => 'url2', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
|
|
79
|
-
# {:url => 'url3', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}}],
|
|
80
|
-
# { :follow_location => true, :multipart_form_post => true },
|
|
81
|
-
# {:pipeline => true }) do|easy|
|
|
82
|
-
# easy_handle_on_request_complete
|
|
83
|
-
# end
|
|
84
|
-
#
|
|
85
|
-
# Blocking call to POST multiple form's in parallel.
|
|
86
|
-
#
|
|
87
|
-
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
88
|
-
# easy_options: are a set of common options to set on all easy handles
|
|
89
|
-
# multi_options: options to set on the Curl::Multi handle
|
|
90
|
-
#
|
|
91
|
-
def post(urls_with_config, easy_options={}, multi_options={}, &blk)
|
|
92
|
-
url_confs = []
|
|
93
|
-
urls_with_config.each do|uconf|
|
|
94
|
-
url_confs << uconf.merge(:method => :post).merge(easy_options)
|
|
95
|
-
end
|
|
96
|
-
self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# call-seq:
|
|
100
|
-
#
|
|
101
|
-
# Curl::Multi.put([{:url => 'url1', :put_data => "some message"},
|
|
102
|
-
# {:url => 'url2', :put_data => IO.read('filepath')},
|
|
103
|
-
# {:url => 'url3', :put_data => "maybe another string or socket?"],
|
|
104
|
-
# {:follow_location => true},
|
|
105
|
-
# {:pipeline => true }) do|easy|
|
|
106
|
-
# easy_handle_on_request_complete
|
|
107
|
-
# end
|
|
108
|
-
#
|
|
109
|
-
# Blocking call to POST multiple form's in parallel.
|
|
110
|
-
#
|
|
111
|
-
# urls_with_config: is a hash of url's pointing to the postfields to send
|
|
112
|
-
# easy_options: are a set of common options to set on all easy handles
|
|
113
|
-
# multi_options: options to set on the Curl::Multi handle
|
|
114
|
-
#
|
|
115
|
-
def put(urls_with_config, easy_options={}, multi_options={}, &blk)
|
|
116
|
-
url_confs = []
|
|
117
|
-
urls_with_config.each do|uconf|
|
|
118
|
-
url_confs << uconf.merge(:method => :put).merge(easy_options)
|
|
119
|
-
end
|
|
120
|
-
self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
# call-seq:
|
|
125
|
-
#
|
|
126
|
-
# Curl::Multi.http( [
|
|
127
|
-
# { :url => 'url1', :method => :post,
|
|
128
|
-
# :post_fields => {'field1' => 'value1', 'field2' => 'value2'} },
|
|
129
|
-
# { :url => 'url2', :method => :get,
|
|
130
|
-
# :follow_location => true, :max_redirects => 3 },
|
|
131
|
-
# { :url => 'url3', :method => :put, :put_data => File.open('file.txt','rb') },
|
|
132
|
-
# { :url => 'url4', :method => :head }
|
|
133
|
-
# ], {:pipeline => true})
|
|
134
|
-
#
|
|
135
|
-
# Blocking call to issue multiple HTTP requests with varying verb's.
|
|
136
|
-
#
|
|
137
|
-
# urls_with_config: is a hash of url's pointing to the easy handle options as well as the special option :method, that can by one of [:get, :post, :put, :delete, :head], when no verb is provided e.g. :method => nil -> GET is used
|
|
138
|
-
# multi_options: options for the multi handle
|
|
139
|
-
# blk: a callback, that yeilds when a handle is completed
|
|
140
|
-
#
|
|
141
|
-
def http(urls_with_config, multi_options={}, &blk)
|
|
142
|
-
m = Curl::Multi.new
|
|
143
|
-
# configure the multi handle
|
|
144
|
-
multi_options.each { |k,v| m.send("#{k}=", v) }
|
|
145
|
-
|
|
146
|
-
urls_with_config.each do|conf|
|
|
147
|
-
c = conf.dup # avoid being destructive to input
|
|
148
|
-
url = c.delete(:url)
|
|
149
|
-
method = c.delete(:method)
|
|
150
|
-
headers = c.delete(:headers)
|
|
151
|
-
|
|
152
|
-
easy = Curl::Easy.new(url)
|
|
153
|
-
|
|
154
|
-
case method
|
|
155
|
-
when :post
|
|
156
|
-
fields = c.delete(:post_fields)
|
|
157
|
-
# set the post post using the url fields
|
|
158
|
-
easy.post_body = fields.map{|f,k| "#{easy.escape(f)}=#{easy.escape(k)}"}.join('&')
|
|
159
|
-
when :put
|
|
160
|
-
easy.put_data = c.delete(:put_data)
|
|
161
|
-
when :head
|
|
162
|
-
easy.head = true
|
|
163
|
-
when :delete
|
|
164
|
-
easy.delete = true
|
|
165
|
-
when :get
|
|
166
|
-
else
|
|
167
|
-
# XXX: nil is treated like a GET
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# headers is a special key
|
|
171
|
-
headers.each {|k,v| easy.headers[k] = v } if headers
|
|
172
|
-
|
|
173
|
-
#
|
|
174
|
-
# use the remaining options as specific configuration to the easy handle
|
|
175
|
-
# bad options should raise an undefined method error
|
|
176
|
-
#
|
|
177
|
-
c.each { |k,v| easy.send("#{k}=",v) }
|
|
178
|
-
|
|
179
|
-
easy.on_complete {|curl,code| blk.call(curl,code,method) } if blk
|
|
180
|
-
m.add(easy)
|
|
181
|
-
end
|
|
182
|
-
m.perform
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
1
|
+
require 'curl'
|