nitro 0.24.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
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