incubator-heraldry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ket...@apache.org
Subject svn commit: r463001 [1/2] - in /incubator/heraldry/libraries/ruby/yadis: ./ trunk/ trunk/admin/ trunk/examples/ trunk/lib/ trunk/lib/yadis/ trunk/test/ trunk/test/data/
Date Wed, 11 Oct 2006 22:17:08 GMT
Author: keturn
Date: Wed Oct 11 15:17:05 2006
New Revision: 463001

URL: http://svn.apache.org/viewvc?view=rev&rev=463001
Log:
Initial import of Ruby Yadis libraries from JanRain.

Previous development history may be found in the darcs repository at
http://www.openidenabled.com/resources/repos/ruby/yadis/

Added:
    incubator/heraldry/libraries/ruby/yadis/
    incubator/heraldry/libraries/ruby/yadis/trunk/   (with props)
    incubator/heraldry/libraries/ruby/yadis/trunk/COPYING
    incubator/heraldry/libraries/ruby/yadis/trunk/INSTALL
    incubator/heraldry/libraries/ruby/yadis/trunk/README
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs   (with props)
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/darcs-ignore
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms   (with props)
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/library-name
    incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release   (with props)
    incubator/heraldry/libraries/ruby/yadis/trunk/examples/
    incubator/heraldry/libraries/ruby/yadis/trunk/examples/openid.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/gemspec
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/fetcher.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/htmltokenizer.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/manager.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/parsehtml.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/service.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrds.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xri.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrires.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/yadis.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/setup.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/test/
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi_uri.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian_priority.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brianellin.mylid.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/index.html
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/index_xrds.html
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/index_yadis.html
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/keturn.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/manifest.txt
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/proxy-june1.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/data/weirdver.xrds
    incubator/heraldry/libraries/ruby/yadis/trunk/test/runtests.rb   (with props)
    incubator/heraldry/libraries/ruby/yadis/trunk/test/test_discovery.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/test/test_parse.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/test/test_xrds.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/test/test_xri.rb
    incubator/heraldry/libraries/ruby/yadis/trunk/test/test_yadis.rb

Propchange: incubator/heraldry/libraries/ruby/yadis/trunk/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Oct 11 15:17:05 2006
@@ -0,0 +1 @@
+_darcs

