infod 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/infod.rb +2 -3
  2. data/infod/Es.rb +31 -67
  3. data/infod/{W/source.rb → Es/code.rb} +6 -10
  4. data/infod/Es/css.rb +21 -0
  5. data/infod/{W → Es}/csv.rb +0 -0
  6. data/infod/Es/du.rb +16 -0
  7. data/infod/{W → Es}/feed.rb +13 -11
  8. data/infod/Es/filter.rb +75 -0
  9. data/infod/Es/find.rb +20 -0
  10. data/infod/Es/fs.rb +145 -136
  11. data/infod/Es/glob.rb +22 -0
  12. data/infod/Es/grep.rb +61 -0
  13. data/infod/Es/groonga.rb +47 -56
  14. data/infod/Es/html.rb +271 -0
  15. data/infod/Es/image.rb +114 -0
  16. data/infod/Es/in.rb +68 -0
  17. data/infod/Es/index.rb +183 -0
  18. data/infod/{W → Es}/json.rb +28 -4
  19. data/infod/Es/kv.rb +60 -0
  20. data/infod/Es/ls.rb +58 -0
  21. data/infod/Es/mail.rb +87 -0
  22. data/infod/Es/man.rb +112 -0
  23. data/infod/Es/mime.rb +59 -0
  24. data/infod/Es/out.rb +52 -0
  25. data/infod/{W/page.rb → Es/pager.rb} +7 -3
  26. data/infod/Es/pdf.rb +19 -0
  27. data/infod/Es/rdf.rb +35 -0
  28. data/infod/Es/schema.rb +99 -0
  29. data/infod/Es/search.rb +24 -0
  30. data/infod/Es/sh.rb +21 -0
  31. data/infod/{W → Es}/text.rb +26 -14
  32. data/infod/H.rb +15 -29
  33. data/infod/H/audio.rb +19 -0
  34. data/infod/H/blog.rb +15 -0
  35. data/infod/{W → H}/cal.rb +2 -31
  36. data/infod/H/edit.rb +88 -0
  37. data/infod/{W/examine/examine.rb → H/facets.rb} +17 -17
  38. data/infod/{W → H}/forum.rb +1 -0
  39. data/infod/{W/examine/sw.rb → H/hf.rb} +12 -12
  40. data/infod/H/histogram.rb +78 -0
  41. data/infod/H/mail.rb +92 -0
  42. data/infod/{W/chat.rb → H/microblog.rb} +21 -16
  43. data/infod/H/threads.rb +77 -0
  44. data/infod/H/time.rb +131 -0
  45. data/infod/H/who.rb +30 -0
  46. data/infod/{W → H}/wiki.rb +0 -0
  47. data/infod/K.rb +28 -60
  48. data/infod/N.rb +151 -74
  49. data/infod/Rb.rb +3 -3
  50. data/infod/Th.rb +27 -101
  51. data/infod/Th/404.rb +29 -36
  52. data/infod/Th/500.rb +36 -5
  53. data/infod/Th/GET.rb +48 -118
  54. data/infod/Th/POST.rb +31 -11
  55. data/infod/Th/perf.rb +37 -0
  56. data/infod/Th/util.rb +89 -0
  57. data/infod/Y.rb +24 -7
  58. data/infod/infod.rb +2 -3
  59. metadata +92 -64
  60. data/infod/Es/redis.rb +0 -3
  61. data/infod/Es/sqlite.rb +0 -3
  62. data/infod/Th/local.rb +0 -22
  63. data/infod/W.rb +0 -34
  64. data/infod/W/audio.rb +0 -56
  65. data/infod/W/blog.rb +0 -3
  66. data/infod/W/color.rb +0 -28
  67. data/infod/W/core.rb +0 -77
  68. data/infod/W/css.rb +0 -24
  69. data/infod/W/du.rb +0 -35
  70. data/infod/W/edit.rb +0 -8
  71. data/infod/W/examine/exhibit.rb +0 -34
  72. data/infod/W/examine/hist.rb +0 -55
  73. data/infod/W/examine/history.rb +0 -19
  74. data/infod/W/examine/normal.rb +0 -31
  75. data/infod/W/examine/protovis.rb +0 -30
  76. data/infod/W/examine/time/graph.rb +0 -86
  77. data/infod/W/examine/time/line.rb +0 -24
  78. data/infod/W/find.rb +0 -24
  79. data/infod/W/grep.rb +0 -27
  80. data/infod/W/html.rb +0 -143
  81. data/infod/W/image.rb +0 -61
  82. data/infod/W/kv.rb +0 -66
  83. data/infod/W/ls.rb +0 -50
  84. data/infod/W/mail.rb +0 -248
  85. data/infod/W/pdf.rb +0 -16
  86. data/infod/W/post.rb +0 -9
  87. data/infod/W/rdf.rb +0 -32
  88. data/infod/W/schema.rb +0 -172
  89. data/infod/W/search.rb +0 -33
  90. data/infod/W/shell.rb +0 -30
  91. data/infod/W/table.rb +0 -87
  92. data/infod/W/tree.rb +0 -26
  93. data/infod/W/vfs.rb +0 -175
