discodactyl 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/MANIFEST CHANGED
@@ -12,6 +12,8 @@ bin/webfinger
12
12
  discodactyl.gemspec
13
13
  lib/discodactyl.rb
14
14
  lib/discodactyl/acct_uri.rb
15
+ lib/discodactyl/cli.rb
16
+ lib/discodactyl/cli/format.rb
15
17
  lib/discodactyl/host_meta.rb
16
18
  lib/discodactyl/host_meta_jrd.rb
17
19
  lib/discodactyl/jrd.rb
@@ -30,6 +32,7 @@ test/test_helper.rb
30
32
  test/test_host_meta.rb
31
33
  test/test_host_meta_jrd.rb
32
34
  test/test_jrd_document.rb
35
+ test/test_known_accounts.rb
33
36
  test/test_link_header.rb
34
37
  test/test_resource_discovery.rb
35
38
  test/test_uri_template.rb
data/NEWS CHANGED
@@ -1,3 +1,34 @@
1
+ === 0.5.0 / 2010-11-17
2
+
3
+ Brought Out of Retirement!
4
+
5
+ Now using ISC licence instead of AGPL
6
+
7
+ New Features
8
+
9
+ * Support pluggable formatters for rel types
10
+
11
+ Breaking Changes
12
+
13
+ * Discodactyl::KNOWN_RELS has switched its keys and values
14
+
15
+ Bug Fixes
16
+
17
+ * Replace mofo with prism
18
+
19
+ === 0.4.1 / 2011-03-14
20
+
21
+ Bug Fixes
22
+
23
+ * Handle missing JRD hostmeta
24
+
25
+ === 0.4.0 / 2010-11-17
26
+
27
+ New Features
28
+
29
+ * JRD parsing, querying
30
+ * Support many known rel formats
31
+
1
32
  === 0.3.0 / 2010-07-08
2
33
 
3
34
  New Features
@@ -1,14 +1,15 @@
1
1
  = Discodactyl
