gonzui 1.2-x86-mswin32-60

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.
Files changed (120) hide show
  1. data/AUTHORS.txt +9 -0
  2. data/History.txt +5539 -0
  3. data/Manifest.txt +115 -0
  4. data/PostInstall.txt +17 -0
  5. data/README.rdoc +149 -0
  6. data/Rakefile +28 -0
  7. data/bin/gonzui-db +167 -0
  8. data/bin/gonzui-import +177 -0
  9. data/bin/gonzui-remove +58 -0
  10. data/bin/gonzui-search +68 -0
  11. data/bin/gonzui-server +176 -0
  12. data/bin/gonzui-update +53 -0
  13. data/data/gonzui/catalog/catalog.ja +80 -0
  14. data/data/gonzui/doc/favicon.ico +0 -0
  15. data/data/gonzui/doc/folder.png +0 -0
  16. data/data/gonzui/doc/gonzui.css +279 -0
  17. data/data/gonzui/doc/gonzui.js +111 -0
  18. data/data/gonzui/doc/text.png +0 -0
  19. data/data/gonzuirc.sample +29 -0
  20. data/ext/autopack/autopack.c +88 -0
  21. data/ext/autopack/extconf.rb +3 -0
  22. data/ext/delta/delta.c +147 -0
  23. data/ext/delta/extconf.rb +5 -0
  24. data/ext/texttokenizer/extconf.rb +5 -0
  25. data/ext/texttokenizer/texttokenizer.c +93 -0
  26. data/ext/xmlformatter/extconf.rb +5 -0
  27. data/ext/xmlformatter/xmlformatter.c +207 -0
  28. data/lib/gonzui.rb +59 -0
  29. data/lib/gonzui/apt.rb +193 -0
  30. data/lib/gonzui/autopack.so +0 -0
  31. data/lib/gonzui/bdbdbm.rb +118 -0
  32. data/lib/gonzui/cmdapp.rb +14 -0
  33. data/lib/gonzui/cmdapp/app.rb +175 -0
  34. data/lib/gonzui/cmdapp/search.rb +134 -0
  35. data/lib/gonzui/config.rb +117 -0
  36. data/lib/gonzui/content.rb +19 -0
  37. data/lib/gonzui/dbm.rb +673 -0
  38. data/lib/gonzui/deindexer.rb +162 -0
  39. data/lib/gonzui/delta.rb +49 -0
  40. data/lib/gonzui/delta.so +0 -0
  41. data/lib/gonzui/extractor.rb +347 -0
  42. data/lib/gonzui/fetcher.rb +309 -0
  43. data/lib/gonzui/gettext.rb +144 -0
  44. data/lib/gonzui/importer.rb +84 -0
  45. data/lib/gonzui/indexer.rb +316 -0
  46. data/lib/gonzui/info.rb +80 -0
  47. data/lib/gonzui/license.rb +100 -0
  48. data/lib/gonzui/logger.rb +48 -0
  49. data/lib/gonzui/monitor.rb +177 -0
  50. data/lib/gonzui/progressbar.rb +235 -0
  51. data/lib/gonzui/remover.rb +38 -0
  52. data/lib/gonzui/searcher.rb +330 -0
  53. data/lib/gonzui/searchquery.rb +235 -0
  54. data/lib/gonzui/searchresult.rb +111 -0
  55. data/lib/gonzui/texttokenizer.so +0 -0
  56. data/lib/gonzui/updater.rb +254 -0
  57. data/lib/gonzui/util.rb +415 -0
  58. data/lib/gonzui/vcs.rb +128 -0
  59. data/lib/gonzui/webapp.rb +25 -0
  60. data/lib/gonzui/webapp/advsearch.rb +123 -0
  61. data/lib/gonzui/webapp/filehandler.rb +24 -0
  62. data/lib/gonzui/webapp/jsfeed.rb +61 -0
  63. data/lib/gonzui/webapp/markup.rb +445 -0
  64. data/lib/gonzui/webapp/search.rb +269 -0
  65. data/lib/gonzui/webapp/servlet.rb +319 -0
  66. data/lib/gonzui/webapp/snippet.rb +155 -0
  67. data/lib/gonzui/webapp/source.rb +37 -0
  68. data/lib/gonzui/webapp/stat.rb +137 -0
  69. data/lib/gonzui/webapp/top.rb +63 -0
  70. data/lib/gonzui/webapp/uri.rb +140 -0
  71. data/lib/gonzui/webapp/webrick.rb +48 -0
  72. data/lib/gonzui/webapp/xmlformatter.so +0 -0
  73. data/script/console +10 -0
  74. data/script/destroy +14 -0
  75. data/script/generate +14 -0
  76. data/script/makemanifest.rb +21 -0
  77. data/tasks/extconf.rake +13 -0
  78. data/tasks/extconf/autopack.rake +43 -0
  79. data/tasks/extconf/delta.rake +43 -0
  80. data/tasks/extconf/texttokenizer.rake +43 -0
  81. data/tasks/extconf/xmlformatter.rake +43 -0
  82. data/test/_external_tools.rb +13 -0
  83. data/test/_test-util.rb +142 -0
  84. data/test/foo/Makefile.foo +66 -0
  85. data/test/foo/bar.c +5 -0
  86. data/test/foo/bar.h +6 -0
  87. data/test/foo/foo.c +25 -0
  88. data/test/foo/foo.spec +33 -0
  89. data/test/test_apt.rb +42 -0
  90. data/test/test_autopack_extn.rb +7 -0
  91. data/test/test_bdbdbm.rb +79 -0
  92. data/test/test_cmdapp-app.rb +35 -0
  93. data/test/test_cmdapp-search.rb +99 -0
  94. data/test/test_config.rb +28 -0
  95. data/test/test_content.rb +15 -0
  96. data/test/test_dbm.rb +171 -0
  97. data/test/test_deindexer.rb +50 -0
  98. data/test/test_delta.rb +66 -0
  99. data/test/test_extractor.rb +78 -0
  100. data/test/test_fetcher.rb +75 -0
  101. data/test/test_gettext.rb +50 -0
  102. data/test/test_gonzui.rb +11 -0
  103. data/test/test_helper.rb +10 -0
  104. data/test/test_importer.rb +56 -0
  105. data/test/test_indexer.rb +37 -0
  106. data/test/test_info.rb +82 -0
  107. data/test/test_license.rb +49 -0
  108. data/test/test_logger.rb +60 -0
  109. data/test/test_monitor.rb +23 -0
  110. data/test/test_searcher.rb +37 -0
  111. data/test/test_searchquery.rb +27 -0
  112. data/test/test_searchresult.rb +43 -0
  113. data/test/test_texttokenizer.rb +47 -0
  114. data/test/test_updater.rb +95 -0
  115. data/test/test_util.rb +149 -0
  116. data/test/test_vcs.rb +61 -0
  117. data/test/test_webapp-markup.rb +42 -0
  118. data/test/test_webapp-util.rb +19 -0
  119. data/test/test_webapp-xmlformatter.rb +19 -0
  120. metadata +292 -0
