raw 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/doc/CONTRIBUTORS +106 -0
  2. data/doc/LICENSE +32 -0
  3. data/doc/coding_conventions.txt +11 -0
  4. data/lib/raw.rb +42 -0
  5. data/lib/raw/adapter.rb +113 -0
  6. data/lib/raw/adapter/cgi.rb +41 -0
  7. data/lib/raw/adapter/fastcgi.rb +48 -0
  8. data/lib/raw/adapter/mongrel.rb +146 -0
  9. data/lib/raw/adapter/script.rb +94 -0
  10. data/lib/raw/adapter/webrick.rb +144 -0
  11. data/lib/raw/adapter/webrick/vcr.rb +91 -0
  12. data/lib/raw/cgi.rb +323 -0
  13. data/lib/raw/cgi/cookie.rb +47 -0
  14. data/lib/raw/cgi/http.rb +62 -0
  15. data/lib/raw/compiler.rb +138 -0
  16. data/lib/raw/compiler/filter/cleanup.rb +21 -0
  17. data/lib/raw/compiler/filter/elements.rb +166 -0
  18. data/lib/raw/compiler/filter/elements/element.rb +210 -0
  19. data/lib/raw/compiler/filter/localization.rb +23 -0
  20. data/lib/raw/compiler/filter/markup.rb +32 -0
  21. data/lib/raw/compiler/filter/morph.rb +123 -0
  22. data/lib/raw/compiler/filter/morph/each.rb +34 -0
  23. data/lib/raw/compiler/filter/morph/for.rb +11 -0
  24. data/lib/raw/compiler/filter/morph/if.rb +26 -0
  25. data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
  26. data/lib/raw/compiler/filter/morph/standard.rb +55 -0
  27. data/lib/raw/compiler/filter/morph/times.rb +27 -0
  28. data/lib/raw/compiler/filter/script.rb +116 -0
  29. data/lib/raw/compiler/filter/squeeze.rb +16 -0
  30. data/lib/raw/compiler/filter/static_include.rb +74 -0
  31. data/lib/raw/compiler/filter/template.rb +121 -0
  32. data/lib/raw/compiler/reloader.rb +96 -0
  33. data/lib/raw/context.rb +154 -0
  34. data/lib/raw/context/flash.rb +157 -0
  35. data/lib/raw/context/global.rb +88 -0
  36. data/lib/raw/context/request.rb +338 -0
  37. data/lib/raw/context/response.rb +57 -0
  38. data/lib/raw/context/session.rb +198 -0
  39. data/lib/raw/context/session/drb.rb +11 -0
  40. data/lib/raw/context/session/file.rb +15 -0
  41. data/lib/raw/context/session/memcached.rb +13 -0
  42. data/lib/raw/context/session/memory.rb +12 -0
  43. data/lib/raw/context/session/og.rb +15 -0
  44. data/lib/raw/context/session/pstore.rb +13 -0
  45. data/lib/raw/control.rb +18 -0
  46. data/lib/raw/control/attribute.rb +91 -0
  47. data/lib/raw/control/attribute/checkbox.rb +25 -0
  48. data/lib/raw/control/attribute/datetime.rb +21 -0
  49. data/lib/raw/control/attribute/file.rb +20 -0
  50. data/lib/raw/control/attribute/fixnum.rb +26 -0
  51. data/lib/raw/control/attribute/float.rb +26 -0
  52. data/lib/raw/control/attribute/options.rb +38 -0
  53. data/lib/raw/control/attribute/password.rb +16 -0
  54. data/lib/raw/control/attribute/text.rb +16 -0
  55. data/lib/raw/control/attribute/textarea.rb +16 -0
  56. data/lib/raw/control/none.rb +16 -0
  57. data/lib/raw/control/relation.rb +59 -0
  58. data/lib/raw/control/relation/belongs_to.rb +0 -0
  59. data/lib/raw/control/relation/has_many.rb +97 -0
  60. data/lib/raw/control/relation/joins_many.rb +0 -0
  61. data/lib/raw/control/relation/many_to_many.rb +0 -0
  62. data/lib/raw/control/relation/refers_to.rb +29 -0
  63. data/lib/raw/controller.rb +37 -0
  64. data/lib/raw/controller/publishable.rb +160 -0
  65. data/lib/raw/dispatcher.rb +209 -0
  66. data/lib/raw/dispatcher/format.rb +108 -0
  67. data/lib/raw/dispatcher/format/atom.rb +31 -0
  68. data/lib/raw/dispatcher/format/css.rb +0 -0
  69. data/lib/raw/dispatcher/format/html.rb +42 -0
  70. data/lib/raw/dispatcher/format/json.rb +31 -0
  71. data/lib/raw/dispatcher/format/rss.rb +33 -0
  72. data/lib/raw/dispatcher/format/xoxo.rb +31 -0
  73. data/lib/raw/dispatcher/mounter.rb +60 -0
  74. data/lib/raw/dispatcher/router.rb +111 -0
  75. data/lib/raw/errors.rb +19 -0
  76. data/lib/raw/helper.rb +86 -0
  77. data/lib/raw/helper/benchmark.rb +23 -0
  78. data/lib/raw/helper/buffer.rb +60 -0
  79. data/lib/raw/helper/cookie.rb +32 -0
  80. data/lib/raw/helper/debug.rb +28 -0
  81. data/lib/raw/helper/default.rb +16 -0
  82. data/lib/raw/helper/feed.rb +451 -0
  83. data/lib/raw/helper/form.rb +284 -0
  84. data/lib/raw/helper/javascript.rb +59 -0
  85. data/lib/raw/helper/layout.rb +40 -0
  86. data/lib/raw/helper/navigation.rb +87 -0
  87. data/lib/raw/helper/pager.rb +305 -0
  88. data/lib/raw/helper/table.rb +247 -0
  89. data/lib/raw/helper/xhtml.rb +218 -0
  90. data/lib/raw/helper/xml.rb +125 -0
  91. data/lib/raw/mixin/magick.rb +35 -0
  92. data/lib/raw/mixin/sweeper.rb +71 -0
  93. data/lib/raw/mixin/thumbnails.rb +1 -0
  94. data/lib/raw/mixin/webfile.rb +165 -0
  95. data/lib/raw/render.rb +271 -0
  96. data/lib/raw/render/builder.rb +26 -0
  97. data/lib/raw/render/caching.rb +81 -0
  98. data/lib/raw/render/call.rb +43 -0
  99. data/lib/raw/render/send_file.rb +46 -0
  100. data/lib/raw/render/stream.rb +39 -0
  101. data/lib/raw/scaffold.rb +13 -0
  102. data/lib/raw/scaffold/controller.rb +25 -0
  103. data/lib/raw/scaffold/model.rb +157 -0
  104. data/lib/raw/test.rb +5 -0
  105. data/lib/raw/test/assertions.rb +169 -0
  106. data/lib/raw/test/context.rb +55 -0
  107. data/lib/raw/test/testcase.rb +79 -0
  108. data/lib/raw/util/attr.rb +128 -0
  109. data/lib/raw/util/encode_uri.rb +149 -0
  110. data/lib/raw/util/html_filter.rb +538 -0
  111. data/lib/raw/util/markup.rb +130 -0
  112. data/test/glue/tc_webfile.rb +1 -0
  113. data/test/nitro/CONFIG.rb +3 -0
  114. data/test/nitro/adapter/raw_post1.bin +9 -0
  115. data/test/nitro/adapter/tc_webrick.rb +16 -0
  116. data/test/nitro/cgi/tc_cookie.rb +14 -0
  117. data/test/nitro/cgi/tc_request.rb +61 -0
  118. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  119. data/test/nitro/compiler/tc_compiler.rb +25 -0
  120. data/test/nitro/dispatcher/tc_mounter.rb +47 -0
  121. data/test/nitro/helper/tc_feed.rb +135 -0
  122. data/test/nitro/helper/tc_navbar.rb +74 -0
  123. data/test/nitro/helper/tc_pager.rb +35 -0
  124. data/test/nitro/helper/tc_table.rb +68 -0
  125. data/test/nitro/helper/tc_xhtml.rb +19 -0
  126. data/test/nitro/tc_caching.rb +19 -0
  127. data/test/nitro/tc_cgi.rb +222 -0
  128. data/test/nitro/tc_context.rb +17 -0
  129. data/test/nitro/tc_controller.rb +103 -0
  130. data/test/nitro/tc_controller_aspect.rb +32 -0
  131. data/test/nitro/tc_controller_params.rb +885 -0
  132. data/test/nitro/tc_dispatcher.rb +109 -0
  133. data/test/nitro/tc_element.rb +85 -0
  134. data/test/nitro/tc_flash.rb +59 -0
  135. data/test/nitro/tc_helper.rb +47 -0
  136. data/test/nitro/tc_render.rb +119 -0
  137. data/test/nitro/tc_router.rb +61 -0
  138. data/test/nitro/tc_server.rb +35 -0
  139. data/test/nitro/tc_session.rb +66 -0
  140. data/test/nitro/tc_template.rb +71 -0
  141. data/test/nitro/util/tc_encode_url.rb +87 -0
  142. data/test/nitro/util/tc_markup.rb +31 -0
  143. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  144. data/test/public/blog/inc1.xhtml +2 -0
  145. data/test/public/blog/inc2.xhtml +1 -0
  146. data/test/public/blog/list.xhtml +9 -0
  147. data/test/public/dummy_mailer/registration.xhtml +5 -0
  148. metadata +244 -0
