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