Added: incubator/heraldry/libraries/ruby/yadis/trunk/COPYING
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/COPYING?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/COPYING (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/COPYING Wed Oct 11 15:17:05 2006
@@ -0,0 +1,10 @@
+Copyright (c) 2006, JanRain, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+    * Neither the name of the JanRain, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file

Added: incubator/heraldry/libraries/ruby/yadis/trunk/INSTALL
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/INSTALL?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/INSTALL (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/INSTALL Wed Oct 11 15:17:05 2006
@@ -0,0 +1,22 @@
+= Ruby YADIS Library Installation
+
+== Installation
+
+Unpack the archive and run setup.rb (you may need to be root)
+
+ ruby setup.rb
+
+setup.rb installs the library into your system ruby.  If don't want to
+add yadis to you system ruby, make sure to add the *lib* directory of
+the extracted tarball to your RUBYLIB environment variable.
+
+Make sure everything installed ok:
+ $> irb
+ irb(main):001:0> require "yadis"
+ => true
+
+== Run the test suite
+
+Go into the test directory and execute the *runtests.rb* script.
+
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/README
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/README?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/README (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/README Wed Oct 11 15:17:05 2006
@@ -0,0 +1,22 @@
+=Ruby Yadis
+
+A Ruby library for performing Yadis service discovery.
+
+Yadis Specification details:
+
+* http://yadis.org
+* http://www.openidenabled.com/yadis/yadis-notes/
+
+Please see the INSTALL, and have a look at the YADIS interface in yadis/yadis.rb
+
+==Authors
+Brian Ellin.  brian -at- janrain -dot- com
+JanRain, Inc.  http://www.janrain.com/
+
+Eugene Eric Kim.  eekim -at- blueoxen -dot- com
+Blue Oxen Associates.  http://www.blueoxen.com/
+
+
+
+
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs Wed Oct 11 15:17:05 2006
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+#
+# Build the HTML documentation 
+#
+# Usage:
+#  build-docs
+#
+# Must be run from the base of the repository
+# Add files you'd like to be in the docs to RDOC_FILES
+
+RDOC_FILES="README INSTALL COPYING lib/yadis/yadis.rb lib/yadis/parsehtml.rb lib/yadis/xrds.rb lib/yadis/fetcher.rb"
+MAIN=README
+rdoc --main="$MAIN" $RDOC_FILES
\ No newline at end of file

Propchange: incubator/heraldry/libraries/ruby/yadis/trunk/admin/build-docs
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/heraldry/libraries/ruby/yadis/trunk/admin/darcs-ignore
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/admin/darcs-ignore?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/admin/darcs-ignore (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/admin/darcs-ignore Wed Oct 11 15:17:05 2006
@@ -0,0 +1,36 @@
+# Boring file regexps:
+\.hi$
+\.o$
+\.o\.cmd$
+# *.ko files aren't boring by default because they might
+# be Korean translations rather than kernel modules.
+# \.ko$
+\.ko\.cmd$
+\.mod\.c$
+(^|/)\.tmp_versions($|/)
+(^|/)CVS($|/)
+(^|/)RCS($|/)
+~$
+#(^|/)\.[^/]
+(^|/)_darcs($|/)
+\.bak$
+\.BAK$
+\.orig$
+(^|/)vssver\.scc$
+\.swp$
+(^|/)MT($|/)
+(^|/)\{arch\}($|/)
+(^|/).arch-ids($|/)
+(^|/),
+\.class$
+\.prof$
+(^|/)\.DS_Store$
+(^|/)BitKeeper($|/)
+(^|/)ChangeSet($|/)
+(^|/)\.svn($|/)
+\.py[co]$
+\#
+\.cvsignore$
+(^|/)Thumbs\.db$
+^doc($|/)
+^CHANGELOG$
\ No newline at end of file

Added: incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms Wed Oct 11 15:17:05 2006
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+chmod +x admin/prepare-release admin/build-docs admin/fixperms test/runtests.rb

Propchange: incubator/heraldry/libraries/ruby/yadis/trunk/admin/fixperms
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/heraldry/libraries/ruby/yadis/trunk/admin/library-name
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/admin/library-name?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/admin/library-name (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/admin/library-name Wed Oct 11 15:17:05 2006
@@ -0,0 +1 @@
+ruby-yadis

Added: incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release Wed Oct 11 15:17:05 2006
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Prepare this repository for release
+#
+# required tools:
+#  rdoc
+#  darcs
+
+set -e
+
+HERE=$(readlink --canonicalize $(dirname "$0"))
+ROOT=$(dirname "$HERE")
+
+cd "$ROOT"
+echo $ROOT
+
+# set permissions
+bash ./admin/fixperms
+
+# build documentation
+./admin/build-docs
+
+# build changelog
+darcs changes --from-tag . --summary > CHANGELOG
+

Propchange: incubator/heraldry/libraries/ruby/yadis/trunk/admin/prepare-release
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/heraldry/libraries/ruby/yadis/trunk/examples/openid.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/examples/openid.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/examples/openid.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/examples/openid.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,27 @@
+# example of finding an OpenID server using YADIS
+
+require 'yadis'
+
+# Want to verify server certificates for https?
+# Visit http://curl.haxx.se/docs/caextract.html and uncomment:
+# YADIS.ca_path = '/path/to/cacert.pem'
+
+url = 'http://brianellin.com/'
+puts "Looking for servers for #{url}\n"
+
+yadis = YADIS.discover(url)
+openid_filter = Proc.new do |service|
+  service.service_types.member?('http://openid.net/signon/1.0') ? service : nil
+end
+
+if yadis.nil?
+  puts 'No XRDS found.'
+else
+  services = yadis.filter_services(openid_filter)
+  if services.length > 0
+    services.each {|s| puts "OpenID server found: #{s.uri}"}
+  else
+    puts 'No OpenID servers found.'  
+  end
+end
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/gemspec
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/gemspec?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/gemspec (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/gemspec Wed Oct 11 15:17:05 2006
@@ -0,0 +1,19 @@
+require 'rubygems'
+
+SPEC = Gem::Specification.new do |s|
+  s.name = `cat admin/library-name`.strip
+  s.version = `darcs changes --tags= | awk '$1 == "tagged" { print $2 }' | head -n 1`.strip
+  s.author = 'Brian Ellin (JanRain, Inc), Eugene Eric Kim (Blue Oxen Associates)'
+  s.email = 'brian@janrian.com, eekim@blueoxen.com'
+  s.homepage = 'http://www.openidenabled.com/yadis/libraries/ruby'
+  s.platform = Gem::Platform::RUBY
+  s.summary = 'A library for performing Yadis service discovery'
+  files = Dir.glob("{examples,lib,test}/**/*")
+  s.files = files.delete_if {|f| f.include?('_darcs') || f.include?('admin')}
+  s.require_path = 'lib'
+  s.autorequire  = 'yadis'
+  s.test_file = 'test/runtests.rb'
+  s.has_rdoc = true
+  s.extra_rdoc_files = ['README','INSTALL','COPYING']
+  s.rdoc_options << '--main' << 'README'
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,8 @@
+require 'yadis/yadis'
+require 'yadis/xrds'
+require 'yadis/service'
+require 'yadis/parsehtml'
+require 'yadis/fetcher'
+require 'yadis/manager'
+require 'yadis/xri'
+require 'yadis/xrires'

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/fetcher.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/fetcher.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/fetcher.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/fetcher.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,80 @@
+require "uri"
+
+begin
+  require "net/https"
+rescue LoadError
+  HAS_OPENSSL_ = false
+  require 'net/http'
+else  
+  HAS_OPENSSL_ = true
+end
+
+class NetHTTPFetcher
+    
+  attr_accessor :ca_path
+  
+  def initialize(read_timeout=20, open_timeout=20)
+    @read_timeout = read_timeout
+    @open_timeout = open_timeout
+    @ca_path = nil
+  end
+    
+  def get(url, params = nil)    
+    resp, final_url = do_get(url, params)
+    if resp.nil?
+      nil
+    else
+      [final_url, resp]
+    end
+  end
+  
+  protected
+    
+    # return a Net::HTTP object ready for use    
+    def get_http_obj(uri)
+      http = Net::HTTP.new(uri.host, uri.port)
+      http.read_timeout = @read_timeout
+      http.open_timeout = @open_timeout
+
+      if uri.scheme == 'https'        
+        if HAS_OPENSSL_
+          http.use_ssl = true
+          if @ca_path
+            http.ca_file = @ca_path
+            http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+          else
+            http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+            STDERR.puts("Warning: fetching over https without verifying server certificate")
+          end
+        else
+          STDERR.puts('Warning: trying to fetch HTTPS URL without OpenSSL support')
+        end
+      end
+
+      return http
+    end
+    
+    # do a GET following redirects limit deep    
+    def do_get(url, params, limit=5)
+      if limit == 0
+        return nil
+      end
+      begin
+        uri = URI.parse(url)
+        http = get_http_obj(uri)
+        resp = http.request_get(uri.request_uri, params)
+      rescue
+        nil
+      else
+        case resp
+        when Net::HTTPSuccess
+          return [resp, URI.parse(url).to_s]
+        when Net::HTTPRedirection
+          return do_get(resp["location"], params, limit-1)
+        else
+          return nil
+        end
+      end
+    end
+
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/htmltokenizer.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/htmltokenizer.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/htmltokenizer.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/htmltokenizer.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,355 @@
+# = HTMLTokenizer
+#
+# Author::    Ben Giddings  (mailto:bg-rubyforge@infofiend.com)
+# Copyright:: Copyright (c) 2004 Ben Giddings
+# License::   Distributes under the same terms as Ruby
+#
+#
+# This is a partial port of the functionality behind Perl's TokeParser
+# Provided a page it progressively returns tokens from that page
+#
+# $Id: htmltokenizer.rb,v 1.7 2005/06/07 21:05:53 merc Exp $
+
+#
+# A class to tokenize HTML.
+#
+# Example:
+#
+#   page = "<HTML>
+#   <HEAD>
+#   <TITLE>This is the title</TITLE>
+#   </HEAD>
+#    <!-- Here comes the <a href=\"missing.link\">blah</a>
+#    comment body
+#     -->
+#    <BODY>
+#      <H1>This is the header</H1>
+#      <P>
+#        This is the paragraph, it contains
+#        <a href=\"link.html\">links</a>,
+#        <img src=\"blah.gif\" optional alt='images
+#        are
+#        really cool'>.  Ok, here is some more text and
+#        <A href=\"http://another.link.com/\" target=\"_blank\">another link</A>.
+#      </P>
+#    </body>
+#    </HTML>
+#    "
+#    toke = HTMLTokenizer.new(page)
+#
+#    assert("<h1>" == toke.getTag("h1", "h2", "h3").to_s.downcase)
+#    assert(HTMLTag.new("<a href=\"link.html\">") == toke.getTag("IMG", "A"))
+#    assert("links" == toke.getTrimmedText)
+#    assert(toke.getTag("IMG", "A").attr_hash['optional'])
+#    assert("_blank" == toke.getTag("IMG", "A").attr_hash['target'])
+#
+class HTMLTokenizer
+  @@version = 1.0
+
+  # Get version of HTMLTokenizer lib
+  def self.version
+    @@version
+  end
+
+  attr_reader :page
+
+  # Create a new tokenizer, based on the content, used as a string.
+  def initialize(content)
+    @page = content.to_s
+    @cur_pos = 0
+  end
+
+  # Reset the parser, setting the current position back at the stop
+  def reset
+    @cur_pos = 0
+  end
+
+  # Look at the next token, but don't actually grab it
+  def peekNextToken
+    if @cur_pos == @page.length then return nil end
+
+    if ?< == @page[@cur_pos]
+      # Next token is a tag of some kind
+      if '!--' == @page[(@cur_pos + 1), 3]
+        # Token is a comment
+        tag_end = @page.index('-->', (@cur_pos + 1))
+        if tag_end.nil?
+          raise "No end found to started comment:\n#{@page[@cur_pos,80]}"
+        end
+        # p @page[@cur_pos .. (tag_end+2)]
+        HTMLComment.new(@page[@cur_pos .. (tag_end + 2)])
+      else
+        # Token is a html tag
+        tag_end = @page.index('>', (@cur_pos + 1))
+        if tag_end.nil?
+          raise "No end found to started tag:\n#{@page[@cur_pos,80]}"
+        end
+        # p @page[@cur_pos .. tag_end]
+        HTMLTag.new(@page[@cur_pos .. tag_end])
+      end
+    else
+      # Next token is text
+      text_end = @page.index('<', @cur_pos)
+      text_end = text_end.nil? ? -1 : (text_end - 1)
+      # p @page[@cur_pos .. text_end]
+      HTMLText.new(@page[@cur_pos .. text_end])
+    end
+  end
+
+  # Get the next token, returns an instance of
+  # * HTMLText
+  # * HTMLToken
+  # * HTMLTag
+  def getNextToken
+    token = peekNextToken
+    if token
+      # @page = @page[token.raw.length .. -1]
+      # @page.slice!(0, token.raw.length)
+      @cur_pos += token.raw.length
+    end
+    #p token
+    #print token.raw
+    return token
+  end
+
+  # Get a tag from the specified set of desired tags.
+  # For example:
+  # <tt>foo =  toke.getTag("h1", "h2", "h3")</tt>
+  # Will return the next header tag encountered.
+  def getTag(*sought_tags)
+    sought_tags.collect! {|elm| elm.downcase}
+
+    while (tag = getNextToken)
+      if tag.kind_of?(HTMLTag) and
+          (0 == sought_tags.length or sought_tags.include?(tag.tag_name))
+        break
+      end
+    end
+    tag
+  end
+
+  # Get all the text between the current position and the next tag
+  # (if specified) or a specific later tag
+  def getText(until_tag = nil)
+    if until_tag.nil?
+      if ?< == @page[@cur_pos]
+        # Next token is a tag, not text
+        ""
+      else
+        # Next token is text
+        getNextToken.text
+      end
+    else
+      ret_str = ""
+
+      while (tag = peekNextToken)
+        if tag.kind_of?(HTMLTag) and tag.tag_name == until_tag
+          break
+        end
+
+        if ("" != tag.text)
+          ret_str << (tag.text + " ")
+        end
+        getNextToken
+      end
+
+      ret_str
+    end
+  end
+
+  # Like getText, but squeeze all whitespace, getting rid of
+  # leading and trailing whitespace, and squeezing multiple
+  # spaces into a single space.
+  def getTrimmedText(until_tag = nil)
+    getText(until_tag).strip.gsub(/\s+/m, " ")
+  end
+
+end
+
+# The parent class for all three types of HTML tokens
+class HTMLToken
+  attr_accessor :raw
+
+  # Initialize the token based on the raw text
+  def initialize(text)
+    @raw = text
+  end
+
+  # By default, return exactly the string used to create the text
+  def to_s
+    raw
+  end
+
+  # By default tokens have no text representation
+  def text
+    ""
+  end
+
+  def trimmed_text
+    text.strip.gsub(/\s+/m, " ")
+  end
+
+  # Compare to another based on the raw source
+  def ==(other)
+    raw == other.to_s
+  end
+end
+
+# Class representing text that isn't inside a tag
+class HTMLText < HTMLToken
+  def text
+    raw
+  end
+end
+
+# Class representing an HTML comment
+class HTMLComment < HTMLToken
+  attr_accessor :contents
+  def initialize(text)
+    super(text)
+    temp_arr = text.scan(/^<!--\s*(.*?)\s*-->$/m)
+    if temp_arr[0].nil?
+      raise "Text passed to HTMLComment.initialize is not a comment"
+    end
+
+    @contents = temp_arr[0][0]
+  end
+end
+
+# Class representing an HTML tag
+class HTMLTag < HTMLToken
+  attr_reader :end_tag, :tag_name
+  def initialize(text)
+    super(text)
+    if ?< != text[0] or ?> != text[-1]
+      raise "Text passed to HTMLComment.initialize is not a comment"
+    end
+
+    @attr_hash = Hash.new
+    @raw = text
+
+    tag_name = text.scan(/[\w:-]+/)[0]
+    if tag_name.nil?
+      raise "Error, tag is nil: #{tag_name}"
+    end
+
+    if ?/ == text[1]
+      # It's an end tag
+      @end_tag = true
+      @tag_name = '/' + tag_name.downcase
+    else
+      @end_tag = false
+      @tag_name = tag_name.downcase
+    end
+
+    @hashed = false
+  end
+
+  # Retrieve a hash of all the tag's attributes.
+  # Lazily done, so that if you don't look at a tag's attributes
+  # things go quicker
+  def attr_hash
+    # Lazy initialize == don't build the hash until it's needed
+    if !@hashed
+      if !@end_tag
+        # Get the attributes
+        attr_arr = @raw.scan(/<[\w:-]+\s+(.*)>/m)[0]
+        if attr_arr.kind_of?(Array)
+          # Attributes found, parse them
+          attrs = attr_arr[0]
+          attr_arr = attrs.scan(/\s*([\w:-]+)(?:\s*=\s*("[^"]*"|'[^']*'|([^"'>][^\s>]*)))?/m)
+          # clean up the array by:
+          # * setting all nil elements to true
+          # * removing enclosing quotes
+          attr_arr.each {
+            |item|
+            val = if item[1].nil?
+                    item[0]
+                  elsif '"'[0] == item[1][0] or '\''[0] == item[1][0]
+                    item[1][1 .. -2]
+                  else
+                    item[1]
+                  end
+            @attr_hash[item[0].downcase] = val
+          }
+        end
+      end
+      @hashed = true
+    end
+
+    #p self
+
+    @attr_hash
+  end
+
+  # Get the 'alt' text for a tag, if it exists, or an empty string otherwise
+  def text
+    if !end_tag
+      case tag_name
+      when 'img'
+        if !attr_hash['alt'].nil?
+          return attr_hash['alt']
+        end
+      when 'applet'
+        if !attr_hash['alt'].nil?
+          return attr_hash['alt']
+        end
+      end
+    end
+    return ''
+  end
+end
+
+if $0 == __FILE__
+  require 'test/unit'
+
+  class TC_TestHTMLTokenizer < Test::Unit::TestCase
+    def test_bad_link
+      toke = HTMLTokenizer.new("<p><a href=http://bad.com/link>foo</a></p>")
+      assert("http://bad.com/link" == toke.getTag("a").attr_hash['href'])
+    end
+
+    def test_namespace
+      toke = HTMLTokenizer.new("<f:table xmlns:f=\"http://www.com/foo\">")
+      assert("http://www.com/foo" == toke.getTag("f:table").attr_hash['xmlns:f'])
+    end
+
+    def test_comment
+      toke = HTMLTokenizer.new("<!-- comment on me -->")
+      t = toke.getNextToken
+      assert(HTMLComment == t.class)
+      assert("comment on me" == t.contents)
+    end
+
+
+    def test_full
+      page = "<HTML>
+<HEAD>
+<TITLE>This is the title</TITLE>
+</HEAD>
+<!-- Here comes the <a href=\"missing.link\">blah</a>
+comment body
+ -->
+<BODY>
+  <H1>This is the header</H1>
+  <P>
+    This is the paragraph, it contains
+    <a href=\"link.html\">links</a>, 
+    <img src=\"blah.gif\" optional alt='images
+are
+really cool'>.  Ok, here is some more text and
+    <A href=\"http://another.link.com/\" target=\"_blank\">another link</A>.
+  </P>
+</body>
+</HTML>
+"
+      toke = HTMLTokenizer.new(page)
+
+      assert("<h1>" == toke.getTag("h1", "h2", "h3").to_s.downcase)
+      assert(HTMLTag.new("<a href=\"link.html\">") == toke.getTag("IMG", "A"))
+      assert("links" == toke.getTrimmedText)
+      assert(toke.getTag("IMG", "A").attr_hash['optional'])
+      assert("_blank" == toke.getTag("IMG", "A").attr_hash['target'])
+    end
+  end
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/manager.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/manager.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/manager.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/manager.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,145 @@
+require 'yadis/yadis'
+
+class YadisServiceManager
+
+  attr_reader :starting_url, :yadis_url, :services, :session_key, :current
+
+  def initialize(starting_url, yadis_url, services)
+    @starting_url = starting_url
+    @yadis_url = yadis_url
+    @services = services
+    @current = nil
+  end
+
+  def next
+    @current = @services.shift
+  end
+
+  def for_url?(url)
+    url == @starting_url or url == @yadis_url
+  end
+
+  def started?
+    not @current.nil?
+  end
+
+  def length
+    @services.length
+  end
+
+end
+
+class Discovery
+
+  @@default_suffix = 'auth'
+  @@prefix = '_yadis_services_'
+
+  # expects a normalized url
+  def initialize(session, url, session_key_suffix=nil)
+    @session = session
+    @url = url
+    @session_key = @@prefix + (session_key_suffix or @@default_suffix)
+  end
+
+  def next_service
+    manager = self.get_manager
+    if manager and manager.length <= 0
+      self.destroy_manager
+      manager = nil
+    end
+
+    unless manager
+      begin
+        yadis_url, services = self.discover
+      rescue YADISParseError, YADISHTTPError
+        manager = nil
+      else
+        manager = self.create_manager(services, yadis_url)   
+      end     
+    end
+
+    if manager
+      service = manager.next
+      self.store_manager(manager)
+    else
+      service = nil
+    end
+    
+    return service
+  end
+
+  def finish
+    manager = self.get_manager
+    return nil unless manager
+
+    service = manager.current
+    self.destroy_manager
+    return service
+  end
+
+  def current
+    manager = self.get_manager
+    return nil unless manager
+    return manager.current
+  end
+
+  def get_manager
+    manager = @session[@session_key]
+
+    # make sure we've got the right manager here
+    if manager and manager.for_url?(@url)
+      return manager
+    end
+
+    return nil
+  end
+
+  def create_manager(services, yadis_url=nil)
+    if self.get_manager
+      raise ArgumentError, "There is already a manager for #{@url}"
+    end
+
+    if services.length > 0
+      manager = YadisServiceManager.new(@url, yadis_url, services)
+      self.store_manager(manager)
+    else
+      manager = nil
+    end
+
+    return manager
+  end
+
+  def destroy_manager
+    if self.get_manager
+      begin
+        @session.delete(@session_key)
+      rescue
+        # sometimes Hash like session objects don't have a delete
+        # method.  We handle that case by assigning nil to the session[key]
+        @session[@session_key] = nil
+      end
+    end
+  end
+
+  def store_manager(manager)
+    @session[@session_key] = manager
+  end
+
+  # The filter argument is a Proc that will be used to call
+  # YADIS.filter_services.  See the documentation for YADIS.filter_services
+  # for more information about writing filters.
+  def discover(filter=nil)
+    y = YADIS.new(@url)
+    
+    # a default filter which sends through everything.  you should
+    # probably consider writing a custom filter and passing it in.
+    unless filter
+      filter = lambda {|s| s}
+    end
+
+    return [y.uri, y.filter_services(filter)]    
+  end
+
+end
+
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/parsehtml.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/parsehtml.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/parsehtml.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/parsehtml.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,32 @@
+require "yadis/htmltokenizer"
+
+def html_yadis_location(html)
+  parser = HTMLTokenizer.new(html)
+
+  # to keep track of whether or not we are in the head element
+  in_head = false
+
+  begin
+    while el = parser.getTag('head', '/head', 'meta', 'body')
+      
+      # we are leaving head or have reached body, so we bail
+      return nil if ['/head', 'body'].member?(el.tag_name)
+
+      # meta needs to be in head, so we mark it
+      in_head = true if el.tag_name == 'head'
+      continue unless in_head
+
+      if el.tag_name == 'meta' and (equiv = el.attr_hash['http-equiv'])
+        if ['x-xrds-location','x-yadis-location'].member?(equiv.downcase)
+          return el.attr_hash['content']
+        end
+      end
+      
+    end
+  rescue
+    return nil
+  end
+
+end
+
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/service.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/service.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/service.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/service.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,22 @@
+# Class representing an XRD Service element.  
+class ServiceEndpoint
+
+  attr_accessor :service_types, :uri, :yadis_uri, :element, :yadis, :canonical_id
+
+  def initialize
+    @service_types = []
+    @uri = nil
+    @yadis_uri = nil
+    @element = nil
+    @canonical_id = nil
+  end
+
+  def match_type_uris(type_uris)
+    type_uris.find_all {|t| @service_types.member?(t)}
+  end
+
+  def ==(other)
+    return self.instance_variables == other.instance_variables
+  end
+
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrds.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrds.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrds.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrds.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,146 @@
+require 'rexml/document'
+require 'yadis/service'
+
+# Class that handles XRDS parsing and XRD Service element extraction.
+
+module XRDSUtil
+  
+  @@namespaces = {
+    'xrdsns' => 'xri://$xrds',
+    'xrdns' => 'xri://$xrd*($v*2.0)'
+  }
+
+  def last_xrd(root_element)
+    REXML::XPath.match(root_element, '/xrdsns:XRDS/xrdns:XRD',
+                       @@namespaces)[-1]
+  end
+  
+end
+
+class XRDS
+
+  include XRDSUtil
+  attr_reader :xml
+
+  # Method for producing a valid XRDS object.  Accepts an XML
+  # String. Returns an XRDS object on success, or nil on failure.
+  # Same as calling XRDS.new, but does not raise ArgumentErrors.
+  def XRDS.parse(xml)
+    begin
+      return new(xml)
+    rescue
+      return nil
+    end
+  end
+
+  # Create a new XRDS object.  Raises ArgumentError if xml_text is
+  # malformed or invalid XRDS.
+  def initialize(xml_text)
+    @xml_text = xml_text
+    parse_xml(xml_text)
+  end
+
+  def _dump(depth)
+    return @xml_text
+  end
+
+  def XRDS._load(s)
+    XRDS.new(s)
+  end
+
+  def parse_xml(xml_text)   
+    begin
+      xml = @xml = REXML::Document.new(xml_text)
+    rescue
+      raise ArgumentError, "Can't parse XRDS"
+    end
+    
+    if xml.root.nil?
+      raise ArgumentError, "No document root"
+    end
+
+    xrd = self.last_xrd(xml.root)
+    raise ArgumentError, "No XRD Elements found" if xrd.nil?
+   
+    @services = {}  # keyed by [service_priority, uri_priority]
+    REXML::XPath.each(xrd, 'xrdns:Service', @@namespaces) do |s|
+      _create_services(s)
+    end
+    
+    REXML::XPath.each(xrd, 'xrdns:CanonicalID', @@namespaces) do |c|
+      canonical_id = c.text.strip
+      if canonical_id.length > 0
+        self.services.each {|s| s.canonical_id = canonical_id}
+      end
+    end
+
+  end
+
+
+  # Returns an Array of ServiceEndpoint objects, sorted by priority.  Highest
+  # priority is at element 0.
+  def services
+    s = []
+
+    @services.keys.sort.each do |key|
+      services_list = @services[key].dup
+
+      # randomize services with the same priority
+      while services_list.length > 0
+        s << services_list.delete_at((rand * services_list.length).to_i)
+      end
+
+    end
+    
+    return s
+  end
+
+  private
+
+  # create services objects
+  def _create_services(service_element)
+    service = ServiceEndpoint.new
+    service.element = service_element
+    service.uri = nil
+    service.service_types = []
+
+    REXML::XPath.each(service_element, 'xrdns:Type', @@namespaces) do |t|
+      # XXX: If the Type element is empty, should we add an empty element
+      # to our list, or none at all?
+      service.service_types << t.text.strip unless t.text.nil?
+    end
+
+    sp = service_element.attributes['priority']
+    service_priority = sp ? sp.to_i : -1
+    has_uri = false
+
+    REXML::XPath.each(service.element, 'xrdns:URI', @@namespaces) do |uri|
+      has_uri = true
+      _service = service.dup
+      _service.uri = uri.text.strip
+      
+      up = uri.attributes['priority']
+      uri_priority = up ? up.to_i : -1
+      priority = [service_priority, uri_priority]
+      
+      _add_service(priority, _service)
+    end
+      
+    unless has_uri
+      priority = [service_priority, -1]
+      _add_service(priority, service)
+    end
+
+  end
+
+  def _add_service(priority, service)
+    unless @services.has_key?(priority)
+      @services[priority] = []
+    end
+
+    # services with the same priority are appended to the list
+    @services[priority] << service
+  end
+
+end
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xri.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xri.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xri.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xri.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,87 @@
+require 'yadis/xrds'
+require 'yadis/fetcher'
+
+# The '(' is for cross-reference authorities, and hopefully has a matching ')'
+# somewhere.
+XRI_AUTHORITIES = ["!", "=", "@", "+", "$", "("]
+
+module XRI
+
+  def XRI.identifier_scheme(identifier)
+    if identifier.match('^xri://') or XRI_AUTHORITIES.member?(identifier[0].chr)
+      return :xri
+    else
+      return :uri
+    end
+  end
+
+  # Transform an XRI reference to an IRI reference.
+  # Note this is not not idempotent, so do not apply this to an identifier more
+  # than once.
+  # XRI Syntax section 2.3.1
+  def XRI.to_iri_normal(xri)
+    iri = xri.dup
+    iri.insert(0, 'xri://') if not iri.match('^xri://')
+    return escape_for_iri(iri)
+  end
+  
+  # Note this is not not idempotent, so do not apply this more than once.
+  # XRI Syntax section 2.3.2
+  def XRI.escape_for_iri(xri)
+    esc = xri.dup
+    # encode all %
+    esc.gsub!(/%/, '%25')
+    esc.gsub!(/\((.*?)\)/) { |xref_match|
+      xref_match.gsub(/[\/\?\#]/) { |char_match|
+        CGI::escape(char_match)
+      }
+    }
+    return esc
+  end
+
+  # Transform an XRI reference to a URI reference.
+  # Note this is not not idempotent, so do not apply this to an identifier more
+  # than once.
+  # XRI Syntax section 2.3.1
+  def XRI.to_uri_normal(xri)
+    return iri_to_uri(to_iri_normal(xri))
+  end
+  
+  # RFC 3987 section 3.1
+  def XRI.iri_to_uri(iri)
+    uri = iri.dup
+    # for char in ucschar or iprivate
+    # convert each char to %HH%HH%HH (as many %HH as octets)
+    return uri
+  end
+
+  def provider_is_authoritative(provider_id, canonical_id)
+    lastbang = canonical_id.rindex('!')
+    return false unless lastbang
+    parent = canonical_id[0...lastbang]
+    return parent == provider_id
+  end
+
+  def root_authority(xri)
+    xri = xri[6..-1] if xri.index('xri://') == 0
+    authority = xri.split('/', 2)[0]
+    if authority[0].chr == '('
+      root = authority[0...authority.index(')')+1]
+    elsif XRI_AUTHORITIES.member?(authority[0].chr)
+      root = authority[0].chr
+    else
+      root = authority.split(/[!*]/)[0]
+    end
+    
+    make_xri(root)
+  end
+
+  
+  def make_xri(xri)
+    if xri.index('xri://') != 0
+      xri = 'xri://' + xri
+    end
+    return xri
+  end
+
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrires.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrires.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrires.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/xrires.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,94 @@
+require "cgi"
+require "yadis/xri"
+require "yadis/xrds"
+require "yadis/fetcher"
+
+module XRI
+
+  class XRIHTTPError < StandardError; end
+  
+  class ProxyResolver
+
+    DEFAULT_PROXY = 'http://proxy.xri.net/'
+    
+    def initialize(proxy_url=nil)
+      if proxy_url
+        @proxy_url = proxy_url
+      else
+        @proxy_url = DEFAULT_PROXY
+      end
+
+      @proxy_url += '/' unless @proxy_url.match('/$')
+    end
+
+    def query_url(xri, service_type=nil)
+      # URI normal form has a leading xri://, but we need to strip
+      # that off again for the QXRI.  This is under discussion for
+      # XRI Resolution WD 11.
+      # 
+      qxri = XRI.to_uri_normal(xri)[6..-1]
+      hxri = @proxy_url + qxri
+      args = {'_xrd_r' => 'application/xrds+xml'}
+      if service_type
+        args['_xrd_t'] = service_type
+      else
+        # don't perform service endpoint selection 
+        args['_xrd_r'] += ';sep=false'
+      end
+
+      return XRI.append_args(hxri, args)
+    end
+
+    def query(xri, service_types)
+      # these can be query args or http headers, needn't be both.
+      # headers = {'Accept' => 'application/xrds+xml;sep=true'}
+      fetcher = NetHTTPFetcher.new
+      services = service_types.collect { |service_type|
+        url = self.query_url(xri, service_type)
+        response = fetcher.get(url)
+        raise XRIHTTPError, "Could not fetch #{xri}" if response.nil?
+        xrds = XRDS.new(response[1].body)
+        return xrds.services unless xrds.nil?
+      }
+      # TODO:
+      #  * If we do get hits for multiple service_types, we're almost 
+      #    certainly going to have duplicated service entries and 
+      #    broken priority ordering.
+      services = services.inject([]) { |flatter, some_services|
+        flatter.concat(some_services) unless some_services.nil?
+      }
+    end
+  end
+
+  def XRI.urlencode(args)
+    a = []
+    args.each do |key, val|
+      a << (CGI::escape(key) + "=" + CGI::escape(val))
+    end
+    a.join("&")
+  end
+
+  def XRI.append_args(url, args)
+    return url if args.length == 0
+    
+    # rstrip question marks
+    rstripped = url.dup
+    while rstripped[-1].chr == '?'
+      rstripped = rstripped[0...rstripped.length-1]
+    end
+    
+    if rstripped.index('?')
+      sep = '&'
+    else
+      sep = '?'
+    end
+    
+    return url + sep + XRI.urlencode(args)
+  end
+
+end
+
+# Example:
+#  r = XRI::ProxyResolver.new('http://proxy.xri.net/')
+#  j = r.query('=keturn', ['xri://+i-service*(+forwarding)*($v*1.0)'])
+#  Stderr.puts("the answer is #{j}")

Added: incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/yadis.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/yadis.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/yadis.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/lib/yadis/yadis.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,108 @@
+require 'yadis/xrds'
+require 'yadis/fetcher'
+require 'yadis/parsehtml'
+
+class YADISParseError < StandardError; end
+class YADISHTTPError < StandardError; end
+
+
+# High level class for performing the Yadis protocol on a given URL. The
+# YADIS.discover class method is a good place to get started in determining
+# which services a URL supports.
+class YADIS
+
+  @@ca_path = nil
+  attr_accessor :uri, :xrds_uri, :xrds
+
+  # Discover services for a given URI.  Please note that no normalization 
+  # will be done to the passed in URI, it should be a textually
+  # valid URI string before calling discover.
+  #
+  # Returns nil if no XRDS was found, or a YADIS object on success.  This
+  # method is essentially the same as YADIS.new, but does not raise any
+  # exceptions.
+  def YADIS.discover(uri)
+    return nil unless uri
+    begin
+      return YADIS.new(uri)
+    rescue
+      return nil
+    end
+  end
+
+  # Set the path to a certificate authority pem file, for verifying
+  # server certificates of HTTPS pages.  If you are interested in verifying
+  # certs like the mozilla web browser, have a look at the files here:
+  #
+  # http://curl.haxx.se/docs/caextract.html
+  def YADIS.ca_path=(ca_path)
+    ca_path = ca_path.to_s
+    if File.exists?(ca_path)
+      @@ca_path = ca_path
+    else
+      raise ArgumentError, "#{ca_path} is not a valid file path"
+    end
+  end
+
+  # Discover services for a URI using the Yadis protocol.  +uri+ should
+  # be a valid URI represented as a string.  This method may raise
+  # YADISParseError in the case of an invalid or unparsable XRDS file,
+  # or YADISHTTPError is the URI cannot be fetched.
+  def initialize(uri)
+    http = NetHTTPFetcher.new
+    http.ca_path = @@ca_path if @@ca_path    
+    headers = {'Accept' => 'application/xrds+xml'}
+
+    response = http.get(uri, headers)
+    raise YADISHTTPError, "Could not fetch #{uri}" if response.nil?
+
+    uri, resp_payload = response
+    xrds_uri = uri
+
+    header = resp_payload['x-xrds-location']
+    header = resp_payload['x-yadis-location'] if header.nil?
+
+    if header
+      xrds_uri = header
+      response = http.get(xrds_uri)
+      raise YADISHTTPError, "Could not fetch XRDS #{xrds_uri}" if response.nil?
+      resp_payload = response[1]
+    end
+
+    unless resp_payload['content-type'] == 'application/xrds+xml'
+      loc = html_yadis_location(resp_payload.body)
+      unless loc.nil?
+        xrds_uri, resp_payload = http.get(loc)
+      end
+    end
+
+    xrds = XRDS.parse(resp_payload.body)
+    raise YADISParseError, "Bad XRDS" if xrds.nil?
+
+    @uri = uri
+    @xrds_uri = xrds_uri
+    @xrds = xrds
+  end
+
+  # Returns an Array Service objects sorted by priority.
+  def services
+    @xrds.services.each {|s| s.yadis = self}
+    @xrds.services
+  end
+
+  # Returns a list of services, ordered by priority,
+  # that match the filter. filter is a Proc object that produces
+  # ServiceEnpoint objects, subclasses of ServiceEnpoint or nil.
+  # This method is useful for extracting several types of services while
+  # maintaining priority, for example you may write a filter Proc to extract
+  # OpenID and LID ServiceEnpoint objects.
+  def filter_services(filter)
+    # product a list of filtered ServiceEndpoint objects.  filtered
+    # will contain a list of nil or ServiceEnpoint (subclasses) objects.
+    filtered = self.services.collect {|s| filter.call(s)}
+    
+    # return all object in filtered that are not nil
+    return filtered.find_all {|s| s}
+  end
+
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/setup.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/setup.rb?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/setup.rb (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/setup.rb Wed Oct 11 15:17:05 2006
@@ -0,0 +1,1551 @@
+#
+# setup.rb
+#
+# Copyright (c) 2000-2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU LGPL, Lesser General Public License version 2.1.
+#
+
+unless Enumerable.method_defined?(:map)   # Ruby 1.4.6
+  module Enumerable
+    alias map collect
+  end
+end
+
+unless File.respond_to?(:read)   # Ruby 1.6
+  def File.read(fname)
+    open(fname) {|f|
+      return f.read
+    }
+  end
+end
+
+unless Errno.const_defined?(:ENOTEMPTY)   # Windows?
+  module Errno
+    class ENOTEMPTY
+      # We do not raise this exception, implementation is not needed.
+    end
+  end
+end
+
+def File.binread(fname)
+  open(fname, 'rb') {|f|
+    return f.read
+  }
+end
+
+# for corrupted Windows' stat(2)
+def File.dir?(path)
+  File.directory?((path[-1,1] == '/') ? path : path + '/')
+end
+
+
+class ConfigTable
+
+  include Enumerable
+
+  def initialize(rbconfig)
+    @rbconfig = rbconfig
+    @items = []
+    @table = {}
+    # options
+    @install_prefix = nil
+    @config_opt = nil
+    @verbose = true
+    @no_harm = false
+    @libsrc_pattern = '*.rb'
+  end
+
+  attr_accessor :install_prefix
+  attr_accessor :config_opt
+
+  attr_writer :verbose
+
+  def verbose?
+    @verbose
+  end
+
+  attr_writer :no_harm
+
+  def no_harm?
+    @no_harm
+  end
+
+  attr_accessor :libsrc_pattern
+
+  def [](key)
+    lookup(key).resolve(self)
+  end
+
+  def []=(key, val)
+    lookup(key).set val
+  end
+
+  def names
+    @items.map {|i| i.name }
+  end
+
+  def each(&block)
+    @items.each(&block)
+  end
+
+  def key?(name)
+    @table.key?(name)
+  end
+
+  def lookup(name)
+    @table[name] or setup_rb_error "no such config item: #{name}"
+  end
+
+  def add(item)
+    @items.push item
+    @table[item.name] = item
+  end
+
+  def remove(name)
+    item = lookup(name)
+    @items.delete_if {|i| i.name == name }
+    @table.delete_if {|name, i| i.name == name }
+    item
+  end
+
+  def load_script(path, inst = nil)
+    if File.file?(path)
+      MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
+    end
+  end
+
+  def savefile
+    '.config'
+  end
+
+  def load_savefile
+    begin
+      File.foreach(savefile()) do |line|
+        k, v = *line.split(/=/, 2)
+        self[k] = v.strip
+      end
+    rescue Errno::ENOENT
+      setup_rb_error $!.message + "\n#{File.basename($0)} config first"
+    end
+  end
+
+  def save
+    @items.each {|i| i.value }
+    File.open(savefile(), 'w') {|f|
+      @items.each do |i|
+        f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
+      end
+    }
+  end
+
+  def load_standard_entries
+    standard_entries(@rbconfig).each do |ent|
+      add ent
+    end
+  end
+
+  def standard_entries(rbconfig)
+    c = rbconfig
+
+    rubypath = c['bindir'] + '/' + c['ruby_install_name']
+
+    major = c['MAJOR'].to_i
+    minor = c['MINOR'].to_i
+    teeny = c['TEENY'].to_i
+    version = "#{major}.#{minor}"
+
+    # ruby ver. >= 1.4.4?
+    newpath_p = ((major >= 2) or
+                 ((major == 1) and
+                  ((minor >= 5) or
+                   ((minor == 4) and (teeny >= 4)))))
+
+    if c['rubylibdir']
+      # V > 1.6.3
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = c['rubylibdir']
+      librubyverarch  = c['archdir']
+      siteruby        = c['sitedir']
+      siterubyver     = c['sitelibdir']
+      siterubyverarch = c['sitearchdir']
+    elsif newpath_p
+      # 1.4.4 <= V <= 1.6.3
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
+      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+      siteruby        = c['sitedir']
+      siterubyver     = "$siteruby/#{version}"
+      siterubyverarch = "$siterubyver/#{c['arch']}"
+    else
+      # V < 1.4.4
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
+      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+      siteruby        = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
+      siterubyver     = siteruby
+      siterubyverarch = "$siterubyver/#{c['arch']}"
+    end
+    parameterize = lambda {|path|
+      path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
+    }
+
+    if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+      makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
+    else
+      makeprog = 'make'
+    end
+
+    [
+      ExecItem.new('installdirs', 'std/site/home',
+                   'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
+          {|val, table|
+            case val
+            when 'std'
+              table['rbdir'] = '$librubyver'
+              table['sodir'] = '$librubyverarch'
+            when 'site'
+              table['rbdir'] = '$siterubyver'
+              table['sodir'] = '$siterubyverarch'
+            when 'home'
+              setup_rb_error '$HOME was not set' unless ENV['HOME']
+              table['prefix'] = ENV['HOME']
+              table['rbdir'] = '$libdir/ruby'
+              table['sodir'] = '$libdir/ruby'
+            end
+          },
+      PathItem.new('prefix', 'path', c['prefix'],
+                   'path prefix of target environment'),
+      PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
+                   'the directory for commands'),
+      PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
+                   'the directory for libraries'),
+      PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
+                   'the directory for shared data'),
+      PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
+                   'the directory for man pages'),
+      PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
+                   'the directory for system configuration files'),
+      PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
+                   'the directory for local state data'),
+      PathItem.new('libruby', 'path', libruby,
+                   'the directory for ruby libraries'),
+      PathItem.new('librubyver', 'path', librubyver,
+                   'the directory for standard ruby libraries'),
+      PathItem.new('librubyverarch', 'path', librubyverarch,
+                   'the directory for standard ruby extensions'),
+      PathItem.new('siteruby', 'path', siteruby,
+          'the directory for version-independent aux ruby libraries'),
+      PathItem.new('siterubyver', 'path', siterubyver,
+                   'the directory for aux ruby libraries'),
+      PathItem.new('siterubyverarch', 'path', siterubyverarch,
+                   'the directory for aux ruby binaries'),
+      PathItem.new('rbdir', 'path', '$siterubyver',
+                   'the directory for ruby scripts'),
+      PathItem.new('sodir', 'path', '$siterubyverarch',
+                   'the directory for ruby extentions'),
+      PathItem.new('rubypath', 'path', rubypath,
+                   'the path to set to #! line'),
+      ProgramItem.new('rubyprog', 'name', rubypath,
+                      'the ruby program using for installation'),
+      ProgramItem.new('makeprog', 'name', makeprog,
+                      'the make program to compile ruby extentions'),
+      SelectItem.new('shebang', 'all/ruby/never', 'ruby',
+                     'shebang line (#!) editing mode'),
+      BoolItem.new('without-ext', 'yes/no', 'no',
+                   'does not compile/install ruby extentions')
+    ]
+  end
+  private :standard_entries
+
+  def load_multipackage_entries
+    multipackage_entries().each do |ent|
+      add ent
+    end
+  end
+
+  def multipackage_entries
+    [
+      PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
+                               'package names that you want to install'),
+      PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
+                               'package names that you do not want to install')
+    ]
+  end
+  private :multipackage_entries
+
+  ALIASES = {
+    'std-ruby'         => 'librubyver',
+    'stdruby'          => 'librubyver',
+    'rubylibdir'       => 'librubyver',
+    'archdir'          => 'librubyverarch',
+    'site-ruby-common' => 'siteruby',     # For backward compatibility
+    'site-ruby'        => 'siterubyver',  # For backward compatibility
+    'bin-dir'          => 'bindir',
+    'bin-dir'          => 'bindir',
+    'rb-dir'           => 'rbdir',
+    'so-dir'           => 'sodir',
+    'data-dir'         => 'datadir',
+    'ruby-path'        => 'rubypath',
+    'ruby-prog'        => 'rubyprog',
+    'ruby'             => 'rubyprog',
+    'make-prog'        => 'makeprog',
+    'make'             => 'makeprog'
+  }
+
+  def fixup
+    ALIASES.each do |ali, name|
+      @table[ali] = @table[name]
+    end
+    @items.freeze
+    @table.freeze
+    @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
+  end
+
+  def parse_opt(opt)
+    m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
+    m.to_a[1,2]
+  end
+
+  def dllext
+    @rbconfig['DLEXT']
+  end
+
+  def value_config?(name)
+    lookup(name).value?
+  end
+
+  class Item
+    def initialize(name, template, default, desc)
+      @name = name.freeze
+      @template = template
+      @value = default
+      @default = default
+      @description = desc
+    end
+
+    attr_reader :name
+    attr_reader :description
+
+    attr_accessor :default
+    alias help_default default
+
+    def help_opt
+      "--#{@name}=#{@template}"
+    end
+
+    def value?
+      true
+    end
+
+    def value
+      @value
+    end
+
+    def resolve(table)
+      @value.gsub(%r<\$([^/]+)>) { table[$1] }
+    end
+
+    def set(val)
+      @value = check(val)
+    end
+
+    private
+
+    def check(val)
+      setup_rb_error "config: --#{name} requires argument" unless val
+      val
+    end
+  end
+
+  class BoolItem < Item
+    def config_type
+      'bool'
+    end
+
+    def help_opt
+      "--#{@name}"
+    end
+
+    private
+
+    def check(val)
+      return 'yes' unless val
+      unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
+        setup_rb_error "config: --#{@name} accepts only yes/no for argument"
+      end
+      (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
+    end
+  end
+
+  class PathItem < Item
+    def config_type
+      'path'
+    end
+
+    private
+
+    def check(path)
+      setup_rb_error "config: --#{@name} requires argument"  unless path
+      path[0,1] == '$' ? path : File.expand_path(path)
+    end
+  end
+
+  class ProgramItem < Item
+    def config_type
+      'program'
+    end
+  end
+
+  class SelectItem < Item
+    def initialize(name, selection, default, desc)
+      super
+      @ok = selection.split('/')
+    end
+
+    def config_type
+      'select'
+    end
+
+    private
+
+    def check(val)
+      unless @ok.include?(val.strip)
+        setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
+      end
+      val.strip
+    end
+  end
+
+  class ExecItem < Item
+    def initialize(name, selection, desc, &block)
+      super name, selection, nil, desc
+      @ok = selection.split('/')
+      @action = block
+    end
+
+    def config_type
+      'exec'
+    end
+
+    def value?
+      false
+    end
+
+    def resolve(table)
+      setup_rb_error "$#{name()} wrongly used as option value"
+    end
+
+    undef set
+
+    def evaluate(val, table)
+      v = val.strip.downcase
+      unless @ok.include?(v)
+        setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
+      end
+      @action.call v, table
+    end
+  end
+
+  class PackageSelectionItem < Item
+    def initialize(name, template, default, help_default, desc)
+      super name, template, default, desc
+      @help_default = help_default
+    end
+
+    attr_reader :help_default
+
+    def config_type
+      'package'
+    end
+
+    private
+
+    def check(val)
+      unless File.dir?("packages/#{val}")
+        setup_rb_error "config: no such package: #{val}"
+      end
+      val
+    end
+  end
+
+  class MetaConfigEnvironment
+    def intiailize(config, installer)
+      @config = config
+      @installer = installer
+    end
+
+    def config_names
+      @config.names
+    end
+
+    def config?(name)
+      @config.key?(name)
+    end
+
+    def bool_config?(name)
+      @config.lookup(name).config_type == 'bool'
+    end
+
+    def path_config?(name)
+      @config.lookup(name).config_type == 'path'
+    end
+
+    def value_config?(name)
+      @config.lookup(name).config_type != 'exec'
+    end
+
+    def add_config(item)
+      @config.add item
+    end
+
+    def add_bool_config(name, default, desc)
+      @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
+    end
+
+    def add_path_config(name, default, desc)
+      @config.add PathItem.new(name, 'path', default, desc)
+    end
+
+    def set_config_default(name, default)
+      @config.lookup(name).default = default
+    end
+
+    def remove_config(name)
+      @config.remove(name)
+    end
+
+    # For only multipackage
+    def packages
+      raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
+      @installer.packages
+    end
+
+    # For only multipackage
+    def declare_packages(list)
+      raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
+      @installer.packages = list
+    end
+  end
+
+end   # class ConfigTable
+
+
+# This module requires: #verbose?, #no_harm?
+module FileOperations
+
+  def mkdir_p(dirname, prefix = nil)
+    dirname = prefix + File.expand_path(dirname) if prefix
+    $stderr.puts "mkdir -p #{dirname}" if verbose?
+    return if no_harm?
+
+    # Does not check '/', it's too abnormal.
+    dirs = File.expand_path(dirname).split(%r<(?=/)>)
+    if /\A[a-z]:\z/i =~ dirs[0]
+      disk = dirs.shift
+      dirs[0] = disk + dirs[0]
+    end
+    dirs.each_index do |idx|
+      path = dirs[0..idx].join('')
+      Dir.mkdir path unless File.dir?(path)
+    end
+  end
+
+  def rm_f(path)
+    $stderr.puts "rm -f #{path}" if verbose?
+    return if no_harm?
+    force_remove_file path
+  end
+
+  def rm_rf(path)
+    $stderr.puts "rm -rf #{path}" if verbose?
+    return if no_harm?
+    remove_tree path
+  end
+
+  def remove_tree(path)
+    if File.symlink?(path)
+      remove_file path
+    elsif File.dir?(path)
+      remove_tree0 path
+    else
+      force_remove_file path
+    end
+  end
+
+  def remove_tree0(path)
+    Dir.foreach(path) do |ent|
+      next if ent == '.'
+      next if ent == '..'
+      entpath = "#{path}/#{ent}"
+      if File.symlink?(entpath)
+        remove_file entpath
+      elsif File.dir?(entpath)
+        remove_tree0 entpath
+      else
+        force_remove_file entpath
+      end
+    end
+    begin
+      Dir.rmdir path
+    rescue Errno::ENOTEMPTY
+      # directory may not be empty
+    end
+  end
+
+  def move_file(src, dest)
+    force_remove_file dest
+    begin
+      File.rename src, dest
+    rescue
+      File.open(dest, 'wb') {|f|
+        f.write File.binread(src)
+      }
+      File.chmod File.stat(src).mode, dest
+      File.unlink src
+    end
+  end
+
+  def force_remove_file(path)
+    begin
+      remove_file path
+    rescue
+    end
+  end
+
+  def remove_file(path)
+    File.chmod 0777, path
+    File.unlink path
+  end
+
+  def install(from, dest, mode, prefix = nil)
+    $stderr.puts "install #{from} #{dest}" if verbose?
+    return if no_harm?
+
+    realdest = prefix ? prefix + File.expand_path(dest) : dest
+    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+    str = File.binread(from)
+    if diff?(str, realdest)
+      verbose_off {
+        rm_f realdest if File.exist?(realdest)
+      }
+      File.open(realdest, 'wb') {|f|
+        f.write str
+      }
+      File.chmod mode, realdest
+
+      File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+        if prefix
+          f.puts realdest.sub(prefix, '')
+        else
+          f.puts realdest
+        end
+      }
+    end
+  end
+
+  def diff?(new_content, path)
+    return true unless File.exist?(path)
+    new_content != File.binread(path)
+  end
+
+  def command(*args)
+    $stderr.puts args.join(' ') if verbose?
+    system(*args) or raise RuntimeError,
+        "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
+  end
+
+  def ruby(*args)
+    command config('rubyprog'), *args
+  end
+  
+  def make(task = nil)
+    command(*[config('makeprog'), task].compact)
+  end
+
+  def extdir?(dir)
+    File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
+  end
+
+  def files_of(dir)
+    Dir.open(dir) {|d|
+      return d.select {|ent| File.file?("#{dir}/#{ent}") }
+    }
+  end
+
+  DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
+
+  def directories_of(dir)
+    Dir.open(dir) {|d|
+      return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
+    }
+  end
+
+end
+
+
+# This module requires: #srcdir_root, #objdir_root, #relpath
+module HookScriptAPI
+
+  def get_config(key)
+    @config[key]
+  end
+
+  alias config get_config
+
+  # obsolete: use metaconfig to change configuration
+  def set_config(key, val)
+    @config[key] = val
+  end
+
+  #
+  # srcdir/objdir (works only in the package directory)
+  #
+
+  def curr_srcdir
+    "#{srcdir_root()}/#{relpath()}"
+  end
+
+  def curr_objdir
+    "#{objdir_root()}/#{relpath()}"
+  end
+
+  def srcfile(path)
+    "#{curr_srcdir()}/#{path}"
+  end
+
+  def srcexist?(path)
+    File.exist?(srcfile(path))
+  end
+
+  def srcdirectory?(path)
+    File.dir?(srcfile(path))
+  end
+  
+  def srcfile?(path)
+    File.file?(srcfile(path))
+  end
+
+  def srcentries(path = '.')
+    Dir.open("#{curr_srcdir()}/#{path}") {|d|
+      return d.to_a - %w(. ..)
+    }
+  end
+
+  def srcfiles(path = '.')
+    srcentries(path).select {|fname|
+      File.file?(File.join(curr_srcdir(), path, fname))
+    }
+  end
+
+  def srcdirectories(path = '.')
+    srcentries(path).select {|fname|
+      File.dir?(File.join(curr_srcdir(), path, fname))
+    }
+  end
+
+end
+
+
+class ToplevelInstaller
+
+  Version   = '3.4.0'
+  Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
+
+  TASKS = [
+    [ 'all',      'do config, setup, then install' ],
+    [ 'config',   'saves your configurations' ],
+    [ 'show',     'shows current configuration' ],
+    [ 'setup',    'compiles ruby extentions and others' ],
+    [ 'install',  'installs files' ],
+    [ 'test',     'run all tests in test/' ],
+    [ 'clean',    "does `make clean' for each extention" ],
+    [ 'distclean',"does `make distclean' for each extention" ]
+  ]
+
+  def ToplevelInstaller.invoke
+    config = ConfigTable.new(load_rbconfig())
+    config.load_standard_entries
+    config.load_multipackage_entries if multipackage?
+    config.fixup
+    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
+    klass.new(File.dirname($0), config).invoke
+  end
+
+  def ToplevelInstaller.multipackage?
+    File.dir?(File.dirname($0) + '/packages')
+  end
+
+  def ToplevelInstaller.load_rbconfig
+    if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
+      ARGV.delete(arg)
+      load File.expand_path(arg.split(/=/, 2)[1])
+      $".push 'rbconfig.rb'
+    else
+      require 'rbconfig'
+    end
+    ::Config::CONFIG
+  end
+
+  def initialize(ardir_root, config)
+    @ardir = File.expand_path(ardir_root)
+    @config = config
+    # cache
+    @valid_task_re = nil
+  end
+
+  def config(key)
+    @config[key]
+  end
+
+  def inspect
+    "#<#{self.class} #{__id__()}>"
+  end
+
+  def invoke
+    run_metaconfigs
+    case task = parsearg_global()
+    when nil, 'all'
+      parsearg_config
+      init_installers
+      exec_config
+      exec_setup
+      exec_install
+    else
+      case task
+      when 'config', 'test'
+        ;
+      when 'clean', 'distclean'
+        @config.load_savefile if File.exist?(@config.savefile)
+      else
+        @config.load_savefile
+      end
+      __send__ "parsearg_#{task}"
+      init_installers
+      __send__ "exec_#{task}"
+    end
+  end
+  
+  def run_metaconfigs
+    @config.load_script "#{@ardir}/metaconfig"
+  end
+
+  def init_installers
+    @installer = Installer.new(@config, @ardir, File.expand_path('.'))
+  end
+
+  #
+  # Hook Script API bases
+  #
+
+  def srcdir_root
+    @ardir
+  end
+
+  def objdir_root
+    '.'
+  end
+
+  def relpath
+    '.'
+  end
+
+  #
+  # Option Parsing
+  #
+
+  def parsearg_global
+    while arg = ARGV.shift
+      case arg
+      when /\A\w+\z/
+        setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
+        return arg
+      when '-q', '--quiet'
+        @config.verbose = false
+      when '--verbose'
+        @config.verbose = true
+      when '--help'
+        print_usage $stdout
+        exit 0
+      when '--version'
+        puts "#{File.basename($0)} version #{Version}"
+        exit 0
+      when '--copyright'
+        puts Copyright
+        exit 0
+      else
+        setup_rb_error "unknown global option '#{arg}'"
+      end
+    end
+    nil
+  end
+
+  def valid_task?(t)
+    valid_task_re() =~ t
+  end
+
+  def valid_task_re
+    @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
+  end
+
+  def parsearg_no_options
+    unless ARGV.empty?
+      setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
+    end
+  end
+
+  alias parsearg_show       parsearg_no_options
+  alias parsearg_setup      parsearg_no_options
+  alias parsearg_test       parsearg_no_options
+  alias parsearg_clean      parsearg_no_options
+  alias parsearg_distclean  parsearg_no_options
+
+  def parsearg_config
+    evalopt = []
+    set = []
+    @config.config_opt = []
+    while i = ARGV.shift
+      if /\A--?\z/ =~ i
+        @config.config_opt = ARGV.dup
+        break
+      end
+      name, value = *@config.parse_opt(i)
+      if @config.value_config?(name)
+        @config[name] = value
+      else
+        evalopt.push [name, value]
+      end
+      set.push name
+    end
+    evalopt.each do |name, value|
+      @config.lookup(name).evaluate value, @config
+    end
+    # Check if configuration is valid
+    set.each do |n|
+      @config[n] if @config.value_config?(n)
+    end
+  end
+
+  def parsearg_install
+    @config.no_harm = false
+    @config.install_prefix = ''
+    while a = ARGV.shift
+      case a
+      when '--no-harm'
+        @config.no_harm = true
+      when /\A--prefix=/
+        path = a.split(/=/, 2)[1]
+        path = File.expand_path(path) unless path[0,1] == '/'
+        @config.install_prefix = path
+      else
+        setup_rb_error "install: unknown option #{a}"
+      end
+    end
+  end
+
+  def print_usage(out)
+    out.puts 'Typical Installation Procedure:'
+    out.puts "  $ ruby #{File.basename $0} config"
+    out.puts "  $ ruby #{File.basename $0} setup"
+    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
+    out.puts
+    out.puts 'Detailed Usage:'
+    out.puts "  ruby #{File.basename $0} <global option>"
+    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+
+    fmt = "  %-24s %s\n"
+    out.puts
+    out.puts 'Global options:'
+    out.printf fmt, '-q,--quiet',   'suppress message outputs'
+    out.printf fmt, '   --verbose', 'output messages verbosely'
+    out.printf fmt, '   --help',    'print this message'
+    out.printf fmt, '   --version', 'print version and quit'
+    out.printf fmt, '   --copyright',  'print copyright and quit'
+    out.puts
+    out.puts 'Tasks:'
+    TASKS.each do |name, desc|
+      out.printf fmt, name, desc
+    end
+
+    fmt = "  %-24s %s [%s]\n"
+    out.puts
+    out.puts 'Options for CONFIG or ALL:'
+    @config.each do |item|
+      out.printf fmt, item.help_opt, item.description, item.help_default
+    end
+    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
+    out.puts
+    out.puts 'Options for INSTALL:'
+    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
+    out.printf fmt, '--prefix=path',  'install path prefix', ''
+    out.puts
+  end
+
+  #
+  # Task Handlers
+  #
+
+  def exec_config
+    @installer.exec_config
+    @config.save   # must be final
+  end
+
+  def exec_setup
+    @installer.exec_setup
+  end
+
+  def exec_install
+    @installer.exec_install
+  end
+
+  def exec_test
+    @installer.exec_test
+  end
+
+  def exec_show
+    @config.each do |i|
+      printf "%-20s %s\n", i.name, i.value if i.value?
+    end
+  end
+
+  def exec_clean
+    @installer.exec_clean
+  end
+
+  def exec_distclean
+    @installer.exec_distclean
+  end
+
+end   # class ToplevelInstaller
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+  include FileOperations
+
+  def initialize(ardir_root, config)
+    super
+    @packages = directories_of("#{@ardir}/packages")
+    raise 'no package exists' if @packages.empty?
+    @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
+  end
+
+  def run_metaconfigs
+    @config.load_script "#{@ardir}/metaconfig", self
+    @packages.each do |name|
+      @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
+    end
+  end
+
+  attr_reader :packages
+
+  def packages=(list)
+    raise 'package list is empty' if list.empty?
+    list.each do |name|
+      raise "directory packages/#{name} does not exist"\
+              unless File.dir?("#{@ardir}/packages/#{name}")
+    end
+    @packages = list
+  end
+
+  def init_installers
+    @installers = {}
+    @packages.each do |pack|
+      @installers[pack] = Installer.new(@config,
+                                       "#{@ardir}/packages/#{pack}",
+                                       "packages/#{pack}")
+    end
+    with    = extract_selection(config('with'))
+    without = extract_selection(config('without'))
+    @selected = @installers.keys.select {|name|
+                  (with.empty? or with.include?(name)) \
+                      and not without.include?(name)
+                }
+  end
+
+  def extract_selection(list)
+    a = list.split(/,/)
+    a.each do |name|
+      setup_rb_error "no such package: #{name}"  unless @installers.key?(name)
+    end
+    a
+  end
+
+  def print_usage(f)
+    super
+    f.puts 'Inluded packages:'
+    f.puts '  ' + @packages.sort.join(' ')
+    f.puts
+  end
+
+  #
+  # Task Handlers
+  #
+
+  def exec_config
+    run_hook 'pre-config'
+    each_selected_installers {|inst| inst.exec_config }
+    run_hook 'post-config'
+    @config.save   # must be final
+  end
+
+  def exec_setup
+    run_hook 'pre-setup'
+    each_selected_installers {|inst| inst.exec_setup }
+    run_hook 'post-setup'
+  end
+
+  def exec_install
+    run_hook 'pre-install'
+    each_selected_installers {|inst| inst.exec_install }
+    run_hook 'post-install'
+  end
+
+  def exec_test
+    run_hook 'pre-test'
+    each_selected_installers {|inst| inst.exec_test }
+    run_hook 'post-test'
+  end
+
+  def exec_clean
+    rm_f @config.savefile
+    run_hook 'pre-clean'
+    each_selected_installers {|inst| inst.exec_clean }
+    run_hook 'post-clean'
+  end
+
+  def exec_distclean
+    rm_f @config.savefile
+    run_hook 'pre-distclean'
+    each_selected_installers {|inst| inst.exec_distclean }
+    run_hook 'post-distclean'
+  end
+
+  #
+  # lib
+  #
+
+  def each_selected_installers
+    Dir.mkdir 'packages' unless File.dir?('packages')
+    @selected.each do |pack|
+      $stderr.puts "Processing the package `#{pack}' ..." if verbose?
+      Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+      Dir.chdir "packages/#{pack}"
+      yield @installers[pack]
+      Dir.chdir '../..'
+    end
+  end
+
+  def run_hook(id)
+    @root_installer.run_hook id
+  end
+
+  # module FileOperations requires this
+  def verbose?
+    @config.verbose?
+  end
+
+  # module FileOperations requires this
+  def no_harm?
+    @config.no_harm?
+  end
+
+end   # class ToplevelInstallerMulti
+
+
+class Installer
+
+  FILETYPES = %w( bin lib ext data conf man )
+
+  include FileOperations
+  include HookScriptAPI
+
+  def initialize(config, srcroot, objroot)
+    @config = config
+    @srcdir = File.expand_path(srcroot)
+    @objdir = File.expand_path(objroot)
+    @currdir = '.'
+  end
+
+  def inspect
+    "#<#{self.class} #{File.basename(@srcdir)}>"
+  end
+
+  #
+  # Hook Script API base methods
+  #
+
+  def srcdir_root
+    @srcdir
+  end
+
+  def objdir_root
+    @objdir
+  end
+
+  def relpath
+    @currdir
+  end
+
+  #
+  # Config Access
+  #
+
+  # module FileOperations requires this
+  def verbose?
+    @config.verbose?
+  end
+
+  # module FileOperations requires this
+  def no_harm?
+    @config.no_harm?
+  end
+
+  def verbose_off
+    begin
+      save, @config.verbose = @config.verbose?, false
+      yield
+    ensure
+      @config.verbose = save
+    end
+  end
+
+  #
+  # TASK config
+  #
+
+  def exec_config
+    exec_task_traverse 'config'
+  end
+
+  def config_dir_bin(rel)
+  end
+
+  def config_dir_lib(rel)
+  end
+
+  def config_dir_man(rel)
+  end
+
+  def config_dir_ext(rel)
+    extconf if extdir?(curr_srcdir())
+  end
+
+  def extconf
+    ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
+  end
+
+  def config_dir_data(rel)
+  end
+
+  def config_dir_conf(rel)
+  end
+
+  #
+  # TASK setup
+  #
+
+  def exec_setup
+    exec_task_traverse 'setup'
+  end
+
+  def setup_dir_bin(rel)
+    files_of(curr_srcdir()).each do |fname|
+      adjust_shebang "#{curr_srcdir()}/#{fname}"
+    end
+  end
+
+  def adjust_shebang(path)
+    return if no_harm?
+    tmpfile = File.basename(path) + '.tmp'
+    begin
+      File.open(path, 'rb') {|r|
+        first = r.gets
+        return unless File.basename(first.sub(/\A\#!/, '').split[0].to_s) == 'ruby'
+        $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
+        File.open(tmpfile, 'wb') {|w|
+          w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
+          w.write r.read
+        }
+      }
+      move_file tmpfile, File.basename(path)
+    ensure
+      File.unlink tmpfile if File.exist?(tmpfile)
+    end
+  end
+
+  def setup_dir_lib(rel)
+  end
+
+  def setup_dir_man(rel)
+  end
+
+  def setup_dir_ext(rel)
+    make if extdir?(curr_srcdir())
+  end
+
+  def setup_dir_data(rel)
+  end
+
+  def setup_dir_conf(rel)
+  end
+
+  #
+  # TASK install
+  #
+
+  def exec_install
+    rm_f 'InstalledFiles'
+    exec_task_traverse 'install'
+  end
+
+  def install_dir_bin(rel)
+    install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
+  end
+
+  def install_dir_lib(rel)
+    install_files rubyscripts(), "#{config('rbdir')}/#{rel}", 0644
+  end
+
+  def install_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    install_files rubyextentions('.'),
+                  "#{config('sodir')}/#{File.dirname(rel)}",
+                  0555
+  end
+
+  def install_dir_data(rel)
+    install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
+  end
+
+  def install_dir_conf(rel)
+    # FIXME: should not remove current config files
+    # (rename previous file to .old/.org)
+    install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
+  end
+
+  def install_dir_man(rel)
+    install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
+  end
+
+  def install_files(list, dest, mode)
+    mkdir_p dest, @config.install_prefix
+    list.each do |fname|
+      install fname, dest, mode, @config.install_prefix
+    end
+  end
+
+  def rubyscripts
+    glob_select(@config.libsrc_pattern, targetfiles())
+  end
+
+  def rubyextentions(dir)
+    ents = glob_select("*.#{@config.dllext}", targetfiles())
+    if ents.empty?
+      setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
+    end
+    ents
+  end
+
+  def targetfiles
+    mapdir(existfiles() - hookfiles())
+  end
+
+  def mapdir(ents)
+    ents.map {|ent|
+      if File.exist?(ent)
+      then ent                         # objdir
+      else "#{curr_srcdir()}/#{ent}"   # srcdir
+      end
+    }
+  end
+
+  # picked up many entries from cvs-1.11.1/src/ignore.c
+  JUNK_FILES = %w( 
+    core RCSLOG tags TAGS .make.state
+    .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+    *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+    *.org *.in .*
+  )
+
+  def existfiles
+    glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
+  end
+
+  def hookfiles
+    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+      %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+    }.flatten
+  end
+
+  def glob_select(pat, ents)
+    re = globs2re([pat])
+    ents.select {|ent| re =~ ent }
+  end
+
+  def glob_reject(pats, ents)
+    re = globs2re(pats)
+    ents.reject {|ent| re =~ ent }
+  end
+
+  GLOB2REGEX = {
+    '.' => '\.',
+    '$' => '\$',
+    '#' => '\#',
+    '*' => '.*'
+  }
+
+  def globs2re(pats)
+    /\A(?:#{
+      pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
+    })\z/
+  end
+
+  #
+  # TASK test
+  #
+
+  TESTDIR = 'test'
+
+  def exec_test
+    unless File.directory?('test')
+      $stderr.puts 'no test in this package' if verbose?
+      return
+    end
+    $stderr.puts 'Running tests...' if verbose?
+    require 'test/unit'
+    runner = Test::Unit::AutoRunner.new(true)
+    runner.to_run << TESTDIR
+    runner.run
+  end
+
+  #
+  # TASK clean
+  #
+
+  def exec_clean
+    exec_task_traverse 'clean'
+    rm_f @config.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  def clean_dir_bin(rel)
+  end
+
+  def clean_dir_lib(rel)
+  end
+
+  def clean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'clean' if File.file?('Makefile')
+  end
+
+  def clean_dir_data(rel)
+  end
+
+  def clean_dir_conf(rel)
+  end
+
+  #
+  # TASK distclean
+  #
+
+  def exec_distclean
+    exec_task_traverse 'distclean'
+    rm_f @config.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  def distclean_dir_bin(rel)
+  end
+
+  def distclean_dir_lib(rel)
+  end
+
+  def distclean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'distclean' if File.file?('Makefile')
+  end
+
+  def distclean_dir_data(rel)
+  end
+
+  def distclean_dir_conf(rel)
+  end
+
+  #
+  # lib
+  #
+
+  def exec_task_traverse(task)
+    run_hook "pre-#{task}"
+    FILETYPES.each do |type|
+      if config('without-ext') == 'yes' and type == 'ext'
+        $stderr.puts 'skipping ext/* by user option' if verbose?
+        next
+      end
+      traverse task, type, "#{task}_dir_#{type}"
+    end
+    run_hook "post-#{task}"
+  end
+
+  def traverse(task, rel, mid)
+    dive_into(rel) {
+      run_hook "pre-#{task}"
+      __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+      directories_of(curr_srcdir()).each do |d|
+        traverse task, "#{rel}/#{d}", mid
+      end
+      run_hook "post-#{task}"
+    }
+  end
+
+  def dive_into(rel)
+    return unless File.dir?("#{@srcdir}/#{rel}")
+
+    dir = File.basename(rel)
+    Dir.mkdir dir unless File.dir?(dir)
+    prevdir = Dir.pwd
+    Dir.chdir dir
+    $stderr.puts '---> ' + rel if verbose?
+    @currdir = rel
+    yield
+    Dir.chdir prevdir
+    $stderr.puts '<--- ' + rel if verbose?
+    @currdir = File.dirname(rel)
+  end
+
+  def run_hook(id)
+    path = [ "#{curr_srcdir()}/#{id}",
+             "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
+    return unless path
+    begin
+      instance_eval File.read(path), path, 1
+    rescue
+      raise if $DEBUG
+      setup_rb_error "hook #{path} failed:\n" + $!.message
+    end
+  end
+
+end   # class Installer
+
+
+class SetupError < StandardError; end
+
+def setup_rb_error(msg)
+  raise SetupError, msg
+end
+
+if $0 == __FILE__
+  begin
+    ToplevelInstaller.invoke
+  rescue SetupError
+    raise if $DEBUG
+    $stderr.puts $!.message
+    $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
+    exit 1
+  end
+end

Added: incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi.xrds
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi.xrds?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi.xrds (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi.xrds Wed Oct 11 15:17:05 2006
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+    xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
+    xmlns="xri://$xrd*($v*2.0)">
+  <XRD>
+
+    <Service priority="2">
+      <Type>http://openid.net/signon/1.1</Type>
+      <URI>http://www.myopenid.com/server</URI>
+      <openid:Delegate>http://frank.myopenid.com/</openid:Delegate>
+    </Service>
+
+  </XRD>
+  <XRD>
+
+    <Service priority="1">
+      <Type>http://bar.com/</Type>
+      <URI>http://bar.com/server</URI>
+    </Service>
+
+    <Service priority="2">
+      <Type>http://foo.com</Type>
+      <URI>http://foo.com/server</URI>
+    </Service>
+
+  </XRD>
+  <XRD>
+
+    <Service priority="0">
+      <Type>http://openid.net/signon/1.0</Type>
+      <URI>http://www.myopenid.com/server</URI>
+      <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+    </Service>
+
+  </XRD>
+</xrds:XRDS>
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi_uri.xrds
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi_uri.xrds?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi_uri.xrds (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.multi_uri.xrds Wed Oct 11 15:17:05 2006
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+    xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
+    xmlns="xri://$xrd*($v*2.0)">
+  <XRD>
+
+    <Service>
+      <Type>http://openid.net/signon/1.0</Type>
+      <URI>http://www.myopenid.com/server</URI>
+      <URI>http://example.com/server</URI>
+    </Service>
+
+  </XRD>
+</xrds:XRDS>
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.xrds
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.xrds?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.xrds (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian.xrds Wed Oct 11 15:17:05 2006
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+    xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
+    xmlns="xri://$xrd*($v*2.0)">
+  <XRD>
+
+    <Service priority="0">
+      <Type>http://openid.net/signon/1.0</Type>
+      <URI>http://www.myopenid.com/server</URI>
+      <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+    </Service>
+
+  </XRD>
+</xrds:XRDS>
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian_priority.xrds
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian_priority.xrds?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian_priority.xrds (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brian_priority.xrds Wed Oct 11 15:17:05 2006
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+    xmlns:xrds="xri://$xrds"
+    xmlns:openid="http://openid.net/xmlns/1.0"
+    xmlns="xri://$xrd*($v*2.0)">
+  <XRD>
+
+    <Service priority="2">
+      <Type>http://openid.net/signon/1.0</Type>
+      <URI>http://www.schtuff.com/?action=openid_server</URI>
+      <openid:Delegate>http://users.schtuff.com/brian</openid:Delegate>
+    </Service>
+
+    <Service priority="1">
+      <Type>http://openid.net/signon/1.0</Type>
+      <URI>http://www.myopenid.com/server</URI>
+      <openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
+    </Service>
+
+  </XRD>
+</xrds:XRDS>
+

Added: incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brianellin.mylid.xrds
URL: http://svn.apache.org/viewvc/incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brianellin.mylid.xrds?view=auto&rev=463001
==============================================================================
--- incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brianellin.mylid.xrds (added)
+++ incubator/heraldry/libraries/ruby/yadis/trunk/test/data/brianellin.mylid.xrds Wed Oct 11 15:17:05 2006
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRDS xmlns="xri://$xrds" xmlns:xrd="xri://$xrd*($v*2.0)">
+ <xrd:XRD>
+  <xrd:Service priority="1">
+   <xrd:Type>http://lid.netmesh.org/minimum-lid/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="2">
+   <xrd:Type>http://lid.netmesh.org/sso/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="3">
+   <xrd:Type>http://lid.netmesh.org/sso/1.0</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="4">
+   <xrd:Type>http://lid.netmesh.org/relying-party/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="5">
+   <xrd:Type>http://lid.netmesh.org/traversal/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="6">
+   <xrd:Type>http://lid.netmesh.org/format-negotiation/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="7">
+   <xrd:Type>http://lid.netmesh.org/post/sender/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="8">
+   <xrd:Type>http://lid.netmesh.org/post/receiver/2.0b9</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+  </xrd:Service>
+  <xrd:Service priority="9">
+   <xrd:Type>http://openid.net/signon/1.0</xrd:Type>
+   <xrd:URI>http://mylid.net/brianellin</xrd:URI>
+   <openid:Delegate xmlns:openid="http://openid.net/xmlns/1.0">http://mylid.net/brianellin</openid:Delegate>
+  </xrd:Service>
+ </xrd:XRD>
+</XRDS>



Mime
View raw message