discodactyl 0.3.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -6
- data/MANIFEST +9 -1
- data/{README → README.rdoc} +19 -5
- data/TODO +22 -5
- data/bin/webfinger +59 -14
- data/discodactyl.gemspec +7 -5
- data/lib/discodactyl/acct_uri.rb +3 -1
- data/lib/discodactyl/host_meta.rb +12 -0
- data/lib/discodactyl/host_meta_jrd.rb +35 -0
- data/lib/discodactyl/jrd/document.rb +49 -0
- data/lib/discodactyl/jrd/link.rb +25 -0
- data/lib/discodactyl/jrd.rb +2 -0
- data/lib/discodactyl/known_rels.rb +12 -0
- data/lib/discodactyl/link_header.rb +2 -2
- data/lib/discodactyl/log.rb +5 -0
- data/lib/discodactyl/resource_discovery.rb +22 -1
- data/lib/discodactyl/xrd/document.rb +15 -1
- data/lib/discodactyl/xrd/link.rb +5 -6
- data/lib/discodactyl.rb +5 -1
- data/test/test_host_meta_jrd.rb +63 -0
- data/test/test_jrd_document.rb +142 -0
- metadata +70 -15
data/Gemfile
CHANGED
data/MANIFEST
CHANGED
@@ -5,7 +5,7 @@ Gemfile
|
|
5
5
|
INSTALL
|
6
6
|
MANIFEST
|
7
7
|
NEWS
|
8
|
-
README
|
8
|
+
README.rdoc
|
9
9
|
Rakefile
|
10
10
|
TODO
|
11
11
|
bin/webfinger
|
@@ -13,7 +13,13 @@ discodactyl.gemspec
|
|
13
13
|
lib/discodactyl.rb
|
14
14
|
lib/discodactyl/acct_uri.rb
|
15
15
|
lib/discodactyl/host_meta.rb
|
16
|
+
lib/discodactyl/host_meta_jrd.rb
|
17
|
+
lib/discodactyl/jrd.rb
|
18
|
+
lib/discodactyl/jrd/document.rb
|
19
|
+
lib/discodactyl/jrd/link.rb
|
20
|
+
lib/discodactyl/known_rels.rb
|
16
21
|
lib/discodactyl/link_header.rb
|
22
|
+
lib/discodactyl/log.rb
|
17
23
|
lib/discodactyl/resource_discovery.rb
|
18
24
|
lib/discodactyl/uri_template.rb
|
19
25
|
lib/discodactyl/xrd.rb
|
@@ -22,6 +28,8 @@ lib/discodactyl/xrd/link.rb
|
|
22
28
|
test/test_acct_uri.rb
|
23
29
|
test/test_helper.rb
|
24
30
|
test/test_host_meta.rb
|
31
|
+
test/test_host_meta_jrd.rb
|
32
|
+
test/test_jrd_document.rb
|
25
33
|
test/test_link_header.rb
|
26
34
|
test/test_resource_discovery.rb
|
27
35
|
test/test_uri_template.rb
|
data/{README → README.rdoc}
RENAMED
@@ -1,9 +1,10 @@
|
|
1
1
|
= Discodactyl
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Code :: http://github.com/josephholsten/discodactyl
|
4
|
+
Bugs :: http://josephholsten.lighthouseapp.com/projects/36040-discodactyl
|
5
|
+
Tests :: http://discodactyl-ci.heroku.com/
|
6
|
+
Docs :: http://rdoc.info/projects/josephholsten/discodactyl
|
7
|
+
Author :: mailto:joseph@josephholsten.com
|
7
8
|
|
8
9
|
== DESCRIPTION:
|
9
10
|
|
@@ -18,9 +19,22 @@ Discodactyl is an experimental toolkit for XRD service discovery documents and r
|
|
18
19
|
* acct: URI parsing.
|
19
20
|
* Minimal URI Template parsing and application.
|
20
21
|
* Probably filled with bugs. Don't forget your bug powder.
|
22
|
+
* JRD parsing, querying.
|
23
|
+
* Yahoo 'webfinger' doesn't work. Sadly, they need to update their format to the most recent one.
|
21
24
|
|
22
25
|
== SYNOPSIS:
|
23
26
|
|
27
|
+
For command-line fiends:
|
28
|
+
|
29
|
+
$ webfinger bradfitz@gmail.com
|
30
|
+
Profile: http://www.google.com/profiles/bradfitz
|
31
|
+
Profile data: http://www-opensocial.googleusercontent.com/api/people/115863474911002159675/
|
32
|
+
describedby: http://www.google.com/profiles/bradfitz
|
33
|
+
Contacts: http://www-opensocial.googleusercontent.com/api/people/
|
34
|
+
Status: Hah... about 4 hours ago
|
35
|
+
|
36
|
+
For ruby mongers:
|
37
|
+
|
24
38
|
# All of WebFinger! In very few, if long and pointy, lines!
|
25
39
|
require 'discodactyl'
|
26
40
|
|
@@ -46,7 +60,7 @@ This software is also available in a permissive license. Please contact Joseph H
|
|
46
60
|
|
47
61
|
(The GNU Affero General Public License)
|
48
62
|
|
49
|
-
Copyright (c) 2009, 2010 Joseph Anthony Pasquale Holsten
|
63
|
+
Copyright (c) 2009, 2010, 2011 Joseph Anthony Pasquale Holsten
|
50
64
|
|
51
65
|
This program is free software: you can redistribute it and/or modify
|
52
66
|
it under the terms of the GNU Affero General Public License as published by
|
data/TODO
CHANGED
@@ -14,11 +14,28 @@
|
|
14
14
|
* REXML support
|
15
15
|
* collect common rel values into a enum module
|
16
16
|
* put license info in every file
|
17
|
+
* find out if ruby has a default debug flag
|
18
|
+
* find well known uris via WellKnown.find(uri, :host_meta)
|
17
19
|
|
18
20
|
Reference Specs
|
19
|
-
* host meta http://tools.ietf.org/html/draft-hammer-hostmeta-
|
21
|
+
* host meta http://tools.ietf.org/html/draft-hammer-hostmeta-13
|
20
22
|
* webfinger
|
21
|
-
* xrd http://
|
22
|
-
* lrdd http://tools.ietf.org/html/draft-hammer-discovery-
|
23
|
-
* link header http://tools.ietf.org/html/
|
24
|
-
* versioning-rels http://tools.ietf.org/html/
|
23
|
+
* xrd http://docs.oasis-open.org/xri/xrd/v1.0/xrd-1.0.html
|
24
|
+
* lrdd http://tools.ietf.org/html/draft-hammer-discovery-06
|
25
|
+
* link header http://tools.ietf.org/html/rfc5988
|
26
|
+
* versioning-rels http://tools.ietf.org/html/rfc5829
|
27
|
+
|
28
|
+
Interesting webfinger variants
|
29
|
+
* joseph@josephholsten.com
|
30
|
+
* romeda@gmail.com
|
31
|
+
* will@willmeyer.com
|
32
|
+
* dclinton@gmail.com
|
33
|
+
* bradfitz@gmail.com
|
34
|
+
* dclinton@yahoo.com
|
35
|
+
* beestage@yahoo.com
|
36
|
+
* gffletch@aol.com
|
37
|
+
|
38
|
+
other clients
|
39
|
+
* webfingerclient-dclinton.appspot.com/
|
40
|
+
* webfinger.org/lookup/darron@froese.org
|
41
|
+
* web.mailana.com/labs/findbyemail/
|
data/bin/webfinger
CHANGED
@@ -7,14 +7,27 @@ require 'open-uri'
|
|
7
7
|
require 'action_view'
|
8
8
|
require 'mofo'
|
9
9
|
require 'feedzirra'
|
10
|
+
require 'logger'
|
11
|
+
|
12
|
+
log = Logger.new(STDOUT)
|
13
|
+
Discodactyl.log = log
|
10
14
|
|
11
15
|
if ARGV.length == 0
|
12
16
|
puts "Usage: #{__FILE__} user@host"
|
13
17
|
exit 0
|
14
18
|
end
|
15
19
|
|
20
|
+
if ARGV[0].match /^-d/
|
21
|
+
log.level = Logger::DEBUG
|
22
|
+
# ARGV.unshift
|
23
|
+
ARGV.shift
|
24
|
+
else
|
25
|
+
log.level = Logger::WARN
|
26
|
+
end
|
27
|
+
|
16
28
|
# parse identifier
|
17
|
-
|
29
|
+
raw_acct = ARGV[0]
|
30
|
+
acct = URI::ACCT.parse(raw_acct)
|
18
31
|
|
19
32
|
# Perform LRDD discovery on acct with the webfinger relation
|
20
33
|
finger_rel = "lrdd"
|
@@ -22,41 +35,73 @@ begin
|
|
22
35
|
webfinger_uris = Discodactyl::ResourceDiscovery.get_uris_by_rel(acct, finger_rel, 'uri' => acct)
|
23
36
|
rescue Discodactyl::HostMetaHTTPError => error
|
24
37
|
if error.io.status[1] == 'Not Found'
|
25
|
-
abort "No host meta webfinger information found at #{error.io.base_uri}"
|
38
|
+
abort "No host meta webfinger information found at #{error.io.base_uri}. Is the file there?"
|
26
39
|
else
|
27
40
|
raise
|
28
41
|
end
|
42
|
+
rescue Discodactyl::HostMetaSocketError => error
|
43
|
+
abort "Could not connect to #{error.host}:#{error.port}. Is your internet connection working?"
|
29
44
|
end
|
30
45
|
|
31
46
|
abort "URI didn't have any linked webfinger URIs" if webfinger_uris.empty?
|
32
47
|
|
33
48
|
# retrieve user disco doc
|
34
|
-
|
49
|
+
begin
|
50
|
+
disco_uri = webfinger_uris.first
|
51
|
+
disco_res = open(disco_uri)
|
52
|
+
rescue OpenURI::HTTPError
|
53
|
+
abort "Couldn't open the disco doc at #{disco_uri}. Is your host-meta pointed at the right place?"
|
54
|
+
end
|
35
55
|
|
36
56
|
# parse disco doc
|
37
|
-
|
57
|
+
begin
|
58
|
+
disco = Discodactyl::JRD::Document.parse(disco_res)
|
59
|
+
log.debug "disco doc <#{webfinger_uris.first}>:\n#{disco.inspect}\n"
|
60
|
+
rescue Discodactyl::JRD::ParseError => e
|
61
|
+
log.debug "disco doc doesn't seem to be a JRD #{e.message}"
|
62
|
+
disco_res.rewind
|
63
|
+
disco = Discodactyl::XRD::Document.parse(disco_res)
|
64
|
+
log.debug "disco doc <#{webfinger_uris.first}>:\n#{disco}\n"
|
65
|
+
end
|
66
|
+
|
67
|
+
log.debug "links: #{disco.links.map{|r| [r.rel, r.type, r.href]}.inspect}"
|
68
|
+
log.debug "rels: #{disco.rels.inspect}"
|
69
|
+
|
70
|
+
if disco.subject
|
71
|
+
log.debug "subject: #{disco.subject}"
|
72
|
+
unless acct.to_s == disco.subject.to_s
|
73
|
+
abort "Disco doc's subject <#{disco.subject}> doesn't match account we're webfingering <#{acct}>"
|
74
|
+
end
|
75
|
+
else
|
76
|
+
log.warn("Disco doc didn't list a subject. Assuming everything is well.")
|
77
|
+
end
|
38
78
|
|
39
79
|
hcard_uri = disco.uris_by_rel('http://microformats.org/profile/hcard').first
|
40
|
-
hcard = hCard.find(:first => hcard_uri)
|
80
|
+
hcard = hCard.find(:first => hcard_uri) rescue
|
41
81
|
if hcard
|
42
82
|
puts "Name: #{hcard.fn.gsub(/\s+/, ' ')}" if hcard.properties.include?('fn')
|
43
83
|
puts "Title: #{hcard.title}" if hcard.properties.include?('title')
|
44
84
|
puts "Organization: #{hcard.org}" if hcard.properties.include?('org')
|
45
85
|
end
|
46
86
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
puts "Profile: #{profile}" if profile
|
87
|
+
links_with_titles = disco.links.select{|l| l.title.present? }
|
88
|
+
links_with_titles.each do |link|
|
89
|
+
puts "#{link.title}: #{link.to_uri}"
|
90
|
+
end
|
52
91
|
|
53
|
-
|
54
|
-
|
92
|
+
Discodactyl::KNOWN_RELS.each do |name, rel|
|
93
|
+
uri = disco.uris_by_rel(rel).first
|
94
|
+
puts "#{name}: #{uri}" if uri
|
95
|
+
end
|
55
96
|
|
56
97
|
activities = disco.uris_by_rel('http://schemas.google.com/g/2010#updates-from').first
|
57
98
|
if activities
|
58
99
|
feed = Feedzirra::Feed.fetch_and_parse(activities)
|
59
100
|
entry = feed.entries.first
|
60
|
-
|
61
|
-
|
101
|
+
if entry
|
102
|
+
include ActionView::Helpers::DateHelper
|
103
|
+
silence_warnings do
|
104
|
+
puts "Status: #{Loofah::Helpers.strip_tags(entry.content)} #{time_ago_in_words(entry.published)} ago"
|
105
|
+
end
|
106
|
+
end
|
62
107
|
end
|
data/discodactyl.gemspec
CHANGED
@@ -7,17 +7,19 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.email = "joseph@josephholsten.com"
|
8
8
|
spec.homepage = "http://dactylo.us"
|
9
9
|
spec.description = %q{Discodactyl is an experimental toolkit for XRD service discovery documents and related protocols. It includes implementations of XRD URITemplate Link-Patterns, basic site-meta support, HTTP Link header parsing, acct: URIs and a webfinger poking stick.}
|
10
|
-
spec.extra_rdoc_files = %w[ AUTHORS CHANGELOG COPYING INSTALL NEWS README TODO ]
|
10
|
+
spec.extra_rdoc_files = %w[ AUTHORS CHANGELOG COPYING INSTALL NEWS README.rdoc TODO ]
|
11
11
|
spec.rdoc_options << "--charset=UTF-8" <<
|
12
12
|
"--title" << "Discodactyl Documentation" <<
|
13
|
-
"--main" << "README"
|
13
|
+
"--main" << "README.rdoc"
|
14
14
|
spec.version = version
|
15
15
|
spec.summary = spec.description.split(/\.\s+/).first
|
16
16
|
spec.files = File.read("MANIFEST").split(/\r?\n\r?/)
|
17
17
|
spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(/^test\/.*test_.*\.rb$/)
|
19
|
-
spec.add_runtime_dependency 'nokogiri', '~>1.4.
|
20
|
-
spec.add_runtime_dependency 'actionpack', '~>
|
19
|
+
spec.add_runtime_dependency 'nokogiri', '~>1.4.2'
|
20
|
+
spec.add_runtime_dependency 'actionpack', '~>3.0.0'
|
21
21
|
spec.add_runtime_dependency 'feedzirra', '~>0.0.23'
|
22
|
-
spec.add_runtime_dependency 'mofo', '~>0.2.
|
22
|
+
spec.add_runtime_dependency 'mofo', '~>0.2.16'
|
23
|
+
spec.add_development_dependency 'rr', '~>0.10.11'
|
24
|
+
spec.add_development_dependency 'rake', '~>0.8.7'
|
23
25
|
end
|
data/lib/discodactyl/acct_uri.rb
CHANGED
@@ -13,7 +13,9 @@ module URI # :nodoc:
|
|
13
13
|
/^(acct:)?(.*)$/ =~ str
|
14
14
|
scheme = 'acct'
|
15
15
|
opaque = $2
|
16
|
-
self.new(scheme, nil, nil, nil, nil, nil, opaque, nil, nil)
|
16
|
+
acct = self.new(scheme, nil, nil, nil, nil, nil, opaque, nil, nil)
|
17
|
+
Discodactyl.log.debug("Parsed #{str.inspect} into URI #{acct.inspect}") if Discodactyl.log
|
18
|
+
acct
|
17
19
|
end
|
18
20
|
|
19
21
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'discodactyl/xrd'
|
2
2
|
require 'open-uri'
|
3
|
+
require 'socket'
|
3
4
|
|
4
5
|
module Discodactyl # :nodoc
|
5
6
|
# Convienient access to host metadata and individual resources controlled by
|
@@ -15,6 +16,7 @@ module Discodactyl # :nodoc
|
|
15
16
|
# Take a URI and retrieve its HostMeta document
|
16
17
|
def from_uri(uri)
|
17
18
|
uri = get_uri_from_uri(uri)
|
19
|
+
Discodactyl.log.debug("got xrd host-meta uri: #{uri}") if Discodactyl.log
|
18
20
|
begin
|
19
21
|
raw = uri.open
|
20
22
|
rescue OpenURI::HTTPError => error
|
@@ -24,6 +26,8 @@ module Discodactyl # :nodoc
|
|
24
26
|
else
|
25
27
|
raise
|
26
28
|
end
|
29
|
+
rescue ::SocketError => error
|
30
|
+
raise HostMetaSocketError.new(error.message, uri.host, uri.port)
|
27
31
|
end
|
28
32
|
self.parse raw
|
29
33
|
end
|
@@ -31,4 +35,12 @@ module Discodactyl # :nodoc
|
|
31
35
|
end
|
32
36
|
class HostMetaHTTPError < OpenURI::HTTPError # :nodoc:
|
33
37
|
end
|
38
|
+
class HostMetaSocketError < StandardError # :nodoc:
|
39
|
+
attr_accessor :host, :port
|
40
|
+
def initialize(msg = nil, host = nil, port = nil)
|
41
|
+
message = msg
|
42
|
+
@host = host
|
43
|
+
@port = port
|
44
|
+
end
|
45
|
+
end
|
34
46
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'active_support'
|
3
|
+
require 'socket'
|
4
|
+
require "discodactyl/uri_template"
|
5
|
+
require "discodactyl/jrd"
|
6
|
+
require 'discodactyl/log'
|
7
|
+
|
8
|
+
module Discodactyl
|
9
|
+
class HostMetaJRD < Discodactyl::JRD::Document
|
10
|
+
# Take a URI and return the URI for its HostMeta document
|
11
|
+
def self.get_uri_from_uri(uri)
|
12
|
+
host = uri.respond_to?('host') ? uri.host : uri
|
13
|
+
URI.parse('http://'+ host + '/.well-known/host-meta.json')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Take a URI and retrieve its HostMeta document
|
17
|
+
def self.from_uri(uri)
|
18
|
+
uri = get_uri_from_uri(uri)
|
19
|
+
Discodactyl.log.debug("got jrd host-meta uri: #{uri}") if Discodactyl.log
|
20
|
+
begin
|
21
|
+
raw = uri.open
|
22
|
+
rescue OpenURI::HTTPError => error
|
23
|
+
if error.io.status[1] == 'Not Found'
|
24
|
+
error.io.base_uri = uri
|
25
|
+
raise HostMetaHTTPError.new(error.message, error.io)
|
26
|
+
else
|
27
|
+
raise
|
28
|
+
end
|
29
|
+
rescue ::SocketError => error
|
30
|
+
raise HostMetaSocketError.new(error.message, uri.host, uri.port)
|
31
|
+
end
|
32
|
+
self.parse raw
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'active_support'
|
3
|
+
require 'discodactyl/jrd/link'
|
4
|
+
require "discodactyl/uri_template"
|
5
|
+
|
6
|
+
module Discodactyl # :nodoc:
|
7
|
+
module JRD # :nodoc:
|
8
|
+
class Document < Hash
|
9
|
+
def self.parse(raw)
|
10
|
+
begin
|
11
|
+
Discodactyl.log.debug("parsing jrd: #{raw}") if Discodactyl.log
|
12
|
+
decoded = ActiveSupport::JSON.decode(raw)
|
13
|
+
rescue => e
|
14
|
+
raise ParseError.new(e.message)
|
15
|
+
end
|
16
|
+
self.[](decoded)
|
17
|
+
end
|
18
|
+
|
19
|
+
def uris_by_rel(rel, params={})
|
20
|
+
links_by_rel(rel).map do |link|
|
21
|
+
link.href || link.template.to_uri(params)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def links_by_rel(rel)
|
26
|
+
if self.has_key? 'links' and self['links'].has_key? rel
|
27
|
+
self['links'][rel].map{|link| Link.parse(link.merge('rel'=>rel)) }
|
28
|
+
else
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def links
|
34
|
+
rels.map do |rel, links|
|
35
|
+
links.map {|link| Link.parse(link.merge('rel' => rel)) }
|
36
|
+
end.flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def rels
|
40
|
+
self['links'] || []
|
41
|
+
end
|
42
|
+
|
43
|
+
def subject
|
44
|
+
self['subject']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
class ParseError < StandardError; end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'discodactyl/uri_template'
|
2
|
+
|
3
|
+
module Discodactyl # :nodoc:
|
4
|
+
module JRD # :nodoc:
|
5
|
+
class Link < Struct.new(:href, :template, :rel, :title, :type)
|
6
|
+
attr_accessor :raw
|
7
|
+
class << self
|
8
|
+
def parse(element)
|
9
|
+
self.new.tap do |link|
|
10
|
+
begin
|
11
|
+
link.rel = element['rel']
|
12
|
+
link.type = element['type']
|
13
|
+
link.href = element['href']
|
14
|
+
link.title = element['title']
|
15
|
+
link.template = URITemplate.new(element['template']) unless link.href
|
16
|
+
link.raw = element
|
17
|
+
rescue
|
18
|
+
raise "Couldn't parse #{link} into a JRD Link"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Discodactyl # :nodoc:
|
2
|
+
KNOWN_RELS = {
|
3
|
+
'OpenID' => 'http://specs.openid.net/auth/',
|
4
|
+
'OpenID Provider' => 'http://specs.openid.net/auth/2.0/provider',
|
5
|
+
'OpenID Provider' => 'openid2.provider',
|
6
|
+
"Profile" => 'http://webfinger.net/rel/profile-page',
|
7
|
+
"Profile data" => 'http://portablecontacts.net/spec/1.0#me',
|
8
|
+
"Contacts" => 'http://portablecontacts.net/spec/1.0',
|
9
|
+
"describedby" => 'describedby', # from POWDER
|
10
|
+
"Webfinger/LRDD" => 'lrdd'
|
11
|
+
}
|
12
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'active_support/core_ext/object/misc'
|
1
|
+
# require 'active_support/core_ext/object/misc'
|
2
2
|
|
3
3
|
module Discodactyl # :nodoc:
|
4
4
|
# Access to web links stored in HTTP Link header-fields. See also:
|
@@ -14,7 +14,7 @@ module Discodactyl # :nodoc:
|
|
14
14
|
# link[:href] # '/'
|
15
15
|
# link[:rel] # ['http://example.net/foo']
|
16
16
|
def parse(string)
|
17
|
-
|
17
|
+
LinkHeader.new.tap do |params|
|
18
18
|
if string =~ /^<([^>]+)>(.*)$/
|
19
19
|
params[:href] = $1
|
20
20
|
$2.split(/;\s*/).each do |part|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'open-uri'
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'discodactyl/link_header'
|
4
|
+
require 'discodactyl/log'
|
4
5
|
|
5
6
|
module Discodactyl # :nodoc:
|
6
7
|
class ResourceDiscovery
|
@@ -20,6 +21,7 @@ module Discodactyl # :nodoc:
|
|
20
21
|
def get_uris_by_rel(uri, rel, params = {})
|
21
22
|
begin
|
22
23
|
uri = URI.parse(uri.to_s) unless uri.respond_to?('open')
|
24
|
+
Discodactyl.log.debug "Getting uris for uri #{uri.inspect} by rel #{rel.inspect} with params #{params.inspect}" if Discodactyl.log
|
23
25
|
resource = uri.open
|
24
26
|
rescue OpenURI::HTTPError => e
|
25
27
|
status = e.io.status[0] # => 3xx, 4xx, or 5xx
|
@@ -61,9 +63,28 @@ module Discodactyl # :nodoc:
|
|
61
63
|
end
|
62
64
|
end
|
63
65
|
unless uris
|
64
|
-
|
66
|
+
Discodactyl.log.debug("getting jrd host-meta") if Discodactyl.log
|
67
|
+
begin
|
68
|
+
host_meta = Discodactyl::HostMetaJRD.from_uri uri
|
69
|
+
rescue => error
|
70
|
+
Discodactyl.log.debug("Error parsing jrd host-meta: #{error}") if Discodactyl.log
|
71
|
+
end
|
72
|
+
Discodactyl.log.debug("finding uris in jrd host-meta") if Discodactyl.log
|
73
|
+
uris = host_meta.uris_by_rel(rel, params) if host_meta
|
74
|
+
end
|
75
|
+
|
76
|
+
unless uris
|
77
|
+
Discodactyl.log.debug("Getting xrd host-meta") if Discodactyl.log
|
78
|
+
begin
|
79
|
+
host_meta = Discodactyl::HostMeta.from_uri uri
|
80
|
+
rescue => error
|
81
|
+
Discodactyl.log.debug("Error getting xrd host-meta: #{error}") if Discodactyl.log
|
82
|
+
raise
|
83
|
+
end
|
84
|
+
Discodactyl.log.debug("finding uris in host-meta") if Discodactyl.log
|
65
85
|
uris = host_meta.uris_by_rel(rel, params)
|
66
86
|
end
|
87
|
+
Discodactyl.log.debug "URIs: #{uris.inspect}" if Discodactyl.log
|
67
88
|
uris
|
68
89
|
end
|
69
90
|
|
@@ -8,6 +8,7 @@ module XRD # :nodoc:
|
|
8
8
|
class << self
|
9
9
|
def parse(string)
|
10
10
|
raw = Nokogiri::XML(string)
|
11
|
+
Discodactyl.log.debug("parsing xrd: #{raw}") if Discodactyl.log
|
11
12
|
doc = self.new
|
12
13
|
|
13
14
|
doc.raw = raw
|
@@ -29,7 +30,8 @@ module XRD # :nodoc:
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def links_by_rel(rel)
|
32
|
-
linkelems_by_rel(rel).map {|e| Link.parse(e) }
|
33
|
+
# linkelems_by_rel(rel).map {|e| Link.parse(e) }
|
34
|
+
find_all_links_by_rel(rel)
|
33
35
|
end
|
34
36
|
|
35
37
|
def uris_by_rel(rel, params = {})
|
@@ -54,6 +56,10 @@ module XRD # :nodoc:
|
|
54
56
|
def find_link_by_id(link_id)
|
55
57
|
links.find {|link| link.id == link_id}
|
56
58
|
end
|
59
|
+
|
60
|
+
def find_all_links_by_rel(rel)
|
61
|
+
links.find_all {|link| link.rel == rel }
|
62
|
+
end
|
57
63
|
|
58
64
|
def ids
|
59
65
|
links.map(&:id).reject(&:nil?)
|
@@ -62,6 +68,10 @@ module XRD # :nodoc:
|
|
62
68
|
def to_s
|
63
69
|
raw.to_s
|
64
70
|
end
|
71
|
+
|
72
|
+
def rels
|
73
|
+
links.map(&:rel).reject(&:nil?).uniq
|
74
|
+
end
|
65
75
|
|
66
76
|
def generate_tag_uri
|
67
77
|
scheme = 'tag'
|
@@ -70,6 +80,10 @@ module XRD # :nodoc:
|
|
70
80
|
specific = "/xrd/link/#{rand(2**10)}"
|
71
81
|
"#{scheme}:#{authority},#{date}:#{specific}"
|
72
82
|
end
|
83
|
+
|
84
|
+
def subject
|
85
|
+
raw.xpath('/xrd:XRD/xrd:Subject', XMLNS).text
|
86
|
+
end
|
73
87
|
end
|
74
88
|
end
|
75
89
|
end
|
data/lib/discodactyl/xrd/link.rb
CHANGED
@@ -1,26 +1,25 @@
|
|
1
1
|
require 'nokogiri'
|
2
|
-
require 'active_support/core_ext/object/misc'
|
3
2
|
require 'discodactyl/uri_template'
|
4
3
|
|
5
4
|
module Discodactyl # :nodoc:
|
6
5
|
module XRD # :nodoc:
|
7
|
-
class Link
|
6
|
+
class Link < Struct.new(:href, :template, :rel, :title, :type)
|
7
|
+
attr_accessor :raw
|
8
8
|
class << self
|
9
9
|
def parse(element)
|
10
|
-
|
10
|
+
self.new.tap do |link|
|
11
11
|
link.rel = element['rel']
|
12
12
|
link.type = element['type']
|
13
13
|
link.href = element['href']
|
14
|
+
link.title = element['title']
|
14
15
|
link.template = URITemplate.new(element['template']) unless link.href
|
15
16
|
link.raw = element
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
attr_accessor :href, :template, :rel, :type, :raw
|
21
|
-
|
22
21
|
def to_uri(params = {})
|
23
|
-
|
22
|
+
href || template.to_uri(params)
|
24
23
|
end
|
25
24
|
|
26
25
|
def id
|
data/lib/discodactyl.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
require 'discodactyl/acct_uri'
|
2
2
|
require 'discodactyl/host_meta'
|
3
|
+
require 'discodactyl/host_meta_jrd'
|
4
|
+
require 'discodactyl/jrd'
|
5
|
+
require 'discodactyl/known_rels'
|
6
|
+
require 'discodactyl/log'
|
3
7
|
require 'discodactyl/resource_discovery'
|
4
8
|
require 'discodactyl/uri_template'
|
5
9
|
require 'discodactyl/xrd'
|
6
10
|
|
7
11
|
module Discodactyl # :nodoc:
|
8
|
-
VERSION = '0.
|
12
|
+
VERSION = '0.4.1'
|
9
13
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
libdir = File.expand_path('../../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
4
|
+
|
5
|
+
require "test/unit"
|
6
|
+
require "discodactyl/host_meta_jrd"
|
7
|
+
require 'discodactyl/acct_uri'
|
8
|
+
|
9
|
+
class TestHostMetaJRD < Test::Unit::TestCase
|
10
|
+
def test_get_uri_from_host
|
11
|
+
uri = 'host.example'
|
12
|
+
expected = URI.parse 'http://host.example/.well-known/host-meta.json'
|
13
|
+
assert_equal expected, Discodactyl::HostMetaJRD.get_uri_from_uri(uri)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_get_uri_from_http
|
17
|
+
uri = URI.parse 'http://host.example/some/path'
|
18
|
+
expected = URI.parse 'http://host.example/.well-known/host-meta.json'
|
19
|
+
assert_equal expected, Discodactyl::HostMetaJRD.get_uri_from_uri(uri)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_get_uri_from_acct
|
23
|
+
uri = URI.parse 'acct:user@host.example'
|
24
|
+
expected = URI.parse 'http://host.example/.well-known/host-meta.json'
|
25
|
+
assert_equal expected, Discodactyl::HostMetaJRD.get_uri_from_uri(uri)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_from_uri
|
29
|
+
uri = URI.parse 'acct:josephholsten@localhost'
|
30
|
+
assert_equal({"links"=>{"lrdd"=>[{"href"=>"http://localhost/discovery.jrd"}]}}, Discodactyl::HostMetaJRD.from_uri(uri))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_parse
|
34
|
+
json = <<JSON
|
35
|
+
{ "links": {
|
36
|
+
"lrdd": [{
|
37
|
+
"href":"http://host.example/discovery.jrd" }]}}
|
38
|
+
JSON
|
39
|
+
assert_equal({"links"=>{"lrdd"=>[{"href"=>"http://host.example/discovery.jrd"}]}}, Discodactyl::HostMetaJRD.parse(json))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_links_by_rel
|
43
|
+
jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"href"=>"http://host.example/discovery.jrd"}]}}]
|
44
|
+
expected = [Discodactyl::JRD::Link.parse({'href'=>'http://host.example/discovery.jrd', 'rel' => 'lrdd'})]
|
45
|
+
assert_equal(expected, jrd.links_by_rel('lrdd'))
|
46
|
+
end
|
47
|
+
|
48
|
+
# links by rel when links is missing, when rel is missing
|
49
|
+
def test_links_by_rel_when_missing
|
50
|
+
jrd = Discodactyl::HostMetaJRD[{}]
|
51
|
+
assert_equal([], jrd.links_by_rel('lrdd'))
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_uris_by_rel
|
55
|
+
jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"href"=>"http://host.example/discovery.jrd"}]}}]
|
56
|
+
assert_equal(['http://host.example/discovery.jrd'], jrd.uris_by_rel('lrdd'))
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_uris_by_rel_with_template
|
60
|
+
jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"template"=>"http://host.example/{id}"}]}}]
|
61
|
+
assert_equal(['http://host.example/foo'], jrd.uris_by_rel('lrdd', 'id' => 'foo'))
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
libdir = File.expand_path('../../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
4
|
+
testdir = File.expand_path('../../test', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(testdir) unless $LOAD_PATH.include?(testdir)
|
6
|
+
|
7
|
+
require 'test_helper'
|
8
|
+
require 'discodactyl/jrd/document'
|
9
|
+
|
10
|
+
class TestJRDParsing < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@minimal_jrd_string =<<eos
|
13
|
+
{
|
14
|
+
"subject":"http://host.example/"
|
15
|
+
}
|
16
|
+
eos
|
17
|
+
|
18
|
+
# @full_jrd_string =<<eos
|
19
|
+
# {"subject":"http://host.example/","links":{"describedby":[{"href":"http://host.example/endpoint"},{"template":"http://host.example/descriptor?q={%id}"}],"webfinger":[{"href":"http://host.example/endpoint"}],"feed":[{"template":"http://host.example/descriptor?q={%id}"}]}}
|
20
|
+
# eos
|
21
|
+
# <"{\"subject\":\"http://host.example/\",\"links\":{\"describedby\":[{\"href\":\"http://host.example/endpoint\"},{\"template\":\"http://host.example/descriptor?q={%id}\"}],\"webfinger\":[{\"href\":\"http://host.example/endpoint\"}],\"feed\":[{\"template\":\"http://host.example/descriptor?q={%id}\"}]}}\n"> expected but was
|
22
|
+
# <"{\"subject\":\"http://host.example/\",\"links\":{\"webfinger\":[{\"href\":\"http://host.example/endpoint\"}],\"describedby\":[{\"href\":\"http://host.example/endpoint\"},{\"template\":\"http://host.example/descriptor?q={%id}\"}],\"feed\":[{\"template\":\"http://host.example/descriptor?q={%id}\"}]}}">.
|
23
|
+
|
24
|
+
@full_jrd_string =<<eos
|
25
|
+
{"subject":"http://host.example/","links":{"webfinger":[{"href":"http://host.example/endpoint"}],"describedby":[{"href":"http://host.example/endpoint"},{"template":"http://host.example/descriptor?q={%id}"}],"feed":[{"template":"http://host.example/descriptor?q={%id}"}]}}
|
26
|
+
eos
|
27
|
+
|
28
|
+
@raw_link_without_id = '<Link rel="http://oexchange.org/spec/0.8/rel/user-target" type="application/xrd+xml" href="http://www.example.com/linkeater/oexchange.xrd"/>'
|
29
|
+
|
30
|
+
@raw_link_without_id = '{"http://oexchange.org/spec/0.8/rel/user-target":[{"type":"application/xrd+xml", "href":"http://www.example.com/linkeater/oexchange.xrd"}]}'
|
31
|
+
@raw_link_with_id = '{"http://oexchange.org/spec/0.8/rel/user-target":[{"id":"foo","type":"application/xrd+xml", "href":"http://www.example.com/linkeater/oexchange.xrd"}]}'
|
32
|
+
|
33
|
+
@jrd = Discodactyl::JRD::Document.parse(@full_jrd_string)
|
34
|
+
end
|
35
|
+
def test_parse
|
36
|
+
doc = Discodactyl::JRD::Document.parse(@full_jrd_string)
|
37
|
+
assert_not_nil(doc)
|
38
|
+
end
|
39
|
+
def test_parse_links
|
40
|
+
assert_equal(4, @jrd.links.length)
|
41
|
+
end
|
42
|
+
|
43
|
+
# def test_linkelems_by_rel
|
44
|
+
# link_elems = @jrd.linkelems_by_rel 'describedby'
|
45
|
+
#
|
46
|
+
# assert_length(2, link_elems)
|
47
|
+
#
|
48
|
+
# assert_equal 'http://host.example/endpoint', link_elems[0]['href']
|
49
|
+
# assert_equal 'http://host.example/descriptor?q={%id}', link_elems[1]['template']
|
50
|
+
# end
|
51
|
+
|
52
|
+
# def test_linkelems_by_rel_with_multiple_rels
|
53
|
+
# link_elems = @jrd.linkelems_by_rel 'describedby'
|
54
|
+
#
|
55
|
+
# assert_length(2, link_elems)
|
56
|
+
#
|
57
|
+
# assert_equal 'http://host.example/endpoint', link_elems[0]['href']
|
58
|
+
# assert_equal 'http://host.example/descriptor?q={%id}', link_elems[1]['template']
|
59
|
+
# end
|
60
|
+
|
61
|
+
def test_uris_by_rel
|
62
|
+
uris = @jrd.uris_by_rel 'describedby', 'id' => 'bradfitz@gmail.com'
|
63
|
+
|
64
|
+
assert_length(2, uris)
|
65
|
+
|
66
|
+
assert_equal 'http://host.example/endpoint', uris[0]
|
67
|
+
assert_equal 'http://host.example/descriptor?q=bradfitz@gmail.com', uris[1]
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_links_by_rel
|
71
|
+
links = @jrd.links_by_rel('feed')
|
72
|
+
|
73
|
+
assert_length(1, links)
|
74
|
+
expected = Discodactyl::URITemplate.new('http://host.example/descriptor?q={%id}')
|
75
|
+
assert_equal(expected, links[0].template)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_uris_by_rel
|
79
|
+
links = @jrd.uris_by_rel('feed', 'id' => 'dclinton@gmail.com')
|
80
|
+
|
81
|
+
assert_length(1, links)
|
82
|
+
assert_include?('http://host.example/descriptor?q=dclinton@gmail.com', links)
|
83
|
+
end
|
84
|
+
|
85
|
+
# def test_update
|
86
|
+
# jrd_str =<<eos
|
87
|
+
# <?xml version=\"1.0\"?>
|
88
|
+
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
89
|
+
# <Subject>http://host.example/</Subject>
|
90
|
+
# <Link rel="webfinger" href="http://host.example/endpoint"/>
|
91
|
+
# <Link rel="describedby" href="http://host.example/endpoint"/>
|
92
|
+
# <Link rel="feed" template="http://host.example/descriptor?q={%id}"/>
|
93
|
+
# <Link rel="describedby" template="http://host.example/descriptor?q={%id}"/>
|
94
|
+
# <Link href="http://www.example.com/linkeater/oexchange.xrd" rel="http://oexchange.org/spec/0.8/rel/user-target" type="application/xrd+xml"/>
|
95
|
+
# </XRD>
|
96
|
+
# eos
|
97
|
+
# doc = Discodactyl::JRD::Document.parse jrd_str
|
98
|
+
#
|
99
|
+
# link = "<Link rel='http://oexchange.org/spec/0.8/rel/user-target' type='application/xrd+xml' href='updated' />"
|
100
|
+
#
|
101
|
+
# doc.raw.xpath('//xrd:Link',Discodactyl::XRD::XMLNS).after(link)
|
102
|
+
#
|
103
|
+
# expected =<<eos
|
104
|
+
# <?xml version=\"1.0\"?>
|
105
|
+
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
106
|
+
# <Subject>http://host.example/</Subject>
|
107
|
+
# <Link rel="webfinger" href="http://host.example/endpoint"/>
|
108
|
+
# <Link rel="describedby" href="http://host.example/endpoint"/>
|
109
|
+
# <Link rel="feed" template="http://host.example/descriptor?q={%id}"/>
|
110
|
+
# <Link rel="describedby" template="http://host.example/descriptor?q={%id}"/>
|
111
|
+
# <Link href="updated" rel="http://oexchange.org/spec/0.8/rel/user-target" type="application/xrd+xml"/>
|
112
|
+
# </XRD>
|
113
|
+
# eos
|
114
|
+
#
|
115
|
+
# assert_equal expected, doc.to_s
|
116
|
+
# end
|
117
|
+
|
118
|
+
# def test_delete
|
119
|
+
# xrd_str =<<eos
|
120
|
+
# <?xml version=\"1.0\"?>
|
121
|
+
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
122
|
+
# <Subject>http://host.example/</Subject>
|
123
|
+
# <Link xml:id='1' href="http://example.com/" rel="user-target" type="application/xrd+xml"/>
|
124
|
+
# </XRD>
|
125
|
+
# eos
|
126
|
+
# doc = Discodactyl::XRD::Document.parse xrd_str
|
127
|
+
#
|
128
|
+
# link = "<Link rel='http://oexchange.org/spec/0.8/rel/user-target' type='application/xrd+xml' href='updated' />"
|
129
|
+
#
|
130
|
+
# doc.raw.xpath('//xrd:Link',Discodactyl::XRD::XMLNS).after(link)
|
131
|
+
#
|
132
|
+
# expected =<<eos
|
133
|
+
# <?xml version=\"1.0\"?>
|
134
|
+
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
135
|
+
# <Subject>http://host.example/</Subject>
|
136
|
+
# </XRD>
|
137
|
+
# eos
|
138
|
+
#
|
139
|
+
# assert_equal expected, doc.to_s
|
140
|
+
# assert !doc.include?(link)
|
141
|
+
# end
|
142
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discodactyl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 13
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 1
|
10
|
+
version: 0.4.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Joseph Anthony Pasquale Holsten
|
@@ -14,44 +15,50 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-03-14 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: nokogiri
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ~>
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
27
30
|
segments:
|
28
31
|
- 1
|
29
32
|
- 4
|
30
|
-
-
|
31
|
-
version: 1.4.
|
33
|
+
- 2
|
34
|
+
version: 1.4.2
|
32
35
|
type: :runtime
|
33
36
|
version_requirements: *id001
|
34
37
|
- !ruby/object:Gem::Dependency
|
35
38
|
name: actionpack
|
36
39
|
prerelease: false
|
37
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
38
42
|
requirements:
|
39
43
|
- - ~>
|
40
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
41
46
|
segments:
|
42
|
-
- 2
|
43
47
|
- 3
|
44
48
|
- 0
|
45
|
-
|
49
|
+
- 0
|
50
|
+
version: 3.0.0
|
46
51
|
type: :runtime
|
47
52
|
version_requirements: *id002
|
48
53
|
- !ruby/object:Gem::Dependency
|
49
54
|
name: feedzirra
|
50
55
|
prerelease: false
|
51
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
52
58
|
requirements:
|
53
59
|
- - ~>
|
54
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 49
|
55
62
|
segments:
|
56
63
|
- 0
|
57
64
|
- 0
|
@@ -63,16 +70,50 @@ dependencies:
|
|
63
70
|
name: mofo
|
64
71
|
prerelease: false
|
65
72
|
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
66
74
|
requirements:
|
67
75
|
- - ~>
|
68
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 55
|
69
78
|
segments:
|
70
79
|
- 0
|
71
80
|
- 2
|
72
|
-
-
|
73
|
-
version: 0.2.
|
81
|
+
- 16
|
82
|
+
version: 0.2.16
|
74
83
|
type: :runtime
|
75
84
|
version_requirements: *id004
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rr
|
87
|
+
prerelease: false
|
88
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 33
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 10
|
97
|
+
- 11
|
98
|
+
version: 0.10.11
|
99
|
+
type: :development
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: rake
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 49
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
- 8
|
113
|
+
- 7
|
114
|
+
version: 0.8.7
|
115
|
+
type: :development
|
116
|
+
version_requirements: *id006
|
76
117
|
description: "Discodactyl is an experimental toolkit for XRD service discovery documents and related protocols. It includes implementations of XRD URITemplate Link-Patterns, basic site-meta support, HTTP Link header parsing, acct: URIs and a webfinger poking stick."
|
77
118
|
email: joseph@josephholsten.com
|
78
119
|
executables:
|
@@ -85,7 +126,7 @@ extra_rdoc_files:
|
|
85
126
|
- COPYING
|
86
127
|
- INSTALL
|
87
128
|
- NEWS
|
88
|
-
- README
|
129
|
+
- README.rdoc
|
89
130
|
- TODO
|
90
131
|
files:
|
91
132
|
- AUTHORS
|
@@ -95,7 +136,7 @@ files:
|
|
95
136
|
- INSTALL
|
96
137
|
- MANIFEST
|
97
138
|
- NEWS
|
98
|
-
- README
|
139
|
+
- README.rdoc
|
99
140
|
- Rakefile
|
100
141
|
- TODO
|
101
142
|
- bin/webfinger
|
@@ -103,7 +144,13 @@ files:
|
|
103
144
|
- lib/discodactyl.rb
|
104
145
|
- lib/discodactyl/acct_uri.rb
|
105
146
|
- lib/discodactyl/host_meta.rb
|
147
|
+
- lib/discodactyl/host_meta_jrd.rb
|
148
|
+
- lib/discodactyl/jrd.rb
|
149
|
+
- lib/discodactyl/jrd/document.rb
|
150
|
+
- lib/discodactyl/jrd/link.rb
|
151
|
+
- lib/discodactyl/known_rels.rb
|
106
152
|
- lib/discodactyl/link_header.rb
|
153
|
+
- lib/discodactyl/log.rb
|
107
154
|
- lib/discodactyl/resource_discovery.rb
|
108
155
|
- lib/discodactyl/uri_template.rb
|
109
156
|
- lib/discodactyl/xrd.rb
|
@@ -112,6 +159,8 @@ files:
|
|
112
159
|
- test/test_acct_uri.rb
|
113
160
|
- test/test_helper.rb
|
114
161
|
- test/test_host_meta.rb
|
162
|
+
- test/test_host_meta_jrd.rb
|
163
|
+
- test/test_jrd_document.rb
|
115
164
|
- test/test_link_header.rb
|
116
165
|
- test/test_resource_discovery.rb
|
117
166
|
- test/test_uri_template.rb
|
@@ -128,27 +177,31 @@ rdoc_options:
|
|
128
177
|
- --title
|
129
178
|
- Discodactyl Documentation
|
130
179
|
- --main
|
131
|
-
- README
|
180
|
+
- README.rdoc
|
132
181
|
require_paths:
|
133
182
|
- lib
|
134
183
|
required_ruby_version: !ruby/object:Gem::Requirement
|
184
|
+
none: false
|
135
185
|
requirements:
|
136
186
|
- - ">="
|
137
187
|
- !ruby/object:Gem::Version
|
188
|
+
hash: 3
|
138
189
|
segments:
|
139
190
|
- 0
|
140
191
|
version: "0"
|
141
192
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
142
194
|
requirements:
|
143
195
|
- - ">="
|
144
196
|
- !ruby/object:Gem::Version
|
197
|
+
hash: 3
|
145
198
|
segments:
|
146
199
|
- 0
|
147
200
|
version: "0"
|
148
201
|
requirements: []
|
149
202
|
|
150
203
|
rubyforge_project:
|
151
|
-
rubygems_version: 1.
|
204
|
+
rubygems_version: 1.5.0
|
152
205
|
signing_key:
|
153
206
|
specification_version: 3
|
154
207
|
summary: Discodactyl is an experimental toolkit for XRD service discovery documents and related protocols
|
@@ -156,6 +209,8 @@ test_files:
|
|
156
209
|
- test/test_acct_uri.rb
|
157
210
|
- test/test_helper.rb
|
158
211
|
- test/test_host_meta.rb
|
212
|
+
- test/test_host_meta_jrd.rb
|
213
|
+
- test/test_jrd_document.rb
|
159
214
|
- test/test_link_header.rb
|
160
215
|
- test/test_resource_discovery.rb
|
161
216
|
- test/test_uri_template.rb
|