@@ -0,0 +1 @@
1
+ require "raw/mixin/magick"
@@ -0,0 +1,165 @@
1
+ require "fileutils"
2
+
3
+ require "facets/more/inheritor"
4
+
5
+ module Raw::Mixin
6
+
7
+ # A Web File.
8
+ #
9
+ # You can customize the path where the uploaded file will be
10
+ # by defining a webfile_path class method *before* the property:
11
+ #
12
+ # class Icon
13
+ # def self.webfile_path request, name
14
+ # File.join(Uploads.public_root, request.user.name, 'icon.png')
15
+ # end
16
+ #
17
+ # attr_accessor :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' }
18
+ # end
19
+ #--
20
+ # TODO: webfile_path customization sucks, should be improved!
21
+ #++
22
+
23
+ class WebFile
24
+
25
+ # The directory where uploaded files are stored. Typically
26
+ # this is a symlink to another directory outside of the
27
+ # webapp dir for easier updates.
28
+
29
+ setting :upload_root, :default => 'upload', :doc => 'The directory where upload files are stored'
30
+
31
+ # Override files by default?
32
+
33
+ setting :override_files, :default => true, :doc => 'Override files by default?'
34
+
35
+ # Modify the base class when this class is included as a
36
+ # property
37
+ #--
38
+ # TODO: find a better name.
39
+ #++
40
+
41
+ def self.included_as_property(base, args)
42
+ if args.last.is_a?(Hash)
43
+ options = args.pop
44
+ else
45
+ options = Hash.new
46
+ end
47
+
48
+ args.pop if args.last.is_a?(Class)
49
+
50
+ if thumbnails = (options[:thumbnail] || options[:thumbnails] || options[:magick]) or self.name == 'WebImage'
51
+ require 'glue/thumbnails'
52
+ base.send :include, Thumbnails
53
+ thumbnails = { :small => :thumbnails } if thumbnails.is_a?(String)
54
+ end
55
+
56
+ for name in args
57
+ base.module_eval do
58
+ # The 'web' path to the file (relative to the public
59
+ # root directory. Uses the original property name
60
+ # or the #{name}_path alias.
61
+
62
+ attr_accessor name.to_sym, String, :control => :file
63
+ alias_method "#{name}_path".to_sym, name.to_sym
64
+
65
+ # The file size.
66
+
67
+ attr_accessor "#{name}_size".to_sym, Fixnum, :control => :none
68
+
69
+ # The mime type.
70
+
71
+ attr_accessor "#{name}_mime_type".to_sym, String , :control => :none
72
+
73
+ # Assignment callbacks.
74
+ #--
75
+ # gmosx, FIXME: this is a hack!! better implementation
76
+ # is needed (generalized property assigners).
77
+
78
+ inheritor(:assign_callbacks, [], :merge) unless @assign_callbacks
79
+ end
80
+
81
+ if thumbnails
82
+ for tname in thumbnails.keys
83
+ base.module_eval do
84
+ attr_accessor "#{name}_#{tname}_thumbnail".to_sym, String, :control => :none
85
+ end
86
+ end
87
+ end
88
+
89
+ code = %{
90
+ def #{name}_real_path
91
+ File.join(Nitro::Server.public_root, @#{name})
92
+ end
93
+
94
+ def #{name}_from_request(request)
95
+ param = request['#{name}']
96
+
97
+ return if param.nil? or param.original_filename.blank?
98
+ }
99
+ if base.respond_to? :webfile_path
100
+ code << %{
101
+ path = #{base}.webfile_path(request, '#{name}')
102
+ }
103
+ else
104
+ code << %{
105
+ path = File.join(WebFile.upload_root, WebFile.sanitize(param.original_filename))
106
+ }
107
+ end
108
+
109
+ code << %{
110
+ @#{name} = path
111
+ @#{name}_size = param.size
112
+
113
+ real_path = #{name}_real_path
114
+ raise 'file exists' if !WebFile.override_files and File.exists?(real_path)
115
+ FileUtils.mkdir_p(File.dirname(real_path))
116
+ if param.path
117
+ FileUtils.cp(param.path, real_path)
118
+ else
119
+ # gmosx FIXME: this is a hack!!
120
+ param.rewind
121
+ File.open(real_path, 'wb') { |f| f << param.read }
122
+ end
123
+ FileUtils.chmod(0664, real_path)
124
+ }
125
+
126
+ if thumbnails
127
+ for tname, geostring in thumbnails
128
+ code << %{
129
+ @#{name}_#{tname}_thumbnail = Thumbnails.generate_thumbnail(path, '#{tname}', '#{geostring}')
130
+ }
131
+ end
132
+ end
133
+
134
+ code << %{
135
+ end
136
+
137
+ def delete_#{name}
138
+ FileUtils.rm(#{name}_real_path)
139
+ end
140
+
141
+ assign_callbacks! << proc { |obj, values, options|
142
+ obj.#{name}_from_request(values)
143
+ }
144
+ }
145
+
146
+ base.module_eval(code)
147
+ end
148
+ end
149
+
150
+ # Sanitize a filename. You can override this method to make
151
+ # this suit your needs.
152
+
153
+ def self.sanitize(filename)
154
+ ext = File::extname(filename)
155
+ base = File::basename(filename, ext).gsub(/[\\\/\? !@$\(\)]/, '-')[0..64]
156
+ return "#{base}.#{ext}"
157
+ end
158
+
159
+ end
160
+
161
+ # An alias, implies thumbnailing.
162
+
163
+ WebImage = WebFile
164
+
165
+ end
@@ -0,0 +1,271 @@
1
+ require "stringio"
2
+
3
+ require "facets/core/string/blank"
4
+ require "facets/more/settings"
5
+
6
+ require "raw/render/builder"
7
+ require "raw/render/call"
8
+
9
+ module Raw
10
+
11
+ #--
12
+ # Raise or Throw this exception to stop the current action.
13
+ # Typically called to skip the template. This is considerered
14
+ # a low level tactic. Prefer to use the exit method.
15
+ #++
16
+
17
+ class ActionExit < Exception # :nodoc: all
18
+ end
19
+
20
+ #--
21
+ # Raise or Throw this exception to stop rendering altogether.
22
+ # Typically called by redirects.
23
+ #++
24
+
25
+ class RenderExit < Exception # :nodoc: all
26
+ end
27
+
28
+ #--
29
+ # The output buffer. The output of a contoller action is
30
+ # accumulated in this buffer before sending this to the client
31
+ # as a HTTP Response.
32
+ #
33
+ # TODO: Implement a FAST string (maybe in C)
34
+ #++
35
+
36
+ class OutputBuffer < String # :nodoc: all
37
+ end
38
+
39
+ # The rendering mixin. This module is typically included in
40
+ # published objects and/or controllers to provide rendering
41
+ # functionality.
42
+
43
+ module Render
44
+
45
+ # The output buffer. The output of a script/action is
46
+ # accumulated in this buffer.
47
+
48
+ attr_accessor :out
49
+ alias_method :body, :out
50
+
51
+ # The context.
52
+
53
+ attr_accessor :context
54
+ alias_method :request, :context
55
+ alias_method :response, :context
56
+
57
+ # The name of the currently executing action.
58
+
59
+ attr_accessor :action_name
60
+
61
+ # The current controller class.
62
+
63
+ attr_accessor :controller
64
+
65
+ # Initialize the render.
66
+ #
67
+ # [+context+]
68
+ # A parent render/controller acts as the context.
69
+
70
+ def initialize(context)
71
+ @context = context
72
+ @out = context.output_buffer
73
+ end
74
+
75
+ # Renders the action denoted by path. The path
76
+ # is resolved by the dispatcher to get the correct
77
+ # controller.
78
+ #
79
+ # Both relative and absolute paths are supported. Relative
80
+ # paths are converted to absolute by prepending the mount path
81
+ # of the controller.
82
+
83
+ def render(*args)
84
+ path = encode_uri(*args)
85
+ debug "Rendering '#{path}'" if $DBG
86
+
87
+ @controller, action, query, params, ext = @context.dispatcher.dispatch(path)
88
+ @context.content_type = @context.format.content_type
89
+
90
+ @context.level += 1
91
+ old_controller = Controller.replace_current(@controller)
92
+
93
+ if self.class == @controller
94
+ self.send(action, params)
95
+ else
96
+ @controller.new(@context).send(action, params)
97
+ end
98
+
99
+ Controller.replace_current(old_controller)
100
+ @context.level -= 1
101
+
102
+ rescue RenderExit, ActionExit => e1
103
+ # Just stop rendering.
104
+
105
+ rescue ActionError => e2
106
+ # Client Error family of errors, typically send 4XX
107
+ # status code.
108
+ handle_error(e2, 404)
109
+ error e2.to_s
110
+
111
+ rescue Object => e3
112
+ # Server Error family of errors, typically send 5XX
113
+ # status code.
114
+ # puts "--------", pp_exception(e3)
115
+
116
+ handle_error(e3, 500)
117
+ error "Error while handling '#{path}'"
118
+ error pp_exception(e3)
119
+ end
120
+
121
+ private
122
+ RADIUS = 3
123
+
124
+ # Extract the offending source code for a server error.
125
+
126
+ def extract_source_from(error)
127
+ extract = []
128
+
129
+ code = error.backtrace[1]
130
+ md = code.match(%r{:(\d+):in `(.*)'$})
131
+ line_num = md[1].to_i
132
+
133
+ code.split("\n")[(line_num - RADIUS)..(line_num + RADIUS)].each_with_index do |line, idx|
134
+ lidx = line_num - RADIUS + idx
135
+ extract << "#{lidx}: #{line}"
136
+ end
137
+
138
+ return extract
139
+ end
140
+
141
+ # Helper method to exit the current action, typically used
142
+ # to skip the template rendering.
143
+ #
144
+ # === Example
145
+ #
146
+ # def my_action
147
+ # ...
148
+ # exit unless user.admin?
149
+ # end
150
+
151
+ def exit
152
+ raise ActionExit.new
153
+ end
154
+
155
+ # Flush the IO object (OutputBuffer) if we are in streaming
156
+ # mode.
157
+
158
+ def flush
159
+ @out.flush if @out.is_a?(IO)
160
+ end
161
+
162
+ # :section: Redirection methods.
163
+
164
+ # Send a redirect response.
165
+ #
166
+ # If the URI (path) starts with '/' it is considered absolute, else
167
+ # the URI is considered relative to the current controller and
168
+ # the controller base is prepended.
169
+ #
170
+ # The parameters are passed to the R operator (encode_uri)
171
+ # to actually build the URI. So the following forms (among
172
+ # others) are allowed:
173
+ #
174
+ # redirect 'home/login'
175
+ # redirect ForaController, :post, :title, 'The title'
176
+ # redirect :welcome
177
+ # redirect article # => article.to_href
178
+ #
179
+ # You can also pass optional hash parameters at the end,
180
+ # for example:
181
+ #
182
+ # redirect :welcome, :status => 307
183
+ #
184
+ # The default redirect status is 303.
185
+ #
186
+ #--
187
+ # TODO: add a check for redirect to self (infinite loop)
188
+ #++
189
+
190
+ def redirect(*args)
191
+ # If this is an ajax and/or rpc request skip the redirect.
192
+ # Allows to write more reusable code.
193
+
194
+ return if request.script?
195
+
196
+ if args.last.is_a? Hash
197
+ status = args.last.fetch(:status, 303)
198
+ else
199
+ status = 303
200
+ end
201
+
202
+ uri = encode_uri(*args)
203
+
204
+ # gmosx, THINK: this may be unnecessary!
205
+
206
+ unless uri =~ /^http/
207
+ uri = "#{@context.host_uri}/#{uri.gsub(/^\//, '')}"
208
+ end
209
+
210
+ @context.status = status
211
+ @out = "<html><a href=\"#{uri}\">#{uri}</a>.</html>\n"
212
+ @context.response_headers['location'] = uri
213
+
214
+ raise RenderExit
215
+ end
216
+ alias_method :redirect_to, :redirect
217
+
218
+ # Redirect to the referer.
219
+
220
+ def redirect_referer(postfix = nil, status = 303)
221
+ redirect "#{@context.referer}#{postfix}", :status => status
222
+ end
223
+ alias_method :redirect_to_referer, :redirect_referer
224
+ alias_method :redirect_referrer, :redirect_referer
225
+ alias_method :redirect_to_referrer, :redirect_referer
226
+
227
+ # Redirect to home.
228
+
229
+ def redirect_home(status = 303)
230
+ redirect "/", :status => status
231
+ end
232
+ alias_method :redirect_to_home, :redirect_home
233
+
234
+ # Handle an error.
235
+ #--
236
+ # gmosx, TODO: add check for infinite loops here.
237
+ #++
238
+
239
+ def handle_error(exception, error_status = 500)
240
+ @context.status = error_status
241
+ @out = ""
242
+
243
+ session[:RENDERING_ERROR] = exception
244
+
245
+ render("/status_#{error_status}")
246
+ end
247
+
248
+ # Convenience method to lookup the session.
249
+
250
+ def session
251
+ @context.session
252
+ end
253
+
254
+ # Add some text to the output buffer.
255
+
256
+ def render_text(text)
257
+ @out << text
258
+ end
259
+ alias_method :print, :render_text
260
+
261
+ # Render a template into the output buffer.
262
+ # HACK FIX, will be removed.
263
+
264
+ def render_template(path)
265
+ render(path)
266
+ exit
267
+ end
268
+
269
+ end
270
+
271
+ end
@@ -0,0 +1,26 @@
1
+ require "glue/builder/xml"
2
+
3
+ module Raw
4
+
5
+ module Render
6
+
7
+ # Access the programmatic renderer (builder).
8
+
9
+ def build(&block)
10
+ if block.arity == 1
11
+ yield XmlBuilder.new(@out)
12
+ else
13
+ XmlBuilder.new(@out).instance_eval(&block)
14
+ end
15
+ end
16
+
17
+ # Return a programmatic renderer that targets the
18
+ # output buffer.
19
+
20
+ def builder
21
+ XmlBuilder.new(@out)
22
+ end
23
+
24
+ end
25
+
26
+ end