data/lib/gonzui/vcs.rb ADDED
@@ -0,0 +1,128 @@
1
+ #
2
+ # vcs.rb - simple interface to version control systems
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ module Gonzui
13
+ class VCSError < GonzuiError; end
14
+
15
+ class AbstractVCS
16
+ include Util
17
+
18
+ def initialize(config, root, mozule)
19
+ @config = config
20
+ @root = root
21
+ @mozule = mozule
22
+ end
23
+
24
+ private
25
+ def run_command(command_line, message)
26
+ printf("running %s...\n", message) unless @config.quiet
27
+ dn = "/dev/null"
28
+ dn = "nul" if (/mswin|mingw|bccwin/ =~ RUBY_PLATFORM)
29
+ command_line += ">#{dn} 2>&1" unless @config.verbose
30
+ status = system(command_line)
31
+ raise VCSError.new("command execution failed") if status == false
32
+ end
33
+
34
+ public
35
+ def extract
36
+ File.mkpath(@config.cache_directory)
37
+ output_directory = File.join(@config.cache_directory, @mozule)
38
+ if not File.exist?(output_directory)
39
+ do_checkout(output_directory)
40
+ elsif File.directory?(output_directory)
41
+ do_update(output_directory)
42
+ else
43
+ raise VCSError.new("#{output_directory}: obstacle found")
44
+ end
45
+ return output_directory
46
+ end
47
+
48
+ def clean
49
+ end
50
+ end
51
+
52
+ class CVS < AbstractVCS
53
+ def initialize(config, root, mozule)
54
+ require_command("cvs")
55
+ super(config, root, mozule)
56
+ end
57
+
58
+ def do_checkout(output_directory)
59
+ Dir.chdir(@config.cache_directory) {
60
+ command_line = sprintf("cvs -z3 -d %s co -P %s",
61
+ shell_escape(@root),
62
+ shell_escape(@mozule))
63
+ run_command(command_line, "cvs checkout")
64
+ }
65
+ end
66
+
67
+ def do_update(output_directory)
68
+ Dir.chdir(output_directory) {
69
+ run_command("cvs -z3 update -dP", "cvs update")
70
+ }
71
+ end
72
+
73
+ def do_extract
74
+ File.mkpath(@config.cache_directory)
75
+ output_directory = File.join(@config.cache_directory, @mozule)
76
+ if File.exist?(output_directory)
77
+ run_cvs_update(output_directory)
78
+ else
79
+ run_cvs_checkout
80
+ end
81
+ return output_directory
82
+ end
83
+ end
84
+
85
+ class Subversion < AbstractVCS
86
+ def initialize(config, root, mozule)
87
+ require_command("svn")
88
+ super(config, root, mozule)
89
+ end
90
+
91
+ def do_checkout(output_directory)
92
+ Dir.chdir(@config.cache_directory) {
93
+ command_line = sprintf("svn co %s %s",
94
+ shell_escape(@root),
95
+ shell_escape(@mozule))
96
+ run_command(command_line, "svn checkout")
97
+ }
98
+ end
99
+
100
+ def do_update(output_directory)
101
+ Dir.chdir(output_directory) {
102
+ run_command("svn update","svn update")
103
+ }
104
+ end
105
+ end
106
+
107
+ class Git < AbstractVCS
108
+ def initialize(config, root, mozule = nil)
109
+ require_command("git")
110
+ mozule = File.basename(URI.parse(root).path, ".git") unless mozule
111
+ super(config, root, mozule)
112
+ end
113
+
114
+ def do_checkout(output_directory)
115
+ Dir.chdir(@config.cache_directory) {
116
+ command_line = sprintf("git clone %s",
117
+ shell_escape(@root))
118
+ run_command(command_line, "git clone")
119
+ }
120
+ end
121
+
122
+ def do_update(output_directory)
123
+ Dir.chdir(output_directory) {
124
+ run_command("git pull","git pull")
125
+ }
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,25 @@
1
+ #
2
+ # webapp.rb - a library for web-based applications
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ require 'gonzui/webapp/xmlformatter'
13
+ require 'gonzui/webapp/webrick'
14
+ require 'gonzui/webapp/uri'
15
+ require 'gonzui/webapp/servlet'
16
+ require 'gonzui/webapp/snippet'
17
+
18
+ require 'gonzui/webapp/advsearch'
19
+ require 'gonzui/webapp/filehandler'
20
+ require 'gonzui/webapp/jsfeed'
21
+ require 'gonzui/webapp/markup'
22
+ require 'gonzui/webapp/search'
23
+ require 'gonzui/webapp/source'
24
+ require 'gonzui/webapp/stat'
25
+ require 'gonzui/webapp/top'
@@ -0,0 +1,123 @@
1
+ #
2
+ # advsearch.rb - advanced search servlet
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ module Gonzui
13
+ class AdvancedSearchServlet < GonzuiAbstractServlet
14
+ def self.mount_point
15
+ "advsearch"
16
+ end
17
+
18
+ def do_make_status_line
19
+ []
20
+ end
21
+
22
+ def make_target_select
23
+ tt = get_short_name(:target_type)
24
+ select = [:select, {:name => tt}]
25
+ oall = [:option, {:type => "radio", :name => tt,
26
+ :value => ""}, _("All")]
27
+ select.push(oall)
28
+ LangScan::Type.each_group {|group|
29
+ og = [:optgroup, {:label => _(group.name)}]
30
+ added_p = false
31
+ group.each {|type_info|
32
+ if @dbm.has_type?(type_info.type)
33
+ o = [:option, {:type => "radio", :name => tt,
34
+ :value => type_info.type}, _(type_info.name)]
35
+ og.push(o)
36
+ added_p = true
37
+ end
38
+ }
39
+ select.push(og) if added_p
40
+ }
41
+ return select
42
+ end
43
+
44
+ def make_nresults_select
45
+ nr = get_short_name(:nresults_per_page)
46
+ select = [:select, {:name => nr}]
47
+ @config.nresults_candidates.each {|n|
48
+ o = [:option, {:type => "radio", :name => nr,
49
+ :value => n}, sprintf(_("%d results"), n)]
50
+ select.push(o)
51
+ }
52
+ return select
53
+ end
54
+
55
+ def make_target_specific_search_form
56
+ form = [:form, { :method => "get",
57
+ :action => make_uri_general(SearchServlet)}]
58
+
59
+ ikeyword = [:input, {:type => "text", :size => 30,
60
+ :name => get_short_name(:basic_query),
61
+ :value => @search_query.keywords.join(" ")}]
62
+ iphrase = [:input, {:type => "text", :size => 30,
63
+ :name => get_short_name(:phrase_query),
64
+ :value => (@search_query.phrases.first or []).join(" ")}]
65
+
66
+ nresults_select = make_nresults_select
67
+
68
+ isubmit = [:input, {:type => "submit", :value => _("Search")}]
69
+
70
+ table = [:table]
71
+ table.push([:tr, [:td, {:width => "20%"}, _("Keyword")],
72
+ [:td, {:width => "30%"}, ikeyword],
73
+ [:td, {:width => "15%"}, nresults_select],
74
+ [:td, {:width => "15%"}, isubmit]])
75
+ table.push([:tr, [:td, {:width => "20%"}, _("Phrase")],
76
+ [:td, {:width => "30%"}, iphrase]])
77
+
78
+ table.push([:tr])
79
+
80
+ target_select = make_target_select
81
+ table.push([:tr, [:td, _("Target")],
82
+ [:td, target_select], [:td]])
83
+
84
+ format_select = make_format_select
85
+ table.push([:tr, [:td, _("Format")], [:td, format_select], [:td]])
86
+
87
+ license_select = make_license_select
88
+ table.push([:tr, [:td, _("License")], [:td, license_select], [:td]])
89
+
90
+ form.push(table)
91
+ return form
92
+ end
93
+
94
+ def make_advanced_search_form
95
+ form = make_target_specific_search_form
96
+ return [:div, {:class =>"advanced-search"}, form]
97
+ end
98
+
99
+ def do_GET(request, response)
100
+ init_servlet(request, response)
101
+ log()
102
+
103
+ html = make_html
104
+ title = make_title(_("Advanced Search"))
105
+ head = [:head, title, *make_meta_and_css]
106
+ body = [:body]
107
+
108
+ h1 = make_h1
109
+ status_line = make_status_line(_("Advanced Search"))
110
+ content = make_advanced_search_form
111
+ footer = make_footer
112
+ body.push(h1, status_line, content, footer)
113
+
114
+ html.push(head)
115
+ html.push(body)
116
+ set_content_type_text_html
117
+ response.body = format_html(html)
118
+ end
119
+
120
+ GonzuiServlet.register(self)
121
+ end
122
+ end
123
+
@@ -0,0 +1,24 @@
1
+ #
2
+ # filehandler.rb - file handler servlet
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ module Gonzui
13
+ class FileHandler < WEBrick::HTTPServlet::FileHandler
14
+ def self.mount_point
15
+ "doc"
16
+ end
17
+
18
+ def initialize(server, config, logger, dbm, catalogs)
19
+ super(server, config.doc_directory)
20
+ end
21
+
22
+ GonzuiServlet.register(self)
23
+ end
24
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # jsfeed - javascript-feed servlet
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ module Gonzui
13
+ class JSFeedServlet < GonzuiAbstractServlet
14
+ def self.mount_point
15
+ "jsfeed"
16
+ end
17
+
18
+ def do_GET(request, response)
19
+ init_servlet(request, response)
20
+ path = make_path
21
+ log(path)
22
+
23
+ from = to = nil
24
+ if m = /^(\d+)-(\d+)$/.match(request.query_string)
25
+ from = m[1].to_i
26
+ to = m[2].to_i
27
+ end
28
+
29
+ if from and to
30
+ path_id = @dbm.get_path_id(path)
31
+ if path_id
32
+ content = @dbm.get_content(path_id)
33
+ lineno = 0
34
+ lines = []
35
+ range = Range.new(from, to)
36
+ content.each_line {|line|
37
+ lineno += 1
38
+ if range.include?(lineno)
39
+ line_with_lineno = sprintf("%5d: %s", lineno, line)
40
+ line_with_lineno.chop!
41
+ lines.push(HTMLUtils.escape(line_with_lineno))
42
+ end
43
+ }
44
+ snippet = lines.join("<br />")
45
+ response.body = sprintf("document.writeln('<pre>%s</pre>');",
46
+ snippet)
47
+ response['Content-Type'] = "application/x-javascript"
48
+ else
49
+ response.body = sprintf("%s: not found", path)
50
+ response.status = 404
51
+ response['Content-Type'] = "text/html"
52
+ end
53
+ else
54
+ response.body = "invalid query"
55
+ response['Content-Type'] = "text/html"
56
+ end
57
+ end
58
+
59
+ GonzuiServlet.register(self)
60
+ end
61
+ end
@@ -0,0 +1,445 @@
1
+ #
2
+ # markup.rb - markup servlet
3
+ #
4
+ # Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
5
+ # All rights reserved.
6
+ # This is free software with ABSOLUTELY NO WARRANTY.
7
+ #
8
+ # You can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License version 2.
10
+ #
11
+
12
+ require 'stringio'
13
+ require 'zlib'
14
+ require 'strscan'
15
+
16
+ module Gonzui
17
+ class TextBeautifier
18
+ def initialize(content, digest, occurrences, search_uri)
19
+ @content = content
20
+ @digest = digest # to be destroyed
21
+ @occurrences = occurrences # to be destroyed
22
+ @search_uri = search_uri
23
+
24
+ @break_points = [0, @content.length]
25
+ @lines = {}
26
+ pos = lineno = 0
27
+ @content.each_line {|line|
28
+ lineno += 1
29
+ @break_points.push(pos)
30
+ @lines[pos] = [lineno, line]
31
+ pos += line.length
32
+ }
33
+ @digest.each {|info|
34
+ @break_points.push(info.byteno)
35
+ @break_points.push(info.end_byteno)
36
+ }
37
+ @occurrences.each {|occ|
38
+ @break_points.push(occ.byteno)
39
+ @break_points.push(occ.end_byteno)
40
+ }
41
+ @break_points.uniq!
42
+ @break_points.sort!
43
+
44
+ @info = @digest.shift
45
+ @occ = @occurrences.shift
46
+ @seen_ids = {}
47
+ @latest_id = "0"
48
+ end
49
+
50
+ def make_line_mark(lineno)
51
+ anchor = "l" + lineno.to_s
52
+ [:span, {:class => "lineno", :onclick => "olnc(this);"},
53
+ [:a, {:id => anchor, :name => anchor, :href => "#" + anchor},
54
+ sprintf("%5d: ", lineno)]]
55
+ end
56
+
57
+ def choose_target_type
58
+ case @info.type
59
+ when :fundef
60
+ :funcall
61
+ when :funcall
62
+ :fundef
63
+ when :fundecl
64
+ :fundef
65
+ else
66
+ assert_not_reached
67
+ end
68
+ end
69
+
70
+ def decorate(text)
71
+ unless @seen_ids.include?(text)
72
+ @seen_ids[text] = @latest_id
73
+ @latest_id = @latest_id.next
74
+ end
75
+ id = @seen_ids[text]
76
+ inner = [:span, {:class => id, :onmouseover => "hl('#{id}');"}, text]
77
+ part = [:span, {:class => @info.type.to_s}, inner]
78
+
79
+ if LangScan::Type.function?(@info.type)
80
+ tt = choose_target_type
81
+ query_string = sprintf("%s:%s", tt, HTTPUtils.escape_form(text))
82
+ uri = @search_uri + query_string
83
+ part = [:a, {:href => uri}, part]
84
+ end
85
+ return part
86
+ end
87
+
88
+ def markup_part(bp, ep)
89
+ part = @content[bp...ep]
90
+ if @info and (bp == @info.byteno or @info.range.include?(bp))
91
+ part = decorate(part)
92
+ @info = @digest.shift if @info.end_byteno <= ep
93
+ end
94
+ if @occ and (bp == @occ.byteno or @occ.range.include?(bp))
95
+ part = [:strong, {:class => "highlight"}, part]
96
+ @occ = @occurrences.shift if @occ.end_byteno <= ep
97
+ end
98
+ return part
99
+ end
100
+
101
+ def make_lineno_part(bp)
102
+ lineno, line = @lines[bp]
103
+ [:span, {:class => "line", :title => line}, make_line_mark(lineno)]
104
+ end
105
+
106
+ def beautify
107
+ code = []
108
+ bp = @break_points.shift
109
+ line = nil
110
+ while not @break_points.empty?
111
+ ep = @break_points.shift
112
+ if @lines.include?(bp)
113
+ code.push(line) if line
114
+ line = make_lineno_part(bp)
115
+ end
116
+ part = markup_part(bp, ep)
117
+ line.push(part)
118
+ bp = ep
119
+ end
120
+ code.push(line) if line
121
+ return code
122
+ end
123
+ end
124
+
125
+ class MarkupServlet < GonzuiAbstractServlet
126
+ def self.mount_point
127
+ "markup"
128
+ end
129
+
130
+ def make_breadcrumbs(path)
131
+ parts = path.split("/")
132
+ breadcrumbs = (1 .. parts.length).map {|i|
133
+ [ parts[i - 1], parts[0, i]]
134
+ }.map {|part, parts|
135
+ path = parts.join("/")
136
+ uri = make_markup_uri(parts.join("/"), @search_query)
137
+ [:a, {:href => uri}, part]
138
+ }
139
+ (breadcrumbs.length - 1).times {|i|
140
+ breadcrumbs.insert(i * 2 + 1, "/")
141
+ }
142
+ return [:span, *breadcrumbs]
143
+ end
144
+
145
+ def do_make_status_line(method)
146
+ items = []
147
+
148
+ case method
149
+ when :markup_file
150
+ if @path_id
151
+ bare = [:a, {:href => make_source_uri(@path)},
152
+ _("bare source")]
153
+ permlink = [:a, {:href => make_markup_uri(@path)},
154
+ _("permlink")]
155
+ items.push(bare)
156
+ items.push(permlink)
157
+ end
158
+ when :list_files
159
+ if @total
160
+ items.push([:span, [:strong, @total], _(" contents.")])
161
+ end
162
+ when :list_packages
163
+ if @to and @total
164
+ packages = [:span, _("Packages "),
165
+ [:strong, commify(@from + 1)], " - ",
166
+ [:strong, commify(@to)], _(" of "),
167
+ [:strong, commify(@total)], _(".")]
168
+ items.push(packages)
169
+ end
170
+ end
171
+ return items
172
+ end
173
+
174
+ def calc_ncolumns(items)
175
+ sum = items.inject(0) {|a, b|
176
+ name = b.first
177
+ a + name.length
178
+ }
179
+ average = sum / items.length
180
+ ncolumns = [40 / average, items.length].min
181
+ ncolumns = 1 if ncolumns == 0
182
+ return ncolumns
183
+ end
184
+
185
+ def make_table(items)
186
+ table = [:table, {:class => "fullwidth"}]
187
+ return table if items.empty?
188
+ ncolumns = calc_ncolumns(items)
189
+ width = sprintf("%d%%", 100/ncolumns)
190
+
191
+ nrows = (items.length - 1) / ncolumns + 1
192
+ nrows.times {|i|
193
+ k = if (i + 1) % 2 == 0 then "even" else "odd" end
194
+ row = [:tr, {:class => k}]
195
+ ncolumns.times {|j|
196
+ # item = items[j * nrows + i] # for vertical arrange
197
+ item = items[i * ncolumns + j]
198
+ value = if item
199
+ name, klass, image, uri, title = item
200
+ tr = [:tr]
201
+ if image
202
+ img = [:img, {:src => image, :alt => ""}]
203
+ tr << [:td, [:a, {:href => uri}, img]]
204
+ end
205
+ a = [:a, {:class => klass, :href =>uri,:title =>title}, name]
206
+ tr << [:td, a]
207
+ [:table, {:class => "item"}, tr]
208
+ else
209
+ make_spacer
210
+ end
211
+ k = if j == 0 then "first" else "nonfirst" end
212
+ td = [:td, {:width => width, :class => k}, value]
213
+ row.push(td)
214
+ }
215
+ table.push(row)
216
+ }
217
+ return table
218
+ end
219
+
220
+ def make_title_for_path(path, file_p)
221
+ title = if file_p
222
+ path_id = @dbm.get_path_id(path)
223
+ info = @dbm.get_content_info(path_id)
224
+ sprintf(_("Size: %s (%s lines)"),
225
+ format_bytes(info.size),
226
+ commify(info.nlines))
227
+ else
228
+ ""
229
+ end
230
+ return title
231
+ end
232
+
233
+ def make_table_of_files(paths)
234
+ items = paths.map {|path, file_p|
235
+ basename = File.basename(path)
236
+ klass = if file_p then "file" else "directory" end
237
+ image = if file_p
238
+ make_doc_uri("text.png")
239
+ else
240
+ make_doc_uri("folder.png")
241
+ end
242
+ uri = make_markup_uri(path, @search_query)
243
+ title = make_title_for_path(path, file_p)
244
+ [basename, klass, image, uri, title]
245
+ }
246
+ return make_table(items)
247
+ end
248
+
249
+ def make_table_of_packages(package_names)
250
+ items = package_names.map {|package_name|
251
+ package_id = @dbm.get_package_id(package_name)
252
+ uri = make_markup_uri(package_name)
253
+ title = ""
254
+ [package_name, "directory", nil, uri, title]
255
+ }
256
+ return make_table(items)
257
+ end
258
+
259
+ def list_files
260
+ path_parts = @path.split("/")
261
+ depth = path_parts.length
262
+
263
+ package_id = @dbm.get_package_id(@package_name)
264
+ path_ids = @dbm.get_path_ids(package_id)
265
+ paths = path_ids.map {|path_id|
266
+ @dbm.get_path(path_id)
267
+ }.map {|path|
268
+ path.split("/")
269
+ }.find_all {|parts|
270
+ parts.length > depth and parts[0, depth] == path_parts
271
+ }.map {|parts|
272
+ file_p = parts.length == depth + 1
273
+ [parts[0, depth + 1].join("/"), file_p]
274
+ }.uniq
275
+ if paths.empty?
276
+ return ""
277
+ else
278
+ @total = paths.length
279
+ return make_table_of_files(paths)
280
+ end
281
+ end
282
+
283
+ def do_make_navi(from)
284
+ make_markup_uri("", nil, :from => from)
285
+ end
286
+
287
+ def list_packages
288
+ # FIXME: sorting every time is not efficient.
289
+ all = []
290
+ @dbm.each_package_name {|package_name|
291
+ all.push(package_name)
292
+ }
293
+ all.sort!
294
+
295
+ package_names = all[@from, @config.max_packages_per_page]
296
+ if package_names
297
+ @to = @from + package_names.length
298
+ @total = all.length
299
+ table = make_table_of_packages(package_names)
300
+ navi = make_navi(all.length, @from, @config.max_packages_per_page)
301
+ return [:div, table, navi]
302
+ else
303
+ return ""
304
+ end
305
+ end
306
+
307
+ def markup_source
308
+ content = @dbm.get_content(@path_id)
309
+ digest = @dbm.get_digest(@path_id)
310
+ occurrences = if @search_query.string.empty?
311
+ []
312
+ else
313
+ search_query = @search_query.clone
314
+ search_query.path ||= @path
315
+ searcher = Searcher.new(@dbm, search_query,
316
+ @config.max_results_overall)
317
+ result = searcher.search
318
+ item = result.first
319
+ if item and not item.list.empty?
320
+ item.list
321
+ else
322
+ []
323
+ end
324
+ end
325
+ search_uri = make_search_uri_partial("")
326
+ beautifier = TextBeautifier.new(content, digest, occurrences, search_uri)
327
+ return beautifier.beautify
328
+ end
329
+
330
+ def make_isearch_form
331
+ isearch = [:div, {:class => "isearch"}]
332
+ form = [:form, {:method => "get", :action => "",
333
+ :onsubmit => "return false;"}]
334
+ p = [:p]
335
+ p.push(_("Search this content: "))
336
+ p.push([:input, {:type => "text", :name => "g", :size => "20",
337
+ :onkeyup => "isearch(this.value);",
338
+ :value => ""
339
+ }])
340
+ p.push(" ")
341
+ form.push(p)
342
+ isearch.push(form)
343
+ return isearch
344
+ end
345
+
346
+ def markup_file
347
+ path = @dbm.get_path(@path_id)
348
+
349
+ mime_type = get_mime_type(path)
350
+ media_type = get_media_type(path)
351
+ if media_type == "image"
352
+ img = [:img, {:src => make_source_uri(path),
353
+ :alt => path }]
354
+ content = [:div, {:class => "image"}, img]
355
+ elsif mime_type == "text/html"
356
+ iframe = [:iframe, {:src => make_source_uri(path),
357
+ :width => "100%", :height => "400"},
358
+ [:a, {:href => make_source_uri(path)}, path]
359
+ ]
360
+ content = iframe
361
+ else
362
+ content = [:div]
363
+ isearch = make_isearch_form
364
+ content.push(isearch)
365
+ code = markup_source
366
+ content.push([:pre, *code])
367
+ end
368
+ return content
369
+ end
370
+
371
+ def make_not_found
372
+ sprintf(_("No contents were found matching %s"),
373
+ @path)
374
+ end
375
+
376
+ def gzip(string)
377
+ strio = StringIO.new
378
+ writer = Zlib::GzipWriter.new(strio)
379
+ writer.print(string)
380
+ writer.finish
381
+ return strio.string
382
+ end
383
+
384
+ def set_response(html)
385
+ set_content_type_text_html
386
+ body = format_html(html)
387
+ if @request.gzip_encoding_supported?
388
+ @response["Content-Encoding"] = "gzip"
389
+ @response.body = gzip(body)
390
+ else
391
+ @response.body = body
392
+ end
393
+ end
394
+
395
+ def choose_method
396
+ method = :make_not_found
397
+ if @path.empty?
398
+ method = :list_packages
399
+ title = make_title(_("List of Packages"))
400
+ status_title = _("List of Packages")
401
+ else
402
+ @path_id = @dbm.get_path_id(@path)
403
+ @package_name = @path.split("/").first
404
+ if @path_id
405
+ method = :markup_file
406
+ elsif @dbm.has_package?(@package_name)
407
+ method = :list_files
408
+ end
409
+ title = make_title(@path)
410
+ status_title = make_breadcrumbs(@path)
411
+ end
412
+ return method, title, status_title
413
+ end
414
+
415
+ def do_GET(request, response)
416
+ init_servlet(request, response)
417
+ log(@path)
418
+
419
+ @path = make_path
420
+ @to = nil
421
+ @total = nil
422
+
423
+ method, title, status_title = choose_method
424
+
425
+ html = make_html
426
+ head = [:head, title, make_script, *make_meta_and_css]
427
+ body = [:body, {:onload => "initCache();",
428
+ :onclick => "clearHighlight();" }]
429
+ body.push(make_h1)
430
+ body.push(make_search_form)
431
+ content = self.send(method)
432
+
433
+ status_line = make_status_line(status_title, method)
434
+ body.push(status_line)
435
+ body.push(content)
436
+ body.push(make_footer)
437
+
438
+ html.push(head)
439
+ html.push(body)
440
+ set_response(html)
441
+ end
442
+
443
+ GonzuiServlet.register(self)
444
+ end
445
+ end