nitro 0.8.0 → 0.9.3

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 (198) hide show
  1. data/AUTHORS +3 -4
  2. data/ChangeLog +418 -0
  3. data/LICENSE +1 -1
  4. data/README +157 -89
  5. data/RELEASES +50 -0
  6. data/Rakefile +5 -7
  7. data/benchmark/nitro/bench.rb +5 -0
  8. data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
  9. data/benchmark/nitro/static-webrick-n-200.txt +43 -0
  10. data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
  11. data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
  12. data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
  13. data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
  14. data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
  15. data/bin/proto/README +2 -2
  16. data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
  17. data/bin/proto/conf/app.conf.rb +22 -0
  18. data/bin/proto/conf/lhttpd.conf +236 -0
  19. data/bin/proto/ctl +4 -0
  20. data/bin/proto/lib/README +5 -0
  21. data/bin/proto/log/README +3 -0
  22. data/bin/proto/root/fcgi.rb +6 -0
  23. data/bin/proto/root/index.xhtml +65 -7
  24. data/bin/proto/root/m/nitro.png +0 -0
  25. data/examples/blog/README +7 -5
  26. data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
  27. data/examples/blog/conf/app.conf.rb +56 -0
  28. data/examples/blog/conf/lhttpd.conf +236 -0
  29. data/examples/blog/ctl +4 -0
  30. data/examples/blog/lib/blog.rb +11 -136
  31. data/examples/blog/lib/blog/controller.rb +99 -0
  32. data/examples/blog/lib/blog/model.rb +39 -0
  33. data/examples/blog/log/README +3 -0
  34. data/examples/blog/root/comments.xhtml +2 -2
  35. data/examples/blog/root/fcgi.rb +6 -0
  36. data/examples/blog/root/index.xhtml +4 -5
  37. data/examples/blog/root/login.xhtml +2 -2
  38. data/examples/blog/root/style.xsl +9 -9
  39. data/examples/blog/root/view_entry.xhtml +2 -2
  40. data/examples/flash/conf/app.conf.rb +23 -0
  41. data/examples/flash/ctl +4 -0
  42. data/examples/flash/log/README +3 -0
  43. data/examples/flash/root/index.xhtml +0 -9
  44. data/examples/flash/root/show_inline_text.xhtml +10 -5
  45. data/examples/no_xsl_blog/README +12 -0
  46. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  47. data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
  48. data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
  49. data/examples/no_xsl_blog/ctl +4 -0
  50. data/examples/no_xsl_blog/lib/blog.rb +20 -0
  51. data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
  52. data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
  53. data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
  54. data/examples/no_xsl_blog/log/README +3 -0
  55. data/examples/no_xsl_blog/root/comments.xhtml +41 -0
  56. data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
  57. data/examples/no_xsl_blog/root/fcgi.rb +6 -0
  58. data/examples/no_xsl_blog/root/index.xhtml +39 -0
  59. data/examples/no_xsl_blog/root/login.xhtml +21 -0
  60. data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
  61. data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
  62. data/examples/no_xsl_blog/root/m/down.gif +0 -0
  63. data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
  64. data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
  65. data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
  66. data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
  67. data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
  68. data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
  69. data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
  70. data/examples/no_xsl_blog/root/m/obull.gif +0 -0
  71. data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
  72. data/examples/no_xsl_blog/root/m/rss.gif +0 -0
  73. data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
  74. data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
  75. data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
  76. data/examples/no_xsl_blog/root/style.css +301 -0
  77. data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
  78. data/examples/no_xsl_blog/root/view_entry.xml +12 -0
  79. data/examples/og/run.rb +2 -2
  80. data/examples/tiny/README +2 -2
  81. data/examples/tiny/conf/apache.conf +5 -0
  82. data/examples/tiny/conf/app.conf.rb +21 -0
  83. data/examples/tiny/conf/lhttpd.conf +236 -0
  84. data/examples/tiny/ctl +4 -0
  85. data/examples/tiny/log/README +3 -0
  86. data/examples/tiny/root/fcgi.rb +6 -0
  87. data/examples/tiny/root/index.xhtml +7 -4
  88. data/examples/tiny/root/nitro.png +0 -0
  89. data/lib/glue.rb +13 -9
  90. data/lib/glue/array.rb +1 -1
  91. data/lib/glue/cache.rb +1 -1
  92. data/lib/glue/flexob.rb +12 -0
  93. data/lib/glue/hash.rb +1 -1
  94. data/lib/glue/inflector.rb +2 -2
  95. data/lib/glue/logger.rb +4 -8
  96. data/lib/glue/misc.rb +14 -0
  97. data/lib/glue/number.rb +1 -1
  98. data/lib/glue/object.rb +26 -0
  99. data/lib/glue/pool.rb +1 -1
  100. data/lib/glue/property.rb +84 -91
  101. data/lib/glue/string.rb +1 -1
  102. data/lib/glue/time.rb +1 -1
  103. data/lib/glue/validation.rb +1 -1
  104. data/lib/nitro.rb +18 -6
  105. data/lib/nitro/adaptors/cgi.rb +291 -0
  106. data/lib/nitro/adaptors/fastcgi.rb +42 -0
  107. data/lib/nitro/adaptors/runner.rb +123 -0
  108. data/lib/nitro/adaptors/webrick.rb +110 -0
  109. data/lib/nitro/buffering.rb +43 -0
  110. data/lib/nitro/builders/form.rb +1 -1
  111. data/lib/nitro/builders/rss.rb +1 -1
  112. data/{bin → lib/nitro}/cluster.rb +26 -30
  113. data/lib/nitro/context.rb +82 -0
  114. data/lib/nitro/controller.rb +50 -0
  115. data/lib/nitro/cookie.rb +46 -0
  116. data/lib/nitro/dispatcher.rb +105 -0
  117. data/lib/nitro/filters.rb +9 -10
  118. data/lib/nitro/localization.rb +42 -0
  119. data/lib/nitro/mail.rb +11 -14
  120. data/lib/nitro/render.rb +275 -0
  121. data/lib/nitro/request.rb +128 -0
  122. data/lib/nitro/response.rb +38 -0
  123. data/lib/nitro/scaffold.rb +11 -11
  124. data/lib/nitro/session.rb +84 -0
  125. data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
  126. data/lib/nitro/ui/pager.rb +23 -26
  127. data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
  128. data/lib/nitro/uri.rb +1 -1
  129. data/lib/nitro/version.rb +10 -8
  130. data/lib/og.rb +66 -65
  131. data/lib/og/backend.rb +1 -1
  132. data/lib/og/backends/mysql.rb +48 -52
  133. data/lib/og/backends/psql.rb +34 -37
  134. data/lib/og/connection.rb +15 -15
  135. data/lib/og/enchant.rb +16 -9
  136. data/lib/og/meta.rb +127 -54
  137. data/lib/og/mock.rb +18 -18
  138. data/lib/og/version.rb +6 -4
  139. data/lib/parts/content.rb +4 -8
  140. data/test/glue/tc_logger.rb +3 -0
  141. data/test/glue/tc_property.rb +19 -3
  142. data/test/nitro/adaptors/tc_cgi.rb +63 -0
  143. data/test/nitro/adaptors/tc_webrick.rb +15 -0
  144. data/test/nitro/builders/tc_xml.rb +2 -2
  145. data/test/nitro/tc_context.rb +13 -0
  146. data/test/nitro/tc_controller.rb +47 -0
  147. data/test/nitro/tc_dispatcher.rb +64 -0
  148. data/test/nitro/tc_session.rb +20 -0
  149. data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
  150. data/test/root/blog/list.xhtml +6 -0
  151. data/test/tc_og.rb +41 -4
  152. metadata +115 -59
  153. data/bin/proto/app.rb +0 -20
  154. data/bin/proto/config.rb +0 -77
  155. data/examples/blog/app.rb +0 -21
  156. data/examples/blog/config.rb +0 -95
  157. data/examples/blog/env.rb +0 -22
  158. data/examples/flash/README +0 -34
  159. data/examples/flash/app.rb +0 -20
  160. data/examples/flash/config.rb +0 -38
  161. data/examples/flash/lib/flash.rb +0 -40
  162. data/examples/flash/tmp.swf +0 -0
  163. data/examples/tiny/app.rb +0 -19
  164. data/examples/tiny/config.rb +0 -29
  165. data/examples/tiny/root/nitro-small.png +0 -0
  166. data/lib/nitro/application.rb +0 -217
  167. data/lib/nitro/config.rb +0 -128
  168. data/lib/nitro/events.rb +0 -122
  169. data/lib/nitro/html.rb +0 -151
  170. data/lib/nitro/http.rb +0 -102
  171. data/lib/nitro/l10n.rb +0 -30
  172. data/lib/nitro/server.rb +0 -59
  173. data/lib/nitro/server/appserver.rb +0 -67
  174. data/lib/nitro/server/cookie.rb +0 -87
  175. data/lib/nitro/server/dispatcher.rb +0 -62
  176. data/lib/nitro/server/filters.rb +0 -75
  177. data/lib/nitro/server/filters/autologin.rb +0 -51
  178. data/lib/nitro/server/fragment.rb +0 -70
  179. data/lib/nitro/server/handlers.rb +0 -127
  180. data/lib/nitro/server/render.rb +0 -426
  181. data/lib/nitro/server/request.rb +0 -658
  182. data/lib/nitro/server/requestpart.rb +0 -54
  183. data/lib/nitro/server/script.rb +0 -387
  184. data/lib/nitro/server/server.rb +0 -57
  185. data/lib/nitro/server/session.rb +0 -220
  186. data/lib/nitro/server/user.rb +0 -46
  187. data/lib/nitro/server/webrick.rb +0 -180
  188. data/lib/nitro/service.rb +0 -26
  189. data/lib/xsl/ui.xsl +0 -51
  190. data/lib/xsl/xforms.xsl +0 -28
  191. data/test/nitro/server/tc_cookie.rb +0 -34
  192. data/test/nitro/server/tc_filters.rb +0 -38
  193. data/test/nitro/server/tc_request.rb +0 -70
  194. data/test/nitro/server/tc_requestpart.rb +0 -28
  195. data/test/nitro/server/tc_session.rb +0 -34
  196. data/test/nitro/tc_events.rb +0 -44
  197. data/test/nitro/tc_html.rb +0 -79
  198. data/test/nitro/tc_http.rb +0 -18
