ethon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/CHANGELOG.md +0 -0
  2. data/Gemfile +6 -0
  3. data/LICENSE +20 -0
  4. data/README.md +85 -0
  5. data/Rakefile +39 -0
  6. data/lib/ethon.rb +18 -0
  7. data/lib/ethon/curl.rb +586 -0
  8. data/lib/ethon/easies/callbacks.rb +80 -0
  9. data/lib/ethon/easies/form.rb +131 -0
  10. data/lib/ethon/easies/header.rb +65 -0
  11. data/lib/ethon/easies/http.rb +43 -0
  12. data/lib/ethon/easies/http/actionable.rb +99 -0
  13. data/lib/ethon/easies/http/delete.rb +23 -0
  14. data/lib/ethon/easies/http/get.rb +22 -0
  15. data/lib/ethon/easies/http/head.rb +22 -0
  16. data/lib/ethon/easies/http/options.rb +22 -0
  17. data/lib/ethon/easies/http/patch.rb +22 -0
  18. data/lib/ethon/easies/http/post.rb +18 -0
  19. data/lib/ethon/easies/http/postable.rb +27 -0
  20. data/lib/ethon/easies/http/put.rb +19 -0
  21. data/lib/ethon/easies/http/putable.rb +22 -0
  22. data/lib/ethon/easies/informations.rb +83 -0
  23. data/lib/ethon/easies/operations.rb +31 -0
  24. data/lib/ethon/easies/options.rb +105 -0
  25. data/lib/ethon/easies/params.rb +54 -0
  26. data/lib/ethon/easies/response_callbacks.rb +25 -0
  27. data/lib/ethon/easies/util.rb +41 -0
  28. data/lib/ethon/easy.rb +104 -0
  29. data/lib/ethon/errors.rb +13 -0
  30. data/lib/ethon/errors/ethon_error.rb +8 -0
  31. data/lib/ethon/errors/multi_add.rb +12 -0
  32. data/lib/ethon/errors/multi_fdset.rb +12 -0
  33. data/lib/ethon/errors/multi_remove.rb +11 -0
  34. data/lib/ethon/errors/multi_timeout.rb +12 -0
  35. data/lib/ethon/errors/select.rb +12 -0
  36. data/lib/ethon/extensions.rb +1 -0
  37. data/lib/ethon/extensions/string.rb +11 -0
  38. data/lib/ethon/multi.rb +47 -0
  39. data/lib/ethon/multies/operations.rb +132 -0
  40. data/lib/ethon/multies/stack.rb +43 -0
  41. data/lib/ethon/version.rb +5 -0
  42. metadata +217 -0
