curb 0.8.5 → 0.8.6

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.
@@ -30,13 +30,13 @@ extern VALUE eCurlErrMalformedURLUser;
30
30
  extern VALUE eCurlErrProxyResolution;
31
31
  extern VALUE eCurlErrHostResolution;
32
32
  extern VALUE eCurlErrConnectFailed;
33
- extern VALUE eCurlErrFTPWierdReply;
33
+ extern VALUE eCurlErrFTPWeirdReply;
34
34
  extern VALUE eCurlErrFTPAccessDenied;
35
35
  extern VALUE eCurlErrFTPBadPassword;
36
- extern VALUE eCurlErrFTPWierdPassReply;
37
- extern VALUE eCurlErrFTPWierdUserReply;
38
- extern VALUE eCurlErrFTPWierdPasvReply;
39
- extern VALUE eCurlErrFTPWierd227Format;
36
+ extern VALUE eCurlErrFTPWeirdPassReply;
37
+ extern VALUE eCurlErrFTPWeirdUserReply;
38
+ extern VALUE eCurlErrFTPWeirdPasvReply;
39
+ extern VALUE eCurlErrFTPWeird227Format;
40
40
  extern VALUE eCurlErrFTPCantGetHost;
41
41
  extern VALUE eCurlErrFTPCantReconnect;
42
42
  extern VALUE eCurlErrFTPCouldntSetBinary;
@@ -116,6 +116,9 @@ extern VALUE mCurlErrOutOfMemory;
116
116
  extern VALUE mCurlErrInternalError;
117
117
  extern VALUE mCurlErrBadSocket;
118
118
  extern VALUE mCurlErrUnknownOption;
119
+ #if HAVE_CURLM_ADDED_ALREADY
120
+ extern VALUE mCurlErrAddedAlready;
121
+ #endif
119
122
 
120
123
  /* binding errors */
121
124
  extern VALUE eCurlErrInvalidPostField;
@@ -4,13 +4,17 @@
4
4
  *
5
5
  */
6
6
  #include "curb_config.h"
7
- #ifdef HAVE_RUBY19_ST_H
8
- #include <ruby.h>
7
+ #include <ruby.h>
8
+ #ifdef HAVE_RUBY_ST_H
9
9
  #include <ruby/st.h>
10
10
  #else
11
- #include <ruby.h>
12
11
  #include <st.h>
13
12
  #endif
13
+
14
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
15
+ #include <ruby/thread.h>
16
+ #endif
17
+
14
18
  #include "curb_easy.h"
15
19
  #include "curb_errors.h"
16
20
  #include "curb_postfield.h"
