nitro 0.40.0 → 0.41.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/nitro CHANGED
@@ -84,7 +84,7 @@ class NitroCommand < Console::Command
84
84
  ENV['NITRO_INVOKE'] = 'irb'
85
85
 
86
86
  if f = application_file
87
- ENV['CONFIGURATION_MODE'] = $DBG ? 'debug' : 'live'
87
+ ENV['NITRO_MODE'] = $DBG ? 'debug' : 'live'
88
88
  exec "#{irb_name} -r #{f} -r irb/completion --noinspect"
89
89
  end
90
90
 
@@ -114,18 +114,18 @@ class NitroCommand < Console::Command
114
114
 
115
115
  def __debug
116
116
  ARGV.delete('--debug')
117
- ENV['CONFIGURATION_MODE'] = 'debug'
117
+ ENV['NITRO_MODE'] = 'debug'
118
118
  end
119
119
  alias __devel __debug
120
120
 
121
121
  def __stage
122
122
  ARGV.delete('--stage')
123
- ENV['CONFIGURATION_MODE'] = 'stage'
123
+ ENV['NITRO_MODE'] = 'stage'
124
124
  end
125
125
 
126
126
  def __live
127
127
  ARGV.delete('--live')
128
- ENV['CONFIGURATION_MODE'] = 'live'
128
+ ENV['NITRO_MODE'] = 'live'
129
129
  end
130
130
  alias __production __live
131
131
 
@@ -10,6 +10,13 @@ For more help, send your question to the mailing list:
10
10
  http://rubyforge.org/mailman/listinfo/nitro-general
11
11
 
12
12
 
13
+ == 0.41.0 <- 0.40.0
14
+
15
+ This release is backwards compatible with 0.40.0. But please
16
+ prefer to use the NITRO_MODE env variable instead of the
17
+ deprecated CONFIGURATION_MODE env variable.
18
+
19
+
13
20
  == 0.40.0 <- 0.31.0
14
21
 
15
22
  This version was in the making for ages, so there are some changes
@@ -1,3 +1,32 @@
1
+ == Version 0.41.0
2
+
3
+ This is a bug fix release. As it fixes some important bugs of the
4
+ previous release, including a DOS vulnurability you are strongly
5
+ advised to update your version. However, you will also find
6
+ a couple of new features:
7
+
8
+ * Extended entity .finder method can now handle relations.
9
+
10
+ Post.find_by_title_and_forum_name(title,forumName)
11
+
12
+ class Forum
13
+ property :name, String
14
+ has_many :posts, Post
15
+ end
16
+
17
+ class Post
18
+ property :title, String
19
+ property :message, String
20
+ belongs_to :forum, Forum
21
+ end
22
+
23
+ 'forum' is the :forum from belongs_to, 'name' is a property from the
24
+ relations. It creates a SQL subquery to find the correct forum_oid.
25
+
26
+ * Added a simple call/answer mechanism that may be useful in some
27
+ cases. Will be improved in future versions.
28
+
29
+
1
30
  == Version 0.40.0
2
31
 
3
32
  This is the biggest release yet! Tons of new wonderful features,
data/doc/TODO CHANGED
@@ -3,6 +3,8 @@
3
3
 
4
4
  h2. Nitro
5
5
 
6
+ * send error code on not found!
7
+ * support this: <?include href="/comment/list" with="obj = article" ?>
6
8
  * the examples require *serious* updating.
7
9
  * move markup back to glue.
8
10
  * Optimize settings lookup.
@@ -14,7 +14,7 @@ module Glue
14
14
  # File.join(Uploads.public_root, request.user.name, 'icon.png')
15
15
  # end
16
16
  #
17
- # property :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' }
17
+ # attr_accessor :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' }
18
18
  # end
19
19
  #--
20
20
  # TODO: webfile_path customization sucks, should be improved!
@@ -99,12 +99,12 @@ class WebFile
99
99
  }
100
100
  else
101
101
  code << %{
102
- path = File.join(WebFile.upload_root, param.original_filename)
102
+ path = File.join(WebFile.upload_root, WebFile.sanitize(param.original_filename))
103
103
  }
104
104
  end
105
105
 
