nitro 0.40.0 → 0.41.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.
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