data/infod/H/who.rb ADDED
@@ -0,0 +1,30 @@
1
+ #watch __FILE__
2
+ class E
3
+
4
+ fn '/whois/GET',->e,r{
5
+ [302,{Location: '/' + ( r.q['p'].match(/to$/) ? 'to' : 'from' ) + '/' + (URI.escape r.q['q'])},[]]
6
+ }
7
+
8
+ fn '/to/GET',->e,r{
9
+ name = e.pathSegment.uri.sub('/to/','/').tail
10
+ if !name || name.empty?
11
+ false
12
+ else
13
+ H({style: 'text-align: center',
14
+ c: [To.E.rangeP.map(&:uri).grep(/#{name}/).map{|n|
15
+ {_: :a,href: n.E.url+'?set=indexPO&p=sioc:addressed_to&view=page&v', c: n}},
16
+ {_: :style, c: "a {display:block;text-decoration:none}"}]}).hR
17
+ end}
18
+
19
+ fn '/from/GET',->e,r{
20
+ name = e.pathSegment.uri.sub('/from/','/').tail
21
+ if !name || name.empty?
22
+ false
23
+ else
24
+ H({style: 'text-align: center',
25
+ c: [Creator.E.rangeP(1e4).map(&:uri).grep(/#{name}/).map{|n|
26
+ {_: :a,href: n.E.url+'?set=indexPO&p=sioc:has_creator&view=page&v', c: n}},
27
+ {_: :style, c: "a {display:block;text-decoration:none}"}]}).hR
28
+ end}
29
+
30
+ end
File without changes
data/infod/K.rb CHANGED
@@ -1,10 +1,10 @@
1
+ #watch __FILE__
1
2
  class E
2
3
 
3
- FSbase = `pwd`.chomp
4
- Prefix = '/@' # resolver for non-local and non-HTTP URIs
5
- S = '<>' # path separator
4
+ FSbase = `pwd`.chomp ; BaseLen = FSbase.size
5
+ Prefix = '/@' # non-HTTP URI path resolution-prefix
6
+ S = /\._/ # data path-separator
6
7
 
7
- # frequently-used URIs
8
8
  W3 = 'http://www.w3.org/'
9
9
  Purl = 'http://purl.org/'
10
10
  FOAF = "http://xmlns.com/foaf/0.1/"
@@ -22,13 +22,17 @@ class E
22
22
  Type = W3 + "1999/02/22-rdf-syntax-ns#type"
23
23
  RDFs = W3 + '2000/01/rdf-schema#'
24
24
  HTTP = W3 + '2011/http#'
25
+ Header = W3 + '2011/http-headers#'
25
26
  Posix = W3 + 'ns/posix/'
26
27
  Stat = Posix + 'stat#'
27
28
  Label = RDFs + 'label'
28
29
  EXIF = 'http://www.w3.org/2003/12/exif/ns#'
29
30
  Audio = 'http://www.semanticdesktop.org/ontologies/nid3/#'
31
+ Edit = 'http://buzzword.org.uk/rdf/personal-link-types#edit'
32
+ Render = 'render/'
33
+ Apache = ENV['apache']
34
+ Nginx = ENV['nginx']
30
35
 
