nitro 0.24.0 → 0.25.0

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 (67) hide show
  1. data/CHANGELOG +279 -0
  2. data/ProjectInfo +7 -7
  3. data/doc/AUTHORS +4 -2
  4. data/doc/RELEASES +96 -1
  5. data/lib/nitro.rb +5 -2
  6. data/lib/nitro/adapter/cgi.rb +1 -1
  7. data/lib/nitro/adapter/webrick.rb +7 -5
  8. data/lib/nitro/caching/output.rb +3 -2
  9. data/lib/nitro/cgi/utils.rb +8 -4
  10. data/lib/nitro/compiler.rb +9 -5
  11. data/lib/nitro/compiler/include.rb +42 -0
  12. data/lib/nitro/compiler/markup.rb +1 -1
  13. data/lib/nitro/compiler/morphing.rb +120 -50
  14. data/lib/nitro/compiler/squeeze.rb +2 -2
  15. data/lib/nitro/context.rb +9 -0
  16. data/lib/nitro/controller.rb +8 -4
  17. data/lib/nitro/dispatcher.rb +5 -5
  18. data/lib/nitro/dispatcher/nice.rb +16 -5
  19. data/lib/nitro/element.rb +30 -8
  20. data/lib/nitro/helper.rb +56 -0
  21. data/lib/nitro/{mixin → helper}/benchmark.rb +1 -1
  22. data/lib/nitro/{mixin → helper}/buffer.rb +1 -2
  23. data/lib/nitro/{mixin → helper}/debug.rb +1 -1
  24. data/lib/nitro/{mixin/helper.rb → helper/default.rb} +4 -4
  25. data/lib/nitro/{mixin → helper}/form.rb +3 -3
  26. data/lib/nitro/{mixin → helper}/javascript.rb +17 -1
  27. data/lib/nitro/{mixin → helper}/pager.rb +1 -1
  28. data/lib/nitro/{mixin → helper}/rss.rb +3 -3
  29. data/lib/nitro/{mixin → helper}/table.rb +1 -1
  30. data/lib/nitro/{mixin → helper}/xhtml.rb +2 -2
  31. data/lib/nitro/{mixin → helper}/xml.rb +1 -1
  32. data/lib/nitro/render.rb +16 -8
  33. data/lib/nitro/scaffold.rb +6 -6
  34. data/lib/nitro/server/runner.rb +12 -0
  35. data/lib/nitro/session/drbserver.rb +16 -1
  36. data/proto/public/js/builder.js +97 -0
  37. data/proto/public/js/controls.js +18 -5
  38. data/proto/public/js/dragdrop.js +8 -5
  39. data/proto/public/js/effects.js +185 -4
  40. data/proto/public/js/prototype.js +432 -178
  41. data/proto/public/js/scriptaculous.js +6 -2
  42. data/proto/public/js/slider.js +226 -0
  43. data/proto/public/js/unittest.js +363 -0
  44. data/proto/public/media/nitro.png +0 -0
  45. data/{script → proto/script}/scgi_ctl +0 -0
  46. data/{script → proto/script}/scgi_service +16 -8
  47. data/proto/src/skin.rb +24 -0
  48. data/{lib → src}/part/admin.rb +0 -0
  49. data/src/part/admin/controller.rb +47 -0
  50. data/{lib → src}/part/admin/skin.rb +0 -0
  51. data/src/part/admin/template/denied.xhtml +1 -0
  52. data/{lib → src}/part/admin/template/index.xhtml +0 -0
  53. data/test/nitro/{mixin → helper}/tc_pager.rb +2 -2
  54. data/test/nitro/{mixin → helper}/tc_rss.rb +3 -3
  55. data/test/nitro/{mixin → helper}/tc_table.rb +3 -3
  56. data/test/nitro/{mixin → helper}/tc_xhtml.rb +3 -3
  57. data/test/nitro/tc_caching.rb +4 -1
  58. data/test/nitro/tc_controller.rb +2 -2
  59. data/test/nitro/tc_element.rb +30 -0
  60. data/test/nitro/tc_helper.rb +36 -0
  61. data/test/nitro/tc_render.rb +1 -1
  62. metadata +70 -38
  63. data/lib/nitro/mixin/markup.rb +0 -122
  64. data/lib/part/admin/controller.rb +0 -28
  65. data/proto/README +0 -11
  66. data/proto/doc/README +0 -1
  67. data/proto/scgi.rb +0 -333
