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.
@@ -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,23 +1,35 @@
1
+ class FalseClass
2
+ def do; false end
3
+ end
4
+
5
+ class NilClass
6
+ def do; nil end
7
+ def html e=nil,g=nil; "" end
8
+ def R; "".R end
9
+ end
10
+
11
+ class Object
12
+ def id; self end
13
+ def do; yield self end
14
+ def maybeURI; nil end
15
+ def justArray; [self] end
16
+ end
1
17
 
2
18
  def watch f
3
- E::Watch[f]=File.mtime f
19
+ R::Watch[f]=File.mtime f
4
20
  puts 'dev '+f end
5
21
 
6
- class E
22
+ class R
7
23
 
8
24
  def initialize uri
9
25
  @uri = uri.to_s
10
26
  end
11
27
 
12
- def E arg=nil
13
- if arg
14
- E.new arg
15
- else
16
- self
17
- end
28
+ def R uri = nil
29
+ uri ? R.new(uri) : self
18
30
  end
19
31
 
20
- def E.[] u; u.E end
32
+ def R.[] uri; R.new uri end
21
33
 
22
34
  F={}
23
35
  Watch={}
@@ -31,23 +43,23 @@ class E
31
43
  end }
32
44
  end
33
45
 
34
- # call lambda @id
35
- def y *a
36
- F[uri][*a]
46
+ # util, prefix, cleaner -> tripleStream
47
+ def triplrStdOut e,f='/',g=/^\s*(.*?)\s*$/,a=sh
48
+ `#{e} #{a}|grep :`.each_line{|i|
49
+ i = i.split /:/
50
+ yield uri, (f + (i[0].match(g)||[0,i[0]])[1]. # s
51
+ gsub(/\s/,'_').gsub(/\//,'-').gsub(/[\(\)]+/,'')), # p
52
+ i.tail.join(':').strip.do{|v|v.match(/^[0-9\.]+$/) ? v.to_f : v.hrefs}} # o
53
+ rescue
37
54
  end
38
55
 
39
56
  end
40
57
 
41
58
  # URI -> function
42
-
43
59
  def fn u,y
44
- E::F[u.to_s] = y
45
- end
46
-
47
- def Fn a,*g
48
- E::F[a][*g]
60
+ R::F[u.to_s] = y
49
61
  end
50
62
 
51
- def E e
52
- E.new e
63
+ def R uri
64
+ R.new uri
53
65
  end
@@ -1,14 +1,14 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
4
  fn 'view/dir',->i,e{
5
- a = -> i { i = i.E
5
+ a = -> i { i = i.R
6
6
  {_: :a, href: i.localURL(e), c: i.uri.match(/(gif|jpe?g|png)$/i) ? {_: :img, src: i.uri+'?y=scaleImage&px=233'} : i.uri.sub(/.*\//,'')}}
7
7
 
8
8
  [(H.once e, 'dir', (H.css '/css/ls')),
9
9
  i.map{|u,r|
10
- url = r.E.localURL e
11
- {class: :dir, style: "background-color: #{E.cs}", # dir wrapper
10
+ url = r.R.localURL e
11
+ {class: :dir, style: "background-color: #{R.cs}", # dir wrapper
12
12
  c: [{c: [{_: :a, href: url.t + '?view=ls', c: r.uri.sub('http://'+e['SERVER_NAME'],'')},
13
13
  {_: :a, href: url.t, c: '/'}]},
14
14
  r[Posix+'dir#child'].do{|c|c.map{|c|a[c]}}]}}]}
@@ -18,7 +18,7 @@ class E
18
18
  fn 'view/ls',->i,e{
19
19
  e.q['sort'] ||= 'stat:mtime'
20
20
  e.q['reverse'] ||= true
21
- dir = e['uri'].E
21
+ dir = e['uri'].R
22
22
  path = dir.pathSegment
23
23
  up = (!path || path.uri == '/') ? '/' : dir.parent.url
24
24
  i = i.dup
@@ -30,8 +30,31 @@ class E
30
30
  r.delete_if{|p,o|!f[p]}}
31
31
  [(H.css '/css/ls'),
32
32
  {_: :a, class: :up, href: up+'?view=ls', c: '↑'},
33
- {class: :ls, c: (Fn 'view/table',i,e)},'<br clear=all>',
34
- {_: :a, class: :down, href: e['uri'].E.url.t, c: '&darr;'}]}
33
+ {class: :ls, c: F['view/table'][i,e]},'<br clear=all>',
34
+ {_: :a, class: :down, href: e['uri'].R.url.t, c: '&darr;'}]}
35
+
36
+ fn 'set/find',->e,q,m,x=''{
37
+ q['q'].do{|q|
38
+ r = '-iregex ' + ('.*' + q + '.*' + x).sh
39
+ s = q['size'].do{|s| s.match(/^\d+$/) && '-size +' + s + 'M'} || ""
40
+ t = q['day'].do{|d| d.match(/^\d+$/) && '-ctime -' + d } || ""
41
+ [e,e.pathSegment].compact.select(&:e).map{|e|
42
+ `find #{e.sh} #{t} #{s} #{r} | head -n 1000`.
43
+ lines.map{|l|l.chomp.unpath}}.compact.flatten}}
44
+
45
+ fn 'set/glob',->d,e=nil,_=nil{
46
+ p = [d,d.pathSegment].compact.map(&:glob).flatten[0..4e2].compact.partition &:inside
47
+ p[0] }
48
+
49
+ fn 'view/find',->i,e{
50
+ {_: :form, method: :GET, action: e['REQUEST_PATH'].t,
51
+ c: [{_: :input, name: :set, value: :find, type: :hidden},
52
+ {_: :input, name: :view, value: :ls, type: :hidden},
53
+ {_: :input, name: :q, style: 'float: left;font-size:1.3em'}]}}
54
+
55
+ fn 'req/randomFile',->e,r{
56
+ g = F['set/glob'][e]
57
+ !g.empty? ? [302, {Location: g[rand g.length].uri}, []] : [404]}
35
58
 
36
59
  fn 'protograph/du',->d,q,m{
37
60
  d.pathSegment.do{|path|
@@ -46,9 +69,9 @@ class E
46
69
  fn 'graph/du',->e,_,m{
47
70
  `du -a #{m.values[0].sh}`.each_line{|l|
48
71
  s,p = l.chomp.split /\t/ # size, path
49
- p = p.unpathFs # path -> URI
72
+ p = p.unpath # path -> URI
50
73
  m[p.uri] = {'uri' => p.uri,
51
- Posix+'util#du' => E[p.uri+'?graph=du#du'],
74
+ Posix+'util#du' => R[p.uri+'?graph=du#du'],
52
75
  Stat+'size' => [s.to_i]}}
53
76
  m }
54
77
 
@@ -1,115 +1,125 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
- begin
5
- require 'tmail'
6
- rescue LoadError => e
7
- end
8
-
9
- MessagePath = ->id{ h = id.h # hash identifier
10
- '/msg/' + h[0..2] + '/' + id}
4
+ MessagePath = ->id{'/msg/' + id.h[0..2] + '/' + id}
11
5
 
12
6
  GREP_DIRS.push /^\/m\/[^\/]+\// # allow grep within a single address
13
7
 
14
8
  F['/m/GET'] = -> e,r{
9
+ # set overview(summary) view and start a depth-first view of message tree of this address
15
10
  if m = e.pathSegment.uri.match(/^\/m\/([^\/]+)$/)
16
- r.q['set'] = 'depth'
11
+ r.q['set'] ||= 'depth'
17
12
  r.q['view'] ||= 'threads'
18
13
  e.response
19
14
  else
20
15
  false
21
16
  end}
22
17
 
23
- def triplrTmail &f
24
- (TMail::Mail.load node).do{|m| # load
25
- d = m.message_id; return unless d # parse successful?
26
- id = d[1..-2] # message-ID
27
- e = MessagePath[id] # webized ID
28
- from = m.from[0].to_utf8 # author
29
- creator = '/m/'+from+'#'+from # author URI
30
- yield e, DC+'identifier', id # original ID
31
- yield e, DC+'source', self # original file
32
- yield e, Type, E[SIOCt + 'MailMessage']
33
- yield e, Type, E[SIOC + 'Post']
34
- yield e, Date, m.date.iso8601 if m.date
35
- yield e, Title, m.subject.to_utf8
36
- yield e, Creator, E[creator]
37
- yield e, SIOC+'has_discussion', E[e+'?graph=thread&view=timegraph#discussion']
38
- yield creator, Name, m.friendly_from.to_utf8
39
- yield creator, DC+'identifier', E['mailto:'+from]
40
- yield e, SIOC+'reply_to',
41
- E[URI.escape("mailto:#{m.header['x-original-to']||from}?References=<#{id}>&In-Reply-To=<#{id}>&Subject=#{m.subject.to_utf8}&")+'#reply']
42
-
43
- %w{to cc bcc}.map{|to|
44
- m.send(to).do{|to| to.map{|to|
45
- to = to.to_utf8
46
- yield e, To, E['/m/'+to+'#'+to]
47
- }}}
48
-
49
- %w{in_reply_to references}.map{|ref|
50
- m.send(ref).do{|refs| refs.map{|r|
51
- yield e, SIOC+'reply_of', E[MessagePath[r[1..-2]]]}}}
52
- m.in_reply_to.do{|refs| refs.map{|r|yield e, SIOC+'has_parent', E[MessagePath[r[1..-2]]]}}
53
-
54
- # RDF:HTML message-body
55
- yield e, Content,
56
- H([{_: :pre, class: :mail, style: 'white-space: pre-wrap',
57
- c: m.concat_message(e.E,0,&f).gsub(/^\s*(&gt;)(&gt;|\s)*\n/,"").lines.to_a.map{|l| # skip quoted empty-lines
58
- l.match(/(^\s*(&gt;|On[^\n]+(said|wrote))[^\n]*)\n/) ? {_: :span, class: :q, depth: l.scan(/(&gt;)/).size, c: l} : l # quotes
59
- }},(H.css '/css/mail',true)])}
60
- rescue Exception => e
61
- puts e
62
- end
18
+ IndexMail = ->doc, graph, host {
19
+ graph.map{|u,r|
20
+ a = [] # address references
21
+ r[Creator].do{|c|a.concat c}
22
+ r[To].do{|t|a.concat t}
23
+ r[Date].do{|t|
24
+ st = '/' + t[0][0..18].gsub('-','/').sub('T','.') + '.' + u.h[0..1] + '.e'
25
+ a.map{|rel|
26
+ doc.ln R[rel.uri.split('#')[0]+st]}}}}
63
27
 
64
28
  def triplrMailMessage &f
65
- # indexing function, called on previously-unseen doc-graphs
66
- ix = ->doc, graph, host {
67
- graph.map{|u,r|
68
- a = [] # addresses
69
- r[Creator].do{|c|a.concat c}
70
- r[To].do{|t|a.concat t}
71
- r[Date].do{|t|
72
- st = '/'+t[0].gsub('-','/').sub('T','.').sub(/\+.*/,'.'+u.h[0..1]+'.e')
73
- a.map{|rel|
74
- doc.ln E[rel.uri.split('#')[0]+st]}}}}
75
- addDocs :triplrTmail, @r['SERVER_NAME'], [SIOC+'reply_of'], ix, &f
29
+ addDocs :triplrMail, @r['SERVER_NAME'], [SIOC+'reply_of'], IndexMail, &f
76
30
  end
77
31
 
78
- F['view/'+MIMEtype+'message/rfc822'] = NullView # hide containing file in default render
32
+ def mail
33
+ Mail.read node if f
34
+ end
79
35
 
80
- end
36
+ def triplrMail
37
+ m = mail ; return unless m # mail
38
+ id = m.message_id ; return unless id # message-ID
39
+ e = MessagePath[id.gsub(/[<>]/,'')] # message URI
40
+ yield e, DC+'identifier', id # origin-domain ID
41
+ yield e, DC+'source', self # source-file URI
42
+ [R[SIOCt+'MailMessage'], # SIOC types
43
+ R[SIOC+'Post']].map{|t|yield e, Type, t} # RDF types
44
+
45
+ m.from.do{|f| # any authors?
46
+ f.justArray.map{|f| # each author
47
+ f = f.to_utf8
48
+ creator = '/m/'+f+'#'+f # author URI
49
+ yield e, Creator, R[creator] # message -> author
50
+ yield creator, DC+'identifier', R['mailto:'+f] # author ID
51
+ yield e, SIOC+'reply_to', # reply URI
52
+ R[URI.escape("mailto:#{m.reply_to.do{|t|t[0]}||f}?References=<#{id}>&In-Reply-To=<#{id}>&Subject=#{m.subject}&")+'#reply']}}
53
+
54
+ yield e, Date, m.date.iso8601 if m.date # date
55
+
56
+ m.subject.do{|s|yield e, Title, s.to_utf8} # subject
57
+
58
+ yield e, SIOC+'has_discussion', # thread
59
+ R[e+'?graph=thread&view=timegraph#discussion'] if m.in_reply_to || m.references
60
+
61
+ %w{to cc bcc}.map{|to| # reciever fields
62
+ m.send(to).do{|to| # has field?
63
+ to.justArray.map{|to| # each recipient
64
+ to.do{|to| # non-nil?
65
+ to = to.to_utf8 # UTF-8
66
+ yield e, To, R['/m/'+to+'#'+to]}}}} # recipient URI
67
+
68
+ %w{in_reply_to references}.map{|ref| # reference predicates
69
+ m.send(ref).do{|rs| rs.justArray.map{|r| # indirect-references
70
+ yield e, SIOC+'reply_of', R[MessagePath[r]]}}} # reference URI
71
+
72
+ m.in_reply_to.do{|r| # direct-reference predicate
73
+ yield e, SIOC+'has_parent', R[MessagePath[r]]} # reference URI
74
+
75
+ parts = m.all_parts.push m # parts
76
+
77
+ parts.select{|p| # text parts
78
+ (!p.mime_type || p.mime_type=='text/plain') &&
79
+ Mail::Encodings.defined?(p.body.encoding) # decodable?
80
+ }.map{|p|
81
+ yield e, Content,
82
+ H([{_: :pre, class: :mail, style: 'white-space: pre-wrap', # wrap body
83
+ c: p.decoded.to_utf8.hrefs.gsub(/^\s*(&gt;)(&gt;|\s)*\n/,"").lines.to_a.map{|l| # skip quoted*empty lines
84
+ l.match(/(^\s*(&gt;|On[^\n]+(said|wrote))[^\n]*)\n/) ? # quoted?
85
+ {_: :span, class: :q, depth: l.scan(/(&gt;)/).size, c: l} : l # wrap quotes
86
+ }},(H.css '/css/mail',true)])}
87
+
88
+ attache = -> { e.R.a('.attache').mk } # filesystem container for attachments & parts
89
+
90
+ htmlCount = 0
91
+ parts.select{|p|p.mime_type=='text/html'}.map{|p| # HTML content
92
+ html = attache[].as "page#{htmlCount}.html" # name
93
+ yield e, DC+'hasFormat', html # message -> HTML resource
94
+ html.w p.decoded if !html.e # write content
95
+ htmlCount += 1 }
96
+ # attached
97
+ m.attachments.select{|p|Mail::Encodings.defined?(p.body.encoding)}.map{|p|
98
+ name = p.filename.do{|f|f.to_utf8.do{|f|!f.empty? && f}} || (rand.to_s.h + '.' + (MIME.invert[p.mime_type] || 'bin').to_s)
99
+ file = attache[].as name # name
100
+ file.w p.body.decoded if !file.e # write
101
+ yield e, SIOC+'attachment', file # message -> attached resource
102
+ if p.main_type=='image' # image reference in HTML
103
+ yield e, Content, H({_: :a, href: file.uri, c: [{_: :img, src: file.uri},p.filename]})
104
+ end }
81
105
 
82
- module TMail
83
- class Mail
84
- def unicode_body
85
- unquoted_body.to_utf8
86
- end
87
- def concat_message i, partCount=0, &f
88
- if multipart?
89
- parts.map{|part|
90
- if part.multipart? # and even more nested parts..
91
- part.concat_message i, partCount, &f
92
- elsif !attachment?(part) && part.sub_type != 'html'
93
- part.unicode_body.hrefs true
94
- else # attachment
95
- a = i.a('.attache').mk # create container
96
- p = a.as(part['content-type']['name'] || (partCount.to_s + '.' + (E::MIME.invert[part.content_type] || '.bin').to_s))
97
- p.w part.body if !p.e # write attachment into message container
98
- partCount += 1 # display images
99
- yield i.uri, E::SIOC+'attachment', p
100
- '<a href="'+p.uri+'">'+(part.main_type=='image' ? '<img src="'+p.uri+'">' : '')+p.uri.label+"</a><br>\n"
101
- end
102
- }.join
103
- else # just a part
104
- unicode_body.do{|b|
105
- if content_type && content_type.match(/html/)
106
- E::F['cleanHTML'][b]
107
- else
108
- b.hrefs true
109
- end}
110
- end
111
- end
112
106
  end
113
- end
114
107
 
115
- class String; def is_binary_data?; true; end; end
108
+ F['view/'+MIMEtype+'message/rfc822'] = NullView # hide container-resource in default view
109
+ =begin
110
+ USAGE(context)
111
+
112
+ admin (irb) move messages among filesystems
113
+ p = R['/m/semantic-web@w3.org'].take.map{|g|'.' + g.graph.values.find{|r|r.has_key?(R::DC+'source')}[R::DC+'source'][0].R.path}
114
+ `rsync -avRz #{p.join ' '} h:/www/`
115
+
116
+ view (rb) default to overview of directory
117
+ F['/mail/GET'] = -> e,r {
118
+ r.q['view'] ||= 'threads' if e.uri[-1] == '/'
119
+ false }
120
+
121
+ home (sh) current day-dir in Markdown
122
+ echo "[today](/?y=day&view=threads)" > TODAY.md
123
+
124
+ =end
125
+ end
@@ -1,5 +1,5 @@
1
1
  #watch __FILE__
2
- class E
2
+ class R
3
3
 
4
4
  fn '/man/GET',->e,r{
5
5
  manPath = '/usr/share/man'
@@ -16,7 +16,7 @@ class E
16
16
  if !name || name.empty? || name.match(/\//)
17
17
  if section
18
18
  # enumerate section children
19
- body = H [H.css('/css/man'),{_: :style, c: "a {background-color: #{E.cs}}"},
19
+ body = H [H.css('/css/man'),{_: :style, c: "a {background-color: #{R.cs}}"},
20
20
  Pathname(manPath+'/man'+section).c.map{|p|
21
21
  n = p.basename.to_s.sub /\.[0-9][a-z]*\...$/,''
22
22
  }.group_by{|e|e[0].match(/[a-zA-Z]/) ? e[0].downcase : '0-9'}.sort.map{|g,m|
@@ -37,8 +37,8 @@ class E
37
37
  return false
38
38
  else
39
39
 
40
- roff = man.E
41
- htmlBase = roff.dir.to_s.sub(/.*\/share/,'').E
40
+ roff = man.R
41
+ htmlBase = roff.dir.to_s.sub(/.*\/share/,'').R
42
42
  html = htmlBase.as roff.bare + '.html'
43
43
  cached = html.e && html.m > (Pathname man).stat.mtime
44
44
 
@@ -59,7 +59,7 @@ class E
59
59
 
60
60
  # add CSS link
61
61
  body.add_child H H.css('/css/man')
62
- body.add_child H[{_: :style, c: "a {background-color:#{E.cs}}"}]
62
+ body.add_child H[{_: :style, c: "a {background-color:#{R.cs}}"}]
63
63
 
64
64
  # add localization links
65
65
  (body.css('h1')[0] ||
@@ -69,7 +69,7 @@ class E
69
69
 
70
70
  # webize image paths
71
71
  body.css('img').map{|i|
72
- p = (i.attr 'src').unpathFs
72
+ p = (i.attr 'src').unpath
73
73
  i.replace H[{_: :img, src: p}]}
74
74
 
75
75
  # inspect plaintext