diff options
Diffstat (limited to 'app')
31 files changed, 361 insertions, 646 deletions
diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index 3e574b10f..c7c8d4972 100644 --- a/app/controllers/admin_request_controller.rb +++ b/app/controllers/admin_request_controller.rb @@ -207,8 +207,7 @@ class AdminRequestController < AdminController end raw_email_data = incoming_message.raw_email.data - mail = TMail::Mail.parse(raw_email_data) - mail.base64_decode + mail = MailHandler.mail_from_raw_email(raw_email_data) destination_request.receive(mail, raw_email_data, true) incoming_message_id = incoming_message.id @@ -278,7 +277,7 @@ class AdminRequestController < AdminController if params[:incoming_message_id] incoming_message = IncomingMessage.find(params[:incoming_message_id]) - email = incoming_message.mail.from_addrs[0].address + email = incoming_message.from_email name = incoming_message.safe_mail_from || info_request.public_body.name else email = info_request.public_body.request_email @@ -313,12 +312,12 @@ class AdminRequestController < AdminController @raw_email = RawEmail.find(params[:id]) # For the holding pen, try to guess where it should be ... @holding_pen = false - if (@raw_email.incoming_message.info_request == InfoRequest.holding_pen_request && !@raw_email.incoming_message.mail.from_addrs.nil? && @raw_email.incoming_message.mail.from_addrs.size > 0) + if (@raw_email.incoming_message.info_request == InfoRequest.holding_pen_request && !@raw_email.incoming_message.empty_from_field?) @holding_pen = true # 1. Use domain of email to try and guess which public body it # is associated with, so we can display that. - email = @raw_email.incoming_message.mail.from_addrs[0].spec + email = @raw_email.incoming_message.from_email domain = PublicBody.extract_domain_from_email(email) if domain.nil? diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index aa5e85db3..15fb4f5f9 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -1,30 +1,30 @@ class ApiController < ApplicationController before_filter :check_api_key - + def show_request @request = InfoRequest.find(params[:id]) raise PermissionDenied if @request.public_body_id != @public_body.id - + @request_data = { :id => @request.id, :url => make_url("request", @request.url_title), :title => @request.title, - + :created_at => @request.created_at, :updated_at => @request.updated_at, - + :status => @request.calculate_status, - + :public_body_url => make_url("body", @request.public_body.url_name), :requestor_url => make_url("user", @request.user.url_name), :request_email => @request.incoming_email, - + :request_text => @request.last_event_forming_initial_request.outgoing_message.body, } - + render :json => @request_data end - + def create_request json = ActiveSupport::JSON.decode(params[:request_json]) request = InfoRequest.new( @@ -34,7 +34,7 @@ class ApiController < ApplicationController :external_user_name => json["external_user_name"], :external_url => json["external_url"] ) - + outgoing_message = OutgoingMessage.new( :status => 'ready', :message_type => 'initial_request', @@ -44,7 +44,7 @@ class ApiController < ApplicationController :info_request => request ) request.outgoing_messages << outgoing_message - + # Return an error if the request is invalid # (Can this ever happen?) if !request.valid? @@ -53,7 +53,7 @@ class ApiController < ApplicationController } return end - + # Save the request, and add the corresponding InfoRequestEvent request.save! request.log_event("sent", @@ -62,69 +62,69 @@ class ApiController < ApplicationController :outgoing_message_id => outgoing_message.id, :smtp_message_id => nil ) - + # Return the URL and ID number. render :json => { 'url' => make_url("request", request.url_title), 'id' => request.id } - + end - + def add_correspondence request = InfoRequest.find_by_id(params[:id]) if request.nil? render :json => { "errors" => ["Could not find request #{params[:id]}"] }, :status => 404 return end - + json = ActiveSupport::JSON.decode(params[:correspondence_json]) attachments = params[:attachments] - + direction = json["direction"] body = json["body"] sent_at_str = json["sent_at"] - + errors = [] - + if !request.is_external? render :json => { "errors" => ["Request #{params[:id]} cannot be updated using the API"] }, :status => 500 return end - + if request.public_body_id != @public_body.id render :json => { "errors" => ["You do not own request #{params[:id]}"] }, :status => 500 return end - + if !["request", "response"].include?(direction) errors << "The direction parameter must be 'request' or 'response'" end - + if body.nil? errors << "The 'body' is missing" elsif body.empty? errors << "The 'body' is empty" end - + begin sent_at = Time.iso8601(sent_at_str) rescue ArgumentError errors << "Failed to parse 'sent_at' field as ISO8601 time: #{sent_at_str}" end - + if direction == "request" && !attachments.nil? errors << "You cannot attach files to messages in the 'request' direction" end - + if !errors.empty? render :json => { "errors" => errors }, :status => 500 return end - + if direction == "request" # In the 'request' direction, i.e. what we (Alaveteli) regard as outgoing - + outgoing_message = OutgoingMessage.new( :info_request => request, :status => 'ready', @@ -154,19 +154,19 @@ class ApiController < ApplicationController :filename => filename ) end - + mail = RequestMailer.create_external_response(request, body, sent_at, attachment_hashes) request.receive(mail, mail.encoded, true) end render :json => { 'url' => make_url("request", request.url_title), - } + } end - + def body_request_events feed_type = params[:feed_type] raise PermissionDenied.new("#{@public_body.id} != #{params[:id]}") if @public_body.id != params[:id].to_i - + since_date_str = params[:since_date] if since_date_str.nil? @events = InfoRequestEvent.find_by_sql([ @@ -213,7 +213,7 @@ class ApiController < ApplicationController @event_data = [] @events.each do |event| break if event.id == @since_event_id - + request = event.info_request this_event = { :request_id => request.id, @@ -224,13 +224,13 @@ class ApiController < ApplicationController :request_email => request.incoming_email, :title => request.title, :body => event.outgoing_message.body, - + :user_name => request.user_name, } if request.user this_event[:user_url] = main_url(user_url(request.user)) end - + @event_data.push(this_event) end render :json => @event_data @@ -238,14 +238,14 @@ class ApiController < ApplicationController raise ActiveRecord::RecordNotFound.new("Unrecognised feed type: #{feed_type}") end end - + protected def check_api_key - raise "Missing required parameter 'k'" if params[:k].nil? + raise PermissionDenied.new("Missing required parameter 'k'") if params[:k].nil? @public_body = PublicBody.find_by_api_key(params[:k].gsub(' ', '+')) raise PermissionDenied if @public_body.nil? end - + private def make_url(*args) "http://" + Configuration::domain + "/" + args.join("/") diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b707ae878..a946526b8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -54,10 +54,15 @@ class ApplicationController < ActionController::Base end def set_gettext_locale + if Configuration::include_default_locale_in_urls == false + params_locale = params[:locale] ? params[:locale] : I18n.default_locale + else + params_locale = params[:locale] + end if Configuration::use_default_browser_language - requested_locale = params[:locale] || session[:locale] || cookies[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] || I18n.default_locale + requested_locale = params_locale || session[:locale] || cookies[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] || I18n.default_locale else - requested_locale = params[:locale] || session[:locale] || cookies[:locale] || I18n.default_locale + requested_locale = params_locale || session[:locale] || cookies[:locale] || I18n.default_locale end requested_locale = FastGettext.best_locale_in(requested_locale) session[:locale] = FastGettext.set_locale(requested_locale) @@ -117,17 +122,14 @@ class ApplicationController < ActionController::Base # Override default error handler, for production sites. def rescue_action_in_public(exception) - # Call `set_view_paths` from the theme, if it exists. + # 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. - begin - set_view_paths - rescue NameError => e - if !(e.message =~ /undefined local variable or method `set_view_paths'/) - raise - end + 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) diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb index 0cde238cd..3ba636e29 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -226,12 +226,6 @@ class GeneralController < ApplicationController redirect_to request_url(info_request) end - # For debugging - def fai_test - sleep 10 - render :text => "awake\n" - end - def custom_css long_cache @locale = self.locale_from_params() diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ab953cb25..6411cf27e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -77,25 +77,6 @@ module ApplicationHelper return LanguageNames::get_language_name(locale) end - # Use our own algorithm for finding path of cache - def foi_cache(name = {}, options = nil, &block) - if @controller.perform_caching - key = name.merge(:only_path => true) - key_path = @controller.foi_fragment_cache_path(key) - - if @controller.foi_fragment_cache_exists?(key_path) - cached = @controller.foi_fragment_cache_read(key_path) - output_buffer.concat(cached) - return - end - - pos = output_buffer.length - content = block.call - @controller.foi_fragment_cache_write(key_path, output_buffer[pos..-1]) - else - block.call - end - end # (unfortunately) ugly way of getting id of generated form element # ids # see http://chrisblunt.com/2009/10/12/rails-getting-the-id-of-form-fields-inside-a-fields_for-block/ @@ -131,5 +112,12 @@ module ApplicationHelper return "#{exact_date} (#{ago_text})" end + # Note that if the admin interface is proxied via another server, we can't + # rely on a sesssion being shared between the front end and admin interface, + # so need to check the status of the user. + def is_admin? + return !session[:using_admin].nil? || (!@user.nil? && @user.super?) + end + end diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index 994da0e87..030fab20b 100755 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -255,9 +255,11 @@ module LinkToHelper # Basic date format def simple_date(date) + date = date.in_time_zone.to_date unless date.is_a? Date + date_format = _("simple_date_format") date_format = :long if date_format == "simple_date_format" - return I18n.l(date.to_date, :format => date_format) + return I18n.l(date, :format => date_format) end def simple_time(date) diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb index a40898aef..2f8a9ab04 100644 --- a/app/models/foi_attachment.rb +++ b/app/models/foi_attachment.rb @@ -38,7 +38,7 @@ class FoiAttachment < ActiveRecord::Base BODY_MAX_DELAY = 5 def directory - rails_env = ENV['RAILS_ENV'] + rails_env = Rails.env if rails_env.nil? || rails_env.empty? raise "$RAILS_ENV is not set" end @@ -67,9 +67,22 @@ class FoiAttachment < ActiveRecord::Base file.write d } update_display_size! + encode_cached_body! @cached_body = d end + # If the original mail part had a charset, it's some kind of string, so assume that + # it should be handled as a string in the stated charset, not a bytearray, and then + # convert it our default encoding. For ruby 1.8 this is a noop. + def encode_cached_body! + if RUBY_VERSION.to_f >= 1.9 + if charset + @cached_body.force_encoding(charset) + @cached_body = @cached_body.encode(Encoding.default_internal, charset) + end + end + end + def body if @cached_body.nil? tries = 0 @@ -90,6 +103,7 @@ class FoiAttachment < ActiveRecord::Base self.incoming_message.parse_raw_email!(force) retry end + encode_cached_body! end return @cached_body end @@ -310,31 +324,41 @@ class FoiAttachment < ActiveRecord::Base # the extractions will also produce image files, which go in the # current directory, so change to the directory the function caller # wants everything in - Dir.chdir(dir) do - tempfile = Tempfile.new('foiextract', '.') - tempfile.print self.body - tempfile.flush - - html = nil - if self.content_type == 'application/pdf' - # We set a timeout here, because pdftohtml can spiral out of control - # on some PDF files and we don’t want to crash the whole server. - html = AlaveteliExternalCommand.run("pdftohtml", "-nodrm", "-zoom", "1.0", "-stdout", "-enc", "UTF-8", "-noframes", tempfile.path, :timeout => 30) - elsif self.content_type == 'application/rtf' - html = AlaveteliExternalCommand.run("unrtf", "--html", tempfile.path, :timeout => 120) - end - - if html.nil? - if self.has_google_docs_viewer? - html = '' # force error and using Google docs viewer + + html = nil + if ['application/pdf', 'application/rtf'].include?(self.content_type) + text = self.body + Dir.chdir(dir) do + if RUBY_VERSION.to_f >= 1.9 + tempfile = Tempfile.new('foiextract', '.', :encoding => text.encoding) else - raise "No HTML conversion available for type " + self.content_type + tempfile = Tempfile.new('foiextract', '.') end - end + tempfile.print text + tempfile.flush + - tempfile.close - tempfile.delete + if self.content_type == 'application/pdf' + # We set a timeout here, because pdftohtml can spiral out of control + # on some PDF files and we don't want to crash the whole server. + html = AlaveteliExternalCommand.run("pdftohtml", "-nodrm", "-zoom", "1.0", "-stdout", "-enc", "UTF-8", "-noframes", tempfile.path, :timeout => 30) + elsif self.content_type == 'application/rtf' + html = AlaveteliExternalCommand.run("unrtf", "--html", tempfile.path, :timeout => 120) + end + + tempfile.close + tempfile.delete + end end + if html.nil? + if self.has_google_docs_viewer? + html = '' # force error and using Google docs viewer + else + raise "No HTML conversion available for type " + self.content_type + end + end + + # We need to look at: # a) Any error code diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 60828e179..a02d2456a 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -38,14 +38,6 @@ require 'zip/zip' require 'mapi/msg' require 'mapi/convert' -# Monkeypatch! Adding some extra members to store extra info in. -module TMail - class Mail - attr_accessor :url_part_number - attr_accessor :rfc822_attachment # when a whole email message is attached as text - attr_accessor :within_rfc822_attachment # for parts within a message attached as text (for getting subject mainly) - end -end class IncomingMessage < ActiveRecord::Base belongs_to :info_request @@ -70,34 +62,35 @@ class IncomingMessage < ActiveRecord::Base 'application/zip' => 1, } - # Return the structured TMail::Mail object - # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ + # Return a cached structured mail object def mail(force = nil) if (!force.nil? || @mail.nil?) && !self.raw_email.nil? - # Hack round bug in TMail's MIME decoding. - # Report of TMail bug: - # http://rubyforge.org/tracker/index.php?func=detail&aid=21810&group_id=4512&atid=17370 - copy_of_raw_data = self.raw_email.data.gsub(/; boundary=\s+"/im,'; boundary="') - - @mail = TMail::Mail.parse(copy_of_raw_data) - @mail.base64_decode + @mail = MailHandler.mail_from_raw_email(self.raw_email.data) end @mail end - # Returns the name of the person the incoming message is from, or nil if - # there isn't one or if there is only an email address. XXX can probably - # remove from_name_if_present (which is a monkey patch) by just calling - # .from_addrs[0].name here instead? + def empty_from_field? + self.mail.from_addrs.nil? || self.mail.from_addrs.size == 0 + end + + def from_email + MailHandler.get_from_address(self.mail) + end + + def addresses + MailHandler.get_all_addresses(self.mail) + end + + def message_id + self.mail.message_id + end # Return false if for some reason this is a message that we shouldn't let them reply to def _calculate_valid_to_reply_to # check validity of email - if self.mail.from_addrs.nil? || self.mail.from_addrs.size == 0 - return false - end - email = self.mail.from_addrs[0].spec - if !MySociety::Validate.is_valid_email(email) + email = self.from_email + if email.nil? || !MySociety::Validate.is_valid_email(email) return false end @@ -107,13 +100,13 @@ class IncomingMessage < ActiveRecord::Base prefix = email prefix =~ /^(.*)@/ prefix = $1 - if !prefix.nil? && prefix.downcase.match(/^(postmaster|mailer-daemon|auto_reply|donotreply|no.reply)$/) + if !prefix.nil? && prefix.downcase.match(/^(postmaster|mailer-daemon|auto_reply|do.?not.?reply|no.reply)$/) return false end - if !self.mail['return-path'].nil? && self.mail['return-path'].addr == "<>" + if MailHandler.empty_return_path?(self.mail) return false end - if !self.mail['auto-submitted'].nil? + if !MailHandler.get_auto_submitted(self.mail).nil? return false end return true @@ -131,13 +124,10 @@ class IncomingMessage < ActiveRecord::Base self.extract_attachments! self.sent_at = self.mail.date || self.created_at self.subject = self.mail.subject - # XXX can probably remove from_name_if_present (which is a - # monkey patch) by just calling .from_addrs[0].name here - # instead? - self.mail_from = self.mail.from_name_if_present - begin - self.mail_from_domain = PublicBody.extract_domain_from_email(self.mail.from_addrs[0].spec) - rescue NoMethodError + self.mail_from = MailHandler.get_from_name(self.mail) + if self.from_email + self.mail_from_domain = PublicBody.extract_domain_from_email(self.from_email) + else self.mail_from_domain = "" end self.valid_to_reply_to = self._calculate_valid_to_reply_to @@ -183,54 +173,8 @@ class IncomingMessage < ActiveRecord::Base super end - # Number the attachments in depth first tree order, for use in URLs. - # XXX This fills in part.rfc822_attachment and part.url_part_number within - # all the parts of the email (see TMail monkeypatch above for how these - # attributes are added). ensure_parts_counted must be called before using - # the attributes. - def ensure_parts_counted - @count_parts_count = 0 - _count_parts_recursive(self.mail) - # we carry on using these numeric ids for attachments uudecoded from within text parts - @count_first_uudecode_count = @count_parts_count - end - def _count_parts_recursive(part) - if part.multipart? - part.parts.each do |p| - _count_parts_recursive(p) - end - else - part_filename = TMail::Mail.get_part_file_name(part) - begin - if part.content_type == 'message/rfc822' - # An email attached as text - # e.g. http://www.whatdotheyknow.com/request/64/response/102 - part.rfc822_attachment = TMail::Mail.parse(part.body) - elsif part.content_type == 'application/vnd.ms-outlook' || part_filename && AlaveteliFileTypes.filename_to_mimetype(part_filename) == 'application/vnd.ms-outlook' - # An email attached as an Outlook file - # e.g. http://www.whatdotheyknow.com/request/chinese_names_for_british_politi - msg = Mapi::Msg.open(StringIO.new(part.body)) - part.rfc822_attachment = TMail::Mail.parse(msg.to_mime.to_s) - elsif part.content_type == 'application/ms-tnef' - # A set of attachments in a TNEF file - part.rfc822_attachment = TNEF.as_tmail(part.body) - end - rescue - # If attached mail doesn't parse, treat it as text part - part.rfc822_attachment = nil - else - unless part.rfc822_attachment.nil? - _count_parts_recursive(part.rfc822_attachment) - end - end - if part.rfc822_attachment.nil? - @count_parts_count += 1 - part.url_part_number = @count_parts_count - end - end - end # And look up by URL part number to get an attachment - # XXX relies on extract_attachments calling ensure_parts_counted + # 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 @@ -451,105 +395,6 @@ class IncomingMessage < ActiveRecord::Base return text end - # Internal function - def _get_part_file_name(mail) - part_file_name = TMail::Mail.get_part_file_name(mail) - if part_file_name.nil? - return nil - end - part_file_name = part_file_name.dup - return part_file_name - end - - # (This risks losing info if the unchosen alternative is the only one to contain - # useful info, but let's worry about that another time) - def get_attachment_leaves - force = true - return _get_attachment_leaves_recursive(self.mail(force)) - end - def _get_attachment_leaves_recursive(curr_mail, within_rfc822_attachment = nil) - leaves_found = [] - if curr_mail.multipart? - if curr_mail.parts.size == 0 - raise "no parts on multipart mail" - end - - if curr_mail.sub_type == 'alternative' - # Choose best part from alternatives - best_part = nil - # Take the last text/plain one, or else the first one - curr_mail.parts.each do |m| - if not best_part - best_part = m - elsif m.content_type == 'text/plain' - best_part = m - end - end - # Take an HTML one as even higher priority. (They tend - # to render better than text/plain, e.g. don't wrap links here: - # http://www.whatdotheyknow.com/request/amount_and_cost_of_freedom_of_in#incoming-72238 ) - curr_mail.parts.each do |m| - if m.content_type == 'text/html' - best_part = m - end - end - leaves_found += _get_attachment_leaves_recursive(best_part, within_rfc822_attachment) - else - # Add all parts - curr_mail.parts.each do |m| - leaves_found += _get_attachment_leaves_recursive(m, within_rfc822_attachment) - end - end - else - # XXX Yuck. this section alters various content_type's. That puts - # it into conflict with ensure_parts_counted which it has to be - # called both before and after. It will fail with cases of - # attachments of attachments etc. - charset = curr_mail.charset # save this, because overwriting content_type also resets charset - # Don't allow nil content_types - if curr_mail.content_type.nil? - curr_mail.content_type = 'application/octet-stream' - end - # PDFs often come with this mime type, fix it up for view code - if curr_mail.content_type == 'application/octet-stream' - part_file_name = self._get_part_file_name(curr_mail) - calc_mime = AlaveteliFileTypes.filename_and_content_to_mimetype(part_file_name, curr_mail.body) - if calc_mime - curr_mail.content_type = calc_mime - end - end - - # Use standard content types for Word documents etc. - curr_mail.content_type = normalise_content_type(curr_mail.content_type) - if curr_mail.content_type == 'message/rfc822' - ensure_parts_counted # fills in rfc822_attachment variable - if curr_mail.rfc822_attachment.nil? - # Attached mail didn't parse, so treat as text - curr_mail.content_type = 'text/plain' - end - end - if curr_mail.content_type == 'application/vnd.ms-outlook' || curr_mail.content_type == 'application/ms-tnef' - ensure_parts_counted # fills in rfc822_attachment variable - if curr_mail.rfc822_attachment.nil? - # Attached mail didn't parse, so treat as binary - curr_mail.content_type = 'application/octet-stream' - end - end - # If the part is an attachment of email - if curr_mail.content_type == 'message/rfc822' || curr_mail.content_type == 'application/vnd.ms-outlook' || curr_mail.content_type == 'application/ms-tnef' - ensure_parts_counted # fills in rfc822_attachment variable - leaves_found += _get_attachment_leaves_recursive(curr_mail.rfc822_attachment, curr_mail.rfc822_attachment) - else - # Store leaf - curr_mail.within_rfc822_attachment = within_rfc822_attachment - leaves_found += [curr_mail] - end - # restore original charset - curr_mail.charset = charset - end - return leaves_found - end - # Removes anything cached about the object in the database, and saves def clear_in_database_caches! self.cached_attachment_text_clipped = nil @@ -612,7 +457,8 @@ class IncomingMessage < ActiveRecord::Base text = "[ Email has no body, please see attachments ]" source_charset = "utf-8" else - text = part.body # by default, TMail converts to UTF8 in this call + # by default, the body (coming from an foi_attachment) should have been converted to utf-8 + text = part.body source_charset = part.charset if part.content_type == 'text/html' # e.g. http://www.whatdotheyknow.com/request/35/response/177 @@ -620,42 +466,31 @@ class IncomingMessage < ActiveRecord::Base # convert to text routine. Could instead call a # sanitize HTML one. - # If the text isn't UTF8, it means TMail had a problem + # If the text isn't UTF8, it means we had a problem # converting it (invalid characters, etc), and we # should instead tell elinks to respect the source # charset use_charset = "utf-8" - begin - text = Iconv.conv('utf-8', 'utf-8', text) - rescue Iconv::IllegalSequence - use_charset = source_charset - end - text = self.class._get_attachment_text_internal_one_file(part.content_type, text, use_charset) - end - end - - # If TMail can't convert text, it just returns it, so we sanitise it. - begin - # Test if it's good UTF-8 - text = Iconv.conv('utf-8', 'utf-8', text) - rescue Iconv::IllegalSequence - # Text looks like unlabelled nonsense, - # strip out anything that isn't UTF-8 - begin - source_charset = 'utf-8' if source_charset.nil? - text = Iconv.conv('utf-8//IGNORE', source_charset, text) + - _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]", - :site_name => Configuration::site_name) - rescue Iconv::InvalidEncoding, Iconv::IllegalSequence - if source_charset != "utf-8" - source_charset = "utf-8" - retry + if RUBY_VERSION.to_f >= 1.9 + begin + text.encode('utf-8') + rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError + use_charset = source_charset + end + else + begin + text = Iconv.conv('utf-8', 'utf-8', text) + rescue Iconv::IllegalSequence + use_charset = source_charset + end end + text = MailHandler.get_attachment_text_one_file(part.content_type, text, use_charset) end end + # If text hasn't been converted, we sanitise it. + text = _sanitize_text(text) # Fix DOS style linefeeds to Unix style ones (or other later regexps won't work) - # Needed for e.g. http://www.whatdotheyknow.com/request/60/response/98 text = text.gsub(/\r\n/, "\n") # Compress extra spaces down to save space, and to stop regular expressions @@ -665,6 +500,51 @@ class IncomingMessage < ActiveRecord::Base return text end + + def _sanitize_text(text) + if RUBY_VERSION.to_f >= 1.9 + begin + # Test if it's good UTF-8 + text.encode('utf-8') + rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError + source_charset = 'utf-8' if source_charset.nil? + # strip out anything that isn't UTF-8 + begin + text = text.encode("utf-8", :invalid => :replace, + :undef => :replace, + :replace => "") + + _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]", + :site_name => MySociety::Config.get('SITE_NAME', 'Alaveteli')) + rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError + if source_charset != "utf-8" + source_charset = "utf-8" + retry + end + end + end + else + begin + # Test if it's good UTF-8 + text = Iconv.conv('utf-8', 'utf-8', text) + rescue Iconv::IllegalSequence + # Text looks like unlabelled nonsense, + # strip out anything that isn't UTF-8 + begin + source_charset = 'utf-8' if source_charset.nil? + text = Iconv.conv('utf-8//IGNORE', source_charset, text) + + _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]", + :site_name => Configuration::site_name) + rescue Iconv::InvalidEncoding, Iconv::IllegalSequence + if source_charset != "utf-8" + source_charset = "utf-8" + retry + end + end + end + end + 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 @@ -718,7 +598,7 @@ class IncomingMessage < ActiveRecord::Base filename = uu.match(/^begin\s+[0-9]+\s+(.*)$/)[1] calc_mime = AlaveteliFileTypes.filename_and_content_to_mimetype(filename, content) if calc_mime - calc_mime = normalise_content_type(calc_mime) + calc_mime = MailHandler.normalise_content_type(calc_mime) content_type = calc_mime else content_type = 'application/octet-stream' @@ -747,55 +627,15 @@ class IncomingMessage < ActiveRecord::Base end def extract_attachments! - leaves = get_attachment_leaves # XXX check where else this is called from - # XXX we have to call ensure_parts_counted after get_attachment_leaves - # which is really messy. - ensure_parts_counted + force = true + attachment_attributes = MailHandler.get_attachment_attributes(self.mail(force)) attachments = [] - for leaf in leaves - body = leaf.body - # As leaf.body causes MIME decoding which uses lots of RAM, do garbage collection here - # to prevent excess memory use. XXX not really sure if this helps reduce - # peak RAM use overall. Anyway, maybe there is something better to do than this. - GC.start - if leaf.within_rfc822_attachment - within_rfc822_subject = leaf.within_rfc822_attachment.subject - # Test to see if we are in the first part of the attached - # RFC822 message and it is text, if so add headers. - # XXX should probably use hunting algorithm to find main text part, rather than - # just expect it to be first. This will do for now though. - # Example request that needs this: - # http://www.whatdotheyknow.com/request/2923/response/7013/attach/2/Cycle%20Path%20Bank.txt - if leaf.within_rfc822_attachment == leaf && leaf.content_type == 'text/plain' - headers = "" - for header in [ 'Date', 'Subject', 'From', 'To', 'Cc' ] - if leaf.within_rfc822_attachment.header.include?(header.downcase) - header_value = leaf.within_rfc822_attachment.header[header.downcase] - # Example message which has a blank Date header: - # http://www.whatdotheyknow.com/request/30747/response/80253/attach/html/17/Common%20Purpose%20Advisory%20Group%20Meeting%20Tuesday%202nd%20March.txt.html - if !header_value.blank? - headers = headers + header + ": " + header_value.to_s + "\n" - end - end - end - # XXX call _convert_part_body_to_text here, but need to get charset somehow - # e.g. http://www.whatdotheyknow.com/request/1593/response/3088/attach/4/Freedom%20of%20Information%20request%20-%20car%20oval%20sticker:%20Article%2020,%20Convention%20on%20Road%20Traffic%201949.txt - body = headers + "\n" + body - - # This is quick way of getting all headers, but instead we only add some a) to - # make it more usable, b) as at least one authority accidentally leaked security - # information into a header. - #attachment.body = leaf.within_rfc822_attachment.port.to_s - end - end - hexdigest = Digest::MD5.hexdigest(body) - attachment = self.foi_attachments.find_or_create_by_hexdigest(:hexdigest => hexdigest) - attachment.update_attributes(:url_part_number => leaf.url_part_number, - :content_type => leaf.content_type, - :filename => _get_part_file_name(leaf), - :charset => leaf.charset, - :within_rfc822_subject => within_rfc822_subject, - :body => body) + attachment_attributes.each do |attrs| + attachment = self.foi_attachments.find_or_create_by_hexdigest(:hexdigest => attrs[:hexdigest]) + body = attrs.delete(:body) + attachment.update_attributes(attrs) + # Set the body separately as its handling can depend on the value of charset + attachment.body = body attachment.save! attachments << attachment.id end @@ -805,7 +645,7 @@ class IncomingMessage < ActiveRecord::Base # e.g. for https://secure.mysociety.org/admin/foi/request/show_raw_email/24550 if !main_part.nil? uudecoded_attachments = _uudecode_and_save_attachments(main_part.body) - c = @count_first_uudecode_count + c = self.mail.count_first_uudecode_count for uudecode_attachment in uudecoded_attachments c += 1 uudecode_attachment.url_part_number = c @@ -897,101 +737,15 @@ class IncomingMessage < ActiveRecord::Base return self.cached_attachment_text_clipped end - def IncomingMessage._get_attachment_text_internal_one_file(content_type, body, charset = 'utf-8') - # note re. charset: TMail always tries to convert email bodies - # to UTF8 by default, so normally it should already be that. - text = '' - # XXX - tell all these command line tools to return utf-8 - if content_type == 'text/plain' - text += body + "\n\n" - else - tempfile = Tempfile.new('foiextract') - tempfile.print body - tempfile.flush - if content_type == 'application/vnd.ms-word' - AlaveteliExternalCommand.run("wvText", tempfile.path, tempfile.path + ".txt") - # Try catdoc if we get into trouble (e.g. for InfoRequestEvent 2701) - if not File.exists?(tempfile.path + ".txt") - AlaveteliExternalCommand.run("catdoc", tempfile.path, :append_to => text) - else - text += File.read(tempfile.path + ".txt") + "\n\n" - File.unlink(tempfile.path + ".txt") - end - elsif content_type == 'application/rtf' - # catdoc on RTF prodcues less comments and extra bumf than --text option to unrtf - AlaveteliExternalCommand.run("catdoc", tempfile.path, :append_to => text) - elsif content_type == 'text/html' - # lynx wordwraps links in its output, which then don't - # get formatted properly by Alaveteli. We use elinks - # instead, which doesn't do that. - AlaveteliExternalCommand.run("elinks", "-eval", "set document.codepage.assume = \"#{charset}\"", "-eval", "set document.codepage.force_assumed = 1", "-dump-charset", "utf-8", "-force-html", "-dump", - tempfile.path, :append_to => text, :env => {"LANG" => "C"}) - elsif content_type == 'application/vnd.ms-excel' - # Bit crazy using /usr/bin/strings - but xls2csv, xlhtml and - # py_xls2txt only extract text from cells, not from floating - # notes. catdoc may be fooled by weird character sets, but will - # probably do for UK FOI requests. - AlaveteliExternalCommand.run("/usr/bin/strings", tempfile.path, :append_to => text) - elsif content_type == 'application/vnd.ms-powerpoint' - # ppthtml seems to catch more text, but only outputs HTML when - # we want text, so just use catppt for now - AlaveteliExternalCommand.run("catppt", tempfile.path, :append_to => text) - elsif content_type == 'application/pdf' - AlaveteliExternalCommand.run("pdftotext", tempfile.path, "-", :append_to => text) - elsif content_type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - # This is Microsoft's XML office document format. - # Just pull out the main XML file, and strip it of text. - xml = AlaveteliExternalCommand.run("/usr/bin/unzip", "-qq", "-c", tempfile.path, "word/document.xml") - if !xml.nil? - doc = REXML::Document.new(xml) - text += doc.each_element( './/text()' ){}.join(" ") - end - elsif content_type == 'application/zip' - # recurse into zip files - begin - zip_file = Zip::ZipFile.open(tempfile.path) - text += IncomingMessage._get_attachment_text_from_zip_file(zip_file) - zip_file.close() - rescue - $stderr.puts("Error processing zip file: #{$!.inspect}") - end - end - tempfile.close - end - return text - end - def IncomingMessage._get_attachment_text_from_zip_file(zip_file) - text = "" - for entry in zip_file - if entry.file? - filename = entry.to_s - begin - body = entry.get_input_stream.read - rescue - # move to next attachment silently if there were problems - # XXX really should reduce this to specific exceptions? - # e.g. password protected - next - end - calc_mime = AlaveteliFileTypes.filename_to_mimetype(filename) - if calc_mime - content_type = calc_mime - else - content_type = 'application/octet-stream' - end - - text += _get_attachment_text_internal_one_file(content_type, body) - end - end - return text - end def _get_attachment_text_internal # Extract text from each attachment text = '' attachments = self.get_attachments_for_display for attachment in attachments - text += IncomingMessage._get_attachment_text_internal_one_file(attachment.content_type, attachment.body, attachment.charset) + text += MailHandler.get_attachment_text_one_file(attachment.content_type, + attachment.body, + attachment.charset) end # Remove any bad characters text = Iconv.conv('utf-8//IGNORE', 'utf-8', text) @@ -1059,66 +813,12 @@ class IncomingMessage < ActiveRecord::Base return AlaveteliFileTypes.all_extensions.join(" ") end - # Return false if for some reason this is a message that we shouldn't let them reply to - def valid_to_reply_to? - # check validity of email - if self.mail.from_addrs.nil? || self.mail.from_addrs.size == 0 - return false - end - email = self.mail.from_addrs[0].spec - if !MySociety::Validate.is_valid_email(email) - return false - end - - # reject postmaster - authorities seem to nearly always not respond to - # email to postmaster, and it tends to only happen after delivery failure. - # likewise Mailer-Daemon, Auto_Reply... - prefix = email - prefix =~ /^(.*)@/ - prefix = $1 - if !prefix.nil? && prefix.downcase.match(/^(postmaster|mailer-daemon|auto_reply|do.?not.?reply|no.reply)$/) - return false + def for_admin_column + self.class.content_columns.each do |column| + yield(column.human_name, self.send(column.name), column.type.to_s, column.name) end - if !self.mail['return-path'].nil? && self.mail['return-path'].addr == "<>" - return false - end - if !self.mail['auto-submitted'].nil? - return false - end - return true end - def normalise_content_type(content_type) - # e.g. http://www.whatdotheyknow.com/request/93/response/250 - if content_type == 'application/excel' or content_type == 'application/msexcel' or content_type == 'application/x-ms-excel' - content_type = 'application/vnd.ms-excel' - end - if content_type == 'application/mspowerpoint' or content_type == 'application/x-ms-powerpoint' - content_type = 'application/vnd.ms-powerpoint' - end - if content_type == 'application/msword' or content_type == 'application/x-ms-word' - content_type = 'application/vnd.ms-word' - end - if content_type == 'application/x-zip-compressed' - content_type = 'application/zip' - end - - # e.g. http://www.whatdotheyknow.com/request/copy_of_current_swessex_scr_opt#incoming-9928 - if content_type == 'application/acrobat' - content_type = 'application/pdf' - end - - return content_type - end - - def for_admin_column - self.class.content_columns.each do |column| - yield(column.human_name, self.send(column.name), column.type.to_s, column.name) - end - end - - private :normalise_content_type - end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 89893a396..3355b9443 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -138,7 +138,7 @@ class InfoRequest < ActiveRecord::Base if external_user_name.nil? fake_slug = "anonymous" else - fake_slug = external_user_name.parameterize + fake_slug = MySociety::Format.simplify_url_part(external_user_name, 'external_user', 32) end (public_body.url_name || "") + "_" + fake_slug else @@ -275,7 +275,7 @@ public return self.magic_email("request-") end def incoming_name_and_email - return TMail::Address.address_from_name_and_email(self.user_name, self.incoming_email).to_s + return MailHandler.address_from_name_and_email(self.user_name, self.incoming_email) end # Subject lines for emails about the request @@ -355,12 +355,7 @@ public def InfoRequest.guess_by_incoming_email(incoming_message) guesses = [] # 1. Try to guess based on the email address(es) - addresses = - (incoming_message.mail.to || []) + - (incoming_message.mail.cc || []) + - (incoming_message.mail.envelope_to || []) - addresses.uniq! - for address in addresses + incoming_message.addresses.each do |address| id, hash = InfoRequest._extract_id_hash_from_email(address) guesses.push(InfoRequest.find_by_id(id)) guesses.push(InfoRequest.find_by_idhash(hash)) @@ -419,8 +414,7 @@ public end for im in self.incoming_messages - other_message_id = im.mail.message_id - if message_id == other_message_id + if message_id == im.message_id return true end end @@ -440,11 +434,11 @@ public elsif self.allow_new_responses_from == 'anybody' allow = true elsif self.allow_new_responses_from == 'authority_only' - if email.from_addrs.nil? || email.from_addrs.size == 0 + sender_email = MailHandler.get_from_address(email) + if sender_email.nil? allow = false reason = _('Only the authority can reply to this request, but there is no "From" address to check against') else - sender_email = email.from_addrs[0].spec sender_domain = PublicBody.extract_domain_from_email(sender_email) reason = _("Only the authority can reply to this request, and I don't recognise the address this reply was sent from") allow = false @@ -713,11 +707,11 @@ public return self.public_body.is_followupable? end def recipient_name_and_email - return TMail::Address.address_from_name_and_email( + return MailHandler.address_from_name_and_email( _("{{law_used}} requests at {{public_body}}", :law_used => self.law_used_short, :public_body => self.public_body.short_or_long_name), - self.recipient_email).to_s + self.recipient_email) end # History of some things that have happened @@ -1130,7 +1124,11 @@ public } if deep - ret[:user] = self.user.json_for_api + if self.user + ret[:user] = self.user.json_for_api + else + ret[:user_name] = self.user_name + end ret[:public_body] = self.public_body.json_for_api ret[:info_request_events] = self.info_request_events.map { |e| e.json_for_api(false) } end diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 5a8e3416f..09eba31ab 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -384,7 +384,7 @@ class InfoRequestEvent < ActiveRecord::Base if prev_addr.nil? || curr_addr.nil? return false end - return TMail::Address.parse(prev_addr).address == TMail::Address.parse(curr_addr).address + return MailHandler.address_from_string(prev_addr) == MailHandler.address_from_string(curr_addr) end def json_for_api(deep, snippet_highlight_proc = nil) diff --git a/app/models/outgoing_mailer.rb b/app/models/outgoing_mailer.rb index a307bb778..503166b8a 100644 --- a/app/models/outgoing_mailer.rb +++ b/app/models/outgoing_mailer.rb @@ -47,7 +47,8 @@ class OutgoingMailer < ApplicationMailer return info_request.recipient_name_and_email else # calling safe_mail_from from so censor rules are run - return TMail::Address.address_from_name_and_email(incoming_message_followup.safe_mail_from, incoming_message_followup.mail.from_addrs[0].spec).to_s + return MailHandler.address_from_name_and_email(incoming_message_followup.safe_mail_from, + incoming_message_followup.from_email) end end # Used in the preview of followup @@ -64,7 +65,7 @@ class OutgoingMailer < ApplicationMailer if incoming_message_followup.nil? || !incoming_message_followup.valid_to_reply_to? return info_request.recipient_email else - return incoming_message_followup.mail.from_addrs[0].spec + return incoming_message_followup.from_email end end # Subject to use for followup diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb index bae144931..de7978b82 100644 --- a/app/models/raw_email.rb +++ b/app/models/raw_email.rb @@ -22,7 +22,7 @@ class RawEmail < ActiveRecord::Base if request_id.empty? raise "Failed to find the id number of the associated request: has it been saved?" end - + if ENV["RAILS_ENV"] == "test" return File.join(Rails.root, 'files/raw_email_test') else @@ -49,7 +49,7 @@ class RawEmail < ActiveRecord::Base end def data - File.open(self.filepath, "rb").read + File.open(self.filepath, "r").read end def destroy_file_representation! diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb index 90c4c6b53..493d6961c 100644 --- a/app/models/request_mailer.rb +++ b/app/models/request_mailer.rb @@ -204,15 +204,14 @@ class RequestMailer < ApplicationMailer # # That is because we want to be sure we properly record the actual message # received in its raw form - so any information won't be lost in a round - # trip via TMail, or by bugs in it, and so we can use something other than - # TMail at a later date. And so we can offer an option to download the + # trip via the mail handler, or by bugs in it, and so we can use something + # other than TMail at a later date. And so we can offer an option to download the # actual original mail sent by the authority in the admin interface (so # can check that attachment decoding failures are problems in the message, # not in our code). ] def self.receive(raw_email) logger.info "Received mail:\n #{raw_email}" unless logger.nil? - mail = TMail::Mail.parse(raw_email) - mail.base64_decode + mail = MailHandler.mail_from_raw_email(raw_email) new.receive(mail, raw_email) end diff --git a/app/models/user.rb b/app/models/user.rb index 70386f7e4..6e1e21481 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -203,7 +203,7 @@ class User < ActiveRecord::Base # For use in to/from in email messages def name_and_email - return TMail::Address.address_from_name_and_email(self.name, self.email).to_s + return MailHandler.address_from_name_and_email(self.name, self.email) end # The "internal admin" is a special user for internal use. diff --git a/app/views/comment/_single_comment.rhtml b/app/views/comment/_single_comment.rhtml index 013e5e107..b645721cf 100644 --- a/app/views/comment/_single_comment.rhtml +++ b/app/views/comment/_single_comment.rhtml @@ -11,7 +11,7 @@ </h2> <div class="comment_in_request_text"> <p> - <img class="comment_quote" src="/images/quote.png" alt=""> + <img class="comment_quote" src="/images/quote-marks.png" alt=""> <%= comment.get_body_for_html_display %> </p> </div> diff --git a/app/views/general/_frontpage_new_request.rhtml b/app/views/general/_frontpage_new_request.rhtml index fd4225069..499b60eb5 100644 --- a/app/views/general/_frontpage_new_request.rhtml +++ b/app/views/general/_frontpage_new_request.rhtml @@ -4,4 +4,4 @@ Information<br/> request</strong>") %> </h1> -<a class="link_button_green_large" href="/select_authority"><%= _("Start now »") %></a> +<a class="link_button_green_large" href="<%= select_authority_path %>"><%= _("Start now »") %></a> diff --git a/app/views/general/_frontpage_search_box.rhtml b/app/views/general/_frontpage_search_box.rhtml index 6de4eae98..d2718b3a3 100644 --- a/app/views/general/_frontpage_search_box.rhtml +++ b/app/views/general/_frontpage_search_box.rhtml @@ -4,7 +4,7 @@ <strong>{{number_of_authorities}} authorities</strong>", :number_of_requests => InfoRequest.visible.count, :number_of_authorities => PublicBody.visible.count) %> </h2> -<form id="search_form" method="post" action="/search"> +<form id="search_form" method="post" action="<%= search_redirect_path %>"> <div> <input id="query" type="text" size="30" name="query"> <input type="submit" value="<%= _('Search') %>"> diff --git a/app/views/help/_sidebar.rhtml b/app/views/help/_sidebar.rhtml index 783d35983..2b7ed5647 100644 --- a/app/views/help/_sidebar.rhtml +++ b/app/views/help/_sidebar.rhtml @@ -1,19 +1,19 @@ <div id="right_column_flip"> <h2>Help pages</h2> <ul class="no_bullets"> - <li><%= link_to_unless_current "Introduction", "/help/about" %></li> - <li><%= link_to_unless_current "Making requests", "/help/requesting" %></li> - <li><%= link_to_unless_current "Your privacy", "/help/privacy" %></li> - <li><%= link_to_unless_current "FOI officers", "/help/officers" %></li> - <li><%= link_to_unless_current "About the software", "/help/alaveteli" %></li> - <li><%= link_to_unless_current "Credits", "/help/credits" %></li> - <li><%= link_to_unless_current "Programmers API", "/help/api" %></li> - <li><%= link_to_unless_current "Advanced search", "/advancedsearch" %></li> + <li><%= link_to_unless_current "Introduction", help_about_path %></li> + <li><%= link_to_unless_current "Making requests", help_requesting_path %></li> + <li><%= link_to_unless_current "Your privacy", help_privacy_path %></li> + <li><%= link_to_unless_current "FOI officers", help_officers_path %></li> + <li><%= link_to_unless_current "About the software", help_alaveteli_path %></li> + <li><%= link_to_unless_current "Credits", help_credits_path %></li> + <li><%= link_to_unless_current "Programmers API", help_api_path %></li> + <li><%= link_to_unless_current "Advanced search", advanced_search_path %></li> </ul> <h2 id="contact">Contact us</h2> <p>If your question isn't answered here, or you just wanted to let us know - something about the site, <a href="/help/contact">contact us</a>. + something about the site, <a href="<%= help_contact_path %>">contact us</a>. </p> </div> diff --git a/app/views/help/about.rhtml b/app/views/help/about.rhtml index 9f75cac8b..477f0e750 100644 --- a/app/views/help/about.rhtml +++ b/app/views/help/about.rhtml @@ -41,13 +41,13 @@ </dd> <dt id="updates">How can I keep up with news about WhatDoTheyKnow?<a href="#updates">#</a> </dt> - <dd>We have a <a href="/blog">blog</a> and a <a href="https://twitter.com/whatdotheyknow">twitter feed</a>. + <dd>We have a <a href="<%= blog_path %>">blog</a> and a <a href="https://twitter.com/whatdotheyknow">twitter feed</a>. </dd> </dl> - <p><strong>Next</strong>, read about <a href="/help/requesting">making requests</a> --> + <p><strong>Next</strong>, read about <a href="<%= help_requesting_path %>">making requests</a> --> <div id="hash_link_padding"></div> </div> diff --git a/app/views/help/api.rhtml b/app/views/help/api.rhtml index 76d2992fb..da6253f87 100644 --- a/app/views/help/api.rhtml +++ b/app/views/help/api.rhtml @@ -19,7 +19,7 @@ <dt>Linking to new requests</dt> <dd> <p>To encourage your users to make links to a particular public authority, use URLs of the form - <%= link_to new_request_to_body_url(:url_name => "liverpool_city_council") , new_request_to_body_url(:url_name => "liverpool_city_council") %>. + <%= link_to new_request_to_body_url(:url_name => "liverpool_city_council") , new_request_to_body_url(:url_name => "liverpool_city_council") %>. These are the parameters you can add to those URLs, either in the URL or from a form. <ul> @@ -34,7 +34,7 @@ <dd> <p>There are Atom feeds on most pages which list FOI requests, which you can use to get updates and links in XML format. Find the URL of the Atom feed in - one of these ways: + one of these ways: <ul> <li>Look for the <img src="/images/feed-16.png" alt=""> RSS feed links.</li> <li>Examine the <tt><link rel="alternate" type="application/atom+xml"></tt> tag in the head of the HTML. </li> @@ -43,7 +43,7 @@ <p>In particular, even complicated search queries have Atom feeds. You can do all sorts of things with them, such as query by authority, by file - type, by date range, or by status. See the <a href="/search">advanced search + type, by date range, or by status. See the <a href="<%= advanced_search_path %>">advanced search tips</a> for details. </dd> @@ -51,18 +51,18 @@ <dd> <p>Quite a few pages have JSON versions, which let you download information about objects in a structured form. Find them by: + </p> <ul> <li>Adding <tt>.json</tt> to the end of the URL. </li> <li>Look for the <tt><link rel="alternate" type="application/json"></tt> tag in the head of the HTML. </li> </ul> - </p> <p>Requests, users and authorities all have JSON versions containing basic information about them. Every Atom feed has a JSON equivalent, containing information about the list of events in the feed. </p> </dd> - + <dt>Spreadsheet of all authorities</dt> <dd> <p> @@ -73,7 +73,7 @@ </dd> </dl> - <p>Please <a href="/help/contact">contact us</a> if you need an API feature that isn't there yet. It's + <p>Please <a href="<%= help_contact_path %>">contact us</a> if you need an API feature that isn't there yet. It's very much a work in progress, and we do add things when people ask us to.</p> <div id="hash_link_padding"></div> diff --git a/app/views/help/contact.rhtml b/app/views/help/contact.rhtml index 37df68f49..fab5017b8 100644 --- a/app/views/help/contact.rhtml +++ b/app/views/help/contact.rhtml @@ -9,13 +9,13 @@ <% if !flash[:notice] %> <h2>Contact an authority to get official information</h2> <ul> - <li><a href="/new">Go here</a> to make a request, in public, for information + <li><a href="<%= new_request_path %>">Go here</a> to make a request, in public, for information from public authorities.</li> <li> Asking for private information about yourself? Please read our - <a href="/help/requesting#data_protection">help page</a>. + <a href="<%= help_requesting_path(:anchor => 'data_protection') %>">help page</a>. </li> </ul> @@ -25,10 +25,10 @@ <% if !flash[:notice] %> <ul> <li> - Please read the <a href="/help/about">help page</a> first, as it may - answer your question quicker. + Please read the <a href="<%= help_about_path %>">help page</a> first, as it may + answer your question quicker. </li> - + <li>We'd love to hear how you've found using this site. Either fill in this form, or send an email to <a href="mailto:<%=@contact_email%>"><%=@contact_email%></a> @@ -56,25 +56,25 @@ <% end %> <p> - <label class="form_label" for="contact_subject">Subject:</label> + <label class="form_label" for="contact_subject">Subject:</label> <%= f.text_field :subject, :size => 50 %> </p> <p> - <label class="form_label" for="contact_message">Message to website:</label> + <label class="form_label" for="contact_message">Message to website:</label> <%= f.text_area :message, :rows => 10, :cols => 60 %> </p> <% if !@last_request.nil? %> <p> - <label class="form_label" for="contact_message">Include link to request:</label> + <label class="form_label" for="contact_message">Include link to request:</label> <%=request_link(@last_request) %> <%= submit_tag "remove", :name => 'remove' %> </p> <% end %> <% if !@last_body.nil? %> <p> - <label class="form_label" for="contact_message">Include link to authority:</label> + <label class="form_label" for="contact_message">Include link to authority:</label> <%=public_body_link(@last_body) %> <%= submit_tag "remove", :name => 'remove' %> </p> diff --git a/app/views/help/officers.rhtml b/app/views/help/officers.rhtml index 3defec62f..b13e225fe 100644 --- a/app/views/help/officers.rhtml +++ b/app/views/help/officers.rhtml @@ -19,13 +19,13 @@ </p> <p>If you have privacy or other concerns, please read the answers below. You might also like to read the <a - href="/help/about">introduction to WhatDoTheyKnow</a> to find out more about what + href="<%= help_about_path %>">introduction to WhatDoTheyKnow</a> to find out more about what the site does from the point of view of a user. You can also search the site to find the authority that you work for, and view the status of any requests made using the site. <p>Finally, we welcome comments and - thoughts from FOI officers, please <a href="/help/contact">get in touch</a>. + thoughts from FOI officers, please <a href="<%= help_contact_path %>">get in touch</a>. </p> </dd> @@ -75,13 +75,13 @@ the authority by email. Any delivery failure messages will automatically appear on the site. You can check the address we're using with the "View FOI email address" link which appears on the page for the authority. <a - href="/help/contact">Contact us</a> if there is a better address we can + href="<%= help_contact_path %>">Contact us</a> if there is a better address we can use.</p> <p>Requests are sometimes not delivered because they are quietly removed by "spam filters" in the IT department of the authority. Authorities can make - sure this doesn't happen by asking their IT departments to "whitelist" + sure this doesn't happen by asking their IT departments to "whitelist" any email from <strong>@whatdotheyknow.com</strong>. - If you <a href="/help/contact">ask us</a> we will resend any request, + If you <a href="<%= help_contact_path %>">ask us</a> we will resend any request, and/or give technical details of delivery so an IT department can chase up what happened to the message. </p> @@ -159,7 +159,7 @@ </li> </ul> - <p>If you're getting really nerdy about all this, read the <a href="http://www.ico.gov.uk/upload/documents/library/freedom_of_information/detailed_specialist_guides/timeforcompliance.pdf">detailed ICO guidance</a>. + <p>If you're getting really nerdy about all this, read the <a href="http://www.ico.gov.uk/upload/documents/library/freedom_of_information/detailed_specialist_guides/timeforcompliance.pdf">detailed ICO guidance</a>. Meanwhile, remember that the law says authorities must respond <strong>promptly</strong>. That's really what matters.</p> @@ -173,14 +173,14 @@ extension when applying a <strong>public interest test</strong>. Information Commissioner guidance says that it should only be used in "exceptionally complex" cases - (<a href="http://www.ico.gov.uk/upload/documents/library/freedom_of_information/detailed_specialist_guides/foi_good_practice_guidance_4.pdf">FOI Good Practice Guidance No. 4</a>). + (<a href="http://www.ico.gov.uk/upload/documents/library/freedom_of_information/detailed_specialist_guides/foi_good_practice_guidance_4.pdf">FOI Good Practice Guidance No. 4</a>). WhatDoTheyKnow doesn't specifically handle this case, which is why we use the phrase "should normally have responded by" when the 20 working day time is - exceeded. + exceeded. </p> <p>The same guidance says that, even in exceptionally complex cases, no - Freedom of Information request should take more than <strong>40 working days</strong> + Freedom of Information request should take more than <strong>40 working days</strong> to answer. WhatDoTheyKnow displays requests which are overdue by that much with stronger wording to indicate they are definitely late. </p> @@ -191,7 +191,7 @@ of 40 working days even with the extension (the House of Lords <a href="http://www.publicwhip.org.uk/division.php?date=2000-10-17&number=1&house=lords">voted to remove</a> provision for such a time limit during the initial passage - of the UK Act through Parliament). + of the UK Act through Parliament). </p> </dd> @@ -199,7 +199,7 @@ <dd>Instead of email, you can respond to a request directly from your web browser, including uploading a file. To do this, choose "respond to request" at - the bottom of the request's page. <a href="/help/contact">Contact us</a> if it + the bottom of the request's page. <a href="<%= help_contact_path %>">Contact us</a> if it is too big for even that (more than, say, 50Mb). </dd> @@ -207,17 +207,17 @@ <dd>We consider what officers or servants do in the course of their employment to be public information. We will only remove content in exceptional - circumstances, see our <a href="/help/privacy#takedown">take down policy</a>. + circumstances, see our <a href="<%= help_privacy_path(:anchor => 'takedown') %>">take down policy</a>. </dd> <dt id="mobiles">Do you publish email addresses or mobile phone numbers? <a href="#mobiles">#</a> </dt> <dd><p>To prevent spam, we automatically remove most emails and some mobile numbers from - responses to requests. Please <a href="/help/contact">contact us</a> if we've - missed one. + responses to requests. Please <a href="<%= help_contact_path %>">contact us</a> if we've + missed one. For technical reasons we don't always remove them from attachments, such as certain PDFs.</p> <p>If you need to know what an address was that we've removed, please <a - href="/help/contact">get in touch with us</a>. Occasionally, an email address + href="<%= help_contact_path %>">get in touch with us</a>. Occasionally, an email address forms an important part of a response and we will post it up in an obscured form in an annotation. </dd> @@ -225,10 +225,10 @@ <dt id="copyright"><a name="commercial"></a>What is your policy on copyright of documents?<a href="#copyright">#</a> </dt> <dd>Our Freedom of Information law is "applicant blind", so anyone in the - world can request the same document and get a copy of it. + world can request the same document and get a copy of it. If you think our making a document available on the internet infringes your - copyright, you may <a href="/help/contact">contact us</a> and ask us + copyright, you may <a href="<%= help_contact_path %>">contact us</a> and ask us to take it down. However, to save tax payers' money by preventing duplicate requests, and for good public relations, we'd advise you not to do that. </dd> @@ -238,8 +238,8 @@ </dl> - <p><strong>If you haven't already</strong>, read <a href="/help/about">the introduction</a> --> - <br><strong>Otherwise</strong>, the <a href="/help/credits">credits</a> or the <a href="/help/api">programmers API</a> --> + <p><strong>If you haven't already</strong>, read <a href="<%= help_about_path %>">the introduction</a> --> + <br><strong>Otherwise</strong>, the <a href="<%= help_credits_path %>">credits</a> or the <a href="<%= help_api_path %>">programmers API</a> --> <div id="hash_link_padding"></div> </div> diff --git a/app/views/help/privacy.rhtml b/app/views/help/privacy.rhtml index bec0c8c23..8e5293892 100644 --- a/app/views/help/privacy.rhtml +++ b/app/views/help/privacy.rhtml @@ -10,7 +10,7 @@ <dd><p>We will not disclose your email address to anyone unless we are obliged to by law, or you ask us to. This includes the public authority that you are sending a - request to. They only get to see an email address + request to. They only get to see an email address @whatdotheyknow.com which is specific to that request. </p> <p>If you send a message to another user on the site, then it will reveal your email address to them. You will be told that this is going to happen.</p> @@ -35,7 +35,7 @@ Your name is tangled up with your request, so has to be published as well. It is only fair, as we're going to publish the name of the civil servant who writes the response to your request. Using your real name also helps people - get in touch with you to assist you with your research or to campaign with you. + get in touch with you to assist you with your research or to campaign with you. </p> <p>By law, you must use your real name for the request to be a valid Freedom of Information request. See the next question for alternatives if you do not want @@ -66,16 +66,16 @@ Information Commissioner later about the handling of your request. <ul> <li>Use a different form of your name. The guidance says that "Mr Arthur Thomas Roberts" can make a valid request as "Arthur Roberts", -"A. T. Roberts", or "Mr Roberts", but <strong>not</strong> as "Arthur" or "A.T.R.". +"A. T. Roberts", or "Mr Roberts", but <strong>not</strong> as "Arthur" or "A.T.R.". </li> <li>Women may use their maiden name.</li> <li>In most cases, you may use any name by which you are "widely known and/or is regularly used". <li>Use the name of an organisation, the name of a company, the trading name of a company, or the trading name of a sole trader. -<li>Ask someone else to make the request on your behalf. +<li>Ask someone else to make the request on your behalf. <li>You may, if you are really stuck, ask us to make the request on -your behalf. Please <a href="/help/contact">contact us</a> with +your behalf. Please <a href="<%= help_contact_path %>">contact us</a> with a good reason why you cannot make the request yourself and cannot ask a friend to. We don't have the resources to do this for everyone. </ul> @@ -88,19 +88,19 @@ ask a friend to. We don't have the resources to do this for everyone. <dd> <p>If a public authority asks you for your full, physical address, reply to them saying -that section 8.1.b of the FOI Act asks for an "address for correspondence", -and that the email address you are using is sufficient. +that section 8.1.b of the FOI Act asks for an "address for correspondence", +and that the email address you are using is sufficient. </p> <p> The Ministry of Justice has <a href="http://www.justice.gov.uk/guidance/foi-procedural-what.htm">guidance on this</a> – <em>"As well as hard copy written correspondence, requests that are -transmitted electronically (for example, in emails) are acceptable +transmitted electronically (for example, in emails) are acceptable ... If a request is received by email and no postal address is given, the email address should be treated as the return address." </em> </p> -<p>As if that isn't enough, the Information Commissioner's +<p>As if that isn't enough, the Information Commissioner's <a href="http://www.ico.gov.uk/upload/documents/library/freedom_of_information/practical_application/foi_hints_for_practitioners_handing_foi_and_eir_requests_2008_final.pdf">Hints for Practitioners</a> say <em>"Any correspondence could include a request for information. If it is written (this includes e-mail), legible, gives the name of the applicant, an address for reply (which could be electronic), and includes a description of the information required, then it will fall within the scope of the legislation."</em> </p> @@ -141,10 +141,10 @@ see the section on <a href="#real_name">pseudonyms</a>.</p> <dt id="takedown">Can you take down personal information about me? <a href="#takedown">#</a> </dt> -<dd> +<dd> <p>If you see any personal information about you on the site which you'd like -us to remove or hide, then please <a href="/help/contact">let us know</a>. +us to remove or hide, then please <a href="<%= help_contact_path %>">let us know</a>. Specify exactly what information you believe to be problematic and why, and where it appears on the site.</p> @@ -165,8 +165,8 @@ which outweighs the public interest, and must demonstrate that efforts have been made to conceal the name on the organisation's own website.</p> <p>For all other requests we apply a public interest test to decide -whether information should be removed. -<a href="http://www.statutelaw.gov.uk/content.aspx?ActiveTextDocId=3190650"> Section 32</a> +whether information should be removed. +<a href="http://www.statutelaw.gov.uk/content.aspx?ActiveTextDocId=3190650"> Section 32</a> of the Data Protection Act 1998 permits us to do this, as the material we publish is journalistic. We cannot easily edit many types of attachments (such as PDFs, or Microsoft Word or Excel files), so we will usually ask @@ -177,7 +177,7 @@ that authorities resend these with the personal information removed.</p> </dl> -<p><strong>Learn more</strong> from the help for <a href="/help/officers">FOI officers</a> --> +<p><strong>Learn more</strong> from the help for <a href="<%= help_officers_path %>">FOI officers</a> --> <div id="hash_link_padding"></div> </div> diff --git a/app/views/help/requesting.rhtml b/app/views/help/requesting.rhtml index af8f2e45d..e7cfdd199 100644 --- a/app/views/help/requesting.rhtml +++ b/app/views/help/requesting.rhtml @@ -20,7 +20,7 @@ <li>Don't worry excessively about getting the right authority. If you get it wrong, they ought to advise you who to make the request to instead. </li> - <li>If you've got a thorny case, please <a href="/help/contact">contact us</a> for help.</li> + <li>If you've got a thorny case, please <a href="<%= help_contact_path %>">contact us</a> for help.</li> </ul> </dd> @@ -30,7 +30,7 @@ <dt id="missing_body">You're missing the public authority that I want to request from! <a href="#missing_body">#</a> </dt> <dd> - <p>Please <a href="/help/contact">contact us</a> with the name of the public authority and, + <p>Please <a href="<%= help_contact_path %>">contact us</a> with the name of the public authority and, if you can find it, their contact email address for Freedom of Information requests. </p> <p>If you'd like to help add a whole category of public authority to the site, we'd love @@ -47,11 +47,11 @@ <ul> <li> Those formally subject to the FOI Act</li> - <li> Those formally subject to the Environmental Regulations (a less well + <li> Those formally subject to the Environmental Regulations (a less well defined group)</li> <li> Those which voluntarily comply with the FOI Act</li> <li> Those which aren't subject to the Act but we think should be, on grounds - such as them having significant public responsibilities. + such as them having significant public responsibilities. </li> </ul> @@ -132,7 +132,7 @@ <p>Even if they are not prompt, in nearly all cases they must respond within 20 working days. If you had to clarify your request, or they are a school, or one or two other cases, then they may have more time - (<a href="/help/officers#days">full details</a>). + (<a href="<%= help_officers_path(:anchor => 'days') %>">full details</a>). <p>WhatDoTheyKnow will email you if you don't get a timely response. You can then send the public authority a message to remind them, and tell them if they @@ -158,24 +158,24 @@ checking that they received the request. It was sent to them by email. </li> <li>If they have not received it, the problem is most likely due to - "spam filters". Refer the authority to the measures in the answer - '<a href="/help/officers#spam_problems">I can see a request on WhatDoTheyKnow, but we never got it by email!</a>' - in the FOI officers section of this help. + "spam filters". Refer the authority to the measures in the answer + '<a href="<%= help_officers_path(:anchor => 'spam_problems') %>">I can see a request on WhatDoTheyKnow, but we never got it by email!</a>' + in the FOI officers section of this help. </li> <li>If you're still having no luck, then you can ask for an internal review, and then complain to the Information Commissioner about the authority. - Read our page '<a href="/help/unhappy">Unhappy about the response you got?</a>'. + Read our page '<a href="<%= help_general_path(:action => 'unhappy') %>">Unhappy about the response you got?</a>'. </ul> </dd> <dt id="not_satifised">What if I'm not satisfied with the response? <a href="#not_satifised">#</a> </dt> <dd>If you didn't get the information you asked for, or you didn't get it in time, - then read our page '<a href="/help/unhappy">Unhappy about the response you got?</a>'. + then read our page '<a href="<%= help_general_path(:action => 'unhappy') %>">Unhappy about the response you got?</a>'. </dd> <dt id="reuse">It says I can't re-use the information I got!<a href="#reuse">#</a> </dt> <dd> - <p>Authorities often add legal boilerplate about the + <p>Authorities often add legal boilerplate about the "<a href="http://www.opsi.gov.uk/si/si2005/20051515">Re-Use of Public Sector Information Regulations 2005</a>", which at first glance implies you may not be able do anything with the information. @@ -184,7 +184,7 @@ <p>You can, of course, write articles about the information or summarise it, or quote parts of it. We also think you should feel free to republish the information in full, just as we do, even though in theory you might not be - allowed to do so. See <a href="/help/officers#copyright">our policy on copyright</a>.</p> + allowed to do so. See <a href="<%= help_officers_path(:anchor => 'copyright') %>">our policy on copyright</a>.</p> </dd> @@ -199,7 +199,7 @@ the process is very similar. There are differences around time limits for compliance. See the <a href="http://www.itspublicknowledge.info/nmsruntime/saveasdialog.asp?lID=1858&sID=321">Scottish - Information Commissioner's guidance</a> for details.</p> + Information Commissioner's guidance</a> for details.</p> </dd> <dt id="data_protection">Can I request information about myself? <a href="#data_protection">#</a> </dt> @@ -216,7 +216,7 @@ website) explains how to do this.</p> <p>If you see that somebody has included personal information, perhaps - unwittingly, in a request, please <a href="/help/contact">contact us</a> + unwittingly, in a request, please <a href="<%= help_contact_path %>">contact us</a> immediately so we can remove it.</p> </dd> @@ -228,7 +228,7 @@ to read. </p> <p>You should contact the public authority directly if you would like to make a request in private. If you're interested in buying a system which helps - you manage FOI requests in secret, then <a href="/help/contact">contact us</a>. + you manage FOI requests in secret, then <a href="<%= help_contact_path %>">contact us</a>. </p> </dd> @@ -237,7 +237,7 @@ <dd> <p>Some public authorities, such as <a href="http://www.whatdotheyknow.com/body/south_east_water">South East Water</a>, don't come under the Freedom of Information Act, but do come under another law called - the Environmental Information Regulations (EIR). + the Environmental Information Regulations (EIR). </p> <p>It's a very similar law, so you make a request @@ -250,7 +250,7 @@ <p>You can, of course, request environmental information from other authorities. Just make a Freedom of Information (FOI) request as normal. The authority has a duty to work out if the Environmental Information Regulations - (EIR) is the more appropriate legislation to reply under. + (EIR) is the more appropriate legislation to reply under. </p> </dd> @@ -275,7 +275,7 @@ <dt id="moderation">How do you moderate request annotations? <a href="#moderation">#</a> </dt> - <dd> + <dd> <p>Annotations on WhatDoTheyKnow are to help people get the information they want, or to give them pointers to places they can go to help them act on it. We reserve the right to remove anything else. @@ -286,7 +286,7 @@ </dl> - <p><strong>Next</strong>, read about <a href="/help/privacy">your privacy</a> --> + <p><strong>Next</strong>, read about <a href="<%= help_privacy_path %>">your privacy</a> --> <div id="hash_link_padding"></div> </div> diff --git a/app/views/help/unhappy.rhtml b/app/views/help/unhappy.rhtml index 4f3c67b9e..2b00341c2 100644 --- a/app/views/help/unhappy.rhtml +++ b/app/views/help/unhappy.rhtml @@ -2,7 +2,7 @@ <% if !@info_request.nil? %> -<h1>Unhappy about the response you got +<h1>Unhappy about the response you got to your request '<%=request_link(@info_request) %>'? </h1> <% else %> @@ -58,10 +58,10 @@ authority, then <a href="http://www.itspublicknowledge.info/YourRights/HowToApp to the Scottish Information Commissioner</a>. </p> -<p>To make it easier to send the relevant information to the +<p>To make it easier to send the relevant information to the Information Commissioner, either <% if !@info_request.nil? %> - include a link to your request + include a link to your request <strong><%=h main_url(request_url(@info_request)) %></strong> <% else %> include a link to your request on <%= site_name %> @@ -86,8 +86,8 @@ get the information by <strong>other means...</strong></p> <ul> <li>Make a <strong>new FOI request</strong> for summary information, or for -documentation relating indirectly to matters in your refused request. -<a href="/help/contact">Ask us for ideas</a> if you're stuck.</li> +documentation relating indirectly to matters in your refused request. +<a href="<%= help_contact_path %>">Ask us for ideas</a> if you're stuck.</li> <li>If any <strong>other public authorities</strong> or publicly owned companies are involved, then make FOI requests to them.</li> <li>Write to <strong>your MP</strong> or other politician using <a @@ -95,13 +95,13 @@ href="http://www.writetothem.com">WriteToThem</a> and ask for their help finding the answer. MPs can write directly to ministers or departments, and can ask written questions in the House of Commons. Councillors in local authorities can talk directly to council officers.</li> -<li>Ask <strong>other researchers</strong> who are interested in a similar +<li>Ask <strong>other researchers</strong> who are interested in a similar issue to yours for ideas. You can sometimes find them by browsing this site; contact any registered user from their page. There may be an Internet forum or group that they hang out in. If it is a local matter, use <a -href="http://www.groupsnearyou.com">GroupsNearYou</a> to find such a +href="http://www.groupsnearyou.com">GroupsNearYou</a> to find such a forum.</li> -<li><strong>Start a pledge</strong> on <a href="http://www.pledgebank.com">PledgeBank</a> to get +<li><strong>Start a pledge</strong> on <a href="http://www.pledgebank.com">PledgeBank</a> to get others to act together with you. For example, you could arrange a meeting with staff from the authority. Or you could form a small local campaigns group. </ul> diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml index 76bdbd2dd..6ac7064a7 100644 --- a/app/views/layouts/default.rhtml +++ b/app/views/layouts/default.rhtml @@ -12,7 +12,7 @@ <link rel="shortcut icon" href="/favicon.ico"> <%= render :partial => 'general/stylesheet_includes' %> - <% if session[:using_admin] %> + <% if is_admin? %> <%= stylesheet_link_tag "/adminbootstraptheme/stylesheets/admin", :title => "Main", :rel => "stylesheet" %> <% end %> @@ -63,15 +63,15 @@ </script> <% end %> -<% if session[:using_admin] %> +<% if is_admin? %> <%= render :partial => 'admin_general/admin_navbar' %> <% end %> <% if !@popup_banner.blank? %> <div id="everypage" class="jshide"> - <p style="float:right"><a href="#top" onclick="$.cookie('seen_foi2', 1, { expires: 7, path: '/' }); $('#everypage').hide('slow'); return false;"><%= _('Close') %></a></p> + <p class="popup-close"><a href="#top" onclick="$.cookie('seen_foi2', 1, { expires: 7, path: '/' }); $('#everypage').hide('slow'); return false;"><%= _('Close') %></a></p> <%= @popup_banner %> - <p style="text-align: right"><a href="#top" onclick="$.cookie('seen_foi2', 1, { expires: 7, path: '/' }); $('#everypage').hide('slow'); return false;"><%= _('Close') %></a></p> + <p class="popup-close"><a href="#top" onclick="$.cookie('seen_foi2', 1, { expires: 7, path: '/' }); $('#everypage').hide('slow'); return false;"><%= _('Close') %></a></p> </div> <% end %> @@ -100,7 +100,7 @@ <% end %> <div id="navigation_search"> - <form id="navigation_search_form" method="post" action="/search"> + <form id="navigation_search_form" method="post" action="<%= search_redirect_path %>"> <p> <%= text_field_tag 'query', params[:query], { :size => 40, :id => "navigation_search_query" } %> <input id="navigation_search_button" type="submit" value="search"> @@ -140,11 +140,11 @@ </div> <% unless Configuration::ga_code.empty? || (@user && @user.super?) %> - <script> + <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> - <script> + <script type="text/javascript"> var pageTracker = _gat._getTracker("<%= Configuration::ga_code %>"); pageTracker._trackPageview(); </script> diff --git a/app/views/request/_correspondence.rhtml b/app/views/request/_correspondence.rhtml index bcfc93657..99c6c7d26 100644 --- a/app/views/request/_correspondence.rhtml +++ b/app/views/request/_correspondence.rhtml @@ -1,5 +1,5 @@ <div class="ff-print-fix"></div> -<% +<% if !info_request_event.nil? && info_request_event.event_type == 'response' incoming_message = info_request_event.incoming_message end @@ -21,9 +21,9 @@ if not incoming_message.nil? <p class="event_actions"> <% if !@user.nil? && @user.admin_page_links? %> - <%= link_to "Admin", admin_url("request/show_raw_email/" + incoming_message.raw_email_id.to_s) %> | + <%= link_to "Admin", admin_url("request/show_raw_email/" + incoming_message.raw_email_id.to_s) %> | <% end %> - <%= link_to _("Link to this"), incoming_message_url(incoming_message), :class => "link_to_this" %> + <%= link_to _("Link to this"), incoming_message_url(incoming_message), :class => "link_to_this" %> </p> </div> <% @@ -39,28 +39,28 @@ elsif [ 'sent', 'followup_sent' ].include?(info_request_event.event_type) <%= render :partial => 'bubble', :locals => { :body => outgoing_message.get_body_for_html_display(), :attachments => nil } %> - <p class="event_actions"> + <p class="event_actions"> <% if outgoing_message.status == 'ready' && !@info_request.is_external? %> <strong>Warning:</strong> This message has <strong>not yet been sent</strong> for an unknown reason. - <% end %> + <% end %> <!-- Can use this to get name of who followup was too, if say you play with proper from display, but not sure needed <% if outgoing_message.message_type == 'followup' && !outgoing_message.incoming_message_followup.nil? && !outgoing_message.incoming_message_followup.safe_mail_from.nil? %> - Follow up sent to: <%=h outgoing_message.incoming_message_followup.safe_mail_from %> - <% end %> + Follow up sent to: <%=h outgoing_message.incoming_message_followup.safe_mail_from %> + <% end %> --> - <%= link_to _("Link to this"), outgoing_message_url(outgoing_message), :class => "link_to_this" %> + <%= link_to _("Link to this"), outgoing_message_url(outgoing_message), :class => "link_to_this" %> </p> </div> <% elsif [ 'resent', 'followup_resent' ].include?(info_request_event.event_type) %> - <div class="outgoing correspondence" id="outgoing-<%=outgoing_message.id.to_s%>"> + <div class="outgoing correspondence" id="outgoing-<%=info_request_event.outgoing_message.id.to_s%>"> <h2> <%= simple_date(info_request_event.created_at) %> </h2> - <p class="event_plain"> - Sent + <p class="event_plain"> + Sent <% if info_request_event.outgoing_message.message_type == 'initial_request' %> request <% elsif info_request_event.outgoing_message.message_type == 'followup' %> @@ -72,7 +72,7 @@ elsif [ 'sent', 'followup_sent' ].include?(info_request_event.event_type) to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. </p> </div> -<% elsif info_request_event.event_type == 'comment' +<% elsif info_request_event.event_type == 'comment' comment = info_request_event.comment %> <%= render :partial => 'comment/single_comment', :locals => { :comment => comment } %> diff --git a/app/views/request/select_authority.rhtml b/app/views/request/select_authority.rhtml index 521136f8e..1166c3ff9 100644 --- a/app/views/request/select_authority.rhtml +++ b/app/views/request/select_authority.rhtml @@ -31,7 +31,7 @@ <div id="authority_selection"> <% form_tag({:controller => "request", :action => "select_authority"}, {:id => "search_form", :method => "get"}) do %> - <p> + <div> <p> <%= _('First, type in the <strong>name of the UK public authority</strong> you\'d like information from. <strong>By law, they have to respond</strong> @@ -40,7 +40,7 @@ <%= text_field_tag 'query', params[:query], { :size => 30 } %> <%= hidden_field_tag 'bodies', 1 %> <%= submit_tag _('Search') %> - </p> + </div> <% end %> <div id="typeahead_response"> <% if !@xapian_requests.nil? %> diff --git a/app/views/request/show.rhtml b/app/views/request/show.rhtml index cf1f971d9..7aff1aeab 100644 --- a/app/views/request/show.rhtml +++ b/app/views/request/show.rhtml @@ -22,8 +22,6 @@ </div> <% end %> -<%= render :partial => 'sidebar' %> - <div id="left_column"> <h1><%=h(@info_request.title)%></h1> @@ -148,3 +146,4 @@ <%= render :partial => 'after_actions' %> </div> +<%= render :partial => 'sidebar' %> diff --git a/app/views/user/_show_user_info.rhtml b/app/views/user/_show_user_info.rhtml index 5dfecee1e..3c229e9ce 100644 --- a/app/views/user/_show_user_info.rhtml +++ b/app/views/user/_show_user_info.rhtml @@ -1,7 +1,7 @@ <% if !@display_user.get_about_me_for_html_display.empty? || @is_you %> <div class="user_about_me"> - <img class="comment_quote" src="/images/quote.png" alt=""> + <img class="comment_quote" src="/images/quote-marks.png" alt=""> <%= @display_user.get_about_me_for_html_display %> <% if @is_you %> (<%= link_to _("edit text about you"), set_profile_about_me_url() %>) diff --git a/app/views/user/sign.rhtml b/app/views/user/sign.rhtml index 4704ea95a..6a1979155 100644 --- a/app/views/user/sign.rhtml +++ b/app/views/user/sign.rhtml @@ -1,16 +1,16 @@ + <% if !@post_redirect.nil? && @post_redirect.reason_params[:user_name] %> <% @title = _("Sign in") %> - <div id="sign_alone"> <p id="sign_in_reason"> <% if @post_redirect.reason_params[:web].empty? %> <%= _('Please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. <% else %> - <%= @post_redirect.reason_params[:web] %>, + <%= @post_redirect.reason_params[:web] %>, <%= _('please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>. <% end %> - </p> + </p> <% if @post_redirect.post_params["controller"] == "admin_general" %> <p id="superuser_message">Don't have a superuser account yet? <%= link_to "Sign in as the emergency user", @post_redirect.uri + "?emergency=1" %></p> <% end %> @@ -22,7 +22,16 @@ <% else %> <% @title = _('Sign in or make a new account') %> - <div id="sign_together"> + <div id="sign_together"> + <% if !@post_redirect.nil? %> + <p id="sign_in_reason"> + <% if @post_redirect.reason_params[:web].empty? %> + <%= _('Please sign in or make a new account.') %> + <% else %> + <%= _('{{reason}}, please sign in or make a new account.', :reason => @post_redirect.reason_params[:web]) %> + <% end %> + </p> + <% end %> <div id="left_half"> <h1><%= _('Sign in') %></h1> <%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => false } %> |