atom-tools 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/bin/atom-client.rb +23 -19
- data/lib/atom/entry.rb +1 -1
- data/lib/atom/feed.rb +3 -3
- data/lib/atom/http.rb +12 -8
- data/lib/atom/service.rb +17 -8
- data/test/test_constructs.rb +1 -1
- data/test/test_http.rb +1 -1
- data/test/test_protocol.rb +2 -5
- data/test/test_xml.rb +1 -1
- metadata +3 -3
data/Rakefile
CHANGED
data/bin/atom-client.rb
CHANGED
@@ -32,7 +32,6 @@ require "atom/service"
|
|
32
32
|
require "atom/http"
|
33
33
|
|
34
34
|
require "rubygems"
|
35
|
-
require "bluecloth"
|
36
35
|
|
37
36
|
require "time"
|
38
37
|
|
@@ -63,34 +62,26 @@ class String
|
|
63
62
|
end
|
64
63
|
|
65
64
|
class Atom::Entry
|
66
|
-
def prepare_for_output
|
67
|
-
filter_hook
|
68
|
-
|
69
|
-
updated!
|
70
|
-
end
|
71
|
-
|
72
|
-
def filter_hook
|
73
|
-
# so much for actual text content...
|
74
|
-
if @content and @content["type"] == "text"
|
75
|
-
self.content = BlueCloth.new( @content.to_s ).to_html
|
76
|
-
@content["type"] = "xhtml"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
65
|
def edit
|
81
66
|
yaml = YAML.load(self.to_yaml)
|
82
67
|
|
83
|
-
#
|
68
|
+
# delete bits the person doesn't need to see
|
84
69
|
yaml.delete "id"
|
85
70
|
|
86
71
|
if yaml["links"]
|
87
|
-
yaml["links"].find_all { |l|
|
72
|
+
yaml["links"].find_all { |l| ["alternate", "edit"].member? l["rel"] }.each { |l| yaml["links"].delete(l) }
|
88
73
|
yaml.delete("links") if yaml["links"].empty?
|
89
74
|
end
|
90
|
-
|
75
|
+
|
76
|
+
if self.content
|
77
|
+
yaml["content"] = $text_filter_before.call(self.content.html)
|
78
|
+
end
|
79
|
+
|
91
80
|
new_yaml, entry = write_entry(yaml.to_yaml)
|
92
81
|
|
82
|
+
# restore deleted bits
|
93
83
|
entry.id = self.id
|
84
|
+
self.links.each { |l| entry.links << l }
|
94
85
|
|
95
86
|
[new_yaml["slug"], entry]
|
96
87
|
end
|
@@ -145,7 +136,12 @@ def write_entry(editstring = "")
|
|
145
136
|
|
146
137
|
entry = Atom::Entry.from_yaml yaml
|
147
138
|
|
148
|
-
|
139
|
+
if yaml["content"] #and not yaml["type"]
|
140
|
+
entry.content, type = $text_filter_after.call(yaml["content"])
|
141
|
+
entry.content["type"] = (type || "text")
|
142
|
+
end
|
143
|
+
|
144
|
+
entry.updated!
|
149
145
|
|
150
146
|
# XXX disabled until the APP WG can decide what a valid entry is
|
151
147
|
=begin
|
@@ -187,6 +183,14 @@ url = if options[:url]
|
|
187
183
|
options[:url]
|
188
184
|
else
|
189
185
|
yaml = YAML.load(File.read("#{ENV["HOME"]}/.atom-client"))
|
186
|
+
|
187
|
+
# leave it the way it came in
|
188
|
+
i = Proc.new { |x| x }
|
189
|
+
$text_filter_before = eval(yaml["text_filter_before"])
|
190
|
+
$text_filter_before ||= i
|
191
|
+
$text_filter_after = eval(yaml["text_filter_after"])
|
192
|
+
$text_filter_after ||= i
|
193
|
+
|
190
194
|
collections = yaml["collections"]
|
191
195
|
|
192
196
|
puts "which collection?"
|
data/lib/atom/entry.rb
CHANGED
@@ -5,7 +5,7 @@ require "atom/text"
|
|
5
5
|
|
6
6
|
module Atom
|
7
7
|
NS = "http://www.w3.org/2005/Atom"
|
8
|
-
PP_NS = "http://
|
8
|
+
PP_NS = "http://www.w3.org/2007/app"
|
9
9
|
|
10
10
|
# An individual entry in a feed. As an Atom::Element, it can be
|
11
11
|
# manipulated using accessors for each of its child elements. You
|
data/lib/atom/feed.rb
CHANGED
@@ -197,14 +197,14 @@ module Atom
|
|
197
197
|
|
198
198
|
coll = Atom::Feed.parse(coll, self.base.to_s)
|
199
199
|
merge! coll
|
200
|
-
|
201
|
-
link = coll.links.find { |l| l["rel"]
|
200
|
+
|
201
|
+
link = coll.links.find { |l| l["rel"] == "next" and l["type"] == "application/atom+xml" }
|
202
202
|
if link
|
203
203
|
abs_uri = @uri + link["href"]
|
204
204
|
@next = Feed.new(abs_uri.to_s, @http)
|
205
205
|
end
|
206
206
|
|
207
|
-
link = coll.links.find { |l| l["rel"]
|
207
|
+
link = coll.links.find { |l| l["rel"] == "previous" and l["type"] == "application/atom+xml" }
|
208
208
|
if link
|
209
209
|
abs_uri = @uri + link["href"]
|
210
210
|
@prev = Feed.new(abs_uri.to_s, @http)
|
data/lib/atom/http.rb
CHANGED
@@ -3,7 +3,7 @@ require "net/https"
|
|
3
3
|
require "uri"
|
4
4
|
|
5
5
|
require "sha1"
|
6
|
-
require "md5"
|
6
|
+
require "digest/md5"
|
7
7
|
|
8
8
|
module URI # :nodoc: all
|
9
9
|
class Generic; def to_uri; self; end; end
|
@@ -17,7 +17,7 @@ module Atom
|
|
17
17
|
UA = "atom-tools 0.9.3"
|
18
18
|
|
19
19
|
module DigestAuth
|
20
|
-
CNONCE = Digest::MD5.
|
20
|
+
CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
21
21
|
|
22
22
|
@@nonce_count = -1
|
23
23
|
|
@@ -223,18 +223,21 @@ module Atom
|
|
223
223
|
req.basic_auth user, pass
|
224
224
|
end
|
225
225
|
|
226
|
-
#
|
227
|
-
#
|
226
|
+
# is this the right way to do it? who knows, there's no
|
227
|
+
# spec!
|
228
|
+
# <http://necronomicorp.com/lab/atom-authentication-sucks>
|
229
|
+
#
|
230
|
+
# thanks to H. Miyamoto for clearing things up.
|
228
231
|
def wsse_authenticate(req, url, params = {})
|
229
232
|
user, pass = username_and_password_for_realm(url, params["realm"])
|
230
233
|
|
231
|
-
# thanks to Sam Ruby
|
232
234
|
nonce = rand(16**32).to_s(16)
|
235
|
+
nonce_enc = [nonce].pack('m').chomp
|
233
236
|
now = Time.now.gmtime.iso8601
|
234
237
|
|
235
238
|
digest = [Digest::SHA1.digest(nonce + now + pass)].pack("m").chomp
|
236
239
|
|
237
|
-
req['X-WSSE'] = %Q<UsernameToken Username="#{user}", PasswordDigest="#{digest}", Nonce="#{
|
240
|
+
req['X-WSSE'] = %Q<UsernameToken Username="#{user}", PasswordDigest="#{digest}", Nonce="#{nonce_enc}", Created="#{now}">
|
238
241
|
req["Authorization"] = 'WSSE profile="UsernameToken"'
|
239
242
|
end
|
240
243
|
|
@@ -281,8 +284,9 @@ module Atom
|
|
281
284
|
|
282
285
|
case res
|
283
286
|
when Net::HTTPUnauthorized
|
284
|
-
if @always_auth or www_authenticate # XXX and not stale (Digest only)
|
285
|
-
# we've tried the credentials you gave us once
|
287
|
+
if @always_auth or www_authenticate or not res["WWW-Authenticate"] # XXX and not stale (Digest only)
|
288
|
+
# we've tried the credentials you gave us once
|
289
|
+
# and failed, or the server gave us no way to fix it
|
286
290
|
raise Unauthorized, "Your authorization was rejected"
|
287
291
|
else
|
288
292
|
# once more, with authentication
|
data/lib/atom/service.rb
CHANGED
@@ -36,12 +36,12 @@ module Atom
|
|
36
36
|
|
37
37
|
coll = Atom::Collection.new(url, http)
|
38
38
|
|
39
|
-
# XXX this is a Text Construct, and should be parsed as such
|
40
39
|
col_el.fill_text_construct(coll, "title")
|
41
40
|
|
42
41
|
accepts = REXML::XPath.first( col_el,
|
43
42
|
"./app:accept",
|
44
43
|
{"app" => Atom::PP_NS} )
|
44
|
+
|
45
45
|
coll.accepts = (accepts ? accepts.text : "entry")
|
46
46
|
|
47
47
|
ws.collections << coll
|
@@ -53,10 +53,11 @@ module Atom
|
|
53
53
|
def to_element # :nodoc:
|
54
54
|
root = REXML::Element.new "workspace"
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
if self.title
|
57
|
+
title = self.title.to_element
|
58
|
+
title.name = "atom:title"
|
59
|
+
root << title
|
60
|
+
end
|
60
61
|
|
61
62
|
self.collections.each do |coll|
|
62
63
|
el = REXML::Element.new "collection"
|
@@ -98,8 +99,8 @@ module Atom
|
|
98
99
|
|
99
100
|
rxml = nil
|
100
101
|
|
101
|
-
res = @http.get(base, "Accept" => "application/
|
102
|
-
res.validate_content_type(["application/
|
102
|
+
res = @http.get(base, "Accept" => "application/atomsvc+xml")
|
103
|
+
res.validate_content_type(["application/atomsvc+xml"])
|
103
104
|
|
104
105
|
unless res.code == "200" # XXX needs to handle redirects, &c.
|
105
106
|
raise WrongResponse, "service document URL responded with unexpected code #{res.code}"
|
@@ -107,7 +108,15 @@ module Atom
|
|
107
108
|
|
108
109
|
parse(res.body, base)
|
109
110
|
end
|
110
|
-
|
111
|
+
|
112
|
+
def self.parse xml, base = ""
|
113
|
+
Atom::Service.new.parse(xml, base)
|
114
|
+
end
|
115
|
+
|
116
|
+
def collections
|
117
|
+
self.workspaces.map { |ws| ws.collections }.flatten
|
118
|
+
end
|
119
|
+
|
111
120
|
# parse a service document, adding its workspaces to this object
|
112
121
|
def parse xml, base = ""
|
113
122
|
rxml = if xml.is_a? REXML::Document
|
data/test/test_constructs.rb
CHANGED
data/test/test_http.rb
CHANGED
@@ -226,7 +226,7 @@ class AtomHTTPTest < Test::Unit::TestCase
|
|
226
226
|
assert_match /^UsernameToken /, xwsse
|
227
227
|
|
228
228
|
# Base64( SHA1( Nonce + CreationTimestamp + Password ) )
|
229
|
-
pd_string = p[:Nonce] + p[:Created] + PASS
|
229
|
+
pd_string = p[:Nonce].unpack("m").first + p[:Created] + PASS
|
230
230
|
password_digest = [Digest::SHA1.digest(pd_string)].pack("m").chomp
|
231
231
|
|
232
232
|
assert_equal password_digest, p[:PasswordDigest]
|
data/test/test_protocol.rb
CHANGED
@@ -21,7 +21,7 @@ end
|
|
21
21
|
class AtomProtocolTest < Test::Unit::TestCase
|
22
22
|
def test_introspection
|
23
23
|
doc = <<END
|
24
|
-
<service xmlns="http://
|
24
|
+
<service xmlns="http://www.w3.org/2007/app"
|
25
25
|
xmlns:atom="http://www.w3.org/2005/Atom">
|
26
26
|
<workspace>
|
27
27
|
<atom:title>My Blog</atom:title>
|
@@ -36,11 +36,8 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
36
36
|
</service>
|
37
37
|
END
|
38
38
|
|
39
|
-
#http = FakeHTTP.new({ "http://example.com/service.xml" => service }, "application/atomserv+xml")
|
40
|
-
|
41
39
|
service = Atom::Service.new
|
42
40
|
service.parse doc
|
43
|
-
#service = Atom::Service.new "http://example.com/service.xml", http
|
44
41
|
|
45
42
|
ws = service.workspaces.first
|
46
43
|
assert_equal "My Blog", ws.title.to_s
|
@@ -84,7 +81,7 @@ END
|
|
84
81
|
|
85
82
|
doc = REXML::Document.new(service.to_s)
|
86
83
|
|
87
|
-
assert_equal "http://
|
84
|
+
assert_equal "http://www.w3.org/2007/app", doc.root.namespace
|
88
85
|
|
89
86
|
ws = REXML::XPath.first( doc.root,
|
90
87
|
"/app:service/app:workspace",
|
data/test/test_xml.rb
CHANGED
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: atom-tools
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.9.4
|
7
|
+
date: 2007-08-11 00:00:00 -06:00
|
8
8
|
summary: Tools for working with Atom Entries, Feeds and Collections
|
9
9
|
require_paths:
|
10
10
|
- lib
|