nitro 0.29.0 → 0.30.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 (93) hide show
  1. data/CHANGELOG +410 -0
  2. data/ProjectInfo +36 -44
  3. data/README +5 -5
  4. data/doc/AUTHORS +6 -0
  5. data/doc/RELEASES +159 -2
  6. data/lib/glue/sweeper.rb +2 -2
  7. data/lib/glue/webfile.rb +14 -1
  8. data/lib/nitro.rb +6 -9
  9. data/lib/nitro/adapter/mongrel.rb +36 -43
  10. data/lib/nitro/adapter/scgi.rb +1 -1
  11. data/lib/nitro/adapter/webrick.rb +96 -24
  12. data/lib/nitro/caching/actions.rb +2 -1
  13. data/lib/nitro/caching/fragments.rb +1 -8
  14. data/lib/nitro/caching/output.rb +14 -4
  15. data/lib/nitro/cgi.rb +19 -21
  16. data/lib/nitro/cgi/cookie.rb +5 -1
  17. data/lib/nitro/cgi/request.rb +20 -4
  18. data/lib/nitro/compiler.rb +74 -28
  19. data/lib/nitro/compiler/cleanup.rb +1 -1
  20. data/lib/nitro/compiler/elements.rb +1 -2
  21. data/lib/nitro/compiler/localization.rb +1 -1
  22. data/lib/nitro/compiler/markup.rb +1 -1
  23. data/lib/nitro/compiler/script.rb +52 -44
  24. data/lib/nitro/compiler/squeeze.rb +4 -3
  25. data/lib/nitro/compiler/xslt.rb +7 -6
  26. data/lib/nitro/context.rb +39 -20
  27. data/lib/nitro/controller.rb +24 -5
  28. data/lib/nitro/dispatcher.rb +13 -5
  29. data/lib/nitro/global.rb +63 -0
  30. data/lib/nitro/helper/feed.rb +432 -0
  31. data/lib/nitro/helper/form.rb +11 -3
  32. data/lib/nitro/helper/form/builder.rb +140 -0
  33. data/lib/nitro/helper/form/controls.rb +2 -1
  34. data/lib/nitro/helper/javascript.rb +6 -0
  35. data/lib/nitro/helper/javascript/morphing.rb +13 -6
  36. data/lib/nitro/helper/xhtml.rb +42 -6
  37. data/lib/nitro/helper/xml.rb +3 -0
  38. data/lib/nitro/part.rb +2 -2
  39. data/lib/nitro/render.rb +7 -2
  40. data/lib/nitro/router.rb +57 -16
  41. data/lib/nitro/scaffolding.rb +29 -20
  42. data/lib/nitro/server.rb +4 -10
  43. data/lib/nitro/server/drb.rb +1 -1
  44. data/lib/nitro/server/runner.rb +10 -0
  45. data/lib/nitro/session.rb +31 -12
  46. data/lib/nitro/session/drb.rb +13 -1
  47. data/lib/nitro/session/file.rb +1 -1
  48. data/lib/nitro/session/memcached.rb +1 -1
  49. data/lib/nitro/session/memory.rb +1 -1
  50. data/lib/nitro/session/og.rb +1 -1
  51. data/lib/nitro/test/testcase.rb +3 -0
  52. data/proto/public/error.xhtml +5 -5
  53. data/proto/public/js/controls.js +2 -2
  54. data/proto/public/js/dragdrop.js +320 -79
  55. data/proto/public/js/effects.js +200 -152
  56. data/proto/public/js/prototype.js +284 -63
  57. data/proto/public/js/scriptaculous.js +7 -5
  58. data/proto/public/js/unittest.js +11 -0
  59. data/proto/public/scaffold/advanced_search.xhtml +30 -0
  60. data/proto/public/scaffold/list.xhtml +8 -1
  61. data/proto/public/scaffold/search.xhtml +2 -1
  62. data/proto/script/scgi_service +1 -1
  63. data/src/part/admin/controller.rb +1 -1
  64. data/src/part/admin/skin.rb +1 -1
  65. data/test/nitro/CONFIG.rb +3 -0
  66. data/test/nitro/adapter/tc_webrick.rb +1 -1
  67. data/test/nitro/cgi/tc_cookie.rb +1 -1
  68. data/test/nitro/cgi/tc_request.rb +5 -5
  69. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  70. data/test/nitro/compiler/tc_compiler.rb +2 -0
  71. data/test/nitro/helper/tc_feed.rb +138 -0
  72. data/test/nitro/helper/tc_pager.rb +1 -1
  73. data/test/nitro/helper/tc_rss.rb +1 -1
  74. data/test/nitro/helper/tc_table.rb +1 -1
  75. data/test/nitro/helper/tc_xhtml.rb +1 -1
  76. data/test/nitro/tc_caching.rb +1 -1
  77. data/test/nitro/tc_cgi.rb +1 -1
  78. data/test/nitro/tc_context.rb +1 -1
  79. data/test/nitro/tc_controller.rb +31 -3
  80. data/test/nitro/tc_controller_aspect.rb +1 -1
  81. data/test/nitro/tc_dispatcher.rb +1 -1
  82. data/test/nitro/tc_element.rb +1 -1
  83. data/test/nitro/tc_flash.rb +1 -1
  84. data/test/nitro/tc_helper.rb +1 -1
  85. data/test/nitro/tc_render.rb +6 -6
  86. data/test/nitro/tc_router.rb +8 -4
  87. data/test/nitro/tc_server.rb +1 -3
  88. data/test/nitro/tc_session.rb +1 -3
  89. metadata +107 -104
  90. data/Rakefile +0 -232
  91. data/lib/nitro/adapter/acgi.rb +0 -237
  92. data/proto/public/Makefile.acgi +0 -40
  93. data/proto/public/acgi.c +0 -138