2
2
 
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
3
+ {<img src="https://secure.travis-ci.org/josephholsten/discodactyl.png" alt="Build Status" />}[http://travis-ci.org/josephholsten/discodactyl] | {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/josephholsten/discodactyl] | {<img src="https://gemnasium.com/josephholsten/discodactyl.png" alt="Dependency Status" />}[https://gemnasium.com/josephholsten/discodactyl]
4
+
5
+ {Docs}[http://rdoc.info/projects/josephholsten/discodactyl] | {Code}[https:/github.com/josephholsten/discodactyl] | {Bugs}[http://github.com/josephholsten/discodactyl/issues]
8
6
 
9
7
  == DESCRIPTION:
10
8
 
11
- 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.
9
+ Discodactyl is an experimental toolkit for XRD service discovery
10
+ documents and related protocols. It includes implementations of XRD
11
+ URITemplate Link-Patterns, basic site-meta support, HTTP Link header
12
+ parsing, acct: URIs and a webfinger poking stick.
12
13
 
13
14
  == FEATURES/PROBLEMS:
14
15
 
@@ -18,9 +19,10 @@ Discodactyl is an experimental toolkit for XRD service discovery documents and r
18
19
  * HTTP Link header parsing.
19
20
  * acct: URI parsing.
20
21
  * Minimal URI Template parsing and application.
21
- * Probably filled with bugs. Don't forget your bug powder.
22
22
  * JRD parsing, querying.
23
- * Yahoo 'webfinger' doesn't work. Sadly, they need to update their format to the most recent one.
23
+ * Probably filled with bugs. Don't forget your bug powder.
24
+ * Yahoo 'webfinger' doesn't work. Sadly, they need to update their
25
+ format to the most recent one.
24
26
 
25
27
  == SYNOPSIS:
26
28
 
@@ -46,9 +48,9 @@ For ruby mongers:
46
48
  == REQUIREMENTS:
47
49
 
48
50
  * nokogiri 1.4
49
- * actionpack 2.3
51
+ * actionpack 3.0
50
52
  * feedzirra 0.0.23
51
- * mofo 0.2
53
+ * prism 0.1
52
54
 
53
55
  == INSTALLING:
54
56
 
@@ -56,22 +58,17 @@ See the INSTALL file for details.
56
58
 
57
59
  == LICENSE:
58
60
 
59
- This software is also available in a permissive license. Please contact Joseph Holsten <joseph@josephholsten.com> for more information.
60
-
61
- (The GNU Affero General Public License)
62
-
63
- Copyright (c) 2009, 2010, 2011 Joseph Anthony Pasquale Holsten
64
-
65
- This program is free software: you can redistribute it and/or modify
66
- it under the terms of the GNU Affero General Public License as published by
67
- the Free Software Foundation, either version 3 of the License, or
68
- (at your option) any later version.
69
61
 
70
- This program is distributed in the hope that it will be useful,
71
- but WITHOUT ANY WARRANTY; without even the implied warranty of
72
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73
- GNU Affero General Public License for more details.
62
+ Copyright (c) 2009, 2010, 2011, 2012 Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
74
63
 
75
- You should have received a copy of the GNU Affero General Public License
76
- along with this program. If not, see <http://www.gnu.org/licenses/>.
64
+ Permission to use, copy, modify, and/or distribute this software for
65
+ any purpose with or without fee is hereby granted, provided that the
66
+ above copyright notice and this permission notice appear in all copies.
77
67
 
68
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
69
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
70
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
71
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
72
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
73
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
74
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env rake
2
2
 
3
+ require 'bundler'
4
+ Bundler.setup
5
+
3
6
  require "rake/testtask"
4
7
  Rake::TestTask.new do |test|
5
8
  test.test_files = Dir['test/**/test_*.rb']
data/TODO CHANGED
@@ -25,16 +25,6 @@ Reference Specs
25
25
  * link header http://tools.ietf.org/html/rfc5988
26
26
  * versioning-rels http://tools.ietf.org/html/rfc5829
27
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
28
  other clients
39
29
  * webfingerclient-dclinton.appspot.com/
40
30
  * webfinger.org/lookup/darron@froese.org
@@ -3,13 +3,14 @@ libdir = File.expand_path('../../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
4
4
 
5
5
  require 'discodactyl'
6
+ require 'discodactyl/cli'
6
7
  require 'open-uri'
7
8
  require 'action_view'
8
- require 'mofo'
9
+ require 'prism'
9
10
  require 'feedzirra'
10
11
  require 'logger'
11
12
 
12
- log = Logger.new(STDOUT)
13
+ log = Logger.new(STDERR)
13
14
  Discodactyl.log = log
14
15
 
15
16
  if ARGV.length == 0
@@ -76,32 +77,13 @@ else
76
77
  log.warn("Disco doc didn't list a subject. Assuming everything is well.")
77
78
  end
78
79
 
79
- hcard_uri = disco.uris_by_rel('http://microformats.org/profile/hcard').first
80
- hcard = hCard.find(:first => hcard_uri) rescue
81
- if hcard
82
- puts "Name: #{hcard.fn.gsub(/\s+/, ' ')}" if hcard.properties.include?('fn')
83
- puts "Title: #{hcard.title}" if hcard.properties.include?('title')
84
- puts "Organization: #{hcard.org}" if hcard.properties.include?('org')
85
- end
86
-
87
80
  links_with_titles = disco.links.select{|l| l.title.present? }
88
81
  links_with_titles.each do |link|
89
82
  puts "#{link.title}: #{link.to_uri}"
90
83
  end
91
84
 
92
- Discodactyl::KNOWN_RELS.each do |name, rel|
85
+ Discodactyl::KNOWN_RELS.each do |rel, name|
93
86
  uri = disco.uris_by_rel(rel).first
94
- puts "#{name}: #{uri}" if uri
95
- end
96
-
97
- activities = disco.uris_by_rel('http://schemas.google.com/g/2010#updates-from').first
98
- if activities
99
- feed = Feedzirra::Feed.fetch_and_parse(activities)
100
- entry = feed.entries.first
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
87
+ formatter = Discodactyl::CLI::Format.for_rel(rel)
88
+ formatter.call(uri, STDOUT)
107
89
  end
@@ -16,10 +16,10 @@ Gem::Specification.new do |spec|
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.2'
20
- spec.add_runtime_dependency 'actionpack', '~>3.0.0'
21
- spec.add_runtime_dependency 'feedzirra', '~>0.0.23'
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'
19
+ spec.add_runtime_dependency 'nokogiri', '>= 1.4.2'
20
+ spec.add_runtime_dependency 'actionpack', '>= 3.0.8'
21
+ spec.add_runtime_dependency 'feedzirra', '>= 0.0.22'
22
+ spec.add_runtime_dependency 'prism', '>= 0.1.0'
23
+ spec.add_development_dependency 'mocha', '>= 0.12.7'
24
+ spec.add_development_dependency 'rake', '>= 0.9.2.2'
25
25
  end
@@ -9,5 +9,5 @@ require 'discodactyl/uri_template'
9
9
  require 'discodactyl/xrd'
10
10
 
11
11
  module Discodactyl # :nodoc:
12
- VERSION = '0.4.1'
12
+ VERSION = '0.5.0'
13
13
  end
@@ -0,0 +1 @@
1
+ require 'discodactyl/cli/format'
@@ -0,0 +1,69 @@
1
+ module Discodactyl # :nodoc
2
+ module CLI # :nodoc
3
+ # Formatting helpers for various rels
4
+ class Format
5
+ def self.for_rel(rel)
6
+ case rel
7
+ when 'http://microformats.org/profile/hcard' then
8
+ lambda {|uri, io| Discodactyl::CLI::Format.hcard_from_uri(uri, io) }
9
+ when 'http://schemas.google.com/g/2010#updates-from' then
10
+ lambda {|uri, io| Discodactyl::CLI::Format.activities_from_uri(uri, io) }
11
+ else
12
+ if name = Discodactyl::KNOWN_RELS[rel]
13
+ lambda {|uri, io| io.puts "#{name}: #{uri}" if uri }
14
+ else
15
+ lambda {|uri, io| }
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.hcard_adr(adr)
21
+ segments = []
22
+ segments << adr.street_address if adr.properties.include?(:street_address)
23
+ segments << adr.locality if adr.properties.include?(:locality)
24
+ segments << adr.region if adr.properties.include?(:region)
25
+ segments << adr.postal_code if adr.properties.include?(:postal_code)
26
+ segments << adr.country_name if adr.properties.include?(:country_name)
27
+ segments.join(' ')
28
+ end
29
+
30
+ def self.hcard_from_uri(uri, io)
31
+ begin
32
+ Discodactyl.log.debug("hCard lookup for #{uri}") if Discodactyl.log
33
+ if hcards = Prism.find(uri, :hcard)
34
+ hcards.each do |hcard|
35
+ if hcard
36
+ io << "Name: #{hcard.fn.gsub(/\s+/, ' ')}\n" if hcard.properties.include?(:fn)
37
+ io << "Title: #{hcard.title}\n" if hcard.properties.include?(:title)
38
+ io << "Organization: #{hcard.org}\n" if hcard.properties.include?(:org)
39
+ io << "Address: #{hcard_adr(hcard.adr)}\n" if hcard.properties.include?(:adr)
40
+ end
41
+ end
42
+ end
43
+ rescue RuntimeError => e
44
+ Discodactyl.log.warn(e.message) if Discodactyl.log
45
+ Discodactyl.log.debug(e) if Discodactyl.log
46
+ end
47
+ end
48
+
49
+ def self.activities_from_uri(uri, io)
50
+ Discodactyl.log.debug("Activity feed lookup for #{uri}") if Discodactyl.log
51
+ begin
52
+ if uri && (feed = Feedzirra::Feed.fetch_and_parse(uri)) && feed.respond_to?(:entries)
53
+ Array(feed.entries).each do |entry|
54
+ include ActionView::Helpers::DateHelper
55
+ silence_warnings do
56
+ io.puts "Status: #{Loofah::Helpers.strip_tags(entry.content)} #{time_ago_in_words(entry.published)} ago"
57
+ end
58
+ end
59
+ else
60
+ Discodactyl.log.debug("Failed activity feed lookup with uri: #{uri.inspect} feed: #{feed.inspect}") if Discodactyl.log
61
+ end
62
+ rescue
63
+ Discodactyl.log.warn($!) if Discodactyl.log
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -1,12 +1,14 @@
1
1
  module Discodactyl # :nodoc:
2
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'
3
+ 'http://microformats.org/profile/hcard' => 'hcard',
4
+ 'http://specs.openid.net/auth/' => 'OpenID',
5
+ 'http://specs.openid.net/auth/2.0/provider' => 'OpenID Provider',
6
+ 'openid2.provider' => 'OpenID Provider',
7
+ 'http://webfinger.net/rel/profile-page' => 'Profile',
8
+ 'http://portablecontacts.net/spec/1.0#me' => 'Profile data',
9
+ 'http://portablecontacts.net/spec/1.0' => 'Contacts',
10
+ 'describedby' => 'describedby', # from POWDER
11
+ 'lrdd' => 'Webfinger/LRDD',
12
+ 'http://schemas.google.com/g/2010#updates-from' => 'activities'
11
13
  }
12
- end
14
+ end
@@ -1,4 +1,6 @@
1
1
  require "test/unit"
2
+ require "mocha"
3
+
2
4
  module Test::Unit::Assertions
3
5
  def assert_length(expected, enum, message = nil)
4
6
  message = build_message message, '<?> is not length <?>', enum, expected
@@ -10,8 +12,3 @@ module Test::Unit::Assertions
10
12
  assert enum.include?(atom), message
11
13
  end
12
14
  end
13
-
14
- class Test::Unit::TestCase
15
- require 'rr'
16
- include RR::Adapters::TestUnit
17
- end
@@ -1,12 +1,22 @@
1
1
  #!/usr/bin/env ruby -w
2
2
  libdir = File.expand_path('../../lib', __FILE__)
3
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)
4
6
 
5
- require "test/unit"
6
- require "discodactyl/host_meta_jrd"
7
+ require 'test/unit'
8
+ require 'test_helper'
9
+ require 'discodactyl/host_meta_jrd'
7
10
  require 'discodactyl/acct_uri'
8
11
 
9
12
  class TestHostMetaJRD < Test::Unit::TestCase
13
+ def setup
14
+ @json = <<JSON
15
+ { "links": {
16
+ "lrdd": [{
17
+ "href":"http://host.example/discovery.jrd" }]}}
18
+ JSON
19
+ end
10
20
  def test_get_uri_from_host
11
21
  uri = 'host.example'
12
22
  expected = URI.parse 'http://host.example/.well-known/host-meta.json'
@@ -27,20 +37,16 @@ class TestHostMetaJRD < Test::Unit::TestCase
27
37
 
28
38
  def test_from_uri
29
39
  uri = URI.parse 'acct:josephholsten@localhost'
30
- assert_equal({"links"=>{"lrdd"=>[{"href"=>"http://localhost/discovery.jrd"}]}}, Discodactyl::HostMetaJRD.from_uri(uri))
40
+ URI::HTTP.any_instance.stubs(:open).returns(StringIO.new(@json))
41
+ assert_equal({'links'=>{'lrdd'=>[{'href'=>'http://host.example/discovery.jrd'}]}}, Discodactyl::HostMetaJRD.from_uri(uri))
31
42
  end
32
43
 
33
44
  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))
