atom-tools 0.9.1 → 0.9.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/doc/classes/Atom/Author.html +130 -0
- data/doc/classes/Atom/Category.html +128 -0
- data/doc/classes/Atom/Collection.html +322 -0
- data/doc/classes/Atom/Content.html +129 -0
- data/doc/classes/Atom/Contributor.html +119 -0
- data/doc/classes/Atom/DigestAuth.html +285 -0
- data/doc/classes/Atom/Element.html +325 -0
- data/doc/classes/Atom/Entry.html +369 -0
- data/doc/classes/Atom/Feed.html +595 -0
- data/doc/classes/Atom/HTTP.html +436 -0
- data/doc/classes/Atom/HTTPResponse.html +149 -0
- data/doc/classes/Atom/Link.html +137 -0
- data/doc/classes/Atom/Service.html +260 -0
- data/doc/classes/Atom/Text.html +245 -0
- data/doc/classes/Atom/Workspace.html +121 -0
- data/doc/classes/XHTML.html +118 -0
- data/doc/created.rid +1 -0
- data/doc/files/README.html +213 -0
- data/doc/files/lib/atom/collection_rb.html +110 -0
- data/doc/files/lib/atom/element_rb.html +109 -0
- data/doc/files/lib/atom/entry_rb.html +111 -0
- data/doc/files/lib/atom/feed_rb.html +112 -0
- data/doc/files/lib/atom/http_rb.html +112 -0
- data/doc/files/lib/atom/service_rb.html +111 -0
- data/doc/files/lib/atom/text_rb.html +109 -0
- data/doc/files/lib/atom/xml_rb.html +110 -0
- data/doc/files/lib/atom/yaml_rb.html +109 -0
- data/doc/fr_class_index.html +42 -0
- data/doc/fr_file_index.html +36 -0
- data/doc/fr_method_index.html +69 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/atom/collection.rb +0 -21
- data/lib/atom/entry.rb +13 -0
- data/lib/atom/feed.rb +6 -7
- data/lib/atom/http.rb +97 -19
- data/lib/atom/service.rb +2 -22
- data/lib/atom/yaml.rb +1 -1
- data/test/test_feed.rb +27 -4
- data/test/test_http.rb +153 -34
- metadata +39 -2
data/lib/atom/service.rb
CHANGED
@@ -9,8 +9,6 @@ module Atom
|
|
9
9
|
|
10
10
|
class WrongNamespace < RuntimeError #:nodoc:
|
11
11
|
end
|
12
|
-
class WrongMimetype < RuntimeError # :nodoc:
|
13
|
-
end
|
14
12
|
class WrongResponse < RuntimeError # :nodoc:
|
15
13
|
end
|
16
14
|
|
@@ -102,16 +100,13 @@ module Atom
|
|
102
100
|
|
103
101
|
rxml = nil
|
104
102
|
|
105
|
-
res = @http.get(base)
|
103
|
+
res = @http.get(base, "Accept" => "application/atomserv+xml")
|
104
|
+
res.validate_content_type(["application/atomserv+xml"])
|
106
105
|
|
107
106
|
unless res.code == "200" # XXX needs to handle redirects, &c.
|
108
107
|
raise WrongResponse, "service document URL responded with unexpected code #{res.code}"
|
109
108
|
end
|
110
109
|
|
111
|
-
unless res.content_type == "application/atomserv+xml"
|
112
|
-
raise WrongMimetype, "this isn't an atom service document!"
|
113
|
-
end
|
114
|
-
|
115
110
|
parse(res.body, base)
|
116
111
|
end
|
117
112
|
|
@@ -152,19 +147,4 @@ module Atom
|
|
152
147
|
doc
|
153
148
|
end
|
154
149
|
end
|
155
|
-
|
156
|
-
class Entry
|
157
|
-
# the @href of an entry's link[@rel="edit"]
|
158
|
-
def edit_url
|
159
|
-
begin
|
160
|
-
edit_link = self.links.find do |link|
|
161
|
-
link["rel"] == "edit"
|
162
|
-
end
|
163
|
-
|
164
|
-
edit_link["href"]
|
165
|
-
rescue
|
166
|
-
nil
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
150
|
end
|
data/lib/atom/yaml.rb
CHANGED
data/test/test_feed.rb
CHANGED
@@ -60,6 +60,8 @@ END
|
|
60
60
|
|
61
61
|
def test_update
|
62
62
|
@s.mount_proc("/") do |req,res|
|
63
|
+
assert_equal "application/atom+xml", req["Accept"]
|
64
|
+
|
63
65
|
res.content_type = "application/atom+xml"
|
64
66
|
res.body = @test_feed
|
65
67
|
|
@@ -89,6 +91,9 @@ END
|
|
89
91
|
|
90
92
|
@s.stop
|
91
93
|
end
|
94
|
+
# there's some kind of race condition here that will result in a
|
95
|
+
# timeout sometimes. this is a dirty fix.
|
96
|
+
sleep 0.5
|
92
97
|
one_shot
|
93
98
|
end
|
94
99
|
|
@@ -96,15 +101,32 @@ END
|
|
96
101
|
|
97
102
|
# even if it looks like a feed, the server's word is law
|
98
103
|
c.call("text/plain")
|
99
|
-
assert_raise(Atom::
|
104
|
+
assert_raise(Atom::WrongMimetype) { feed.update! }
|
105
|
+
|
106
|
+
# a parameter shouldn't change the type
|
107
|
+
c.call("application/atom+xml;type=feed")
|
108
|
+
assert_nothing_raised { feed.update! }
|
109
|
+
|
110
|
+
# type and subtype are case insensitive (param. attribute names too)
|
111
|
+
c.call("ApPliCatIon/ATOM+XML")
|
112
|
+
assert_nothing_raised { feed.update! }
|
100
113
|
|
101
114
|
# text/xml isn't the preferred mimetype, but we'll accept it
|
102
115
|
c.call("text/xml")
|
103
116
|
assert_nothing_raised { feed.update! }
|
104
117
|
|
105
118
|
# same goes for application/xml
|
106
|
-
|
107
|
-
|
119
|
+
c.call("application/xml")
|
120
|
+
assert_nothing_raised { feed.update! }
|
121
|
+
|
122
|
+
# nil content type
|
123
|
+
@s.mount_proc("/") do |req,res|
|
124
|
+
res.body = @test_feed
|
125
|
+
|
126
|
+
@s.stop
|
127
|
+
end
|
128
|
+
one_shot
|
129
|
+
assert_raises(Atom::HTTPException) { feed.update! }
|
108
130
|
end
|
109
131
|
|
110
132
|
def test_conditional_get
|
@@ -139,7 +161,8 @@ END
|
|
139
161
|
assert_equal 'Wed, 15 Nov 1995 04:58:08 GMT', req["If-Modified-Since"]
|
140
162
|
|
141
163
|
res.status = 304
|
142
|
-
res.
|
164
|
+
res.content_type = "application/atom+xml"
|
165
|
+
res.body = @test_feed
|
143
166
|
|
144
167
|
@s.stop
|
145
168
|
end
|
data/test/test_http.rb
CHANGED
@@ -3,10 +3,14 @@ require "test/unit"
|
|
3
3
|
require "atom/http"
|
4
4
|
require "webrick"
|
5
5
|
|
6
|
-
class
|
6
|
+
class AtomHTTPTest < Test::Unit::TestCase
|
7
7
|
REALM = "test authentication"
|
8
8
|
USER = "test_user"
|
9
9
|
PASS = "aoeuaoeu"
|
10
|
+
|
11
|
+
# for Google AuthSub authentication
|
12
|
+
TOKEN = "pq7266382__838"
|
13
|
+
|
10
14
|
SECRET_DATA = "I kissed a boy once"
|
11
15
|
|
12
16
|
def setup
|
@@ -18,11 +22,13 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
18
22
|
end
|
19
23
|
|
20
24
|
def test_parse_wwwauth
|
25
|
+
# a Basic WWW-Authenticate
|
21
26
|
header = 'realm="SokEvo"'
|
22
27
|
|
23
28
|
params = @http.send :parse_quoted_wwwauth, header
|
24
29
|
assert_equal "SokEvo", params[:realm]
|
25
30
|
|
31
|
+
# Digest is parsed a bit differently
|
26
32
|
header = 'opaque="07UrfUiCYac5BbWJ", algorithm=MD5-sess, qop="auth", stale=TRUE, nonce="MDAx0Mzk", realm="test authentication"'
|
27
33
|
|
28
34
|
params = @http.send :parse_wwwauth_digest, header
|
@@ -36,57 +42,120 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
36
42
|
end
|
37
43
|
|
38
44
|
def test_GET
|
39
|
-
|
45
|
+
mount_one_shot do |req,res|
|
40
46
|
assert_equal("/", req.path)
|
41
47
|
|
42
48
|
res.content_type = "text/plain"
|
43
|
-
res.body = "
|
44
|
-
|
45
|
-
@s.stop
|
49
|
+
res.body = "Success!"
|
46
50
|
end
|
47
51
|
|
48
|
-
one_shot
|
49
|
-
|
50
52
|
get_root
|
51
53
|
|
52
|
-
assert_equal
|
53
|
-
assert_equal
|
54
|
-
assert_equal
|
54
|
+
assert_equal "200", @res.code
|
55
|
+
assert_equal "text/plain", @res.content_type
|
56
|
+
assert_equal "Success!", @res.body
|
55
57
|
end
|
56
58
|
|
57
59
|
def test_GET_headers
|
58
|
-
|
60
|
+
mount_one_shot do |req,res|
|
59
61
|
assert_equal("tester agent", req["User-Agent"])
|
62
|
+
end
|
63
|
+
|
64
|
+
get_root("User-Agent" => "tester agent")
|
65
|
+
|
66
|
+
assert_equal "200", @res.code
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_redirect
|
70
|
+
@s.mount_proc("/") do |req,res|
|
71
|
+
res.status = 302
|
72
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
60
73
|
|
74
|
+
res.body = "ignore me."
|
75
|
+
end
|
76
|
+
|
77
|
+
@s.mount_proc("/redirected") do |req,res|
|
78
|
+
res.content_type = "text/plain"
|
79
|
+
res.body = "Success!"
|
80
|
+
|
61
81
|
@s.stop
|
62
82
|
end
|
63
83
|
|
84
|
+
one_shot; get_root
|
85
|
+
|
86
|
+
# the redirect should be transparent (to whatever extent it can be)
|
87
|
+
assert_equal "200", @res.code
|
88
|
+
assert_equal "Success!", @res.body
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_redirect_loop
|
92
|
+
@s.mount_proc("/") do |req,res|
|
93
|
+
res.status = 302
|
94
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
95
|
+
end
|
96
|
+
|
97
|
+
@s.mount_proc("/redirected") do |req,res|
|
98
|
+
res.status = 302
|
99
|
+
res["Location"] = "http://localhost:#{@port}/"
|
100
|
+
end
|
101
|
+
|
64
102
|
one_shot
|
103
|
+
|
104
|
+
assert_raises(Atom::HTTPException) { get_root }
|
65
105
|
|
66
|
-
|
106
|
+
@s.stop
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_redirect_non_GET_non_HEAD
|
110
|
+
@s.mount_proc("/") do |req,res|
|
111
|
+
assert_equal "POST", req.request_method
|
112
|
+
res.status = 302
|
113
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
114
|
+
end
|
115
|
+
|
116
|
+
@s.mount_proc("/redirected") do |req,res|
|
117
|
+
assert_equal "POST", req.request_method
|
118
|
+
assert_equal "important message", req.body
|
119
|
+
res.content_type = "text/plain"
|
120
|
+
res.body = "Success!"
|
121
|
+
end
|
122
|
+
|
123
|
+
one_shot
|
124
|
+
|
125
|
+
@res = @http.post "http://localhost:#{@port}/", "important message"
|
126
|
+
|
127
|
+
assert_equal "302", @res.code
|
67
128
|
|
68
|
-
|
129
|
+
@http.allow_all_redirects = true
|
130
|
+
|
131
|
+
one_shot
|
132
|
+
|
133
|
+
@res = @http.post "http://localhost:#{@port}/", "important message"
|
134
|
+
|
135
|
+
assert_equal "200", @res.code
|
136
|
+
assert_equal "Success!", @res.body
|
137
|
+
|
138
|
+
@s.stop
|
69
139
|
end
|
70
140
|
|
71
141
|
def test_basic_auth
|
72
|
-
|
142
|
+
mount_one_shot do |req,res|
|
73
143
|
WEBrick::HTTPAuth.basic_auth(req, res, REALM) do |u,p|
|
74
144
|
u == USER and p == PASS
|
75
145
|
end
|
76
146
|
|
77
147
|
res.body = SECRET_DATA
|
78
|
-
@s.stop
|
79
148
|
end
|
80
149
|
|
81
|
-
|
82
|
-
|
83
|
-
# with no credentials
|
150
|
+
# no credentials
|
84
151
|
assert_raises(Atom::Unauthorized) { get_root }
|
85
152
|
|
86
153
|
@http.user = USER
|
87
154
|
@http.pass = "incorrect_password"
|
88
155
|
|
89
|
-
|
156
|
+
one_shot
|
157
|
+
|
158
|
+
# incorrect credentials
|
90
159
|
assert_raises(Atom::Unauthorized) { get_root }
|
91
160
|
|
92
161
|
@http.when_auth do |abs_url,realm|
|
@@ -95,19 +164,20 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
95
164
|
|
96
165
|
[USER, PASS]
|
97
166
|
end
|
98
|
-
|
167
|
+
|
99
168
|
one_shot
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
assert_equal SECRET_DATA, @res.body
|
169
|
+
|
170
|
+
# correct credentials
|
171
|
+
assert_authenticates
|
104
172
|
end
|
105
173
|
|
106
174
|
def test_digest_auth
|
107
|
-
# a dummy userdb
|
175
|
+
# a dummy userdb (saves me creating a file)
|
108
176
|
userdb = {}
|
177
|
+
# with a single entry
|
109
178
|
userdb[USER] = PASS
|
110
179
|
|
180
|
+
# HTTPAuth::DigestAuth#authenticate uses this
|
111
181
|
def userdb.get_passwd(realm, user, reload)
|
112
182
|
Digest::MD5::hexdigest([user, realm, self[user]].join(":"))
|
113
183
|
end
|
@@ -132,14 +202,13 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
132
202
|
@http.pass = PASS
|
133
203
|
|
134
204
|
# correct credentials
|
135
|
-
|
136
|
-
assert_equal SECRET_DATA, res.body
|
205
|
+
assert_authenticates
|
137
206
|
|
138
207
|
@s.stop
|
139
208
|
end
|
140
209
|
|
141
210
|
def test_wsse_auth
|
142
|
-
|
211
|
+
mount_one_shot do |req,res|
|
143
212
|
assert_equal 'WSSE profile="UsernameToken"', req["Authorization"]
|
144
213
|
|
145
214
|
xwsse = req["X-WSSE"]
|
@@ -159,24 +228,74 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
159
228
|
assert_equal password_digest, p[:PasswordDigest]
|
160
229
|
|
161
230
|
res.body = SECRET_DATA
|
162
|
-
@s.stop
|
163
231
|
end
|
164
232
|
|
165
|
-
one_shot
|
166
|
-
|
167
233
|
@http.always_auth = :wsse
|
168
234
|
@http.user = USER
|
169
235
|
@http.pass = PASS
|
170
|
-
|
171
|
-
get_root
|
172
236
|
|
237
|
+
assert_authenticates
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_authsub_auth
|
241
|
+
mount_one_shot do |req,res|
|
242
|
+
assert_equal %{AuthSub token="#{TOKEN}"}, req["Authorization"]
|
243
|
+
|
244
|
+
res.body = SECRET_DATA
|
245
|
+
end
|
246
|
+
|
247
|
+
@http.always_auth = :authsub
|
248
|
+
@http.token = TOKEN
|
249
|
+
|
250
|
+
assert_authenticates
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_https
|
254
|
+
require 'webrick/https'
|
255
|
+
|
256
|
+
@s = WEBrick::HTTPServer.new(
|
257
|
+
:Port => (@port + 1),
|
258
|
+
:DocumentRoot => Dir::pwd + "/htdocs",
|
259
|
+
:Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL),
|
260
|
+
:AccessLog => [],
|
261
|
+
:SSLEnable => true,
|
262
|
+
:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
|
263
|
+
:SSLCertName => [ ["C","CA"], ["O","localhost"], ["CN", "WWW"] ]
|
264
|
+
)
|
265
|
+
|
266
|
+
mount_one_shot do |req,res|
|
267
|
+
res.body = SECRET_DATA
|
268
|
+
end
|
269
|
+
|
270
|
+
res = @http.get("https://localhost:#{@port + 1}/")
|
271
|
+
|
272
|
+
assert_equal "200", res.code
|
273
|
+
assert_equal SECRET_DATA, res.body
|
274
|
+
end
|
275
|
+
|
276
|
+
# mount a block on the test server, shutting the server down after a
|
277
|
+
# single request
|
278
|
+
def mount_one_shot &block
|
279
|
+
@s.mount_proc("/") do |req,res|
|
280
|
+
block.call req, res
|
281
|
+
@s.stop
|
282
|
+
end
|
283
|
+
|
284
|
+
one_shot
|
285
|
+
end
|
286
|
+
|
287
|
+
# test that we authenticated properly
|
288
|
+
def assert_authenticates
|
289
|
+
get_root
|
173
290
|
assert_equal "200", @res.code
|
174
|
-
assert_equal SECRET_DATA, @res.body
|
291
|
+
assert_equal SECRET_DATA, @res.body
|
175
292
|
end
|
176
293
|
|
294
|
+
# performs a GET on the test server
|
177
295
|
def get_root(*args)
|
178
296
|
@res = @http.get("http://localhost:#{@port}/", *args)
|
179
297
|
end
|
180
298
|
|
299
|
+
# sets up the server for a single request
|
181
300
|
def one_shot; Thread.new { @s.start }; end
|
182
301
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: atom-tools
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
date: 2006-
|
6
|
+
version: 0.9.2
|
7
|
+
date: 2006-12-27 00:00:00 -07:00
|
8
8
|
summary: Tools for working with Atom Entries, Feeds and Collections
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,6 +33,43 @@ files:
|
|
33
33
|
- Rakefile
|
34
34
|
- setup.rb
|
35
35
|
- bin/atom-client.rb
|
36
|
+
- doc/files
|
37
|
+
- doc/index.html
|
38
|
+
- doc/rdoc-style.css
|
39
|
+
- doc/fr_method_index.html
|
40
|
+
- doc/fr_class_index.html
|
41
|
+
- doc/fr_file_index.html
|
42
|
+
- doc/created.rid
|
43
|
+
- doc/classes
|
44
|
+
- doc/files/lib
|
45
|
+
- doc/files/README.html
|
46
|
+
- doc/files/lib/atom
|
47
|
+
- doc/files/lib/atom/feed_rb.html
|
48
|
+
- doc/files/lib/atom/text_rb.html
|
49
|
+
- doc/files/lib/atom/xml_rb.html
|
50
|
+
- doc/files/lib/atom/yaml_rb.html
|
51
|
+
- doc/files/lib/atom/service_rb.html
|
52
|
+
- doc/files/lib/atom/element_rb.html
|
53
|
+
- doc/files/lib/atom/entry_rb.html
|
54
|
+
- doc/files/lib/atom/http_rb.html
|
55
|
+
- doc/files/lib/atom/collection_rb.html
|
56
|
+
- doc/classes/Atom
|
57
|
+
- doc/classes/XHTML.html
|
58
|
+
- doc/classes/Atom/Service.html
|
59
|
+
- doc/classes/Atom/Author.html
|
60
|
+
- doc/classes/Atom/Element.html
|
61
|
+
- doc/classes/Atom/Feed.html
|
62
|
+
- doc/classes/Atom/DigestAuth.html
|
63
|
+
- doc/classes/Atom/Text.html
|
64
|
+
- doc/classes/Atom/Contributor.html
|
65
|
+
- doc/classes/Atom/HTTPResponse.html
|
66
|
+
- doc/classes/Atom/HTTP.html
|
67
|
+
- doc/classes/Atom/Link.html
|
68
|
+
- doc/classes/Atom/Collection.html
|
69
|
+
- doc/classes/Atom/Content.html
|
70
|
+
- doc/classes/Atom/Category.html
|
71
|
+
- doc/classes/Atom/Workspace.html
|
72
|
+
- doc/classes/Atom/Entry.html
|
36
73
|
- test/test_constructs.rb
|
37
74
|
- test/runtests.rb
|
38
75
|
- test/test_feed.rb
|