106
106
  code << %{
107
- @#{name} = WebFile.sanitize(path)
107
+ @#{name} = path
108
108
  @#{name}_size = param.size
109
109
 
110
110
  real_path = #{name}_real_path
@@ -144,15 +144,15 @@ class WebFile
144
144
  end
145
145
  end
146
146
 
147
- # Sanitize a filename.
148
- #--
149
- # TODO: implement me!
150
- #++
147
+ # Sanitize a filename. You can override this method to make
148
+ # this suit your needs.
151
149
 
152
150
  def self.sanitize(filename)
153
- filename
151
+ ext = File::extname(filename)
152
+ base = File::basename(filename, ext).gsub(/[\\\/\? !@$\(\)]/, '-')[0..64]
153
+ return "#{base}.#{ext}"
154
154
  end
155
-
155
+
156
156
  end
157
157
 
158
158
  # An alias, implies thumbnailing.
@@ -214,8 +214,11 @@ class Cgi
214
214
 
215
215
  params = Hash.new()
216
216
  boundary = "--" + boundary
217
+ quoted_boundary = Regexp.quote(boundary, "n")
217
218
  buf = ""
218
-
219
+ boundary_end=""
220
+
221
+ # start multipart/form-data
219
222
  input.binmode if defined? input.binmode
220
223
  boundary_size = boundary.size + EOL.size
221
224
  content_length -= boundary_size
@@ -234,6 +237,7 @@ class Cgi
234
237
  body = Tempfile.new("CGI")
235
238
  else
236
239
  begin
240
+ require "stringio"
237
241
  body = StringIO.new
238
242
  rescue LoadError
239
243
  body = Tempfile.new("CGI")
@@ -241,7 +245,7 @@ class Cgi
241
245
  end
242
246
  body.binmode if defined? body.binmode
243
247
 
244
- until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
248
+ until head and /#{quoted_boundary}(?:#{EOL}|--)/n.match(buf)
245
249
 
246
250
  if (not head) and /#{EOL}#{EOL}/n.match(buf)
247
251
  buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
@@ -268,11 +272,12 @@ class Cgi
268
272
  content_length -= c.size
269
273
  end
270
274
 
271
- buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{boundary}([\r\n]{1,2}|--)/n) do
275
+ buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
272
276
  body.print $1
273
277
  if "--" == $2
274
278
  content_length = -1
275
279
  end
280
+ boundary_end = $2.dup
276
281
  ""
277
282
  end
278
283
 
@@ -308,6 +313,7 @@ class Cgi
308
313
  break if buf.size == 0
309
314
  break if content_length === -1
310
315
  end
316
+ raise EOFError, "bad boundary end of body" unless boundary_end =~ /--/
311
317
 
312
318
  return params
313
319
  end
@@ -139,11 +139,19 @@ class Elements # :nodoc: all
139
139
  @buffer << "<?#{name}#{attributes}?>"
140
140
  end
141
141
 
142
+ def cdata(content)
143
+ @buffer << "<![CDATA[#{content}]]>"
144
+ end
145
+
142
146
  def comment(c)
143
147
  unless Template.strip_xml_comments
144
148
  @buffer << "<!--#{c}-->"
145
149
  end
146
150
  end
151
+
152
+ def doctype(name, pub_sys, long_name, uri)
153
+ @buffer << "<!DOCTYPE #{name} #{pub_sys} #{long_name} #{uri}>\n"
154
+ end
147
155
  end
148
156
 
149
157
  class << self
@@ -202,6 +202,10 @@ class Morphing
202
202
  @buffer << "<?#{name}#{attributes}?>"
203
203
  end
204
204
 
205
+ def cdata(content)
206
+ @buffer << "<![CDATA[#{content}]]>"
207
+ end
208
+
205
209
  def comment(c)
206
210
  unless Nitro::Template.strip_xml_comments
207
211
  @buffer << "<!--#{c}-->"
@@ -209,7 +213,7 @@ class Morphing
209
213
  end
210
214
 
211
215
  def doctype(name, pub_sys, long_name, uri)
212
- @buffer << "<!DOCTYPE #{name} #{pub_sys} #{long_name} #{uri}>"
216
+ @buffer << "<!DOCTYPE #{name} #{pub_sys} #{long_name} #{uri}>\n"
213
217
  end
214
218
  end
215
219
 
@@ -70,6 +70,7 @@ module Helpers
70
70
  raise "helper #{modname} not found (module not defined), check name"
71
71
  end
72
72
  symbols = mod.instance_methods.collect { |m| m.to_sym }
73
+
73
74
  self.send(:include, mod)
74
75
  self.send(:private, *symbols)
75
76
  self.send(:private, mod.to_s[/[^:]+$/].to_sym)
@@ -1,4 +1,3 @@
1
- require 'glue/uri'
2
1
  require 'glue/configuration'
3
2
 
4
3
  require 'og/collection'