data/Rakefile DELETED
@@ -1,232 +0,0 @@
1
- require 'rake/rdoctask'
2
- require 'rake/testtask'
3
- require 'rake/gempackagetask'
4
-
5
- # Initialize some variables.
6
-
7
- readme = File.read('README')
8
- Release = (readme[/^= (.+) README$/, 1] || 'unknown').downcase.tr(" ", "-")
9
- Name = Release[/\D+/].sub(/\-+$/, '') || 'unknown'
10
- Version = Release[/[\d.]+/] || 'unknown'
11
-
12
- AuthorName, AuthorMail = 'George Moschovitis', 'gm@navel.gr'
13
- RubyVersion = '1.8.3'
14
-
15
- # Description = (readme[/README\s+(.+?)\n\n/m, 1] || "unknown").gsub(/\s+/, " ")
16
- # Summary = Description[/^.+?>/] || "unknown"
17
-
18
- # DocFiles = %w(README NEWS TODO COPYING GPL)
19
- # RDocFiles = DocFiles - %w(GPL)
20
- RDocOpts = ["--inline-source", "--line-numbers","--title", Name ]
21
- # AdditionalFiles = DocFiles + %w(setup.rb)
22
- VersionFile = MainFile = File.join("lib", Name + '.rb')
23
-
24
- RubyForgeProject = Name
25
- RubyForgeUser = 'gmosx'
26
- Homepage = "http://www.nitrohq.org/"
27
-
28
- task :default => :package
29
-
30
- $NITRO_NO_ENVIRONMENT = true
31
-
32
- # Run the tests.
33
-
34
- Rake::TestTask.new do |t|
35
- cwd = File.expand_path(File.join(File.dirname(__FILE__), '..'))
36
- t.libs << 'test'
37
- %w[glue nitro og].each do |dir|
38
- t.libs << File.join(cwd, dir, 'lib')
39
- end
40
- t.test_files = FileList['test/**/tc*.rb']
41
- t.verbose = true
42
- end
43
-
44
- # Generate RDoc documentation.
45
-
46
- Rake::RDocTask.new do |rd|
47
- rd.main = 'README'
48
- rd.rdoc_dir = 'rdoc'
49
- rd.rdoc_files.include('README', 'INSTALL', 'doc/RELEASES', 'lib/**/*.rb')
50
- rd.options << '--all --inline-source'
51
- end
52
-
53
- # Build gem.
54
-
55
- spec = Gem::Specification.new do |s|
56
- s.name = 'nitro'
57
- if File.read('lib/nitro.rb') =~ /Version\s+=\s+'(\d+\.\d+\.\d+)'/
58
- s.version = $1
59
- else
60
- raise 'No version found'
61
- end
62
- s.summary = 'Nitro Web Engine'
63
- s.description =
64
- 'Nitro provides everything you need to develop real-world, scalable ' +
65
- 'web applications.'
66
-
67
- s.add_dependency 'glue', "= #{s.version}"
68
- s.add_dependency 'og', "= #{s.version}"
69
- s.add_dependency 'gen', "= #{s.version}"
70
- s.add_dependency 'ruby-breakpoint', '= 0.5'
71
- s.add_dependency 'RedCloth', '= 3.0.3'
72
-
73
- s.required_ruby_version = '= 1.8.3'
74
-
75
- s.files = FileList[
76
- '[A-Z]*', 'setup.rb', '{bin,benchmark,examples,doc,proto,lib,test,vendor}/**/*'
77
- ].exclude("_darcs").exclude("_darcs/**/*").exclude('*.og').exclude('**/*.log').to_a
78
-
79
- s.require_path = 'lib'
80
- s.autorequire = 'nitro'
81
-
82
- s.has_rdoc = true
83
- s.extra_rdoc_files = FileList['[A-Z]*'].to_a
84
- s.rdoc_options << '--main' << 'README' << '--title' << 'Nitro Documentation'
85
- s.rdoc_options << '--all' << '--inline-source'
86
-
87
- s.test_files = []
88
-
89
- s.bindir = 'bin'
90
- s.executables = ['nitro', 'nitrogen']
91
- s.default_executable = 'nitro'
92
-
93
- s.author = 'George Moschovitis'
94
- s.email = 'gm@navel.gr'
95
- s.homepage = 'http://www.nitrohq.com'
96
- s.rubyforge_project = 'nitro'
97
- end
98
-
99
- Rake::GemPackageTask.new(spec) do |pkg|
100
- pkg.package_dir = 'dist'
101
- pkg.need_zip = true
102
- pkg.need_tar = true
103
- end
104
-
105
- # Manual install (not recommended).
106
-
107
- task :install do
108
- ruby 'install.rb'
109
- end
110
-
111
- # Release files to Rubyforge.
112
- # The code for this task provided by Florian Gross.
113
-
114
- desc "Publish the release files to RubyForge."
115
- task :publish => [:package] do
116
- files = ['gem', 'tgz', 'zip'].map { |ext| "dist/#{Release}.#{ext}" }
117
-
118
- if RubyForgeProject then
119
- require 'net/http'
120
- require 'open-uri'
121
-
122
- changes = ''
123
- if File.exist?('doc/RELEASES') then
124
- changes_re = /^== \s+ Version \s+ #{Regexp.quote(Version)} \s*
125
- (.+?) (?:==|\Z)/mx
126
- changes = File.read('doc/RELEASES')[changes_re, 1] || ''
127
- end
128
-
129
- project_uri = "http://rubyforge.org/projects/#{RubyForgeProject}/"
130
- project_data = open(project_uri) { |data| data.read }
131
- group_id = project_data[/[?&]group_id=(\d+)/, 1]
132
- raise "Couldn't get group id" unless group_id
133
-
134
- print "#{RubyForgeUser}@rubyforge.org's password: "
135
- password = STDIN.gets.chomp
136
-
137
- login_response = Net::HTTP.start('rubyforge.org', 80) do |http|
138
- data = [
139
- "login=1",
140
- "form_loginname=#{RubyForgeUser}",
141
- "form_pw=#{password}"
142
- ].join("&")
143
- http.post('/account/login.php', data)
144
- end
145
-
146
- cookie = login_response['set-cookie']
147
- raise 'Login failed' unless cookie
148
- headers = { 'Cookie' => cookie }
149
-
150
- release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
151
- release_data = open(release_uri, headers) { |data| data.read }
152
- package_id = release_data[/[?&]package_id=(\d+)/, 1]
153
- raise "Couldn't get package id" unless package_id
154
-
155
- first_file = true
156
- release_id = ""
157
-
158
- files.each do |filename|
159
- basename = File.basename(filename)
160
- file_ext = File.extname(filename)
161
- file_data = File.open(filename, "rb") { |file| file.read }
162
-
163
- puts "Releasing #{basename}..."
164
-
165
- release_response = Net::HTTP.start('rubyforge.org', 80) do |http|
166
- release_date = Time.now.strftime('%Y-%m-%d %H:%M')
167
- type_map = {
168
- '.zip' => '3000',
169
- '.tgz' => '3110',
170
- '.gz' => '3110',
171
- '.gem' => '1400',
172
- '.md5sum' => '8100'
173
- }; type_map.default = '9999'
174
- type = type_map[file_ext]
175
- boundary = 'rubyqMY6QN9bp6e4kS21H4y0zxcvoor'
176
-
177
- query_hash = if first_file then
178
- {
179
- 'group_id' => group_id,
180
- 'package_id' => package_id,
181
- 'release_name' => Release,
182
- 'release_date' => release_date,
183
- 'type_id' => type,
184
- 'processor_id' => '8000', # Any
185
- 'release_notes' => '',
186
- 'release_changes' => changes,
187
- 'preformatted' => '1',
188
- 'submit' => '1'
189
- }
190
- else
191
- {
192
- 'group_id' => group_id,
193
- 'release_id' => release_id,
194
- 'package_id' => package_id,
195
- 'step2' => '1',
196
- 'type_id' => type,
197
- 'processor_id' => '8000', # Any
198
- 'submit' => 'Add This File'
199
- }
200
- end
201
-
202
- query = '?' + query_hash.map do |(name, value)|
203
- [name, URI.encode(value)].join('=')
204
- end.join('&')
205
-
206
- data = [
207
- "--" + boundary,
208
- "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
209
- "Content-Type: application/octet-stream",
210
- "Content-Transfer-Encoding: binary",
211
- "", file_data, ""
212
- ].join("\x0D\x0A")
213
-
214
- release_headers = headers.merge(
215
- 'Content-Type' => "multipart/form-data; boundary=#{boundary}"
216
- )
217
-
218
- target = first_file ? '/frs/admin/qrs.php' : '/frs/admin/editrelease.php'
219
- http.post(target + query, data, release_headers)
220
- end
221
-
222
- if first_file then
223
- release_id = release_response.body[/release_id=(\d+)/, 1]
224
- raise("Couldn't get release id") unless release_id
225
- end
226
-
227
- first_file = false
228
- end
229
- end
230
- end
231
-
232
- # * George Moschovitis <gm@navel.gr>
@@ -1,237 +0,0 @@
1
- require 'cgi'
2
- require 'posixlock'
3
-
4
- STDOUT.sync = STDERR.sync = true
5
- $VERBOSE = nil
6
-
7
- require 'nitro/context'
8
- require 'nitro/dispatcher'
9
- require 'nitro/cgi'
10
-
11
- # Speeds things up, more comaptible with OSX.
12
-
13
- Socket.do_not_reverse_lookup = true
14
-
15
- # No multi-threading.
16
-
17
- Og.thread_safe = false if defined?(Og) and Og.respond_to?(:thread_safe)
18
-
19
- module Nitro
20
-
21
- # ACGI Adaptor. ACGI is a language independent,
22
- # scalable, open extension to CGI that provides high
23
- # performance without the limitations of server
24
- # specific APIs.
25
- #
26
- # This code is directly from the author. Please go to
27
- # http://codeforpeople.com/lib/ruby/acgi/ for more
28
- # information about ACGI.
29
- # or email: ara [dot] t [dot] howard [at] noaa [dot] gov
30
- #
31
- # It uses a compiled C cgi program to handle
32
- # connections compile the acgi.c by executing
33
- # "make -f Makefile.acgi" in your public/ folder.
34
- # then make your .htaccess redirect all calls to acgi.cgi
35
- # instead of fcgi.rb / cgi.rb
36
- #
37
- #--
38
- # gmosx: not tested! Use at your own risk!
39
- #++
40
-
41
- class ACGI < ::CGI
42
- THIS = File::expand_path $0
43
- COMMAND_LINE = [THIS, ARGV].join ' '
44
- LOADED = Time::now
45
- IPC_DIR = "/tmp/acgi_ipc"
46
- CLIENT_LOCK_PATH = File::join IPC_DIR, "client.lock"
47
- SERVER_LOCK_PATH = File::join IPC_DIR, "server.lock"
48
- SERVER_ENVIRONMENT_PATH = File::join IPC_DIR, "server.environment"
49
- SERVER_STDIN_PATH = File::join IPC_DIR, "server.stdin"
50
- SERVER_STDOUT_PATH = File::join IPC_DIR, "server.stdout"
51
- SERVER_STDERR_PATH = File::join IPC_DIR, "server.stderr"
52
- SERVER_PID_PATH = File::join IPC_DIR, "server.pid"
53
-
54
- RE_ENV = %r/^ ([^=]+) = (.*) $/ox
55
- RE_NUL = %r/#{ Regexp::escape "\0" }/ox
56
-
57
- SERVER = ENV['ACGI_SERVER'] || ARGV.delete('--server') || ARGV.delete('-s')
58
-
59
- if SERVER
60
- trap('HUP'){ exec ::ACGI::COMMAND_LINE }
61
- %w( INT KILL TERM ).each{|s| trap(s){ exit }}
62
- end
63
-
64
- class << self
65
- def each_cgi(*a, &b)
66
- if SERVER
67
- start_server(*a, &b)
68
- else
69
- munge_environment
70
- @cgi = new(*a)
71
- catching_errors{ b[ @cgi ] }
72
- end
73
- end
74
-
75
- def start_server(*a, &b)
76
- daemon do
77
- ENV.clear # __very__ important for speed!
78
- aquire_server_lock
79
- record_pid
80
- loop do
81
- load_environment
82
- munge_environment
83
- @cgi = redirecting_stdin{ new(*a) }
84
- redirecting_stdout_and_stderr{ catching_errors{ b[ @cgi ] }}
85
- restart_if_updated
86
- end
87
- end
88
- end
89
-
90
- def restart_if_updated
91
- # put the full path to your run.rb here if it doesn't work
92
- #th = "/path/to/app/run.rb"
93
- if File::stat(THIS).mtime > LOADED
94
- #if File::stat(th).mtime > LOADED
95
- exec COMMAND_LINE
96
- end
97
- end
98
-
99
- def aquire_server_lock
100
- lockfile = File.open(SERVER_LOCK_PATH)
101
- lockfile.reopen(SERVER_LOCK_PATH, 'w')
102
- at_exit{ lockfile.close }
103
- ret = lockfile.posixlock(File::LOCK_EX|File::LOCK_NB)
104
-
105
- raise("#{ File::basename $0 } already running..") if(!ret or !ret.zero?)
106
- end
107
-
108
- def record_pid
109
- begin
110
- f = File::open(SERVER_PID_PATH)
111
- f.reopen(SERVER_PID_PATH, 'w')
112
- f.print Process::pid
113
- f.chmod 0777 rescue nil
114
- ensure
115
- f.close
116
- end
117
- end
118
-
119
- def env_table
120
- SERVER ? (@environment ||= {}) : ENV
121
- end
122
-
123
- def env
124
- env_table
125
- end
126
-
127
- def load_environment
128
- begin
129
- f = File::open(SERVER_ENVIRONMENT_PATH)
130
- f.reopen(SERVER_ENVIRONMENT_PATH, "r")
131
- env_table.clear
132
- kvs = f.read.chop.split RE_NUL
133
- kvs.each do |kv|
134
- m = RE_ENV.match(kv)
135
- k, v = m[1], m[2]
136
- env_table[k] = v
137
- end
138
- ensure
139
- f.close
140
- end
141
- end
142
-
143
- def munge_environment # because CGI::Cookie::parse is broken!
144
- env_table['HTTP_COOKIE'] =
145
- munge_http_cookie env_table['HTTP_COOKIE']
146
- end
147
-
148
- def munge_http_cookie http_cookie
149
- return unless http_cookie
150
- kvs = http_cookie.split %r/[;,]\s+/o
151
- h = Hash::new{|h,k| h[k] = []}
152
- kvs.each do |kv|
153
- k, v = kv.split %r/=/o, 2
154
- next unless k
155
- k = CGI::unescape k
156
- vs = v.to_s.split(%r/&/).map{|v| CGI::unescape v}
157
- h[k].push(*vs)
158
- end
159
- h.sort.map{|k,vs| [k, vs.join('&')].join('=')}.join('; ')
160
- end
161
-
162
- def redirecting_stdin
163
- stdin = $stdin
164
- begin
165
- @stdin = File::open(SERVER_STDIN_PATH)
166
- @stdin.reopen(SERVER_STDIN_PATH, "r")
167
- $stdin = @stdin
168
- yield
169
- ensure
170
- @stdin.close if @stdin
171
- $stdin = stdin
172
- end
173
- end
174
-
175
- def redirecting_stdout_and_stderr
176
- stdout, stderr = $stdout, $stderr
177
- begin
178
- @stdout = File::open(SERVER_STDOUT_PATH)
179
- @stdout.reopen(SERVER_STDOUT_PATH, "w")
180
- @stderr = File::open(SERVER_STDERR_PATH)
181
- @stderr.reopen(SERVER_STDERR_PATH, "w")
182
- $stdout, $stderr = @stdout, @stderr
183
- yield
184
- ensure
185
- @stdout.close if @stdout
186
- @stderr.close if @stderr
187
- $stdout, $stderr = stdout, stderr
188
- end
189
- end
190
-
191
- def catching_errors
192
- @cgi ||= CGI::new
193
- begin
194
- yield
195
- rescue Exception => e
196
- m, c, b = e.message, e.class, e.backtrace.join("<br>\n")
197
- @cgi.out{ "<hr><b><i>#{ m } (#{ c })</b></i><hr><hr>#{ b }" }
198
- end
199
- end
200
-
201
- def daemon
202
- exit!(0) if fork
203
- Process::setsid
204
- exit!(0) if fork
205
- # Dir::chdir("/")
206
- # File::umask(0)
207
-
208
- # uncomment these if you don't want logs
209
- #STDIN.reopen("/dev/null")
210
- #STDOUT.reopen("/dev/null", "w")
211
- #STDERR.reopen("/dev/null", "w")
212
- yield if block_given?
213
- end
214
- end
215
-
216
- def env_table
217
- self::class.env_table
218
- end
219
- def env
220
- self::class.env
221
- end
222
-
223
- # use this to start the ACGI server.
224
-
225
- def self.start(server)
226
- ACGI.each_cgi do |cgi|
227
- begin
228
- Cgi.process(server, cgi, $stdin, $stdout)
229
- end
230
- end
231
- end
232
-
233
- end
234
-
235
- end
236
-
237
- # * Ara Howard <ara.t.howard@noaa.gov>