Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 344
- Log:
Massive changeset which brings the old, ROOL customised Instiki
version up to date, but without any ROOL customisations in this
latest checked-in version (which is 0.19.1). This is deliberate,
so that it's easy to see the changes made for the ROOL version
in a subsequent changeset. The 'app/views/shared' directory is not
part of Instiki but is kept to maintain the change history with
updated ROOL customisations, some of which involve the same files
in that same directory.
- Author:
- rool
- Date:
- Sat Mar 19 19:52:13 +0000 2011
- Size:
- 9291 Bytes
- Properties:
- Property svn:mergeinfo is set
1 | # The filters added to this controller will be run for all controllers in the application. |
2 | # Likewise will all the methods added be available for all controllers. |
3 | class ApplicationController < ActionController::Base |
4 | |
5 | protect_forms_from_spam |
6 | before_filter :connect_to_model, :check_authorization, :setup_url_generator, :set_content_type_header, :set_robots_metatag |
7 | after_filter :remember_location, :teardown_url_generator |
8 | |
9 | # For injecting a different wiki model implementation. Intended for use in tests |
10 | def self.wiki=(the_wiki) |
11 | # a global variable is used here because Rails reloads controller and model classes in the |
12 | # development environment; therefore, storing it as a class variable does not work |
13 | # class variable is, anyway, not much different from a global variable |
14 | #$instiki_wiki_service = the_wiki |
15 | logger.debug("Wiki service: #{the_wiki.to_s}") |
16 | end |
17 | |
18 | def self.wiki |
19 | Wiki.new |
20 | end |
21 | |
22 | helper_method :xhtml_enabled?, :html_ext, :darken |
23 | |
24 | protected |
25 | |
26 | def xhtml_enabled? |
27 | in_a_web? and [:markdownMML, :markdownPNG, :markdown].include?(@web.markup) |
28 | end |
29 | |
30 | def html_ext |
31 | if xhtml_enabled? && request.env.include?('HTTP_ACCEPT') && |
32 | Mime::Type.parse(request.env["HTTP_ACCEPT"]).include?(Mime::XHTML) |
33 | 'xhtml' |
34 | else |
35 | 'html' |
36 | end |
37 | end |
38 | |
39 | def darken(s) |
40 | n=s.length/3 |
41 | s.scan( %r(\w{#{n},#{n}}) ).collect {|a| (a.hex * 2/3).to_s(16).rjust(n,'0')}.join |
42 | end |
43 | |
44 | def check_authorization |
45 | if in_a_web? and authorization_needed? and not authorized? |
46 | redirect_to :controller => 'wiki', :action => 'login', :web => @web_name |
47 | return false |
48 | end |
49 | end |
50 | |
51 | def connect_to_model |
52 | @action_name = params['action'] || 'index' |
53 | @web_name = params['web'] |
54 | @wiki = wiki |
55 | @author = cookies['author'] || 'AnonymousCoward' |
56 | if @web_name |
57 | @web = @wiki.webs[@web_name] |
58 | if @web.nil? |
59 | render(:status => 404, :text => "Unknown web '#{@web_name}'", :layout => 'error') |
60 | return false |
61 | end |
62 | end |
63 | end |
64 | |
65 | FILE_TYPES = { |
66 | '.aif' => 'audio/x-aiff', |
67 | '.aiff'=> 'audio/x-aiff', |
68 | '.avi' => 'video/x-msvideo', |
69 | '.exe' => 'application/octet-stream', |
70 | '.gif' => 'image/gif', |
71 | '.jpg' => 'image/jpeg', |
72 | '.pdf' => 'application/pdf', |
73 | '.png' => 'image/png', |
74 | '.oga' => 'audio/ogg', |
75 | '.ogg' => 'audio/ogg', |
76 | '.ogv' => 'video/ogg', |
77 | '.mov' => 'video/quicktime', |
78 | '.mp3' => 'audio/mpeg', |
79 | '.mp4' => 'video/mp4', |
80 | '.spx' => 'audio/speex', |
81 | '.txt' => 'text/plain', |
82 | '.tex' => 'text/plain', |
83 | '.wav' => 'audio/x-wav', |
84 | '.zip' => 'application/zip' |
85 | } unless defined? FILE_TYPES |
86 | |
87 | DISPOSITION = { |
88 | 'application/octet-stream' => 'attachment', |
89 | 'application/pdf' => 'inline', |
90 | 'image/gif' => 'inline', |
91 | 'image/jpeg' => 'inline', |
92 | 'image/png' => 'inline', |
93 | 'audio/mpeg' => 'inline', |
94 | 'audio/x-wav' => 'inline', |
95 | 'audio/x-aiff' => 'inline', |
96 | 'audio/speex' => 'inline', |
97 | 'audio/ogg' => 'inline', |
98 | 'video/ogg' => 'inline', |
99 | 'video/mp4' => 'inline', |
100 | 'video/quicktime' => 'inline', |
101 | 'video/x-msvideo' => 'inline', |
102 | 'text/plain' => 'inline', |
103 | 'application/zip' => 'attachment' |
104 | } unless defined? DISPOSITION |
105 | |
106 | def determine_file_options_for(file_name, original_options = {}) |
107 | original_options[:type] ||= (FILE_TYPES[File.extname(file_name)] or 'application/octet-stream') |
108 | original_options[:disposition] ||= (DISPOSITION[original_options[:type]] or 'attachment') |
109 | original_options[:stream] ||= false |
110 | original_options[:x_sendfile] = true if request.env.include?('HTTP_X_SENDFILE_TYPE') && |
111 | ( request.remote_addr == LOCALHOST || defined?(PhusionPassenger) ) |
112 | original_options |
113 | end |
114 | |
115 | def send_file(file, options = {}) |
116 | determine_file_options_for(file, options) |
117 | super(file, options) |
118 | end |
119 | |
120 | def password_check(password) |
121 | if password == @web.password |
122 | cookies[CGI.escape(@web_name)] = password |
123 | true |
124 | else |
125 | false |
126 | end |
127 | end |
128 | |
129 | def password_error(password) |
130 | if password.nil? or password.empty? |
131 | 'Please enter the password.' |
132 | else |
133 | 'You entered a wrong password. Please enter the right one.' |
134 | end |
135 | end |
136 | |
137 | def redirect_home(web = @web_name) |
138 | if web |
139 | redirect_to_page('HomePage', web) |
140 | else |
141 | redirect_to '/' |
142 | end |
143 | end |
144 | |
145 | def redirect_to_page(page_name = @page_name, web = @web_name) |
146 | redirect_to :web => web, :controller => 'wiki', :action => 'show', |
147 | :id => (page_name or 'HomePage') |
148 | end |
149 | |
150 | def remember_location |
151 | if request.method == :get and |
152 | @status == '200' and not \ |
153 | %w(locked save back file pic import).include?(action_name) |
154 | session[:return_to] = request.request_uri |
155 | logger.debug "Session ##{session.object_id}: remembered URL '#{session[:return_to]}'" |
156 | end |
157 | end |
158 | |
159 | def rescue_action_in_public(exception) |
160 | render :status => 500, :text => <<-EOL |
161 | <html xmlns="http://www.w3.org/1999/xhtml"><body> |
162 | <h2>Internal Error</h2> |
163 | <p>An application error occurred while processing your request.</p> |
164 | <!-- \n#{exception.to_s.purify.gsub!(/-{2,}/, '- -') }\n#{exception.backtrace.join("\n")}\n --> |
165 | </body></html> |
166 | EOL |
167 | end |
168 | |
169 | def return_to_last_remembered |
170 | # Forget the redirect location |
171 | redirect_target, session[:return_to] = session[:return_to], nil |
172 | tried_home, session[:tried_home] = session[:tried_home], false |
173 | |
174 | # then try to redirect to it |
175 | if redirect_target.nil? |
176 | if tried_home |
177 | raise 'Application could not render the index page' |
178 | else |
179 | logger.debug("Session ##{session.object_id}: no remembered redirect location, trying home") |
180 | redirect_home |
181 | end |
182 | else |
183 | logger.debug("Session ##{session.object_id}: " + |
184 | "redirect to the last remembered URL #{redirect_target}") |
185 | redirect_to(redirect_target) |
186 | end |
187 | end |
188 | |
189 | def set_content_type_header |
190 | response.charset = 'utf-8' |
191 | if %w(atom_with_content atom_with_headlines).include?(action_name) |
192 | response.content_type = Mime::ATOM |
193 | elsif %w(tex tex_list).include?(action_name) |
194 | response.content_type = Mime::TEXT |
195 | elsif xhtml_enabled? |
196 | if request.user_agent =~ /Validator/ or request.env.include?('HTTP_ACCEPT') && |
197 | Mime::Type.parse(request.env["HTTP_ACCEPT"]).include?(Mime::XHTML) |
198 | response.content_type = Mime::XHTML |
199 | elsif request.user_agent =~ /MathPlayer/ |
200 | response.charset = nil |
201 | response.content_type = Mime::XHTML |
202 | response.extend(MathPlayerHack) |
203 | else |
204 | response.content_type = Mime::HTML |
205 | end |
206 | else |
207 | response.content_type = Mime::HTML |
208 | end |
209 | end |
210 | |
211 | def set_robots_metatag |
212 | if controller_name == 'wiki' and %w(show published s5).include? action_name and !(params[:mode] == 'diff') |
213 | @robots_metatag_value = 'index,follow' |
214 | else |
215 | @robots_metatag_value = 'noindex,nofollow' |
216 | end |
217 | end |
218 | |
219 | def setup_url_generator |
220 | PageRenderer.setup_url_generator(UrlGenerator.new(self)) |
221 | end |
222 | |
223 | def teardown_url_generator |
224 | PageRenderer.teardown_url_generator |
225 | end |
226 | |
227 | def wiki |
228 | self.class.wiki |
229 | end |
230 | |
231 | private |
232 | |
233 | def in_a_web? |
234 | not @web_name.nil? |
235 | end |
236 | |
237 | def authorization_needed? |
238 | not %w(login authenticate feeds published atom_with_headlines atom_with_content file blahtex_png).include?(action_name) |
239 | end |
240 | |
241 | def authorized? |
242 | @web.nil? or |
243 | @web.password.nil? or |
244 | cookies[CGI.escape(@web_name)] == @web.password or |
245 | password_check(params['password']) or |
246 | (@web.published? and action_name == 's5') |
247 | end |
248 | |
249 | def is_post |
250 | unless (request.post? || Rails.env.test?) |
251 | layout = 'error' |
252 | layout = false if %w(tex tex_list).include?(action_name) |
253 | headers['Allow'] = 'POST' |
254 | render(:status => 405, :text => 'You must use an HTTP POST', :layout => layout) |
255 | return false |
256 | end |
257 | return true |
258 | end |
259 | |
260 | end |
261 | |
262 | module Mime |
263 | # Fix HTML |
264 | #HTML = Type.new "text/html", :html, %w( application/xhtml+xml ) |
265 | self.class.const_set("HTML", Type.new("text/html", :html) ) |
266 | |
267 | # Add XHTML |
268 | XHTML = Type.new "application/xhtml+xml", :xhtml |
269 | |
270 | # Fix xhtml and html lookups |
271 | LOOKUP["text/html"] = HTML |
272 | LOOKUP["application/xhtml+xml"] = XHTML |
273 | end |
274 | |
275 | module MathPlayerHack |
276 | def charset=(encoding) |
277 | self.headers["Content-Type"] = "#{content_type || Mime::HTML}" |
278 | end |
279 | end |
280 | |
281 | module Instiki |
282 | module VERSION #:nodoc: |
283 | MAJOR = 0 |
284 | MINOR = 19 |
285 | TINY = 1 |
286 | SUFFIX = '(MML+)' |
287 | PRERELEASE = false |
288 | if PRERELEASE |
289 | STRING = [MAJOR, MINOR].join('.') + PRERELEASE + SUFFIX |
290 | else |
291 | STRING = [MAJOR, MINOR, TINY].join('.') + SUFFIX |
292 | end |
293 | end |
294 | end |
295 | |
296 | # Monkey patch, to make Hash#key work in Ruby 1.8 |
297 | class Hash |
298 | alias_method(:key, :index) unless method_defined?(:key) |
299 | end |
300 | |
301 | # Monkey patch, to ensure ActionCache doesn't muck with the content-type header. |
302 | module ActionController #:nodoc: |
303 | module Caching |
304 | module Actions |
305 | class ActionCacheFilter |
306 | private |
307 | def set_content_type!(controller, extension) |
308 | return |
309 | end |
310 | end |
311 | end |
312 | end |
313 | end |