barx 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ 0.2.0 April 1 2008
2
+ - The REXML stdlib in Ruby 1.8.6 deprecated Document#write but we still like it. Monkey-patched it back in as #simple_write.
3
+
4
+ - XriParser::AuthorityParser
5
+ - Added #appendable_query which removes XRI control parameters (and our barxdemo param) from the returned query string, per XRI Resolution 2.0 CD 02 Section 11.3.3.
6
+ - We now assemble @qxri using #appendable_query.
7
+ - Fixed @path regex to handle multiple '?'s at beginning of query string.
8
+ - Added #to_hash method to provide parser output convertible to JSON.
9
+ - Added #to_xml method to provide parser output as XML.
10
+
11
+ - XriResolver::AuthorityResolver
12
+ - Copied the CGI stdlib #escape and #unescape methods into AuthorityResolver, so we don't need to require CGI.
13
+ - Fixed all references to CGI.escape and CGI.unescape to use our local methods instead.
14
+ - Changed #build_xrds to add the XML prologue to the beginning of its output, and to strip out all return characters, giving a compact XML response.
15
+ - Added #to_pretty to return the XRDS as formatted XML using #simple_write.
16
+ - Added #last_xrd_to_s to return the last XRD as compact XML.
17
+ - Added #last_xrd_to_pretty to return the last XRD as formatted XML.
18
+ - Changed #doappend to use #appendable_query.
19
+ - We now rescue Cache.add exceptions.
20
+
21
+ - Added CacheError class
22
+
23
+ - XriResolver::ParseInputParameters#parse_query_params now removes any extra '?'s at beginning of query string.
24
+
25
+ - Removed XriResolver::XRIRoot class, and replaced it with XriResolver::XRIAuthorities hash. It's now easy for an app, having required the barx gem, to use the Hash []= or delete methods on XriResolver::XRIAuthorities to modify the available XRI root authorities.
26
+
27
+
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 Victor Grey and Kermit Snelson
1
+ Copyright (c) 2008 Victor Grey and Kermit Snelson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README CHANGED
@@ -9,3 +9,5 @@ The basic API is as follows:
9
9
  In the above example, QXRI refers to qxri as defined in section 7 of <http://www.oasis-open.org/committees/download.php/25741/xri-resolution-v2.0-wd-11-ed-06.pdf>, and params_hash is a Ruby hash of the keys and values in the Query String part of the QXRI or the relevant HTTP Accept header.
10
10
 
11
11
  See examples/README for more information. There is also a full featured XRI proxy resolver, barx-proxy, available at <http://rubyforge.org/projects/barx/>.
12
+
13
+ Author contact information and more examples are available at <http://xrisoft.org>.
@@ -1,4 +1,3 @@
1
- require 'cgi'
2
1
  require 'yaml'
3
2
  require 'rexml/document'
4
3
  require 'uri'
@@ -6,4 +5,4 @@ require 'uri'
6
5
  require File.dirname(__FILE__) + '/httpclient' ## make sure we get -our- httpclient
7
6
  require 'xri_parser'
8
7
  require 'xri_resolver'
9
-
8
+ require 'simple_write'
@@ -0,0 +1,16 @@
1
+ ## The REXML stdlib in Ruby 1.8.6 deprecated Document#write but we still like it.
2
+ ## So monkey-patching it back in as simple_write.
3
+ ## =vg
4
+ module REXML
5
+ class Document
6
+ def simple_write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
7
+ output = Output.new( output, xml_decl.encoding ) if xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
8
+ @children.each { |node|
9
+ indent( output, indent ) if node.node_type == :element
10
+ if node.write( output, indent, transitive, ie_hack )
11
+ output << "\n" unless indent<0 or node == @children[-1]
12
+ end
13
+ }
14
+ end
15
+ end
16
+ end
@@ -8,7 +8,7 @@ module XriParser
8
8
  end
9
9
  end
10
10
 
11
- attr_reader :root, :subsegments, :authority, :local, :query, :qxri
11
+ attr_reader :root, :subsegments, :authority, :local, :query, :appendable_query, :qxri
12
12
  attr_accessor :path
13
13
 
14
14
  def initialize(xri, get_root=true)
@@ -16,7 +16,6 @@ module XriParser
16
16
  @subsegments = Array.new
17
17
  xri = xri.strip rescue nil
18
18
  xri = xri_strip_scheme(xri) rescue nil
19
- @qxri = xri
20
19
  raise 'No XRI Received' if xri.nil? or xri.empty?
21
20
  #get root
22
21
  if get_root
@@ -97,9 +96,12 @@ module XriParser
97
96
 
98
97
  @subsegments << segment_buf # flush buffer at the end
99
98
  @local = xri[@subsegments.to_s.length..-1] # the rest of xri
