atom-tools 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|