infod 0.0.3.2 → 0.0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 06750f111d49bb2b62f28cd18bc35dd5212dc0ac
4
+ data.tar.gz: 7ee2db920696465b43201741aa28e6ecaf64af41
5
+ SHA512:
6
+ metadata.gz: 03d0d7ae6b88af73a4d5054e2736764d46d5e3247284bcbda919c811182ab0bdbf4e2ef37ccd5fdd8228f4435f3bc6f23311f6f6ac41a9f70016338e4bc6a01c
7
+ data.tar.gz: ff95efae2b1690cd8f244360e903d1f9a7ea287a2450cdcb85e418b1f444eed54d9601819f4a266897ba0409711ad5af572f984f65a9b076395c2cf690a26cdb
data/bin/infod CHANGED
@@ -28,7 +28,7 @@ module Rack
28
28
  def self.load _
29
29
  Rack::Builder.new {
30
30
  use Rack::Deflater
31
- run E
31
+ run R
32
32
  }.to_app
33
33
  end
34
34
  end
data/infod.rb CHANGED
@@ -1,3 +1,17 @@
1
+ %w{
2
+ cgi
3
+ date
4
+ digest/sha1
5
+ fileutils
6
+ json
7
+ linkeddata
8
+ mail
9
+ nokogiri
10
+ open-uri
11
+ pathname
12
+ rack
13
+ shellwords}.map{|r|require r}
14
+
1
15
  %w{
2
16
  constants
3
17
  lambda
@@ -13,34 +27,25 @@ csv
13
27
  edit
14
28
  facets
15
29
  feed
16
- find
17
30
  forum
18
31
  fs
19
32
  GET
20
- glob
21
33
  graph
22
34
  groonga
23
- HEAD
24
35
  histogram
25
36
  html
26
37
  HTTP
27
38
  image
28
39
  index
29
- kv
30
40
  ls
31
41
  mail
32
42
  man
33
43
  microblog
34
44
  names
35
- page
36
45
  POST
37
- postscript
38
46
  rdf
39
- ruby
40
47
  schema
41
- sh
42
48
  text
43
49
  threads
44
50
  time
45
- wiki
46
51
  }.map{|e|require_relative e}
@@ -1,4 +1,4 @@
1
- class E
1
+ class R
2
2
 
3
3
  E404 = 'req/'+HTTP+'404'
4
4
 
@@ -13,18 +13,20 @@ r.map{|k,v| s[Header + k] = k == 'uri' ? v : [v] }
13
13
  %w{CHARSET LANGUAGE ENCODING}.map{|a|
14
14
  s[Header+'ACCEPT_'+a] = [r.accept_('_' + a)]}
15
15
  s[Header+'ACCEPT'] = [r.accept]
