curb 0.5.8.0-x86-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of curb might be problematic. Click here for more details.

@@ -0,0 +1,40 @@
1
+ /* curb_postfield.h - Field class for POST method
2
+ * Copyright (c)2006 Ross Bamford.
3
+ * Licensed under the Ruby License. See LICENSE for details.
4
+ *
5
+ * $Id: curb_postfield.h 4 2006-11-17 18:35:31Z roscopeco $
6
+ */
7
+ #ifndef __CURB_POSTFIELD_H
8
+ #define __CURB_POSTFIELD_H
9
+
10
+ #include "curb.h"
11
+
12
+ /*
13
+ * postfield doesn't actually wrap a curl_httppost - instead,
14
+ * it just holds together some ruby objects and has a C-side
15
+ * method to add it to a given form list during the perform.
16
+ */
17
+ typedef struct {
18
+ /* Objects we associate */
19
+ VALUE name;
20
+ VALUE content;
21
+ VALUE content_type;
22
+ VALUE content_proc;
23
+ VALUE local_file;
24
+ VALUE remote_file;
25
+
26
+ /* this will sometimes hold a string, which is the result
27
+ * of the content_proc invocation. We need it to hang around.
28
+ */
29
+ VALUE buffer_str;
30
+ } ruby_curl_postfield;
31
+
32
+ extern VALUE cCurlPostField;
33
+
34
+ void append_to_form(VALUE self,
35
+ struct curl_httppost **first,
36
+ struct curl_httppost **last);
37
+
38
+ void init_curb_postfield();
39
+
40
+ #endif
Binary file
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) 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 = FIX2INT(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/curb_upload.o ADDED
Binary file
data/ext/extconf.rb ADDED
@@ -0,0 +1,162 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('curl')
4
+
5
+ if find_executable('curl-config')
6
+ $CFLAGS << " #{`curl-config --cflags`.strip}"
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')
18
+ fail <<-EOM
19
+ Can't find libcurl or curl/curl.h
20
+
21
+ Try passing --with-curl-dir or --with-curl-lib and --with-curl-include
22
+ options to extconf.
23
+ EOM
24
+ end
25
+
26
+ # Check arch flags
27
+ archs = $CFLAGS.scan(/-arch\s(.*?)\s/).first # get the first arch flag
28
+ if archs and archs.size >= 1
29
+ # need to reduce the number of archs...
30
+ # guess the first one is correct... at least the first one is probably the ruby installed arch...
31
+ # this could lead to compiled binaries that crash at runtime...
32
+ $CFLAGS.gsub!(/-arch\s(.*?)\s/,' ')
33
+ $CFLAGS << " -arch #{archs.first}"
34
+ puts "Selected arch: #{archs.first}"
35
+ end
36
+
37
+ def define(s)
38
+ $defs.push( format("-D HAVE_%s", s.to_s.upcase) )
39
+ end
40
+
41
+ def have_constant(name)
42
+ checking_for name do
43
+ src = %{
44
+ #include <curl/curl.h>
45
+ int main() {
46
+ int test = (int)#{name.upcase};
47
+ return 0;
48
+ }
49
+ }
50
+ if try_compile(src,"#{$CFLAGS} #{$LIBS}")
51
+ define name
52
+ true
53
+ else
54
+ false
55
+ end
56
+ end
57
+ end
58
+
59
+ have_constant "curlinfo_redirect_time"
60
+ have_constant "curlinfo_response_code"
61
+ have_constant "curlinfo_filetime"
62
+ have_constant "curlinfo_redirect_count"
63
+ have_constant "curlinfo_os_errno"
64
+ have_constant "curlinfo_num_connects"
65
+ have_constant "curlinfo_ftp_entry_path"
66
+ have_constant "curl_version_ssl"
67
+ have_constant "curl_version_libz"
68
+ have_constant "curl_version_ntlm"
69
+ have_constant "curl_version_gssnegotiate"
70
+ have_constant "curl_version_debug"
71
+ have_constant "curl_version_asynchdns"
72
+ have_constant "curl_version_spnego"
73
+ have_constant "curl_version_largefile"
74
+ have_constant "curl_version_idn"
75
+ have_constant "curl_version_sspi"
76
+ have_constant "curl_version_conv"
77
+ have_constant "curlproxy_http"
78
+ have_constant "curlproxy_socks4"
79
+ have_constant "curlproxy_socks5"
80
+ have_constant "curlauth_basic"
81
+ have_constant "curlauth_digest"
82
+ have_constant "curlauth_gssnegotiate"
83
+ have_constant "curlauth_ntlm"
84
+ have_constant "curlauth_anysafe"
85
+ have_constant "curlauth_any"
86
+ have_constant "curle_tftp_notfound"
87
+ have_constant "curle_tftp_perm"
88
+ have_constant "curle_tftp_diskfull"
89
+ have_constant "curle_tftp_illegal"
90
+ have_constant "curle_tftp_unknownid"
91
+ have_constant "curle_tftp_exists"
92
+ have_constant "curle_tftp_nosuchuser"
93
+ # older versions of libcurl 7.12
94
+ have_constant "curle_send_fail_rewind"
95
+ have_constant "curle_ssl_engine_initfailed"
96
+ have_constant "curle_login_denied"
97
+
98
+ # older than 7.16.3
99
+ have_constant "curlmopt_maxconnects"
100
+
101
+ # additional consts
102
+ have_constant "curle_conv_failed"
103
+ have_constant "curle_conv_reqd"
104
+ have_constant "curle_ssl_cacert_badfile"
105
+ have_constant "curle_remote_file_not_found"
106
+ have_constant "curle_ssh"
107
+ have_constant "curle_ssl_shutdown_failed"
108
+ have_constant "curle_again"
109
+ have_constant "curle_ssl_crl_badfile"
110
+ have_constant "curle_ssl_issuer_error"
111
+
112
+ # centos 4.5 build of libcurl
113
+ have_constant "curlm_bad_socket"
114
+ have_constant "curlm_unknown_option"
115
+ have_func("curl_multi_timeout")
116
+ have_func("curl_multi_fdset")
117
+ have_func("curl_multi_perform")
118
+
119
+ if try_compile('int main() { return 0; }','-Wall')
120
+ $CFLAGS << ' -Wall'
121
+ end
122
+
123
+ # do some checking to detect ruby 1.8 hash.c vs ruby 1.9 hash.c
124
+ def test_for(name, const, src)
125
+ checking_for name do
126
+ if try_compile(src,"#{$CFLAGS} #{$LIBS}")
127
+ define const
128
+ true
129
+ else
130
+ false
131
+ end
132
+ end
133
+ end
134
+ test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
135
+ #include <ruby.h>
136
+ int main() {
137
+ VALUE hash = rb_hash_new();
138
+ if( RHASH(hash)->ntbl->num_entries ) {
139
+ return 0;
140
+ }
141
+ return 1;
142
+ }
143
+ })
144
+ test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
145
+ #include <ruby.h>
146
+ #include <ruby/st.h>
147
+ int main() {
148
+ return 0;
149
+ }
150
+ })
151
+
152
+ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
153
+ #include <curl/curl.h>
154
+ int main() {
155
+ CURL *easy = curl_easy_init();
156
+ curl_easy_escape(easy,"hello",5);
157
+ return 0;
158
+ }
159
+ })
160
+
161
+ create_header('curb_config.h')
162
+ create_makefile('curb_core')
data/lib/curb.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'curb_core'
2
+
3
+ module Curl
4
+ class Easy
5
+ class << self
6
+
7
+ # call-seq:
8
+ # Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
9
+ #
10
+ # Stream the specified url (via perform) and save the data directly to the
11
+ # supplied filename (defaults to the last component of the URL path, which will
12
+ # usually be the filename most simple urls).
13
+ #
14
+ # If a block is supplied, it will be passed the curl instance prior to the
15
+ # perform call.
16
+ #
17
+ # *Note* that the semantics of the on_body handler are subtly changed when using
18
+ # download, to account for the automatic routing of data to the specified file: The
19
+ # data string is passed to the handler *before* it is written
20
+ # to the file, allowing the handler to perform mutative operations where
21
+ # necessary. As usual, the transfer will be aborted if the on_body handler
22
+ # returns a size that differs from the data chunk size - in this case, the
23
+ # offending chunk will *not* be written to the file, the file will be closed,
24
+ # and a Curl::Err::AbortedByCallbackError will be raised.
25
+ def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
26
+ curl = Curl::Easy.new(url, &blk)
27
+
28
+ File.open(filename, "wb") do |output|
29
+ old_on_body = curl.on_body do |data|
30
+ result = old_on_body ? old_on_body.call(data) : data.length
31
+ output << data if result == data.length
32
+ result
33
+ end
34
+
35
+ curl.perform
36
+ end
37
+
38
+ return curl
39
+ end
40
+ end
41
+
42
+ # Allow the incoming cert string to be file:password
43
+ # but be careful to not use a colon from a windows file path
44
+ # as the split point. Mimic what curl's main does
45
+ alias_method :native_cert=, :cert=
46
+ def cert=(cert_file)
47
+ pos = cert_file.rindex(':')
48
+ if pos && pos > 1
49
+ self.native_cert= cert_file[0..pos-1]
50
+ self.certpassword= cert_file[pos+1..-1]
51
+ else
52
+ self.native_cert= cert_file
53
+ end
54
+ self.cert
55
+ end
56
+ end
57
+ class Multi
58
+ class << self
59
+ # call-seq:
60
+ # Curl::Multi.get('url1','url2','url3','url4','url5', :follow_location => true) do|easy|
61
+ # easy
62
+ # end
63
+ #
64
+ # Blocking call to fetch multiple url's in parallel.
65
+ def get(urls, easy_options={}, multi_options={}, &blk)
66
+ url_confs = []
67
+ urls.each do|url|
68
+ url_confs << {:url => url, :method => :get}.merge(easy_options)
69
+ end
70
+ self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
71
+ end
72
+
73
+ # call-seq:
74
+ #
75
+ # Curl::Multi.post([{:url => 'url1', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
76
+ # {:url => 'url2', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}},
77
+ # {:url => 'url3', :post_fields => {'field1' => 'value1', 'field2' => 'value2'}}],
78
+ # { :follow_location => true, :multipart_form_post => true },
79
+ # {:pipeline => true }) do|easy|
80
+ # easy_handle_on_request_complete
81
+ # end
82
+ #
83
+ # Blocking call to POST multiple form's in parallel.
84
+ #
85
+ # urls_with_config: is a hash of url's pointing to the postfields to send
86
+ # easy_options: are a set of common options to set on all easy handles
87
+ # multi_options: options to set on the Curl::Multi handle
88
+ #
89
+ def post(urls_with_config, easy_options={}, multi_options={}, &blk)
90
+ url_confs = []
91
+ urls_with_config.each do|uconf|
92
+ url_confs << uconf.merge(:method => :post).merge(easy_options)
93
+ end
94
+ self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
95
+ end
96
+
97
+ # call-seq:
98
+ #
99
+ # Curl::Multi.put([{:url => 'url1', :put_data => "some message"},
100
+ # {:url => 'url2', :put_data => IO.read('filepath')},
101
+ # {:url => 'url3', :put_data => "maybe another string or socket?"],
102
+ # {:follow_location => true},
103
+ # {:pipeline => true }) do|easy|
104
+ # easy_handle_on_request_complete
105
+ # end
106
+ #
107
+ # Blocking call to POST multiple form's in parallel.
108
+ #
109
+ # urls_with_config: is a hash of url's pointing to the postfields to send
110
+ # easy_options: are a set of common options to set on all easy handles
111
+ # multi_options: options to set on the Curl::Multi handle
112
+ #
113
+ def put(urls_with_config, easy_options={}, multi_options={}, &blk)
114
+ url_confs = []
115
+ urls_with_config.each do|uconf|
116
+ url_confs << uconf.merge(:method => :put).merge(easy_options)
117
+ end
118
+ self.http(url_confs, multi_options) {|c,code,method| blk.call(c) }
119
+ end
120
+
121
+
122
+ # call-seq:
123
+ #
124
+ # Curl::Multi.http( [
125
+ # { :url => 'url1', :method => :post,
126
+ # :post_fields => {'field1' => 'value1', 'field2' => 'value2'} },
127
+ # { :url => 'url2', :method => :get,
128
+ # :follow_location => true, :max_redirects => 3 },
129
+ # { :url => 'url3', :method => :put, :put_data => File.open('file.txt','rb') },
130
+ # { :url => 'url4', :method => :head }
131
+ # ], {:pipeline => true})
132
+ #
133
+ # Blocking call to issue multiple HTTP requests with varying verb's.
134
+ #
135
+ # 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
136
+ # multi_options: options for the multi handle
137
+ # blk: a callback, that yeilds when a handle is completed
138
+ #
139
+ def http(urls_with_config, multi_options={}, &blk)
140
+ m = Curl::Multi.new
141
+ # configure the multi handle
142
+ multi_options.each { |k,v| m.send("#{k}=", v) }
143
+
144
+ urls_with_config.each do|conf|
145
+ c = conf.dup # avoid being destructive to input
146
+ url = c.delete(:url)
147
+ method = c.delete(:method)
148
+ headers = c.delete(:headers)
149
+
150
+ easy = Curl::Easy.new(url)
151
+
152
+ case method
153
+ when :post
154
+ fields = c.delete(:post_fields)
155
+ # set the post post using the url fields
156
+ easy.post_body = fields.map{|f,k| "#{easy.escape(f)}=#{easy.escape(k)}"}.join('&')
157
+ when :put
158
+ easy.put_data = c.delete(:put_data)
159
+ when :head
160
+ easy.head = true
161
+ when :delete
162
+ easy.delete = true
163
+ when :get
164
+ else
165
+ # XXX: nil is treated like a GET
166
+ end
167
+
168
+ # headers is a special key
169
+ headers.each {|k,v| easy.headers[k] = v } if headers
170
+
171
+ #
172
+ # use the remaining options as specific configuration to the easy handle
173
+ # bad options should raise an undefined method error
174
+ #
175
+ c.each { |k,v| easy.send("#{k}=",v) }
176
+
177
+ easy.on_complete {|curl,code| blk.call(curl,code,method) } if blk
178
+ m.add(easy)
179
+ end
180
+ m.perform
181
+ end
182
+ end
183
+ end
184
+ end