45
+ assert_equal({'links'=>{'lrdd'=>[{'href'=>'http://host.example/discovery.jrd'}]}}, Discodactyl::HostMetaJRD.parse(@json))
40
46
  end
41
47
 
42
48
  def test_links_by_rel
43
- jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"href"=>"http://host.example/discovery.jrd"}]}}]
49
+ jrd = Discodactyl::HostMetaJRD[{'links'=>{'lrdd'=>[{'href'=>'http://host.example/discovery.jrd'}]}}]
44
50
  expected = [Discodactyl::JRD::Link.parse({'href'=>'http://host.example/discovery.jrd', 'rel' => 'lrdd'})]
45
51
  assert_equal(expected, jrd.links_by_rel('lrdd'))
46
52
  end
@@ -52,12 +58,12 @@ JSON
52
58
  end
53
59
 
54
60
  def test_uris_by_rel
55
- jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"href"=>"http://host.example/discovery.jrd"}]}}]
61
+ jrd = Discodactyl::HostMetaJRD[{'links'=>{'lrdd'=>[{'href'=>'http://host.example/discovery.jrd'}]}}]
56
62
  assert_equal(['http://host.example/discovery.jrd'], jrd.uris_by_rel('lrdd'))
57
63
  end
58
64
 
59
65
  def test_uris_by_rel_with_template