@@ -1,122 +0,0 @@
1
- require 'singleton'
2
- require 'redcloth'
3
- require 'cgi'
4
-
5
- require 'glue/sanitize'
6
-
7
- module Nitro
8
-
9
- # Generalised Markup transformations.
10
- #
11
- # The expand methods evaluate (expand) the markup
12
- # code to produce the final content. The compact
13
- # methods reverse this process to create the original
14
- # markup code. Not all markup transformations are
15
- # reversible.
16
- #
17
- # When this library is included, the default PropertyUtils
18
- # implementation is overriden to add markup support.
19
- #
20
- # === Examples
21
- #
22
- # Define your custom markup methods like this:
23
- #
24
- # module Markup
25
- # def markup_simple
26
- # ...
27
- # end
28
- # def markup_special
29
- # ...
30
- # end
31
- #
32
- # # maps the {{..}} macro
33
- # alias_method :sanitize, :markup_simple
34
- # # maps the {|..|} macro
35
- # alias_method :markup, :markup_special
36
- # end
37
- #
38
- # here comes the #{obj.body} # => prints the expanded version.
39
- #
40
- # obj.body = markup(@params['body'])
41
-
42
- module Markup
43
- private
44
-
45
- # The default markup method. You should override this method
46
- # in your application to call your custom markup
47
- # methods.
48
-
49
- def expand(str)
50
- if str
51
- xstr = str.dup
52
- # xstr.gsub!(/</, '&lt;')
53
- xstr.gsub!(/>/, '&gt;')
54
- return String.sanitize(xstr)
55
- end
56
- return nil
57
- end
58
- alias_method :sanitize, :expand
59
-
60
- # ...
61
-
62
- def expand_redcloth(str)
63
- if str
64
- return RedCloth.new(expand(str)).to_html
65
- end
66
- return nil
67
- end
68
- alias_method :markup, :expand_redcloth
69
-
70
- # Compact (reverse) the content to the origial markup
71
- # code. Not all markup transformations are reversible.
72
- # You should override this method in your application
73
- # to call your custom markup methods.
74
- #
75
- # NOT IMPLEMENTED.
76
-
77
- def compact(str, meth = nil)
78
- end
79
-
80
- # Remove markup code from the input string.
81
- #
82
- # NOT IMPLEMENTED.
83
-
84
- def clear(str)
85
- end
86
-
87
- def escape(str)
88
- return nil unless str
89
- CGI.escape(str.gsub(/ /, '_'))
90
- end
91
-
92
- def unescape(str)
93
- CGI.unescape(str.gsub(/_/, ' '))
94
- end
95
-
96
- class << self
97
- # Helper method for manipulating the sanitize transformation.
98
-
99
- def setup_sanitize_transform(&block)
100
- self.send :define_method, :sanitize, block
101
- end
102
- alias_method :setup_sanitize_transformation, :setup_sanitize_transform
103
-
104
- # Helper method for manipulating the markup transformation.
105
-
106
- def setup_markup_transform(&block)
107
- self.send :define_method, :markup, block
108
- end
109
- alias_method :setup_markup_transformation, :setup_markup_transform
110
- end
111
- end
112
-
113
- # An abstract Markup class.
114
-
115
- class MarkupKit
116
- extend Markup
117
- include Markup
118
- end
119
-
120
- end
121
-
122
- # * George Moschovitis <gm@navel.gr>
@@ -1,28 +0,0 @@
1
- require 'nitro/controller'
2
- require 'nitro/mixin/form'
3
-
4
- class AdminController < Nitro::Controller
5
- include Nitro::FormMixin
6
-
7
- def self.template_root
8
- File.join(File.dirname(__FILE__), 'template')
9
- end
10
-
11
- def index
12
- @classes = self.class.managed_classes
13
- end
14
-
15
- class << self
16
- # The managed classes of this application.
17
-
18
- attr_accessor :managed_classes
19
-
20
- # Called when this controller is mounted.
21
-
22
- def mounted(path)
23
- @managed_classes = Og.manager.manageable_classes
24
- @managed_classes.each { |c| scaffold(c) }
25
- end
26
- end
27
-
28
- end
data/proto/README DELETED
@@ -1,11 +0,0 @@
1
- = Proto
2
-
3
- A prototype NITRO application.
4
-
5
- === Running
6
-
7
- Start the application with:
8
-
9
- $ ruby run.rb
10
-
11
-
data/proto/doc/README DELETED
@@ -1 +0,0 @@
1
- Your documentation comes here.
data/proto/scgi.rb DELETED
@@ -1,333 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'stringio'
4
- require 'yaml'
5
- require 'digest/sha1'
6
- require 'logger'
7
- require 'fileutils'
8
- require 'socket'
9
- require 'cgi'
10
- require 'rubygems'
11
- require 'cmdparse'
12
- require 'monitor'
13
-
14
- def log(msg)
15
- $stderr.print msg,"\n"
16
- end
17
-
18
- def error(msg, exc=nil)
19
- if exc
20
- $stderr.print "ERROR: #{msg}: #{exc}\n"
21
- $stderr.puts exc.backtrace
22
- else
23
- $stderr.print "ERROR: #{msg}\n"
24
- end
25
- end
26
-
27
-
28
- # Modifies CGI so that we can use it.
29
- class SCGIFixed < ::CGI
30
- public :env_table
31
-
32
- def initialize(params, data, out, *args)
33
- @env_table = params
34
- @args = *args
35
- @input = StringIO.new(data)
36
- @out = out
37
- super(*args)
38
- end
39
- def args
40
- @args
41
- end
42
- def env_table
43
- @env_table
44
- end
45
- def stdinput
46
- @input
47
- end
48
- def stdoutput
49
- @out
50
- end
51
- end
52
-
53
-
54
- class SCGIProcessor < Monitor
55
-
56
- def initialize(settings)
57
- @env = settings[:env] || "development"
58
- @debug = settings[:debug] || false
59
- @host = settings[:host] || "127.0.0.1"
60
- @port = settings[:port] || "9999"
61
- @children = settings[:children] || 1
62
- @pid_file = settings[:pid_file] || "children.yaml"
63
- @status_dir = settings[:status_dir] || "/tmp"
64
- @log_file = settings[:logfile] || "log/scgi.log"
65
- @maxconns = settings[:maxconns]
66
- @busy_msg = settings[:busy_msg] || "BUSY"
67
- @settings = settings
68
- @started = Time.now
69
- @conns = 0
70
- @total_conns = 0
71
- @errors = 0
72
-
73
- if @maxconns
74
- @maxconns = @maxconns.to_i
75
- else
76
- @maxconns = 2**30-1
77
- end
78
-
79
- if settings[:conns_second]
80
- @throttle_sleep = 1.0/settings[:conns_second].to_i
81
- end
82
-
83
- super()
84
- end
85
-
86
- def run
87
- ENV['NITRO_ENV'] = @env
88
-
89
- require 'nitro'
90
- server = TCPServer.new(@host, @port)
91
-
92
- if @debug
93
- log("Listening for connections on #@host:#@port")
94
- listen(server)
95
- else
96
- childpids = []
97
- @children.to_i.times do
98
- # fork each child listening to the same port. very simple yet effective way to spread the load
99
- # to multiple processes without using threads and still using high performance libevent
100
- begin
101
- pid = fork do
102
- $stderr = open(@log_file,"w")
103
- $stderr.sync = false
104
- listen(server)
105
- end
106
- childpids << pid
107
- Process.detach(pid)
108
- rescue Object
109
- error("Could not fork child processes. Your system might not support fork. Use -D instead.", $!)
110
- end
111
- end
112
-
113
- # tell the user what the sha1 is so they can check for modification later
114
- log("#@pid_file will have SHA1 #{Digest::SHA1.hexdigest(YAML.dump(childpids))}")
115
- log("Record this somewhere so you know if it was modified later by someone else.")
116
- # all children forked and the pids are now ready to write to the pid file
117
- open(@pid_file,"w") { |f| f.write(YAML.dump(childpids)) }
118
- end
119
- end
120
-
121
-
122
- def listen(socket)
123
- thread = Thread.new do
124
- while true
125
- handle_client(socket.accept)
126
- sleep @throttle_sleep if @throttle_sleep
127
-
128
- @total_conns += 1
129
- end
130
- end
131
-
132
- begin
133
- thread.join
134
- rescue Interrupt
135
- log("Shutting down from SIGINT.")
136
- rescue Object
137
- error("while listening for connections on #@host:#@port", $!)
138
- end
139
- end
140
-
141
-
142
- def handle_client(socket)
143
- Thread.new do
144
- begin
145
- synchronize { @conns += 1}
146
-
147
- len = ""
148
- # we only read 10 bytes of the length. any request longer than this is invalid
149
- while len.length <= 10
150
- c = socket.read(1)
151
- if c == ':'
152
- # found the terminal, len now has a length in it so read the payload
153
- break
154
- else
155
- len << c
156
- end
157
- end
158
-
159
- # we should now either have a payload length to get
160
- payload = socket.read(len.to_i)
161
- if (c = socket.read(1)) != ','
162
- error("Malformed request, does not end with ','")
163
- else
164
- read_header(socket, payload, @conns)
165
- end
166
- rescue IOError
167
- error("received IOError #$! when handling client. Your web server doesn't like me.")
168
- rescue Object
169
- @errors += 1
170
- error("after accepting client #@host:#@port -- #{$!.class}", $!)
171
- ensure
172
- synchronize { @conns -= 1}
173
- socket.close if not socket.closed?
174
- end
175
- end
176
-
177
- end
178
-
179
-
180
- def read_header(socket, payload, conns)
181
- return if socket.closed?
182
- request = split_body(payload)
183
- if request and request["CONTENT_LENGTH"]
184
- length = request["CONTENT_LENGTH"].to_i
185
- if length > 0
186
- body = socket.read(length)
187
- else
188
- body = ""
189
- end
190
-
191
- if @conns > @maxconns
192
- socket.write("Content-type: text/plain\r\n\r\n")
193
- socket.write(@busy_msg)
194
- else
195
- process_request(request, body, socket)
196
- end
197
- end
198
- end
199
-
200
-
201
- def process_request(request, body, socket)
202
- return if socket.closed?
203
- cgi = SCGIFixed.new(request, body, socket)
204
- begin
205
- synchronize do
206
- # unfortuneatly, the dependencies.rb file is not thread safe and will throw exceptions
207
- # claiming that Dispatcher is not defined, or that other classes are missing. We have
208
- # to sync the dispatch call to get around this.
209
- Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, cgi.stdoutput)
210
- end
211
- rescue IOError
212
- error("received IOError #$! when handling client. Your web server doesn't like me.")
213
- rescue Object => nitro_error
214
- error("calling Dispatcher.dispatch", nitro_error)
215
- end
216
- end
217
-
218
-
219
- def split_body(data)
220
- result = {}
221
- el = data.split("\0")
222
- i = 0
223
- len = el.length
224
- while i < len
225
- result[el[i]] = el[i+1]
226
- i += 1
227
- end
228
-
229
- return result
230
- end
231
-
232
- def status
233
- pid = Process.pid
234
- open("#@status_dir/scgi_nitro_status.#{pid}","w") do |f|
235
- status = {
236
- 'time' => Time.now, 'pid' => pid, 'settings' => @settings,
237
- 'env' => @env, 'status_dir' => @status_dir, 'started' => @started,
238
- 'max_conns' => @maxconns, 'total_conns' => @total_conns,
239
- 'conns' => @conns, 'errors' => @errors, 'systimes' => Process.times
240
- }
241
- f.write(YAML.dump(status))
242
- end
243
- end
244
- end
245
-
246
-
247
- def signal_children(pidfile, signal)
248
- if not File.exists? pidfile
249
- log("No #{pidfile} as specified. Probably nothing running or wrong path.")
250
- exit 1
251
- end
252
-
253
- childpids = YAML.load_file(pidfile)
254
- childpids.each do |pid|
255
- begin
256
- log("Signaling pid #{pid}")
257
- Process.kill(signal, pid)
258
- rescue Object
259
- log("Couldn't send #{signal} signal to #{pid} pid.")
260
- end
261
- end
262
- end
263
-
264
-
265
- def make_command(parent, name, desc, options)
266
- cmd = CmdParse::Command.new(name, false )
267
- cmd.short_desc = desc
268
- settings = {}
269
- cmd.options = CmdParse::OptionParserWrapper.new do |opt|
270
- options.each do |short, long, info, symbol|
271
- opt.on(short, long, info) {|val| settings[symbol] = val}
272
- end
273
- end
274
- cmd.set_execution_block do |args|
275
- yield(settings, args)
276
- end
277
- parent.add_command(cmd)
278
- end
279
-
280
-
281
- cmd = CmdParse::CommandParser.new( true )
282
- cmd.program_name = 'scgi'
283
- cmd.program_version = [0, 2, 1]
284
- cmd.options = CmdParse::OptionParserWrapper.new do |opt|
285
- opt.separator "Global options:"
286
- opt.on("--verbose", "Be verbose when outputting info") {|t| $verbose = true }
287
- end
288
-
289
- cmd.add_command( CmdParse::HelpCommand.new )
290
- cmd.add_command( CmdParse::VersionCommand.new )
291
-
292
- make_command(cmd, 'start', "Start Nitro Application",
293
- [['-e','--env STRING','Nitro environment', :env],
294
- ['-D','--[no-]debug', 'Do not fork children, stay in foreground.', :debug],
295
- ['-h','--host STRING', 'IP address to bind as server', :host],
296
- ['-p','--port NUMBER', 'Port to bind to', :port],
297
- ['-c','--children NUMBER', 'Number of children to start (not win32)', :children],
298
- ['-f','--pid-file PATH', 'Where to read the list of running children', :pid_file],
299
- ['-l','--log-file PATH', 'Use a different log from from log/scgi.log', :logfile],
300
- ['-t','--throttle NUMBER', 'Max conn/second to allow.', :conns_second],
301
- ['-m','--max-conns NUMBER', 'Max simultaneous connections before the busy message', :maxconns],
302
- ['-b','--busy-msg', 'Busy message given to clients over the max connections ("busy")', :busy_msg],
303
- ['-s','--status-dir PATH', 'Where to put the status files', :status_dir]]) do |settings, args|
304
- scgi = SCGIProcessor.new(settings)
305
- begin
306
- trap("HUP") { scgi.status }
307
- rescue Object
308
- error("Could not setup a SIGHUP handler. You won't be able to get status.")
309
- end
310
-
311
- scgi.run
312
- end
313
-
314
-
315
- make_command(cmd, 'status', "Get status from all running children",
316
- [['-s','--status-dir PATH', 'Where to put the status files', :status_dir],
317
- ['-f','--pid-file PATH', 'Where to read the list of running children', :pid_file]]) do |settings, args|
318
- signal_children(settings[:pid_file] || 'children.yaml', "HUP")
319
- log("Status files for each child should show up in the configured status directory (/tmp by default).")
320
- end
321
-
322
- make_command(cmd, 'stop', "Stop all running children",
323
- [['-s','--sig SIGNAL', 'Where to put the status files', :signal],
324
- ['-n','--[no-]delete', 'Keep the children.yaml file rather than delete', :nodelete],
325
- ['-f','--pid-file PATH', 'Where to read the list of running children', :pid_file]]) do |settings, args|
326
- pid_file = settings[:pid_file] || "children.yaml"
327
- signal_children(pid_file, settings[:signal] || "INT")
328
- if not settings[:nodelete] and File.exist?(pid_file)
329
- File.unlink(pid_file)
330
- end
331
- end
332
-
333
- cmd.parse