atom-tools 2.0.1 → 2.0.2
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.
- 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
|