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