atom-tools 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/bin/atom-grep +0 -0
- data/bin/atom-post +0 -0
- data/lib/atom/element.rb +4 -1
- data/lib/atom/http.rb +90 -3
- data/test/runtests.rb +0 -0
- data/test/test_general.rb +0 -0
- data/test/test_http.rb +3 -26
- data/test/test_protocol.rb +20 -0
- data/test/test_xml.rb +0 -0
- metadata +3 -4
- data/bin/atom-show +0 -70
data/Rakefile
CHANGED
data/bin/atom-grep
CHANGED
File without changes
|
data/bin/atom-post
CHANGED
File without changes
|
data/lib/atom/element.rb
CHANGED
@@ -288,7 +288,10 @@ module Atom # :nodoc:
|
|
288
288
|
|
289
289
|
self.on_build do |e,x|
|
290
290
|
if v = e.get(name)
|
291
|
-
|
291
|
+
unless x.namespaces[ns[0]]
|
292
|
+
x.add_namespace *ns
|
293
|
+
end
|
294
|
+
x.attributes["#{ns[0]}:#{name}"] = v.to_s
|
292
295
|
end
|
293
296
|
end
|
294
297
|
end
|
data/lib/atom/http.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "net/http"
|
2
2
|
require "net/https"
|
3
3
|
require "uri"
|
4
|
+
require "cgi"
|
4
5
|
|
5
6
|
require "atom/cache"
|
6
7
|
|
@@ -16,7 +17,8 @@ class String # :nodoc:
|
|
16
17
|
end
|
17
18
|
|
18
19
|
module Atom
|
19
|
-
|
20
|
+
TOOLS_VERSION = '2.0.2'
|
21
|
+
UA = "atom-tools " + TOOLS_VERSION
|
20
22
|
|
21
23
|
module DigestAuth
|
22
24
|
CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
@@ -130,6 +132,8 @@ module Atom
|
|
130
132
|
#
|
131
133
|
# defaults to nil
|
132
134
|
attr_accessor :always_auth
|
135
|
+
# if this is true, we tell Net::HTTP to die if it can't verify the SSL when doing https
|
136
|
+
attr_accessor :strict_ssl
|
133
137
|
|
134
138
|
# automatically handle redirects, even for POST/PUT/DELETE requests?
|
135
139
|
#
|
@@ -254,10 +258,90 @@ module Atom
|
|
254
258
|
req["Authorization"] = 'WSSE profile="UsernameToken"'
|
255
259
|
end
|
256
260
|
|
257
|
-
def authsub_authenticate req, url
|
261
|
+
def authsub_authenticate req, url, param_string = ""
|
258
262
|
req["Authorization"] = %{AuthSub token="#{@token}"}
|
259
263
|
end
|
260
264
|
|
265
|
+
# GoogleLogin support thanks to Adrian Hosey
|
266
|
+
def googlelogin_authenticate(req, url, param_string)
|
267
|
+
params_h = Hash.new
|
268
|
+
param_string.split(',').each do |p|
|
269
|
+
k, v = p.split('=')
|
270
|
+
# No whitespace in the key
|
271
|
+
k.delete!(' ')
|
272
|
+
# Values come wrapped in doublequotes - remove
|
273
|
+
v.gsub!(/^"|"$/, '')
|
274
|
+
params_h[k] = v
|
275
|
+
end
|
276
|
+
|
277
|
+
abs_url = (url + "/").to_s
|
278
|
+
user, pass = @get_auth_details.call(abs_url, params_h["realm"])
|
279
|
+
token = fetch_googlelogin_token(user, pass, params_h["realm"], params_h["service"])
|
280
|
+
if !token.nil?
|
281
|
+
req["Authorization"] = "GoogleLogin auth=#{token}"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def fetch_googlelogin_token(user, pass, url_s, service)
|
286
|
+
req, url = new_request(url_s, Net::HTTP::Post)
|
287
|
+
http_obj = Net::HTTP.new(url.host, url.port)
|
288
|
+
if url.scheme == "https"
|
289
|
+
http_obj.use_ssl = true
|
290
|
+
probe_for_cafile(http_obj)
|
291
|
+
end
|
292
|
+
|
293
|
+
body = "Email=#{CGI.escape(user)}&Passwd=#{CGI.escape(pass)}&service=#{CGI.escape(service)}"
|
294
|
+
body += "&accountType=GOOGLE&source=ruby-atom-tools-#{CGI.escape(TOOLS_VERSION)}"
|
295
|
+
res = http_obj.start do |h|
|
296
|
+
h.request(req, body)
|
297
|
+
end
|
298
|
+
|
299
|
+
retval = nil
|
300
|
+
case res
|
301
|
+
when Net::HTTPUnauthorized
|
302
|
+
raise Unauthorized, "Your authorization was rejected"
|
303
|
+
when Net::HTTPOK, Net::HTTPNonAuthoritativeInformation
|
304
|
+
res.body.each_line do |l|
|
305
|
+
k, v = l.split('=')
|
306
|
+
if k == "Auth"
|
307
|
+
retval = v.chomp
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
retval
|
313
|
+
end
|
314
|
+
|
315
|
+
# Look for a root CA file and set the relevant options on the passed-in Net::HTTP object.
|
316
|
+
def probe_for_cafile(http_obj)
|
317
|
+
ca_possibles = [
|
318
|
+
'/usr/share/curl/curl-ca-bundle.crt', # OS X
|
319
|
+
'/etc/pki/tls/certs/ca-bundle.crt', # newer Redhat
|
320
|
+
'/usr/share/ssl/certs/ca-bundle.crt', # older Redhat
|
321
|
+
'/etc/ssl/certs/ca-certificates.crt', # Ubuntu (I think)
|
322
|
+
# <irony>Dear LSB: Thank you for standardizing Linux</irony>
|
323
|
+
]
|
324
|
+
cafile = nil
|
325
|
+
ca_possibles.each do |ca|
|
326
|
+
if File.exist? ca
|
327
|
+
cafile = ca
|
328
|
+
break
|
329
|
+
end
|
330
|
+
end
|
331
|
+
if cafile.nil?
|
332
|
+
if @strict_ssl
|
333
|
+
# set this knowing it will die, since we didn't find a good cafile
|
334
|
+
http_obj.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
335
|
+
else
|
336
|
+
http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
337
|
+
end
|
338
|
+
else
|
339
|
+
http_obj.ca_file = cafile
|
340
|
+
http_obj.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
341
|
+
http_obj.verify_depth = 5
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
261
345
|
def username_and_password_for_realm(url, realm)
|
262
346
|
abs_url = (url + "/").to_s
|
263
347
|
user, pass = @get_auth_details.call(abs_url, realm)
|
@@ -313,7 +397,10 @@ module Atom
|
|
313
397
|
end
|
314
398
|
|
315
399
|
http_obj = Net::HTTP.new(url.host, url.port)
|
316
|
-
|
400
|
+
if url.scheme == "https"
|
401
|
+
http_obj.use_ssl = true
|
402
|
+
probe_for_cafile(http_obj)
|
403
|
+
end
|
317
404
|
|
318
405
|
res = http_obj.start do |h|
|
319
406
|
h.request(req, body)
|
data/test/runtests.rb
CHANGED
File without changes
|
data/test/test_general.rb
CHANGED
File without changes
|
data/test/test_http.rb
CHANGED
@@ -24,7 +24,7 @@ class AtomHTTPTest < Test::Unit::TestCase
|
|
24
24
|
def test_parse_wwwauth
|
25
25
|
# a Basic WWW-Authenticate
|
26
26
|
header = 'realm="SokEvo"'
|
27
|
-
|
27
|
+
|
28
28
|
params = @http.send :parse_quoted_wwwauth, header
|
29
29
|
assert_equal "SokEvo", params[:realm]
|
30
30
|
|
@@ -272,29 +272,6 @@ class AtomHTTPTest < Test::Unit::TestCase
|
|
272
272
|
assert_authenticates
|
273
273
|
end
|
274
274
|
|
275
|
-
def test_https
|
276
|
-
require 'webrick/https'
|
277
|
-
|
278
|
-
@s = WEBrick::HTTPServer.new(
|
279
|
-
:Port => (@port + 1),
|
280
|
-
:DocumentRoot => Dir::pwd + "/htdocs",
|
281
|
-
:Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL),
|
282
|
-
:AccessLog => [],
|
283
|
-
:SSLEnable => true,
|
284
|
-
:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
|
285
|
-
:SSLCertName => [ ["C","CA"], ["O","localhost"], ["CN", "WWW"] ]
|
286
|
-
)
|
287
|
-
|
288
|
-
mount_one_shot do |req,res|
|
289
|
-
res.body = SECRET_DATA
|
290
|
-
end
|
291
|
-
|
292
|
-
res = @http.get("https://localhost:#{@port + 1}/")
|
293
|
-
|
294
|
-
assert_equal "200", res.code
|
295
|
-
assert_equal SECRET_DATA, res.body
|
296
|
-
end
|
297
|
-
|
298
275
|
# mount a block on the test server, shutting the server down after a
|
299
276
|
# single request
|
300
277
|
def mount_one_shot &block
|
@@ -309,8 +286,8 @@ class AtomHTTPTest < Test::Unit::TestCase
|
|
309
286
|
# test that we authenticated properly
|
310
287
|
def assert_authenticates
|
311
288
|
get_root
|
312
|
-
assert_equal "200", @res.code
|
313
|
-
assert_equal SECRET_DATA, @res.body
|
289
|
+
assert_equal "200", @res.code
|
290
|
+
assert_equal SECRET_DATA, @res.body
|
314
291
|
end
|
315
292
|
|
316
293
|
# performs a GET on the test server
|
data/test/test_protocol.rb
CHANGED
@@ -2,6 +2,9 @@ require "test/unit"
|
|
2
2
|
|
3
3
|
require "atom/service"
|
4
4
|
|
5
|
+
# needed for hpricot
|
6
|
+
require "rubygems"
|
7
|
+
|
5
8
|
class FakeHTTP
|
6
9
|
Response = Struct.new(:body, :code, :content_type)
|
7
10
|
|
@@ -25,6 +28,17 @@ class FakeHTTP
|
|
25
28
|
end
|
26
29
|
|
27
30
|
class AtomProtocolTest < Test::Unit::TestCase
|
31
|
+
attr_reader :have_hpricot
|
32
|
+
|
33
|
+
def initialize *args
|
34
|
+
super
|
35
|
+
|
36
|
+
require "hpricot"
|
37
|
+
@have_hpricot = true
|
38
|
+
rescue LoadError
|
39
|
+
puts "skipping hpricot tests"
|
40
|
+
end
|
41
|
+
|
28
42
|
def test_introspection
|
29
43
|
doc = <<END
|
30
44
|
<service xmlns="http://www.w3.org/2007/app"
|
@@ -123,6 +137,8 @@ END
|
|
123
137
|
end
|
124
138
|
|
125
139
|
def test_autodiscover_service_link
|
140
|
+
return unless have_hpricot
|
141
|
+
|
126
142
|
http = FakeHTTP.new \
|
127
143
|
'http://example.org/' => [ 'text/html', '<html><link rel="service" href="svc">' ],
|
128
144
|
'http://example.org/xhtml' => [ 'text/html', '<html><head><link rel="service" href="svc"/></head></html>' ],
|
@@ -136,6 +152,8 @@ END
|
|
136
152
|
end
|
137
153
|
|
138
154
|
def test_autodiscover_rsd
|
155
|
+
return unless have_hpricot
|
156
|
+
|
139
157
|
http = FakeHTTP.new \
|
140
158
|
'http://example.org/' => [ 'text/html', '<html><link rel="EditURI" href="rsd">' ],
|
141
159
|
'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ],
|
@@ -154,6 +172,8 @@ END
|
|
154
172
|
end
|
155
173
|
|
156
174
|
def test_cant_autodiscover
|
175
|
+
return unless have_hpricot
|
176
|
+
|
157
177
|
http = FakeHTTP.new 'http://example.org/h' => [ 'text/html', '<html>' ],
|
158
178
|
'http://example.org/t' => [ 'text/plain', 'no joy.' ]
|
159
179
|
|
data/test/test_xml.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atom-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brendan Taylor
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-05-01 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -28,7 +28,6 @@ files:
|
|
28
28
|
- setup.rb
|
29
29
|
- bin/atom-grep
|
30
30
|
- bin/atom-post
|
31
|
-
- bin/atom-show
|
32
31
|
- bin/atom-purge
|
33
32
|
- bin/atom-cp
|
34
33
|
- test/test_constructs.rb
|
@@ -76,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
75
|
requirements: []
|
77
76
|
|
78
77
|
rubyforge_project: ibes
|
79
|
-
rubygems_version: 1.
|
78
|
+
rubygems_version: 1.3.1
|
80
79
|
signing_key:
|
81
80
|
specification_version: 2
|
82
81
|
summary: Tools for working with Atom Entries, Feeds and Collections
|
data/bin/atom-show
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
3
|
-
=begin
|
4
|
-
Usage: atom-show [options] source
|
5
|
-
displays a feed human-readably
|
6
|
-
|
7
|
-
'source' can be a path on the local filesystem, the
|
8
|
-
URL of an Atom Collection or '-' for stdin.
|
9
|
-
=end
|
10
|
-
|
11
|
-
require 'atom/tools'
|
12
|
-
include Atom::Tools
|
13
|
-
|
14
|
-
def parse_options
|
15
|
-
options = { }
|
16
|
-
|
17
|
-
opts = OptionParser.new do |opts|
|
18
|
-
opts.banner = <<END
|
19
|
-
Usage: #{$0} [options] [source]
|
20
|
-
displays a feed human-readably
|
21
|
-
|
22
|
-
'source' can be a path on the local filesystem, the
|
23
|
-
URL of an Atom Collection or '-' for stdin.
|
24
|
-
END
|
25
|
-
|
26
|
-
opts.on('-c', '--complete', "Follow previous and next links in the source feed to obtain the entire logical feed") do
|
27
|
-
options[:complete] = true
|
28
|
-
end
|
29
|
-
|
30
|
-
opts.on('-n', '--content [MAX-LENGTH]', "Display max-length words of each entry's content") do |length|
|
31
|
-
options[:content] = length ? length.to_i : 0
|
32
|
-
end
|
33
|
-
|
34
|
-
atom_options opts, options
|
35
|
-
end
|
36
|
-
|
37
|
-
opts.parse!(ARGV)
|
38
|
-
|
39
|
-
if ARGV.length > 1
|
40
|
-
puts opts
|
41
|
-
exit
|
42
|
-
end
|
43
|
-
|
44
|
-
options
|
45
|
-
end
|
46
|
-
|
47
|
-
if __FILE__ == $0
|
48
|
-
require 'optparse'
|
49
|
-
|
50
|
-
options = parse_options
|
51
|
-
|
52
|
-
source = ARGV[0]
|
53
|
-
source ||= '-'
|
54
|
-
|
55
|
-
entries = parse_input source, options
|
56
|
-
|
57
|
-
entries.each do |e|
|
58
|
-
puts e.title
|
59
|
-
|
60
|
-
if options[:content]
|
61
|
-
if options[:content].zero?
|
62
|
-
puts e.content.to_s
|
63
|
-
else
|
64
|
-
puts e.content.to_s.split(' ')[0,options[:content]].join(' ')
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
puts
|
69
|
-
end
|
70
|
-
end
|