100
- @path = @local.index('?') ? @local[/^(.*)\?/, 1] : @local # path is everything up to a question mark
99
+ @path = @local.index('?') ? @local[/^(.*?)\?/, 1] : @local # path is everything up to a question mark
101
100
  @query = @local.index('?') ? @local[/\?(.*)$/, 1] : '' # query is everything after a question mark
102
101
  @authority = self.normalized
102
+ @appendable_query = make_appendable_query(@query)
103
+ @qxri = "#{@authority}#{@path}"
104
+ @qxri << "?#{@appendable_query}" unless @appendable_query.empty?
103
105
  true
104
106
  end
105
107
 
@@ -157,6 +159,49 @@ module XriParser
157
159
  end
158
160
  end
159
161
 
162
+ def make_appendable_query(query)
163
+ q = Array.new
164
+ #extract leading extra "?"s
165
+ if query =~ /^([\?]+)(.*)$/
166
+ q << $1
167
+ query = $2
168
+ end
169
+ ## remove XRI control params (and our barxdemo param)
170
+ query.scan(/[^&]+/).each {|tok| q << tok unless tok =~ /^(barxdemo=|_xrd_r=|_xrd_t=|_xrd_m=)/}
171
+ q.to_s
172
+ end
173
+
174
+ def to_hash
175
+ h = Hash.new
176
+ h[:authority] = @authority
177
+ h[:local] = @local
178
+ h[:path] = @path
179
+ h[:query] = @query
180
+ h[:qxri] = @qxri
181
+ h[:root] = @root
182
+ h[:subsegments] = @subsegments
183
+ h
184
+ end
185
+
186
+ def to_xml
187
+ xml = %Q{<?xml version="1.0" encoding="UTF-8"?>}
188
+ xml << %Q{<parsed req="#{@qxri}">}
189
+ xml << %Q{<root>#{@root}</root>}
190
+ xml << %Q{<subsegments>}
191
+ @subsegments.each {|sub| xml << %Q{<subsegment>#{sub}</subsegment>} }
192
+ xml << %Q{</subsegments>}
193
+ xml << %Q{<authority>#{@authority}</authority>}
194
+ xml << %Q{<local>#{@local}</local>}
195
+ xml << %Q{<path>#{@path}</path>}
196
+ xml << %Q{<query>#{@query}</query>}
197
+ xml << %Q{<qxri>#{@qxri}</qxri>}
198
+ xml << %Q{</parsed>}
199
+ output = ""
200
+ doc = REXML::Document.new(xml)
201
+ doc.simple_write(output, 0)
202
+ output
203
+ end
204
+
160
205
  end
161
206
 
162
207
  class XRIRootMissing < RuntimeError; end
@@ -2,14 +2,9 @@ module XriResolver
2
2
  XRDNS = {"xrd"=>"xri://$xrd*($v*2.0)"} # XRD xml namespace
3
3
  XRDType = "xri://$res*auth*($v*2.0)"
4
4
 
5
- class XRIRoot
6
- class <<self
7
- def authorities
8
- { "@"=>{:authority_uris=>["https://at.xri.net/", "http://at.xri.net/"], :verify_server_cert=>true},
9
- "="=>{:authority_uris=>["https://equal.xri.net/", "http://equal.xri.net/"], :verify_server_cert=>true}}
10
- end
11
- end
12
- end
5
+ ## default authorities -- add or remove from this Hash as desired
6
+ XRIAuthorities = { "@"=>{:authority_uris=>["https://at.xri.net/", "http://at.xri.net/"], :verify_server_cert=>true},
7
+ "="=>{:authority_uris=>["https://equal.xri.net/", "http://equal.xri.net/"], :verify_server_cert=>true}}
13
8
 
14
9
  class AuthorityResolver
15
10
  ## usage:
@@ -55,9 +50,9 @@ module XriResolver
55
50
  return
56
51
  end
57
52
 
58
- raise UNKNOWN_ROOT, @xri.root unless Hash === XRIRoot.authorities[@xri.root]
53
+ raise UNKNOWN_ROOT, @xri.root unless Hash === XRIAuthorities[@xri.root]
59
54
  @client = HTTPClient.new
60
- @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE unless XRIRoot.authorities[@xri.root][:verify_server_cert]
55
+ @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE unless XRIAuthorities[@xri.root][:verify_server_cert]
61
56
  @accept_header = 'application/xrds+xml'
62
57
  @accept_header << ';https=true' if @req.https
63
58
 
@@ -66,7 +61,7 @@ module XriResolver
66
61
  @status_code = String.new ## status code of the last resolved subsegment
67
62
  subsegments_resolved = 0
68
63
 
69
- @authority_uris = XRIRoot.authorities[@xri.root][:authority_uris].map {|u| URI.parse(u)}
64
+ @authority_uris = XRIAuthorities[@xri.root][:authority_uris].map {|u| URI.parse(u)}
70
65
 
71
66
  errorcode = '220'
72
67
  errortext = ResponseStatus[errorcode]
@@ -110,7 +105,7 @@ module XriResolver
110
105
  sts.add_attribute('code', errorcode)
111
106
  sts.text = errortext
112
107
  qry = REXML::Element.new('Query')
113
- qry.text = CGI.unescape(@xri.subsegments[subsegments_resolved]).unpack('C*').pack('U*')
108
+ qry.text = unescape(@xri.subsegments[subsegments_resolved]).unpack('C*').pack('U*')
114
109
  xrd = REXML::Element.new('XRD')
115
110
  xrd << qry
116
111
  xrd << sts
@@ -126,13 +121,20 @@ module XriResolver
126
121
  end
127
122
 
128
123
  def resolved_successfully?
129
- @resolved == CGI.unescape(@xri.fully_qualified) and @status_code === '100'
124
+ @resolved == unescape(@xri.fully_qualified) and @status_code === '100'
130
125
  end
131
126
 
132
127
  def to_s
133
128
  build_xrds(@xrd_array)
134
129
  end
135
130
 
131
+ def to_pretty
132
+ output = ""
133
+ doc = REXML::Document.new(self.to_s)
134
+ doc.simple_write(output, 0) ## REXML::Document monkey-patched with simple_write at bottom of this file
135
+ output
136
+ end
137
+
136
138
  def to_xrds
137
139
  REXML::Document.new(self.to_s)
138
140
  end
@@ -149,6 +151,17 @@ module XriResolver
149
151
  REXML::Document.new(self.last_xrd.to_s.unpack('U*').pack('C*'))
150
152
  end
151
153
 
154
+ def last_xrd_to_s
155
+ %Q{<?xml version='1.0' encoding='UTF-8'?>#{last_xrd.to_s.unpack('U*').pack('C*').gsub(/\n/, '')}}
156
+ end
157
+
158
+ def last_xrd_to_pretty
159
+ output = ""
160
+ doc = REXML::Document.new(last_xrd_to_s)
161
+ doc.simple_write(output, 0)
162
+ output
163
+ end
164
+
152
165
  def doappend(uri, inplace=nil)
153
166
  uri_txt = uri.text
154
167
  uri_app = uri.attribute('append').value rescue 'none'
@@ -166,7 +179,7 @@ module XriResolver
166
179
  when 'path'
167
180
  uri_txt << @xri.path
168
181
  when 'query'
169
- uri_txt << @xri.query
182
+ uri_txt << @xri.appendable_query
170
183
  when 'qxri'
171
184
  uri_txt << @xri.qxri
172
185
  end
@@ -252,8 +265,8 @@ module XriResolver
252
265
  begin
253
266
  uri = @authority_uris.shift
254
267
  uri.path << '/'
255
- if subsegment[1..-1] == CGI.unescape(subsegment[1..-1])
256
- hxri = uri.merge("#{subsegment[0,1]}#{CGI.escape(subsegment[1..-1])}")
268
+ if subsegment[1..-1] == unescape(subsegment[1..-1])
269
+ hxri = uri.merge("#{subsegment[0,1]}#{escape(subsegment[1..-1])}")
257
270
  else
258
271
  hxri = uri.merge(subsegment)
259
272
  end
@@ -263,7 +276,7 @@ module XriResolver
263
276
  unless @authority_uris.empty?
264
277
  retry
265
278
  else
266
- raise XRIResolutionFailure, "Unable to resolve #{subsegment} because: #{e.message}"
279
+ raise XRIResolutionFailure, "Unable to resolve #{subsegment} because: #{e.class}: #{e.message}"
267
280
  end
268
281
  end
269
282
 
@@ -308,7 +321,11 @@ module XriResolver
308
321
  exp = Time.now.to_i + 3600
309
322
  end
310
323
  key = hxri.host + hxri.path + @accept_header
311
- Cache.add(key, xml, exp)
324
+ begin
325
+ Cache.add(key, xml, exp)
326
+ rescue Exception => e
327
+ raise CacheError, e.message
328
+ end
312
329
  end
313
330
 
314
331
  def get_header_exp(hdr)
@@ -339,8 +356,8 @@ module XriResolver
339
356
  end
340
357
 
341
358
  def build_xrds(xrd_array)
342
- xrds = %Q{<XRDS xmlns="xri://$xrds" ref="xri://#{CGI.unescape(@xri.normalized)}">\n}
343
- xrd_array.each {|xrd| xrds << "#{xrd.to_s.unpack('U*').pack('C*')}\n" }
359
+ xrds = %Q{<?xml version='1.0' encoding='UTF-8'?><XRDS xmlns="xri://$xrds" ref="xri://#{unescape(@xri.normalized)}">}
360
+ xrd_array.each {|xrd| xrds << xrd.to_s.unpack('U*').pack('C*').gsub(/\n/, '')}
344
361
  xrds << "</XRDS>"
345
362
  end
346
363
 
@@ -632,6 +649,19 @@ module XriResolver
632
649
  @xrd_array << seplist.to_xrd
633
650
  @xrd_array << chosenxrds if chosenxrds
634
651
  end
652
+
653
+ # from CGI.escape and CGI.unescape
654
+ def escape(str)
655
+ str.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
656
+ '%' + $1.unpack('H2' * $1.size).join('%').upcase
657
+ }.tr(' ', '+')
658
+ end
659
+
660
+ def unescape(string)
661
+ string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
662
+ [$1.delete('%')].pack('H*')
663
+ end
664
+ end
635
665
  end
636
666
 
637
667
  ResponseStatus = {
@@ -674,6 +704,7 @@ module XriResolver
674
704
  class XRIResolutionFailure < RuntimeError; end
675
705
  class INVALID_XRDS < XRIResolutionFailure; end
676
706
  class UNKNOWN_ROOT < XRIResolutionFailure; end
707
+ class CacheError < RuntimeError; end
677
708
 
678
709
  class SEPSelector
679
710
  ## usage:
@@ -1006,6 +1037,13 @@ module XriResolver
1006
1037
  end
1007
1038
 
1008
1039
  def parse_query_params(params)
1040
+ ## remove any extra leading "?"s
1041
+ params.each do |k,v|
1042
+ if k =~ /^[\?]+(.*)$/
1043
+ params.delete(k)
1044
+ params[$1] = v
1045
+ end
1046
+ end
1009
1047
  inputs = {:res_media_type => ""}
1010
1048
  ## get Resolution Media type
1011
1049
  if params.has_key?(:_xrd_r)
@@ -1099,4 +1137,5 @@ module XriResolver
1099
1137
  (x.to_i == y.to_i) ? (rand(3) - 1) : (x.to_i <=> y.to_i)
1100
1138
  end
1101
1139
  end
1140
+
1102
1141
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: barx
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.3
7
- date: 2007-11-06 00:00:00 +00:00
6
+ version: 0.2.0
7
+ date: 2008-04-04 00:00:00 -07:00
8
8
  summary: Provides XRI resolution services. Read more about XRI resolution at http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xri.
9
9
  require_paths:
10
10
  - lib
@@ -29,35 +29,37 @@ post_install_message:
29
29
  authors:
30
30
  - Victor Grey and Kermit Snelson
31
31
  files:
32
- - test
33
- - lib
34
32
  - bin
33
+ - CHANGELOG
35
34
  - examples
35
+ - lib
36
36
  - MIT-LICENSE
37
37
  - README
38
+ - test
39
+ - lib/barx.rb
38
40
  - lib/httpclient
39
- - lib/httpclient/cacert.p7s
40
- - lib/httpclient/http.rb
41
- - lib/httpclient/cookie.rb
42
41
  - lib/httpclient.rb
42
+ - lib/simple_write.rb
43
43
  - lib/xri_parser.rb
44
44
  - lib/xri_resolver.rb
45
- - lib/barx.rb
45
+ - lib/httpclient/cacert.p7s
46
+ - lib/httpclient/cookie.rb
47
+ - lib/httpclient/http.rb
48
+ - test/authority_parser_profile.rb
49
+ - test/test_helper.rb
46
50
  - test/unit
51
+ - test/xrds_sources
47
52
  - test/unit/all.rb
48
- - test/unit/multi_stage_resolution_test.rb
49
53
  - test/unit/authority_parser_test.rb
50
54
  - test/unit/input_param_parser_test.rb
55
+ - test/unit/multi_stage_resolution_test.rb
51
56
  - test/unit/sep_selection_test.rb
52
- - test/xrds_sources
53
- - test/xrds_sources/second_stage1
54
- - test/xrds_sources/sep1
55
- - test/xrds_sources/empty_sels_sep
56
57
  - test/xrds_sources/empty_sels_no_append_qxri_sep
58
+ - test/xrds_sources/empty_sels_sep
57
59
  - test/xrds_sources/first_stage1
58
60
  - test/xrds_sources/no_svc_sep
59
- - test/test_helper.rb
60
- - test/authority_parser_profile.rb
61
+ - test/xrds_sources/second_stage1
62
+ - test/xrds_sources/sep1
61
63
  - examples/proxri
62
64
  - examples/README
63
65
  - examples/xrioid