31
- # file-name extension -> MIME type
32
36
  MIME={
33
37
  aif: 'audio/aif',
34
38
  ans: 'text/ansi',
@@ -58,12 +62,13 @@ class E
58
62
  mp3: 'audio/mpeg',
59
63
  mp4: 'video/mp4',
60
64
  mpg: 'video/mpg',
61
- n3: 'text/rdf+n3',
65
+ n3: 'text/n3',
62
66
  nfo: 'text/nfo',
63
67
  nt: 'text/ntriples',
64
68
  ntriples: 'text/ntriples',
65
69
  owl: 'application/rdf+xml',
66
70
  pdf: 'application/pdf',
71
+ pl: 'application/perl',
67
72
  png: 'image/png',
68
73
  py: 'application/python',
69
74
  rb: 'application/ruby',
@@ -76,17 +81,20 @@ class E
76
81
  ttl: 'text/turtle',
77
82
  txt: 'text/plain',
78
83
  u: 'application/uri',
84
+ url: 'text/plain',
79
85
  wav: 'audio/wav',
80
86
  wmv: 'video/wmv',
81
87
  xlsx: 'application/excel',
82
88
  }
83
89
 
84
- # MIME type -> triplrFn
90
+ VideoFile = /(avi|flv|mkv|mpg|mp4|wmv)$/i
91
+ AudioFile = /(aif|wav|flac|mp3|m4a|aac|ogg)$/i
92
+
85
93
  MIMEsource={
86
94
  'application/atom+xml' => [:triplrFeed],
87
95
  'application/markdown' => [:triplrMarkdown],
88
96
  'application/org' => [:triplrOrg],
89
- 'application/rdf+xml' => [:triplrRDFformats,:rdfxml],
97
+ 'application/rdf+xml' => [:triplrRDF,:rdfxml],
90
98
  'application/json' => [:triplrJSON],
91
99
  'application/pdf' => [:triplrPDF],
92
100
  'application/textile' => [:triplrTextile],
@@ -95,51 +103,44 @@ class E
95
103
  'audio/mp4' => [:triplrStdOut,'faad -i',Audio],
96
104
  'audio/mpeg' => [:triplrStdOut,'id3info',Audio,/\((.*?)\)$/],
97
105
  'audio' => [:triplrStdOut,'sndfile-info',Audio],
98
- 'image' => [:triplrStdOut,'exiftool',EXIF],
106
+ 'inode/symlink' => [:triplrSymlink],
99
107
  'message/rfc822' => [:triplrMail],
100
108
  'text/ansi' => [:triplrANSI],
101
109
  'text/comma-separated-values'=>[:triplrCSV,/,/],
102
- 'text/html' => [:triplrRDFformats, :rdfa],
103
- 'text/log' => [:triplrLog],
110
+ 'text/log' => [:triplrIRC],
111
+ 'text/man' => [:triplrMan],
104
112
  'text/nfo' => [:triplrHref,'cp437'],
105
- 'text/ntriples' => [:triplrRDFformats, :ntriples],
113
+ 'text/ntriples' => [:triplrRDF, :ntriples],
106
114
  'text/plain' => [:triplrHref],
107
115
  'text/rtf' => [:triplrRTF],
108
116
  'text/semicolon-separated-values'=>[:triplrCSV,/;/],
109
117
  'text/tab-separated-values'=>[:triplrCSV,/\t/],
110
- 'text/turtle' => [:triplrRDFformats,:turtle],
118
+ 'text/turtle' => [:triplrRDF,:turtle],
111
119
  }
112
120
 
113
- # MIME type -> formatted content
114
- Render='render/'
115
- fn Render+'application/ld+json',->d,_=nil{E.renderRDF d, :jsonld}
116
- fn Render+'application/rdf+xml',->d,_=nil{E.renderRDF d, :rdfxml}
117
- fn Render+'text/ntriples',->d,_=nil{E.renderRDF d, :ntriples}
118
- fn Render+'text/turtle', ->d,_=nil{E.renderRDF d, :turtle}
119
- fn Render+'text/rdf+n3', ->d,_=nil{E.renderRDF d, :n3}
120
- fn Render+'text/n3', ->d,_=nil{E.renderRDF d, :n3}
121
-
122
- # render a view even if requested file exists
121
+ # prefer a view even if requested file exists
123
122
  MIMEcook={
124
123
  'application/atom+xml' => true,
125
124
  'application/markdown' => true,
126
- 'application/json' => true,
127
125
  'application/json+rdf' => true,
128
126
  'application/org' => true,
129
127
  'application/textile' => true,
128
+ 'application/uri' => true,
130
129
  'application/word' => true,
130
+ 'inode/symlink' => true,
131
131
  'message/rfc822'=> true,
132
132
  'text/ansi'=>true,
133
133
  'text/log'=>true,
134
+ 'text/man'=>true,
134
135
  'text/nfo'=>true,
135
136
  'text/rtf'=>true,
136
137
  }
