aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/application_controller.rb59
-rw-r--r--app/controllers/general_controller.rb6
-rw-r--r--app/controllers/request_controller.rb12
-rw-r--r--app/controllers/track_controller.rb2
-rw-r--r--app/controllers/user_controller.rb4
-rw-r--r--app/mailers/request_mailer.rb2
-rw-r--r--app/models/foi_attachment.rb7
-rw-r--r--app/models/incoming_message.rb53
-rw-r--r--app/views/admin_censor_rule/new.html.erb2
-rw-r--r--app/views/public_body/_search_ahead.html.erb5
-rw-r--r--app/views/request/_hidden_correspondence.html.erb2
-rw-r--r--app/views/request/_sidebar.html.erb4
-rw-r--r--app/views/request/select_authority.html.erb21
-rw-r--r--app/views/user/set_crop_profile_photo.html.erb2
14 files changed, 91 insertions, 90 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 029b536ec..2615b61f2 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -12,6 +12,11 @@ require 'open-uri'
class ApplicationController < ActionController::Base
class PermissionDenied < StandardError
end
+ class RouteNotFound < StandardError
+ end
+ # assign our own handler method for non-local exceptions
+ rescue_from Exception, :with => :render_exception
+
# Standard headers, footers and navigation for whole site
layout "default"
include FastGettext::Translation # make functions like _, n_, N_ etc available)
@@ -111,55 +116,35 @@ class ApplicationController < ActionController::Base
end
end
- # Override default error handler, for production sites.
- def rescue_action_in_public(exception)
- # Looks for before_filters called something like `set_view_paths_{themename}`. These
- # are set by the themes.
- # Normally, this is called by the theme itself in a
- # :before_filter, but when there's an error, this doesn't
- # happen. By calling it here, we can ensure error pages are
- # still styled according to the theme.
- ActionController::Base.before_filters.select{|f| f.to_s =~ /set_view_paths/}.each do |f|
- self.send(f)
- end
- # Make sure expiry time for session is set (before_filters are
- # otherwise missed by this override)
- session_remember_me
+ def render_exception(exception)
- # Make sure the locale is set correctly too
- set_gettext_locale
+ # In development, or the admin interface, or for a local request, let Rails handle the exception
+ # with its stack trace templates. Local requests in testing are a special case so that we can
+ # test this method - there we use consider_all_requests_local to control behaviour.
+ if Rails.application.config.consider_all_requests_local || local_request? ||
+ (request.local? && !Rails.env.test?)
+ raise exception
+ end
+ @exception_backtrace = exception.backtrace.join("\n")
+ @exception_class = exception.class.to_s
+ @exception_message = exception.message
case exception
- when ActiveRecord::RecordNotFound, ActionController::UnknownAction, ActionController::RoutingError
+ when ActiveRecord::RecordNotFound, RouteNotFound
@status = 404
when PermissionDenied
@status = 403
else
+ message = "\n#{@exception_class} (#{@exception_message}):\n"
+ backtrace = Rails.backtrace_cleaner.clean(exception.backtrace, :silent)
+ message << " " << backtrace.join("\n ")
+ Rails.logger.fatal("#{message}\n\n")
+ ExceptionNotifier::Notifier.exception_notification(request.env, exception).deliver
@status = 500
- notify_about_exception exception
end
- # Display user appropriate error message
- @exception_backtrace = exception.backtrace.join("\n")
- @exception_class = exception.class.to_s
- @exception_message = exception.message
render :template => "general/exception_caught", :status => @status
end
- # FIXME: This was disabled during the Rails 3 upgrade as this is now handled by Rack
- # # For development sites.
- # alias original_rescue_action_locally rescue_action_locally
- # def rescue_action_locally(exception)
- # # Make sure expiry time for session is set (before_filters are
- # # otherwise missed by this override)
- # session_remember_me
-
- # # Make sure the locale is set correctly too
- # set_gettext_locale
-
- # # Display default, detailed error for developers
- # original_rescue_action_locally(exception)
- # end
-
def local_request?
false
end
diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb
index 0df685829..9d0f91dda 100644
--- a/app/controllers/general_controller.rb
+++ b/app/controllers/general_controller.rb
@@ -222,5 +222,11 @@ class GeneralController < ApplicationController
@locale = self.locale_from_params()
render(:layout => false, :content_type => 'text/css')
end
+
+ # Handle requests for non-existent URLs - will be handled by ApplicationController::render_exception
+ def not_found
+ raise RouteNotFound
+ end
+
end
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index a0f88096e..b8ccdf926 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -5,7 +5,6 @@
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: hello@mysociety.org; WWW: http://www.mysociety.org/
-require 'alaveteli_file_types'
require 'zip/zip'
require 'open-uri'
@@ -722,7 +721,7 @@ class RequestController < ApplicationController
yield
- if params[:skip_cache].nil?
+ if params[:skip_cache].nil? && response.status == 200
# write it to the fileystem ourselves, so is just a plain file. (The
# various fragment cache functions using Ruby Marshall to write the file
# which adds a header, so isnt compatible with images that have been
@@ -737,6 +736,7 @@ class RequestController < ApplicationController
def get_attachment
get_attachment_internal(false)
+ return unless @attachment
# Prevent spam to magic request address. Note that the binary
# subsitution method used depends on the content type
@@ -756,6 +756,7 @@ class RequestController < ApplicationController
raise ActiveRecord::RecordNotFound.new("Attachment HTML not found.")
end
get_attachment_internal(true)
+ return unless @attachment
# images made during conversion (e.g. images in PDF files) are put in the cache directory, so
# the same cache code in cache_attachments above will display them.
@@ -802,8 +803,11 @@ class RequestController < ApplicationController
# check permissions
raise "internal error, pre-auth filter should have caught this" if !@info_request.user_can_view?(authenticated_user)
- @attachment = IncomingMessage.get_attachment_by_url_part_number(@incoming_message.get_attachments_for_display, @part_number)
- raise ActiveRecord::RecordNotFound.new("attachment not found part number " + @part_number.to_s + " incoming_message " + @incoming_message.id.to_s) if @attachment.nil?
+ @attachment = IncomingMessage.get_attachment_by_url_part_number_and_filename(@incoming_message.get_attachments_for_display, @part_number, @original_filename)
+ # If we can't find the right attachment, redirect to the incoming message:
+ unless @attachment
+ return redirect_to incoming_message_url(@incoming_message), :status => 303
+ end
# check filename in URL matches that in database (use a censor rule if you want to change a filename)
raise ActiveRecord::RecordNotFound.new("please use same filename as original file has, display: '" + @attachment.display_filename + "' old_display: '" + @attachment.old_display_filename + "' original: '" + @original_filename + "'") if @attachment.display_filename != @original_filename && @attachment.old_display_filename != @original_filename
diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb
index 9076148c4..40e82e7a4 100644
--- a/app/controllers/track_controller.rb
+++ b/app/controllers/track_controller.rb
@@ -157,7 +157,7 @@ class TrackController < ApplicationController
format.json { render :json => @xapian_object.results.map { |r| r[:model].json_for_api(true,
lambda { |t| view_context.highlight_and_excerpt(t, @xapian_object.words_to_highlight, 150) }
) } }
- format.any { render :template => 'track/atom_feed.atom', :layout => false, :content_type => :atom }
+ format.any { render :template => 'track/atom_feed.atom', :layout => false, :content_type => 'application/atom+xml' }
end
end
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
index dca3cda17..b7912b528 100644
--- a/app/controllers/user_controller.rb
+++ b/app/controllers/user_controller.rb
@@ -527,7 +527,7 @@ class UserController < ApplicationController
def get_draft_profile_photo
profile_photo = ProfilePhoto.find(params[:id])
response.content_type = "image/png"
- render_for_text(profile_photo.data)
+ render :text => profile_photo.data
end
# actual profile photo of a user
@@ -542,7 +542,7 @@ class UserController < ApplicationController
end
response.content_type = "image/png"
- render_for_text(@display_user.profile_photo.data)
+ render :text => @display_user.profile_photo.data
end
# Change about me text on your profile page
diff --git a/app/mailers/request_mailer.rb b/app/mailers/request_mailer.rb
index 3eb89c660..4dbce6738 100644
--- a/app/mailers/request_mailer.rb
+++ b/app/mailers/request_mailer.rb
@@ -4,8 +4,6 @@
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: hello@mysociety.org; WWW: http://www.mysociety.org/
-require 'alaveteli_file_types'
-
class RequestMailer < ApplicationMailer
# Used when an FOI officer uploads a response from their web browser - this is
# the "fake" email used to store in the same format in the database as if they
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index fcde379e0..0340f2b83 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -71,7 +71,12 @@ class FoiAttachment < ActiveRecord::Base
tries = 0
delay = 1
begin
- @cached_body = File.open(self.filepath, "rb" ).read
+ binary_data = File.open(self.filepath, "rb" ).read
+ if self.content_type =~ /^text/
+ @cached_body = convert_string_to_utf8_or_binary(binary_data, 'UTF-8')
+ else
+ @cached_body = binary_data
+ end
rescue Errno::ENOENT
# we've lost our cached attachments for some reason. Reparse them.
if tries > BODY_MAX_TRIES
diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb
index c914edb7e..f959a8799 100644
--- a/app/models/incoming_message.rb
+++ b/app/models/incoming_message.rb
@@ -31,12 +31,9 @@
# Move some of the (e.g. quoting) functions here into rblib, as they feel
# general not specific to IncomingMessage.
-require 'alaveteli_file_types'
require 'htmlentities'
require 'rexml/document'
require 'zip/zip'
-require 'mapi/msg'
-require 'mapi/convert'
require 'iconv' unless RUBY_VERSION >= '1.9'
class IncomingMessage < ActiveRecord::Base
@@ -132,6 +129,7 @@ class IncomingMessage < ActiveRecord::Base
end
self.valid_to_reply_to = self._calculate_valid_to_reply_to
self.last_parsed = Time.now
+ self.foi_attachments reload=true
self.save!
end
end
@@ -173,15 +171,29 @@ class IncomingMessage < ActiveRecord::Base
super
end
- # And look up by URL part number to get an attachment
+ # And look up by URL part number and display filename to get an attachment
# XXX relies on extract_attachments calling MailHandler.ensure_parts_counted
- def self.get_attachment_by_url_part_number(attachments, found_url_part_number)
- attachments.each do |a|
- if a.url_part_number == found_url_part_number
- return a
+ # The filename here is passed from the URL parameter, so it's the
+ # display_filename rather than the real filename.
+ def self.get_attachment_by_url_part_number_and_filename(attachments, found_url_part_number, display_filename)
+ attachment_by_part_number = attachments.detect { |a| a.url_part_number == found_url_part_number }
+ if attachment_by_part_number && attachment_by_part_number.display_filename == display_filename
+ # Then the filename matches, which is fine:
+ attachment_by_part_number
+ else
+ # Otherwise if the URL part number and filename don't
+ # match - this is probably due to a reparsing of the
+ # email. In that case, try to find a unique matching
+ # filename from any attachment.
+ attachments_by_filename = attachments.select { |a|
+ a.display_filename == display_filename
+ }
+ if attachments_by_filename.length == 1
+ attachments_by_filename[0]
+ else
+ nil
end
end
- return nil
end
# Converts email addresses we know about into textual descriptions of them
@@ -556,9 +568,11 @@ class IncomingMessage < ActiveRecord::Base
text
end
- # Returns part which contains main body text, or nil if there isn't one
- def get_main_body_text_part
- leaves = self.foi_attachments
+ # Returns part which contains main body text, or nil if there isn't one,
+ # from a set of foi_attachments. If the leaves parameter is empty or not
+ # supplied, uses its own foi_attachments.
+ def get_main_body_text_part(leaves=[])
+ leaves = self.foi_attachments if leaves.empty?
# Find first part which is text/plain or text/html
# (We have to include HTML, as increasingly there are mail clients that
@@ -592,6 +606,7 @@ class IncomingMessage < ActiveRecord::Base
# nil in this case)
return p
end
+
# Returns attachments that are uuencoded in main body part
def _uudecode_and_save_attachments(text)
# Find any uudecoded things buried in it, yeuchly
@@ -645,12 +660,16 @@ class IncomingMessage < ActiveRecord::Base
attachment = self.foi_attachments.find_or_create_by_hexdigest(attrs[:hexdigest])
attachment.update_attributes(attrs)
attachment.save!
- attachments << attachment.id
+ attachments << attachment
end
+
# Reload to refresh newly created foi_attachments
self.reload
- main_part = get_main_body_text_part
+ # get the main body part from the set of attachments we just created,
+ # not from the self.foi_attachments association - some of the total set of
+ # self.foi_attachments may now be obsolete
+ main_part = get_main_body_text_part(attachments)
# we don't use get_main_body_text_internal, as we want to avoid charset
# conversions, since /usr/bin/uudecode needs to deal with those.
# e.g. for https://secure.mysociety.org/admin/foi/request/show_raw_email/24550
@@ -661,12 +680,14 @@ class IncomingMessage < ActiveRecord::Base
c += 1
uudecode_attachment.url_part_number = c
uudecode_attachment.save!
- attachments << uudecode_attachment.id
+ attachments << uudecode_attachment
end
end
+ attachment_ids = attachments.map{ |attachment| attachment.id }
# now get rid of any attachments we no longer have
- FoiAttachment.destroy_all("id NOT IN (#{attachments.join(',')}) AND incoming_message_id = #{self.id}")
+ FoiAttachment.destroy_all(["id NOT IN (?) AND incoming_message_id = ?",
+ attachment_ids, self.id])
end
# Returns body text as HTML with quotes flattened, and emails removed.
diff --git a/app/views/admin_censor_rule/new.html.erb b/app/views/admin_censor_rule/new.html.erb
index 1694308f3..77d22990c 100644
--- a/app/views/admin_censor_rule/new.html.erb
+++ b/app/views/admin_censor_rule/new.html.erb
@@ -1,4 +1,4 @@
-<% @title = 'New censor rule' %>
+<% @title = _('New censor rule') %>
<h1><%=@title%></h1>
diff --git a/app/views/public_body/_search_ahead.html.erb b/app/views/public_body/_search_ahead.html.erb
index b1af2464d..3d1dc8f93 100644
--- a/app/views/public_body/_search_ahead.html.erb
+++ b/app/views/public_body/_search_ahead.html.erb
@@ -1,4 +1,4 @@
-<div>
+
<% if !@xapian_requests.nil? %>
<% if @xapian_requests.results.size > 0 %>
<h3><%= _('Top search results:') %></h3>
@@ -10,12 +10,11 @@
<% end %>
<div id="authority_search_ahead_results">
<% for result in @xapian_requests.results %>
- <%= render :partial => 'body_listing_single', :locals => { :public_body => result[:model] } %>
+ <%= render :partial => 'public_body/body_listing_single', :locals => { :public_body => result[:model] } %>
<% end %>
</div>
<%= will_paginate WillPaginate::Collection.new(@page, @per_page, @xapian_requests.matches_estimated), :params => {:controller=>"request", :action => "select_authority"} %>
<% end %>
-</div>
diff --git a/app/views/request/_hidden_correspondence.html.erb b/app/views/request/_hidden_correspondence.html.erb
index 5ee9a4724..4c06f1f48 100644
--- a/app/views/request/_hidden_correspondence.html.erb
+++ b/app/views/request/_hidden_correspondence.html.erb
@@ -15,7 +15,7 @@
<div class="correspondence" id="outgoing-<%=outgoing_message.id.to_s%>">
<p>
<%= _('This outgoing message has been hidden. See annotations to
- find out why. If you are the requester, then you may <a href="{{url}}">sign in</a> to view the response.', :url => signin_url(:r => request.fullpath).html_safe) %>
+ find out why. If you are the requester, then you may <a href="{{url}}">sign in</a> to view the response.', :url => signin_url(:r => request.fullpath).html_safe) %>
</p>
</div>
<% elsif info_request_event.event_type == 'comment' %>
diff --git a/app/views/request/_sidebar.html.erb b/app/views/request/_sidebar.html.erb
index e0b01924d..4bc8826fd 100644
--- a/app/views/request/_sidebar.html.erb
+++ b/app/views/request/_sidebar.html.erb
@@ -36,8 +36,8 @@
<h2><%= _("Act on what you've learnt") %></h2>
<div class="act_link">
- <% tweet_link = "https://twitter.com/share?url=#{h(request.url)}&via=#{h(AlaveteliConfiguration::twitter_username)}&text='#{h(@info_request.title)}'&related=#{_('alaveteli_foi:The software that runs {{site_name}}', :site_name => h(site_name))}" %>
- <%= link_to tweet_link do %>
+ <% tweet_link = "https://twitter.com/share?" + {:url => request.url, :via => AlaveteliConfiguration::twitter_username, :text => "'#{@info_request.title}'", :related => _('alaveteli_foi:The software that runs {{site_name}}', :site_name => site_name)}.to_query %>
+ <% link_to tweet_link do %>
<%= image_tag "twitter-16.png", :alt => "twitter icon" %>
<% end %>
<%= link_to _("Tweet this request"), tweet_link %>
diff --git a/app/views/request/select_authority.html.erb b/app/views/request/select_authority.html.erb
index c01e2776f..75c51fc57 100644
--- a/app/views/request/select_authority.html.erb
+++ b/app/views/request/select_authority.html.erb
@@ -42,26 +42,9 @@
<%= submit_tag _('Search') %>
</div>
<% end %>
- <div id="typeahead_response">
- <% if !@xapian_requests.nil? %>
- <% if @xapian_requests.results.size > 0 %>
- <h3><%= _('Top search results:') %></h3>
- <p>
- <%= _('Select one to see more information about the authority.')%>
- </p>
- <% else %>
- <h3><%= _('No results found.') %></h3>
- <% end %>
- <div id="authority_search_ahead_results">
- <% for result in @xapian_requests.results %>
- <%= render :partial => 'public_body/body_listing_single', :locals => { :public_body => result[:model] } %>
- <% end %>
- </div>
-
- <% end %>
-
-
+ <div id="typeahead_response">
+ <%= render :partial => 'public_body/search_ahead' %>
</div>
</div>
diff --git a/app/views/user/set_crop_profile_photo.html.erb b/app/views/user/set_crop_profile_photo.html.erb
index fea7ccab8..0a22d36dc 100644
--- a/app/views/user/set_crop_profile_photo.html.erb
+++ b/app/views/user/set_crop_profile_photo.html.erb
@@ -37,7 +37,7 @@
<p>
<%= hidden_field_tag 'submitted_crop_profile_photo', 1 %>
- <%= submit_tag _("Done") + " &gt;&gt;" %>
+ <%= submit_tag _("Done &gt;&gt;") %>
</p>
<% end %>