diff options
Diffstat (limited to 'app')
37 files changed, 494 insertions, 392 deletions
diff --git a/app/controllers/admin_censor_rule_controller.rb b/app/controllers/admin_censor_rule_controller.rb index dca312b8b..5381921bf 100644 --- a/app/controllers/admin_censor_rule_controller.rb +++ b/app/controllers/admin_censor_rule_controller.rb @@ -15,7 +15,7 @@ class AdminCensorRuleController < AdminController end def create - params[:censor_rule][:last_edit_editor] = admin_http_auth_user() + params[:censor_rule][:last_edit_editor] = admin_current_user() @censor_rule = CensorRule.new(params[:censor_rule]) if @censor_rule.save if !@censor_rule.info_request.nil? @@ -42,7 +42,7 @@ class AdminCensorRuleController < AdminController end def update - params[:censor_rule][:last_edit_editor] = admin_http_auth_user() + params[:censor_rule][:last_edit_editor] = admin_current_user() @censor_rule = CensorRule.find(params[:id]) if @censor_rule.update_attributes(params[:censor_rule]) if !@censor_rule.info_request.nil? diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index dd966c4af..d7933b212 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -45,12 +45,36 @@ class AdminController < ApplicationController end end + # For administration interface, return display name of authenticated user + def admin_current_user + if Configuration::skip_admin_auth + admin_http_auth_user + else + session[:admin_name] + end + end + + # If we're skipping Alaveteli admin authentication, assume that the environment + # will give us an authenticated user name + def admin_http_auth_user + # This needs special magic in mongrel: http://www.ruby-forum.com/topic/83067 + # Hence the second clause which reads X-Forwarded-User header if available. + # See the rewrite rules in conf/httpd.conf which set X-Forwarded-User + if request.env["REMOTE_USER"] + return request.env["REMOTE_USER"] + elsif request.env["HTTP_X_FORWARDED_USER"] + return request.env["HTTP_X_FORWARDED_USER"] + else + return "*unknown*"; + end + end + def authenticate if Configuration::skip_admin_auth session[:using_admin] = 1 return else - if session[:using_admin].nil? + if session[:using_admin].nil? || session[:admin_name].nil? if params[:emergency].nil? if authenticated?( :web => _("To log into the administrative interface"), @@ -59,11 +83,12 @@ class AdminController < ApplicationController :user_name => "a superuser") if !@user.nil? && @user.admin_level == "super" session[:using_admin] = 1 - request.env['REMOTE_USER'] = @user.url_name + session[:admin_name] = @user.url_name else session[:using_admin] = nil session[:user_id] = nil + session[:admin_name] = nil self.authenticate end end @@ -71,7 +96,7 @@ class AdminController < ApplicationController authenticate_or_request_with_http_basic do |user_name, password| if user_name == Configuration::admin_username && password == Configuration::admin_password session[:using_admin] = 1 - request.env['REMOTE_USER'] = user_name + session[:admin_name] = user_name else request_http_basic_authentication end diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index 5176eb8db..9f4c398c1 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -120,7 +120,7 @@ class AdminGeneralController < AdminController end def debug - @http_auth_user = admin_http_auth_user + @admin_current_user = admin_current_user @current_commit = `git log -1 --format="%H"` @current_branch = `git branch | perl -ne 'print $1 if /^\\* (.*)/'` @current_version = `git describe --always --tags` diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb index e64925bde..ac12e97b2 100644 --- a/app/controllers/admin_public_body_controller.rb +++ b/app/controllers/admin_public_body_controller.rb @@ -88,7 +88,7 @@ class AdminPublicBodyController < AdminController def create PublicBody.with_locale(I18n.default_locale) do - params[:public_body][:last_edit_editor] = admin_http_auth_user() + params[:public_body][:last_edit_editor] = admin_current_user() @public_body = PublicBody.new(params[:public_body]) if @public_body.save flash[:notice] = 'PublicBody was successfully created.' @@ -107,7 +107,7 @@ class AdminPublicBodyController < AdminController def update PublicBody.with_locale(I18n.default_locale) do - params[:public_body][:last_edit_editor] = admin_http_auth_user() + params[:public_body][:last_edit_editor] = admin_current_user() @public_body = PublicBody.find(params[:id]) if @public_body.update_attributes(params[:public_body]) flash[:notice] = 'PublicBody was successfully updated.' @@ -157,7 +157,7 @@ class AdminPublicBodyController < AdminController params[:tag], params[:tag_behaviour], true, - admin_http_auth_user(), + admin_current_user(), I18n.available_locales) if errors.size == 0 @@ -171,7 +171,7 @@ class AdminPublicBodyController < AdminController params[:tag], params[:tag_behaviour], false, - admin_http_auth_user(), + admin_current_user(), I18n.available_locales) if errors.size != 0 raise "dry run mismatched real run" diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index c97ef7f1e..3e574b10f 100644 --- a/app/controllers/admin_request_controller.rb +++ b/app/controllers/admin_request_controller.rb @@ -85,7 +85,7 @@ class AdminRequestController < AdminController if @info_request.valid? @info_request.save! @info_request.log_event("edit", - { :editor => admin_http_auth_user(), + { :editor => admin_current_user(), :old_title => old_title, :title => @info_request.title, :old_prominence => old_prominence, :prominence => @info_request.prominence, :old_described_state => old_described_state, :described_state => @info_request.described_state, @@ -128,7 +128,7 @@ class AdminRequestController < AdminController @outgoing_message.fully_destroy @outgoing_message.info_request.log_event("destroy_outgoing", - { :editor => admin_http_auth_user(), :deleted_outgoing_message_id => outgoing_message_id }) + { :editor => admin_current_user(), :deleted_outgoing_message_id => outgoing_message_id }) flash[:notice] = 'Outgoing message successfully destroyed.' redirect_to request_admin_url(@info_request) @@ -141,7 +141,7 @@ class AdminRequestController < AdminController if @outgoing_message.update_attributes(params[:outgoing_message]) @outgoing_message.info_request.log_event("edit_outgoing", - { :outgoing_message_id => @outgoing_message.id, :editor => admin_http_auth_user(), + { :outgoing_message_id => @outgoing_message.id, :editor => admin_current_user(), :old_body => old_body, :body => @outgoing_message.body }) flash[:notice] = 'Outgoing message successfully updated.' redirect_to request_admin_url(@outgoing_message.info_request) @@ -163,7 +163,7 @@ class AdminRequestController < AdminController if @comment.update_attributes(params[:comment]) @comment.info_request.log_event("edit_comment", - { :comment_id => @comment.id, :editor => admin_http_auth_user(), + { :comment_id => @comment.id, :editor => admin_current_user(), :old_body => old_body, :body => @comment.body, :old_visible => old_visible, :visible => @comment.visible, }) @@ -182,7 +182,7 @@ class AdminRequestController < AdminController @incoming_message.fully_destroy @incoming_message.info_request.log_event("destroy_incoming", - { :editor => admin_http_auth_user(), :deleted_incoming_message_id => incoming_message_id }) + { :editor => admin_current_user(), :deleted_incoming_message_id => incoming_message_id }) # expire cached files expire_for_request(@info_request) flash[:notice] = 'Incoming message successfully destroyed.' @@ -213,7 +213,7 @@ class AdminRequestController < AdminController incoming_message_id = incoming_message.id incoming_message.info_request.log_event("redeliver_incoming", { - :editor => admin_http_auth_user(), + :editor => admin_current_user(), :destination_request => destination_request.id, :deleted_incoming_message_id => incoming_message_id }) @@ -239,7 +239,7 @@ class AdminRequestController < AdminController info_request.user = destination_user info_request.save! info_request.log_event("move_request", { - :editor => admin_http_auth_user(), + :editor => admin_current_user(), :old_user_url_name => old_user.url_name, :user_url_name => destination_user.url_name }) @@ -257,7 +257,7 @@ class AdminRequestController < AdminController info_request.public_body = destination_public_body info_request.save! info_request.log_event("move_request", { - :editor => admin_http_auth_user(), + :editor => admin_current_user(), :old_public_body_url_name => old_public_body.url_name, :public_body_url_name => destination_public_body.url_name }) @@ -367,7 +367,7 @@ class AdminRequestController < AdminController info_request.prominence = "requester_only" info_request.log_event("hide", { - :editor => admin_http_auth_user(), + :editor => admin_current_user(), :reason => params[:reason], :subject => subject, :explanation => explanation diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f29015c63..3f3c169ae 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -340,20 +340,6 @@ class ApplicationController < ActionController::Base end - # For administration interface, return display name of authenticated user - def admin_http_auth_user - # This needs special magic in mongrel: http://www.ruby-forum.com/topic/83067 - # Hence the second clause which reads X-Forwarded-User header if available. - # See the rewrite rules in conf/httpd.conf which set X-Forwarded-User - if request.env["REMOTE_USER"] - return request.env["REMOTE_USER"] - elsif request.env["HTTP_X_FORWARDED_USER"] - return request.env["HTTP_X_FORWARDED_USER"] - else - return "*unknown*"; - end - end - # Convert URL name for sort by order, to Xapian query def order_to_sort_by(sortby) if sortby.nil? diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb index 150b433ec..0cde238cd 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -29,7 +29,7 @@ class GeneralController < ApplicationController PublicBody.with_locale(@locale) do if body_short_names.empty? # This is too slow - @popular_bodies = PublicBody.find(:all, + @popular_bodies = PublicBody.visible.find(:all, :order => "info_requests_count desc", :limit => 32, :conditions => conditions, @@ -58,6 +58,8 @@ class GeneralController < ApplicationController xapian_object = perform_search([InfoRequestEvent], query, sortby, 'request_title_collapse', max_count-@request_events.count) more_events = xapian_object.results.map { |r| r[:model] } @request_events += more_events + # Overall we still want the list sorted with the newest first + @request_events.sort!{|e1,e2| e2.created_at <=> e1.created_at} else @request_events_all_successful = true end @@ -71,7 +73,9 @@ class GeneralController < ApplicationController def blog medium_cache @feed_autodetect = [] - @feed_url = "#{Configuration::blog_feed}?lang=#{self.locale_from_params()}" + @feed_url = Configuration::blog_feed + separator = @feed_url.include?('?') ? '&' : '?' + @feed_url = "#{@feed_url}#{separator}lang=#{self.locale_from_params()}" @blog_items = [] if not @feed_url.empty? content = quietly_try_to_open(@feed_url) diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index b34e89b8d..8a4a65820 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -146,38 +146,7 @@ class PublicBodyController < ApplicationController end def list_all_csv - public_bodies = PublicBody.find(:all, :order => 'url_name', - :include => [:translations, :tags]) - report = FasterCSV.generate() do |csv| - csv << [ - 'Name', - 'Short name', - # deliberately not including 'Request email' - 'URL name', - 'Tags', - 'Home page', - 'Publication scheme', - 'Created at', - 'Updated at', - 'Version', - ] - public_bodies.each do |public_body| - csv << [ - public_body.name, - public_body.short_name, - # DO NOT include request_email (we don't want to make it - # easy to spam all authorities with requests) - public_body.url_name, - public_body.tag_string, - public_body.calculated_home_page, - public_body.publication_scheme, - public_body.created_at, - public_body.updated_at, - public_body.version, - ] - end - end - send_data(report, :type=> 'text/csv; charset=utf-8; header=present', + send_data(PublicBody.export_csv, :type=> 'text/csv; charset=utf-8; header=present', :filename => 'all-authorities.csv', :disposition =>'attachment', :encoding => 'utf8') end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index 3296db6b7..c732a4b32 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -44,7 +44,7 @@ class RequestController < ApplicationController end def show - if !Configuration::varnish_host.nil? + if !Configuration::varnish_host.blank? # If varnish is set up to accept PURGEs, then cache for a # long time long_cache @@ -876,7 +876,7 @@ class RequestController < ApplicationController Zip::ZipFile.open(file_path, Zip::ZipFile::CREATE) { |zipfile| convert_command = Configuration::html_to_pdf_command done = false - if File.exists?(convert_command) + if !convert_command.blank? && File.exists?(convert_command) url = "http://#{Configuration::domain}#{request_url(info_request)}?print_stylesheet=1" tempfile = Tempfile.new('foihtml2pdf') output = AlaveteliExternalCommand.run(convert_command, url, tempfile.path) diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index ead5d73b7..38bf51772 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -9,13 +9,13 @@ class ServicesController < ApplicationController iso_country_code = Configuration::iso_country_code.downcase if country_from_ip.downcase != iso_country_code found_country = WorldFOIWebsites.by_code(country_from_ip) - found_country_name = !found_country.nil? && found_country[:country_name] old_fgt_locale = FastGettext.locale begin FastGettext.locale = FastGettext.best_locale_in(request.env['HTTP_ACCEPT_LANGUAGE']) - if found_country_name - text = _("Hello! You can make Freedom of Information requests within {{country_name}} at {{link_to_website}}", :country_name => found_country_name, :link_to_website => "<a href=\"#{found_country[:url]}\">#{found_country[:name]}</a>") + if found_country && found_country[:country_name] && found_country[:url] && found_country[:name] + text = _("Hello! You can make Freedom of Information requests within {{country_name}} at {{link_to_website}}", + :country_name => found_country[:country_name], :link_to_website => "<a href=\"#{found_country[:url]}\">#{found_country[:name]}</a>") else current_country = WorldFOIWebsites.by_code(iso_country_code)[:country_name] text = _("Hello! We have an <a href=\"/help/alaveteli?country_name=#{CGI.escape(current_country)}\">important message</a> for visitors outside {{country_name}}", :country_name => current_country) diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb index 8e76b4c9f..51e081c88 100644 --- a/app/controllers/track_controller.rb +++ b/app/controllers/track_controller.rb @@ -180,7 +180,7 @@ class TrackController < ApplicationController new_medium = params[:track_medium] if new_medium == 'delete' track_thing.destroy - flash[:notice] = _("You are no longer following {{track_description}}", :track_description => track_thing.params[:list_description]) + flash[:notice] = _("You are no longer following {{track_description}}.", :track_description => track_thing.params[:list_description]) redirect_to params[:r] # Reuse code like this if we let medium change again. #elsif new_medium == 'email_daily' diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 810b3321e..4ee527bae 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -119,13 +119,13 @@ class UserController < ApplicationController @track_things = TrackThing.find(:all, :conditions => ["tracking_user_id = ? and track_medium = ?", @display_user.id, 'email_daily'], :order => 'created_at desc') for track_thing in @track_things # XXX factor out of track_mailer.rb - xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 20, 1) + xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 20, 1) feed_results += xapian_object.results.map {|x| x[:model]} end end @feed_results = Array(feed_results).sort {|x,y| y.created_at <=> x.created_at}.first(20) - + respond_to do |format| format.html { @has_json = true } format.json { render :json => @display_user.json_for_api } @@ -244,6 +244,7 @@ class UserController < ApplicationController session[:user_circumstance] = nil session[:remember_me] = false session[:using_admin] = nil + session[:admin_name] = nil end def signout self._do_signout diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 090359f1f..ab953cb25 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -43,7 +43,7 @@ module ApplicationHelper end content_tag(:div, - content_tag(:ul, error_messages), + content_tag(:ul, error_messages.join), html ) else @@ -108,7 +108,7 @@ module ApplicationHelper end def form_tag_id(object_name, method_name, locale=nil) - if locale.nil? + if locale.nil? return "#{sanitized_object_name(object_name.to_s)}_#{sanitized_method_name(method_name.to_s)}" else return "#{sanitized_object_name(object_name.to_s)}_#{sanitized_method_name(method_name.to_s)}__#{locale.to_s}" @@ -131,9 +131,5 @@ module ApplicationHelper return "#{exact_date} (#{ago_text})" end - def is_admin? - return !session[:using_admin].nil? || (!@user.nil? && @user.admin_level == "super") - end - end diff --git a/app/models/exim_log.rb b/app/models/exim_log.rb deleted file mode 100644 index abe198493..000000000 --- a/app/models/exim_log.rb +++ /dev/null @@ -1,129 +0,0 @@ -# == Schema Information -# Schema version: 114 -# -# Table name: exim_logs -# -# id :integer not null, primary key -# exim_log_done_id :integer -# info_request_id :integer -# order :integer not null -# line :text not null -# created_at :datetime not null -# updated_at :datetime not null -# - -# models/exim_log.rb: -# We load log file lines for requests in here, for display in the admin interface. -# -# Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ - -class EximLog < ActiveRecord::Base - belongs_to :info_request - belongs_to :exim_log_done - - # Load in exim log file from disk, or update if we already have it - # Assumes files are named with date, rather than cyclically. - # Doesn't do anything if file hasn't been modified since it was last loaded. - def EximLog.load_file(file_name) - file_name_db = file_name - is_gz = false - if file_name.include?(".gz") - is_gz = true - file_name_db = file_name.gsub(".gz", "") - end - - modified = File::stat(file_name).mtime - raise "EximLog.load_file: file not found " + file_name if modified.nil? - - ActiveRecord::Base.transaction do - # see if we already have it - done = EximLogDone.find_by_filename(file_name_db) - if !done.nil? - if modified.utc == done.last_stat.utc - # already have that, nothing to do - return - end - EximLog.delete_all "exim_log_done_id = " + done.id.to_s - end - if !done - done = EximLogDone.new - done.filename = file_name_db - end - done.last_stat = modified - - # scan the file - if is_gz - f = Zlib::GzipReader.open(file_name) - else - f = File.open(file_name, 'r') - end - order = 0 - for line in f - order = order + 1 - email_domain = Configuration::incoming_email_domain - emails = line.scan(/request-[^\s]+@#{email_domain}/).sort.uniq - for email in emails - info_request = InfoRequest.find_by_incoming_email(email) - if !info_request.nil? - exim_log = EximLog.new - exim_log.info_request = info_request - exim_log.exim_log_done = done - exim_log.line = line - exim_log.order = order - exim_log.save! - end - end - end - - # update done structure so we know when we last read this file - done.save! - end - end - - # Check that the last day of requests has been sent in Exim and we got the - # lines. Writes any errors to STDERR. This check is really mainly to - # check the envelope from is the request address, as Ruby is quite - # flaky with regard to that, and it is important for anti-spam reasons. - # XXX does this really check that, as the exim log just wouldn't pick - # up at all if the requests weren't sent that way as there would be - # no request- email in it? - def EximLog.check_recent_requests_have_been_sent - # Get all requests sent for from 2 to 10 days ago. The 2 day gap is - # because we load exim log lines via cron at best an hour after they - # are made) - irs = InfoRequest.find(:all, :conditions => [ "created_at < ? and created_at > ? and user_id is not null", Time.now() - 2.day, Time.now() - 10.days ] ) - - # Go through each request and check it - ok = true - for ir in irs - # Look for line showing request was sent - found = false - for exim_log in ir.exim_logs - test_outgoing = " <= " + ir.incoming_email + " " - if exim_log.line.include?(test_outgoing) - # Check the from value is the same (it always will be, but may as well - # be sure we are parsing the exim line right) - envelope_from = " from <" + ir.incoming_email + "> " - if !exim_log.line.include?(envelope_from) - $stderr.puts("unexpected parsing of exim line: [#{exim_log.line.chomp}]") - else - found = true - end - end - end - if !found - # It's very important the envelope from is set for avoiding spam filter reasons - this - # effectively acts as a check for that. - $stderr.puts("failed to find request sending Exim line for request id " + ir.id.to_s + " " + ir.url_title + " (check envelope from is being set to request address in Ruby, and load-exim-logs crontab is working)") # *** don't comment out this STDERR line, it is the point of the function! - ok = false - end - end - - return ok - end - -end - - - diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index fcb4671c5..60828e179 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -1,3 +1,5 @@ +# coding: utf-8 + # == Schema Information # Schema version: 114 # @@ -17,9 +19,6 @@ # last_parsed :datetime # mail_from :text # sent_at :datetime -# - -# encoding: UTF-8 # models/incoming_message.rb: # An (email) message from really anybody to be logged with a request. e.g. A @@ -75,11 +74,10 @@ class IncomingMessage < ActiveRecord::Base # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ def mail(force = nil) if (!force.nil? || @mail.nil?) && !self.raw_email.nil? - # Hack round bug in TMail's MIME decoding. Example request which provokes it: - # http://www.whatdotheyknow.com/request/reviews_of_unduly_lenient_senten#incoming-4830 + # 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+"/ims,'; boundary="') + copy_of_raw_data = self.raw_email.data.gsub(/; boundary=\s+"/im,'; boundary="') @mail = TMail::Mail.parse(copy_of_raw_data) @mail.base64_decode @@ -291,7 +289,7 @@ class IncomingMessage < ActiveRecord::Base logger.warn "Unable to compress PDF; problem with your pdftk version?" end if !recompressed_text.nil? && !recompressed_text.empty? - text[0..-1] = recompressed_text # [0..-1] makes it change the 'text' string in place + text.replace recompressed_text end end end @@ -345,16 +343,15 @@ class IncomingMessage < ActiveRecord::Base name = Regexp.escape(self.info_request.user_name) # To end of message sections - # http://www.whatdotheyknow.com/request/university_investment_in_the_arm - text.gsub!(/^#{name}[^\n]+\nSent by:[^\n]+\n.*/ims, "\n\n" + replacement) + text.gsub!(/^\s?#{name}[^\n]+\n([^\n]+\n)?\s?Sent by:[^\n]+\n.*/im, "\n\n" + replacement) # Some other sort of forwarding quoting - # http://www.whatdotheyknow.com/request/224/response/326 - text.gsub!(/^#{name}[^\n]+\n[0-9\/:\s]+\s+To\s+FOI requests at.*/ims, "\n\n" + replacement) + text.gsub!(/^\s?#{name}\s+To\s+FOI requests at.*/im, "\n\n" + replacement) + - # http://www.whatdotheyknow.com/request/how_do_the_pct_deal_with_retirin_33#incoming-930 # http://www.whatdotheyknow.com/request/229/response/809 - text.gsub!(/^From: [^\n]+\nSent: [^\n]+\nTo:\s+['"?]#{name}['"]?\nSubject:.*/ims, "\n\n" + replacement) + text.gsub!(/^\s?From: [^\n]+\n\s?Sent: [^\n]+\n\s?To:\s+['"]?#{name}['"]?\n\s?Subject:.*/im, "\n\n" + replacement) + return text @@ -397,7 +394,7 @@ class IncomingMessage < ActiveRecord::Base # http://www.whatdotheyknow.com/request/police_powers_to_inform_car_insu # http://www.whatdotheyknow.com/request/secured_convictions_aided_by_cct multiline_original_message = '(' + '''>>>.* \d\d/\d\d/\d\d\d\d\s+\d\d:\d\d(?::\d\d)?\s*>>>''' + ')' - text.gsub!(/^(#{multiline_original_message}\n.*)$/ms, replacement) + text.gsub!(/^(#{multiline_original_message}\n.*)$/m, replacement) # Single line sections text.gsub!(/^(>.*\n)/, replacement) @@ -568,7 +565,7 @@ class IncomingMessage < ActiveRecord::Base text = self.get_main_body_text_internal # Strip the uudecode parts from main text # - this also effectively does a .dup as well, so text mods don't alter original - text = text.split(/^begin.+^`\n^end\n/sm).join(" ") + text = text.split(/^begin.+^`\n^end\n/m).join(" ") if text.size > 1000000 # 1 MB ish raise "main body text more than 1 MB, need to implement clipping like for attachment text, or there is some other MIME decoding problem or similar" @@ -580,7 +577,8 @@ class IncomingMessage < ActiveRecord::Base # Remove existing quoted sections folded_quoted_text = self.remove_lotus_quoting(text, 'FOLDED_QUOTED_SECTION') - folded_quoted_text = IncomingMessage.remove_quoted_sections(text, "FOLDED_QUOTED_SECTION") + folded_quoted_text = IncomingMessage.remove_quoted_sections(folded_quoted_text, "FOLDED_QUOTED_SECTION") + self.cached_main_body_text_unfolded = text self.cached_main_body_text_folded = folded_quoted_text self.save! @@ -706,7 +704,7 @@ class IncomingMessage < ActiveRecord::Base # Returns attachments that are uuencoded in main body part def _uudecode_and_save_attachments(text) # Find any uudecoded things buried in it, yeuchly - uus = text.scan(/^begin.+^`\n^end\n/sm) + uus = text.scan(/^begin.+^`\n^end\n/m) attachments = [] for uu in uus # Decode the string diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 85168e6d4..89893a396 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -47,10 +47,12 @@ class InfoRequest < ActiveRecord::Base has_many :track_things, :order => 'created_at desc' has_many :comments, :order => 'created_at' has_many :censor_rules, :order => 'created_at desc' - has_many :exim_logs, :order => 'exim_log_done_id' + has_many :mail_server_logs, :order => 'mail_server_log_done_id' has_tag_string + named_scope :visible, :conditions => {:prominence => "normal"} + # user described state (also update in info_request_event, admin_request/edit.rhtml) validate :must_be_valid_state @@ -582,12 +584,11 @@ public # waiting_classification # waiting_response_overdue # waiting_response_very_overdue - def calculate_status - if @@custom_states_loaded - return self.theme_calculate_status - else - self.base_calculate_status + def calculate_status(cached_value_ok=false) + if cached_value_ok && @cached_calculated_status + return @cached_calculated_status end + @cached_calculated_status = @@custom_states_loaded ? self.theme_calculate_status : self.base_calculate_status end def base_calculate_status @@ -869,8 +870,8 @@ public end end - def display_status - InfoRequest.get_status_description(self.calculate_status) + def display_status(cached_value_ok=false) + InfoRequest.get_status_description(self.calculate_status(cached_value_ok)) end # Completely delete this request and all objects depending on it @@ -884,8 +885,8 @@ public info_request_event.track_things_sent_emails.each { |a| a.destroy } info_request_event.destroy end - self.exim_logs.each do |exim_log| - exim_log.destroy + self.mail_server_logs.each do |mail_server_log| + mail_server_log.destroy end self.outgoing_messages.each { |a| a.destroy } self.incoming_messages.each { |a| a.destroy } @@ -1138,7 +1139,7 @@ public before_save :purge_in_cache def purge_in_cache - if !Configuration::varnish_host.nil? && !self.id.nil? + if !Configuration::varnish_host.blank? && !self.id.nil? # we only do this for existing info_requests (new ones have a nil id) path = url_for(:controller => 'request', :action => 'show', :url_title => self.url_title, :only_path => true, :locale => :none) req = PurgeRequest.find_by_url(path) diff --git a/app/models/mail_server_log.rb b/app/models/mail_server_log.rb new file mode 100644 index 000000000..755584b90 --- /dev/null +++ b/app/models/mail_server_log.rb @@ -0,0 +1,201 @@ +# == Schema Information +# Schema version: 20121010214348 +# +# Table name: mail_server_logs +# +# id :integer not null, primary key +# mail_server_log_done_id :integer +# info_request_id :integer +# order :integer not null +# line :text not null +# created_at :datetime not null +# updated_at :datetime not null +# + +# We load log file lines for requests in here, for display in the admin interface. +# +# Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved. +# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ +# +# $Id: exim_log.rb,v 1.14 2009-09-17 21:10:05 francis Exp $ + +class MailServerLog < ActiveRecord::Base + belongs_to :info_request + belongs_to :mail_server_log_done + + # Load in exim or postfix log file from disk, or update if we already have it + # Assumes files are named with date, rather than cyclically. + # Doesn't do anything if file hasn't been modified since it was last loaded. + # Note: If you do use rotated log files (rather than files named by date), at some + # point old loaded log lines will get deleted in the database. + def MailServerLog.load_file(file_name) + is_gz = file_name.include?(".gz") + file_name_db = is_gz ? file_name.gsub(".gz", "") : file_name + + modified = File.stat(file_name).mtime + raise "MailServerLog.load_file: file not found " + file_name if modified.nil? + + ActiveRecord::Base.transaction do + # see if we already have it + done = MailServerLogDone.find_by_filename(file_name_db) + if done + if modified.utc == done.last_stat.utc + # already have that, nothing to do + return + else + MailServerLog.delete_all "mail_server_log_done_id = " + done.id.to_s + end + else + done = MailServerLogDone.new(:filename => file_name_db) + end + done.last_stat = modified + # update done structure so we know when we last read this file + done.save! + + f = is_gz ? Zlib::GzipReader.open(file_name) : File.open(file_name, 'r') + case(Configuration::mta_log_type.to_sym) + when :exim + load_exim_log_data(f, done) + when :postfix + load_postfix_log_data(f, done) + else + raise "Unexpected MTA type: #{type}" + end + end + end + + # Scan the file + def MailServerLog.load_exim_log_data(f, done) + order = 0 + f.each do |line| + order = order + 1 + emails = email_addresses_on_line(line) + for email in emails + info_request = InfoRequest.find_by_incoming_email(email) + if info_request + info_request.mail_server_logs.create!(:line => line, :order => order, :mail_server_log_done => done) + else + puts "Warning: Could not find request with email #{email}" + end + end + end + end + + def MailServerLog.load_postfix_log_data(f, done) + order = 0 + emails = scan_for_postfix_queue_ids(f) + # Go back to the beginning of the file + f.rewind + f.each do |line| + order = order + 1 + queue_id = extract_postfix_queue_id_from_syslog_line(line) + if emails.has_key?(queue_id) + emails[queue_id].each do |email| + info_request = InfoRequest.find_by_incoming_email(email) + if info_request + info_request.mail_server_logs.create!(:line => line, :order => order, :mail_server_log_done => done) + else + puts "Warning: Could not find request with email #{email}" + end + end + end + end + end + + def MailServerLog.scan_for_postfix_queue_ids(f) + result = {} + f.each do |line| + emails = email_addresses_on_line(line) + queue_id = extract_postfix_queue_id_from_syslog_line(line) + result[queue_id] = [] unless result.has_key?(queue_id) + result[queue_id] = (result[queue_id] + emails).uniq + end + result + end + + # Retuns nil if there is no queue id + def MailServerLog.extract_postfix_queue_id_from_syslog_line(line) + # Assume the log file was written using syslog and parse accordingly + m = SyslogProtocol.parse("<13>" + line).content.match(/^\S+: (\S+):/) + m[1] if m + end + + # We also check the email prefix so that we could, for instance, separately handle a staging and production + # instance running on the same server with different email prefixes. + def MailServerLog.email_addresses_on_line(line) + prefix = Regexp::quote(Configuration::incoming_email_prefix) + domain = Regexp::quote(Configuration::incoming_email_domain) + line.scan(/#{prefix}request-[^\s]+@#{domain}/).sort.uniq + end + + def MailServerLog.request_sent?(ir) + case(Configuration::mta_log_type.to_sym) + when :exim + request_exim_sent?(ir) + when :postfix + request_postfix_sent?(ir) + else + raise "Unexpected MTA type: #{type}" + end + end + + # Look at the log for a request and check that an email was delivered + def MailServerLog.request_exim_sent?(ir) + # Look for line showing request was sent + found = false + ir.mail_server_logs.each do |mail_server_log| + test_outgoing = " <= " + ir.incoming_email + " " + if mail_server_log.line.include?(test_outgoing) + # Check the from value is the same (it always will be, but may as well + # be sure we are parsing the exim line right) + envelope_from = " from <" + ir.incoming_email + "> " + if !mail_server_log.line.include?(envelope_from) + $stderr.puts("unexpected parsing of exim line: [#{mail_server_log.line.chomp}]") + else + found = true + end + end + end + found + end + + def MailServerLog.request_postfix_sent?(ir) + # dsn=2.0.0 is the magic word that says that postfix delivered the email + # See http://tools.ietf.org/html/rfc3464 + ir.mail_server_logs.any? { |l| l.line.include?("dsn=2.0.0") } + end + + # Check that the last day of requests has been sent in Exim or Postfix and we got the + # lines. Writes any errors to STDERR. This check is really mainly to + # check the envelope from is the request address, as Ruby is quite + # flaky with regard to that, and it is important for anti-spam reasons. + # XXX does this really check that, as the log just wouldn't pick + # up at all if the requests weren't sent that way as there would be + # no request- email in it? + # + # NB: There can be several emails involved in a request. This just checks that + # at least one of them has been succesfully sent. + # + def MailServerLog.check_recent_requests_have_been_sent + # Get all requests sent for from 2 to 10 days ago. The 2 day gap is + # because we load mail server log lines via cron at best an hour after they + # are made) + irs = InfoRequest.find(:all, :conditions => [ "created_at < ? and created_at > ? and user_id is not null", Time.now() - 2.day, Time.now() - 10.days ] ) + + # Go through each request and check it + ok = true + irs.each do |ir| + unless request_sent?(ir) + # It's very important the envelope from is set for avoiding spam filter reasons - this + # effectively acts as a check for that. + $stderr.puts("failed to find request sending in MTA logs for request id " + ir.id.to_s + " " + ir.url_title + " (check envelope from is being set to request address in Ruby, and load-mail-server-logs crontab is working)") # *** don't comment out this STDERR line, it is the point of the function! + ok = false + end + end + ok + end + +end + + + diff --git a/app/models/exim_log_done.rb b/app/models/mail_server_log_done.rb index 86574a4cd..3fb20f0b3 100644 --- a/app/models/exim_log_done.rb +++ b/app/models/mail_server_log_done.rb @@ -1,7 +1,7 @@ # == Schema Information -# Schema version: 114 +# Schema version: 20121010214348 # -# Table name: exim_log_dones +# Table name: mail_server_log_dones # # id :integer not null, primary key # filename :text not null @@ -10,14 +10,13 @@ # updated_at :datetime not null # -# models/exim_log_done.rb: -# Stores that a particular exim file has been loaded in, see exim_log.rb +# Stores that a particular mail server log file has been loaded in, see mail_server_log.rb # # Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ -class EximLogDone < ActiveRecord::Base - has_many :exim_logs +class MailServerLogDone < ActiveRecord::Base + has_many :mail_server_logs end diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb index 0e547d493..2e98e1021 100644 --- a/app/models/outgoing_message.rb +++ b/app/models/outgoing_message.rb @@ -151,7 +151,7 @@ class OutgoingMessage < ActiveRecord::Base raise "Message id #{self.id} has type '#{self.message_type}' which validate can't handle" end end - if self.body =~ /#{get_signoff}\s*\Z/ms + if self.body =~ /#{get_signoff}\s*\Z/m errors.add(:body, _("Please sign at the bottom with your name, or alter the \"%{signoff}\" signature" % { :signoff => get_signoff })) end if !MySociety::Validate.uses_mixed_capitals(self.body) diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 34bcd332c..57fe27767 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -17,7 +17,7 @@ # notes :text default(""), not null # first_letter :string(255) not null # publication_scheme :text default(""), not null -# api_key :string(255) +# api_key :string(255) not null # info_requests_count :integer default(0), not null # @@ -42,6 +42,12 @@ class PublicBody < ActiveRecord::Base has_tag_string before_save :set_api_key, :set_default_publication_scheme + # Every public body except for the internal admin one is visible + named_scope :visible, lambda { + { + :conditions => "public_bodies.id <> #{PublicBody.internal_admin_body.id}" + } + } translates :name, :short_name, :request_email, :url_name, :notes, :first_letter, :publication_scheme @@ -407,7 +413,7 @@ class PublicBody < ActiveRecord::Base next end - field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'home_page', 'tag_string'] + field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'disclosure_log', 'home_page', 'tag_string'] if public_body = bodies_by_name[name] # Existing public body available_locales.each do |locale| @@ -494,6 +500,45 @@ class PublicBody < ActiveRecord::Base return [errors, notes] end + # Returns all public bodies (except for the internal admin authority) as csv + def self.export_csv + public_bodies = PublicBody.visible.find(:all, :order => 'url_name', + :include => [:translations, :tags]) + FasterCSV.generate() do |csv| + csv << [ + 'Name', + 'Short name', + # deliberately not including 'Request email' + 'URL name', + 'Tags', + 'Home page', + 'Publication scheme', + 'Disclosure log', + 'Notes', + 'Created at', + 'Updated at', + 'Version', + ] + public_bodies.each do |public_body| + csv << [ + public_body.name, + public_body.short_name, + # DO NOT include request_email (we don't want to make it + # easy to spam all authorities with requests) + public_body.url_name, + public_body.tag_string, + public_body.calculated_home_page, + public_body.publication_scheme, + public_body.disclosure_log, + public_body.notes, + public_body.created_at, + public_body.updated_at, + public_body.version, + ] + end + end + end + # Does this user have the power of FOI officer for this body? def is_foi_officer?(user) user_domain = user.email_domain diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index d1cef4d4d..2a61eb858 100644 --- a/app/models/track_thing.rb +++ b/app/models/track_thing.rb @@ -107,7 +107,12 @@ class TrackThing < ActiveRecord::Base end descriptions = [] if varieties.include? _("requests") - descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).sort.join(_(' or '))) + if statuses.empty? + # HACK: Relies on the 'descriptions.sort' below to luckily put this first + descriptions << _("all requests") + else + descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).sort.join(_(' or '))) + end varieties -= [_("requests")] end if descriptions.empty? and varieties.empty? diff --git a/app/models/user.rb b/app/models/user.rb index 59f6c971c..70386f7e4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -246,6 +246,11 @@ class User < ActiveRecord::Base # Does the user magically gain powers as if they owned every request? # e.g. Can classify it def owns_every_request? + self.super? + end + + # Does this user have extraordinary powers? + def super? self.admin_level == 'super' end @@ -255,18 +260,18 @@ class User < ActiveRecord::Base # Can the user see every request, even hidden ones? def User.view_hidden_requests?(user) - !user.nil? && user.admin_level == 'super' + !user.nil? && user.super? end # Should the user be kept logged into their own account # if they follow a /c/ redirect link belonging to another user? def User.stay_logged_in_on_redirect?(user) - !user.nil? && user.admin_level == 'super' + !user.nil? && user.super? end # Does the user get "(admin)" links on each page on the main site? def admin_page_links? - self.admin_level == 'super' + self.super? end # Is it public that they are banned? def public_banned? @@ -281,7 +286,7 @@ class User < ActiveRecord::Base return false if self.no_limit # Has the user issued as many as MAX_REQUESTS_PER_USER_PER_DAY requests in the past 24 hours? - return false if Configuration::max_requests_per_user_per_day.nil? + return false if Configuration::max_requests_per_user_per_day.blank? recent_requests = InfoRequest.count(:conditions => ["user_id = ? and created_at > now() - '1 day'::interval", self.id]) return (recent_requests >= Configuration::max_requests_per_user_per_day) diff --git a/app/views/admin_general/debug.rhtml b/app/views/admin_general/debug.rhtml index d7bf1c6da..99488ba0c 100644 --- a/app/views/admin_general/debug.rhtml +++ b/app/views/admin_general/debug.rhtml @@ -2,7 +2,7 @@ <h1><%=@title%></h1> -<p>You are <%= h @http_auth_user %></p> +<p>You are <%= h @admin_current_user %></p> <h2>Version numbers</h2> diff --git a/app/views/admin_public_body/_form.rhtml b/app/views/admin_public_body/_form.rhtml index d854b53f5..0d6ae51e2 100644 --- a/app/views/admin_public_body/_form.rhtml +++ b/app/views/admin_public_body/_form.rhtml @@ -38,6 +38,9 @@ <p><label for="<%= form_tag_id(t.object_name, :publication_scheme, locale) %>">Publication scheme URL</label><br/> <%= t.text_field :publication_scheme, :size => 60, :id => form_tag_id(t.object_name, :publication_scheme, locale) %></p> + <p><label for="<%= form_tag_id(t.object_name, :disclosure_log, locale) %>">Disclosure log URL</label><br/> + <%= t.text_field :disclosure_log, :size => 60, :id => form_tag_id(t.object_name, :disclosure_log, locale) %></p> + <p><label for="<%= form_tag_id(t.object_name, :notes, locale) %>">Public notes</label> <small>(HTML, for users to consider when making FOI requests to the authority)</small><br/> <%= t.text_area :notes, :rows => 3, :cols => 60, :id => form_tag_id(t.object_name, :notes, locale) %></p> </div> diff --git a/app/views/admin_public_body/import_csv.rhtml b/app/views/admin_public_body/import_csv.rhtml index 4a03d0665..62908ba52 100644 --- a/app/views/admin_public_body/import_csv.rhtml +++ b/app/views/admin_public_body/import_csv.rhtml @@ -51,7 +51,7 @@ </blockquote> <p>Supported fields: name (i18n), short_name (i18n), request_email (i18n), notes (i18n), - publication_scheme (i18n), home_page, tag_string (tags separated by spaces).</p> + publication_scheme (i18n), disclosure_log (i18n), home_page, tag_string (tags separated by spaces).</p> <p><strong>Note:</strong> Choose <strong>dry run</strong> to test, without actually altering the database. Choose <strong>upload</strong> to actually diff --git a/app/views/admin_public_body/show.rhtml b/app/views/admin_public_body/show.rhtml index fa17d4027..094007c02 100644 --- a/app/views/admin_public_body/show.rhtml +++ b/app/views/admin_public_body/show.rhtml @@ -9,9 +9,9 @@ for column in columns %> <b><%= column.human_name %>:</b> - <% if column.name == 'home_page' and !column.name.empty? %> + <% if ['home_page', 'publication_scheme', 'disclosure_log'].include? column.name %> <%= link_to(h(@public_body.send(column.name)), @public_body.send(column.name)) %> - <% elsif column.name == 'request_email' and !column.name.empty? %> + <% elsif column.name == 'request_email' %> <%= link_to(h(@public_body.send(column.name)), "mailto:#{@public_body.send(column.name)}") %> <% if !@public_body.is_requestable? %> (not requestable due to: <%=h @public_body.not_requestable_reason %><% if @public_body.is_followupable? %>; but followupable<% end %>) diff --git a/app/views/admin_request/show.rhtml b/app/views/admin_request/show.rhtml index 9d939eb35..2541fd323 100644 --- a/app/views/admin_request/show.rhtml +++ b/app/views/admin_request/show.rhtml @@ -213,15 +213,15 @@ -<h2>Exim delivery logs</h2> +<h2>Mail server delivery logs</h2> <p><i>(Lines containing the request incoming email address, updated hourly.)</i></p> -<% for exim_log_done_id, exim_logs in @info_request.exim_logs.group_by(&:exim_log_done_id) %> - <!-- <h3><%=h exim_logs[0].exim_log_done.filename %></h3> --> - <pre><% for exim_log in exim_logs %><%=h exim_log.line%><% end %></pre> +<% for mail_server_log_done_id, mail_server_logs in @info_request.mail_server_logs.group_by(&:mail_server_log_done_id) %> + <!-- <h3><%=h mail_server_logs[0].mail_server_log_done.filename %></h3> --> + <pre><% for mail_server_log in mail_server_logs %><%=h mail_server_log.line%><% end %></pre> <% end %> -<% if @info_request.exim_logs.size == 0 %> +<% if @info_request.mail_server_logs.size == 0 %> <p>None (perhaps this is an old or a very new request)</p> <% end %> diff --git a/app/views/general/_frontpage_bodies_list.rhtml b/app/views/general/_frontpage_bodies_list.rhtml new file mode 100644 index 000000000..503b38953 --- /dev/null +++ b/app/views/general/_frontpage_bodies_list.rhtml @@ -0,0 +1,17 @@ +<% if @popular_bodies.size > 0 %> + <div id="examples_0"> + <h3><%= _("Who can I request information from?") %></h3> + <%= _("{{site_name}} covers requests to {{number_of_authorities}} authorities, including:", + :site_name => site_name, :number_of_authorities => PublicBody.visible.count) %> + <ul> + <% for popular_body in @popular_bodies %> + <li><%=public_body_link(popular_body)%> + <%= n_('%d request', '%d requests', popular_body.info_requests_count) % popular_body.info_requests_count %> + </li> + <% end%> + </ul> + <p><strong> + <%= link_to _('Browse all authorities...'), list_public_bodies_default %> + </strong></p> + </div> +<% end %> diff --git a/app/views/general/_frontpage_new_request.rhtml b/app/views/general/_frontpage_new_request.rhtml new file mode 100644 index 000000000..fd4225069 --- /dev/null +++ b/app/views/general/_frontpage_new_request.rhtml @@ -0,0 +1,7 @@ +<h1> + <%= _("Make a new<br/> + <strong>Freedom <span>of</span><br/> + Information<br/> + request</strong>") %> +</h1> +<a class="link_button_green_large" href="/select_authority"><%= _("Start now »") %></a> diff --git a/app/views/general/_frontpage_requests_list.rhtml b/app/views/general/_frontpage_requests_list.rhtml new file mode 100644 index 000000000..3b0efb65e --- /dev/null +++ b/app/views/general/_frontpage_requests_list.rhtml @@ -0,0 +1,35 @@ +<div id="examples_1"> + <h3> + <% if @request_events_all_successful %> + <%= _("What information has been released?") %> + <% else %> + <%= _("What information has been requested?") %> + <% end %> + </h3> + <%= _("{{site_name}} users have made {{number_of_requests}} requests, including:", + :site_name => site_name, :number_of_requests => InfoRequest.visible.count) %> + <ul> + <% for event in @request_events %> + <li> + <% if @request_events_all_successful %> + <%= _("{{public_body_link}} answered a request about", + :public_body_link => public_body_link(event.info_request.public_body)) %> + <% else %> + <%= _("{{public_body_link}} was sent a request about", + :public_body_link => public_body_link(event.info_request.public_body)) %> + <% end %> + + <%=link_to h(event.info_request.title), request_url(event.info_request)%> + <%= _('{{length_of_time}} ago', :length_of_time => time_ago_in_words(event.described_at)) %> + <p class="excerpt" onclick="document.location.href='<%=request_url(event.info_request)%>'"><%= excerpt(event.search_text_main(true), "", 200) %></p> + </li> + <% end %> + </ul> + <p><strong> + <% if @request_events_all_successful %> + <%=link_to _('More successful requests...'), request_list_successful_url %> + <% else %> + <%=link_to _('More requests...'), request_list_all_url %> + <% end %> + </strong></p> +</div> diff --git a/app/views/general/_frontpage_search_box.rhtml b/app/views/general/_frontpage_search_box.rhtml new file mode 100644 index 000000000..6de4eae98 --- /dev/null +++ b/app/views/general/_frontpage_search_box.rhtml @@ -0,0 +1,12 @@ +<h2> + <%= _("Search over<br/> + <strong>{{number_of_requests}} requests</strong> <span>and</span><br/> + <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"> + <div> + <input id="query" type="text" size="30" name="query"> + <input type="submit" value="<%= _('Search') %>"> + </div> +</form> diff --git a/app/views/general/blog.rhtml b/app/views/general/blog.rhtml index a80f167d8..5258e9bbd 100644 --- a/app/views/general/blog.rhtml +++ b/app/views/general/blog.rhtml @@ -7,53 +7,34 @@ <img src="/images/twitter-16.png" alt="twitter icon" class="twitter-icon"> <a href="https://twitter.com/<%= @twitter_user %>"><%= _("Follow us on twitter") %></a><br/><br/> <img src="/images/feed-16.png" alt="RSS icon" valign="middle"> <a href="<%= @feed_url %>"><%= _("Subscribe to blog") %></a> </div> + <% if Configuration::twitter_widget_id %> <div id="twitter"> - <script src="http://widgets.twimg.com/j/2/widget.js"></script> - <script type="text/javascript"> - new TWTR.Widget({ - version: 2, - type: 'profile', - rpp: 15, - interval: 6000, - width: 'auto', - height: 500, - theme: { - shell: { - background: '#eaeaea', - color: '#000000' - }, - tweets: { - background: '#ffffff', - color: '#000000', - links: '#0b004a' - } - }, - features: { - scrollbar: false, - loop: false, - live: false, - hashtags: true, - timestamp: true, - avatars: true, - behavior: 'all' - } - }).render().setUser('<%=@twitter_user %>').start(); - </script> + <a class="twitter-timeline" data-dnt=true href="https://twitter.com/<%= Configuration::twitter_username %>" data-widget-id="<%= Configuration::twitter_widget_id %>">Tweets by @<%= Configuration::twitter_username %></a> + <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script> </div> + <% end %> </div> <% end %> <div id="left_column"> <h1><%=@title %></h1> - + <div id="blog"> <% for item in @blog_items: %> <div class="blog_post"> <h2 id="<%= Time.parse(item['pubDate'][0]).to_i %>"><a href="<%=item['link']%>"><%=h item['title'] %></a></h2> <p class="subtitle"><%= _("Posted on {{date}} by {{author}}", :date=>simple_date(Time.parse(item['pubDate'][0])), :author=>item['creator']) %></p> - <div><%= item['encoded'] %></div> + <div> + <% if item['encoded'] %> + <%= item['encoded'] %> + <% elsif item['description'] %> + <%= item['description'] %> + <% end %> + </div> <p><em> + <% if item['comments'] %> <a href="<%=item['comments'][0]%>"><%= _("{{number_of_comments}} comments", :number_of_comments=>item['comments'][1]) %></a> + <% end %> </em> </p> </div> diff --git a/app/views/general/frontpage.rhtml b/app/views/general/frontpage.rhtml index e2d74a5e2..acc7f4095 100644 --- a/app/views/general/frontpage.rhtml +++ b/app/views/general/frontpage.rhtml @@ -1,28 +1,11 @@ <% view_cache :ttl => 5.minutes.to_i, :tag => I18n.locale do %> <div id="frontpage_splash"> <div id="left_column"> - <h1> - <%= _("Make a new<br/> - <strong>Freedom <span>of</span><br/> - Information<br/> - request</strong>") %> - </h1> - <a class="link_button_green_large" href="/select_authority"><%= _("Start now »") %></a> + <%= render :partial => "frontpage_new_request" %> </div> <div id="right_column"> <div id="frontpage_search_box"> - <h2> - <%= _("Search over<br/> - <strong>{{number_of_requests}} requests</strong> <span>and</span><br/> - <strong>{{number_of_authorities}} authorities</strong>", - :number_of_requests => InfoRequest.count, :number_of_authorities => PublicBody.count) %> - </h2> - <% form_tag({:action => "search_redirect"}, {:id => "search_form"}) do %> - <div> - <%= text_field_tag 'query', params[:query], { :size => 30 } %> - <%= submit_tag _('Search') %> - </div> - <% end %> + <%= render :partial => "frontpage_search_box" %> </div> <div id="frontpage_right_to_know"> <%= render :partial => 'frontpage_intro_sentence' %> @@ -30,55 +13,8 @@ </div> <div style="clear:both"></div> </div> - -<div id="frontpage_examples"> - <% if @popular_bodies.size > 0 %> - <div id="examples_0"> - <h3><%= _("Who can I request information from?") %></h3> - <%= _("{{site_name}} covers requests to {{number_of_authorities}} authorities, including:", - :site_name => site_name, :number_of_authorities => PublicBody.count) %> - <ul> - <% for popular_body in @popular_bodies %> - <li><%=public_body_link(popular_body)%> - <%= n_('%d request', '%d requests', popular_body.info_requests_count) % popular_body.info_requests_count %> - </li> - <% end%> - </ul> - <p><strong> - <%= link_to _('Browse all authorities...'), list_public_bodies_default %> - </strong></p> - </div> - <% end %> - - <div id="examples_1"> - <h3> - <% if @request_events_all_successful %> - <%= _("What information has been released?") %> - <% else %> - <%= _("What information has been requested?") %> - <% end %> - </h3> - <%= _("{{site_name}} users have made {{number_of_requests}} requests, including:", - :site_name => site_name, :number_of_requests => InfoRequest.count) %> - <ul> - <% for event in @request_events %> - <li> - <%= public_body_link(event.info_request.public_body) %> <%= _('answered a request about') %> - <%=link_to h(event.info_request.title), request_url(event.info_request)%> - <%= _('{{length_of_time}} ago', :length_of_time => time_ago_in_words(event.described_at)) %> - <p class="excerpt" onclick="document.location.href='<%=request_url(event.info_request)%>'"><%= excerpt(event.search_text_main(true), "", 200) %></p> - </li> - <% end %> - </ul> - <p><strong> - <% if @request_events_all_successful %> - <%=link_to _('More successful requests...'), request_list_successful_url %> - <% else %> - <%=link_to _('More requests...'), request_list_all_url %> - <% end %> - </strong></p> - </div> -</div> - - + <div id="frontpage_examples"> + <%= render :partial => "frontpage_bodies_list" %> + <%= render :partial => "frontpage_requests_list" %> + </div> <% end %> diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml index 0dd493fd0..76bdbd2dd 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 is_admin? %> + <% if session[:using_admin] %> <%= stylesheet_link_tag "/adminbootstraptheme/stylesheets/admin", :title => "Main", :rel => "stylesheet" %> <% end %> @@ -41,7 +41,7 @@ <%= render :partial => 'general/before_head_end' %> </head> - <body class="<%= 'admin' if is_admin? %> <%= 'front' if params[:action] == 'frontpage' %>"> + <body class="<%= 'front' if params[:action] == 'frontpage' %>"> <% if Configuration::force_registration_on_new_request && !@user %> <%= javascript_include_tag 'jquery.fancybox-1.3.4.pack' %> <script type="text/javascript"> @@ -100,12 +100,12 @@ <% end %> <div id="navigation_search"> - <% form_tag({:controller => "general", :action => "search_redirect"}, {:id => "navigation_search_form"}) do %> - <p> - <%= text_field_tag 'query', params[:query], { :size => 40, :id => "navigation_search_query" } %> - <%= submit_tag 'search', :id => "navigation_search_button" %> - </p> - <% end %> + <form id="navigation_search_form" method="post" action="/search"> + <p> + <%= text_field_tag 'query', params[:query], { :size => 40, :id => "navigation_search_query" } %> + <input id="navigation_search_button" type="submit" value="search"> + </p> + </form> </div> <%= render :partial => 'general/orglink' %> @@ -139,7 +139,7 @@ <input type="text"> </div> <% - unless Configuration::ga_code.empty? %> + unless Configuration::ga_code.empty? || (@user && @user.super?) %> <script> 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")); diff --git a/app/views/public_body/show.rhtml b/app/views/public_body/show.rhtml index b56556d5d..e13f9d1c0 100644 --- a/app/views/public_body/show.rhtml +++ b/app/views/public_body/show.rhtml @@ -14,6 +14,9 @@ <% if !@public_body.publication_scheme.empty? %> <%= link_to _('Publication scheme'), @public_body.publication_scheme %><br> <% end %> + <% unless @public_body.disclosure_log.empty? %> + <%= link_to _('Disclosure log'), @public_body.disclosure_log %><br> + <% end %> <% if @public_body.has_tag?("charity") %> <% for tag_value in @public_body.get_tag_values("charity") %> <% if tag_value.match(/^SC/) %> diff --git a/app/views/request/_request_filter_form.rhtml b/app/views/request/_request_filter_form.rhtml index fa760bf74..0c215a9b6 100644 --- a/app/views/request/_request_filter_form.rhtml +++ b/app/views/request/_request_filter_form.rhtml @@ -27,22 +27,24 @@ </div> <div class="list-filter-item"> <h3 class="title"><%= _("Showing") %></h3> - <% statuses = [["all", _("all requests")], - ["successful", _("successful requests")], - ["unsuccessful", _("unsuccessful requests")], - ["awaiting", _("unresolved requests")]] %> - <% for status, label in statuses %> - <% if params[:view] != status %> - <% if params[:controller] == "public_body" %> - <%= link_to label, url_for(:controller => "public_body", :action => "show", :view => status, :url_name => @public_body.url_name) + "?" + request.query_string + '#results' %> + <div class="filter-request-types"> + <% statuses = [["all", _("all requests")], + ["successful", _("successful requests")], + ["unsuccessful", _("unsuccessful requests")], + ["awaiting", _("unresolved requests")]] %> + <% for status, label in statuses %> + <% if params[:view] != status %> + <% if params[:controller] == "public_body" %> + <%= link_to label, url_for(:controller => "public_body", :action => "show", :view => status, :url_name => @public_body.url_name) + "?" + request.query_string + '#results' %> + <% else %> + <%= link_to label, url_for(:controller => "request", :action => "list", :view => status) + "?" + request.query_string + '#results' %> + <% end %> <% else %> - <%= link_to label, url_for(:controller => "request", :action => "list", :view => status) + "?" + request.query_string + '#results' %> + <%= label %> <% end %> - <% else %> - <%= label %> - <% end %> - <%= "|" unless statuses.last[0] == status %> - <% end %> + <%= "|" unless statuses.last[0] == status %> + <% end %> + </div> </div> <div class="list-filter-item"> diff --git a/app/views/request/_request_listing_via_event.rhtml b/app/views/request/_request_listing_via_event.rhtml index e3abfe393..ee1cc079a 100644 --- a/app/views/request/_request_listing_via_event.rhtml +++ b/app/views/request/_request_listing_via_event.rhtml @@ -17,13 +17,13 @@ end %> </span> <div class="requester"> <% if event.event_type == 'sent' %> - <%= _('Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> + <%= _('Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> <% elsif event.event_type == 'followup_sent' %> <%=event.display_status %> - <%= _('sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> + <%= _('sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> <% elsif event.event_type == 'response' %> <%=event.display_status %> - <%= _('by {{public_body_name}} to {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> + <%= _('by {{public_body_name}} to {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>request_user_link_absolute(info_request),:date=>simple_date(event.created_at )) %> <% elsif event.event_type == 'comment' %> <%= _('Request to {{public_body_name}} by {{info_request_user}}. Annotated by {{event_comment_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>user_link_absolute(info_request.user),:event_comment_user=>user_link_absolute(event.comment.user),:date=>simple_date(event.created_at)) %> <% else %> @@ -35,12 +35,12 @@ end %> </div> <span class="bottomline icon_<%= info_request.calculate_status %>"> <strong> - <%= info_request.display_status %> + <%= info_request.display_status(cached_value_ok=true) %> </strong><br> </span> </div> <div class="request_right"> - <span class="desc"> + <span class="desc"> <%= highlight_and_excerpt(event.search_text_main(true), @highlight_words, 150) %> </span> </div> |