137
- %w{c ruby haskell php python}.map{|t|
138
+
139
+ %w{c c++ fortran haskell makefile pascal perl php python ruby}.map{|t|
138
140
  %w{application/ text/x-}.map{|m|
139
141
  MIMEcook[m+t] = true
140
142
  }}
141
143
 
142
- # short -> full URI
143
144
  Abbrev={
144
145
  "dc" => DC,
145
146
  "foaf" => FOAF,
@@ -149,7 +150,7 @@ class E
149
150
  "stat" => Stat,
150
151
  }
151
152
 
152
- # expose these literals as a path-name
153
+ # literal to pathname types
153
154
  Literal={}
154
155
  [Purl+'dc/elements/1.1/date',
155
156
  Date,
@@ -157,41 +158,8 @@ class E
157
158
  Modified,
158
159
  ].map{|f|Literal[f]=true}
159
160
 
160
- def mime
161
- @mime ||= (# dereferenced symlink
162
- f = readlink
163
-
164
- # filename extension
165
- x = f.ext.downcase.to_sym
166
-
167
- # directory?
168
- if d?
169
- "inode/directory"
170
- # local MIME-types table
171
- elsif MIME[x]
172
- # puts "found mime for #{x} -> #{MIME[x]}"
173
- MIME[x]
174
- # Rack MIME-types table
175
- elsif Rack::Mime::MIME_TYPES[t = '.' + x.to_s]
176
- Rack::Mime::MIME_TYPES[t]
177
- # procmail uses a prefix not an extension
178
- elsif f.base.index('msg.')==0
179
- "message/rfc822"
180
- # ask FILE(1)
181
- elsif f.e
182
- `file --mime-type -b #{f.sh}`.chomp
183
- # default
184
- else
185
- "application/octet-stream"
186
- end)
187
- end
188
-
189
161
  def == u
190
162
  to_s == u.to_s
191
163
  end
192
164
 
193
- Nginx = ENV['nginx']
194
- Apache = ENV['apache']
195
- Version = 'http://web.whats-your.name/www/'
196
-
197
165
  end
data/infod/N.rb CHANGED
@@ -1,39 +1,49 @@
1
1
  %w{base64 cgi shellwords}.each{|r|require(r)}
2
2
 
3
3
  def E e
4
- return e if e.class == E
5
- return e unless e
6
4
  E.new e
7
5
  end
8
6
 
9
7
  class E
10
- def E.[] u; E u end
11
- def E e=uri; super e end
12
8
 
13
- attr_reader :uri
14
- def initialize uri; @uri = uri.to_s end
9
+ def E.[] u; u.E end
10
+
11
+ def E arg=nil
12
+ if arg
13
+ E.new arg
14
+ else
15
+ self
16
+ end
17
+ end
15
18
 
16
- def base
17
- File.basename path
19
+ attr_reader :uri
20
+
21
+ def initialize uri
22
+ @uri = uri.to_s
18
23
  end
19
24
 
20
- def bare
21
- base.sub(/\.#{ext}$/,'')
22
- rescue
23
- base
25
+ def basename
26
+ File.basename path
24
27
  end
28
+ alias_method :base, :basename
25
29
 
26
- def docBase
27
- readlink.uri.
28
- split(/#/)[0].E.
29
- do{|d|
30
- d.dirname.as d.bare}
30
+ def barename
31
+ basename.sub(/\.#{ext}$/,'')
32
+ rescue
33
+ basename
31
34
  end
35
+ alias_method :bare, :barename
32
36
 
33
- def ef; @ef ||= docBase.a('.e') end
34
- def nt; @nt ||= docBase.a('.nt') end
35
- def ttl; @ttl ||= docBase.a('.ttl') end
37
+ def ef; @ef ||= docBase.a('.e') end
38
+ def nt; @nt ||= docBase.a('.nt') end
39
+ def ttl; @ttl||= docBase.a('.ttl') end
36
40
 
41
+ def docBase
42
+ uri.split(/#/)[0].E.do{|d|
43
+ d.dirname.as d.bare }
44
+ end
45
+
46
+ # same as above, but w/ URI errors
37
47
  def docBaseURI
38
48
  u = URI uri
39
49
  s = u.scheme
@@ -49,21 +59,50 @@ class E
49
59
  uri.frag
50
60
  end
51
61
 
52
- def docs
53
- (e ? [self] : []). # directly-referenced
54
- concat(docBase.glob ".{e,html,n3,nt,owl,rdf,ttl}"). # docs
55
- concat((d? && uri[-1]=='/') ? c : []) # trailing slash -> children
62
+ def parent
63
+ E Pathname.new(uri).parent
64
+ end
65
+
66
+ def parents
67
+ parent.do{|p|
68
+ p.uri.match(/^[.\/]+$/) ? [p] : [p].concat(p.parents)}
69
+ end
70
+
71
+ def cascade
72
+ [self].concat parents
56
73
  end
57
74
 
58
75
  def dirname
59
- no.dirname.E
76
+ n = node.dirname
77
+ n = '/' if n.to_s.size <= BaseLen
78
+ n.E
60
79
  end
61
-
62
- # generate URL for non-URL identifier (mail ID, Tag URI..)
80
+ alias_method :dir, :dirname
81
+
82
+ # local URL from unlocatable identifier (mail MSGID, etc)
63
83
  def url
64
84
  path? ? uri : Prefix + (CGI.escape uri)
65
- end
66
-
85
+ end
86
+
87
+ # local URL even if locatable-identifier
88
+ def localURL e
89
+ # path
90
+ if uri.index('/') == 0
91
+ uri
92
+ # host match
93
+ elsif uri.index('http://'+e['SERVER_NAME']+'/') == 0
94
+ pathSegment.uri
95
+ # non-local
96
+ else
97
+ Prefix + (CGI.escape uri)
98
+ end
99
+ end
100
+
101
+ def pathSegment
102
+ m = uri.match(/^([a-z]+:\/\/[^\/]+)?(\/.*)/)
103
+ m && m[2] && m[2].E || nil
104
+ end
105
+
67
106
  # URI extension :: E -> string
68
107
  def ext
69
108
  File.extname(uri).tail||''
@@ -77,84 +116,115 @@ class E
77
116
  uri.expand.E
78
117
  end
79
118
 
80
- # concatenate URIs with separator
81
- # s :: E -> E
82
- def s b
83
- u.a E(b).path
119
+ def prependURI u
120
+ E u.to_s + uri
84
121
  end
85
122
 
86
- def prependURI s
87
- (s + uri).E
123
+ def appendURI u
124
+ E uri + u.to_s
88
125
  end
89
126
 
90
- def appendURI s
91
- (uri + s).E
127
+ def appendSlashURI u
128
+ E uri.t + u.to_s
92
129
  end
93
- alias_method :a, :appendURI
94
- alias_method :+, :appendURI
95
130
 
96
- def appendSlashURI s
97
- E uri.t + s
131
+ def concatURI b
132
+ u.appendURI b.E.path
98
133
  end
134
+
135
+ alias_method :a, :appendURI
136
+ alias_method :+, :appendURI
99
137
  alias_method :as, :appendSlashURI
100
138
 
101
- # path? :: E -> Bool
102
139
  def path?
103
140
  uri.path?
104
141
  end
105
142
 
106
- # path :: E -> String
143
+ # URI -> path
107
144
  def path
108
145
  @path ||=
109
- path? ? (uri.match(/^\//) ?
110
- uri : '/'+uri) :
111
- '/E/'+uri.h.dive[0..5]+(Base64.urlsafe_encode64 uri)
146
+ (if path?
147
+ if uri.match /^\//
148
+ uri
149
+ else
150
+ '/' + uri
151
+ end
152
+ else
153
+ '/E/' + uri.h.dive[0..5] + (Base64.urlsafe_encode64 uri)
154
+ end)
112
155
  end
113
156
 
114
157
  def u
115
- @u ||= E (f ? dirname + '/.' + File.basename(path) : path.t + E::S)
158
+ # data-storage path for resource
159
+ @u ||= E (f ? dirname + '/.' + (File.basename path) : path.t + '._')
116
160
  end
117
161
 
118
- # E (_ _ o) -> E o
119
- def ro
120
- uri.split(/#{E::S}\//)[-1].unpath false
162
+ # (_ _ o) -> o
163
+ def innerPath
164
+ (uri.split S)[-1].unpath
121
165
  end
166
+ alias_method :ro, :innerPath
122
167
 
123
168
  def sh
124
169
  d.force_encoding('UTF-8').sh
125
170
  end
126
171
 
127
- # literal -> URI
172
+ # literals to URIs
173
+
174
+ def E.literal o
175
+ E['/'].literal o
176
+ end
177
+
128
178
  def literal o
179
+
180
+ # already a URI
181
+ return self if o.class == E
182
+
183
+ # blob for non-strings
129
184
  return literalBlob o unless o.class == String
185
+
186
+ # whitelisted predicateURIs to paths
130
187
  return literalURI o if (Literal[uri] || o.size<=88) && !o.match(/\//)
188
+
189
+ # string matches URI format
131
190
  return E o if o.match %r{\A[a-z]+://[^\s]+\Z}
191
+
192
+ # blob
132
193
  literalBlob o
194
+
133
195
  end
134
196
 
135
197
  # pathname for short literals
136
198
  def literalURI o
137
- E "/u/"+(Literal[uri] && o.gsub(/[\.:\-T+]/,'/'))+'/'+o
199
+ E "/l/"+(Literal[uri] && o.gsub(/[\.:\-T+]/,'/'))+'/'+o
138
200
  end
139
201
 
140
202
  def literalBlobURI o
141
203
  if o.class == String
142
- E "/blob/"+o.h.dive
204
+ E "/E/blob/"+o.h.dive
143
205
  else
144
- E "/json/"+[o].to_json.h.dive
206
+ E "/E/json/"+[o].to_json.h.dive
145
207
  end
146
208
  end
147
209
 
210
+ def literalBlob o
211
+ u = literalBlobURI o
212
+ u.w o, !o.class == String unless u.f
213
+ end
214
+
148
215
  # spaceship
149
216
  def <=> c
150
217
  to_s <=> c.to_s
151
218
  end
152
219
 
153
- # example: E('wiggly').to_s -> "wiggly"
154
- def to_s # string
220
+ def to_s
155
221
  uri
156
222
  end
157
223
 
224
+ def to_h
225
+ {'uri' => uri}
226
+ end
227
+
158
228
  end
159
229
 
160
230
  class Hash
@@ -199,34 +269,41 @@ class String
199
269
  Shellwords.escape self
200
270
  end
201
271
 
202
- BaseLen = E::FSbase.size.succ
203
-
204
- def pathToURI r = true
205
- self[BaseLen..-1].unpath r
272
+ def unpathFs
273
+ self[E::BaseLen..-1].do{|p|
274
+ (p.match(/^\/([a-z]+:)\/+(.*)/).do{|m|m[1]+'//'+m[2]}||p).E}
206
275
  end
207
276
 
208
- # string -> E || literal
209
- def unpath r=true # dereference literal?
277
+ # path -> URI || literal
278
+ def unpath
210
279
 
211
- if m=(match /^([a-z]+:)\/+(.*)/) # URL
212
- (m[1]+'//'+m[2]).E
280
+ # URI with scheme
281
+ if m = (match /^\/([a-z]+:)\/+(.*)/)
282
+ (m[1] + '//' + m[2]).E
213
283
 
214
- elsif match /^blob/ # string
215
- r ? ('/'+self).E.r : ('/'+self).E
284
+ # String literal in store
285
+ elsif match /^\/E\/blob/
286
+ self.E.r
216
287
 
217
- elsif match /^json/ # JSON
218
- r ? (('/'+self).E.r true) : ('/'+self).E
288
+ # JSON literal in store
289
+ elsif match /^\/E\/json/
290
+ self.E.r true
219
291
 
220
- elsif match /^u\// # trie
221
- r ? (File.basename self) : ('/'+self).E
292
+ # String literal in basename
293
+ elsif match /^\/l\//
294
+ File.basename self
222
295
 
223
- elsif match /^E\/..\/..\// # !fs-compatible URI
224
- self[8..-1].match(/([^.]+)(.*)/).do{|c|
296
+ # URI (opaque)
297
+ elsif match /^\/E\/..\//
298
+ self[9..-1].match(/([^.]+)(.*)/).do{|c|
225
299
  (Base64.urlsafe_decode64 c[1]) + c[2]
226
300
  }.E
227
- else # path
228
- ('/'+self).E
301
+
302
+ # path
303
+ else
304
+ self.E
229
305
  end
306
+
230
307
  end
231
308
 
232
309
  def E