File without changes
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ gem "rake"
5
+ gem "patron"
6
+ gem "curb"
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Hans Hasselberg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,85 @@
1
+ # Ethon [![Build Status](https://secure.travis-ci.org/typhoeus/ethon.png?branch=master)](http://travis-ci.org/typhoeus/ethon)
2
+
3
+ In the greek mythology Ethon is a gigantic eagle the son of Typhoeus and Echidna. So much for the history.
4
+ In the modern world Ethon is a very basic libcurl wrapper using ffi.
5
+
6
+ * [Documentation](http://rubydoc.info/github/typhoeus/ethon)
7
+
8
+ ## Caution
9
+
10
+ This is __alpha__!
11
+
12
+ ## Installation
13
+
14
+ With bundler:
15
+
16
+ gem "ethon", :git => "https://github.com/typhoeus/ethon.git", :branch => "master"
17
+
18
+ ## Usage
19
+
20
+ Making the first request is realy simple:
21
+
22
+ easy = Ethon::Easy.new(:url => "www.google.de")
23
+ easy.prepare
24
+ easy.perform
25
+ #=> :ok
26
+
27
+ You have access to various options like following redirects:
28
+
29
+ easy = Ethon::Easy.new(:url => "www.google.com", :follow_location => true)
30
+ easy.prepare
31
+ easy.perform
32
+ #=> :ok
33
+
34
+ Once you're done you can look at the response code and body:
35
+
36
+ easy = Ethon::Easy.new(:url => "www.google.de")
37
+ easy.prepare
38
+ easy.perform
39
+ easy.response_code
40
+ #=> 200
41
+ easy.response_body
42
+ #=> "<!doctype html><html ..."
43
+
44
+ ## Http
45
+
46
+ In order to make life easier there are some helpers for doing http requests:
47
+
48
+ easy = Ethon::Easy.new
49
+ easy.http_request("www.google.de", :get, { :params => {:a => 1} })
50
+ easy.prepare
51
+ easy.perform
52
+ #=> :ok
53
+
54
+ easy = Ethon::Easy.new
55
+ easy.http_request("www.google.de", :post, { :params => { :a => 1 }, :body => { :b => 2 } })
56
+ easy.prepare
57
+ easy.perform
58
+ #=> :ok
59
+
60
+ This really handy when doing requests since you don't have to care about setting
61
+ everything up correct.
62
+
63
+ ## LICENSE
64
+
65
+ (The MIT License)
66
+
67
+ Copyright © 2012 [Hans Hasselberg](http://www.hans.io)
68
+
69
+ Permission is hereby granted, free of charge, to any person obtaining a
70
+ copy of this software and associated documentation files (the "Software"),
71
+ to deal in the Software without restriction, including without
72
+ limitation the rights to use, copy, modify, merge, publish, distribute,
73
+ sublicense, and/or sell copies of the Software, and to permit persons
74
+ to whom the Software is furnished to do so, subject to the following conditions:
75
+
76
+ The above copyright notice and this permission notice shall be included
77
+ in all copies or substantial portions of the Software.
78
+
79
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
80
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
82
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
83
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
84
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
85
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,39 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ require "rake"
5
+ require "rspec/core/rake_task"
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
7
+ require "ethon/version"
8
+
9
+ task :gem => :build
10
+ task :build do
11
+ system "gem build ethon.gemspec"
12
+ end
13
+
14
+ task :install => :build do
15
+ system "gem install ethon-#{Ethon::VERSION}.gem"
16
+ end
17
+
18
+ task :release => :build do
19
+ system "git tag -a v#{Ethon::VERSION} -m 'Tagging #{Ethon::VERSION}'"
20
+ system "git push --tags"
21
+ system "gem push ethon-#{Ethon::VERSION}.gem"
22
+ end
23
+
24
+ RSpec::Core::RakeTask.new(:spec) do |t|
25
+ t.verbose = false
26
+ t.ruby_opts = "-W -I./spec -rspec_helper"
27
+ end
28
+
29
+ desc "Start up the test servers"
30
+ task :start do
31
+ require 'spec/support/boot'
32
+ begin
33
+ Boot.start_servers(:rake)
34
+ rescue Exception
35
+ end
36
+ end
37
+
38
+ task :default => :spec
39
+
@@ -0,0 +1,18 @@
1
+ require 'ffi'
2
+ require 'rbconfig'
3
+ require 'thread'
4
+ require 'mime/types'
5
+ require 'cgi'
6
+ require 'tempfile'
7
+
8
+ require 'ethon/extensions'
9
+ require 'ethon/curl'
10
+ require 'ethon/errors'
11
+ require 'ethon/easy'
12
+ require 'ethon/multi'
13
+ require 'ethon/version'
14
+
15
+ # The toplevel namespace which includes everything
16
+ # belonging to ethon.
17
+ module Ethon
18
+ end
@@ -0,0 +1,586 @@
1
+ module Ethon
2
+ # :nodoc:
3
+ module Curl
4
+ # :nodoc:
5
+ def Curl.windows?
6
+ !(RbConfig::CONFIG['host_os'] !~ /mingw|mswin|bccwin/)
7
+ end
8
+
9
+ extend ::FFI::Library
10
+
11
+ # :nodoc:
12
+ VERSION_NOW = 3
13
+
14
+ # :nodoc:
15
+ GLOBAL_SSL = 0x01
16
+ # :nodoc:
17
+ GLOBAL_WIN32 = 0x02
18
+ # :nodoc:
19
+ GLOBAL_ALL = (GLOBAL_SSL | GLOBAL_WIN32)
20
+ # :nodoc:
21
+ GLOBAL_DEFAULT = GLOBAL_ALL
22
+
23
+ # :nodoc:
24
+ EasyCode = enum :easy_code, [
25
+ :ok,
26
+ :unsupported_protocol,
27
+ :failed_init,
28
+ :url_malformat,
29
+ :not_built_in,
30
+ :couldnt_resolve_proxy,
31
+ :couldnt_resolve_host,
32
+ :couldnt_connect,
33
+ :ftp_weird_server_reply,
34
+ :remote_access_denied,
35
+ :ftp_accept_failed,
36
+ :ftp_weird_pass_reply,
37
+ :ftp_accept_timeout,
38
+ :ftp_weird_pasv_reply,
39
+ :ftp_weird_227_format,
40
+ :ftp_cant_get_host,
41
+ :obsolete16,
42
+ :ftp_couldnt_set_type,
43
+ :partial_file,
44
+ :ftp_couldnt_retr_file,
45
+ :obsolete20,
46
+ :quote_error,
47
+ :http_returned_error,
48
+ :write_error,
49
+ :obsolete24,
50
+ :upload_failed,
51
+ :read_error,
52
+ :out_of_memory,
53
+ :operation_timedout,
54
+ :obsolete29,
55
+ :ftp_port_failed,
56
+ :ftp_couldnt_use_rest,
57
+ :obsolete32,
58
+ :range_error,
59
+ :http_post_error,
60
+ :ssl_connect_error,
61
+ :bad_download_resume,
62
+ :file_couldnt_read_file,
63
+ :ldap_cannot_bind,
64
+ :ldap_search_failed,
65
+ :obsolete40,
66
+ :function_not_found,
67
+ :aborted_by_callback,
68
+ :bad_function_argument,
69
+ :obsolete44,
70
+ :interface_failed,
71
+ :obsolete46,
72
+ :too_many_redirects ,
73
+ :unknown_option,
74
+ :telnet_option_syntax ,
75
+ :obsolete50,
76
+ :peer_failed_verification,
77
+ :got_nothing,
78
+ :ssl_engine_notfound,
79
+ :ssl_engine_setfailed,
80
+ :send_error,
81
+ :recv_error,
82
+ :obsolete57,
83
+ :ssl_certproblem,
84
+ :ssl_cipher,
85
+ :ssl_cacert,
86
+ :bad_content_encoding,
87
+ :ldap_invalid_url,
88
+ :filesize_exceeded,
89
+ :use_ssl_failed,
90
+ :send_fail_rewind,
91
+ :ssl_engine_initfailed,
92
+ :login_denied,
93
+ :tftp_notfound,
94
+ :tftp_perm,
95
+ :remote_disk_full,
96
+ :tftp_illegal,
97
+ :tftp_unknownid,
98
+ :remote_file_exists,
99
+ :tftp_nosuchuser,
100
+ :conv_failed,
101
+ :conv_reqd,
102
+ :ssl_cacert_badfile,
103
+ :remote_file_not_found,
104
+ :ssh,
105
+ :ssl_shutdown_failed,
106
+ :again,
107
+ :ssl_crl_badfile,
108
+ :ssl_issuer_error,
109
+ :ftp_pret_failed,
110
+ :rtsp_cseq_error,
111
+ :rtsp_session_error,
112
+ :ftp_bad_file_list,
113
+ :chunk_failed,
114
+ :last]
115
+
116
+ # :nodoc:
117
+ MultiCode = enum :multi_code, [
118
+ :call_multi_perform, -1,
119
+ :ok,
120
+ :bad_handle,
121
+ :bad_easy_handle,
122
+ :out_of_memory,
123
+ :internal_error,
124
+ :bad_socket,
125
+ :unknown_option,
126
+ :last]
127
+
128
+ # :nodoc:
129
+ OptionType = enum [
130
+ :long, 0,
131
+ :object_point, 10000,
132
+ :function_point, 20000,
133
+ :off_t, 30000]
134
+
135
+ # :nodoc:
136
+ Option = enum :option, [
137
+ :file, OptionType[:object_point] + 1,
138
+ :writedata, OptionType[:object_point] + 1,
139
+ :url, OptionType[:object_point] + 2,
140
+ :port, OptionType[:long] + 3,
141
+ :proxy, OptionType[:object_point] + 4,
142
+ :userpwd, OptionType[:object_point] + 5,
143
+ :proxyuserpwd, OptionType[:object_point] + 6,
144
+ :range, OptionType[:object_point] + 7,
145
+ :infile, OptionType[:object_point] + 9,
146
+ :readdata, OptionType[:object_point] + 9,
147
+ :errorbuffer, OptionType[:object_point] + 10,
148
+ :writefunction, OptionType[:function_point] + 11,
149
+ :readfunction, OptionType[:function_point] + 12,
150
+ :timeout, OptionType[:long] + 13,
151
+ :infilesize, OptionType[:long] + 14,
152
+ :postfields, OptionType[:object_point] + 15,
153
+ :referer, OptionType[:object_point] + 16,
154
+ :ftpport, OptionType[:object_point] + 17,
155
+ :useragent, OptionType[:object_point] + 18,
156
+ :low_speed_time, OptionType[:long] + 20,
157
+ :resume_from, OptionType[:long] + 21,
158
+ :cookie, OptionType[:object_point] + 22,
159
+ :httpheader, OptionType[:object_point] + 23,
160
+ :httppost, OptionType[:object_point] + 24,
161
+ :sslcert, OptionType[:object_point] + 25,
162
+ :sslcertpasswd, OptionType[:object_point] + 26,
163
+ :sslkeypasswd, OptionType[:object_point] + 26,
164
+ :crlf, OptionType[:long] + 27,
165
+ :quote, OptionType[:object_point] + 28,
166
+ :writeheader, OptionType[:object_point] + 29,
167
+ :headerdata, OptionType[:object_point] + 29,
168
+ :cookiefile, OptionType[:object_point] + 31,
169
+ :sslversion, OptionType[:long] + 32,
170
+ :timecondition, OptionType[:long] + 33,
171
+ :timevalue, OptionType[:long] + 34,
172
+ :customrequest, OptionType[:object_point] + 36,
173
+ :stderr, OptionType[:object_point] + 37,
174
+ :postquote, OptionType[:object_point] + 39,
175
+ :writeinfo, OptionType[:object_point] + 40,
176
+ :verbose, OptionType[:long] + 41,
177
+ :header, OptionType[:long] + 42,
178
+ :noprogress, OptionType[:long] + 43,
179
+ :nobody, OptionType[:long] + 44,
180
+ :failonerror, OptionType[:long] + 45,
181
+ :upload, OptionType[:long] + 46,
182
+ :post, OptionType[:long] + 47,
183
+ :ftplistonly, OptionType[:long] + 48,
184
+ :ftpappend, OptionType[:long] + 50,
185
+ :netrc, OptionType[:long] + 51,
186
+ :followlocation, OptionType[:long] + 52,
187
+ :transfertext, OptionType[:long] + 53,
188
+ :put, OptionType[:long] + 54,
189
+ :progressfunction, OptionType[:function_point] + 56,
190
+ :progressdata, OptionType[:object_point] + 57,
191
+ :autoreferer, OptionType[:long] + 58,
192
+ :proxyport, OptionType[:long] + 59,
193
+ :postfieldsize, OptionType[:long] + 60,
194
+ :httpproxytunnel, OptionType[:long] + 61,
195
+ :interface, OptionType[:object_point] + 62,
196
+ :ssl_verifypeer, OptionType[:long] + 64,
197
+ :cainfo, OptionType[:object_point] + 65,
198
+ :maxredirs, OptionType[:long] + 68,
199
+ :filetime, OptionType[:long] + 69,
200
+ :telnetoptions, OptionType[:object_point] + 70,
201
+ :maxconnects, OptionType[:long] + 71,
202
+ :closepolicy, OptionType[:long] + 72,
203
+ :fresh_connect, OptionType[:long] + 74,
204
+ :forbid_reuse, OptionType[:long] + 75,
205
+ :random_file, OptionType[:object_point] + 76,
206
+ :egdsocket, OptionType[:object_point] + 77,
207
+ :connecttimeout, OptionType[:long] + 78,
208
+ :headerfunction, OptionType[:function_point] + 79,
209
+ :httpget, OptionType[:long] + 80,
210
+ :ssl_verifyhost, OptionType[:long] + 81,
211
+ :cookiejar, OptionType[:object_point] + 82,
212
+ :ssl_cipher_list, OptionType[:object_point] + 83,
213
+ :http_version, OptionType[:long] + 84,
214
+ :ftp_use_epsv, OptionType[:long] + 85,
215
+ :sslcerttype, OptionType[:object_point] + 86,
216
+ :sslkey, OptionType[:object_point] + 87,
217
+ :sslkeytype, OptionType[:object_point] + 88,
218
+ :sslengine, OptionType[:object_point] + 89,
219
+ :sslengine_default, OptionType[:long] + 90,
220
+ :dns_use_global_cache, OptionType[:long] + 91,
221
+ :dns_cache_timeout, OptionType[:long] + 92,
222
+ :prequote, OptionType[:object_point] + 93,
223
+ :debugfunction, OptionType[:function_point] + 94,
224
+ :debugdata, OptionType[:object_point] + 95,
225
+ :cookiesession, OptionType[:long] + 96,
226
+ :capath, OptionType[:object_point] + 97,
227
+ :buffersize, OptionType[:long] + 98,
228
+ :nosignal, OptionType[:long] + 99,
229
+ :share, OptionType[:object_point] + 100,
230
+ :proxytype, OptionType[:long] + 101,
231
+ :encoding, OptionType[:object_point] + 102,
232
+ :private, OptionType[:object_point] + 103,
233
+ :unrestricted_auth, OptionType[:long] + 105,
234
+ :ftp_use_eprt, OptionType[:long] + 106,
235
+ :httpauth, OptionType[:long] + 107,
236
+ :ssl_ctx_function, OptionType[:function_point] + 108,
237
+ :ssl_ctx_data, OptionType[:object_point] + 109,
238
+ :ftp_create_missing_dirs, OptionType[:long] + 110,
239
+ :proxyauth, OptionType[:long] + 111,
240
+ :ipresolve, OptionType[:long] + 113,
241
+ :maxfilesize, OptionType[:long] + 114,
242
+ :infilesize_large, OptionType[:off_t] + 115,
243
+ :resume_from_large, OptionType[:off_t] + 116,
244
+ :maxfilesize_large, OptionType[:off_t] + 117,
245
+ :netrc_file, OptionType[:object_point] + 118,
246
+ :ftp_ssl, OptionType[:long] + 119,
247
+ :postfieldsize_large, OptionType[:off_t] + 120,
248
+ :tcp_nodelay, OptionType[:long] + 121,
249
+ :ftpsslauth, OptionType[:long] + 129,
250
+ :ioctlfunction, OptionType[:function_point] + 130,
251
+ :ioctldata, OptionType[:object_point] + 131,
252
+ :ftp_account, OptionType[:object_point] + 134,
253
+ :cookielist, OptionType[:object_point] + 135,
254
+ :ignore_content_length, OptionType[:long] + 136,
255
+ :ftp_skip_pasv_ip, OptionType[:long] + 137,
256
+ :ftp_filemethod, OptionType[:long] + 138,
257
+ :localport, OptionType[:long] + 139,
258
+ :localportrange, OptionType[:long] + 140,
259
+ :connect_only, OptionType[:long] + 141,
260
+ :conv_from_network_function, OptionType[:function_point] + 142,
261
+ :conv_to_network_function, OptionType[:function_point] + 143,
262
+ :max_send_speed_large, OptionType[:off_t] + 145,
263
+ :max_recv_speed_large, OptionType[:off_t] + 146,
264
+ :ftp_alternative_to_user, OptionType[:object_point] + 147,
265
+ :sockoptfunction, OptionType[:function_point] + 148,
266
+ :sockoptdata, OptionType[:object_point] + 149,
267
+ :ssl_sessionid_cache, OptionType[:long] + 150,
268
+ :ssh_auth_types, OptionType[:long] + 151,
269
+ :ssh_public_keyfile, OptionType[:object_point] + 152,
270
+ :ssh_private_keyfile, OptionType[:object_point] + 153,
271
+ :ftp_ssl_ccc, OptionType[:long] + 154,
272
+ :timeout_ms, OptionType[:long] + 155,
273
+ :connecttimeout_ms, OptionType[:long] + 156,
274
+ :http_transfer_decoding, OptionType[:long] + 157,
275
+ :http_content_decoding, OptionType[:long] + 158,
276
+ :copypostfields, OptionType[:object_point] + 165]
277
+
278
+ # :nodoc:
279
+ InfoType = enum [
280
+ :string, 0x100000,
281
+ :long, 0x200000,
282
+ :double, 0x300000,
283
+ :slist, 0x400000]
284
+
285
+ # :nodoc:
286
+ Info = enum :info, [
287
+ :effective_url, InfoType[:string] + 1,
288
+ :response_code, InfoType[:long] + 2,
289
+ :total_time, InfoType[:double] + 3,
290
+ :namelookup_time, InfoType[:double] + 4,
291
+ :connect_time, InfoType[:double] + 5,
292
+ :pretransfer_time, InfoType[:double] + 6,
293
+ :size_upload, InfoType[:double] + 7,
294
+ :size_download, InfoType[:double] + 8,
295
+ :speed_download, InfoType[:double] + 9,
296
+ :speed_upload, InfoType[:double] + 10,
297
+ :header_size, InfoType[:long] + 11,
298
+ :request_size, InfoType[:long] + 12,
299
+ :ssl_verifyresult, InfoType[:long] + 13,
300
+ :filetime, InfoType[:long] + 14,
301
+ :content_length_download, InfoType[:double] + 15,
302
+ :content_length_upload, InfoType[:double] + 16,
303
+ :starttransfer_time, InfoType[:double] + 17,
304
+ :content_type, InfoType[:string] + 18,
305
+ :redirect_time, InfoType[:double] + 19,
306
+ :redirect_count, InfoType[:long] + 20,
307
+ :private, InfoType[:string] + 21,
308
+ :http_connectcode, InfoType[:long] + 22,
309
+ :httpauth_avail, InfoType[:long] + 23,
310
+ :proxyauth_avail, InfoType[:long] + 24,
311
+ :os_errno, InfoType[:long] + 25,
312
+ :num_connects, InfoType[:long] + 26,
313
+ :ssl_engines, InfoType[:slist] + 27,
314
+ :cookielist, InfoType[:slist] + 28,
315
+ :lastsocket, InfoType[:long] + 29,
316
+ :ftp_entry_path, InfoType[:string] + 30,
317
+ :redirect_url, InfoType[:string] + 31,
318
+ :primary_ip, InfoType[:string] + 32,
319
+ :appconnect_time, InfoType[:double] + 33,
320
+ :certinfo, InfoType[:slist] + 34,
321
+ :condition_unmet, InfoType[:long] + 35,
322
+ :rtsp_session_id, InfoType[:string] + 36,
323
+ :rtsp_client_cseq, InfoType[:long] + 37,
324
+ :rtsp_server_cseq, InfoType[:long] + 38,
325
+ :rtsp_cseq_recv, InfoType[:long] + 39,
326
+ :primary_port, InfoType[:long] + 40,
327
+ :local_ip, InfoType[:string] + 41,
328
+ :local_port, InfoType[:long] + 42,
329
+ :last, 42]
330
+
331
+ # :nodoc:
332
+ FormOption = enum :form_option, [
333
+ :none,
334
+ :copyname,
335
+ :ptrname,
336
+ :namelength,
337
+ :copycontents,
338
+ :ptrcontents,
339
+ :contentslength,
340
+ :filecontent,
341
+ :array,
342
+ :obsolete,
343
+ :file,
344
+ :buffer,
345
+ :bufferptr,
346
+ :bufferlength,
347
+ :contenttype,
348
+ :contentheader,
349
+ :filename,
350
+ :end,
351
+ :obsolete2,
352
+ :stream,
353
+ :last]
354
+
355
+ # :nodoc:
356
+ Auth = enum [
357
+ :basic, 0x01,
358
+ :digest, 0x02,
359
+ :gssnegotiate, 0x04,
360
+ :ntlm, 0x08,
361
+ :digest_ie, 0x10,
362
+ :auto, 0x1f] # all options or'd together
363
+
364
+ # :nodoc:
365
+ Proxy = enum [
366
+ :http, 0,
367
+ :http_1_0, 1,
368
+ :socks4, 4,
369
+ :socks5, 5,
370
+ :socks4a, 6,
371
+ :socks5_hostname, 7]
372
+
373
+ # :nodoc:
374
+ SSLVersion = enum [
375
+ :default, 0,
376
+ :tlsv1, 1,
377
+ :sslv2, 2,
378
+ :sslv3, 3]
379
+
380
+ # :nodoc:
381
+ MsgCode = enum :msg_code, [:none, :done, :last]
382
+
383
+ # :nodoc:
384
+ class MsgData < ::FFI::Union
385
+ layout :whatever, :pointer,
386
+ :code, :easy_code
387
+ end
388
+
389
+ # :nodoc:
390
+ class Msg < ::FFI::Struct
391
+ layout :code, :msg_code,
392
+ :easy_handle, :pointer,
393
+ :data, MsgData
394
+ end
395
+
396
+ # :nodoc:
397
+ class FDSet < ::FFI::Struct
398
+ # XXX how does this work on non-windows? how can curl know the new size...
399
+ FD_SETSIZE = 524288 # set a higher maximum number of fds. this has never applied to windows, so just use the default there
400
+
401
+ if Curl.windows?
402
+ layout :fd_count, :u_int,
403
+ :fd_array, [:u_int, 64] # 2048 FDs
404
+
405
+ def clear; self[:fd_count] = 0; end
406
+ else
407
+ layout :fds_bits, [:long, FD_SETSIZE / ::FFI::Type::LONG.size]
408
+
409
+ # :nodoc:
410
+ def clear; super; end
411
+ end
412
+ end
413
+
414
+ # :nodoc:
415
+ class Timeval < ::FFI::Struct
416
+ layout :sec, :time_t,
417
+ :usec, :suseconds_t
418
+ end
419
+
420
+ callback :callback, [:pointer, :size_t, :size_t, :pointer], :size_t
421
+
422
+ ffi_lib_flags :now, :global
423
+ ffi_lib 'libcurl'
424
+
425
+ attach_function :global_init, :curl_global_init, [:long], :int
426
+
427
+ attach_function :easy_init, :curl_easy_init, [], :pointer
428
+ attach_function :easy_cleanup, :curl_easy_cleanup, [:pointer], :void
429
+ attach_function :easy_getinfo, :curl_easy_getinfo, [:pointer, :info, :pointer], :easy_code
430
+ attach_function :easy_setopt, :curl_easy_setopt, [:pointer, :option, :pointer], :easy_code
431
+ attach_function :easy_setopt_string, :curl_easy_setopt, [:pointer, :option, :string], :easy_code
432
+ attach_function :easy_setopt_long, :curl_easy_setopt, [:pointer, :option, :long], :easy_code
433
+ attach_function :easy_setopt_callback, :curl_easy_setopt, [:pointer, :option, :callback], :easy_code
434
+ attach_function :easy_perform, :curl_easy_perform, [:pointer], :easy_code
435
+ attach_function :easy_strerror, :curl_easy_strerror, [:int], :string
436
+ attach_function :easy_escape, :curl_easy_escape, [:pointer, :pointer, :int], :string
437
+ attach_function :easy_reset, :curl_easy_reset, [:pointer], :void
438
+
439
+ attach_function :formadd, :curl_formadd, [:pointer, :pointer, :varargs], :int
440
+
441
+ attach_function :multi_init, :curl_multi_init, [], :pointer
442
+ attach_function :multi_add_handle, :curl_multi_add_handle, [:pointer, :pointer], :multi_code
443
+ attach_function :multi_remove_handle, :curl_multi_remove_handle, [:pointer, :pointer], :multi_code
444
+ attach_function :multi_info_read, :curl_multi_info_read, [:pointer, :pointer], Msg.ptr
445
+ attach_function :multi_perform, :curl_multi_perform, [:pointer, :pointer], :multi_code
446
+ attach_function :multi_timeout, :curl_multi_timeout, [:pointer, :pointer], :multi_code
447
+ attach_function :multi_fdset, :curl_multi_fdset, [:pointer, FDSet.ptr, FDSet.ptr, FDSet.ptr, :pointer], :multi_code
448
+ attach_function :multi_strerror, :curl_multi_strerror, [:int], :string
449
+
450
+ attach_function :version, :curl_version, [], :string
451
+ attach_function :slist_append, :curl_slist_append, [:pointer, :string], :pointer
452
+ attach_function :slist_free_all, :curl_slist_free_all, [:pointer], :void
453
+
454
+ if windows?
455
+ ffi_lib 'ws2_32'
456
+ else
457
+ ffi_lib ::FFI::Library::LIBC
458
+ end
459
+ @blocking = true
460
+ attach_function :select, [:int, FDSet.ptr, FDSet.ptr, FDSet.ptr, Timeval.ptr], :int
461
+
462
+ @@initialized = false
463
+ @@init_mutex = Mutex.new
464
+
465
+ class << self
466
+ # This function sets up the program environment that libcurl needs.
467
+ # Think of it as an extension of the library loader.
468
+ #
469
+ # This function must be called at least once within a program (a program is all the
470
+ # code that shares a memory space) before the program calls any other function in libcurl.
471
+ # The environment it sets up is constant for the life of the program and is the same for
472
+ # every program, so multiple calls have the same effect as one call.
473
+ #
474
+ # The flags option is a bit pattern that tells libcurl exactly what features to init,
475
+ # as described below. Set the desired bits by ORing the values together. In normal
476
+ # operation, you must specify CURL_GLOBAL_ALL. Don't use any other value unless
477
+ # you are familiar with it and mean to control internal operations of libcurl.
478
+ #
479
+ # This function is not thread safe. You must not call it when any other thread in
480
+ # the program (i.e. a thread sharing the same memory) is running. This doesn't just
481
+ # mean no other thread that is using libcurl. Because curl_global_init() calls
482
+ # functions of other libraries that are similarly thread unsafe, it could conflict with
483
+ # any other thread that uses these other libraries.
484
+ def init
485
+ @@init_mutex.synchronize {
486
+ if not @@initialized
487
+ raise RuntimeError.new('curl failed to initialise') if Curl.global_init(GLOBAL_ALL) != 0
488
+ @@initialized = true
489
+ end
490
+ }
491
+ end
492
+
493
+ # Sets appropriate option for easy, depending on value type.
494
+ def set_option(option, value, handle)
495
+ case value
496
+ when String
497
+ easy_setopt_string(handle, option, value.to_s)
498
+ when Integer
499
+ easy_setopt_long(handle, option, value)
500
+ when Proc, FFI::Function
501
+ easy_setopt_callback(handle, option, value)
502
+ else
503
+ easy_setopt(handle, option, value) if value
504
+ end
505
+ end
506
+
507
+ # Return info as string.
508
+ #
509
+ # @example Return info.
510
+ # Curl.get_info_string(:primary_ip, easy)
511
+ #
512
+ # @param [ Symbol ] option The option name.
513
+ # @param [ ::FFI::Pointer ] handle The easy handle.
514
+ #
515
+ # @return [ String ] The info.
516
+ def get_info_string(option, handle)
517
+ if easy_getinfo(handle, option, string_ptr) == :ok
518
+ string_ptr.read_pointer.read_string
519
+ else nil
520
+ end
521
+ end
522
+
523
+ # Return info as integer.
524
+ #
525
+ # @example Return info.
526
+ # Curl.get_info_long(:response_code, easy)
527
+ #
528
+ # @param [ Symbol ] option The option name.
529
+ # @param [ ::FFI::Pointer ] handle The easy handle.
530
+ #
531
+ # @return [ Integer ] The info.
532
+ def get_info_long(option, handle)
533
+ if easy_getinfo(handle, option, long_ptr) == :ok
534
+ long_ptr.read_long
535
+ else nil
536
+ end
537
+ end
538
+
539
+ # Return info as float.
540
+ #
541
+ # @example Return info.
542
+ # Curl.get_info_double(:response_code, easy)
543
+ #
544
+ # @param [ Symbol ] option The option name.
545
+ # @param [ ::FFI::Pointer ] handle The easy handle.
546
+ #
547
+ # @return [ Float ] The info.
548
+ def get_info_double(option, handle)
549
+ if easy_getinfo(handle, option, double_ptr) == :ok
550
+ double_ptr.read_double
551
+ else nil
552
+ end
553
+ end
554
+
555
+ # Return a string pointer.
556
+ #
557
+ # @example Return a string pointer.
558
+ # Curl.string_ptr
559
+ #
560
+ # @return [ ::FFI::Pointer ] The string pointer.
561
+ def string_ptr
562
+ @string_ptr ||= ::FFI::MemoryPointer.new(:pointer)
563
+ end
564
+
565
+ # Return a long pointer.
566
+ #
567
+ # @example Return a long pointer.
568
+ # Curl.long_ptr
569
+ #
570
+ # @return [ ::FFI::Pointer ] The long pointer.
571
+ def long_ptr
572
+ @long_ptr ||= ::FFI::MemoryPointer.new(:long)
573
+ end
574
+
575
+ # Return a double pointer.
576
+ #
577
+ # @example Return a double pointer.
578
+ # Curl.double_ptr
579
+ #
580
+ # @return [ ::FFI::Pointer ] The double pointer.
581
+ def double_ptr
582
+ @double_ptr ||= ::FFI::MemoryPointer.new(:double)
583
+ end
584
+ end
585
+ end
586
+ end