16
- s[Type] = [E[HTTP+'Response']]
16
+ s[Type] = [R[HTTP+'Response']]
17
17
  s[HTTP+'statusCodeValue'] = [404]
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=create']]
18
+ s[Header+'HTTP_HOST'] = [R['http://' + s[Header+'HTTP_HOST'][0]]] if s[Header+'HTTP_HOST']
19
+ s[Edit] = [R[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'
23
23
 
24
24
  [404,{'Content-Type'=> r.format},[e.render(r.format,g,r)]]}
25
-
25
+
26
+ F['/cache/GET'] = F[E404]
27
+
26
28
  fn 'view/404',->d,e{
27
- [H.css('/css/404'),{_: :style, c: "a {background-color:#{E.cs}}"},
29
+ [H.css('/css/404'),{_: :style, c: "a {background-color:#{R.cs}}"},
28
30
  d.html]}
29
31
 
30
32
  # a resource-placeholder graph
@@ -32,4 +34,15 @@ s[HTTP+'statusCodeValue'] = [404]
32
34
  m[d.uri] = {}
33
35
  rand.to_s.h}
34
36
 
37
+ def checkURIs
38
+ r = uris.map{|u|
39
+ c = [`curl -IsA 404? "#{u}"`.lines.to_a[0].match(/\d{3}/)[0].to_i,u] # HEAD
40
+ puts c.join ' '
41
+ c } # status, uri tuple
42
+ puts "\n\n"
43
+ r.map{|c|
44
+ # show anomalies
45
+ puts c.join(' ') unless c[0] == 200 }
46
+ end
47
+
35
48
  end
@@ -1,5 +1,5 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
4
  Errors ||= {}
5
5
 
@@ -44,7 +44,7 @@ h1 {padding:.2em; background-color:#f00; color:#fff; margin:0}
44
44
  div {display:inline}
45
45
  table {border-spacing:0;margin:0}
46
46
  b {background-color:#eee;color:#500;padding:.1em .3em .1em .3em}
47
- .frag {font-weight:bold; color:#000; background-color:#{E.cs}}
47
+ .frag {font-weight:bold; color:#000; background-color:#{R.cs}}
48
48
  td.space {background-color:#ddd}
49
49
  td.message {background-color:#009;color:#fff}
50
50
  td.path {text-align:right}
@@ -1,4 +1,4 @@
1
- class E
1
+ class R
2
2
 
3
3
  Apache = ENV['apache']
4
4
  Nginx = ENV['nginx']
@@ -21,6 +21,14 @@ class E
21
21
  end
22
22
  end
23
23
 
24
+ def HEAD
25
+ self.GET.do{|s,h,b|[s,h,[]]}
26
+ end
27
+
28
+ def OPTIONS
29
+ [200,{},[]]
30
+ end
31
+
24
32
  def getFile
25
33
  @r['ETag'] = [m,size].h
26
34
  maybeSend mimeP,->{self}
@@ -52,25 +60,19 @@ class E
52
60
  @r['ETag'] ||= [@r.q['view'].do{|v|F['view/' + v] && v}, graphID, @r.format, Watch].h
53
61
 
54
62
  maybeSend @r.format, ->{
55
-
56
- # response
57
- r = E'/E/req/' + @r['ETag'].dive
58
- if r.e # exists
63
+
64
+ r = R '/cache/view/' + @r['ETag'].dive
65
+ if r.e # exists?
59
66
  r
60
67
  else
61
-
62
- # graph
63
- c = E '/E/graph/' + graphID.dive
64
- if c.e # exists
68
+ c = R '/cache/model/' + graphID.dive
69
+ if c.e # exists?
65
70
  m = c.r true
66
71
  else
67
- # construct
68
- (g && F['graph/' + g] || F['graph/'])[self, @r.q,m]
69
- # cache
70
- c.w m,true
72
+ (g && F['graph/' + g] || F['graph/'])[self, @r.q,m] # construct
73
+ c.w m,true # cache
71
74
  end
72
- # cache < construct
73
- r.w render @r.format, m, @r
75
+ r.w render @r.format, m, @r # construct -> cache
74
76
  end }
75
77
  end
76
78
 
@@ -85,7 +87,7 @@ class E
85
87
  h.update({'Cache-Control' => 'no-transform'}) if m.match /^(audio|image|video)/ # already compresed
86
88
 
87
89
  # frontend-specific handlers
88
- b.class == E ? (Nginx ? # nginx chosen?
90
+ b.class == R ? (Nginx ? # nginx chosen?
89
91
  [c,h.update({'X-Accel-Redirect' => '/fs' + b.path}),[]] : # Nginx handler
90
92
  Apache ? # Apache chosen?
91
93
  [c,h.update({'X-Sendfile' => b.d}),[]] : # Apache handler
@@ -1,14 +1,12 @@
1
1
  #watch __FILE__
2
- require 'rack'
2
+ class R
3
3
 
4
- class E
5
-
6
- def E.call e
7
- e.extend Th # add HTTP utility functions to environment table
4
+ def R.call e
5
+ e.extend Th # HTTP utility functions
8
6
  dev # see if watched files were changed
9
7
  e['HTTP_X_FORWARDED_HOST'].do{|h| e['SERVER_NAME'] = h }
10
8
  path = CGI.unescape e['REQUEST_PATH'].force_encoding('UTF-8').gsub '+','%2B'
11
- resource = E['http://'+e['SERVER_NAME']+path]
9
+ resource = R['http://'+e['SERVER_NAME']+path]
12
10
 
13
11
  if resource.inside
14
12
  e['uri'] = resource.uri
@@ -66,7 +64,7 @@ module Th
66
64
  # Accept formats
67
65
  accept.sort.reverse.map{|q,mimes|
68
66
  mimes.map{|mime|
69
- return mime if E::F[E::Render+mime]}}
67
+ return mime if R::F[R::Render+mime]}}
70
68
  'text/html'
71
69
  end
72
70
 
@@ -1,31 +1,38 @@
1
- watch __FILE__
2
- class E
1
+ #watch __FILE__
2
+ class R
3
3
 
4
4
  def POST
5
- type = @r['CONTENT_TYPE']
6
- case type
7
- when /^application\/sparql-update/
8
- puts "SPARQL"
5
+ # custom handler lookup cascade
6
+ pathSegment.do{|path|
7
+ lambdas = path.cascade.map{|p| p.uri.t + 'POST' }
8
+ ['http://'+@r['SERVER_NAME'],""].map{|h| lambdas.map{|p|
9
+ F[h + p].do{|fn| fn[self,@r].do{|r|
10
+ $stdout.puts [r[0],'http://'+@r['SERVER_NAME']+@r['REQUEST_URI'],@r['HTTP_USER_AGENT'],@r['HTTP_REFERER'],@r.format].join ' '
11
+ return r
12
+ }}}}}
13
+ basicPOST
14
+ end
15
+ def basicPOST
16
+ return [303,{'Location'=>uri},[]]
17
+ case @r['CONTENT_TYPE']
9
18
  when /^application\/x-www-form-urlencoded/
10
19
  changed = false
11
- (Rack::Request.new @r).params.map{|k,v|
12
- s, p, o = (CGI.unescape k).split /\/\._/
13
- if s && p && o
14
- s, p, o = [s, p, o].map &:unpath
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
21
- end
20
+ (Rack::Request.new @r).params.map{|k,v| s, p, tripleA = JSON.parse CGI.unescape k
21
+ s = s.R
22
+ pp = s.predicatePath p
23
+ o = v.match(/\A(\/|http)[\S]+\Z/) ? v.R : F['cleanHTML'][v]
24
+ tripleB = pp.objectPath(o)[0]
25
+ if tripleA.to_s != tripleB.to_s
26
+ tripleA && tripleA.R.do{|t| t.delete if t.e }
27
+ s[p] = o unless o.class==String && o.empty?
28
+ changed = true
22
29
  end}
23
30
  if changed
24
31
  g = {}
25
32
  fromStream g, :triplrDoc
26
- if g.empty?
27
- ef.deleteNode
28
- else
33
+ if g.empty? # no triples left
34
+ ef.delete
35
+ else # snapshot to graph-doc
29
36
  ef.w g, true
30
37
  end
31
38
  end
@@ -1,4 +1,4 @@
1
- class E
1
+ class R
2
2
 
3
3
  VideoFile = /(avi|flv|mkv|mpg|mp4|wmv)$/i
4
4
  AudioFile = /(aif|wav|flac|mp3|m4a|aac|ogg)$/i
@@ -1,29 +1,46 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
- F['view/'+SIOCt+'BlogPost']=->g,e{
4
+ F['/blog/post/POST'] = -> d,e {
5
+ name = URI.escape (Rack::Request.new d.env).params['name'].gsub /[?#\s\/]/,'_'
6
+ doc = 'http://'+e['SERVER_NAME']+Time.now.strftime('/%Y/%m/')+name
7
+ post = doc.R.a '#'
8
+ post[Type] = R[SIOCt+'BlogPost']
9
+ post[Title] = name
10
+ edit = "?prototype=sioct:BlogPost&graph=edit"
11
+ [303,{'Location' => doc + edit},[]]}
5
12
 
6
- F['example/blogview'][g,e]
13
+ F['/blog/post/GET'] = -> d,e {
14
+ [200,{'Content-Type'=>'text/html'},
15
+ [H(['name',
16
+ {_: :form, method: :POST,
17
+ c: [{_: :input, name: :name, style: "font-size:1.6em;width:48ex"},
18
+ {_: :input, type: :submit, value: ' go '}
19
+ ]}])]]}
7
20
 
8
- }
21
+ F['view/'+SIOCt+'BlogPost']=->g,e{F['example/blogview'][g,e]}
9
22
 
10
23
  F['example/blogview']=->g,e{
11
24
  g.map{|u,r|
12
- case u
25
+ case u # match against URIs for customized view
13
26
  when /artery.wbur/ # compact whitespace a bit
14
27
  r[Content] = {class: :WBUR, c: [{_: :style, c: ".WBUR p {margin:0}"},r[Content]]}
15
28
  F['view/base'][{u => r},e,false]
29
+
16
30
  when /boston\.com/ # crop sharebuttons
17
31
  (Nokogiri::HTML.parse r[Content][0]).css('p')[0].do{|p|r[Content]=p.inner_html}
18
32
  F['view/base'][{u => r},e,false]
33
+
19
34
  when /flickr/
20
35
  r[Content]
36
+
21
37
  when /reddit/ # minimal view
22
38
  F['view/'+SIOCt+'BoardPost'][{u => r},e]
39
+
23
40
  when /universalhub/ # logo + trim spacehogging tagjunk
24
41
  c = Nokogiri::HTML.fragment r[Content][0]
25
42
  c.css('section').map{|x|x.remove}
26
- {c: [{_: :a, href: r['http://purl.org/rss/1.0/link'][0].E.uri,
43
+ {c: [{_: :a, href: r['http://purl.org/rss/1.0/link'][0].R.uri,
27
44
  c: [{_: :img, src: '/logos/uhub.png',style: 'position:absolute;top:-93px'},
28
45
  {_: :h2, style: 'color:#000;margin:0',c: r[Title]}]},c.to_s],
29
46
  style: 'float:left;max-width:40em;position:relative;background-color:#fff;border-color:#eee;margin-top:93px;margin-right:.3em;padding-top:0;border-style:dotted;border-width:.3em;border-radius:0 .8em .8em .8em'}
@@ -1,5 +1,5 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
4
  fn 'req/day',->e,r{
5
5
  [303, {'Location'=> e.day.uri + r.q.except('y').qs}, []]}
@@ -51,7 +51,7 @@ class E
51
51
 
52
52
  fn 'view/month',->d,e{
53
53
  [(d.delete :time).do{|month|
54
- {_: :b, c: month.strftime('%B'),style: "color: #{E.cs}"}},
54
+ {_: :b, c: month.strftime('%B'),style: "color: #{R.cs}"}},
55
55
  F['view/t'][d,e,'day','day-terminate']]}
56
56
 
57
57
  fn 'view/day-terminate',->d,e{
@@ -1,4 +1,4 @@
1
- class E
1
+ class R
2
2
 
3
3
  def triplrSourceCode
4
4
  m = mime.split(/\//)[-1].sub(/^x-/,'')
@@ -10,7 +10,7 @@ class E
10
10
  end
11
11
 
12
12
  fn 'view/code',->d,e{[{_: :style, c: 'body{background-color:white;color:black}'},
13
- d.values.map{|r|[r.E.do{|e|[{_: :a,name: e.uri},e.html(e.base,true)]},'<br>',
13
+ d.values.map{|r|[r.R.do{|e|[{_: :a,name: e.uri},e.html(e.base,true)]},'<br>',
14
14
  r[Content]]}]}
15
15
 
16
16
  # ls /usr/share/source-highlight/*.lang | xargs -i basename {} .lang | tr "\n" " "
@@ -1,7 +1,6 @@
1
- class E
1
+ class R
2
2
 
3
3
  FSbase = `pwd`.chomp ; BaseLen = FSbase.size
4
- S = /\._/ # data path-separator
5
4
 
6
5
  W3 = 'http://www.w3.org/'
7
6
  Purl = 'http://purl.org/'
@@ -46,10 +45,13 @@ class E
46
45
  Prefix={
47
46
  "dc" => DC,
48
47
  "foaf" => FOAF,
49
- "rdf" => W3 + "ns/rdf#" ,
48
+ "rdf" => RDFns,
50
49
  "rdfs" => RDFs,
51
50
  "sioc" => SIOC,
51
+ "sioct" => SIOCt,
52
52
  "stat" => Stat,
53
53
  }
54
54
 
55
+ attr_reader :uri
56
+
55
57
  end
@@ -1,19 +1,19 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
4
  # CSV -> tripleStream
5
5
  def triplrCSV d
6
6
  d = @r.q['delim']||d
7
7
  open(node).readlines.map{|l|l.chomp.split(d) rescue []}.do{|lines|
8
8
  lines[0].do{|fields| # ok, we have at least one line..
9
- yield uri+'#', Type, E[CSV+'Table']
9
+ yield uri+'#', Type, R[CSV+'Table']
10
10
  yield uri+'#', CSV+'rowCount', lines.size
11
- yield uri+'#', COGS+'View', E[uri+'?view=csv']
11
+ yield uri+'#', COGS+'View', R[uri+'?view=csv']
12
12
  lines[1..-1].each_with_index{|row,line|
13
13
  row.each_with_index{|field,i|
14
14
  id = uri + '#row:' + line.to_s
15
15
  yield id, fields[i], field
16
- yield id, Type, E[CSV+'Row']
16
+ yield id, Type, R[CSV+'Row']
17
17
  }}}}
18
18
  end
19
19
 
@@ -24,7 +24,7 @@ class E
24
24
  r[Type].do{|t|
25
25
  t.class == Array &&
26
26
  t.map(&:maybeURI).member?(CSV+'Row')})}
27
- # done w/ the type-tag
27
+ # eat the type-tag
28
28
  d.values.map{|r|r.delete Type}
29
29
 
30
30
  [F['view/p'][d,e],
@@ -1,5 +1,5 @@
1
- watch __FILE__
2
- class E
1
+ #watch __FILE__
2
+ class R
3
3
 
4
4
  Prototypes = {
5
5
  SIOCt+'MicroblogPost' => [Content],
@@ -16,7 +16,7 @@ class E
16
16
  fn 'view/create',->g,e{
17
17
  [{_: :style, c: 'a {display:block;font-size:2em}'},{_: :b, c: :type},
18
18
  Prototypes.map{|t,ps|
19
- {_: :a, href: e['REQUEST_PATH']+'?graph=edit&prototype='+(CGI.escape t), c: t.label}}]}
19
+ {_: :a, href: e['REQUEST_PATH']+'?graph=edit&prototype='+(URI.escape t.shorten), c: t.label}}]}
20
20
 
21
21
  # editable triples
22
22
  F['protograph/edit'] = -> e,env,g {
@@ -25,6 +25,7 @@ class E
25
25
  rand.to_s.h}
26
26
 
27
27
  fn 'graph/edit',->e,env,g{
28
+ puts "graph.edit #{e}"
28
29
  e.fromStream g, :triplrDoc} # add fs-sourced triples
29
30
 
30
31
  =begin HTML <form> RDF editor
@@ -35,47 +36,42 @@ class E
35
36
  fn 'view/edit',->g,e{
36
37
 
37
38
  # render a triple
38
- triple = ->s,p,o{
39
- if s && p && o
40
- s = s.E
41
- p = p.E
42
- oE = p.literal o # cast literal to URI
43
- id = s.concatURI(p).concatURI oE # triple identifier
44
- [(case p.uri # more to support here.. http://dev.w3.org/html5/markup/input.html#input
45
- when Content
46
- [{_: :textarea, name: id, c: o, rows: 16, cols: 80},
47
- '<br>',o]
48
- when Date
49
- {_: :input, name: id, type: :datetime, value: o.empty? ? Time.now.iso8601 : o}
50
- else
51
- {_: :input, name: id, value: o, size: 54}
52
- end
53
- ),"<br>\n"]
54
- end}
55
-
39
+ triple = ->s,p,o{ # http://dev.w3.org/html5/markup/input.html#input
40
+ spo = o && s.R.predicatePath(p).objectPath(o)[0].uri
41
+ t = CGI.escape [s,p,spo].to_json
42
+ [(case p.R.uri
43
+ when Content
44
+ [{_: :textarea, name: t, c: o, rows: 16, cols: 80},
45
+ '<br>',o]
46
+ when Date
47
+ {_: :input, name: t, type: :datetime, value: !o || o.empty? && Time.now.iso8601 || o}
48
+ else
49
+ {_: :input, name: t, value: o, size: 54}
50
+ end
51
+ ),"<br>\n"]}
52
+
56
53
  ps = [] # predicates to go editable on
57
- e.q['prototype'].do{|pr|
54
+ e.q['prototype'].do{|pr| pr = pr.expand
58
55
  Prototypes[pr].do{|v|ps.concat v }} # prototype imports
59
56
  e.q['predicate'].do{|p|ps.push p } # explicit predicate
60
57
 
61
- [{_: :style, c: ".abbr {display: none}\ntd {vertical-align:top}"},
58
+ [H.css('/css/html'),
62
59
  {_: :form, name: :editor, method: :POST, action: e['REQUEST_PATH'],
63
60
 
64
61
  c: [{_: :a, class: :edit, c: '+add field',
65
62
  href: e['uri']+'?graph=blank&view=addP', style: 'background-color:#0f0;border-radius:5em;color:#000;padding:.5em'},
66
63
  g.map{|s,r| # subject
67
- uri = s.E.localURL e
68
- {_: :table, style: 'background-color:#eee',
64
+ uri = s.R.localURL e
65
+ {_: :table, class: :html,
69
66
  c: [{_: :tr, c: {_: :td, colspan: 2, c: {_: :a, class: :uri, id: s, c: s, href: uri}}},
70
- {_: :input, type: :hidden, name: s.E.concatURI(Edit.E).concatURI(E['/']), value: e['uri']+'?graph=edit'},
71
67
  r.keys.-([Edit]).concat(ps).uniq.map{|p| # resource + prototype/initialize predicates
72
68
  {_: :tr,
73
- c: [{_: :td, c: {_: :a, title: p, href: p, c: p.abbrURI}}, # property
69
+ c: [{_: :td, class: :key, c: {_: :a, title: p, href: p, c: p.abbrURI}}, # property
74
70
  {_: :td,
75
71
  c: [r[p].do{|o| # objects
76
72
  (o.class == Array ? o : [o]).map{|o| # each object
77
73
  triple[s,p,o]}}, # existing triples
78
- triple[s,p,'']]}]}}]}}, # new triple
74
+ triple[s,p,nil]]}]}}]}}, # new triple
79
75
  {_: :input, type: :submit, value: 'save'}]}]}
80
76
 
81
77
  # select a property to edit