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/Es/ls.rb ADDED
@@ -0,0 +1,58 @@
1
+ #watch __FILE__
2
+ class E
3
+
4
+ fn 'view/dir',->i,e{
5
+
6
+ # item link + preview
7
+ a = -> i { i = i.E
8
+ {_: :a, href: i.localURL(e),
9
+ c: i.uri.match(/(gif|jpe?g|png)$/i) ? {_: :img, src: i.uri+'?y=scaleImage&px=233'} : i.uri.sub(/.*\//,'')}}
10
+
11
+ [(H.once e, 'dir', (H.css '/css/ls')),
12
+ i.map{|u,r|
13
+ if r[Posix+'dir#child']
14
+ url = r.E.localURL e
15
+ {class: :dir, style: "background-color: #{E.cs}", # dir wrapper
16
+ c: [{c: [{_: :a, href: url.t+'?view=ls&triplr=id', # link to "ls"
17
+ c: r.uri.sub( 'http://'+e['SERVER_NAME'],'')},
18
+ {_: :a, href: url.t, c: '/'}]},
19
+ r[Posix+'dir#child'].map{|c|a[c]}]}
20
+ else
21
+ a[r]
22
+ end
23
+ }]}
24
+
25
+ F['view/'+MIMEtype+'inode/directory'] = F['view/dir']
26
+
27
+ fn 'view/ls',->i,e{
28
+ dir = e['uri'].E
29
+ path = dir.pathSegment
30
+ up = (if !path || path.uri == '/'
31
+ '/'
32
+ else
33
+ dir.parent.url.t+'?view=ls&triplr=id'
34
+ end)
35
+
36
+ [(H.css '/css/ls'),
37
+ {_: :a, class: :up, href: up, c: '↑'},
38
+ {class: :ls,
39
+ c: (Fn 'view/table',i,e)},
40
+ (Fn 'view/find',i,e),'<br clear=all>',
41
+ {_: :a, class: :down, href: e['uri'].E.url.t + e.q.except('triplr','view').qs, c: '&darr;'}]}
42
+
43
+ # user-patchable default-handler
44
+ fn '/GET',->e,r{
45
+ x = 'index.html'
46
+ i = [e,e.pathSegment].compact.map{|e|e.as x}.find &:e
47
+ if i
48
+ if e.uri[-1] == '/' # inside dir?
49
+ i.env(r).getFile # show index
50
+ else # descend to indexed dir
51
+ [301, {Location: e.uri.t}, []]
52
+ end
53
+ else
54
+ # default handler
55
+ e.response
56
+ end}
57
+
58
+ end
data/infod/Es/mail.rb ADDED
@@ -0,0 +1,87 @@
1
+ class E
2
+
3
+ # TMail version: 1.2.7.1-4 from:
4
+ # apt-get install ruby-tmail
5
+
6
+ def triplrTmail ; require 'tmail'
7
+
8
+ # read message
9
+ i = -> i {E i[1..-2]} # Message-ID -> E
10
+ (TMail::Mail.load node).do{|m| # parse
11
+ d = m.message_id; return unless d # parse successful?
12
+ e = i[d] # Message resource
13
+
14
+ # index previously unseen mail
15
+ e.e || ( # Message-ID locatable?
16
+ ln e # create message-id path
17
+ self.index Creator, m.from[0].E # index From
18
+ m.to.do{|t|self.index To, t[0].E} # index To
19
+
20
+ %w{in_reply_to references}.map{|p| m.send(p).do{|os| os.map{|o|
21
+ e.index SIOC+'reply_of', i[o]}}}) # index references
22
+
23
+ # yield triples
24
+ yield e.uri, Type, E[SIOCt + 'MailMessage']
25
+ yield e.uri, Type, E[SIOC + 'Post']
26
+ yield e.uri, Date, m.date.iso8601 if m.date
27
+ yield e.uri, Content, m.decentBody
28
+ [[:subject,Title],
29
+ [:to,To,true],
30
+ [:cc,To,true],
31
+ [:bcc,To,true],
32
+ [:friendly_from,SIOC+'name'],
33
+ [:from,Creator,true],
34
+ [:reply_to,'/mail/reply_to',true],
35
+ [:in_reply_to,'/parent',true,true],
36
+ [:in_reply_to,SIOC+'reply_of',true,true],
37
+ [:references,SIOC+'reply_of',true,true],
38
+ ].each{|a| m.send(a[0]).do{|o| [*o].map{|o|
39
+ yield e.uri,a[1], # skip empty String values
40
+ (a[2] ? (a[3] ? i[o] : o.E) : o.to_utf8) unless o.match(/\A[, \n]*\Z/)}}}}
41
+
42
+ rescue Exception => e
43
+ puts [:mail,uri,e].join(' ')
44
+ end
45
+
46
+ alias_method :triplrMail, :triplrTmail
47
+
48
+ # pure-ruby mail is only 10x (vs 100x) slower than C-ext based TMail w/ new parser
49
+ # API is mostly identical, URIs strings arent <>-wrapped
50
+ # TODO replace this msg with triplrMail if anyone wants it
51
+
52
+ end
53
+
54
+ module TMail
55
+ class Mail
56
+ def unicode_body
57
+ unquoted_body.to_utf8
58
+ end
59
+ def decentBody
60
+ unHTML=->t{t.split(/<body[^>]*>/)[-1].split(/<\/body>/)[0]}
61
+ if multipart?
62
+ parts.collect{ |part|
63
+ c = part["content-type"]
64
+ if part.multipart?
65
+ part.decentBody
66
+ elsif header.nil?
67
+ ""
68
+ elsif !attachment?(part) && c.sub_type != 'html'
69
+ part.unicode_body.hrefs(true)
70
+ else
71
+ (c["name"]||'attach').do{|a|
72
+ message_id ? (message_id[1..-2]+'/'+a).E.do{|i|
73
+ i.w part.body if !i.e
74
+ '<a href='+i.url+'>'+(part.main_type=='image' ? '<img src="'+i.url+'">' : a)+"</a><br>\n"
75
+ } : ""};end
76
+ }.join
77
+
78
+ else
79
+ unicode_body.do{|b|content_type&&content_type.match(/html/) ? unHTML.(b) : b.hrefs(true)}
80
+ end
81
+ rescue
82
+ ''
83
+ end
84
+ end
85
+ end
86
+
87
+ class String; def is_binary_data?; true; end; end
data/infod/Es/man.rb ADDED
@@ -0,0 +1,112 @@
1
+ #watch __FILE__
2
+ class E
3
+
4
+ fn '/man/GET',->e,r{
5
+ manPath = '/usr/share/man'
6
+
7
+ # eat selector
8
+ name = e.pathSegment.uri.sub('/man/','/').tail
9
+
10
+ # section requested?
11
+ section = nil
12
+ name.match(/^([0-9])(\/|$)/).do{|p|
13
+ section = p[1]
14
+ name = p.post_match }
15
+
16
+ if !name || name.empty? || name.match(/\//)
17
+ if section
18
+ # enumerate section children
19
+ (H [H.css('/css/man'),{_: :style, c: "a {background-color: #{E.cs}}"},
20
+ Pathname(manPath+'/man'+section).c.map{|p|
21
+ n = p.basename.to_s.sub /\.[0-9][a-z]*\...$/,''
22
+ }.group_by{|e|e[0].match(/[a-zA-Z]/) ? e[0].downcase : '0-9'}.sort.map{|g,m|
23
+ [{_: :h3, c: g},
24
+ m.map{|n|[{_: :a, href: '/man/'+section+'/'+n, c: n },' ']}]}
25
+ ]).hR
26
+ else
27
+ e.response
28
+ end
29
+ else
30
+ acceptLang = r['HTTP_ACCEPT_LANGUAGE'].do{|a|a.split(/,/)[0]}
31
+ lang = r.q['lang'] || acceptLang
32
+ superLang = lang.do{|l| (l.split /[_-]/)[0] }
33
+ langSH = lang.do{|l| '-L ' + l.sub('-','_').sh }
34
+ man = `man #{langSH} -w #{section} #{name.sh}`.chomp
35
+
36
+ if man.empty?
37
+ return false
38
+ else
39
+
40
+ roff = man.E
41
+ htmlBase = roff.dir.to_s.sub(/.*\/share/,'').E
42
+ html = htmlBase.as roff.bare + '.html'
43
+ cached = html.e && html.m > (Pathname man).stat.mtime
44
+
45
+ if !cached
46
+
47
+ locales = Pathname(manPath).c.select{|p|p.basename.to_s.do{|b| !b.match(/^man/) && !b.match(/\./) }}.map{|p|File.basename p}
48
+ localesAvail = locales.select{|l|
49
+ File.exist? manPath + '/' + l + '/' + roff.uri.split('/')[-2..-1].join('/')}
50
+
51
+ imagePath = htmlBase.d + '/images'
52
+ FileUtils.mkdir_p imagePath unless File.exist? imagePath
53
+
54
+ preconv = %w{hu pt tr}.member?(superLang) ? "" : "-k"
55
+ pageCmd = "zcat #{man} | groff #{preconv} -T html -man -P -D -P #{imagePath}"
56
+ page = `#{pageCmd}`#.to_utf8
57
+
58
+ [[:name,name],
59
+ [:acceptLang,acceptLang],
60
+ [:lang, lang],
61
+ [:langSH, langSH],
62
+ [:superLang, superLang],
63
+ [:roff,man],
64
+ [:htmlBase,htmlBase.d],
65
+ [:imagePath,imagePath],
66
+ [:localizations,localesAvail],
67
+ [:pageCmd,pageCmd]].map{|p| puts [" "*(13-p[0].size),*p].join ' ' }
68
+
69
+ page = Nokogiri::HTML.parse page
70
+ body = page.css('body')[0]
71
+
72
+ # add CSS link
73
+ body.add_child H H.css('/css/man')
74
+ body.add_child H[{_: :style, c: "a {background-color:#{E.cs}}"}]
75
+
76
+ # add localization links
77
+ (body.css('h1')[0] ||
78
+ body.css('p')[0]
79
+ ).add_previous_sibling H localesAvail.map{|l|
80
+ {_: :a, class: :lang, href: r['REQUEST_PATH']+'?lang='+l, c: l}}
81
+
82
+ # webize image paths
83
+ body.css('img').map{|i|
84
+ p = (i.attr 'src').unpathFs
85
+ i.replace H[{_: :img, src: p}]}
86
+
87
+ # inspect plaintext
88
+ # HTMLize hyperlinks
89
+ # markup commands
90
+ body.xpath('//text()').map{|a|
91
+ a.replace a.to_s.gsub('&gt;','>').hrefs.gsub /\b([^<>\s(]+)\(/mi, '<b>\1</b>('
92
+ }
93
+
94
+ qs = r['QUERY_STRING'].do{|q| q.empty? ? '' : '?' + q}
95
+ # href-ize commands
96
+ body.css('b').map{|b|
97
+ b.next.do{|n|
98
+ n.to_s.match(/\(([0-9])\)(.*)/).do{|section|
99
+ name, s = b.inner_text, section[1]
100
+ n.replace section[2]
101
+ b.replace " <a href='/man/#{s}/#{name}#{qs}'><b>#{name}</b>(#{s})</a>"}}}
102
+
103
+ html.w page
104
+ end
105
+
106
+ # response
107
+ html.env(r).getFile
108
+ end
109
+ end
110
+ }
111
+
112
+ end
data/infod/Es/mime.rb ADDED
@@ -0,0 +1,59 @@
1
+ #watch __FILE__
2
+ class E
3
+
4
+ # MIME-type, no link-following
5
+ def mime
6
+ @mime ||=
7
+ (t = ext.downcase.to_sym
8
+
9
+ if node.symlink?
10
+ "inode/symlink"
11
+
12
+ elsif d?
13
+ "inode/directory"
14
+
15
+ elsif MIME[t]
16
+ MIME[t]
17
+
18
+ elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
19
+ Rack::Mime::MIME_TYPES[t]
20
+
21
+ elsif base.index('msg.')==0
22
+ "message/rfc822"
23
+
24
+ elsif e
25
+ `file --mime-type -b #{sh}`.chomp
26
+
27
+ else
28
+ "application/octet-stream"
29
+ end)
30
+ end
31
+
32
+ # MIME-type of recursively-dereferenced path
33
+ def mimeP
34
+ @mime ||=
35
+ (p = realpath
36
+
37
+ unless p
38
+ nil
39
+ else
40
+ t = ((File.extname p).tail || '').downcase.to_sym
41
+
42
+ if p.directory?
43
+ "inode/directory"
44
+
45
+ elsif MIME[t]
46
+ MIME[t]
47
+
48
+ elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
49
+ Rack::Mime::MIME_TYPES[t]
50
+
51
+ elsif (File.basename p).index('msg.')==0
52
+ "message/rfc822"
53
+
54
+ else
55
+ `file --mime-type -b #{Shellwords.escape p.to_s}`.chomp
56
+ end
57
+ end )
58
+ end
59
+ end
data/infod/Es/out.rb ADDED
@@ -0,0 +1,52 @@
1
+ class E
2
+
3
+ def render mime, graph, e
4
+ E[Render+ mime].y graph, e
5
+ end
6
+
7
+ fn '/E/GET',->e,r{[301,{Location: '/'},[]]}
8
+
9
+ def response
10
+
11
+ q = @r.q # query-string
12
+ g = q['graph'] # graph-function selector
13
+
14
+ # empty response graph
15
+ m = {}
16
+
17
+ # identify graph
18
+ graphID = (F['protograph/' + g] || F['protograph/'])[self,q,m]
19
+
20
+ return F[E404][self,@r] if m.empty?
21
+
22
+ # identify response
23
+ @r['ETag'] ||= [graphID, q, @r.format, Watch].h
24
+
25
+ maybeSend @r.format, ->{
26
+
27
+ # response
28
+ r = E'/E/req/' + @r['ETag'].dive
29
+ if r.e # response exists
30
+ r # cached response
31
+ else
32
+
33
+ # graph
34
+ c = E '/E/graph/' + graphID.dive
35
+ if c.e # graph exists
36
+ m.merge! c.r true
37
+ else
38
+ # construct graph
39
+ (F['graph/' + g] || F['graph/'])[self,q,m]
40
+ # cache graph
41
+ c.w m,true
42
+ end
43
+
44
+ # graph sort/filter
45
+ E.filter q, m, self
46
+
47
+ # cache response
48
+ r.w render @r.format, m, @r
49
+ end }
50
+ end
51
+
52
+ end
@@ -1,8 +1,12 @@
1
1
  #watch __FILE__
2
2
  class E
3
3
 
4
- fn 'head/page',->d,e{ v = e.q['v']
5
- Fn 'head' + (v != 'page' && '/' + v), d, e}
4
+ fn 'head/page',->d,e{
5
+ v = e.q['v']
6
+ unless v == 'page'
7
+ h = F['head/'+v] || F['head']
8
+ h[d,e]
9
+ end}
6
10
 
7
11
  fn 'view/page',->d,e{
8
12
  # try daydirs if no pagination data provided
@@ -25,6 +29,6 @@ class E
25
29
 
26
30
  [(H.js '/js/pager'),(H.once e,:mu,(H.js '/js/mu')), # n/p key shortcuts
27
31
  c,(H (F['view/'+e.q['v']]||F['view']).(d,e)), # content
28
- '<br clear=all>',c]}
32
+ '<br clear=all>',{class: :bottom, c: c}]}
29
33
 
30
34
  end
data/infod/Es/pdf.rb ADDED
@@ -0,0 +1,19 @@
1
+ class E
2
+
3
+ def triplrPDF &f
4
+
5
+ text = docBase.a '.txt'
6
+ unless text.e && text.m > m
7
+ puts "PDF #{uri}"
8
+ `pdftotext #{sh}`
9
+ end
10
+
11
+ # metadata
12
+ triplrStdOut 'pdfinfo', &f
13
+
14
+ # body
15
+ yield uri, Content, `cat #{text.sh}`
16
+
17
+ end
18
+
19
+ end
data/infod/Es/rdf.rb ADDED
@@ -0,0 +1,35 @@
1
+ #watch __FILE__
2
+ class E
3
+
4
+ def self.renderRDF d,f
5
+ require 'linkeddata'
6
+ (RDF::Writer.for f).buffer{|w|
7
+ d.values.each{|r| r.triples{|s,p,o|
8
+ s = RDF::URI s
9
+ p = RDF::URI p
10
+ o = ([E,Hash].member?(o.class) ? (RDF::URI o.uri) : (RDF::Literal o)) rescue nil
11
+ (w << (RDF::Statement.new s,p,o) if o ) rescue nil
12
+ }}}
13
+ end
14
+
15
+ def triplrRDF format=:rdfa, localFile=true ; require 'linkeddata'
16
+ location = (localFile && f) ? d : uri
17
+ puts [:RDF,location].join ' '
18
+ RDF::Reader.open(location, :format => format){|r|
19
+ r.each_triple{|s,p,o|
20
+ yield s.to_s, p.to_s, [RDF::Node, RDF::URI].member?(o.class) ? E(o) : o.value.do{|v|v.class == String ? v.to_utf8 : v}}}
21
+ end
22
+
23
+ [['application/ld+json',:jsonld],
24
+ ['application/json+ld',:jsonld],
25
+ ['application/jsonld',:jsonld],
26
+ ['application/rdf+xml',:rdfxml],
27
+ ['application/rdfxml',:rdfxml],
28
+ ['text/ntriples',:ntriples],
29
+ ['text/turtle',:turtle],
30
+ ['text/rdf+n3',:n3],
31
+ ['text/n3',:n3]
32
+ ].map{|mime|
33
+ F[Render+mime[0]] = ->d,a=nil{E.renderRDF d, mime[1]}}
34
+
35
+ end