ruwiki 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/Readme.rubygems +86 -0
  2. data/Readme.tarfile +65 -0
  3. data/bin/ruwiki +58 -0
  4. data/bin/ruwiki.cgi +87 -0
  5. data/bin/ruwiki_convert +56 -0
  6. data/bin/ruwiki_service.rb +82 -0
  7. data/bin/ruwiki_servlet +53 -0
  8. data/contrib/enscript-token.rb +55 -0
  9. data/contrib/rublog_integrator.rb +68 -0
  10. data/data/Default/ProjectIndex.ruwiki +49 -0
  11. data/data/Ruwiki/Antispam.ruwiki +65 -0
  12. data/data/Ruwiki/BugTracking.ruwiki +33 -0
  13. data/data/Ruwiki/ChangeLog.ruwiki +102 -0
  14. data/data/Ruwiki/Configuring_Ruwiki.ruwiki +151 -0
  15. data/data/Ruwiki/Extending_Ruwiki.ruwiki +317 -0
  16. data/data/Ruwiki/LicenseAndAuthorInfo.ruwiki +30 -0
  17. data/data/Ruwiki/ProjectIndex.ruwiki +84 -0
  18. data/data/Ruwiki/Roadmap.ruwiki +225 -0
  19. data/data/Ruwiki/RuwikiTemplatingLibrary.ruwiki +156 -0
  20. data/data/Ruwiki/RuwikiUtilities.ruwiki +157 -0
  21. data/data/Ruwiki/SandBox.ruwiki +9 -0
  22. data/data/Ruwiki/To_Do.ruwiki +51 -0
  23. data/data/Ruwiki/TroubleShooting.ruwiki +33 -0
  24. data/data/Ruwiki/WikiFeatures.ruwiki +17 -0
  25. data/data/Ruwiki/WikiMarkup.ruwiki +261 -0
  26. data/data/Tutorial/AddingPages.ruwiki +16 -0
  27. data/data/Tutorial/AddingProjects.ruwiki +16 -0
  28. data/data/Tutorial/ProjectIndex.ruwiki +11 -0
  29. data/data/Tutorial/SandBox.ruwiki +9 -0
  30. data/data/agents.banned +60 -0
  31. data/data/agents.readonly +321 -0
  32. data/data/hostip.banned +30 -0
  33. data/data/hostip.readonly +28 -0
  34. data/lib/ruwiki.rb +622 -0
  35. data/lib/ruwiki/auth.rb +56 -0
  36. data/lib/ruwiki/auth/gforge.rb +73 -0
  37. data/lib/ruwiki/backend.rb +318 -0
  38. data/lib/ruwiki/backend/flatfiles.rb +217 -0
  39. data/lib/ruwiki/config.rb +244 -0
  40. data/lib/ruwiki/exportable.rb +192 -0
  41. data/lib/ruwiki/handler.rb +342 -0
  42. data/lib/ruwiki/lang/de.rb +339 -0
  43. data/lib/ruwiki/lang/en.rb +334 -0
  44. data/lib/ruwiki/lang/es.rb +339 -0
  45. data/lib/ruwiki/page.rb +262 -0
  46. data/lib/ruwiki/servlet.rb +38 -0
  47. data/lib/ruwiki/template.rb +553 -0
  48. data/lib/ruwiki/utils.rb +24 -0
  49. data/lib/ruwiki/utils/command.rb +102 -0
  50. data/lib/ruwiki/utils/converter.rb +297 -0
  51. data/lib/ruwiki/utils/manager.rb +639 -0
  52. data/lib/ruwiki/utils/servletrunner.rb +295 -0
  53. data/lib/ruwiki/wiki.rb +147 -0
  54. data/lib/ruwiki/wiki/tokens.rb +136 -0
  55. data/lib/ruwiki/wiki/tokens/00default.rb +211 -0
  56. data/lib/ruwiki/wiki/tokens/01wikilinks.rb +166 -0
  57. data/lib/ruwiki/wiki/tokens/02actions.rb +63 -0
  58. data/lib/ruwiki/wiki/tokens/abbreviations.rb +40 -0
  59. data/lib/ruwiki/wiki/tokens/calendar.rb +147 -0
  60. data/lib/ruwiki/wiki/tokens/headings.rb +43 -0
  61. data/lib/ruwiki/wiki/tokens/lists.rb +112 -0
  62. data/lib/ruwiki/wiki/tokens/rubylists.rb +48 -0
  63. data/ruwiki.conf +22 -0
  64. data/ruwiki.pkg +0 -0
  65. data/templates/default/body.tmpl +19 -0
  66. data/templates/default/content.tmpl +7 -0
  67. data/templates/default/controls.tmpl +23 -0
  68. data/templates/default/edit.tmpl +27 -0
  69. data/templates/default/error.tmpl +14 -0
  70. data/templates/default/footer.tmpl +23 -0
  71. data/templates/default/ruwiki.css +297 -0
  72. data/templates/default/save.tmpl +8 -0
  73. data/templates/sidebar/body.tmpl +19 -0
  74. data/templates/sidebar/content.tmpl +8 -0
  75. data/templates/sidebar/controls.tmpl +8 -0
  76. data/templates/sidebar/edit.tmpl +27 -0
  77. data/templates/sidebar/error.tmpl +13 -0
  78. data/templates/sidebar/footer.tmpl +22 -0
  79. data/templates/sidebar/ruwiki.css +347 -0
  80. data/templates/sidebar/save.tmpl +10 -0
  81. data/templates/simple/body.tmpl +13 -0
  82. data/templates/simple/content.tmpl +7 -0
  83. data/templates/simple/controls.tmpl +8 -0
  84. data/templates/simple/edit.tmpl +25 -0
  85. data/templates/simple/error.tmpl +10 -0
  86. data/templates/simple/footer.tmpl +10 -0
  87. data/templates/simple/ruwiki.css +192 -0
  88. data/templates/simple/save.tmpl +8 -0
  89. data/tests/harness.rb +52 -0
  90. data/tests/tc_backend_flatfile.rb +103 -0
  91. data/tests/tc_bugs.rb +74 -0
  92. data/tests/tc_exportable.rb +64 -0
  93. data/tests/tc_template.rb +145 -0
  94. data/tests/tc_tokens.rb +335 -0
  95. data/tests/testall.rb +20 -0
  96. metadata +182 -0
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # This file may be renamed to change the URI for the wiki.
11
+ #
12
+ # $Id: utils.rb,v 1.2 2004/09/27 04:48:27 austin Exp $
13
+ #++
14
+
15
+ # So that Ruwiki doesn't have to be loaded in full to use the bloody thing.
16
+ unless defined?(Ruwiki)
17
+ class Ruwiki
18
+ VERSION = "0.9.0"
19
+ end
20
+ end
21
+
22
+ module Ruwiki::Utils
23
+ RUN_PATH = Dir.pwd
24
+ end
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # This file may be renamed to change the URI for the wiki.
11
+ #
12
+ # $Id: command.rb,v 1.3 2004/11/09 14:55:35 austin Exp $
13
+ #++
14
+
15
+ # Implements the command pattern. Commands are used by the command-line
16
+ class Ruwiki::Utils::CommandPattern
17
+ class AbstractCommandError < Exception; end
18
+ class UnknownCommandError < RuntimeError; end
19
+ class CommandAlreadyExists < RuntimeError; end
20
+ class MissingParameterError < ArgumentError
21
+ def initialize(argument)
22
+ @argument = argument
23
+ end
24
+
25
+ attr_reader :argument
26
+ end
27
+
28
+ class << self
29
+ def add(command)
30
+ command = command.new if command.kind_of?(Class)
31
+
32
+ @commands ||= {}
33
+ if @commands.has_key?(command.name)
34
+ raise CommandAlreadyExists
35
+ else
36
+ @commands[command.name] = command
37
+ end
38
+
39
+ if command.respond_to?(:altname)
40
+ unless @commands.has_key?(command.altname)
41
+ @commands[command.altname] = command
42
+ end
43
+ end
44
+ end
45
+
46
+ def <<(command)
47
+ add(command)
48
+ end
49
+
50
+ attr_accessor :default
51
+ def default=(command) #:nodoc:
52
+ if command.kind_of?(Ruwiki::Utils::CommandPattern)
53
+ @default = command
54
+ elsif command.kind_of?(Class)
55
+ @default = command.new
56
+ elsif @commands.has_key?(command)
57
+ @default = @commands[command]
58
+ else
59
+ raise UnknownCommandError
60
+ end
61
+ end
62
+
63
+ def command?(command)
64
+ @commands.has_key?(command)
65
+ end
66
+
67
+ def command(command)
68
+ if command?(command)
69
+ @commands[command]
70
+ else
71
+ @default
72
+ end
73
+ end
74
+
75
+ def [](cmd)
76
+ self.command(cmd)
77
+ end
78
+
79
+ def default_ioe(ioe = {})
80
+ ioe[:input] ||= $stdin
81
+ ioe[:output] ||= $stdout
82
+ ioe[:error] ||= $stderr
83
+ ioe
84
+ end
85
+ end
86
+
87
+ def [](args, opts = {}, ioe = {})
88
+ call(args, opts, ioe)
89
+ end
90
+
91
+ def name
92
+ raise AbstractCommandError
93
+ end
94
+
95
+ def call(args, opts = {}, ioe = {})
96
+ raise AbstractCommandError
97
+ end
98
+
99
+ def help
100
+ raise AbstractCommandError
101
+ end
102
+ end
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # This file may be renamed to change the URI for the wiki.
11
+ #
12
+ # $Id: converter.rb,v 1.5 2004/11/26 12:18:47 austin Exp $
13
+ #++
14
+
15
+ require 'optparse'
16
+ require 'ostruct'
17
+ require 'fileutils'
18
+
19
+ module Ruwiki::Utils::Converter
20
+ class << self
21
+ TARGETS = %w(flatfiles yaml marshal)
22
+
23
+ # Create the regular expressions that are used in Ruwiki 0.6.2
24
+ OLD_HEADER_RE = /^\s*([a-z]+)\s*:\s*(.*)$/
25
+ OLD_HEADER_END_RE = /^#EHDR$/
26
+ DATA_HEADER_END_RE = /\A#EHDR\z/
27
+ NL_RE = /\n/
28
+
29
+ def with(obj)
30
+ yield obj if block_given?
31
+ end
32
+
33
+ # Only allow this to be run once. Silently fail otherwise.
34
+ def set_defaults
35
+ return unless @options.nil?
36
+ @options = OpenStruct.new
37
+
38
+ with @options do |oo|
39
+ oo.traverse_directories = true
40
+ oo.backup_old_files = true
41
+ oo.backup_extension = "~"
42
+ oo.quiet = false
43
+ oo.verbose = false
44
+ oo.extension = 'ruwiki'
45
+ oo.target_format = 'flatfiles'
46
+ end
47
+ end
48
+
49
+ def message=(lang)
50
+ if lang.kind_of?(Hash)
51
+ @message = lang
52
+ elsif "constant" == defined?(lang::Message)
53
+ @message = lang::Message
54
+ else
55
+ raise ArgumentError
56
+ end
57
+ end
58
+ def message(id)
59
+ if @message[id].nil?
60
+ []
61
+ else
62
+ @message[id]
63
+ end
64
+ end
65
+
66
+ def display_options
67
+ end
68
+
69
+ def summary
70
+ end
71
+
72
+ def run(argv, input = $stdin, output = $stdout, error = $stderr)
73
+ set_defaults
74
+
75
+ @input = input
76
+ @output = output
77
+ @error = error
78
+
79
+ language = 'en'
80
+ find_lang = argv.grep(%r{^--lang})
81
+ find_lang.each do |ee|
82
+ if ee =~ %r{^--lang=}
83
+ language = ee.sub(%r{^--lang=}, '')
84
+ else
85
+ language = argv[argv.index(ee).succ]
86
+ end
87
+ end
88
+
89
+ require "ruwiki/lang/#{language.downcase}"
90
+ self.message = Ruwiki::Lang.const_get(language.upcase)
91
+
92
+ argv.options do |opts|
93
+ opts.banner = message(:converter_usage) % File.basename($0)
94
+ opts.separator ''
95
+ opts.on('--format=FORMAT', *message(:converter_format_desc)) do |ff|
96
+ @options.target_format = ff
97
+ end
98
+ opts.on('--[no-]backup', *message(:converter_backup_desc)) do |bb|
99
+ @options.backup_old_files = bb
100
+ end
101
+ opts.on('--backup-extension=EXTENSION', *message(:converter_backupext_desc)) do |ee|
102
+ if ee.nil? or ee.empty?
103
+ @error << message(:converter_backupext_error) << "\n" if ee.nil? or ee.empty?
104
+ @error << "#{opts}\n"
105
+ return 0
106
+ end
107
+ @options.backup_extension = ee
108
+ end
109
+ opts.on('--extension=EXTENSION', *message(:converter_extension_desc)) do |ee|
110
+ if ee.nil? or ee.empty?
111
+ @error << message(:converter_extension_error) << "\n" if ee.nil? or ee.empty?
112
+ @error << "#{opts}\n"
113
+ return 0
114
+ end
115
+ @options.extension = ee
116
+ end
117
+ opts.on('--no-extension', *message(:converter_noextension_desc)) do
118
+ @options.extension = nil
119
+ end
120
+ opts.on('--lang=LANG', *message(:converter_language_desc)) do |lang|
121
+ self.message = Ruwiki::Lang.const_get(lang.upcase)
122
+ end
123
+ opts.on('--quiet', *message(:converter_quiet_desc)) do |qq|
124
+ @options.quiet = qq
125
+ @options.verbose = (not qq)
126
+ end
127
+ opts.on('--verbose', *message(:converter_verbose_desc)) do |vv|
128
+ @options.quiet = (not vv)
129
+ @options.verbose = vv
130
+ end
131
+ opts.separator ''
132
+ opts.on_tail('--help', *message(:converter_help_desc)) do
133
+ @error << "#{opts}\n"
134
+ return 0
135
+ end
136
+
137
+ opts.parse!
138
+ end
139
+
140
+ if argv.empty?
141
+ @error << message(:converter_num_arguments) << "\n#{argv.options}\n" unless @options.quiet
142
+ return 127
143
+ end
144
+
145
+ display_options if @options.verbose
146
+
147
+ @options.target_format.capitalize!
148
+ @options.target_format_class = Ruwiki::Backend.const_get(@options.target_format)
149
+
150
+ argv.each { |file| process_file(file) }
151
+
152
+ summary if not @options.quiet
153
+ end
154
+
155
+ # Process a single file.
156
+ def process_file(file)
157
+ if @options.backup_old_files
158
+ return if file =~ /#{@options.backup_extension}/
159
+ end
160
+ @out << "#{file}: " unless @options.quiet
161
+
162
+ if File.directory?(file) and @options.traverse_directories
163
+ @out << message(:converter_directory) << "\n" unless @options.quiet
164
+ Dir.chdir(file) { Dir['*'].each { |entry| process_file(entry) } }
165
+ else
166
+ begin
167
+ page, page_format = load_page(file)
168
+ @out << message(:converter_converting_from) % [ page_format, @options.target_format ] if @options.verbose
169
+ save_page(file, page)
170
+ @out << message(:converter_done) << "\n" unless @options.quiet
171
+ rescue PageLoadException
172
+ @out << message(:converter_not_ruwiki) << "\n" unless @options.quiet
173
+ rescue PageSaveException
174
+ @out << message(:cannot_nosave_modified) << "\n" % [ file ] unless @options.quiet
175
+ end
176
+ end
177
+ end
178
+
179
+ def load_page(file)
180
+ data = File.read(file)
181
+ page_format = nil
182
+
183
+ if data =~ OLD_HEADER_END_RE
184
+ page_format = 'OldFlatfiles'
185
+
186
+ page = Ruwiki::Page::NULL_PAGE.dup
187
+
188
+ unless data.empty?
189
+ rawbuf = data.split(NL_RE).map { |ee| ee.chomp }
190
+
191
+ loop do
192
+ if rawbuf[0] =~ OLD_HEADER_END_RE
193
+ rawbuf.shift
194
+ break
195
+ end
196
+
197
+ match = OLD_HEADER_RE.match(rawbuf[0])
198
+
199
+ unless match.nil?
200
+ case match.captures[0]
201
+ when 'topic'
202
+ page['properties']['topic'] = match.captures[1]
203
+ page['properties']['title'] = match.captures[1]
204
+ when 'version'
205
+ page['properties']['version'] = match.captures[1].to_i
206
+ else
207
+ nil
208
+ end
209
+ end
210
+ rawbuf.shift
211
+ end
212
+
213
+ page['page']['content'] = rawbuf.join("\n")
214
+
215
+ with page['properties'] do |pp|
216
+ pp['project'] = File.basename(File.dirname(File.expand_path(file)))
217
+ pp['editable'] = true
218
+ pp['indexable'] = true
219
+ pp['entropy'] = 0.0
220
+ end
221
+ end
222
+ end
223
+
224
+ # Try Marshal
225
+ if page_format.nil?
226
+ begin
227
+ page = ::Marshal.load(data)
228
+ page_format = 'Marshal'
229
+ rescue Exception
230
+ nil
231
+ end
232
+ end
233
+
234
+ # Try YAML
235
+ if page_format.nil?
236
+ begin
237
+ page = ::YAML.load(data)
238
+ page_format = 'YAML'
239
+ rescue Exception
240
+ nil
241
+ end
242
+ end
243
+
244
+ # Try the Flatfiles format
245
+ if page_format.nil?
246
+ begin
247
+ page = Ruwiki::Backend::Flatfiles.load(data)
248
+ page_format = 'Exportable'
249
+ rescue Exception => ex
250
+ nil
251
+ end
252
+ end
253
+
254
+ if page_format.nil? # Cannot detect page type.
255
+ @error << @message[:converter_page_format_error] << "\n"
256
+ raise PageLoadException
257
+ end
258
+ [page, page_format]
259
+ rescue PageLoadException
260
+ raise
261
+ rescue Exception => ex
262
+ @error << %Q|#{ex.message}\n#{ex.backtrace.join("\n")}\n| if @options.verbose
263
+ raise PageLoadException
264
+ end
265
+
266
+ def save_page(file, page)
267
+ if @options.backup_extension != '~'
268
+ backup = "#{file}.#{@options.backup_extension}"
269
+ else
270
+ backup = "#{file}#{@options.backup_extension}"
271
+ end
272
+
273
+ # Always backup the file -- we are transactional.
274
+ FileUtils.cp(file, backup)
275
+
276
+ if @options.target_format == 'Marshal'
277
+ method = :print
278
+ else
279
+ method = :puts
280
+ end
281
+ File.open(file, 'wb') { |ff| ff.__send__(method, @options.target_format_class.dump(page)) }
282
+ rescue Exception => ex
283
+ FileUtils.mv(backup, file) if File.exists?(backup)
284
+ @error << %Q|#{ex.message}\n#{ex.backtrace.join("\n")}\n| if @options.verbose
285
+ raise PageSaveException
286
+ ensure
287
+ # If we aren't *supposed* to back up the file, then get rid of the
288
+ # backup.
289
+ if File.exists?(backup) and (not @options.backup_old_files)
290
+ FileUtils.rm(backup)
291
+ end
292
+ end
293
+
294
+ class PageLoadException < RuntimeError; end
295
+ class PageSaveException < RuntimeError; end
296
+ end
297
+ end
@@ -0,0 +1,639 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # This file may be renamed to change the URI for the wiki.
11
+ #
12
+ # $Id: manager.rb,v 1.10 2004/11/28 02:26:57 austin Exp $
13
+ #++
14
+
15
+ require 'optparse'
16
+ require 'ostruct'
17
+ require 'fileutils'
18
+ require 'stringio'
19
+ require 'zlib'
20
+ require 'ruwiki/exportable'
21
+ require 'ruwiki/utils/command'
22
+ require 'ruwiki/config'
23
+
24
+ begin
25
+ if defined?(Gem::Cache)
26
+ require_gem 'archive-tar-minitar', '~> 0.5.1'
27
+ else
28
+ require 'archive/tar/minitar'
29
+ end
30
+ rescue LoadError => ex
31
+ $stderr.puts ex.message
32
+ raise
33
+ end
34
+
35
+ module Ruwiki::Utils::Manager
36
+ DEFAULT_PACKAGE_NAME = 'ruwiki.pkg'
37
+
38
+ def self.message=(lang)
39
+ if lang.kind_of?(Hash)
40
+ @message = lang
41
+ elsif "constant" == defined?(lang::Message)
42
+ @message = lang::Message
43
+ else
44
+ raise ArgumentError
45
+ end
46
+ end
47
+ def self.message(id)
48
+ @message[id]
49
+ end
50
+
51
+ class ManagerError < RuntimeError; end
52
+
53
+ EXECUTABLES = %w(ruwiki.cgi ruwiki_servlet ruwiki_servlet.bat \
54
+ ruwiki_servlet.cmd ruwiki_service.rb)
55
+
56
+ class ManagerHelp < Ruwiki::Utils::CommandPattern
57
+ def name
58
+ "help"
59
+ end
60
+
61
+ def call(args, opts = {}, ioe = {})
62
+ ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
63
+ help_on = args.shift
64
+ output = ""
65
+
66
+ if Ruwiki::Utils::CommandPattern.command?(help_on)
67
+ ioe[:output] << Ruwiki::Utils::CommandPattern[help_on].help
68
+ elsif help_on == "commands"
69
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_help_commands)
70
+ else
71
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_unknown_command) % [ help_on ] << "\n" % [ help_on ] unless help_on.nil? or help_on.empty?
72
+ ioe[:output] << self.help
73
+ end
74
+
75
+ 0
76
+ end
77
+
78
+ def help
79
+ Ruwiki::Utils::Manager.message(:manager_help_help)
80
+ end
81
+ end
82
+
83
+ class ManagerInstall < Ruwiki::Utils::CommandPattern
84
+ def name
85
+ "install"
86
+ end
87
+
88
+ def call(args, opts = {}, ioe = {})
89
+ argv = []
90
+
91
+ replace = false
92
+ dest = "."
93
+ name = nil
94
+
95
+ while (arg = args.shift)
96
+ case arg
97
+ when '--to'
98
+ dir = args.shift
99
+ raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if dir.nil?
100
+ if File.exist?(dir)
101
+ if not File.directory?(dir)
102
+ raise ArgumentError, Ruwiki::Utils::Manager.message(:manager_dest_not_directory)
103
+ end
104
+ else
105
+ FileUtils.mkdir_p(dir)
106
+ end
107
+ dest = dir
108
+ when /;/o
109
+ argv.push(*(arg.split(/;/o)))
110
+ when /,/o
111
+ argv.push(*(arg.split(/,/o)))
112
+ else
113
+ argv << arg
114
+ end
115
+ end
116
+
117
+ options = { 'data' => true }
118
+
119
+ while (arg = argv.shift)
120
+ case arg
121
+ when /^(?:-|no)(.*$)/
122
+ options.delete($1)
123
+ else
124
+ options[arg] = true
125
+ end
126
+ end
127
+
128
+ Ruwiki::Utils::Manager.install(dest, options)
129
+
130
+ 0
131
+ end
132
+
133
+ def help
134
+ Ruwiki::Utils::Manager.message(:manager_install_help)
135
+ end
136
+ end
137
+
138
+ class ManagerPackage < Ruwiki::Utils::CommandPattern
139
+ def name
140
+ "package"
141
+ end
142
+
143
+ def call(args, opts = {}, ioe = {})
144
+ ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
145
+ argv = []
146
+ replace = false
147
+ dest = "."
148
+ name = nil
149
+
150
+ while (arg = args.shift)
151
+ case arg
152
+ when '--replace'
153
+ replace = true
154
+ when '-o', '--output'
155
+ name = args.shift
156
+ raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if name.nil?
157
+ dest = File.dirname(name)
158
+ name = File.basename(name)
159
+ else
160
+ argv << arg
161
+ end
162
+ end
163
+
164
+ if argv.size > 1
165
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_hi_argcount) % [ args.join(" ") ] << "\n"
166
+ ioe[:output] << self.help
167
+ return 1
168
+ end
169
+ source = argv.shift || "."
170
+
171
+ Ruwiki::Utils::Manager.package(source, dest, name, replace)
172
+ 0
173
+ end
174
+
175
+ def help
176
+ Ruwiki::Utils::Manager.message(:manager_package_help) % [ "./#{Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME}",
177
+ Ruwiki::Config::CONFIG_NAME ]
178
+ end
179
+ end
180
+
181
+ class ManagerUnpackage < Ruwiki::Utils::CommandPattern
182
+ def name
183
+ "unpackage"
184
+ end
185
+
186
+ def call(args, opts = {}, ioe = {})
187
+ ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
188
+ argv = []
189
+ dir = "."
190
+
191
+ while (arg = args.shift)
192
+ case arg
193
+ when '-o', '--output'
194
+ dir = args.shift
195
+ raise Ruwiki::Utils::CommandPatter::MissingParameterError.new(arg) if dir.nil? or not File.directory?(dir)
196
+ else
197
+ argv << arg
198
+ end
199
+ end
200
+
201
+ if argv.size > 1
202
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_hi_argcount) % [ args.join(" ") ] << "\n"
203
+ ioe[:output] << self.help
204
+ return 1
205
+ end
206
+ source = argv.shift || Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME
207
+
208
+ Ruwiki::Utils::Manager.unpackage(source, dir)
209
+
210
+ 0
211
+ end
212
+
213
+ def help
214
+ Ruwiki::Utils::Manager.message(:manager_unpackage_help) % [ "./#{Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME}" ]
215
+ end
216
+ end
217
+
218
+ if RUBY_PLATFORM =~ /win32/
219
+ class ManagerService < Ruwiki::Utils::CommandPattern
220
+ def name
221
+ "service"
222
+ end
223
+
224
+ def call(args, opts = {}, ioe = {})
225
+ ioe = Ruwiki::Utils::CommandPattern.default_ioe(ioe)
226
+
227
+ if args.size < 2
228
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_lo_argcount) % [ args.join(" ") ] << "\n"
229
+ ioe[:output] << self.help
230
+ return 0
231
+ end
232
+
233
+ command = args.shift
234
+ service = args.shift
235
+
236
+ options ||= {}
237
+ options[:service_name] = service
238
+ options[:service_home] = File.expand_path(".")
239
+
240
+ argv = []
241
+ while (arg = args.shift)
242
+ case arg
243
+ when "--rubybin"
244
+ options[:ruby_bin] = args.shift
245
+ raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:ruby_bin].nil?
246
+ when "--exec"
247
+ options[:service_bin] = args.shift
248
+ raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:service_bin].nil?
249
+ when "--home"
250
+ options[:service_home] = args.shift
251
+ raise Ruwiki::Utils::CommandPattern::MissingParameterError.new(arg) if options[:service_home].nil?
252
+ else
253
+ argv << arg
254
+ end
255
+ end
256
+
257
+ options[:service_desc] = args.join(" ") if args.size > 0
258
+
259
+ case command
260
+ when "install"
261
+ options[:service_install] = true
262
+ when "start"
263
+ options[:service_start] = true
264
+ when "stop"
265
+ options[:service_stop] = true
266
+ when "delete"
267
+ options[:service_delete] = true
268
+ else
269
+ raise ArgumentError, Ruwiki::Utils::Manager.message(:manager_unknown_command) % [ command ]
270
+ end
271
+
272
+ Ruwiki::Utils::Manager.manage_windows_service(options, ioe)
273
+
274
+ 0
275
+ end
276
+
277
+ def help
278
+ Ruwiki::Utils::Manager.message(:manager_service_help)
279
+ end
280
+ end
281
+ Ruwiki::Utils::CommandPattern << ManagerService
282
+ end
283
+
284
+ Ruwiki::Utils::CommandPattern << ManagerHelp
285
+ Ruwiki::Utils::CommandPattern << ManagerInstall
286
+ Ruwiki::Utils::CommandPattern << ManagerPackage
287
+ Ruwiki::Utils::CommandPattern << ManagerUnpackage
288
+ Ruwiki::Utils::CommandPattern.default = Ruwiki::Utils::CommandPattern["help"]
289
+
290
+ class << self
291
+ attr_accessor :shared
292
+ attr_reader :ruwiki_servlet
293
+ attr_reader :ruwiki_servlet_bat
294
+ attr_reader :ruwiki_servlet_cmd
295
+ attr_reader :ruwiki_service
296
+ attr_reader :ruwiki_cgi
297
+ attr_reader :ruwiki_pkg
298
+ def shared=(shared)
299
+ @shared = shared
300
+ @ruwiki_servlet = File.join(@shared, "bin", "ruwiki_servlet")
301
+ @ruwiki_servlet_bat = File.join(@shared, "bin", "ruwiki_servlet.bat")
302
+ @ruwiki_servlet_cmd = File.join(@shared, "bin", "ruwiki_servlet.cmd")
303
+ @ruwiki_service = File.join(@shared, "bin", "ruwiki_service.rb")
304
+ @ruwiki_cgi = File.join(@shared, "bin", "ruwiki.cgi")
305
+ @ruwiki_pkg = File.join(@shared, Ruwiki::Utils::Manager::DEFAULT_PACKAGE_NAME)
306
+ end
307
+
308
+ def with(obj)
309
+ yield obj if block_given?
310
+ end
311
+
312
+ def tar_files(list, name)
313
+ ff = StringIO.new
314
+ gz = Zlib::GzipWriter.new(ff)
315
+ to = Archive::Tar::Minitar::Output.new(gz)
316
+ list.each { |item| Archive::Tar::Minitar.pack_file(item, to) }
317
+ data = ff.string
318
+ group = {
319
+ :name => name,
320
+ :data => data,
321
+ :mode => 0644,
322
+ }
323
+ return group
324
+ rescue Exception => ex
325
+ puts ex.message, ex.backtrace.join("\n")
326
+ ensure
327
+ to.close
328
+ group[:size] = group[:data].size
329
+ end
330
+
331
+ def package(source, dest, name = nil, replace = false)
332
+ # If the package name is nil, use the default name. If replace is
333
+ # false, then append a number on the end if the file already exists.
334
+ # Increment the number until we have a unique filename.
335
+ if name.nil?
336
+ pkg = File.join(dest, DEFAULT_PACKAGE_NAME)
337
+ if File.exists?(pkg) and (not replace)
338
+ pbn = "#{File.basename(DEFAULT_PACKAGE_NAME, '.pkg')}-%02d.pkg"
339
+ ii = 1
340
+ while File.exists?(pkg)
341
+ pkg = File.join(dest, pbn % ii)
342
+ ii += 1
343
+ end
344
+ end
345
+ else
346
+ pkg = File.join(dest, name)
347
+ if File.exists?(pkg) and (not replace)
348
+ raise ManagerError, Ruwiki::Utils::Manager.message(:manager_package_exists)
349
+ end
350
+ end
351
+
352
+ files = []
353
+
354
+ if File.directory?(source)
355
+ Dir.chdir(source) do
356
+ if File.exists?(Ruwiki::Config::CONFIG_NAME)
357
+ cs = File.stat(Ruwiki::Config::CONFIG_NAME)
358
+ files << {
359
+ :name => Ruwiki::Config::CONFIG_NAME,
360
+ :data => File.read(Ruwiki::Config::CONFIG_NAME),
361
+ :mtime => cs.mtime,
362
+ :mode => 0644,
363
+ :size => cs.size
364
+ }
365
+ end
366
+
367
+ EXECUTABLES.each do |ff|
368
+ if File.exists?(ff)
369
+ cs = File.stat(ff)
370
+ files << {
371
+ :name => ff,
372
+ :data => File.read(ff),
373
+ :mtime => cs.mtime,
374
+ :mode => 0755,
375
+ :size => cs.size
376
+ }
377
+ end
378
+ end
379
+
380
+ f_data = Dir["data/**/**"].select { |dd| dd !~ /CVS\// }
381
+ f_data.unshift("data")
382
+ f_data.map! do |dd|
383
+ res = { :name => dd, :mode => 0644 }
384
+ if File.directory?(dd)
385
+ res[:mode] = 0755
386
+ res[:dir] = true
387
+ end
388
+ res
389
+ end
390
+
391
+ f_tmpl = Dir["templates/**/**"].select { |tt| tt !~ /CVS\// }
392
+ f_tmpl.unshift("templates")
393
+ f_tmpl.map! do |tt|
394
+ res = { :name => tt, :mode => 0644 }
395
+ if File.directory?(tt)
396
+ res[:mode] = 0755
397
+ res[:dir] = true
398
+ end
399
+ res
400
+ end
401
+
402
+ files << tar_files(f_data, "data.pkg")
403
+ files << tar_files(f_tmpl, "tmpl.pkg")
404
+ end
405
+ else
406
+ stat = File.stat(source)
407
+ files << {
408
+ :name => File.basename(source),
409
+ :data => File.read(source),
410
+ :mtime => stat.mtime,
411
+ :mode => 0644,
412
+ :size => stat.size
413
+ }
414
+
415
+ EXECUTABLES.each do |ff|
416
+ ff = File.join(File.dirname(source), ff)
417
+ if File.exists?(ff)
418
+ cs = File.stat(ff)
419
+ files << {
420
+ :name => ff,
421
+ :data => File.read(ff),
422
+ :mtime => cs.mtime,
423
+ :mode => 0755,
424
+ :size => cs.size
425
+ }
426
+ end
427
+ end
428
+
429
+ cc = Ruwiki::Exportable.load(files[0][:data])
430
+ tp = cc['ruwiki-config']['template-path']
431
+ tp = "./templates" if tp.nil? or tp.empty?
432
+ so = cc['ruwiki-config']['storage-options']
433
+
434
+ if so.nil? or so.empty?
435
+ dp = "./data"
436
+ else
437
+ so = Ruwiki::Exportable.load(so)
438
+ key = 'flatfiles'
439
+ dp = so[key]['data-path']
440
+ end
441
+
442
+ dp = "./data" if dp.nil? or dp.empty?
443
+ bndp = File.basename(dp)
444
+ bntp = File.basename(tp)
445
+
446
+ so[key]['data-path'] = bndp
447
+ cc['ruwiki-config']['storage-options'] = Ruwiki::Exportable.dump(so)
448
+ cc['ruwiki-config']['template-path'] = bntp
449
+ files[0][:data] = Ruwiki::Exportable.dump(cc)
450
+ files[0][:size] = files[0][:data].size
451
+
452
+ Dir.chdir(File.dirname(dp)) do
453
+ f_data = Dir["#{bndp}/**/**"].select { |dd| dd !~ /CVS\// }
454
+ f_data.map! { |dd| { :name => dd, :mode => 0644 } }
455
+ files << tar_files(f_data, "data.pkg")
456
+ end
457
+
458
+ Dir.chdir(File.dirname(tp)) do
459
+ f_tmpl = Dir["#{bntp}/**/**"].select { |tt| tt !~ /CVS\// }
460
+ f_tmpl.map! { |tt| { :name => tt, :mode => 0644 } }
461
+ files << tar_files(f_tmpl, "tmpl.pkg")
462
+ end
463
+ end
464
+
465
+ ff = File.open(pkg, "wb")
466
+ gz = Zlib::GzipWriter.new(ff)
467
+ tw = Archive::Tar::Minitar::Writer.new(gz)
468
+
469
+ files.each do |entry|
470
+ tw.add_file_simple(entry[:name], entry) { |os| os.write(entry[:data]) }
471
+ end
472
+
473
+ nil
474
+ rescue Exception => ex
475
+ puts ex, ex.backtrace.join("\n")
476
+ ensure
477
+ tw.close if tw
478
+ gz.close if gz
479
+ end
480
+
481
+ def unpackage(source, dest)
482
+ ff = File.open(source, "rb")
483
+ gz = Zlib::GzipReader.new(ff)
484
+ Archive::Tar::Minitar::Input.open(gz) do |it|
485
+ it.each do |entry|
486
+ case entry.full_name
487
+ when "data.pkg", "tmpl.pkg"
488
+ pkg = StringIO.new(entry.read)
489
+ pkgz = Zlib::GzipReader.new(pkg)
490
+ Archive::Tar::Minitar::Input.open(pkgz) do |inner|
491
+ inner.each { |item| inner.extract_entry(dest, item) }
492
+ end
493
+ else
494
+ it.extract_entry(dest, entry)
495
+ end
496
+ end
497
+ end
498
+
499
+ nil
500
+ end
501
+
502
+ def install(dest, options = {})
503
+ if options['servlet']
504
+ FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet, dest, :mode => 0755)
505
+ if RUBY_PLATFORM =~ /win32/
506
+ if File.exists?(Ruwiki::Utils::Manager.ruwiki_servlet_bat)
507
+ FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet_bat, dest, :mode => 0755)
508
+ end
509
+ if File.exists?(Ruwiki::Utils::Manager.ruwiki_servlet_cmd)
510
+ FileUtils.install(Ruwiki::Utils::Manager.ruwiki_servlet_cmd, dest, :mode => 0755)
511
+ end
512
+ end
513
+ end
514
+
515
+ if RUBY_PLATFORM =~ /win32/ and options['service']
516
+ FileUtils.install(Ruwiki::Utils::Manager.ruwiki_service, dest, :mode => 0755)
517
+ end
518
+
519
+ if options['cgi']
520
+ FileUtils.install(Ruwiki::Utils::Manager.ruwiki_cgi, dest, :mode => 0755)
521
+ end
522
+
523
+ if options['data']
524
+ unpackage(Ruwiki::Utils::Manager.ruwiki_pkg, dest)
525
+ end
526
+ end
527
+
528
+ if RUBY_PLATFORM =~ /win32/
529
+ begin
530
+ require 'win32/service'
531
+ require 'rbconfig'
532
+ HasWin32Service = true
533
+ rescue LoadError
534
+ HasWin32Service = false
535
+ end
536
+
537
+ # The work here is based on Daniel Berger's Instiki Service Tutorial.
538
+ # http://rubyforge.org/docman/view.php/85/107/instiki_service_tutorial.txt
539
+ def manage_windows_service(options, ioe)
540
+ raise Ruwiki::Utils::Manager.message(:manager_service_broken) unless HasWin32Service
541
+
542
+ service_name = options[:service_name] || 'RuwikiSvc'
543
+
544
+ if options[:service_install]
545
+ service_home = options[:service_home]
546
+
547
+ program = options[:service_bin]
548
+ if program.nil? or program.empty?
549
+ program = File.join(service_home, "ruwiki_service.rb")
550
+ elsif program !~ %r{[/\\]}
551
+ program = File.join(service_home, program)
552
+ end
553
+ program = %<"#{program}">
554
+
555
+ ruby = options[:ruby_bin] || %<"#{File.join(Config::CONFIG['bindir'], 'ruby.exe')}">
556
+
557
+ service_desc = options[:service_desc] || 'Ruwiki'
558
+
559
+ binpath = "#{ruby} #{program}".tr('/', '\\')
560
+
561
+ service = Win32::Service.new
562
+ service.create_service do |svc|
563
+ svc.service_name = service_name
564
+ svc.display_name = service_desc
565
+ svc.binary_path_name = binpath
566
+ svc.dependencies = [] # Required because of a bug in Win32::Service
567
+ end
568
+ service.close
569
+ ioe[:output] << Manager.manager(:manager_service_installed) % [ service_name ] << "\n"
570
+ end
571
+
572
+ if options[:service_start]
573
+ Win32::Service.start(service_name)
574
+ started = false
575
+ while (not started)
576
+ status = Win32::Service.status(service_name)
577
+ started = (status.current_state == "running")
578
+ break if started
579
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_one_moment) % [ status.current_state ] << "\n"
580
+ sleep 1
581
+ end
582
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_started) % [ service_name ] << "\n"
583
+ end
584
+
585
+ if options[:service_stop]
586
+ Win32::Service.stop(service_name)
587
+ stopped = false
588
+ while (not stopped)
589
+ status = Win32::Service.status(service_name)
590
+ stopped = (status.current_state == "stopped")
591
+ break if stopped
592
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_one_moment) % [ status.current_state ] << "\n"
593
+ sleep 1
594
+ end
595
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_stopped) % [ service_name ] << "\n"
596
+ end
597
+
598
+ if options[:service_delete]
599
+ Win32::Service.stop(service_name) rescue nil
600
+ Win32::Service.delete(service_name)
601
+ ioe[:output] << Ruwiki::Utils::Manager.message(:manager_service_deleted) % [ service_name ] << "\n"
602
+ end
603
+ end
604
+ end
605
+
606
+ def run(argv, input = $stdin, output = $stdout, error = $stderr)
607
+ ioe = {
608
+ :input => input,
609
+ :output => output,
610
+ :error => error
611
+ }
612
+
613
+ language = 'en'
614
+ find_lang = argv.grep(%r{^--lang})
615
+ find_lang.each do |ee|
616
+ eepos = argv.index(ee)
617
+ if ee =~ %r{^--lang=}
618
+ language = ee.sub(%r{^--lang=}, '')
619
+ else
620
+ language = argv[eepos.succ]
621
+ argv.delete_at(eepos.succ)
622
+ end
623
+ argv.delete_at(eepos)
624
+ end
625
+
626
+ require "ruwiki/lang/#{language.downcase}"
627
+ Ruwiki::Utils::Manager.message = Ruwiki::Lang.const_get(language.upcase)
628
+
629
+ command = Ruwiki::Utils::CommandPattern[(argv.shift or "").downcase]
630
+ return command[argv, {}, ioe]
631
+ rescue Ruwiki::Utils::CommandPattern::MissingParameterError => ee
632
+ ioe[:error] << Ruwiki::Utils::Manager.message(:manager_missing_parameter) % [ ee.argument ] << "\n"
633
+ return 1
634
+ rescue ArgumentError, ManagerError => ee
635
+ ioe[:error] << ee.message << "\n"
636
+ return 1
637
+ end
638
+ end
639
+ end