barx 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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