@@ -232,8 +231,15 @@ private
232
231
  # Generate the target URI.
233
232
 
234
233
  def target_uri(page)
235
- params = { @key => page }
236
- return Glue::UriUtils.update_query_string(@request.uri.to_s, params)
234
+ uri = @request.uri.to_s
235
+
236
+ if uri =~ /[?;]#{@key}=(\d*)/
237
+ return uri.gsub(/([?;]#{@key}=)\d*/) { |m| "#$1#{page}" }
238
+ elsif uri =~ /\?/
239
+ return "#{uri};#{@key}=#{page}"
240
+ else
241
+ return "#{uri}?#{@key}=#{page}"
242
+ end
237
243
  end
238
244
 
239
245
  end
@@ -12,6 +12,8 @@ require 'nitro/flash'
12
12
  require 'nitro/helper'
13
13
  require 'nitro/compiler'
14
14
 
15
+ require 'nitro/util/encode_url'
16
+
15
17
  module Nitro
16
18
 
17
19
  # Include this Mixin to a class to make objects of this class
@@ -64,6 +66,8 @@ module Publishable
64
66
  end
65
67
  end
66
68
 
69
+ base.helper(EncodeUrl)
70
+
67
71
  # Aliases an action
68
72
  #--
69
73
  # gmosx, FIXME: better implementation needed.
@@ -80,6 +84,9 @@ module Publishable
80
84
  # Return the 'action' methods for this Controller.
81
85
  # Some dangerous methods from ancestors are removed.
82
86
  # All private methods are ignored.
87
+ #--
88
+ # gmosx, TODO: maybe we should optimize this method.
89
+ #++
83
90
 
84
91
  base.module_eval do
85
92
  def self.action_methods
@@ -217,7 +224,7 @@ private
217
224
  cookie.expires = Time.now
218
225
  @context.add_cookie(cookie)
219
226
  end
220
-
227
+ =begin
221
228
  # Encode controller, action, params into a valid url.
222
229
  # Automatically respects nice urls and routing.
223
230
  #
@@ -314,6 +321,7 @@ private
314
321
  return "#{request.host_url}#{encode_url(*args)}"
315
322
  end
316
323
  alias RA encode_absolute_url
324
+ =end
317
325
 
318
326
  # Allows instances of Publishable classes to know where they
319
327
  # are mounted.
@@ -238,6 +238,42 @@ private
238
238
  end
239
239
  alias_method :redirect_to_home, :redirect_home
240
240
 
241
+ # :section: Seaside style call/answer methods.
242
+
243
+ # Call redirects to the given url but push the original
244
+ # url in a callstack, so that the target can return by
245
+ # executing answer.
246
+ #
247
+ # === Example
248
+ #
249
+ # caller:
250
+ # color, type = call 'utils/select_color'
251
+ #
252
+ # target:
253
+ # answer color, type
254
+ #--
255
+ # FIXME: dont use yet, you have to encode the branch to
256
+ # make this safe for use.
257
+ #++
258
+
259
+ def call(url, status = 303)
260
+ (session[:CALL_STACK] ||= []) << request.uri
261
+ redirect(url, status)
262
+ end
263
+
264
+ # Returns from a call by poping the callstack.
265
+ #--
266
+ # FIXME: don't use yet.
267
+ #++
268
+
269
+ def answer(index = 0, status = 303)
270
+ if stack = session[:CALL_STACK] and not stack.empty?
271
+ redirect(stack.pop, status)
272
+ else
273
+ raise 'Cannot answer, call stack is empty'
274
+ end
275
+ end
276
+
241
277
  # Log a rendering error.
242
278
 
243
279
  def log_error(error, path, full = true)
@@ -86,14 +86,14 @@ module Scaffold
86
86
  #{controller}
87
87
  }
88
88
 
89
- if defined? OgSystemController
90
- self.extend(OgSystemHelper)
89
+ if defined? OgAdminController
90
+ self.extend(OgAdminHelper)
91
91
 
92
92
  # to_edit_href
93
93
  # ex: admin/update/Article/23
94
94
 
95
95
  define_instance_method klass, :to_edit_href, %{
96
- "\#{OgSystemController.mount_path}/update/#{class_to_name(klass)}/\#{oid}"
96
+ "\#{OgAdminController.mount_path}/update/#{class_to_name(klass)}/\#{oid}"
97
97
  }
98
98
 
99
99
  # to_admin_href
@@ -221,7 +221,7 @@ class Runner
221
221
  # Setup in debug mode.
222
222
 
223
223
  def setup_debug
224
- $DBG = true
224
+ $DBG.nil? ? true : $DBG
225
225
  Compiler.reload = true
226
226
  autoreload(3)
227
227
  Caching.caching_enabled = false
@@ -230,16 +230,17 @@ class Runner
230
230
  end
231
231
 
232
232
  def setup_stage
233
- $DBG = false
233
+ $DBG.nil? ? false : $DBG
234
234
  Compiler.reload = true
235
- autoreload(3)
236
- Logger.set(Logger.new('log/app.log'))
235
+ autoreload(3)
236
+
237
+ # load_external_configuration(:stage)
237
238
 
238
- # load_external_configuration(:stage)
239
+ Logger.set(Configuration.log)
239
240
  end
240
241
 
241
242
  def setup_live
242
- $DBG = false
243
+ $DBG.nil? ? false : $DBG
243
244
 
244
245
  # Enable the reloading even on live apps by default.
245
246
  # But have a longer thread sleep time.
@@ -247,11 +248,12 @@ class Runner
247
248
  # reloading (Compiler.reload = false)
248
249
 
249
250
  Compiler.reload = true
250
- autoreload(2 * 60)
251
- Logger.set(Logger.new('log/app.log'))
251
+ autoreload(2 * 60)
252
+
253
+ # load_external_configuration(:live)
254
+ # load_external_configuration(:production)
252
255
 
253
- # load_external_configuration(:live)
254
- # load_external_configuration(:production)
256
+ Logger.set(Configuration.log)
255
257
  end
256
258
  alias_method :setup_production, :setup_live
257
259
 
@@ -1,5 +1,4 @@
1
1
  require 'md5'
2
- require 'webrick'
3
2
 
4
3
  require 'facets/more/synchash'
5
4
  require 'facets/more/times'
@@ -1,3 +1,4 @@
1
+ require 'digest/md5'
1
2
  require 'ostruct'
2
3
  require 'facets/more/openobject'
3
4
  require 'glue/configuration'
@@ -13,8 +14,9 @@ module TemplateMixin
13
14
 
14
15
  # Set some pretty safe delimiters for templates.
15
16
 
16
- START_DELIM = "<<NITRO_TEMPLATE_DELIMETER\n"
17
- END_DELIM = "\nNITRO_TEMPLATE_DELIMETER\n"
17
+ DELIM_HSH = Digest::MD5.hexdigest(Kernel.rand.to_s)
18
+ START_DELIM = "<<NITRO_TEMPLATE_DELIMETER#{DELIM_HSH}\n"
19
+ END_DELIM = "\nNITRO_TEMPLATE_DELIMETER#{DELIM_HSH}\n"
18
20
 
19
21
  # Convert a template to actual Ruby code, ready to be
20
22
  # evaluated.
@@ -39,7 +41,7 @@ module TemplateMixin
39
41
 
40
42
  # Strip the xml header! (interracts with the following gsub!)
41
43
 
42
- text.gsub!(/<\?xml.*\?>/, "")
44
+ text.gsub!(/<\?xml.*\?>/, '')
43
45
 
44
46
  # Transform include instructions <include href="xxx" />
45
47
  # must be transformed before the processinc instructions.
@@ -49,16 +51,12 @@ module TemplateMixin
49
51
  # add load_statically_included fixes.
50
52
  #++
51
53
 
52
- text.gsub!(/<include href=["'](.*?)["'](.*)(.?)\/>/) do |match|
53
- "<?r File.read( '\#{@dispatcher.root}/#$1' ?>"
54
- end
54
+ text.gsub!(/<include\s+href=["'](.*?)["']\s+\/>/, %[<?r File.read("\#{@dispatcher.root}/\\1") ?>])
55
55
 
56
56
  # xform render/inject instructions <render href="xxx" />
57
57
  # must be transformed before the processinc instructions.
58
58
 
59
- text.gsub!(/<(render|inject) href=["'](.*?)["'](.*)(.?)\/>/) do |match|
60
- "<?r render '#$2' ?>"
61
- end
59
+ text.gsub!(/<(?:render|inject)\s+href=["'](.*?)["']\s+\/>/, %[<?r render "\\1" ?>])
62
60
 
63
61
  # Remove <root> elements. typically removed by xslt but lets
64
62
  # play it safe. The <root> element is typically added to
@@ -69,20 +67,23 @@ module TemplateMixin
69
67
  # Transform the processing instructions, use <?r as
70
68
  # a marker.
71
69
 
72
- text.gsub!(/\?>/, "; #{buffer} << #{START_DELIM}")
73
- text.gsub!(/<\?r(\s?)/, "#{END_DELIM}; ")
70
+ text.gsub!(/<\?r\s+(.*?)\s+\?>/m, "#{END_DELIM}; \\1; #{buffer} << #{START_DELIM}")
71
+ #text.gsub!(/<\?r(\s?)/, "#{END_DELIM}; ")
72
+ #text.gsub!(/\?>/, "; #{buffer} << #{START_DELIM}")
74
73
 
75
74
  # Transform alternative code tags.
76
75
  # (very useful in xsl stylesheets)
77
76
 
78
- text.gsub!(/<\/ruby>/, "; #{buffer} << #{START_DELIM}")
79
- text.gsub!(/<ruby>/, "#{END_DELIM}; ")
77
+ text.gsub!(/<ruby>(.*?)<\/ruby>/m, "#{END_DELIM}; \\1; #{buffer} << #{START_DELIM}")
78
+ #text.gsub!(/<\/ruby>/, "; #{buffer} << #{START_DELIM}")
79
+ #text.gsub!(/<ruby>/, "#{END_DELIM}; ")
80
80
 
81
81
  # Also handle erb/asp/jsp style tags. Those tags
82
82
  # *cannot* be used with an xslt stylesheet.
83
83
 
84
- text.gsub!(/%>/, "; #{buffer} << #{START_DELIM}")
85
- text.gsub!(/<%/, "#{END_DELIM}; ")
84
+ text.gsub!(/<%(.*?)%>/m, "#{END_DELIM}; \\1; #{buffer} << #{START_DELIM}")
85
+ #text.gsub!(/%>/, "; #{buffer} << #{START_DELIM}")
86
+ #text.gsub!(/<%/, "#{END_DELIM}; ")
86
87
 
87
88
  # Alterative versions of interpolation.
88
89
  # (very useful in xsl stylesheets)
@@ -0,0 +1,112 @@
1
+ module Nitro
2
+
3
+ # A collection of intelligent url encoding methods.
4
+
5
+ module EncodeUrl
6
+
7
+ private
8
+
9
+ # Encode controller, action, params into a valid url.
10
+ # Automatically respects nice urls and routing.
11
+ #
12
+ # Handles parameters either as a hash or as an array.
13
+ # Use the array method to pass parameters to 'nice' actions.
14
+ #
15
+ # Pass Controller, action, and (param_name, param_value)
16
+ # pairs.
17
+ #
18
+ # === Examples
19
+ #
20
+ # encode_url ForaController, :post, :title, 'Hello', :body, 'World'
21
+ # encode_url :post, :title, 'Hello', :body, 'World' # => implies controller == self
22
+ # encode_url :kick, :oid, 4
23
+ # encode_url article # => article.to_href
24
+ #
25
+ # Alternatively you can pass options with a hash:
26
+ #
27
+ # encode_url :controller => ForaController, :action => :delete, :params => { :title => 'Hello' }
28
+ # encode_url :action => :delete
29
+ #--
30
+ # FIXME: better implementation? optimize this?
31
+ # TODO: move elsewhere.
32
+ #++
33
+
34
+ def encode_url(*args)
35
+ f = args.first
36
+
37
+ # A standard url as string, return as is.
38
+
39
+ if f.is_a? String
40
+ return f
41
+ end
42
+
43
+ # If the passed param is an object that responds to :to_href
44
+ # returns the url to this object.
45
+
46
+ if f.respond_to? :to_href
47
+ return args.first.to_href
48
+ end
49
+
50
+ if f.is_a? Symbol
51
+ # no controller passed, try to use self as controller.
52
+ if self.is_a? Nitro::Controller
53
+ args.unshift(self.class)
54
+ else
55
+ raise 'No controller passed to encode_url'
56
+ end
57
+ end
58
+
59
+ # Try to encode using the router.
60
+
61
+ if url = Context.current.dispatcher.encode_route(*args)
62
+ return url
63
+ end
64
+
65
+ # No routing rule, manual encoding.
66
+
67
+ controller = args.shift
68
+ action = args.shift.to_sym
69
+
70
+ if action == :index
71
+ url = "#{controller.mount_path}"
72
+ else
73
+ mount_path = controller.mount_path
74
+ mount_path = nil if mount_path == '/'
75
+ url = "#{mount_path}/#{action}"
76
+ end
77
+
78
+ unless args.empty?
79
+ if controller.respond_to_action_or_template? action
80
+ param_count = controller.instance_method(action).arity
81
+ if param_count != 0
82
+ param_count.times do
83
+ args.shift # name
84
+ url << "/#{CGI.escape(args.shift.to_s)}"
85
+ end
86
+ end
87
+ end
88
+
89
+ unless args.empty?
90
+ url << '?'
91
+ params = []
92
+ (args.size / 2).times do
93
+ params << "#{args.shift}=#{args.shift}"
94
+ end
95
+ url << params.join(';')
96
+ end
97
+ end
98
+
99
+ return url
100
+ end
101
+ alias R encode_url
102
+
103
+ # Just like encode_url, but generates an absolute url instead.
104
+
105
+ def encode_absolute_url(*args)
106
+ return "#{request.host_url}#{encode_url(*args)}"
107
+ end
108
+ alias RA encode_absolute_url
109
+
110
+ end
111
+
112
+ end
@@ -2,5 +2,5 @@
2
2
  module Nitro
3
3
  # The version of Nitro.
4
4
 
5
- Version = '0.40.0'
5
+ Version = '0.41.0'
6
6
  end
@@ -4,7 +4,7 @@ require 'part/admin/helper'
4
4
  # The main Controller for the Admin part.
5
5
 
6
6
  class AdminController < Nitro::Controller
7
- helper :table, :sitemap
7
+ helper :table
8
8
  helper AdminHelper
9
9
  ann :self, :element_namespace => AdminSkin
10
10
 
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  class OgAdminController < Nitro::Controller
26
26
 
27
- helper :table, :sitemap
27
+ helper :table
28
28
  helper AdminHelper, OgAdminHelper
29
29
 
30
30
  ann :self, :element_namespace => AdminSkin
@@ -100,14 +100,12 @@ class TestAdapterCgi < Test::Unit::TestCase # :nodoc: all
100
100
  params = Cgi.parse_query_string(qs)
101
101
  assert_equal 2, params.size
102
102
  arr = params['arr']
103
- assert_equal Array, arr.class
104
103
  assert_equal 3, arr.size
105
104
 
106
105
  qs = 'other=1;user.name=gmosx;user.password=hello'
107
106
  params = Cgi.parse_query_string(qs)
108
107
  assert_equal 2, params.size
109
108
  u = params['user']
110
- assert_equal Hash, u.class
111
109
  assert_equal 'gmosx', u['name']
112
110
  assert_equal 'hello', u['password']
113
111
 
@@ -122,7 +120,6 @@ class TestAdapterCgi < Test::Unit::TestCase # :nodoc: all
122
120
  params = Cgi.parse_query_string(qs)
123
121
  assert_equal 2, params.size
124
122
  u = params['user']
125
- assert_equal Hash, u.class
126
123
  assert_equal 'gmosx', u['name']
127
124
  assert_equal 'hello', u['password']
128
125
  end
@@ -21,6 +21,12 @@ module AnotherHelper
21
21
  end
22
22
  end
23
23
 
24
+ module Funny
25
+ def funny_world
26
+ return 1
27
+ end
28
+ end
29
+
24
30
  class MyBase < Base
25
31
  helper :my
26
32
  helper AnotherHelper
@@ -32,5 +38,10 @@ class TC_Helper < Test::Unit::TestCase # :nodoc: all
32
38
  assert MyBase.private_instance_methods.include?('hello_world')
33
39
  assert !MyBase.public_instance_methods.include?('bye_world')
34
40
  assert MyBase.private_instance_methods.include?('bye_world')
41
+
42
+ # test a bug.
43
+ MyBase.helper(Funny)
44
+ assert !MyBase.public_instance_methods.include?('funny_world')
45
+ assert MyBase.private_instance_methods.include?('funny_world')
35
46
  end
36
47
  end
@@ -4,6 +4,8 @@ require 'test/unit'
4
4
 
5
5
  require 'nitro'
6
6
  require 'nitro/render'
7
+ require 'nitro/session'
8
+ require 'nitro/context'
7
9
  require 'facet/mock'
8
10
 
9
11
  class TestRender < Test::Unit::TestCase # :nodoc: all
@@ -17,6 +19,60 @@ class TestRender < Test::Unit::TestCase # :nodoc: all
17
19
  class TestController < Controller
18
20
  end
19
21
 
22
+ class CallController < Controller
23
+ def return_session
24
+ session[:CALL_STACK].inspect
25
+ end
26
+
27
+ def needs_login
28
+ call "login"
29
+ end
30
+
31
+ def login
32
+ answer()
33
+ end
34
+ end
35
+
36
+ @@session = Session.new
37
+ def handle_request(url, value)
38
+ conf = OpenStruct.new
39
+ disp = Nitro::Dispatcher.new('/' => CallController)
40
+ conf.dispatcher = disp
41
+ @ctx = Nitro::Context.new(conf)
42
+ @ctx.headers = { 'REQUEST_METHOD' => 'GET' }
43
+ @ctx.params = {}
44
+ @ctx.instance_variable_set '@session', @@session
45
+
46
+ if value[:in]
47
+ @ctx.in = value.delete(:in)
48
+ @ctx.headers['CONTENT_LENGTH'] = value.delete(:in_size) || @ctx.in.size
49
+ end
50
+
51
+ if value[:method]
52
+ @ctx.headers['REQUEST_METHOD'] = value[:method].to_s
53
+ end
54
+
55
+ if value['CONTENT_TYPE']
56
+ @ctx.headers['CONTENT_TYPE'] = value.delete('CONTENT_TYPE')
57
+ end
58
+
59
+ @ctx.headers['REQUEST_URI'] = url
60
+
61
+ if (!@ctx.query_string || @ctx.query_string.empty?) and @ctx.uri =~ /\?/
62
+ @ctx.headers['QUERY_STRING'] = @ctx.uri.split('?').last
63
+ end
64
+
65
+ Nitro::Cgi.parse_params(@ctx)
66
+ Nitro::Cgi.parse_cookies(@ctx)
67
+
68
+ @ctx.render url
69
+
70
+ #retrieve the stuff from @out again as a hash
71
+ result = @ctx.out
72
+
73
+ return result
74
+ end
75
+
20
76
  def setup
21
77
  ctx = ContextMock.new
22
78
  @controller = TestController.new(ctx)
@@ -52,4 +108,12 @@ class TestRender < Test::Unit::TestCase # :nodoc: all
52
108
  rescue Nitro::RenderExit
53
109
  end
54
110
  end
111
+
112
+ def test_call
113
+ handle_request('/needs_login', {})
114
+ assert_equal ['/needs_login'], eval(handle_request('/return_session', {}))
115
+ handle_request('/login', {})
116
+ assert_equal [], eval(handle_request('/return_session', {}))
117
+ end
118
+
55
119
  end
@@ -6,13 +6,13 @@ require 'nitro/template'
6
6
 
7
7
  class TestTemplate < Test::Unit::TestCase # :nodoc: all
8
8
  include Nitro
9
-
9
+
10
10
  def test_all
11
11
  template = %q{
12
12
  Hello #{user}
13
13
 
14
14
  dont forget the following todo items:
15
-
15
+
16
16
  <?r for item in items ?>
17
17
  <li>#{item}</li>
18
18
  <?r end ?>
@@ -26,9 +26,46 @@ class TestTemplate < Test::Unit::TestCase # :nodoc: all
26
26
 
27
27
  assert_match %r{\<li\>nitro\</li\>}, out
28
28
  assert_match %r{\<li\>really\</li\>}, out
29
- assert_match %r{Hello gmosx}, out
30
-
29
+ assert_match %r{Hello gmosx}, out
30
+
31
31
  # TODO: add test for static inclusion.
32
-
32
+
33
+ end
34
+
35
+ def test_interpolation
36
+ template = %q[
37
+ <% user1 = 'one' %>
38
+ <%
39
+ user2 = 'two'
40
+ %>
41
+ <?r user3 = 'three' ?>
42
+ <?r
43
+ user4 = 'four'
44
+ ?>
45
+ <ruby>user5 = 'five'</ruby>
46
+ <ruby>
47
+ user6 = 'six'
48
+ </ruby>
49
+ user1: #\user1\
50
+ user2: #{user2}
51
+ user3: #{ user3 }
52
+ user4: #\ user4\
53
+ user5: #\user5 \
54
+ user6: #\ user6\
55
+ ]
56
+
57
+ out = ''
58
+ Nitro::Template.process(template, :out, binding)
59
+
60
+ {
61
+ :user1 => 'one',
62
+ :user2 => 'two',
63
+ :user3 => 'three',
64
+ :user4 => 'four',
65
+ :user5 => 'five',
66
+ :user6 => 'six'
67
+ }.each do |key, val|
68
+ assert_match "#{key}: #{val}", out
69
+ end
33
70
  end
34
71
  end
@@ -0,0 +1,62 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'CONFIG.rb')
2
+
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+
6
+ require 'glue'
7
+ require 'glue/logger'
8
+ require 'nitro'
9
+ require 'nitro/util/encode_url'
10
+
11
+ class TC_EncodeUrl < Test::Unit::TestCase # :nodoc: all
12
+ include Nitro
13
+
14
+ class FirstController < Controller
15
+ def list
16
+ end
17
+ public :encode_url
18
+ end
19
+
20
+ class SecondController < Controller
21
+ attr_reader :aqflag, :tflag
22
+
23
+ def self.setup_template_root(path)
24
+ @template_root << File.expand_path(File.join(Nitro::LibPath, "../test/public/#{path}"))
25
+ end
26
+
27
+ def list
28
+ @aqflag = true
29
+ end
30
+
31
+ def another(oid)
32
+ # nop
33
+ end
34
+ end
35
+
36
+ class TestEncoder
37
+ include Nitro::EncodeUrl
38
+ public :encode_url
39
+ end
40
+
41
+ def setup
42
+ @disp = Dispatcher.new '/first' => FirstController,
43
+ '/second' => SecondController
44
+ @conf = OpenStruct.new
45
+ @conf.dispatcher = @disp
46
+ Thread.current[:CURRENT_CONTEXT] = @conf
47
+ end
48
+
49
+ def test_encode
50
+ t = TestEncoder.new
51
+
52
+ assert_equal 'test', t.encode_url('test')
53
+ assert_equal '/first/list', t.encode_url(FirstController, :list)
54
+
55
+ end
56
+
57
+ def test_controller_encode
58
+ t = FirstController.new(@conf)
59
+
60
+ assert_equal '/first/list', t.encode_url(:list)
61
+ end
62
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: nitro
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.40.0
7
- date: 2006-11-13 10:56:16 +02:00
6
+ version: 0.41.0
7
+ date: 2006-12-12 12:36:44 +02:00
8
8
  summary: Everything you need to create Web 2.0 applications with Ruby and Javascript
9
9
  require_paths:
10
10
  - lib
@@ -76,6 +76,7 @@ files:
76
76
  - lib/nitro/test
77
77
  - lib/nitro/test.rb
78
78
  - lib/nitro/version.rb
79
+ - lib/nitro/util
79
80
  - lib/nitro/adapter/cgi.rb
80
81
  - lib/nitro/adapter/console.rb
81
82
  - lib/nitro/adapter/fastcgi.rb
@@ -160,6 +161,7 @@ files:
160
161
  - lib/nitro/test/assertions.rb
161
162
  - lib/nitro/test/context.rb
162
163
  - lib/nitro/test/testcase.rb
164
+ - lib/nitro/util/encode_url.rb
163
165
  - lib/part/admin.rb
164
166
  - lib/part/admin
165
167
  - lib/part/admin/controller.rb
@@ -201,6 +203,7 @@ files:
201
203
  - test/nitro/tc_server.rb
202
204
  - test/nitro/tc_session.rb
203
205
  - test/nitro/tc_template.rb
206
+ - test/nitro/util
204
207
  - test/nitro/adapter/raw_post1.bin
205
208
  - test/nitro/adapter/tc_webrick.rb
206
209
  - test/nitro/cgi/tc_cookie.rb
@@ -212,6 +215,7 @@ files:
212
215
  - test/nitro/helper/tc_pager.rb
213
216
  - test/nitro/helper/tc_table.rb
214
217
  - test/nitro/helper/tc_xhtml.rb
218
+ - test/nitro/util/tc_encode_url.rb
215
219
  - test/public/blog
216
220
  - test/public/dummy_mailer
217
221
  - test/public/blog/another
@@ -279,7 +283,7 @@ dependencies:
279
283
  requirements:
280
284
  - - "="
281
285
  - !ruby/object:Gem::Version
282
- version: 0.40.0
286
+ version: 0.41.0
283
287
  version:
284
288
  - !ruby/object:Gem::Dependency
285
289
  name: gen
@@ -288,7 +292,7 @@ dependencies:
288
292
  requirements:
289
293
  - - "="
290
294
  - !ruby/object:Gem::Version
291
- version: 0.40.0
295
+ version: 0.41.0
292
296
  version:
293
297
  - !ruby/object:Gem::Dependency
294
298
  name: glue
@@ -297,7 +301,7 @@ dependencies:
297
301
  requirements:
298
302
  - - "="
299
303
  - !ruby/object:Gem::Version
300
- version: 0.40.0
304
+ version: 0.41.0
301
305
  version:
302
306
  - !ruby/object:Gem::Dependency
303
307
  name: RedCloth