discodactyl 0.3.0 → 0.4.1
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/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
|