mechanize 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mechanize might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +16 -0
- data/CHANGELOG.rdoc +14 -0
- data/Manifest.txt +1 -0
- data/README.rdoc +7 -6
- data/Rakefile +3 -0
- data/lib/mechanize.rb +1 -1
- data/lib/mechanize/cookie.rb +51 -222
- data/lib/mechanize/cookie_jar.rb +123 -191
- data/lib/mechanize/download.rb +10 -2
- data/lib/mechanize/file.rb +1 -7
- data/lib/mechanize/form.rb +15 -0
- data/lib/mechanize/form/field.rb +12 -0
- data/lib/mechanize/http/agent.rb +28 -15
- data/lib/mechanize/page/image.rb +3 -3
- data/lib/mechanize/prependable.rb +89 -0
- data/lib/mechanize/test_case.rb +3 -5
- data/test/test_mechanize.rb +5 -9
- data/test/test_mechanize_cookie.rb +4 -4
- data/test/test_mechanize_cookie_jar.rb +5 -5
- data/test/test_mechanize_download.rb +1 -1
- data/test/test_mechanize_form.rb +31 -3
- data/test/test_mechanize_http_agent.rb +38 -24
- data/test/test_mechanize_page_image.rb +1 -0
- data/test/test_mechanize_xml_file.rb +1 -1
- metadata +23 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 697096d6b8d2bd29662a4a9e2241b5bc22ccb70d
|
4
|
+
data.tar.gz: 1a4348dbc2f838ee019917249e7f0c4348035a9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a9802905e414093174c09110703e042cde32de5abfde18c8f7bd1d02b6f414dda4dfb897792a7e7201fa3ed52923fdbeb777059ca6075d7c9bb0469cad96cbb
|
7
|
+
data.tar.gz: 5f93e7092082c7cd7c33701e566f621299f4604360e85a61e9f900cb9f81a8971ebf2a2e21cdeeb9e00f9bf582b7bc8db7252fe4dea180e6ace8dc04523f466f
|
data/.travis.yml
CHANGED
@@ -9,8 +9,24 @@ notifications:
|
|
9
9
|
email:
|
10
10
|
- drbrain@segment7.net
|
11
11
|
- ljjarvis@gmail.com
|
12
|
+
- knu@idaemons.org
|
12
13
|
rvm:
|
13
14
|
- 1.8.7
|
14
15
|
- 1.9.2
|
15
16
|
- 1.9.3
|
17
|
+
- 2.0.0
|
18
|
+
- ruby-head
|
19
|
+
- jruby-18mode
|
20
|
+
- jruby-19mode
|
21
|
+
- jruby-head
|
22
|
+
- rbx-18mode
|
23
|
+
- rbx-19mode
|
16
24
|
script: rake travis
|
25
|
+
matrix:
|
26
|
+
allow_failures:
|
27
|
+
- rvm: ruby-head
|
28
|
+
- rvm: jruby-18mode
|
29
|
+
- rvm: jruby-19mode
|
30
|
+
- rvm: jruby-head
|
31
|
+
- rvm: rbx-18mode
|
32
|
+
- rvm: rbx-19mode
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
= Mechanize CHANGELOG
|
2
2
|
|
3
|
+
=== 2.7.0
|
4
|
+
|
5
|
+
* New Features
|
6
|
+
* Mechanize::Agent#response_read will now raise a
|
7
|
+
Mechanize::ResponseReadError instead of an EOFError and avoid losing
|
8
|
+
requested content. #296.
|
9
|
+
* Depend on http-cookie, add backwards compatible deprecations.
|
10
|
+
#257 Akinori MUSHA.
|
11
|
+
* Added `Download#save!` for overwriting existing files. #300 Sean Kim.
|
12
|
+
|
13
|
+
* Bug fix
|
14
|
+
* Ensure page URLs with whitespace in them are escaped #313 @pacop.
|
15
|
+
* Added a workaround for a bug of URI#+ that led to failure in resolving a relative path containing double slash like "/../http://.../". #304
|
16
|
+
|
3
17
|
=== 2.6.0
|
4
18
|
|
5
19
|
* New Features
|
data/Manifest.txt
CHANGED
@@ -62,6 +62,7 @@ lib/mechanize/page/link.rb
|
|
62
62
|
lib/mechanize/page/meta_refresh.rb
|
63
63
|
lib/mechanize/parser.rb
|
64
64
|
lib/mechanize/pluggable_parsers.rb
|
65
|
+
lib/mechanize/prependable.rb
|
65
66
|
lib/mechanize/redirect_limit_reached_error.rb
|
66
67
|
lib/mechanize/redirect_not_get_or_head_error.rb
|
67
68
|
lib/mechanize/response_code_error.rb
|
data/README.rdoc
CHANGED
@@ -13,7 +13,7 @@ a history.
|
|
13
13
|
|
14
14
|
== Dependencies
|
15
15
|
|
16
|
-
* ruby 1.8.7, 1.9.2,
|
16
|
+
* ruby 1.8.7, 1.9.2, 1.9.3, or 2.0.0
|
17
17
|
* nokogiri[http://nokogiri.rubyforge.org]
|
18
18
|
|
19
19
|
== Support:
|
@@ -28,7 +28,7 @@ The bug tracker is available here:
|
|
28
28
|
|
29
29
|
== Examples
|
30
30
|
|
31
|
-
If you are just starting, check out the GUIDE. Also, check out the EXAMPLES
|
31
|
+
If you are just starting, check out the GUIDE[http://mechanize.rubyforge.org/GUIDE_rdoc.html]. Also, check out the EXAMPLES[http://mechanize.rubyforge.org/EXAMPLES_rdoc.html]
|
32
32
|
file.
|
33
33
|
|
34
34
|
== Developers
|
@@ -67,9 +67,10 @@ This library comes with a shameless plug for employing me
|
|
67
67
|
|
68
68
|
== Acknowledgments
|
69
69
|
|
70
|
-
This library was heavily influenced by its namesake in the
|
71
|
-
thanks goes to Andy Lester
|
72
|
-
|
70
|
+
This library was heavily influenced by its namesake in the Perl world. A big
|
71
|
+
thanks goes to {Andy Lester}[http://petdance.com],
|
72
|
+
the author of the original Perl module WWW::Mechanize which is available
|
73
|
+
here[http://search.cpan.org/dist/WWW-Mechanize/]. Ruby Mechanize would not be around without you!
|
73
74
|
|
74
75
|
Thank you to Michael Neumann for starting the Ruby version. Thanks to everyone
|
75
76
|
who's helped out in various ways. Finally, thank you to the people using this
|
@@ -77,5 +78,5 @@ library!
|
|
77
78
|
|
78
79
|
== License
|
79
80
|
|
80
|
-
This library is distributed under the MIT license. Please see the LICENSE file.
|
81
|
+
This library is distributed under the MIT license. Please see the LICENSE[http://mechanize.rubyforge.org/LICENSE_rdoc.html] file.
|
81
82
|
|
data/Rakefile
CHANGED
@@ -21,11 +21,14 @@ hoe = Hoe.spec 'mechanize' do
|
|
21
21
|
self.extra_deps << ['net-http-digest_auth', '~> 1.1', '>= 1.1.1']
|
22
22
|
self.extra_deps << ['net-http-persistent', '~> 2.5', '>= 2.5.2']
|
23
23
|
self.extra_deps << ['mime-types', '~> 1.17', '>= 1.17.2']
|
24
|
+
self.extra_deps << ['http-cookie', '~> 1.0.0']
|
24
25
|
self.extra_deps << ['nokogiri', '~> 1.4']
|
25
26
|
self.extra_deps << ['ntlm-http', '~> 0.1', '>= 0.1.1']
|
26
27
|
self.extra_deps << ['webrobots', '< 0.2', '>= 0.0.9']
|
27
28
|
self.extra_deps << ['domain_name', '~> 0.5', '>= 0.5.1']
|
28
29
|
|
30
|
+
self.extra_dev_deps << ['minitest', '~> 5.0']
|
31
|
+
|
29
32
|
self.spec_extras[:required_ruby_version] = '>= 1.8.7'
|
30
33
|
end
|
31
34
|
|
data/lib/mechanize.rb
CHANGED
data/lib/mechanize/cookie.rb
CHANGED
@@ -1,244 +1,73 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# :call-seq:
|
19
|
-
# new(name, value)
|
20
|
-
# new(name, value, attr_hash)
|
21
|
-
# new(attr_hash)
|
22
|
-
#
|
23
|
-
# Creates a cookie object. For each key of +attr_hash+, the setter
|
24
|
-
# is called if defined. Each key can be either a symbol or a
|
25
|
-
# string, downcased or not.
|
26
|
-
#
|
27
|
-
# e.g.
|
28
|
-
# new("uid", "a12345")
|
29
|
-
# new("uid", "a12345", :domain => 'example.org',
|
30
|
-
# :for_domain => true, :expired => Time.now + 7*86400)
|
31
|
-
# new("name" => "uid", "value" => "a12345", "Domain" => 'www.example.org')
|
32
|
-
#
|
33
|
-
def initialize(*args)
|
34
|
-
@version = 0 # Netscape Cookie
|
35
|
-
|
36
|
-
@domain = @path = @secure = @comment = @max_age =
|
37
|
-
@expires = @comment_url = @discard = @port = @httponly = nil
|
38
|
-
|
39
|
-
@created_at = @accessed_at = Time.now
|
40
|
-
case args.size
|
41
|
-
when 2
|
42
|
-
@name, @value = *args
|
43
|
-
@for_domain = false
|
44
|
-
return
|
45
|
-
when 3
|
46
|
-
@name, @value, attr_hash = *args
|
47
|
-
when 1
|
48
|
-
attr_hash = args.first
|
49
|
-
else
|
50
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for 1-3)"
|
51
|
-
end
|
52
|
-
for_domain = false
|
53
|
-
attr_hash.each_pair { |key, val|
|
54
|
-
skey = key.to_s.downcase
|
55
|
-
skey.sub!(/[!?]\z/, '')
|
56
|
-
case skey
|
57
|
-
when 'for_domain'
|
58
|
-
for_domain = !!val
|
59
|
-
when 'name'
|
60
|
-
@name = val
|
61
|
-
when 'value'
|
62
|
-
@value = val
|
1
|
+
warn 'mechanize/cookie will be deprecated. Please migrate to the http-cookie APIs.' if $VERBOSE
|
2
|
+
|
3
|
+
require 'http/cookie'
|
4
|
+
|
5
|
+
class Mechanize
|
6
|
+
module CookieDeprecated
|
7
|
+
def __deprecated__(to = nil)
|
8
|
+
$VERBOSE or return
|
9
|
+
method = caller[0][/([^`]+)(?='$)/]
|
10
|
+
to ||= method
|
11
|
+
case self
|
12
|
+
when Class
|
13
|
+
lname = name[/[^:]+$/]
|
14
|
+
klass = 'Mechanize::%s' % lname
|
15
|
+
this = '%s.%s' % [klass, method]
|
16
|
+
that = 'HTTP::%s.%s' % [lname, to]
|
63
17
|
else
|
64
|
-
|
65
|
-
|
18
|
+
lname = self.class.name[/[^:]+$/]
|
19
|
+
klass = 'Mechanize::%s' % lname
|
20
|
+
this = '%s#%s' % [klass, method]
|
21
|
+
that = 'HTTP::%s#%s' % [lname, to]
|
66
22
|
end
|
67
|
-
|
68
|
-
@for_domain = for_domain
|
69
|
-
end
|
70
|
-
|
71
|
-
# If this flag is true, this cookie will be sent to any host in the
|
72
|
-
# +domain+. If it is false, this cookie will be sent only to the
|
73
|
-
# host indicated by the +domain+.
|
74
|
-
attr_accessor :for_domain
|
75
|
-
alias for_domain? for_domain
|
76
|
-
|
77
|
-
class << self
|
78
|
-
# Parses a Set-Cookie header line +str+ sent from +uri+ into an
|
79
|
-
# array of Cookie objects. Note that this array may contain
|
80
|
-
# nil's when some of the cookie-pairs are malformed.
|
81
|
-
def parse(uri, str, log = Mechanize.log)
|
82
|
-
return str.to_s.split(/,(?=[^;,]*=)|,$/).map { |c|
|
83
|
-
cookie_elem = c.split(/;+/)
|
84
|
-
first_elem = cookie_elem.shift
|
85
|
-
first_elem.strip!
|
86
|
-
key, value = first_elem.split(/\=/, 2)
|
87
|
-
|
88
|
-
begin
|
89
|
-
cookie = new(key, value.dup)
|
90
|
-
rescue
|
91
|
-
log.warn("Couldn't parse key/value: #{first_elem}") if log
|
92
|
-
next
|
93
|
-
end
|
94
|
-
|
95
|
-
cookie_elem.each do |pair|
|
96
|
-
pair.strip!
|
97
|
-
key, value = pair.split(/=/, 2)
|
98
|
-
next unless key
|
99
|
-
value = WEBrick::HTTPUtils.dequote(value.strip) if value
|
100
|
-
|
101
|
-
|
102
|
-
case key.downcase
|
103
|
-
when 'domain'
|
104
|
-
next unless value && !value.empty?
|
105
|
-
begin
|
106
|
-
cookie.domain = value
|
107
|
-
cookie.for_domain = true
|
108
|
-
rescue
|
109
|
-
log.warn("Couldn't parse domain: #{value}") if log
|
110
|
-
end
|
111
|
-
when 'path'
|
112
|
-
next unless value && !value.empty?
|
113
|
-
cookie.path = value
|
114
|
-
when 'expires'
|
115
|
-
next unless value && !value.empty?
|
116
|
-
begin
|
117
|
-
cookie.expires = Time::parse(value)
|
118
|
-
rescue
|
119
|
-
log.warn("Couldn't parse expires: #{value}") if log
|
120
|
-
end
|
121
|
-
when 'max-age'
|
122
|
-
next unless value && !value.empty?
|
123
|
-
begin
|
124
|
-
cookie.max_age = Integer(value)
|
125
|
-
rescue
|
126
|
-
log.warn("Couldn't parse max age '#{value}'") if log
|
127
|
-
end
|
128
|
-
when 'comment'
|
129
|
-
next unless value
|
130
|
-
cookie.comment = value
|
131
|
-
when 'version'
|
132
|
-
next unless value
|
133
|
-
begin
|
134
|
-
cookie.version = Integer(value)
|
135
|
-
rescue
|
136
|
-
log.warn("Couldn't parse version '#{value}'") if log
|
137
|
-
cookie.version = nil
|
138
|
-
end
|
139
|
-
when 'httponly'
|
140
|
-
cookie.httponly = true
|
141
|
-
when 'secure'
|
142
|
-
cookie.secure = true
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
cookie.path ||= (uri + './').path
|
147
|
-
cookie.secure ||= false
|
148
|
-
cookie.domain ||= uri.host
|
149
|
-
cookie.httponly ||= false
|
150
|
-
|
151
|
-
# RFC 6265 4.1.2.2
|
152
|
-
cookie.expires = Time.now + cookie.max_age if cookie.max_age
|
153
|
-
cookie.session = !cookie.expires
|
154
|
-
|
155
|
-
# Move this in to the cookie jar
|
156
|
-
yield cookie if block_given?
|
157
|
-
|
158
|
-
cookie
|
159
|
-
}
|
23
|
+
warn '%s: The call of %s needs to be fixed to follow the new API (%s).' % [caller[1], this, that]
|
160
24
|
end
|
25
|
+
private :__deprecated__
|
161
26
|
end
|
162
27
|
|
163
|
-
|
28
|
+
module CookieCMethods
|
29
|
+
include CookieDeprecated
|
164
30
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
(domain.respond_to?(:to_str) && (domain = domain.to_str).is_a?(String)) or
|
173
|
-
raise TypeError, "#{domain.class} is not a String"
|
174
|
-
if domain.start_with?('.')
|
175
|
-
@for_domain = true
|
176
|
-
domain = domain[1..-1]
|
177
|
-
end
|
178
|
-
# Do we really need to support this?
|
179
|
-
if domain.match(/\A([^:]+):[0-9]+\z/)
|
180
|
-
domain = $1
|
31
|
+
def parse(arg1, arg2, arg3 = nil, &block)
|
32
|
+
if arg1.is_a?(URI)
|
33
|
+
__deprecated__
|
34
|
+
return [] if arg2.nil?
|
35
|
+
super(arg2, arg1, { :logger => arg3 })
|
36
|
+
else
|
37
|
+
super
|
181
38
|
end
|
182
|
-
@domain_name = DomainName.new(domain)
|
183
39
|
end
|
184
|
-
set_domain(@domain_name.hostname)
|
185
|
-
end
|
186
|
-
|
187
|
-
def expires=(t)
|
188
|
-
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
|
189
40
|
end
|
190
41
|
|
191
|
-
|
192
|
-
|
193
|
-
end
|
42
|
+
module CookieIMethods
|
43
|
+
include CookieDeprecated
|
194
44
|
|
195
|
-
|
196
|
-
|
197
|
-
|
45
|
+
def set_domain(domain)
|
46
|
+
__deprecated__ :domain=
|
47
|
+
@domain = domain
|
48
|
+
end
|
198
49
|
end
|
199
50
|
|
200
|
-
|
201
|
-
alias httponly? httponly
|
51
|
+
Cookie = ::HTTP::Cookie
|
202
52
|
|
203
|
-
|
204
|
-
|
53
|
+
# Compatibility for Ruby 1.8/1.9
|
54
|
+
unless Cookie.respond_to?(:prepend, true)
|
55
|
+
require 'mechanize/prependable'
|
205
56
|
|
206
|
-
|
207
|
-
|
208
|
-
return host.hostname == domain unless @for_domain
|
57
|
+
class Cookie
|
58
|
+
extend Prependable
|
209
59
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
@for_domain = false
|
214
|
-
true
|
215
|
-
else
|
216
|
-
false
|
60
|
+
class << self
|
61
|
+
extend Prependable
|
62
|
+
end
|
217
63
|
end
|
218
64
|
end
|
219
65
|
|
220
|
-
|
221
|
-
|
222
|
-
acceptable_from_uri?(uri) && uri.path.start_with?(path)
|
223
|
-
end
|
224
|
-
|
225
|
-
def to_s
|
226
|
-
"#{@name}=#{@value}"
|
227
|
-
end
|
228
|
-
|
229
|
-
def init_with(coder)
|
230
|
-
yaml_initialize(coder.tag, coder.map)
|
231
|
-
end
|
66
|
+
class Cookie
|
67
|
+
prepend CookieIMethods
|
232
68
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
case key
|
237
|
-
when 'domain'
|
238
|
-
self.domain = value # ditto
|
239
|
-
else
|
240
|
-
instance_variable_set(:"@#{key}", value)
|
241
|
-
end
|
242
|
-
}
|
69
|
+
class << self
|
70
|
+
prepend CookieCMethods
|
71
|
+
end
|
243
72
|
end
|
244
73
|
end
|
data/lib/mechanize/cookie_jar.rb
CHANGED
@@ -1,220 +1,152 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# Add a +cookie+ to the jar if it is considered acceptable from
|
21
|
-
# +uri+. Return nil if the cookie was not added, otherwise return
|
22
|
-
# the cookie added.
|
23
|
-
def add(uri, cookie)
|
24
|
-
return nil unless cookie.acceptable_from_uri?(uri)
|
25
|
-
add!(cookie)
|
26
|
-
cookie
|
27
|
-
end
|
28
|
-
|
29
|
-
# Add a +cookie+ to the jar and return self.
|
30
|
-
def add!(cookie)
|
31
|
-
normal_domain = cookie.domain.downcase
|
32
|
-
|
33
|
-
@jar[normal_domain] ||= {} unless @jar.has_key?(normal_domain)
|
34
|
-
|
35
|
-
@jar[normal_domain][cookie.path] ||= {}
|
36
|
-
@jar[normal_domain][cookie.path][cookie.name] = cookie
|
37
|
-
|
38
|
-
self
|
39
|
-
end
|
40
|
-
alias << add!
|
41
|
-
|
42
|
-
# Fetch the cookies that should be used for the URI object passed in.
|
43
|
-
def cookies(url)
|
44
|
-
cleanup
|
45
|
-
url.path = '/' if url.path.empty?
|
46
|
-
now = Time.now
|
47
|
-
|
48
|
-
select { |cookie|
|
49
|
-
!cookie.expired? && cookie.valid_for_uri?(url) && (cookie.accessed_at = now)
|
50
|
-
}.sort_by { |cookie|
|
51
|
-
# RFC 6265 5.4
|
52
|
-
# Precedence: 1. longer path 2. older creation
|
53
|
-
[-cookie.path.length, cookie.created_at]
|
54
|
-
}
|
55
|
-
end
|
56
|
-
|
57
|
-
def empty?(url)
|
58
|
-
cookies(url).length > 0 ? false : true
|
59
|
-
end
|
60
|
-
|
61
|
-
def each
|
62
|
-
block_given? or return enum_for(__method__)
|
63
|
-
cleanup
|
64
|
-
@jar.each { |domain, paths|
|
65
|
-
paths.each { |path, hash|
|
66
|
-
hash.each_value { |cookie|
|
67
|
-
yield cookie
|
1
|
+
warn 'mechanize/cookie_jar will be deprecated. Please migrate to the http-cookie APIs.' if $VERBOSE
|
2
|
+
|
3
|
+
require 'http/cookie_jar'
|
4
|
+
require 'http/cookie_jar/yaml_saver'
|
5
|
+
require 'mechanize/cookie'
|
6
|
+
|
7
|
+
class Mechanize
|
8
|
+
module CookieJarIMethods
|
9
|
+
include CookieDeprecated
|
10
|
+
|
11
|
+
def add(arg1, arg2 = nil)
|
12
|
+
if arg2
|
13
|
+
__deprecated__ 'add and origin='
|
14
|
+
super arg2.dup.tap { |ncookie|
|
15
|
+
begin
|
16
|
+
ncookie.origin = arg1
|
17
|
+
rescue
|
18
|
+
return nil
|
19
|
+
end
|
68
20
|
}
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# call-seq:
|
74
|
-
# jar.save_as(file, format = :yaml)
|
75
|
-
# jar.save_as(file, options)
|
76
|
-
#
|
77
|
-
# Save the cookie jar to a file in the format specified and return
|
78
|
-
# self.
|
79
|
-
#
|
80
|
-
# Available option keywords are below:
|
81
|
-
#
|
82
|
-
# * +format+
|
83
|
-
# [<tt>:yaml</tt>]
|
84
|
-
# YAML structure (default)
|
85
|
-
# [<tt>:cookiestxt</tt>]
|
86
|
-
# Mozilla's cookies.txt format
|
87
|
-
# * +session+
|
88
|
-
# [+true+]
|
89
|
-
# Save session cookies as well.
|
90
|
-
# [+false+]
|
91
|
-
# Do not save session cookies. (default)
|
92
|
-
def save_as(file, options = nil)
|
93
|
-
if Symbol === options
|
94
|
-
format = options
|
95
|
-
session = false
|
96
|
-
else
|
97
|
-
options ||= {}
|
98
|
-
format = options[:format] || :yaml
|
99
|
-
session = !!options[:session]
|
21
|
+
else
|
22
|
+
super arg1
|
23
|
+
end
|
100
24
|
end
|
101
25
|
|
102
|
-
|
103
|
-
|
26
|
+
# See HTTP::CookieJar#add.
|
27
|
+
def add!(cookie)
|
28
|
+
__deprecated__ :add
|
29
|
+
cookie.domain.nil? and raise NoMethodError, 'raised for compatibility'
|
30
|
+
@store.add(cookie)
|
31
|
+
self
|
32
|
+
end
|
104
33
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
34
|
+
# See HTTP::CookieJar#save.
|
35
|
+
def save_as(filename, *options)
|
36
|
+
__deprecated__ :save
|
37
|
+
save(filename, *options)
|
38
|
+
end
|
109
39
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
}
|
40
|
+
# See HTTP::CookieJar#clear.
|
41
|
+
def clear!
|
42
|
+
__deprecated__ :clear
|
43
|
+
clear
|
44
|
+
end
|
117
45
|
|
118
|
-
|
46
|
+
# See HTTP::CookieJar#store.
|
47
|
+
def jar
|
48
|
+
__deprecated__ :store
|
49
|
+
@store.instance_variable_get(:@jar)
|
50
|
+
end
|
119
51
|
end
|
120
52
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
when
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
53
|
+
class CookieJar < ::HTTP::CookieJar
|
54
|
+
def save(filename, *options)
|
55
|
+
opthash = {
|
56
|
+
:format => :yaml,
|
57
|
+
:session => false,
|
58
|
+
}
|
59
|
+
case options.size
|
60
|
+
when 0
|
61
|
+
when 1
|
62
|
+
case options = options.first
|
63
|
+
when Symbol
|
64
|
+
opthash[:format] = options
|
65
|
+
else
|
66
|
+
opthash.update(options) if options
|
67
|
+
end
|
68
|
+
when 2
|
69
|
+
opthash[:format], options = options
|
70
|
+
opthash.update(options) if options
|
135
71
|
else
|
136
|
-
raise ArgumentError,
|
72
|
+
raise ArgumentError, 'wrong number of arguments (%d for 1-3)' % (1 + options.size)
|
137
73
|
end
|
138
|
-
}
|
139
74
|
|
140
|
-
|
75
|
+
return super if opthash[:format] != :yaml
|
141
76
|
|
142
|
-
|
143
|
-
|
77
|
+
session = opthash[:session]
|
78
|
+
nstore = HashStore.new
|
144
79
|
|
145
|
-
|
146
|
-
|
147
|
-
require 'psych'
|
148
|
-
rescue LoadError
|
149
|
-
end
|
80
|
+
each { |cookie|
|
81
|
+
next if !session && cookie.session?
|
150
82
|
|
151
|
-
|
152
|
-
|
83
|
+
if cookie.max_age
|
84
|
+
cookie = cookie.dup
|
85
|
+
cookie.expires = cookie.expires # convert max_age to expires
|
86
|
+
end
|
87
|
+
nstore.add(cookie)
|
88
|
+
}
|
153
89
|
|
154
|
-
|
155
|
-
def clear!
|
156
|
-
@jar = {}
|
157
|
-
end
|
90
|
+
yaml = YAML.dump(nstore.instance_variable_get(:@jar))
|
158
91
|
|
159
|
-
|
160
|
-
|
161
|
-
|
92
|
+
# a gross hack
|
93
|
+
yaml.gsub!(%r{^( [^ ].*: !ruby/object:)HTTP::Cookie$}) {
|
94
|
+
$1 + 'Mechanize::Cookie'
|
95
|
+
}
|
96
|
+
yaml.gsub!(%r{^( expires: )(?:|!!null|(.+?)) *$}) {
|
97
|
+
$1 + ($2 ? Time.parse($2).httpdate : '')
|
98
|
+
}
|
162
99
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
fields = line.split("\t")
|
100
|
+
open(filename, 'w') { |io|
|
101
|
+
io.write yaml
|
102
|
+
}
|
167
103
|
|
168
|
-
|
104
|
+
self
|
105
|
+
end
|
169
106
|
|
170
|
-
|
171
|
-
|
172
|
-
next if expires and (expires < now)
|
107
|
+
def load(filename, format = :yaml)
|
108
|
+
return super if format != :yaml
|
173
109
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
110
|
+
open(filename) { |io|
|
111
|
+
begin
|
112
|
+
data = YAML.load(io)
|
113
|
+
rescue ArgumentError
|
114
|
+
@logger.warn "unloadable YAML cookie data discarded" if @logger
|
115
|
+
return
|
116
|
+
end
|
181
117
|
|
182
|
-
|
118
|
+
case data
|
119
|
+
when Array
|
120
|
+
# Forward compatibility
|
121
|
+
data.each { |cookie|
|
122
|
+
add(cookie)
|
123
|
+
}
|
124
|
+
when Hash
|
125
|
+
data.each { |domain, paths|
|
126
|
+
paths.each { |path, names|
|
127
|
+
names.each { |cookie_name, cookie|
|
128
|
+
add(cookie)
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
else
|
133
|
+
@logger.warn "incompatible YAML cookie data discarded" if @logger
|
134
|
+
return
|
135
|
+
end
|
136
|
+
}
|
183
137
|
end
|
184
|
-
|
185
|
-
@jar
|
186
138
|
end
|
187
139
|
|
188
|
-
#
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
io.puts([
|
195
|
-
(cookie.for_domain? ? "." : "") + cookie.domain,
|
196
|
-
cookie.for_domain? ? "TRUE" : "FALSE",
|
197
|
-
cookie.path,
|
198
|
-
cookie.secure ? "TRUE" : "FALSE",
|
199
|
-
cookie.expires.to_i.to_s,
|
200
|
-
cookie.name,
|
201
|
-
cookie.value
|
202
|
-
].join("\t"))
|
140
|
+
# Compatibility for Ruby 1.8/1.9
|
141
|
+
unless ::HTTP::CookieJar.respond_to?(:prepend, true)
|
142
|
+
require 'mechanize/prependable'
|
143
|
+
|
144
|
+
class ::HTTP::CookieJar
|
145
|
+
extend Prependable
|
203
146
|
end
|
204
147
|
end
|
205
148
|
|
206
|
-
|
207
|
-
|
208
|
-
# Remove expired cookies
|
209
|
-
def cleanup session = false
|
210
|
-
@jar.each do |domain, paths|
|
211
|
-
paths.each do |path, names|
|
212
|
-
names.each do |cookie_name, cookie|
|
213
|
-
paths[path].delete(cookie_name) if
|
214
|
-
cookie.expired? or (session and cookie.session)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
149
|
+
class ::HTTP::CookieJar
|
150
|
+
prepend CookieJarIMethods
|
218
151
|
end
|
219
152
|
end
|
220
|
-
|