infod 0.0.3.1 → 0.0.3.2
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/infod.rb +1 -6
- data/infod/404.rb +3 -4
- data/infod/500.rb +3 -2
- data/infod/GET.rb +23 -14
- data/infod/HEAD.rb +1 -1
- data/infod/HTTP.rb +24 -40
- data/infod/POST.rb +18 -16
- data/infod/audio.rb +12 -4
- data/infod/blog.rb +1 -1
- data/infod/code.rb +2 -2
- data/infod/constants.rb +6 -6
- data/infod/csv.rb +27 -4
- data/infod/edit.rb +58 -42
- data/infod/feed.rb +55 -27
- data/infod/fs.rb +6 -4
- data/infod/glob.rb +3 -4
- data/infod/graph.rb +66 -50
- data/infod/grep.rb +12 -9
- data/infod/groonga.rb +35 -50
- data/infod/html.rb +82 -55
- data/infod/image.rb +1 -1
- data/infod/index.rb +23 -73
- data/infod/infod.rb +1 -6
- data/infod/kv.rb +8 -6
- data/infod/lambda.rb +2 -0
- data/infod/ls.rb +21 -15
- data/infod/mail.rb +36 -27
- data/infod/man.rb +3 -3
- data/infod/microblog.rb +3 -3
- data/infod/mime.rb +1 -0
- data/infod/names.rb +28 -92
- data/infod/page.rb +10 -4
- data/infod/rdf.rb +11 -4
- data/infod/ruby.rb +2 -1
- data/infod/schema.rb +4 -20
- data/infod/sh.rb +3 -5
- data/infod/text.rb +5 -3
- data/infod/threads.rb +12 -13
- data/infod/time.rb +16 -14
- data/infod/webid.rb +0 -0
- metadata +3 -7
- data/infod/PATCH.rb +0 -5
- data/infod/css.rb +0 -21
- data/infod/du.rb +0 -16
- data/infod/json.rb +0 -38
- data/infod/search.rb +0 -16
data/infod.rb
CHANGED
@@ -4,13 +4,12 @@ lambda
|
|
4
4
|
mime
|
5
5
|
404
|
6
6
|
500
|
7
|
+
grep
|
7
8
|
audio
|
8
9
|
blog
|
9
10
|
cal
|
10
11
|
code
|
11
|
-
css
|
12
12
|
csv
|
13
|
-
du
|
14
13
|
edit
|
15
14
|
facets
|
16
15
|
feed
|
@@ -20,7 +19,6 @@ fs
|
|
20
19
|
GET
|
21
20
|
glob
|
22
21
|
graph
|
23
|
-
grep
|
24
22
|
groonga
|
25
23
|
HEAD
|
26
24
|
histogram
|
@@ -28,7 +26,6 @@ html
|
|
28
26
|
HTTP
|
29
27
|
image
|
30
28
|
index
|
31
|
-
json
|
32
29
|
kv
|
33
30
|
ls
|
34
31
|
mail
|
@@ -36,13 +33,11 @@ man
|
|
36
33
|
microblog
|
37
34
|
names
|
38
35
|
page
|
39
|
-
PATCH
|
40
36
|
POST
|
41
37
|
postscript
|
42
38
|
rdf
|
43
39
|
ruby
|
44
40
|
schema
|
45
|
-
search
|
46
41
|
sh
|
47
42
|
text
|
48
43
|
threads
|
data/infod/404.rb
CHANGED
@@ -16,7 +16,7 @@ r.map{|k,v| s[Header + k] = k == 'uri' ? v : [v] }
|
|
16
16
|
s[Type] = [E[HTTP+'Response']]
|
17
17
|
s[HTTP+'statusCodeValue'] = [404]
|
18
18
|
s[Header+'HTTP_HOST'] = [E['http://' + s[Header+'HTTP_HOST'][0]]] if s[Header+'HTTP_HOST']
|
19
|
-
s[Edit] = [E[r['REQUEST_PATH']+'?graph=
|
19
|
+
s[Edit] = [E[r['REQUEST_PATH']+'?graph=create']]
|
20
20
|
s['#query'] = [r.q]
|
21
21
|
s['#seeAlso'] = [e.parent,*e.a('*').glob]
|
22
22
|
r.q['view'] = '404'
|
@@ -27,9 +27,8 @@ s[HTTP+'statusCodeValue'] = [404]
|
|
27
27
|
[H.css('/css/404'),{_: :style, c: "a {background-color:#{E.cs}}"},
|
28
28
|
d.html]}
|
29
29
|
|
30
|
-
# a placeholder graph
|
31
|
-
|
32
|
-
fn 'protograph/_',->d,_,m{
|
30
|
+
# a resource-placeholder graph
|
31
|
+
fn 'protograph/blank',->d,_,m{
|
33
32
|
m[d.uri] = {}
|
34
33
|
rand.to_s.h}
|
35
34
|
|
data/infod/500.rb
CHANGED
@@ -25,8 +25,9 @@ class E
|
|
25
25
|
{_: :td, class: :index, c: p[1]},
|
26
26
|
{_: :td, class: :context, c: (p[2]||'').hrefs}].cr}}.cr]}]}]}]]]}
|
27
27
|
|
28
|
-
F['/500/GET'] = ->e,r{
|
29
|
-
|
28
|
+
F['/500/GET'] = ->e,r{
|
29
|
+
body = H [Errors.sort_by{|u,r|r[:time]}.reverse.html, H.css('/css/500')]
|
30
|
+
[200, {'Content-Type'=>'text/html; charset=utf-8'}, [body]]}
|
30
31
|
|
31
32
|
F['view/'+COGS+'Exception']=->e,r{
|
32
33
|
e.values.map{|e|
|
data/infod/GET.rb
CHANGED
@@ -10,7 +10,7 @@ class E
|
|
10
10
|
|
11
11
|
elsif file = [self,pathSegment].compact.find(&:f)
|
12
12
|
|
13
|
-
# file exists
|
13
|
+
# file exists. check if client or server want it transformed to another MIME
|
14
14
|
a = @r.accept.values.flatten
|
15
15
|
accepted = a.empty? || (a.member? file.mimeP) || (a.member? '*/*')
|
16
16
|
(!accepted || MIMEcook[file.mimeP] || @r.q.has_key?('view')) ?
|
@@ -23,7 +23,7 @@ class E
|
|
23
23
|
|
24
24
|
def getFile
|
25
25
|
@r['ETag'] = [m,size].h
|
26
|
-
maybeSend mimeP,->{self}
|
26
|
+
maybeSend mimeP,->{self}
|
27
27
|
end
|
28
28
|
|
29
29
|
def resource
|
@@ -42,13 +42,13 @@ class E
|
|
42
42
|
|
43
43
|
m = {}
|
44
44
|
|
45
|
-
# graph
|
45
|
+
# graph-identity (model)
|
46
46
|
g = @r.q['graph']
|
47
47
|
graphID = (g && F['protograph/' + g] || F['protograph/'])[self,@r.q,m]
|
48
48
|
|
49
49
|
return F[E404][self,@r] if m.empty?
|
50
50
|
|
51
|
-
# response
|
51
|
+
# response-identity (view)
|
52
52
|
@r['ETag'] ||= [@r.q['view'].do{|v|F['view/' + v] && v}, graphID, @r.format, Watch].h
|
53
53
|
|
54
54
|
maybeSend @r.format, ->{
|
@@ -78,18 +78,13 @@ class E
|
|
78
78
|
!((m=@r['HTTP_IF_NONE_MATCH']) && m.strip.split(/\s*,\s*/).include?(@r['ETag']))
|
79
79
|
end
|
80
80
|
|
81
|
-
def maybeSend m, b
|
82
|
-
send? ?
|
83
|
-
b[].do{|b|
|
84
|
-
|
85
|
-
h = {'Content-Type'=> m,
|
86
|
-
'ETag'=> @r['ETag']}
|
87
|
-
|
81
|
+
def maybeSend m, b; c = 200
|
82
|
+
send? ?
|
83
|
+
b[].do{|b| # continue
|
84
|
+
h = {'Content-Type'=> m, 'ETag'=> @r['ETag']}
|
88
85
|
h.update({'Cache-Control' => 'no-transform'}) if m.match /^(audio|image|video)/ # already compresed
|
89
|
-
h.update({'Link' => '<' + @r['uri'] + '?view>; rel=meta'}) if iR # link to description
|
90
|
-
# h.update({'MS-Author-Via' => 'SPARQL'}) # authoring preference
|
91
86
|
|
92
|
-
# frontend-specific
|
87
|
+
# frontend-specific handlers
|
93
88
|
b.class == E ? (Nginx ? # nginx chosen?
|
94
89
|
[c,h.update({'X-Accel-Redirect' => '/fs' + b.path}),[]] : # Nginx handler
|
95
90
|
Apache ? # Apache chosen?
|
@@ -101,4 +96,18 @@ class E
|
|
101
96
|
[304,{},[]] # client has response
|
102
97
|
end
|
103
98
|
|
99
|
+
# user-patchable default handler - use index.html or defer to internal default-handler #response
|
100
|
+
fn '/GET',->e,r{
|
101
|
+
x = 'index.html'
|
102
|
+
i = [e,e.pathSegment].compact.map{|e|e.as x}.find &:e
|
103
|
+
if i && !r['REQUEST_URI'].match(/\?/)
|
104
|
+
if e.uri[-1] == '/' # inside dir?
|
105
|
+
i.env(r).getFile # show index
|
106
|
+
else # descend into dir
|
107
|
+
[301, {Location: e.uri.t}, []]
|
108
|
+
end
|
109
|
+
else
|
110
|
+
e.response
|
111
|
+
end}
|
112
|
+
|
104
113
|
end
|
data/infod/HEAD.rb
CHANGED
@@ -10,7 +10,7 @@ class E
|
|
10
10
|
|
11
11
|
# HEAD response-codes on a (.u) list of URIs
|
12
12
|
def checkURIs
|
13
|
-
r = uris.
|
13
|
+
r = uris.map{|u|
|
14
14
|
c = [`curl -IsA 404? "#{u}"`.lines.to_a[0].match(/\d{3}/)[0].to_i,u] # HEAD
|
15
15
|
puts c.join ' '
|
16
16
|
c } # status, uri tuple
|
data/infod/HTTP.rb
CHANGED
@@ -4,15 +4,18 @@ require 'rack'
|
|
4
4
|
class E
|
5
5
|
|
6
6
|
def E.call e
|
7
|
-
|
8
|
-
|
7
|
+
e.extend Th # add HTTP utility functions to environment table
|
8
|
+
dev # see if watched files were changed
|
9
9
|
e['HTTP_X_FORWARDED_HOST'].do{|h| e['SERVER_NAME'] = h }
|
10
|
-
|
10
|
+
path = CGI.unescape e['REQUEST_PATH'].force_encoding('UTF-8').gsub '+','%2B'
|
11
|
+
resource = E['http://'+e['SERVER_NAME']+path]
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
if resource.inside
|
14
|
+
e['uri'] = resource.uri
|
15
|
+
(resource.env e).send e['REQUEST_METHOD']
|
16
|
+
else
|
17
|
+
[403,{},[]]
|
18
|
+
end
|
16
19
|
|
17
20
|
rescue Exception => x
|
18
21
|
F['E500'][x,e]
|
@@ -20,37 +23,22 @@ class E
|
|
20
23
|
|
21
24
|
end
|
22
25
|
|
23
|
-
class String
|
24
|
-
|
25
|
-
# querystring parse
|
26
|
-
def qp
|
27
|
-
d={}
|
28
|
-
split(/&/).map{|e|
|
29
|
-
k,v=e.split(/=/,2).map{|x|
|
30
|
-
CGI.unescape x}
|
31
|
-
d[k]=v}
|
32
|
-
d
|
33
|
-
end
|
34
|
-
|
35
|
-
def hR
|
36
|
-
[200, {'Content-Type'=>'text/html; charset=utf-8'}, [self]]
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
26
|
module Th
|
42
27
|
|
43
|
-
#
|
44
|
-
def qs
|
45
|
-
(['GET','HEAD'].member? verb) ? self['QUERY_STRING'] : self['rack.input'].read
|
46
|
-
end
|
47
|
-
|
48
|
-
# parsed query-string
|
28
|
+
# Query-String -> Hash
|
49
29
|
def q
|
50
|
-
@q ||=
|
30
|
+
@q ||=
|
31
|
+
(if q = self['QUERY_STRING']
|
32
|
+
h = {}
|
33
|
+
q.split(/&/).map{|e| k,v = e.split(/=/,2).map{|x| CGI.unescape x }
|
34
|
+
h[k] = v }
|
35
|
+
h
|
36
|
+
else
|
37
|
+
{}
|
38
|
+
end)
|
51
39
|
end
|
52
40
|
|
53
|
-
# Accept
|
41
|
+
# Accept -> Hash
|
54
42
|
def accept_ k=''
|
55
43
|
d={}
|
56
44
|
self['HTTP_ACCEPT'+k].do{|k|
|
@@ -66,7 +54,7 @@ module Th
|
|
66
54
|
end
|
67
55
|
|
68
56
|
def conneg
|
69
|
-
#
|
57
|
+
# specific format-variant URI
|
70
58
|
{ '.html' => 'text/html',
|
71
59
|
'.jsonld' => 'application/ld+json',
|
72
60
|
'.nt' => 'text/ntriples',
|
@@ -75,7 +63,7 @@ module Th
|
|
75
63
|
}[File.extname self['uri']].do{|mime|
|
76
64
|
return mime}
|
77
65
|
|
78
|
-
# Accept
|
66
|
+
# Accept formats
|
79
67
|
accept.sort.reverse.map{|q,mimes|
|
80
68
|
mimes.map{|mime|
|
81
69
|
return mime if E::F[E::Render+mime]}}
|
@@ -84,15 +72,11 @@ module Th
|
|
84
72
|
|
85
73
|
def accept; @accept ||= accept_ end
|
86
74
|
|
87
|
-
def verb
|
88
|
-
self['REQUEST_METHOD']
|
89
|
-
end
|
90
|
-
|
91
75
|
end
|
92
76
|
|
93
77
|
class Hash
|
94
78
|
|
95
|
-
#
|
79
|
+
# Hash -> Query-String
|
96
80
|
def qs
|
97
81
|
'?'+map{|k,v|k.to_s+'='+(v ? (CGI.escape [*v][0].to_s) : '')}.intersperse("&").join('')
|
98
82
|
end
|
data/infod/POST.rb
CHANGED
@@ -1,34 +1,36 @@
|
|
1
|
-
|
1
|
+
watch __FILE__
|
2
2
|
class E
|
3
3
|
|
4
4
|
def POST
|
5
5
|
type = @r['CONTENT_TYPE']
|
6
6
|
case type
|
7
7
|
when /^application\/sparql-update/
|
8
|
-
|
8
|
+
puts "SPARQL"
|
9
9
|
when /^application\/x-www-form-urlencoded/
|
10
|
-
|
10
|
+
changed = false
|
11
11
|
(Rack::Request.new @r).params.map{|k,v|
|
12
|
-
s, p, o = (CGI.unescape k).split
|
12
|
+
s, p, o = (CGI.unescape k).split /\/\._/
|
13
13
|
if s && p && o
|
14
|
-
oP = o
|
15
14
|
s, p, o = [s, p, o].map &:unpath
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
if s.uri.match(/^http/) && p.uri.match(/^http/)
|
16
|
+
oO = v.match(/\A(\/|http)[\S]+\Z/) ? v.E : F['cleanHTML'][v]
|
17
|
+
if o != oO
|
18
|
+
changed = true
|
19
|
+
s[p,o,oO]
|
20
|
+
end
|
22
21
|
end
|
23
22
|
end}
|
24
|
-
if
|
23
|
+
if changed
|
25
24
|
g = {}
|
26
|
-
fromStream g, :
|
27
|
-
|
25
|
+
fromStream g, :triplrDoc
|
26
|
+
if g.empty?
|
27
|
+
ef.deleteNode
|
28
|
+
else
|
29
|
+
ef.w g, true
|
30
|
+
end
|
28
31
|
end
|
29
32
|
end
|
30
|
-
|
31
|
-
[303,{'Location'=>uri},[]]
|
33
|
+
[303,{'Location'=>uri+'?graph=edit'},[]]
|
32
34
|
end
|
33
35
|
|
34
36
|
end
|
data/infod/audio.rb
CHANGED
@@ -3,12 +3,20 @@ class E
|
|
3
3
|
VideoFile = /(avi|flv|mkv|mpg|mp4|wmv)$/i
|
4
4
|
AudioFile = /(aif|wav|flac|mp3|m4a|aac|ogg)$/i
|
5
5
|
|
6
|
-
fn 'set/audio',->d,e,m{
|
7
|
-
|
6
|
+
fn 'set/audio',->d,e,m{
|
7
|
+
e['view'] = 'audio'
|
8
|
+
d.take.select{|e|e.ext.match AudioFile}}
|
8
9
|
|
10
|
+
fn 'set/video',->d,e,m{
|
11
|
+
e['view'] = 'audio'
|
12
|
+
e['video'] = true
|
13
|
+
d.take.select{|e|e.ext.match VideoFile}}
|
14
|
+
|
15
|
+
# table of audio-resource properties
|
9
16
|
AudioK = {}
|
10
|
-
%w{Album-Movie-Show_title Lead_performers-Soloists Title-songname-content_description}.
|
11
|
-
|
17
|
+
%w{Album-Movie-Show_title Lead_performers-Soloists Title-songname-content_description}.map{|a|Audio + a}.
|
18
|
+
concat(['uri', Stat+'mtime', Stat+'size']).
|
19
|
+
map{|p|AudioK[p] = true}
|
12
20
|
|
13
21
|
fn 'view/audio',->d,e{ d = d.dup
|
14
22
|
|
data/infod/blog.rb
CHANGED
@@ -21,7 +21,7 @@ class E
|
|
21
21
|
when /reddit/ # minimal view
|
22
22
|
F['view/'+SIOCt+'BoardPost'][{u => r},e]
|
23
23
|
when /universalhub/ # logo + trim spacehogging tagjunk
|
24
|
-
c = Nokogiri::HTML.
|
24
|
+
c = Nokogiri::HTML.fragment r[Content][0]
|
25
25
|
c.css('section').map{|x|x.remove}
|
26
26
|
{c: [{_: :a, href: r['http://purl.org/rss/1.0/link'][0].E.uri,
|
27
27
|
c: [{_: :img, src: '/logos/uhub.png',style: 'position:absolute;top:-93px'},
|
data/infod/code.rb
CHANGED
@@ -27,8 +27,8 @@ class E
|
|
27
27
|
# triplr/view mappings
|
28
28
|
[ma,mt].map{|m|
|
29
29
|
MIMEsource[m] ||= [:triplrSourceCode]
|
30
|
+
fn 'view/'+m, F['view/code']}}
|
30
31
|
|
31
|
-
|
32
|
-
}}
|
32
|
+
MIMEsource['text/css'] ||= [:triplrSourceCode] # i hear CSS is Turing complete now, http://inamidst.com/whits/2014/formats
|
33
33
|
|
34
34
|
end
|
data/infod/constants.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
class E
|
2
2
|
|
3
3
|
FSbase = `pwd`.chomp ; BaseLen = FSbase.size
|
4
|
-
URIURL = '/@' # non-HTTP URI path resolution-prefix
|
5
4
|
S = /\._/ # data path-separator
|
6
5
|
|
7
6
|
W3 = 'http://www.w3.org/'
|
@@ -15,23 +14,24 @@ class E
|
|
15
14
|
DC = Purl + 'dc/terms/'
|
16
15
|
Date = DC + 'date'
|
17
16
|
Title = DC + 'title'
|
18
|
-
Name =
|
17
|
+
Name = SIOC + 'name'
|
19
18
|
To = SIOC + 'addressed_to'
|
20
19
|
Creator = SIOC + 'has_creator'
|
21
20
|
Content = SIOC + 'content'
|
22
21
|
XHV = W3 + '1999/xhtml/vocab#'
|
23
22
|
RDFns = W3 + "1999/02/22-rdf-syntax-ns#"
|
23
|
+
RDFs = W3 + '2000/01/rdf-schema#'
|
24
|
+
# RDFns = W3 + 'ns/rdf#'
|
25
|
+
# RDFs = W3 + 'ns/rdfs#'
|
24
26
|
EXIF = W3 + '2003/12/exif/ns#'
|
25
27
|
WF = W3 + '2005/01/wf/flow#'
|
26
28
|
HTTP = W3 + '2011/http#'
|
27
29
|
Header = W3 + '2011/http-headers#'
|
28
30
|
LDP = W3 + 'ns/ldp#'
|
29
|
-
Next = LDP+'nextPage'
|
30
|
-
Prev = LDP+'prevPage'
|
31
|
+
Next = LDP + 'nextPage'
|
32
|
+
Prev = LDP + 'prevPage'
|
31
33
|
Posix = W3 + 'ns/posix/'
|
32
34
|
Type = RDFns+ "type"
|
33
|
-
# Type = W3 + "ns/rdf#type"
|
34
|
-
RDFs = W3 + 'ns/rdfs#'
|
35
35
|
PAC = DIG + '2008/PAC/ontology/pac#'
|
36
36
|
COGS = Deri + 'cogs#'
|
37
37
|
CSV = Deri + 'scsv#'
|
data/infod/csv.rb
CHANGED
@@ -1,13 +1,36 @@
|
|
1
|
+
#watch __FILE__
|
1
2
|
class E
|
2
3
|
|
3
4
|
# CSV -> tripleStream
|
4
5
|
def triplrCSV d
|
5
6
|
d = @r.q['delim']||d
|
6
|
-
open(node).readlines.map{|l|l.chomp.split(d) rescue []}.do{|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
open(node).readlines.map{|l|l.chomp.split(d) rescue []}.do{|lines|
|
8
|
+
lines[0].do{|fields| # ok, we have at least one line..
|
9
|
+
yield uri+'#', Type, E[CSV+'Table']
|
10
|
+
yield uri+'#', CSV+'rowCount', lines.size
|
11
|
+
yield uri+'#', COGS+'View', E[uri+'?view=csv']
|
12
|
+
lines[1..-1].each_with_index{|row,line|
|
13
|
+
row.each_with_index{|field,i|
|
14
|
+
id = uri + '#row:' + line.to_s
|
15
|
+
yield id, fields[i], field
|
16
|
+
yield id, Type, E[CSV+'Row']
|
10
17
|
}}}}
|
11
18
|
end
|
12
19
|
|
20
|
+
F['view/csv'] = -> d,e {
|
21
|
+
# ignore non-rows
|
22
|
+
d.delete_if{|s,r|
|
23
|
+
!(r.class==Hash &&
|
24
|
+
r[Type].do{|t|
|
25
|
+
t.class == Array &&
|
26
|
+
t.map(&:maybeURI).member?(CSV+'Row')})}
|
27
|
+
# done w/ the type-tag
|
28
|
+
d.values.map{|r|r.delete Type}
|
29
|
+
|
30
|
+
[F['view/p'][d,e],
|
31
|
+
{_: :style, c: 'table.tab .abbr, table.tab .scheme {display: inline}'}
|
32
|
+
]}
|
33
|
+
|
34
|
+
F['view/'+CSV+'Row'] = NullView
|
35
|
+
|
13
36
|
end
|