@@ -64,7 +68,7 @@ rb_hash_clear_i(VALUE key, VALUE value, VALUE dummy) {
64
68
 
65
69
  static void curl_multi_free(ruby_curl_multi *rbcm) {
66
70
 
67
- if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH && RHASH_LEN(rbcm->requests) > 0) {
71
+ if (rbcm && !rbcm->requests == Qnil && rb_type(rbcm->requests) == T_HASH && RHASH_SIZE(rbcm->requests) > 0) {
68
72
 
69
73
  rb_hash_foreach( rbcm->requests, (int (*)())curl_multi_flush_easy, (VALUE)rbcm );
70
74
 
@@ -262,12 +266,9 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
262
266
  */
263
267
  VALUE ruby_curl_multi_remove(VALUE self, VALUE easy) {
264
268
  ruby_curl_multi *rbcm;
265
- ruby_curl_easy *rbce;
266
269
 
267
270
  Data_Get_Struct(self, ruby_curl_multi, rbcm);
268
271
 
269
- Data_Get_Struct(easy, ruby_curl_easy, rbce);
270
-
271
272
  rb_curl_multi_remove(rbcm,easy);
272
273
 
273
274
  return self;
@@ -471,7 +472,7 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
471
472
  }
472
473
  #endif
473
474
 
474
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
475
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
475
476
  struct _select_set {
476
477
  int maxfd;
477
478
  fd_set *fdread, *fdwrite, *fdexcep;
@@ -511,7 +512,7 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
511
512
  long timeout_milliseconds;
512
513
  struct timeval tv = {0, 0};
513
514
  VALUE block = Qnil;
514
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
515
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
515
516
  struct _select_set fdset_args;
516
517
  #endif
517
518
 
@@ -570,17 +571,22 @@ VALUE ruby_curl_multi_perform(int argc, VALUE *argv, VALUE self) {
570
571
  create_crt_fd(&fdexcep, &crt_fdexcep);
571
572
  #endif
572
573
 
573
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
574
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
574
575
  fdset_args.maxfd = maxfd+1;
575
576
  fdset_args.fdread = &fdread;
576
577
  fdset_args.fdwrite = &fdwrite;
577
578
  fdset_args.fdexcep = &fdexcep;
578
579
  fdset_args.tv = &tv;
580
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
581
+ rc = (int)(VALUE) rb_thread_call_without_gvl((void *(*)(void *))curb_select, &fdset_args, RUBY_UBF_IO, 0);
582
+ #elif HAVE_RB_THREAD_BLOCKING_REGION
579
583
  rc = rb_thread_blocking_region(curb_select, &fdset_args, RUBY_UBF_IO, 0);
580
584
  #else
581
585
  rc = rb_thread_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tv);
582
586
  #endif
583
587
 
588
+ #endif
589
+
584
590
  #ifdef _WIN32
585
591
  cleanup_crt_fd(&fdread, &crt_fdread);
586
592
  cleanup_crt_fd(&fdwrite, &crt_fdwrite);
@@ -80,6 +80,7 @@ have_constant "curl_version_sspi"
80
80
  have_constant "curl_version_conv"
81
81
  have_constant "curlproxy_http"
82
82
  have_constant "curlproxy_socks4"
83
+ have_constant "curlproxy_socks4a"
83
84
  have_constant "curlproxy_socks5"
84
85
  have_constant "curlauth_basic"
85
86
  have_constant "curlauth_digest"
@@ -357,6 +358,8 @@ have_constant "curlopt_gssapi_delegation"
357
358
  have_constant "curlgssapi_delegation_policy_flag"
358
359
  have_constant "curlgssapi_delegation_flag"
359
360
 
361
+ have_constant "CURLM_ADDED_ALREADY"
362
+
360
363
  if try_compile('int main() { return 0; }','-Wall')
361
364
  $CFLAGS << ' -Wall'
362
365
  end
@@ -372,23 +375,6 @@ def test_for(name, const, src)
372
375
  end
373
376
  end
374
377
  end
375
- test_for("Ruby 1.9 Hash", "RUBY19_HASH", %{
376
- #include <ruby.h>
377
- int main() {
378
- VALUE hash = rb_hash_new();
379
- if( RHASH(hash)->ntbl->num_entries ) {
380
- return 0;
381
- }
382
- return 1;
383
- }
384
- })
385
- test_for("Ruby 1.9 st.h", "RUBY19_ST_H", %{
386
- #include <ruby.h>
387
- #include <ruby/st.h>
388
- int main() {
389
- return 0;
390
- }
391
- })
392
378
 
393
379
  test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
394
380
  #include <curl/curl.h>
@@ -400,6 +386,7 @@ test_for("curl_easy_escape", "CURL_EASY_ESCAPE", %{
400
386
  })
401
387
 
402
388
  have_func('rb_thread_blocking_region')
389
+ have_header('ruby/thread.h') && have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
403
390
 
404
391
  create_header('curb_config.h')
405
392
  create_makefile('curb_core')
@@ -2,6 +2,7 @@ require 'curb_core'
2
2
  require 'curl/easy'
3
3
  require 'curl/multi'
4
4
  require 'uri'
5
+ require 'cgi'
5
6
 
6
7
  # expose shortcut methods
7
8
  module Curl
@@ -46,7 +47,7 @@ module Curl
46
47
  end
47
48
 
48
49
  def self.urlalize(url, params={})
49
- query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{URI.escape(v.to_s)}" }.join('&')
50
+ query_str = params.map {|k,v| "#{URI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
50
51
  if url.match(/\?/)
51
52
  "#{url}&#{query_str}"
52
53
  elsif query_str.size > 0
@@ -6,31 +6,41 @@ module Curl
6
6
  alias body body_str
7
7
  alias head header_str
8
8
 
9
+ class Error < Exception
10
+ attr_accessor :message, :code
11
+ def initialize(code, msg)
12
+ self.message = msg
13
+ self.code = code
14
+ end
15
+ end
16
+
9
17
  #
10
18
  # call-seq:
11
19
  # easy.status => String
12
20
  #
13
21
  def status
14
- parts = self.header_str.split(/\s/)
15
- status = []
16
- parts.shift
17
- while parts.size > 0 && parts.first != ''
18
- status << parts.shift
19
- end
20
- status.join(' ')
22
+ # Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF'
23
+ statuses = self.header_str.scan(/HTTP\/\d\.\d\s(\d+\s.+)\r\n/).map{ |match| match[0] }
24
+ statuses.last.strip
21
25
  end
22
26
 
23
27
  #
24
28
  # call-seq:
25
29
  # easy.set :sym|Fixnum, value
26
- #
30
+ #
27
31
  # set options on the curl easy handle see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
28
32
  #
29
33
  def set(opt,val)
30
34
  if opt.is_a?(Symbol)
31
- setopt(sym2curl(opt), val)
35
+ option = sym2curl(opt)
32
36
  else
33
- setopt(opt.to_i, val)
37
+ option = opt.to_i
38
+ end
39
+
40
+ begin
41
+ setopt(option, val)
42
+ rescue TypeError
43
+ raise TypeError, "Curb doesn't support setting #{opt} [##{option}] option"
34
44
  end
35
45
  end
36
46
 
@@ -58,8 +68,8 @@ module Curl
58
68
  ret = self.multi.perform
59
69
 
60
70
  if self.last_result != 0 && self.on_failure.nil?
61
- error = Curl::Easy.error(self.last_result)
62
- raise error.first
71
+ error = Curl::Easy.error(self.last_result)
72
+ raise error.first.new(error.last)
63
73
  end
64
74
 
65
75
  ret
@@ -83,54 +93,54 @@ module Curl
83
93
  # easy.perform
84
94
  #
85
95
  def delete=(onoff)
86
- set :customrequest, onoff ? 'delete' : nil
96
+ set :customrequest, onoff ? 'DELETE' : nil
87
97
  onoff
88
98
  end
89
- #
99
+ #
90
100
  # call-seq:
91
- #
101
+ #
92
102
  # easy = Curl::Easy.new("url")
93
103
  # easy.version = Curl::HTTP_1_1
94
104
  # easy.version = Curl::HTTP_1_0
95
105
  # easy.version = Curl::HTTP_NONE
96
- #
106
+ #
97
107
  def version=(http_version)
98
108
  set :http_version, http_version
99
109
  end
100
110
 
101
- #
111
+ #
102
112
  # call-seq:
103
113
  # easy.url = "http://some.url/" => "http://some.url/"
104
- #
114
+ #
105
115
  # Set the URL for subsequent calls to +perform+. It is acceptable
106
116
  # (and even recommended) to reuse Curl::Easy instances by reassigning
107
117
  # the URL between calls to +perform+.
108
- #
118
+ #
109
119
  def url=(u)
110
120
  set :url, u
111
121
  end
112
122
 
113
- #
123
+ #
114
124
  # call-seq:
115
125
  # easy.proxy_url = string => string
116
- #
126
+ #
117
127
  # Set the URL of the HTTP proxy to use for subsequent calls to +perform+.
118
128
  # The URL should specify the the host name or dotted IP address. To specify
119
129
  # port number in this string, append :[port] to the end of the host name.
120
130
  # The proxy string may be prefixed with [protocol]:// since any such prefix
121
131
  # will be ignored. The proxy's port number may optionally be specified with
122
132
  # the separate option proxy_port .
123
- #
133
+ #
124
134
  # When you tell the library to use an HTTP proxy, libcurl will transparently
125
135
  # convert operations to HTTP even if you specify an FTP URL etc. This may have
126
136
  # an impact on what other features of the library you can use, such as
127
137
  # FTP specifics that don't work unless you tunnel through the HTTP proxy. Such
128
138
  # tunneling is activated with proxy_tunnel = true.
129
- #
139
+ #
130
140
  # libcurl respects the environment variables *http_proxy*, *ftp_proxy*,
131
141
  # *all_proxy* etc, if any of those is set. The proxy_url option does however
132
142
  # override any possibly set environment variables.
133
- #
143
+ #
134
144
  # Starting with libcurl 7.14.1, the proxy host string given in environment
135
145
  # variables can be specified the exact same way as the proxy can be set with
136
146
  # proxy_url, including protocol prefix (http://) and embedded user + password.
@@ -145,89 +155,89 @@ module Curl
145
155
  self.ssl_verify_host_integer=value
146
156
  end
147
157
 
148
- #
158
+ #
149
159
  # call-seq:
150
160
  # easy.ssl_verify_host? => boolean
151
- #
161
+ #
152
162
  # Deprecated: call easy.ssl_verify_host instead
153
163
  # can be one of [0,1,2]
154
- #
164
+ #
155
165
  # Determine whether this Curl instance will verify that the server cert
156
166
  # is for the server it is known as.
157
- #
167
+ #
158
168
  def ssl_verify_host?
159
169
  ssl_verify_host.nil? ? false : (ssl_verify_host > 0)
160
170
  end
161
171
 
162
- #
172
+ #
163
173
  # call-seq:
164
174
  # easy.interface = string => string
165
- #
175
+ #
166
176
  # Set the interface name to use as the outgoing network interface.
167
177
  # The name can be an interface name, an IP address or a host name.
168
- #
178
+ #
169
179
  def interface=(value)
170
180
  set :interface, value
171
181
  end
172
182
 
173
- #
183
+ #
174
184
  # call-seq:
175
185
  # easy.userpwd = string => string
176
- #
186
+ #
177
187
  # Set the username/password string to use for subsequent calls to +perform+.
178
188
  # The supplied string should have the form "username:password"
179
- #
189
+ #
180
190
  def userpwd=(value)
181
191
  set :userpwd, value
182
192
  end
183
193
 
184
- #
194
+ #
185
195
  # call-seq:
186
196
  # easy.proxypwd = string => string
187
- #
197
+ #
188
198
  # Set the username/password string to use for proxy connection during
189
199
  # subsequent calls to +perform+. The supplied string should have the
190
200
  # form "username:password"
191
- #
201
+ #
192
202
  def proxypwd=(value)
193
203
  set :proxyuserpwd, value
194
204
  end
195
205
 
196
- #
206
+ #
197
207
  # call-seq:
198
208
  # easy.cookies = "name1=content1; name2=content2;" => string
199
- #
209
+ #
200
210
  # Set cookies to be sent by this Curl::Easy instance. The format of the string should
201
211
  # be NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie should contain.
202
212
  # Set multiple cookies in one string like this: "name1=content1; name2=content2;" etc.
203
- #
213
+ #
204
214
  def cookies=(value)
205
215
  set :cookie, value
206
216
  end
207
217
 
208
- #
218
+ #
209
219
  # call-seq:
210
220
  # easy.cookiefile = string => string
211
- #
221
+ #
212
222
  # Set a file that contains cookies to be sent in subsequent requests by this Curl::Easy instance.
213
- #
223
+ #
214
224
  # *Note* that you must set enable_cookies true to enable the cookie
215
225
  # engine, or this option will be ignored.
216
- #
226
+ #
217
227
  def cookiefile=(value)
218
228
  set :cookiefile, value
219
229
  end
220
230
 
221
- #
231
+ #
222
232
  # call-seq:
223
233
  # easy.cookiejar = string => string
224
- #
234
+ #
225
235
  # Set a cookiejar file to use for this Curl::Easy instance.
226
236
  # Cookies from the response will be written into this file.
227
- #
237
+ #
228
238
  # *Note* that you must set enable_cookies true to enable the cookie
229
239
  # engine, or this option will be ignored.
230
- #
240
+ #
231
241
  def cookiejar=(value)
232
242
  set :cookiejar, value
233
243
  end
@@ -405,35 +415,35 @@ module Curl
405
415
  c.http_delete
406
416
  c
407
417
  end
408
-
418
+
409
419
  # call-seq:
410
420
  # Curl::Easy.download(url, filename = url.split(/\?/).first.split(/\//).last) { |curl| ... }
411
- #
421
+ #
412
422
  # Stream the specified url (via perform) and save the data directly to the
413
- # supplied filename (defaults to the last component of the URL path, which will
423
+ # supplied filename (defaults to the last component of the URL path, which will
414
424
  # usually be the filename most simple urls).
415
- #
425
+ #
416
426
  # If a block is supplied, it will be passed the curl instance prior to the
417
427
  # perform call.
418
- #
428
+ #
419
429
  # *Note* that the semantics of the on_body handler are subtly changed when using
420
- # download, to account for the automatic routing of data to the specified file: The
430
+ # download, to account for the automatic routing of data to the specified file: The
421
431
  # data string is passed to the handler *before* it is written
422
- # to the file, allowing the handler to perform mutative operations where
432
+ # to the file, allowing the handler to perform mutative operations where
423
433
  # necessary. As usual, the transfer will be aborted if the on_body handler
424
- # returns a size that differs from the data chunk size - in this case, the
434
+ # returns a size that differs from the data chunk size - in this case, the
425
435
  # offending chunk will *not* be written to the file, the file will be closed,
426
436
  # and a Curl::Err::AbortedByCallbackError will be raised.
427
437
  def download(url, filename = url.split(/\?/).first.split(/\//).last, &blk)
428
438
  curl = Curl::Easy.new(url, &blk)
429
-
439
+
430
440
  output = if filename.is_a? IO
431
441
  filename.binmode if filename.respond_to?(:binmode)
432
442
  filename
433
443
  else
434
444
  File.open(filename, 'wb')
435
445
  end
436
-
446
+
437
447
  begin
438
448
  old_on_body = curl.on_body do |data|
439
449
  result = old_on_body ? old_on_body.call(data) : data.length
@@ -444,7 +454,7 @@ module Curl
444
454
  ensure
445
455
  output.close rescue IOError
446
456
  end
447
-
457
+
448
458
  return curl
449
459
  end
450
460
  end