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.
- data/CHANGELOG +27 -0
- data/MIT-LICENSE +1 -1
- data/README +2 -0
- data/lib/barx.rb +1 -2
- data/lib/simple_write.rb +16 -0
- data/lib/xri_parser.rb +48 -3
- data/lib/xri_resolver.rb +59 -20
- metadata +18 -16
data/CHANGELOG
ADDED
@@ -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
|
+
|
data/MIT-LICENSE
CHANGED
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>.
|
data/lib/barx.rb
CHANGED
@@ -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'
|
data/lib/simple_write.rb
ADDED
@@ -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
|
data/lib/xri_parser.rb
CHANGED
@@ -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[/^(
|
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
|
data/lib/xri_resolver.rb
CHANGED
@@ -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
|
-
|
6
|
-
|
7
|
-
|
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 ===
|
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
|
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 =
|
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 =
|
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 ==
|
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.
|
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] ==
|
256
|
-
hxri = uri.merge("#{subsegment[0,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
|
-
|
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{
|
343
|
-
xrd_array.each {|xrd| xrds <<
|
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.
|
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.
|
7
|
-
date:
|
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/
|
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/
|
60
|
-
- test/
|
61
|
+
- test/xrds_sources/second_stage1
|
62
|
+
- test/xrds_sources/sep1
|
61
63
|
- examples/proxri
|
62
64
|
- examples/README
|
63
65
|
- examples/xrioid
|