nitro 0.8.0 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +3 -4
- data/ChangeLog +418 -0
- data/LICENSE +1 -1
- data/README +157 -89
- data/RELEASES +50 -0
- data/Rakefile +5 -7
- data/benchmark/nitro/bench.rb +5 -0
- data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
- data/benchmark/nitro/static-webrick-n-200.txt +43 -0
- data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
- data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
- data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
- data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
- data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
- data/bin/proto/README +2 -2
- data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
- data/bin/proto/conf/app.conf.rb +22 -0
- data/bin/proto/conf/lhttpd.conf +236 -0
- data/bin/proto/ctl +4 -0
- data/bin/proto/lib/README +5 -0
- data/bin/proto/log/README +3 -0
- data/bin/proto/root/fcgi.rb +6 -0
- data/bin/proto/root/index.xhtml +65 -7
- data/bin/proto/root/m/nitro.png +0 -0
- data/examples/blog/README +7 -5
- data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
- data/examples/blog/conf/app.conf.rb +56 -0
- data/examples/blog/conf/lhttpd.conf +236 -0
- data/examples/blog/ctl +4 -0
- data/examples/blog/lib/blog.rb +11 -136
- data/examples/blog/lib/blog/controller.rb +99 -0
- data/examples/blog/lib/blog/model.rb +39 -0
- data/examples/blog/log/README +3 -0
- data/examples/blog/root/comments.xhtml +2 -2
- data/examples/blog/root/fcgi.rb +6 -0
- data/examples/blog/root/index.xhtml +4 -5
- data/examples/blog/root/login.xhtml +2 -2
- data/examples/blog/root/style.xsl +9 -9
- data/examples/blog/root/view_entry.xhtml +2 -2
- data/examples/flash/conf/app.conf.rb +23 -0
- data/examples/flash/ctl +4 -0
- data/examples/flash/log/README +3 -0
- data/examples/flash/root/index.xhtml +0 -9
- data/examples/flash/root/show_inline_text.xhtml +10 -5
- data/examples/no_xsl_blog/README +12 -0
- data/examples/no_xsl_blog/conf/apache.conf +0 -0
- data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
- data/examples/no_xsl_blog/ctl +4 -0
- data/examples/no_xsl_blog/lib/blog.rb +20 -0
- data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
- data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
- data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
- data/examples/no_xsl_blog/log/README +3 -0
- data/examples/no_xsl_blog/root/comments.xhtml +41 -0
- data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
- data/examples/no_xsl_blog/root/fcgi.rb +6 -0
- data/examples/no_xsl_blog/root/index.xhtml +39 -0
- data/examples/no_xsl_blog/root/login.xhtml +21 -0
- data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
- data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
- data/examples/no_xsl_blog/root/m/down.gif +0 -0
- data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
- data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
- data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
- data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
- data/examples/no_xsl_blog/root/m/obull.gif +0 -0
- data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/rss.gif +0 -0
- data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
- data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
- data/examples/no_xsl_blog/root/style.css +301 -0
- data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
- data/examples/no_xsl_blog/root/view_entry.xml +12 -0
- data/examples/og/run.rb +2 -2
- data/examples/tiny/README +2 -2
- data/examples/tiny/conf/apache.conf +5 -0
- data/examples/tiny/conf/app.conf.rb +21 -0
- data/examples/tiny/conf/lhttpd.conf +236 -0
- data/examples/tiny/ctl +4 -0
- data/examples/tiny/log/README +3 -0
- data/examples/tiny/root/fcgi.rb +6 -0
- data/examples/tiny/root/index.xhtml +7 -4
- data/examples/tiny/root/nitro.png +0 -0
- data/lib/glue.rb +13 -9
- data/lib/glue/array.rb +1 -1
- data/lib/glue/cache.rb +1 -1
- data/lib/glue/flexob.rb +12 -0
- data/lib/glue/hash.rb +1 -1
- data/lib/glue/inflector.rb +2 -2
- data/lib/glue/logger.rb +4 -8
- data/lib/glue/misc.rb +14 -0
- data/lib/glue/number.rb +1 -1
- data/lib/glue/object.rb +26 -0
- data/lib/glue/pool.rb +1 -1
- data/lib/glue/property.rb +84 -91
- data/lib/glue/string.rb +1 -1
- data/lib/glue/time.rb +1 -1
- data/lib/glue/validation.rb +1 -1
- data/lib/nitro.rb +18 -6
- data/lib/nitro/adaptors/cgi.rb +291 -0
- data/lib/nitro/adaptors/fastcgi.rb +42 -0
- data/lib/nitro/adaptors/runner.rb +123 -0
- data/lib/nitro/adaptors/webrick.rb +110 -0
- data/lib/nitro/buffering.rb +43 -0
- data/lib/nitro/builders/form.rb +1 -1
- data/lib/nitro/builders/rss.rb +1 -1
- data/{bin → lib/nitro}/cluster.rb +26 -30
- data/lib/nitro/context.rb +82 -0
- data/lib/nitro/controller.rb +50 -0
- data/lib/nitro/cookie.rb +46 -0
- data/lib/nitro/dispatcher.rb +105 -0
- data/lib/nitro/filters.rb +9 -10
- data/lib/nitro/localization.rb +42 -0
- data/lib/nitro/mail.rb +11 -14
- data/lib/nitro/render.rb +275 -0
- data/lib/nitro/request.rb +128 -0
- data/lib/nitro/response.rb +38 -0
- data/lib/nitro/scaffold.rb +11 -11
- data/lib/nitro/session.rb +84 -0
- data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
- data/lib/nitro/ui/pager.rb +23 -26
- data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
- data/lib/nitro/uri.rb +1 -1
- data/lib/nitro/version.rb +10 -8
- data/lib/og.rb +66 -65
- data/lib/og/backend.rb +1 -1
- data/lib/og/backends/mysql.rb +48 -52
- data/lib/og/backends/psql.rb +34 -37
- data/lib/og/connection.rb +15 -15
- data/lib/og/enchant.rb +16 -9
- data/lib/og/meta.rb +127 -54
- data/lib/og/mock.rb +18 -18
- data/lib/og/version.rb +6 -4
- data/lib/parts/content.rb +4 -8
- data/test/glue/tc_logger.rb +3 -0
- data/test/glue/tc_property.rb +19 -3
- data/test/nitro/adaptors/tc_cgi.rb +63 -0
- data/test/nitro/adaptors/tc_webrick.rb +15 -0
- data/test/nitro/builders/tc_xml.rb +2 -2
- data/test/nitro/tc_context.rb +13 -0
- data/test/nitro/tc_controller.rb +47 -0
- data/test/nitro/tc_dispatcher.rb +64 -0
- data/test/nitro/tc_session.rb +20 -0
- data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
- data/test/root/blog/list.xhtml +6 -0
- data/test/tc_og.rb +41 -4
- metadata +115 -59
- data/bin/proto/app.rb +0 -20
- data/bin/proto/config.rb +0 -77
- data/examples/blog/app.rb +0 -21
- data/examples/blog/config.rb +0 -95
- data/examples/blog/env.rb +0 -22
- data/examples/flash/README +0 -34
- data/examples/flash/app.rb +0 -20
- data/examples/flash/config.rb +0 -38
- data/examples/flash/lib/flash.rb +0 -40
- data/examples/flash/tmp.swf +0 -0
- data/examples/tiny/app.rb +0 -19
- data/examples/tiny/config.rb +0 -29
- data/examples/tiny/root/nitro-small.png +0 -0
- data/lib/nitro/application.rb +0 -217
- data/lib/nitro/config.rb +0 -128
- data/lib/nitro/events.rb +0 -122
- data/lib/nitro/html.rb +0 -151
- data/lib/nitro/http.rb +0 -102
- data/lib/nitro/l10n.rb +0 -30
- data/lib/nitro/server.rb +0 -59
- data/lib/nitro/server/appserver.rb +0 -67
- data/lib/nitro/server/cookie.rb +0 -87
- data/lib/nitro/server/dispatcher.rb +0 -62
- data/lib/nitro/server/filters.rb +0 -75
- data/lib/nitro/server/filters/autologin.rb +0 -51
- data/lib/nitro/server/fragment.rb +0 -70
- data/lib/nitro/server/handlers.rb +0 -127
- data/lib/nitro/server/render.rb +0 -426
- data/lib/nitro/server/request.rb +0 -658
- data/lib/nitro/server/requestpart.rb +0 -54
- data/lib/nitro/server/script.rb +0 -387
- data/lib/nitro/server/server.rb +0 -57
- data/lib/nitro/server/session.rb +0 -220
- data/lib/nitro/server/user.rb +0 -46
- data/lib/nitro/server/webrick.rb +0 -180
- data/lib/nitro/service.rb +0 -26
- data/lib/xsl/ui.xsl +0 -51
- data/lib/xsl/xforms.xsl +0 -28
- data/test/nitro/server/tc_cookie.rb +0 -34
- data/test/nitro/server/tc_filters.rb +0 -38
- data/test/nitro/server/tc_request.rb +0 -70
- data/test/nitro/server/tc_requestpart.rb +0 -28
- data/test/nitro/server/tc_session.rb +0 -34
- data/test/nitro/tc_events.rb +0 -44
- data/test/nitro/tc_html.rb +0 -79
- data/test/nitro/tc_http.rb +0 -18
data/lib/glue/string.rb
CHANGED
data/lib/glue/time.rb
CHANGED
data/lib/glue/validation.rb
CHANGED
@@ -216,7 +216,7 @@ module Validation
|
|
216
216
|
|
217
217
|
for name in params
|
218
218
|
confirm_name = "#{name}#{c[:postfix]}"
|
219
|
-
attr_accessor
|
219
|
+
eval "attr_accessor :#{confirm_name}"
|
220
220
|
|
221
221
|
code = %{
|
222
222
|
if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
|
data/lib/nitro.rb
CHANGED
@@ -5,13 +5,25 @@
|
|
5
5
|
# robust infrastructure for scalable web applications that can be
|
6
6
|
# distributed over a server cluster. However, Nitro can also power
|
7
7
|
# simple web applications for deployment on intranets or even personal
|
8
|
-
# computers.
|
9
|
-
# library.
|
8
|
+
# computers.
|
10
9
|
#
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# Nitro integrates the powerful Og Object-Relational mapping
|
11
|
+
# library.
|
13
12
|
#
|
14
|
-
|
15
|
-
#
|
13
|
+
#--
|
14
|
+
# George Moschovitis <gm@navel.gr>
|
15
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
16
|
+
# $Id: nitro.rb 215 2005-01-24 10:44:05Z gmosx $
|
17
|
+
#++
|
16
18
|
|
17
19
|
require 'glue'
|
20
|
+
require 'glue/logger'
|
21
|
+
|
22
|
+
require 'nitro/context'
|
23
|
+
require 'nitro/dispatcher'
|
24
|
+
require 'nitro/render'
|
25
|
+
|
26
|
+
# Define Nitro namespace.
|
27
|
+
|
28
|
+
module Nitro
|
29
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2005 Navel, all rights reserved.
|
3
|
+
# $Id$
|
4
|
+
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
module N
|
8
|
+
|
9
|
+
=begin
|
10
|
+
# Extend the Request module.
|
11
|
+
|
12
|
+
module Request
|
13
|
+
include CGI::QueryExtension
|
14
|
+
|
15
|
+
def stdinput
|
16
|
+
@in
|
17
|
+
end
|
18
|
+
end
|
19
|
+
=end
|
20
|
+
|
21
|
+
# CGI utility methods.
|
22
|
+
|
23
|
+
class CgiUtils
|
24
|
+
|
25
|
+
# HTTP protocol EOL constants
|
26
|
+
|
27
|
+
CR = "\x0d"
|
28
|
+
LF = "\x0a"
|
29
|
+
CRLF = "\x0d\x0a"
|
30
|
+
EOL = CRLF
|
31
|
+
|
32
|
+
# Constants for readable code
|
33
|
+
|
34
|
+
STATUS_OK = 200
|
35
|
+
STATUS_PARTIAL_CONTENT = 206
|
36
|
+
STATUS_MOVED = 301
|
37
|
+
STATUS_REDIRECT = 302
|
38
|
+
STATUS_SEE_OTHER = 303 # gmosx: VERIFY THIS
|
39
|
+
STATUS_SEE_OTHER_307 = 307 # gmosx: VERIFY THIS
|
40
|
+
STATUS_NOT_MODIFIED = 304
|
41
|
+
STATUS_BAD_REQUEST = 400
|
42
|
+
STATUS_AUTH_REQUIRED = 401
|
43
|
+
STATUS_FORBIDDEN = 403
|
44
|
+
STATUS_NOT_FOUND = 404
|
45
|
+
STATUS_METHOD_NOT_ALLOWED = 405
|
46
|
+
STATUS_NOT_ACCEPTABLE = 406
|
47
|
+
STATUS_LENGTH_REQUIRED = 411
|
48
|
+
STATUS_PRECONDITION_FAILED = 412
|
49
|
+
STATUS_SERVER_ERROR = 500
|
50
|
+
STATUS_NOT_IMPLEMENTED = 501
|
51
|
+
STATUS_BAD_GATEWAY = 502
|
52
|
+
STATUS_VARIANT_ALSO_VARIES = 506
|
53
|
+
|
54
|
+
# Hash to allow id to description maping.
|
55
|
+
|
56
|
+
STATUS_STRINGS = {
|
57
|
+
200 => "OK",
|
58
|
+
206 => "Partial Content",
|
59
|
+
300 => "Multiple Choices",
|
60
|
+
301 => "Moved Permanently",
|
61
|
+
302 => "Found",
|
62
|
+
303 => "See other", # gmosx: VERIFY THIS
|
63
|
+
304 => "Not Modified",
|
64
|
+
307 => "See other 07", # gmosx: VERIFY THIS
|
65
|
+
400 => "Bad Request",
|
66
|
+
401 => "Authorization Required",
|
67
|
+
403 => "Forbidden",
|
68
|
+
404 => "Not Found",
|
69
|
+
405 => "Method Not Allowed",
|
70
|
+
406 => "Not Acceptable",
|
71
|
+
411 => "Length Required",
|
72
|
+
412 => "Precondition Failed",
|
73
|
+
500 => "Internal Server Error",
|
74
|
+
501 => "Method Not Implemented",
|
75
|
+
502 => "Bad Gateway",
|
76
|
+
506 => "Variant Also Negotiates"
|
77
|
+
}
|
78
|
+
|
79
|
+
# Returns a hash with the pairs from the query
|
80
|
+
# string. The implicit hash construction that is done
|
81
|
+
# in parse_request_params is not done here.
|
82
|
+
#
|
83
|
+
# Parameters in the form xxx[] are converted
|
84
|
+
# to arrays.
|
85
|
+
|
86
|
+
def self.parse_query_string(query_string)
|
87
|
+
# gmosx, THINK: better return nil here?
|
88
|
+
|
89
|
+
return {} if (query_string.nil? or query_string.empty?)
|
90
|
+
|
91
|
+
params = {}
|
92
|
+
|
93
|
+
query_string.split(/[&;]/).each do |p|
|
94
|
+
key, val = p.split('=')
|
95
|
+
|
96
|
+
key = CGI.unescape(key) unless key.nil?
|
97
|
+
val = CGI.unescape(val) unless val.nil?
|
98
|
+
|
99
|
+
if key =~ /(.*)\[\]$/
|
100
|
+
if params.has_key?($1)
|
101
|
+
params[$1] << val
|
102
|
+
else
|
103
|
+
params[$1] = [val]
|
104
|
+
end
|
105
|
+
else
|
106
|
+
params[key] = val.nil? ? nil : val
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
return params
|
111
|
+
end
|
112
|
+
|
113
|
+
# Parse the HTTP_COOKIE header and returns the
|
114
|
+
# cookies as a key->value hash. For efficiency no
|
115
|
+
# cookie objects are created.
|
116
|
+
#
|
117
|
+
# [+context+]
|
118
|
+
# The context
|
119
|
+
|
120
|
+
def self.parse_cookies(context)
|
121
|
+
env = context.env
|
122
|
+
|
123
|
+
# FIXME: dont precreate?
|
124
|
+
context.cookies = {}
|
125
|
+
|
126
|
+
if env.has_key?('HTTP_COOKIE') or env.has_key?('COOKIE')
|
127
|
+
(env['HTTP_COOKIE'] or env['COOKIE']).split(/; /).each do |c|
|
128
|
+
key, val = c.split(/=/, 2)
|
129
|
+
|
130
|
+
key = CGI.unescape(key)
|
131
|
+
val = val.split(/&/).collect{|v| CGI::unescape(v)}.join("\0")
|
132
|
+
|
133
|
+
if context.cookies.include?(key)
|
134
|
+
context.cookies[key] += "\0" + val
|
135
|
+
else
|
136
|
+
context.cookies[key] = val
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Build the response headers for the context.
|
143
|
+
|
144
|
+
def self.response_headers(context)
|
145
|
+
reason = STATUS_STRINGS[context.status]
|
146
|
+
buf = "HTTP/1.1 #{context.status} #{reason} #{EOL}"
|
147
|
+
|
148
|
+
context.response_headers.each do |key, value|
|
149
|
+
tmp = key.gsub(/\bwww|^te$|\b\w/) { |s| s.upcase }
|
150
|
+
buf << "#{tmp}: #{value}" << EOL
|
151
|
+
end
|
152
|
+
|
153
|
+
context.response_cookies.each do |cookie|
|
154
|
+
buf << "Set-Cookie: " << cookie.to_s << EOL
|
155
|
+
end if context.response_cookies
|
156
|
+
|
157
|
+
buf << EOL
|
158
|
+
end
|
159
|
+
|
160
|
+
# Initialize the request params.
|
161
|
+
# Handles multipart forms (in particular, forms that involve
|
162
|
+
# file uploads). Reads query parameters in the @params field,
|
163
|
+
# and cookies into @cookies.
|
164
|
+
|
165
|
+
def self.parse_params(context)
|
166
|
+
method = context.method
|
167
|
+
if (:post == method) and
|
168
|
+
%r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(context.headers['CONTENT_TYPE'])
|
169
|
+
boundary = $1.dup
|
170
|
+
context.params = read_multipart(boundary, Integer(context.headers['CONTENT_LENGTH']))
|
171
|
+
else
|
172
|
+
case method
|
173
|
+
when :get, :head
|
174
|
+
context.params = CgiUtils.parse_query_string(context.query_string)
|
175
|
+
when :post
|
176
|
+
context.in.binmode if defined?(context.in.binmode)
|
177
|
+
|
178
|
+
context.params = CgiUtils.parse_query_string(
|
179
|
+
context.in.read(
|
180
|
+
Integer(context.headers['CONTENT_LENGTH'])) || '')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Parse a multipart request.
|
186
|
+
|
187
|
+
def self.read_multipart(boundary, content_length)
|
188
|
+
params = Hash.new([])
|
189
|
+
boundary = "--" + boundary
|
190
|
+
buf = ""
|
191
|
+
bufsize = 10 * 1024
|
192
|
+
|
193
|
+
# start multipart/form-data
|
194
|
+
stdinput.binmode if defined? stdinput.binmode
|
195
|
+
boundary_size = boundary.size + EOL.size
|
196
|
+
content_length -= boundary_size
|
197
|
+
status = stdinput.read(boundary_size)
|
198
|
+
if nil == status
|
199
|
+
raise EOFError, "no content body"
|
200
|
+
elsif boundary + EOL != status
|
201
|
+
raise EOFError, "bad content body"
|
202
|
+
end
|
203
|
+
|
204
|
+
loop do
|
205
|
+
head = nil
|
206
|
+
if 10240 < content_length
|
207
|
+
require "tempfile"
|
208
|
+
body = Tempfile.new("CGI")
|
209
|
+
else
|
210
|
+
begin
|
211
|
+
require "stringio"
|
212
|
+
body = StringIO.new
|
213
|
+
rescue LoadError
|
214
|
+
require "tempfile"
|
215
|
+
body = Tempfile.new("CGI")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
body.binmode if defined? body.binmode
|
219
|
+
|
220
|
+
until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
|
221
|
+
|
222
|
+
if (not head) and /#{EOL}#{EOL}/n.match(buf)
|
223
|
+
buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
|
224
|
+
head = $1.dup
|
225
|
+
""
|
226
|
+
end
|
227
|
+
next
|
228
|
+
end
|
229
|
+
|
230
|
+
if head and ( (EOL + boundary + EOL).size < buf.size )
|
231
|
+
body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
|
232
|
+
buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
|
233
|
+
end
|
234
|
+
|
235
|
+
c = if bufsize < content_length
|
236
|
+
stdinput.read(bufsize)
|
237
|
+
else
|
238
|
+
stdinput.read(content_length)
|
239
|
+
end
|
240
|
+
if c.nil?
|
241
|
+
raise EOFError, "bad content body"
|
242
|
+
end
|
243
|
+
buf.concat(c)
|
244
|
+
content_length -= c.size
|
245
|
+
end
|
246
|
+
|
247
|
+
buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{boundary}([\r\n]{1,2}|--)/n) do
|
248
|
+
body.print $1
|
249
|
+
if "--" == $2
|
250
|
+
content_length = -1
|
251
|
+
end
|
252
|
+
""
|
253
|
+
end
|
254
|
+
|
255
|
+
body.rewind
|
256
|
+
|
257
|
+
/Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
|
258
|
+
filename = ($1 or "")
|
259
|
+
if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
|
260
|
+
/Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
|
261
|
+
(not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
|
262
|
+
filename = CGI::unescape(filename)
|
263
|
+
end
|
264
|
+
|
265
|
+
/Content-Type: (.*)/ni.match(head)
|
266
|
+
content_type = ($1 or "")
|
267
|
+
|
268
|
+
(class << body; self; end).class_eval do
|
269
|
+
alias local_path path
|
270
|
+
define_method(:original_filename) {filename.dup.taint}
|
271
|
+
define_method(:content_type) {content_type.dup.taint}
|
272
|
+
end
|
273
|
+
|
274
|
+
/Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
|
275
|
+
name = $1.dup
|
276
|
+
|
277
|
+
if params.has_key?(name)
|
278
|
+
params[name].push(body)
|
279
|
+
else
|
280
|
+
params[name] = [body]
|
281
|
+
end
|
282
|
+
break if buf.size == 0
|
283
|
+
break if content_length === -1
|
284
|
+
end
|
285
|
+
|
286
|
+
params
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2005 Navel, all rights reserved.
|
3
|
+
# $Id$
|
4
|
+
|
5
|
+
require 'cgi'
|
6
|
+
require 'fcgi'
|
7
|
+
|
8
|
+
require 'nitro/context'
|
9
|
+
require 'nitro/dispatcher'
|
10
|
+
require 'nitro/adaptors/cgi'
|
11
|
+
|
12
|
+
module N
|
13
|
+
|
14
|
+
# FastCGI Adaptor. FastCGI is a language independent,
|
15
|
+
# scalable, open extension to CGI that provides high
|
16
|
+
# performance without the limitations of server
|
17
|
+
# specific APIs.
|
18
|
+
|
19
|
+
class FastCGI
|
20
|
+
|
21
|
+
def self.start(conf)
|
22
|
+
FCGI.each do |cgi|
|
23
|
+
context = Context.new(conf)
|
24
|
+
|
25
|
+
context.in = cgi.in
|
26
|
+
context.headers = cgi.env
|
27
|
+
|
28
|
+
CgiUtils.parse_params(context)
|
29
|
+
CgiUtils.parse_cookies(context)
|
30
|
+
|
31
|
+
context.render(context.path)
|
32
|
+
|
33
|
+
cgi.out.print(CgiUtils.response_headers(context))
|
34
|
+
cgi.out.print(context.out)
|
35
|
+
|
36
|
+
cgi.finish
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# * George Moschovitis <gm@navel.gr>
|
4
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
5
|
+
# $Id$
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
module N
|
10
|
+
|
11
|
+
# The Runner is a helper class that encapsulates a web
|
12
|
+
# application and is responsible for launching the
|
13
|
+
# application using different adaptors. Default arguments
|
14
|
+
# parsing is also provided.
|
15
|
+
#
|
16
|
+
# You can implement your own, custom version of the Runner
|
17
|
+
# to run your custom web applications.
|
18
|
+
#
|
19
|
+
#--
|
20
|
+
# TODO: find a better name
|
21
|
+
#++
|
22
|
+
|
23
|
+
class Runner
|
24
|
+
|
25
|
+
# Parse the arguments and run the web application
|
26
|
+
# using the declared environment and adaptor
|
27
|
+
|
28
|
+
def self.run(argv)
|
29
|
+
|
30
|
+
# :start, :stop, :restart.
|
31
|
+
|
32
|
+
action = :start
|
33
|
+
|
34
|
+
# :webrick, :lhttp, :apache
|
35
|
+
|
36
|
+
server = :webrick
|
37
|
+
|
38
|
+
# daemonize? (in webrick only)
|
39
|
+
|
40
|
+
daemon = false
|
41
|
+
|
42
|
+
# log to file ?
|
43
|
+
|
44
|
+
log_to_file = false
|
45
|
+
|
46
|
+
# Parse the arguments.
|
47
|
+
|
48
|
+
parser = OptionParser.new do |opts|
|
49
|
+
|
50
|
+
opts.banner = 'Usage: ctl [options]'
|
51
|
+
opts.separator ''
|
52
|
+
opts.separator 'Specific options:'
|
53
|
+
|
54
|
+
opts.on("-s", "--start", "Start application.") do
|
55
|
+
action = :start
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("-S", "--stop", "Stop application.") do
|
59
|
+
action = :stop
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-r", "--restart", "Restart application.") do
|
63
|
+
action = :restart
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("-d", "--daemon", "Run application as a daemon.") do
|
67
|
+
daemon = true
|
68
|
+
log_to_file = true
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("-D", "--debug", "Run application in debug mode.") do
|
72
|
+
$DBG = true
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-w", "--webrick", "Use a webrick server [default].") do
|
76
|
+
server = :webrick
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("-l", "--lhttpd", "Use a webrick server [default].") do
|
80
|
+
server = :lhttpd
|
81
|
+
log_to_file = true
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on_tail("-v", "--version", "Show version.") do
|
85
|
+
require 'nitro/version'
|
86
|
+
puts "Nitro #{Nitro::Version}"
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
|
90
|
+
opts.on_tail("-?", "--help", "Show this message.") do
|
91
|
+
puts opts
|
92
|
+
exit
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
parser.parse!(ARGV)
|
98
|
+
|
99
|
+
require 'conf/app.conf.rb'
|
100
|
+
|
101
|
+
if log_to_file
|
102
|
+
Logger.set(Logger.new('log/app.log'))
|
103
|
+
end
|
104
|
+
|
105
|
+
case server
|
106
|
+
|
107
|
+
when :webrick
|
108
|
+
require 'nitro/adaptors/webrick'
|
109
|
+
N::Webrick.start($conf)
|
110
|
+
|
111
|
+
when :lhttpd
|
112
|
+
require 'nitro/adaptors/fastcgi'
|
113
|
+
`lighttpd -f conf/lhttpd.conf`
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
# Run the app!
|
120
|
+
|
121
|
+
Runner.run(ARGV)
|
122
|
+
|
123
|
+
end
|