@@ -4,7 +4,7 @@
4
4
  # * Elias Karakoulakis <ekarak@ktismata.com>
5
5
  #
6
6
  # (c) 2004 Navel, all rights reserved.
7
- # $Id: string.rb 165 2004-11-18 12:04:04Z gmosx $
7
+ # $Id: string.rb 202 2005-01-17 10:44:13Z gmosx $
8
8
 
9
9
  require "uri"
10
10
 
@@ -2,7 +2,7 @@
2
2
  # * George Moschovitis <gm@navel.gr>
3
3
  #
4
4
  # (c) 2004 Navel, all rights reserved.
5
- # $Id: time.rb 167 2004-11-23 14:03:10Z gmosx $
5
+ # $Id: time.rb 202 2005-01-17 10:44:13Z gmosx $
6
6
 
7
7
  require "time.rb"
8
8
 
@@ -216,7 +216,7 @@ module Validation
216
216
 
217
217
  for name in params
218
218
  confirm_name = "#{name}#{c[:postfix]}"
219
- attr_accessor :"#{confirm_name}"
219
+ eval "attr_accessor :#{confirm_name}"
220
220
 
221
221
  code = %{
222
222
  if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
@@ -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. Nitro integrates the powerful Og Object-Relational mapping
9
- # library.
8
+ # computers.
10
9
  #
11
- # code:
12
- # * George Moschovitis <gm@navel.gr>
10
+ # Nitro integrates the powerful Og Object-Relational mapping
11
+ # library.
13
12
  #
14
- # (c) 2004 Navel, all rights reserved.
15
- # $Id: nitro.rb 167 2004-11-23 14:03:10Z gmosx $
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