60
- jrd = Discodactyl::HostMetaJRD[{"links"=>{"lrdd"=>[{"template"=>"http://host.example/{id}"}]}}]
66
+ jrd = Discodactyl::HostMetaJRD[{'links'=>{'lrdd'=>[{'template'=>'http://host.example/{id}'}]}}]
61
67
  assert_equal(['http://host.example/foo'], jrd.uris_by_rel('lrdd', 'id' => 'foo'))
62
68
  end
63
69
  end
File without changes
@@ -0,0 +1,73 @@
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
+
7
+ class TestKnownAccounts < Test::Unit::TestCase
8
+
9
+ def test_dclinton
10
+ expected =<<EOF
11
+ OpenID Provider: http://www.google.com/profiles/dclinton
12
+ Profile: http://www.google.com/profiles/dclinton
13
+ Profile data: http://www-opensocial.googleusercontent.com/api/people/117377434815709898403/
14
+ Contacts: http://www-opensocial.googleusercontent.com/api/people/
15
+ describedby: http://www.google.com/profiles/dclinton
16
+ EOF
17
+ assert_equal expected, `bin/webfinger dclinton@gmail.com`
18
+ end
19
+
20
+ def test_romeda
21
+ expected =<<EOF
22
+ OpenID Provider: http://www.google.com/profiles/romeda
23
+ Profile: http://www.google.com/profiles/romeda
24
+ Profile data: http://www-opensocial.googleusercontent.com/api/people/113651174506128852447/
25
+ Contacts: http://www-opensocial.googleusercontent.com/api/people/
26
+ describedby: http://www.google.com/profiles/romeda
27
+ EOF
28
+ assert_equal expected, `bin/webfinger romeda@gmail.com`
29
+ end
30
+
31
+ def test_bradfitz
32
+ expected =<<EOF
33
+ OpenID Provider: http://www.google.com/profiles/bradfitz
34
+ Profile: http://www.google.com/profiles/bradfitz
35
+ Profile data: http://www-opensocial.googleusercontent.com/api/people/115863474911002159675/
36
+ Contacts: http://www-opensocial.googleusercontent.com/api/people/
37
+ describedby: http://www.google.com/profiles/bradfitz
38
+ EOF
39
+ assert_equal expected, `bin/webfinger bradfitz@gmail.com`
40
+ end
41
+
42
+ def test_willmeyer
43
+ expected =<<EOF
44
+ describedby: http://www.google.com/profiles/willmeyer
45
+ EOF
46
+ assert_equal expected, `bin/webfinger will@willmeyer.com`
47
+ end
48
+
49
+ def test_josephholsten
50
+ expected =<<EOF
51
+ Name: Joseph Anthony Pasquale Holsten
52
+ Address: 5813 East 64th Place Tulsa Oklahoma 74136-2132 USA
53
+ OpenID Provider: https://www.myopenid.com/server
54
+ Profile: http://josephholsten.com
55
+ describedby: http://josephholsten.com
56
+ EOF
57
+ assert_equal expected, `bin/webfinger joseph@josephholsten.com`
58
+ end
59
+
60
+ # Yahoo webfinger causes my ruby to segfault!
61
+ # def test_gffletch
62
+ # expected =<<EOF
63
+ # assert_equal expected, `bin/webfinger dclinton@yahoo.com`
64
+ # assert_equal expected, `bin/webfinger beestage@yahoo.com`
65
+ # end
66
+
67
+ # AOL webfinger now dies at http://www.aol.com/.well-known/host-meta with 503
68
+ # RIP
69
+ # def test_gffletch
70
+ # expected =<<EOF
71
+ # assert_equal expected, `bin/webfinger gffletch@aol.com`
72
+ # end
73
+ end