diff options
149 files changed, 3088 insertions, 7551 deletions
diff --git a/.travis.yml b/.travis.yml index 497a03159..9cc3fd5a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,14 @@ branches: only: - develop - master + - feature/fix-travis-ruby-19-errors rvm: - 1.8.7 + - 1.9.3 before_install: - - sudo gem install rubygems-update --version=1.6.2 - - sudo gem update --system 1.6.2 - - sudo gem install rake + - gem install rubygems-update --version=1.6.2 + - gem update --system 1.6.2 + - gem install rake --version=0.9.2.2 - git submodule update --init --recursive - psql -c "create database foi_test template template0 encoding 'SQL_ASCII';" -U postgres - cp config/database.yml-test config/database.yml @@ -16,6 +16,7 @@ gem 'gettext_i18n_rails', '>= 0.7.1' gem 'gettext', '~> 2.3.3' gem 'json', '~> 1.5.1' gem 'mahoro' +gem 'mail', :platforms => :ruby_19 gem 'memcache-client', :require => 'memcache' gem 'locale', '>= 2.0.5' gem 'net-http-local' @@ -26,11 +27,9 @@ gem 'recaptcha', '~> 0.3.1', :require => 'recaptcha/rails' # :require avoids "already initialized constant" warnings gem 'rmagick', :require => 'RMagick' gem 'routing-filter', '~> 0.2.4' -gem 'rake', '~> 0.9.2.2' +gem 'rake', '0.9.2.2' gem 'rspec', '~> 1.3.2' -gem 'rspec-rails', '~> 1.3.4' gem 'ruby-msg', '~> 1.5.0' -gem 'test-unit', '~> 1.2.3', :platforms => :ruby_19 gem 'vpim' gem 'will_paginate', '~> 2.3.11' # when 1.2.9 is released by the maintainer, we can stop using this fork: @@ -44,6 +43,7 @@ gem 'newrelic_rpm' group :test do gem 'fakeweb' gem 'rspec-rails', '~> 1.3.4' + gem 'test-unit', '~> 1.2.3', :platforms => :ruby_19 end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index f2cdd9d40..6e6f955a9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,7 @@ GEM net-ssh (>= 2.0.14) net-ssh-gateway (>= 1.1.0) chunky_png (1.2.6) + columnize (0.3.6) compass (0.12.2) chunky_png (~> 1.2) fssm (>= 0.2.7) @@ -156,6 +157,7 @@ DEPENDENCIES json (~> 1.5.1) locale (>= 2.0.5) mahoro + mail mailcatcher memcache-client net-http-local @@ -164,7 +166,7 @@ DEPENDENCIES pg rack (~> 1.1.0) rails (= 2.3.14) - rake (~> 0.9.2.2) + rake (= 0.9.2.2) rdoc (~> 2.4.3) recaptcha (~> 0.3.1) rmagick @@ -14,7 +14,8 @@ move towards a world where governments approach transparency as the norm, rather than the exception. Please join our mailing list at -https://groups.google.com/group/alaveteli-dev and introduce yourself. +https://groups.google.com/group/alaveteli-dev and introduce yourself, or +drop a line to hello@alaveteli.org to let us know that you're using Alaveteli. Some documentation can be found in the [`doc/` folder](https://github.com/mysociety/alaveteli/tree/master/doc). @@ -3,7 +3,6 @@ require(File.join(File.dirname(__FILE__), 'config', 'boot')) -require 'rake/dsl_definition' require 'rake' require 'rake/testtask' require 'rdoc/task' 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 } %> diff --git a/commonlib b/commonlib -Subproject 3bf8c34eed89a946f981363eb862f25ac843769 +Subproject 4e84e9ed8fc75764da5139a51722729f2ba96ce diff --git a/config/deploy.rb b/config/deploy.rb index 5c7c181c9..004c3df35 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -51,6 +51,7 @@ namespace :deploy do "#{release_path}/config/memcached.yml" => "#{shared_path}/memcached.yml", "#{release_path}/config/rails_env.rb" => "#{shared_path}/rails_env.rb", "#{release_path}/config/newrelic.yml" => "#{shared_path}/newrelic.yml", + "#{release_path}/config/aliases" => "#{shared_path}/aliases", "#{release_path}/public/foi-live-creation.png" => "#{shared_path}/foi-live-creation.png", "#{release_path}/public/foi-user-use.png" => "#{shared_path}/foi-user-use.png", "#{release_path}/public/favicon.ico" => "#{shared_path}/favicon.ico", diff --git a/config/environment.rb b/config/environment.rb index de20e73e4..5670aed0b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,8 +1,16 @@ # Be sure to restart your web server when you modify this file. - -# the default encoding for IO is utf-8, and we use utf-8 internally if RUBY_VERSION.to_f >= 1.9 + # the default encoding for IO is utf-8, and we use utf-8 internally Encoding.default_external = Encoding.default_internal = Encoding::UTF_8 + # Suppress warning messages and require inflector to avoid iconv deprecation message + # "iconv will be deprecated in the future, use String#encode instead." when loading + # it as part of rails + original_verbose, $VERBOSE = $VERBOSE, nil + require 'active_support/inflector' + # Activate warning messages again. + $VERBOSE = original_verbose + require 'yaml' + YAML::ENGINE.yamler = "syck" end # Uncomment below to force Rails into production mode when @@ -20,7 +28,6 @@ $:.push(File.join(File.dirname(__FILE__), '../commonlib/rblib')) # ... if these fail to include, you need the commonlib submodule from git # (type "git submodule update --init" in the whatdotheyknow directory) -# ruby-ole and ruby-msg. We use a custom ruby-msg to avoid a name conflict $:.unshift(File.join(File.dirname(__FILE__), '../vendor/plugins/globalize2/lib')) load "validate.rb" @@ -87,6 +94,8 @@ Rails::Initializer.run do |config| require 'routing_filters.rb' end + config.autoload_paths << "#{RAILS_ROOT}/lib/mail_handler" + # See Rails::Configuration for more options ENV['RECAPTCHA_PUBLIC_KEY'] = Configuration::recaptcha_public_key ENV['RECAPTCHA_PRIVATE_KEY'] = Configuration::recaptcha_private_key @@ -135,7 +144,6 @@ WillPaginate::ViewHelpers.pagination_options[:renderer] = 'WillPaginateExtension # Load monkey patches and other things from lib/ require 'ruby19.rb' -require 'tmail_extensions.rb' require 'activesupport_cache_extensions.rb' require 'timezone_fixes.rb' require 'use_spans_for_errors.rb' @@ -143,12 +151,12 @@ require 'make_html_4_compliant.rb' require 'activerecord_errors_extensions.rb' require 'willpaginate_extension.rb' require 'sendmail_return_path.rb' -require 'tnef.rb' require 'i18n_fixes.rb' require 'rack_quote_monkeypatch.rb' require 'world_foi_websites.rb' require 'alaveteli_external_command.rb' require 'quiet_opener.rb' +require 'mail_handler' if !Configuration.exception_notifications_from.blank? && !Configuration.exception_notifications_to.blank? ExceptionNotification::Notifier.sender_address = Configuration::exception_notifications_from diff --git a/config/general.yml-example b/config/general.yml-example index fd134b0c2..bfe289541 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -32,6 +32,10 @@ AVAILABLE_LOCALES: 'en es' DEFAULT_LOCALE: 'en' USE_DEFAULT_BROWSER_LANGUAGE: true +# If you don't want the default locale to be included in URLs generated +# by the application, set this to false +INCLUDE_DEFAULT_LOCALE_IN_URLS: true + # How many days should have passed before an answer to a request is officially late? REPLY_LATE_AFTER_DAYS: 20 REPLY_VERY_LATE_AFTER_DAYS: 40 diff --git a/config/initializers/fast_gettext.rb b/config/initializers/fast_gettext.rb index 2ecf5cb5d..1cd6440e4 100644 --- a/config/initializers/fast_gettext.rb +++ b/config/initializers/fast_gettext.rb @@ -3,4 +3,4 @@ FastGettext.default_text_domain = 'app' I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) - +RoutingFilter::Locale.include_default_locale = Configuration::include_default_locale_in_urls
\ No newline at end of file diff --git a/config/packages b/config/packages index ded8dc9a5..775a55e38 100644 --- a/config/packages +++ b/config/packages @@ -33,7 +33,7 @@ libpq-dev uuid-dev ruby1.8-dev rubygems -rake +rake (>= 0.9.2.2) build-essential bundler sqlite3 diff --git a/config/routes.rb b/config/routes.rb index 5fc0075a4..3512b4cd4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,8 +32,6 @@ ActionController::Routing::Routes.draw do |map| general.advanced_search '/advancedsearch', :action => 'search_redirect', :advanced => true general.random_request '/random', :action => 'random_request' - - general.fai_test '/test', :action => 'fai_test' end map.with_options :controller => 'request' do |request| diff --git a/db/migrate/098_fix_public_body_translations.rb b/db/migrate/098_fix_public_body_translations.rb index 9bcefb1c0..25f36336f 100644 --- a/db/migrate/098_fix_public_body_translations.rb +++ b/db/migrate/098_fix_public_body_translations.rb @@ -15,13 +15,12 @@ class FixPublicBodyTranslations < ActiveRecord::Migration where first_letter is null ; SQL - + execute <<-SQL update public_body_translations - set publication_scheme = public_bodies.publication_scheme - from public_bodies - where public_body_translations.public_body_id = public_bodies.id - and public_body_translations.publication_scheme is null + set publication_scheme = (SELECT public_bodies.publication_scheme FROM public_bodies WHERE +public_body_translations.public_body_id = public_bodies.id ) + where public_body_translations.publication_scheme is null ; SQL end diff --git a/lib/alaveteli_external_command.rb b/lib/alaveteli_external_command.rb index 3bfc34e3a..24b4b1aa8 100644 --- a/lib/alaveteli_external_command.rb +++ b/lib/alaveteli_external_command.rb @@ -2,6 +2,12 @@ require 'external_command' module AlaveteliExternalCommand class << self + # Final argument can be a hash of options. + # Valid options are: + # :append_to - string to append the output of the process to + # :stdin_string - stdin string to pass to the process + # :binary_output - boolean flag for treating the output as binary or text (only significant + # ruby 1.9 and above) def run(program_name, *args) # Run an external program, and return its output. # Standard error is suppressed unless the program @@ -10,7 +16,7 @@ module AlaveteliExternalCommand if !args.empty? && args[-1].is_a?(Hash) opts = args.pop end - + if program_name =~ %r(^/) program_path = program_name else @@ -24,12 +30,16 @@ module AlaveteliExternalCommand end raise "Could not find #{program_name} in any of #{Configuration::utility_search_path.join(', ')}" if !found end - + xc = ExternalCommand.new(program_path, *args) if opts.has_key? :append_to xc.out = opts[:append_to] end + if opts.has_key? :binary_output + xc.binary_mode = opts[:binary_output] + end xc.run(opts[:stdin_string] || "", opts[:env] || {}) + if xc.status != 0 # Error $stderr.puts("Error from #{program_name} #{args.join(' ')}:") diff --git a/lib/configuration.rb b/lib/configuration.rb index abd0f5cdc..11fe1c56e 100644 --- a/lib/configuration.rb +++ b/lib/configuration.rb @@ -25,6 +25,7 @@ module Configuration :GA_CODE => '', :GAZE_URL => '', :HTML_TO_PDF_COMMAND => '', + :INCLUDE_DEFAULT_LOCALE_IN_URLS => true, :INCOMING_EMAIL_DOMAIN => 'localhost', :INCOMING_EMAIL_PREFIX => '', :INCOMING_EMAIL_SECRET => 'dummysecret', diff --git a/lib/mail_handler/backends/mail_backend.rb b/lib/mail_handler/backends/mail_backend.rb new file mode 100644 index 000000000..b75e6ed63 --- /dev/null +++ b/lib/mail_handler/backends/mail_backend.rb @@ -0,0 +1,323 @@ +require 'mail' + +module MailHandler + module Backends + module MailBackend + + def backend() + 'Mail' + end + + # Note that the decode flag is not yet used + def mail_from_raw_email(data, decode=true) + Mail.new(data) + end + + # Extracts all attachments from the given TNEF file as a Mail object + def mail_from_tnef(content) + main = Mail.new + tnef_attachments(content).each do |attachment| + main.add_file(attachment) + end + main.ready_to_send! + main + end + + # Returns an outlook message as a Mail object + def mail_from_outlook(content) + msg = Mapi::Msg.open(StringIO.new(content)) + mail = mail_from_raw_email(msg.to_mime.to_s) + mail.ready_to_send! + mail + end + + # Return a copy of the file name for the mail part + def get_part_file_name(part) + part_file_name = part.filename + part_file_name.nil? ? nil : part_file_name.dup + end + + # Get the body of a mail part + def get_part_body(part) + part.body.decoded + end + + # Return the first from field if any + def first_from(mail) + if mail[:from] + begin + mail[:from].addrs[0] + mail[:from].decoded + return mail[:from].addrs[0] + rescue + return mail[:from].value + end + else + nil + end + end + + # Return the first from address if any + def get_from_address(mail) + first_from = first_from(mail) + if first_from + if first_from.is_a?(String) + return nil + else + return first_from.address + end + else + return nil + end + end + + # Return the first from name if any + def get_from_name(mail) + first_from = first_from(mail) + if first_from + if first_from.is_a?(String) + return nil + else + return first_from.display_name ? eval(%Q{"#{first_from.display_name}"}) : nil + end + else + return nil + end + end + + def get_all_addresses(mail) + envelope_to = mail['envelope-to'] ? [mail['envelope-to'].value] : [] + ((mail.to || []) + + (mail.cc || []) + + (envelope_to || [])).uniq + end + + def empty_return_path?(mail) + return false if mail['return-path'].nil? + return true if mail['return-path'].value.blank? + return false + end + + def get_auto_submitted(mail) + mail['auto-submitted'] ? mail['auto-submitted'].value : nil + end + + def get_content_type(part) + part.content_type ? part.content_type.split(';')[0] : nil + end + + def get_header_string(header, mail) + mail.header[header] ? mail.header[header].to_s : nil + end + + # Detects whether a mail part is an Outlook email + def is_outlook?(part) + filename = get_part_file_name(part) + return true if get_content_type(part) == 'application/vnd.ms-outlook' + if filename && AlaveteliFileTypes.filename_to_mimetype(filename) == 'application/vnd.ms-outlook' + return true + end + return false + end + + # Convert a mail part which is an attached mail in one of + # several formats into a mail object and set it as the + # rfc822_attachment on the part. If the mail part can't be + # converted, the content type on the part is updated to + # 'text/plain' for an RFC822 attachment, and 'application/octet-stream' + # for other types + def decode_attached_part(part, parent_mail) + if get_content_type(part) == 'message/rfc822' + # An email attached as text + part.rfc822_attachment = mail_from_raw_email(part.body) + if part.rfc822_attachment.nil? + # Attached mail didn't parse, so treat as text + part.content_type = 'text/plain' + end + elsif is_outlook?(part) + part.rfc822_attachment = mail_from_outlook(part.body.decoded) + if part.rfc822_attachment.nil? + # Attached mail didn't parse, so treat as binary + part.content_type = 'application/octet-stream' + end + elsif get_content_type(part) == 'application/ms-tnef' + # A set of attachments in a TNEF file + part.rfc822_attachment = mail_from_tnef(part.body.decoded) + if part.rfc822_attachment.nil? + # Attached mail didn't parse, so treat as binary + part.content_type = 'application/octet-stream' + end + end + if part.rfc822_attachment + expand_and_normalize_parts(part.rfc822_attachment, parent_mail) + end + end + + # Expand and normalize a mail part recursively. Decodes attached messages into + # Mail objects wherever possible. Sets a default content type if none is + # set. Tries to set a more specific content type for binary content types. + def expand_and_normalize_parts(part, parent_mail) + if part.multipart? + part.parts.each{ |sub_part| expand_and_normalize_parts(sub_part, parent_mail) } + else + part_filename = get_part_file_name(part) + charset = part.charset # save this, because overwriting content_type also resets charset + + # Don't allow nil content_types + if get_content_type(part).nil? + part.content_type = 'application/octet-stream' + end + + # PDFs often come with this mime type, fix it up for view code + if get_content_type(part) == 'application/octet-stream' + part_body = get_part_body(part) + calc_mime = AlaveteliFileTypes.filename_and_content_to_mimetype(part_filename, + part_body) + if calc_mime + part.content_type = calc_mime + end + end + + # Use standard content types for Word documents etc. + part.content_type = normalise_content_type(get_content_type(part)) + decode_attached_part(part, parent_mail) + part.charset = charset + end + end + + # Count the parts in a mail part recursively, including any attached messages. + # Set the count on the parent mail, and set a url_part_number on the part itself. + # Set the count for the first uudecoded part on the parent mail also. + def count_parts(part, parent_mail) + if part.multipart? + part.parts.each { |p| count_parts(p, parent_mail) } + else + if part.rfc822_attachment + count_parts(part.rfc822_attachment, parent_mail) + else + parent_mail.count_parts_count += 1 + part.url_part_number = parent_mail.count_parts_count + end + end + parent_mail.count_first_uudecode_count = parent_mail.count_parts_count + end + + # Choose the best part from alternatives + def choose_best_alternative(mail) + if mail.html_part + return mail.html_part + elsif mail.text_part + return mail.text_part + else + return mail.parts.first + end + end + + # Expand and normalize the parts of a mail, select the best part + # wherever there is an alternative, and then count the returned + # leaves and assign url_part values to them + def get_attachment_leaves(mail) + expand_and_normalize_parts(mail, mail) + leaves = _get_attachment_leaves_recursive(mail, nil, mail) + mail.count_parts_count = 0 + count_parts(mail, mail) + return leaves + end + + # Recurse through a mail part, selecting the best part wherever there is + # an alternative + def _get_attachment_leaves_recursive(part, within_rfc822_attachment, parent_mail) + leaves_found = [] + if part.multipart? + raise "no parts on multipart mail" if part.parts.size == 0 + if part.sub_type == 'alternative' + best_part = choose_best_alternative(part) + leaves_found += _get_attachment_leaves_recursive(best_part, + within_rfc822_attachment, + parent_mail) + else + # Add all parts + part.parts.each do |sub_part| + leaves_found += _get_attachment_leaves_recursive(sub_part, + within_rfc822_attachment, + parent_mail) + end + end + else + # Add all the parts of a decoded attached message + if part.rfc822_attachment + leaves_found += _get_attachment_leaves_recursive(part.rfc822_attachment, + part.rfc822_attachment, + parent_mail) + else + # Store leaf + part.within_rfc822_attachment = within_rfc822_attachment + leaves_found += [part] + end + end + return leaves_found + end + + # Add selected useful headers from an attached message to its body + def extract_attached_message_headers(leaf) + body = get_part_body(leaf) + # Test to see if we are in the first part of the attached + # RFC822 message and it is text, if so add headers. + if leaf.within_rfc822_attachment == leaf && get_content_type(leaf) == 'text/plain' + headers = "" + [ 'Date', 'Subject', 'From', 'To', 'Cc' ].each do |header| + if header_value = get_header_string(header, leaf.within_rfc822_attachment) + 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 + end + body + end + + # Generate a hash of the attributes associated with each significant part of a Mail object + def get_attachment_attributes(mail) + leaves = get_attachment_leaves(mail) + attachments = [] + for leaf in leaves + body = get_part_body(leaf) + if leaf.within_rfc822_attachment + within_rfc822_subject = leaf.within_rfc822_attachment.subject + body = extract_attached_message_headers(leaf) + end + leaf_attributes = { :url_part_number => leaf.url_part_number, + :content_type => get_content_type(leaf), + :filename => get_part_file_name(leaf), + :charset => leaf.charset, + :within_rfc822_subject => within_rfc822_subject, + :body => body, + :hexdigest => Digest::MD5.hexdigest(body) } + attachments << leaf_attributes + end + return attachments + end + + # Format + def address_from_name_and_email(name, email) + if !MySociety::Validate.is_valid_email(email) + raise "invalid email " + email + " passed to address_from_name_and_email" + end + if name.nil? + return Mail::Address.new(email).to_s + end + address = Mail::Address.new + address.display_name = name + address.address = email + address.to_s + end + + def address_from_string(string) + Mail::Address.new(string).address + end + end + end +end
\ No newline at end of file diff --git a/lib/mail_handler/backends/mail_extensions.rb b/lib/mail_handler/backends/mail_extensions.rb new file mode 100644 index 000000000..f756abd1a --- /dev/null +++ b/lib/mail_handler/backends/mail_extensions.rb @@ -0,0 +1,67 @@ +require 'mail/message' +require 'mail/fields/common/parameter_hash' +module Mail + class Message + 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) + attr_accessor :count_parts_count + attr_accessor :count_first_uudecode_count + + # A patched version of the message initializer to work around a bug where stripping the original + # input removes meaningful spaces - e.g. in the case of uuencoded bodies. + def initialize(*args, &block) + @body = nil + @body_raw = nil + @separate_parts = false + @text_part = nil + @html_part = nil + @errors = nil + @header = nil + @charset = 'UTF-8' + @defaulted_charset = true + + @perform_deliveries = true + @raise_delivery_errors = true + + @delivery_handler = nil + + @delivery_method = Mail.delivery_method.dup + + @transport_encoding = Mail::Encodings.get_encoding('7bit') + + @mark_for_delete = false + + if args.flatten.first.respond_to?(:each_pair) + init_with_hash(args.flatten.first) + else + # The replacement of this commented out line is the change. + # init_with_string(args.flatten[0].to_s.strip) + init_with_string(args.flatten[0].to_s) + end + + if block_given? + instance_eval(&block) + end + + self + end + end + + # A patched version of the parameter hash that handles nil values without throwing + # an error. + class ParameterHash < IndifferentHash + + def encoded + map.sort { |a,b| a.first.to_s <=> b.first.to_s }.map do |key_name, value| + # The replacement of this commented out line is the change + # unless value.ascii_only? + unless value.nil? || value.ascii_only? + value = Mail::Encodings.param_encode(value) + key_name = "#{key_name}*" + end + %Q{#{key_name}=#{quote_token(value)}} + end.join(";\r\n\s") + end + end +end
\ No newline at end of file diff --git a/lib/mail_handler/backends/tmail_backend.rb b/lib/mail_handler/backends/tmail_backend.rb new file mode 100644 index 000000000..02124cdb1 --- /dev/null +++ b/lib/mail_handler/backends/tmail_backend.rb @@ -0,0 +1,290 @@ +module MailHandler + module Backends + module TmailBackend + + def backend() + 'TMail' + end + + # Turn raw data into a structured TMail::Mail object + # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ + def mail_from_raw_email(data, decode=true) + # 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 = data.gsub(/; boundary=\s+"/im,'; boundary="') + mail = TMail::Mail.parse(copy_of_raw_data) + mail.base64_decode if decode + mail + end + + # Extracts all attachments from the given TNEF file as a TMail::Mail object + def mail_from_tnef(content) + main = TMail::Mail.new + main.set_content_type 'multipart', 'mixed', { 'boundary' => TMail.new_boundary } + tnef_attachments(content).each do |attachment| + tmail_attachment = TMail::Mail.new + tmail_attachment['content-location'] = attachment[:filename] + tmail_attachment.body = attachment[:content] + main.parts << tmail_attachment + end + main + end + + # Return a copy of the file name for the mail part + def get_part_file_name(mail_part) + part_file_name = TMail::Mail.get_part_file_name(mail_part) + if part_file_name.nil? + return nil + end + part_file_name = part_file_name.dup + return part_file_name + end + + # Get the body of a mail part + def get_part_body(mail_part) + mail_part.body + end + + # Return the first from address if any + def get_from_address(mail) + if mail.from_addrs.nil? || mail.from_addrs.size == 0 + return nil + end + mail.from_addrs[0].spec + end + + # Return the first from name if any + def get_from_name(mail) + mail.from_name_if_present + end + + def get_all_addresses(mail) + ((mail.to || []) + + (mail.cc || []) + + (mail.envelope_to || [])).uniq + end + + def empty_return_path?(mail) + return false if mail['return-path'].nil? + return true if mail['return-path'].addr.to_s == '<>' + return false + end + + def get_auto_submitted(mail) + mail['auto-submitted'] ? mail['auto-submitted'].body : nil + end + + def get_content_type(part) + part.content_type + end + + def get_header_string(header, mail) + mail.header_string(header) + 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 monkeypatches in lib/mail_handler/tmail_extensions and + # lib/mail_handler/mail_extensions for how these attributes are added). ensure_parts_counted + # must be called before using the attributes. + def ensure_parts_counted(mail) + mail.count_parts_count = 0 + _count_parts_recursive(mail, mail) + # we carry on using these numeric ids for attachments uudecoded from within text parts + mail.count_first_uudecode_count = mail.count_parts_count + end + def _count_parts_recursive(part, mail) + if part.multipart? + part.parts.each do |p| + _count_parts_recursive(p, mail) + end + else + part_filename = 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 = mail_from_raw_email(part.body, decode=false) + 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 = mail_from_raw_email(msg.to_mime.to_s, decode=false) + elsif part.content_type == 'application/ms-tnef' + # A set of attachments in a TNEF file + part.rfc822_attachment = mail_from_tnef(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, mail) + end + end + if part.rfc822_attachment.nil? + mail.count_parts_count += 1 + part.url_part_number = mail.count_parts_count + end + end + end + + def get_attachment_attributes(mail) + leaves = get_attachment_leaves(mail) + # XXX we have to call ensure_parts_counted after get_attachment_leaves + # which is really messy. + ensure_parts_counted(mail) + attachment_attributes = [] + for leaf in leaves + body = get_part_body(leaf) + # 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. + 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] + 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 + attachment_attributes << {:url_part_number => leaf.url_part_number, + :content_type => get_content_type(leaf), + :filename => get_part_file_name(leaf), + :charset => leaf.charset, + :within_rfc822_subject => within_rfc822_subject, + :body => body, + :hexdigest => Digest::MD5.hexdigest(body) } + end + attachment_attributes + 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(mail) + return _get_attachment_leaves_recursive(mail, mail) + end + def _get_attachment_leaves_recursive(curr_mail, parent_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, parent_mail, within_rfc822_attachment) + else + # Add all parts + curr_mail.parts.each do |m| + leaves_found += _get_attachment_leaves_recursive(m, parent_mail, within_rfc822_attachment) + end + end + else + # XXX Yuck. this section alters various content_types. 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 = get_part_file_name(curr_mail) + part_body = get_part_body(curr_mail) + calc_mime = AlaveteliFileTypes.filename_and_content_to_mimetype(part_file_name, part_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(parent_mail) # 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(parent_mail) # 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(parent_mail) # fills in rfc822_attachment variable + leaves_found += _get_attachment_leaves_recursive(curr_mail.rfc822_attachment, parent_mail, 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 + + + def address_from_name_and_email(name, email) + if !MySociety::Validate.is_valid_email(email) + raise "invalid email " + email + " passed to address_from_name_and_email" + end + if name.nil? + return TMail::Address.parse(email).to_s + end + # Botch an always quoted RFC address, then parse it + name = name.gsub(/(["\\])/, "\\\\\\1") + TMail::Address.parse('"' + name + '" <' + email + '>').to_s + end + + def address_from_string(string) + TMail::Address.parse(string).address + end + + end + end +end
\ No newline at end of file diff --git a/lib/tmail_extensions.rb b/lib/mail_handler/backends/tmail_extensions.rb index 6a533e658..3576a8eca 100644 --- a/lib/tmail_extensions.rb +++ b/lib/mail_handler/backends/tmail_extensions.rb @@ -15,6 +15,14 @@ require 'tmail/interface' # These mainly used in app/models/incoming_message.rb module TMail class Mail + # Monkeypatch! Adding some extra members to store extra info in. + + 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) + attr_accessor :count_parts_count + attr_accessor :count_first_uudecode_count + # Monkeypatch! (check to see if this becomes a standard function in # TMail::Mail, then use that, whatever it is called) def Mail.get_part_file_name(part) @@ -68,22 +76,6 @@ module TMail end - class Address - # Monkeypatch! Constructor which makes a TMail::Address given - # a name and an email - def Address.address_from_name_and_email(name, email) - if !MySociety::Validate.is_valid_email(email) - raise "invalid email " + email + " passed to address_from_name_and_email" - end - if name.nil? - return TMail::Address.parse(email) - end - # Botch an always quoted RFC address, then parse it - name = name.gsub(/(["\\])/, "\\\\\\1") - return TMail::Address.parse('"' + name + '" <' + email + '>') - end - end - module TextUtils # Monkeypatch! Much more aggressive list of characters to cause quoting # than in normal TMail. e.g. Have found real cases where @ needs quoting. @@ -95,8 +87,8 @@ module TMail end end -# Monkeypatch! TMail 1.2.7.1 will parse only one address out of a list of addresses with -# unquoted display parts https://github.com/mikel/tmail/issues#issue/9 - this monkeypatch +# Monkeypatch! TMail 1.2.7.1 will parse only one address out of a list of addresses with +# unquoted display parts https://github.com/mikel/tmail/issues#issue/9 - this monkeypatch # fixes this issue. module TMail diff --git a/lib/mail_handler/mail_handler.rb b/lib/mail_handler/mail_handler.rb new file mode 100644 index 000000000..8b227b9ca --- /dev/null +++ b/lib/mail_handler/mail_handler.rb @@ -0,0 +1,179 @@ +# Handles the parsing of email +require 'tmpdir' + +module MailHandler + + if RUBY_VERSION.to_f >= 1.9 + require 'mail' + require 'backends/mail_extensions' + require 'backends/mail_backend' + include Backends::MailBackend + else + require 'action_mailer' + require 'backends/tmail_extensions' + require 'backends/tmail_backend' + include Backends::TmailBackend + end + + # Returns a set of attachments from the given TNEF contents + # The TNEF contents also contains the message body, but in general this is the + # same as the message body in the message proper. + def tnef_attachments(content) + attachments = [] + Dir.mktmpdir do |dir| + IO.popen("#{`which tnef`.chomp} -K -C #{dir}", "wb") do |f| + f.write(content) + f.close + if $?.signaled? + raise IOError, "tnef exited with signal #{$?.termsig}" + end + if $?.exited? && $?.exitstatus != 0 + raise IOError, "tnef exited with status #{$?.exitstatus}" + end + end + found = 0 + Dir.new(dir).sort.each do |file| # sort for deterministic behaviour + if file != "." && file != ".." + file_content = File.open("#{dir}/#{file}", "rb").read + attachments << { :content => file_content, + :filename => file } + found += 1 + end + end + if found == 0 + raise IOError, "tnef produced no attachments" + end + end + attachments + 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 get_attachment_text_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.binmode + tempfile.print body + tempfile.flush + default_params = { :append_to => text, :binary_output => false } + 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, default_params) + 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, default_params) + 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, + default_params.merge(: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, default_params) + 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, default_params) + elsif content_type == 'application/pdf' + AlaveteliExternalCommand.run("pdftotext", tempfile.path, "-", default_params) + 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", + {:binary_output => false}) + 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 += 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 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_one_file(content_type, body) + + end + end + return text + end + + # Turn instance methods into class methods + extend self + +end + diff --git a/lib/tasks/translation.rake b/lib/tasks/translation.rake index f6611cc80..273c12bfa 100644 --- a/lib/tasks/translation.rake +++ b/lib/tasks/translation.rake @@ -4,7 +4,7 @@ namespace :translation do include Usage def write_email(email, email_description, output_file) - mail_object = TMail::Mail.parse(email.to_s) + mail_object = MailHandler.mail_from_raw_email(email.to_s, decode=false) output_file.write("\n") output_file.write("Description of email: #{email_description}\n") output_file.write("Subject line: #{mail_object.subject}\n") @@ -86,7 +86,7 @@ namespace :translation do 'fixtures', 'files', 'incoming-request-plain.email')) - response_mail = TMail::Mail.parse(content) + response_mail = MailHandler.mail_from_raw_email(content, decode=false) response_mail.from = "authority@example.com" stopped_responses_email = RequestMailer.create_stopped_responses(info_request, diff --git a/lib/tnef.rb b/lib/tnef.rb deleted file mode 100644 index 1c941f8b0..000000000 --- a/lib/tnef.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'tmpdir' - -class TNEF - - # Extracts all attachments from the given TNEF file as a TMail::Mail object - # The TNEF file also contains the message body, but in general this is the - # same as the message body in the message proper. - def self.as_tmail(content) - main = TMail::Mail.new - main.set_content_type 'multipart', 'mixed', { 'boundary' => TMail.new_boundary } - Dir.mktmpdir do |dir| - IO.popen("#{`which tnef`.chomp} -K -C #{dir}", "w") do |f| - f.write(content) - f.close - if $?.signaled? - raise IOError, "tnef exited with signal #{$?.termsig}" - end - if $?.exited? && $?.exitstatus != 0 - raise IOError, "tnef exited with status #{$?.exitstatus}" - end - end - found = 0 - Dir.new(dir).sort.each do |file| # sort for deterministic behaviour - if file != "." && file != ".." - file_content = File.open("#{dir}/#{file}", "r").read - attachment = TMail::Mail.new - attachment['content-location'] = file - attachment.body = file_content - main.parts << attachment - found += 1 - end - end - if found == 0 - raise IOError, "tnef produced no attachments" - end - end - main - end - -end diff --git a/lib/world_foi_websites.rb b/lib/world_foi_websites.rb index 2ff924713..c3f3655df 100644 --- a/lib/world_foi_websites.rb +++ b/lib/world_foi_websites.rb @@ -46,10 +46,10 @@ class WorldFOIWebsites :country_name => "Chile", :country_iso_code => "CL", :url => "http://accesointeligente.org"}, - {:country_name => "Australia", + {:name => "Right To Know", + :country_name => "Australia", :country_iso_code => "AU", - # The Australian site is not yet live. So, not including name & url yet. - }, + :url => "http://www.righttoknow.org.au"}, {:name => "Informace pro Vsechny", :country_name => "Česká republika", :country_iso_code => "CZ", diff --git a/locale/cs/app.po b/locale/cs/app.po index 6dd251710..fde8f9b0d 100644 --- a/locale/cs/app.po +++ b/locale/cs/app.po @@ -14,8 +14,8 @@ msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" "POT-Creation-Date: 2012-11-06 16:35+0000\n" -"PO-Revision-Date: 2012-11-07 09:52+0000\n" -"Last-Translator: louisecrow <louise@mysociety.org>\n" +"PO-Revision-Date: 2012-11-29 14:58+0000\n" +"Last-Translator: janakneschke <jana.kneschke@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -299,7 +299,7 @@ msgid "" "<p>Your request contains a <strong>postcode</strong>. Unless it directly " "relates to the subject of your request, please remove any address as it will" " <strong>appear publicly on the Internet</strong>.</p>" -msgstr "<p>Váš dotaz obsahuje <strong>PSČ</strong>. Pokud to není údaj nutný k zodpovězení dotazu, prosíme odstraňte adresu či jiný identifikátor. Váš dotaz bude v celém znění<strong>uveřejněn na internetu</strong>.</p>" +msgstr "<p>Váš dotaz obsahuje <strong>PSČ</strong>. Pokud to není údaj nutný k zodpovězení dotazu, prosíme odstraňte adresu či jiný identifikátor. Váš dotaz bude v celém znění a bez osobních údajů<strong>uveřejněn na internetu</strong>.</p>" msgid "" "<p>Your {{law_used_full}} request has been <strong>sent on its " @@ -309,7 +309,7 @@ msgid "" "<p>If you write about this request (for example in a forum or a blog) please" " link to this page, and add an\\n annotation below telling people" " about your writing.</p>" -msgstr "<p><strong>Odesláno!</strong></p>\n<p><strong>Pošleme vám e-mail </strong> až vám instituce odpoví nebo po {{late_number_of_days}} dní po vypršení lhůty na odpověď.</p>\\n <p>Pokud o tomto dotazu budete dále psát (například na nějakém fóru či blogu) prosím přiložte odkaz k vašemu dotazu na těchto stránkách a přidejte k němu komentář.</p>" +msgstr "<p><strong>Odesláno!</strong></p>\n<p><strong>Pošleme vám e-mail </strong> až vám instituce odpoví nebo po {{late_number_of_days}} dní po vypršení lhůty na odpověď.</p>\\n <p>Pokud o svém dotazu budete dále psát (například na nějakém fóru či blogu), přiložte odkaz na stránky IPV a k dotazu přidejte komentář.</p>" msgid "" "<p>{{site_name}} is currently in maintenance. You can only view existing " @@ -353,12 +353,12 @@ msgstr "<strong><code>dotaz:</code></strong> k omezení na konkrétní dotaz vep msgid "" "<strong><code>requested_by:julian_todd</code></strong> to search requests " "made by Julian Todd, typing the name as in the URL." -msgstr "<strong><code>requested_by:julian_todd</code></strong> pokud chcete nalézt více poznámek od Tonyho Bowdena, napište jeho jméno jako URL." +msgstr "<strong><code>rpožadováno od uživatele: julian_todd</code></strong> pokud chcete nalézt více poznámek od Tonyho Bowdena, napište jeho jméno jako URL." msgid "" "<strong><code>requested_from:home_office</code></strong> to search requests " "from the Home Office, typing the name as in the URL." -msgstr "<strong><code>vyžádáno_od:ministerstvo_vnitra</code></strong> pokud chcete nalézt více dotazů vznesených na Ministerstva vnitra, napište název instituce jako URL." +msgstr "<strong><code>vyžádáno_od:ministerstvo_vnitra</code></strong> pokud chcete nalézt více dotazů vznesených na Ministerstvo vnitra, napište název instituce jako URL." msgid "" "<strong><code>status:</code></strong> to select based on the status or " @@ -373,7 +373,7 @@ msgid "" "tag:financial_transaction:335633</code>. Note that by default any of the " "tags\\n can be present, you have to put <code>AND</code> explicitly if " "you only want results them all present." -msgstr "<strong><code>Tagujte:charity</code></strong> umožní vám najít instituce nebo žádosti s daným tagem. Můžete použít více tagů, ⏎ a hodnot tagů, např. <code>tag:openlylocal AND tag:financial_transaction:335633</code>. Jakýkoliv tag může být zahrnut⏎ je třeba vložit <code>AND</code> pokud chcete výsledek, který zahrnuje všechny tagy." +msgstr "<strong><code>Tagujte:charity</code></strong> umožní vám najít instituce nebo dotazy s daným klíčových slovem. Můžete použít více tagů, ⏎ a hodnot tagů, např. <code>tag:openlylocal AND tag:financial_transaction:335633</code>. Jakýkoliv tag může být zahrnut⏎ je třeba vložit <code>AND</code> pokud chcete výsledek, který zahrnuje všechny tagy." msgid "" "<strong><code>variety:</code></strong> to select type of thing to search " @@ -400,7 +400,7 @@ msgid "" "FOI law, and the\\nway authorities use it. Plus you'll need to be an elite " "statistician. Please\\n<a href=\"{{contact_path}}\">contact us</a> with " "questions." -msgstr "<strong>Varování!</strong>Aby datay na stránkách {{site_name}} byla správně seřazena, je vhodné chovat se podle zásad slušného jednání a netikety. Třídění vznesených dotazů není zas tak jednoduché a mohou \nvzniknout chyby a dojít k různým nejednoznačnostem. Musíte\ntaké rozumět zákonu o svobodném přístupu k informacím\na způsobu, jakým jej instituce používají. A ke všemu být vynikající statistik. Prosíme\n<a href=\"{{contact_path}}\">kontaktujte nás</a>, pokud máte otázky." +msgstr "<strong>Doporučení</strong>Veškerá konverzace na stránkách {{site_name}} podléhá zásadám slušného jednání a netikety. Třídění vznesených dotazů není zas tak jednoduché a mohou \nvzniknout chyby a dojít k různým nejednoznačnostem. Je nutné\ntaké rozumět zákonu o svobodném přístupu k informacím\na způsobu, jak tento instituce interpretují. A ke všemu být vynikající statistik. Prosíme\n<a href=\"{{contact_path}}\">kontaktujte nás</a>, pokud máte otázky." msgid "<strong>Clarification</strong> has been requested" msgstr "Bylo vyžádáno <strong>upřesnění</strong> " @@ -413,7 +413,7 @@ msgstr "<strong>Bez odpovědi</strong> \n <small>(možná je to j msgid "" "<strong>Note:</strong> Because we're testing, requests are being sent to " "{{email}} rather than to the actual authority." -msgstr "<strong>Note:</strong> Protože testujeme, žádosti jsou posílány na {{email}} a ne příslušné autoritě." +msgstr "<strong>Note:</strong> Protože testujeme, dotazy jsou posílány na {{email}} a ne příslušné autoritě." msgid "" "<strong>Note:</strong> You're sending a message to yourself, presumably\\n" @@ -438,7 +438,7 @@ msgstr "<strong>Důležité upozornění:</strong> Vaše fotografie bude zveřej msgid "" "<strong>Privacy warning:</strong> Your message, and any response\\n " "to it, will be displayed publicly on this website." -msgstr "<strong>Ochrana soukromí:</strong> Vámi vznesený dotaz, a všechny \n odpovědi na něj budou uveřejněny na těchto stránkách." +msgstr "<strong>Ochrana soukromí:</strong> vámi vznesený dotaz, a všechny \n odpovědi na něj budou uveřejněny na stránkách IPV." msgid "<strong>Some of the information</strong> has been sent " msgstr "<strong>Některé informace</strong> byly odeslány" @@ -555,7 +555,7 @@ msgstr "Upravit sledování dotazů" msgid "" "Although all responses are automatically published, we depend on\\nyou, the " "original requester, to evaluate them." -msgstr "I když jsou všechny odpovědi automaticky uveřejňovány, hodnocení dotazu závisí na vás, tedy tazateli." +msgstr "I když jsou všechny odpovědi automaticky uveřejňovány, hodnocení dotazu závisí na vás, na tazateli." msgid "" "An <a href=\"{{request_url}}\">annotation</a> to <em>{{request_title}}</em> " @@ -613,7 +613,7 @@ msgid "Awaiting classification." msgstr "Čeká se zařazení." msgid "Awaiting internal review." -msgstr "Čeká se na přezkoumání dotazu. " +msgstr "Čeká se na doplnění dotazu." msgid "Awaiting response." msgstr "Čeká se na odpověď." @@ -637,12 +637,12 @@ msgstr "Procházejte všechny instituce" msgid "" "By law, under all circumstances, {{public_body_link}} should have responded " "by now" -msgstr "Podle zákona by {{public_body_link}} měla veřejná instituce v každém případě odpovědět." +msgstr "Podle zákona by instituce {{public_body_link}} měla v každém případě odpovědět." msgid "" "By law, {{public_body_link}} should normally have responded " "<strong>promptly</strong> and" -msgstr "Podle zákona, by měla instituce {{public_body_link}} odpovědět okamžitě" +msgstr "Podle zákona, by měla instituce {{public_body_link}} odpovědět okamžitě a " msgid "Cancel a {{site_name}} alert" msgstr "Zrušte tato upozornění stránek {{site_name}}" @@ -818,7 +818,7 @@ msgstr "Kulturní památky (které mohou být ovlivěny tak, \n jak j msgid "" "Currently <strong>waiting for a response</strong> from {{public_body_link}}," " they must respond promptly and" -msgstr "V současnosti <strong> se čeká na odpověď</strong> od {{public_body_link}}, musí odpovědět co nejdříve a" +msgstr "V současnosti <strong> se čeká na odpověď</strong> od instituce {{public_body_link}}, musí odpovědět co nejdříve a " msgid "Date:" msgstr "Datum:" @@ -847,12 +847,12 @@ msgid "" msgstr "Vyloučení odpovědnosti: Tato zpráva a jakékoliv odpovědi na ni budou uveřejněny na stránkách Informace pro všechny. Naše pravidla o ochraně osobních údajů a autorských právech si přečtěte:" msgid "Disclosure log" -msgstr "" +msgstr "Disclosure log" msgid "" "Don't want to address your message to {{person_or_body}}? You can also " "write to:" -msgstr "Nechcete svou zprávu adresovat pro {{person_or_body}}? Můžete také napsat:" +msgstr "Nechcete svou zprávu adresovat na {{person_or_body}}? Můžete také napsat:" msgid "Done" msgstr "Hotovo" @@ -900,12 +900,12 @@ msgstr "Pošlete mi budoucí aktualizace tohoto dotazu. " msgid "" "Enter words that you want to find separated by spaces, e.g. <strong>climbing" " lane</strong>" -msgstr "Slova, která chcete najít musí být oddělena mezerou, například <strong>přechod pro chodce</strong>" +msgstr "Slova, která chcete najít, musí být oddělena mezerou, například <strong>přechod pro chodce</strong>" msgid "" "Enter your response below. You may attach one file (use email, or\\n <a " "href=\"%s\">contact us</a> if you need more)." -msgstr "Níže můžete vložit svou odpověď. Pokud je to nutné, přiložte jeden dokument, (s použitím e-mailu, nebo⏎ <a href=\"%s\">nás kontaktujte</a> pokud potřebujete přiložit více dokumentů). ??" +msgstr "Níže můžete vložit svou odpověď. Pokud je to nutné, přiložte jeden dokument, (s použitím e-mailu, nebo⏎ <a href=\"%s\">nás kontaktujte</a> pokud potřebujete přiložit více dokumentů)." msgid "Environmental Information Regulations" msgstr "Informace o životním prostředí" @@ -1001,7 +1001,7 @@ msgid "Follow all new requests" msgstr "Sledovat všechny nově vznesené dotazy" msgid "Follow new successful responses" -msgstr "Sledovat všechny zodpovězené dotazy ??" +msgstr "Sledovat všechny zodpovězené dotazy" msgid "Follow requests to {{public_body_name}}" msgstr "Sledovat dotaz vznesený na {{public_body_name}}" @@ -1144,7 +1144,7 @@ msgid "" "hasn't told us whether or not it was successful. Would you mind taking\\n" " a moment to read it and help us keep the place tidy for everyone?\\n " "Thanks." -msgstr "Haló! Potřebujeme vaši pomoc. Osoba, která vznesla tento dotaz nám nesdělila, jestli byla zodpovězena úspěšně. Můžete si ji přečíst a pomoci nám udržovat stránky přehledné? Děkujeme." +msgstr "Haló! Potřebujeme vaši pomoc. Osoba, která vznesla tento dotaz nám nesdělila, jestli byla zodpovězena úspěšně. Můžete si dotaz i odpověď přečíst a pomoci nám tak udržovat stránky přehledné? Děkujeme." msgid "Holiday" msgstr "Státní svátek" @@ -1173,7 +1173,7 @@ msgid "I am asking for <strong>new information</strong>" msgstr "Žádám <strong>novou informaci</strong>" msgid "I am requesting an <strong>internal review</strong>" -msgstr "Žádám o <strong>přezkoumání</strong>" +msgstr "Žádám <strong>o doplnění dotazu</strong>" msgid "I don't like these ones — give me some more!" msgstr "To se mi nelíbí — nabídněte nějaké další!" @@ -1193,10 +1193,10 @@ msgid "" msgstr "Stále <strong>čekám</strong> na svou informaci\n <small>(možná máte potvrzení)</small>" msgid "I'm still <strong>waiting</strong> for the internal review" -msgstr "Stále <strong>čekám</strong> na přezkoumání" +msgstr "Stále <strong>čekám</strong> na doplnění dotazu" msgid "I'm waiting for an <strong>internal review</strong> response" -msgstr "Čekám na vyjádření týkající se <strong>přezkoumání</strong> " +msgstr "Čekám na <strong>doplnění</strong> dotazu" msgid "I've been asked to <strong>clarify</strong> my request" msgstr "Byl/a jsem požádán/a o <strong>vyjasnění</strong> mého dotazu" @@ -1246,7 +1246,7 @@ msgstr "Pokud jste {{user_link}}, prosíme" msgid "" "If you believe this request is not suitable, you can report it for attention" " by the site administrators" -msgstr "Pokud se domníváte, že je tato žádost nevhodná, můžete ji nahlásit administrátorům stránky. " +msgstr "Pokud se domníváte, že je tento dotaz nevhodný, můžete jej nahlásit administrátorům stránky. " msgid "" "If you can't click on it in the email, you'll have to <strong>select and " @@ -1334,13 +1334,13 @@ msgid "IncomingMessage|Valid to reply to" msgstr "IncomingMessage | Platná zpráva pro" msgid "Individual requests" -msgstr "Jednotlivé žádosti" +msgstr "Jednotlivé dotazy" msgid "Info request" -msgstr "Žádost o informaci" +msgstr "Dotaz na informaci" msgid "Info request event" -msgstr "Žádost o informaci – akce ??" +msgstr "Dotaz na informaci – akce ??" msgid "InfoRequestEvent|Calculated state" msgstr "InfoRequestEvent| V procesu" @@ -1361,16 +1361,16 @@ msgid "InfoRequestEvent|Prominence" msgstr "InfoRequestEvent | Prominence ??" msgid "InfoRequest|Allow new responses from" -msgstr "InfoRequestEvent | Povolit nové odpovědi od" +msgstr "InfoRequestEvent | Povolit nové odpovědi od " msgid "InfoRequest|Attention requested" -msgstr "InfoRequestEvent | Podle zákona ??" +msgstr "InfoRequestEvent|Podle zákona ??" msgid "InfoRequest|Awaiting description" msgstr "InfoRequestEvent | Očekává se popis" msgid "InfoRequest|Comments allowed" -msgstr "Info o žádosti|Komentáře dovoleny" +msgstr "Info o dotazu|Komentáře dovoleny" msgid "InfoRequest|Described state" msgstr "InfoRequestEvent | Popsaný status" @@ -1382,10 +1382,10 @@ msgid "InfoRequest|External user name" msgstr "InfoRequest|External user name ??" msgid "InfoRequest|Handle rejected responses" -msgstr "InfoRequestEvent | Řešit odmítnuté odpovědi" +msgstr "InfoRequestEvent | Řešit odmítnuté odpovědi " msgid "InfoRequest|Idhash" -msgstr "InfoRequestEvent I dhash ??" +msgstr "InfoRequestEventIdhash ??" msgid "InfoRequest|Law used" msgstr "InfoRequestEvent | Podle zákona" @@ -1394,10 +1394,10 @@ msgid "InfoRequest|Prominence" msgstr "InfoRequestEvent| Prominence ??" msgid "InfoRequest|Title" -msgstr "InfoRequestEvent | Název" +msgstr "InfoRequestEvent|Název" msgid "InfoRequest|Url title" -msgstr "InfoRequestEvent| Název URL" +msgstr "InfoRequestEvent|Název URL" msgid "Information not held." msgstr "Informace není k dispozici." @@ -1408,12 +1408,12 @@ msgid "" msgstr "Informace o vypouštění imisí a emisí (např. energie, hluk, radiace, odpady)" msgid "Internal review request" -msgstr "Přezkoumání dotazu" +msgstr "Doplnění dotazu" msgid "" "Is {{email_address}} the wrong address for {{type_of_request}} requests to " "{{public_body_name}}? If so, please contact us using this form:" -msgstr "Je {{email_address}} chybná adresa pro {{type_of_request}} dotazy vznesené na {{public_body_name}}? Pokud ano, prosíme kontaktujte nás vyplněním tohoto formuláře:" +msgstr "Je {{email_address}} chybná adresa pro {{type_of_request}} dotazy vznesené na instituci {{public_body_name}}? Pokud ano, prosíme kontaktujte nás vyplněním tohoto formuláře:" msgid "" "It may be that your browser is not set to accept a thing called " @@ -1470,22 +1470,22 @@ msgid "Made between" msgstr "Vloženo mezi" msgid "Mail server log" -msgstr "" +msgstr "Mail server log" msgid "Mail server log done" -msgstr "" +msgstr "Mail server log done" msgid "MailServerLogDone|Filename" -msgstr "" +msgstr "MailServerLogDone|Jméno souboru" msgid "MailServerLogDone|Last stat" -msgstr "" +msgstr "MailServerLogDone|Nejnovější statistiky" msgid "MailServerLog|Line" -msgstr "" +msgstr "MailServerLog|Řádek" msgid "MailServerLog|Order" -msgstr "" +msgstr "MailServerLog|Příkaz" msgid "Make a new <strong>Environmental Information</strong> request" msgstr "Vzneste dotaz týkající se <strong>životního prostředí</strong> " @@ -1513,7 +1513,7 @@ msgid "Make your own request" msgstr "Vzneste vlastní dotaz" msgid "Many requests" -msgstr "Mnoho žádostí" +msgstr "Mnoho dotazů" msgid "Message" msgstr "Zpráva" @@ -1528,7 +1528,7 @@ msgid "More about this authority" msgstr "Více o této instituci" msgid "More requests..." -msgstr "Více žádostí..." +msgstr "Více dotazů..." msgid "More similar requests" msgstr "Více podobných dotazů" @@ -1540,7 +1540,7 @@ msgid "My profile" msgstr "Můj profil" msgid "My request has been <strong>refused</strong>" -msgstr "Můj dotaz byla <strong>odmítnut</strong>" +msgstr "Zopodvězení mého dotazu bylo <strong>zadmítnuto</strong>" msgid "My requests" msgstr "Moje dotazy" @@ -1616,7 +1616,7 @@ msgstr "Nic tu není" msgid "" "Note that the requester will not be notified about your annotation, because " "the request was published by {{public_body_name}} on their behalf." -msgstr "Rádi bychom vás uzporonili, že tazatel nebude na váš komentář upozorněn, jelikož tento dotaz byl zveřejněn na žádost instituce {{public_body_name}}." +msgstr "Rádi bychom vás upozornili, že tazatel nebude o vašem komentáři informován, jelikož tento dotaz byl zveřejněn na žádost instituce {{public_body_name}}." msgid "Now check your email!" msgstr "Nyní zkontrolujte svou e-mailovou schránku!" @@ -1638,7 +1638,7 @@ msgstr "Nevhodný obsah?" msgid "" "Oh no! Sorry to hear that your request was refused. Here is what to do now." -msgstr "Ale ne! Je nám líto, že váš dotaz byla zamítnut. Pokud chcete, můžete učinit následující kroky." +msgstr "Mrzí nás, že zodpovězení vašeho dotazu bylo zamítnuto. Pokud na poskytnutí informací trváte, máte následující možnosti." msgid "Old e-mail:" msgstr "Původní e-mail" @@ -1848,7 +1848,7 @@ msgid "Please enter your password" msgstr "Vložte heslo. " msgid "Please give details explaining why you want a review" -msgstr "Prosíme vysvětlete, proč potřebujete přezkoumání. " +msgstr "Prosíme uveďte důvody, kvůli kterým žádáte o doplnění" msgid "Please keep it shorter than 500 characters" msgstr "Váš text musí být kratší než 500 znaků." @@ -1954,7 +1954,7 @@ msgid "Preview follow up to '" msgstr "Náhled odpovědi pro" msgid "Preview new annotation on '{{info_request_title}}'" -msgstr "Náhled nové anotace o '{{info_request_title}}'" +msgstr "Náhled nové anotace týkající se '{{info_request_title}}'" msgid "Preview your annotation" msgstr "Náhled poznámky" @@ -1990,7 +1990,7 @@ msgid "Public body/translation" msgstr "PublicBody | Verze ??" msgid "PublicBody::Translation|Disclosure log" -msgstr "" +msgstr "PublicBody::Translation|Disclosure log" msgid "PublicBody::Translation|First letter" msgstr "PublicBody | Začáteční písmeno" @@ -2020,7 +2020,7 @@ msgid "PublicBody|Api key" msgstr "PublicBody | Název ??" msgid "PublicBody|Disclosure log" -msgstr "" +msgstr "PublicBody|Disclosure log" msgid "PublicBody|First letter" msgstr "PublicBody | První dopis" @@ -2029,7 +2029,7 @@ msgid "PublicBody|Home page" msgstr "PublicBody | Domovská stránka" msgid "PublicBody|Info requests count" -msgstr "Veřejný orgán | Info o počtu žádostí" +msgstr "Veřejný orgán | Info o počtu dotazů" msgid "PublicBody|Last edit comment" msgstr "PublicBody | Naposled aktualizovaný komentář" @@ -2065,7 +2065,7 @@ msgid "Purge request" msgstr "Vyčistit formulář dotazu" msgid "PurgeRequest|Model" -msgstr "PurgeRequest|Verze ??" +msgstr "PurgeRequest|Verze" msgid "PurgeRequest|Url" msgstr "PurgeRequest|URL" @@ -2117,26 +2117,26 @@ msgid "Reported for administrator attention." msgstr "Administrátor byl již upozorněn." msgid "Request an internal review" -msgstr "Požádat o přezkoumání dotazu" +msgstr "Požádat o doplnění dotazu" msgid "Request an internal review from {{person_or_body}}" -msgstr "Požádat o přezkoumání dotazu u {{person_or_body}}" +msgstr "Požádat o doplnění dotazu od instituce či jmenovitě jejím pracovníkem {{person_or_body}}" msgid "Request has been removed" msgstr "Dotaz byl odstraněn" msgid "" "Request sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "Dotaz byl vznesen na {{public_body_name}} od {{info_request_user}} dne {{date}}." +msgstr "Dotaz byl vznesen na instituci {{public_body_name}} uživatelem {{info_request_user}} dne {{date}}." msgid "" "Request to {{public_body_name}} by {{info_request_user}}. Annotated by " "{{event_comment_user}} on {{date}}." -msgstr "Dotaz byl vznesen na {{public_body_name}} od {{info_request_user}}. Poznámka od {{event_comment_user}} dne {{date}}." +msgstr "Dotaz byl vznesen na instituci {{public_body_name}} uživatelem {{info_request_user}}. Poznámka od uživatele {{event_comment_user}} dne {{date}}." msgid "" "Requested from {{public_body_name}} by {{info_request_user}} on {{date}}" -msgstr "Vyžádáno {{public_body_name}} od {{info_request_user}} dne {{date}}" +msgstr "Vyžádáno institucí {{public_body_name}} od {{info_request_user}} dne {{date}}" msgid "Requested on {{date}}" msgstr "Dotaz byl vznesen dne {{date}}" @@ -2162,10 +2162,10 @@ msgid "Respond using the web" msgstr "Odpovězte na internetových stránkách" msgid "Response" -msgstr "Odpověď" +msgstr "Odpověď " msgid "Response from a public authority" -msgstr "Odpověď od instituce" +msgstr "Odpověď od instituce " msgid "Response to '{{title}}'" msgstr "Odpověď na '{{title}}'" @@ -2180,7 +2180,7 @@ msgid "Response to your request" msgstr "Odpověď na váš dotaz" msgid "Response:" -msgstr "Odpověď:" +msgstr "Odpověď: " msgid "Restrict to" msgstr "Omezit na" @@ -2210,10 +2210,10 @@ msgid "" "Search over<br/>\\n <strong>{{number_of_requests}} requests</strong> " "<span>and</span><br/>\\n <strong>{{number_of_authorities}} " "authorities</strong>" -msgstr "Prohledávejte více než<br/>\n <strong>{{number_of_requests}} dotazů</strong> <span>a</span><br/>\n <strong>{{number_of_authorities}} institucí</strong>" +msgstr "Prohledávejte více než<br/>\n <strong>{{number_of_requests}} dotazů</strong> <span>a</span><br/>\n <strong>{{number_of_authorities}} institucí v adresáři</strong>" msgid "Search queries" -msgstr "Prohledávejte žádosti" +msgstr "Prohledávejte dotazy" msgid "Search results" msgstr "Výsledky vyhledávání" @@ -2288,7 +2288,7 @@ msgid "Sign out" msgstr "Odhlásit" msgid "Sign up" -msgstr "Registovat" +msgstr "Registrovat" msgid "Similar requests" msgstr "Podobné dotazy" @@ -2314,7 +2314,7 @@ msgid "Somebody added a note to your FOI request - " msgstr "Někdo přidal poznámku k vašemu dotazu – " msgid "Someone has updated the status of your request" -msgstr "Někdo aktualizovat status vaší žádosti" +msgstr "Někdo aktualizoval status vašeho dotazu" msgid "" "Someone, perhaps you, just tried to change their email address " @@ -2351,7 +2351,7 @@ msgid "Stay up to date" msgstr "Buďte informováni" msgid "Still awaiting an <strong>internal review</strong>" -msgstr "Stále čekám na <strong>přezkoumání dotazu</strong>" +msgstr "Stále <strong>čekám</strong> na doplnění dotazu" msgid "Subject" msgstr "Předmět" @@ -2377,7 +2377,7 @@ msgstr "Úspěch." msgid "" "Suggest how the requester can find the <strong>rest of the " "information</strong>." -msgstr "Doporučte, jak tazatel může najít<strong>úplné informace</strong>." +msgstr "Doporučte, jak tazatel může najít <strong>úplné informace</strong>." msgid "Summary:" msgstr "Shrnutí:" @@ -2406,13 +2406,13 @@ msgstr "Děkujeme vám za vaši anotaci!" msgid "" "Thank you for responding to this FOI request! Your response has been " "published below, and a link to your response has been emailed to " -msgstr "Děkujeme vám za odpověď na tento dotaz! Vaše odpověď byla publikována níže a odkaz vaší odpovědi byl odeslán " +msgstr "Děkujeme vám za odpověď na tento dotaz! Vaše odpověď byla publikována níže a odkaz s vaší odpovědí byl odeslán " msgid "" "Thank you for updating the status of the request '<a " "href=\"{{url}}\">{{info_request_title}}</a>'. There are some more requests " "below for you to classify." -msgstr "Děkujeme za aktualizaci statusu dotazu '<a href=\"{{url}}\">{{info_request_title}}</a>'. Zde jsou další odkazy, které je třeba zatřídit. " +msgstr "Děkujeme za aktualizaci statusu dotazu '<a href=\"{{url}}\">{{info_request_title}}</a>'. Zde jsou další odkazy, které čekají na zařazenít. " msgid "Thank you for updating this request!" msgstr "Děkujeme vám za aktualizaci tohoto dotazu!" @@ -2523,7 +2523,7 @@ msgid "" "The response to your request has been <strong>delayed</strong>. You can say" " that, \\n by law, the authority should normally have " "responded\\n <strong>promptly</strong> and" -msgstr "Odpověď na váš dotaz má <strong>zpoždění</strong>. Můžete napsat, že podle zákona by instituce měla odpovědět nejpozději\n <strong>do 15 dnů</strong> a" +msgstr "Odpověď na váš dotaz má <strong>zpoždění</strong>. Můžete napsat, že podle zákona by instituce měla odpovědět nejpozději\n <strong>do 15 dnů</strong> a " msgid "" "The response to your request is <strong>long overdue</strong>. You can say" @@ -2575,7 +2575,7 @@ msgid "Then you can sign in to {{site_name}}" msgstr "Poté se můžete přihlásit na stránkách {{site_name}}" msgid "Then you can update the status of your request to " -msgstr "Poté můžete aktualizovat status svého dotazu na" +msgstr "Poté můžete aktualizovat status svého dotazu na " msgid "Then you can upload an FOI response. " msgstr "Poté můžete nahrát odpověď na váš dotaz." @@ -2610,7 +2610,7 @@ msgstr "Od nynějška budete upozorněni jakmile bude na '{{public_body_name}}' msgid "" "Then you will be updated whenever the request '{{request_title}}' is " "updated." -msgstr "Budete upozorněni na zmeěu stavu u dotazu '{{request_title}}'." +msgstr "Budete upozorněni na změnu stavu u dotazu '{{request_title}}'." msgid "Then you'll be allowed to send FOI requests." msgstr "Pak můžete vznést dotaz." @@ -2701,7 +2701,7 @@ msgid "" msgstr "Toto zahrnuje široké spektrum informací o stavu \n <strong>přírody a památek</strong>, například:" msgid "This external request has been hidden" -msgstr "This external request has been hidden ??" +msgstr "Tento dotaz byl skryt." msgid "" "This is a plain-text version of the Freedom of Information request " @@ -2781,7 +2781,7 @@ msgid "" "This request has been <strong>withdrawn</strong> by the person who made " "it.\\n There may be an explanation in the correspondence " "below." -msgstr "Dotaz byla <strong>stažen</strong> tazatelem. \nBližší vysvětlení můžete najít v níže uvedené korespondenci." +msgstr "Dotaz byl <strong>stažen</strong> tazatelem. \nBližší vysvětlení můžete najít v níže uvedené korespondenci." msgid "" "This request has been marked for review by the site administrators, who have" @@ -2795,7 +2795,7 @@ msgstr "Odesláno administrátorovi" msgid "" "This request has been set by an administrator to \"allow new responses from " "nobody\"" -msgstr "Tento dotaz byl poslán administrátorovi, aby \"povolil nové odpovědi od nikoho\"" +msgstr "Tento dotaz byl poslán administrátorovi, aby \"povolil nové odpovědi od nikoho\"." msgid "" "This request has had an unusual response, and <strong>requires " @@ -2854,7 +2854,7 @@ msgid "To change your email address used on {{site_name}}" msgstr "Změnit e-mailovou adresu, kterou používáte na stránkách {{site_name}}" msgid "To classify the response to this FOI request" -msgstr "Pro zatřídění dotazů" +msgstr "Pro utřídění dotazů" msgid "To do that please send a private email to " msgstr "Aby se tak stalo, prosíme pošlete e-mail soukromou cestou" @@ -2894,7 +2894,7 @@ msgstr "Abychom udržovali stránky přehledné, někdo jiný upravil status va msgid "" "To let everyone know, follow this link and then select the appropriate box." -msgstr "To let everyone know, follow this link and then select the appropriate box. ??" +msgstr "Sdílejte tento link a vyberte nejvhodnější variantu. ??" msgid "To log into the administrative interface" msgstr "Přihlásit se do administrace" @@ -2925,7 +2925,7 @@ msgstr "Aktualizovat stav dotazu" msgid "" "To upload a response, you must be logged in using an email address from " -msgstr "Abyste mohli nahrát odpověď, musíte být přihlášeni pod e-mailovou adresou z" +msgstr "Abyste mohli nahrát odpověď, musíte být přihlášeni pod e-mailovou adresou " msgid "" "To use the advanced search, combine phrases and labels as described in the " @@ -3029,7 +3029,7 @@ msgid "Update the status of your request to " msgstr "Aktualizujte stav svého dotazu vzneseného na " msgid "Upload FOI response" -msgstr "Nahrajte odpověď na žádost" +msgstr "Nahrajte odpověď na dotaz " msgid "" "Use OR (in capital letters) where you don't mind which word, e.g. " @@ -3131,12 +3131,12 @@ msgstr "Čeká se na vysvětlení. " msgid "" "Waiting for an <strong>internal review</strong> by {{public_body_link}} of " "their handling of this request." -msgstr "Čeká se na <strong>přezkoumání dotazu</strong> u {{public_body_link}}." +msgstr "Stále <strong>čekám</strong> na doplnění dotazu institucí či jmenovitě jejím pracovníkem {{person_or_body}}." msgid "" "Waiting for the public authority to complete an internal review of their " "handling of the request" -msgstr "Čeká se na vnitřní přezkoumání u instituce, jak na dotaz odpoví" +msgstr "Čekám, až instituce doplní požadované informace k mému dotazu" msgid "Waiting for the public authority to reply" msgstr "Čeká se na odpověď instituce" @@ -3181,7 +3181,7 @@ msgstr "Čekáme, až si to někdo přečte" msgid "" "We've sent an email to your new email address. You'll need to click the link" " in\\nit before your email address will be changed." -msgstr "Poslali jsme e-mail na vaši novou adresu. Je třeba kliknout na zaslaný odkaz,\naby byla vaše nová e-mailová adresa aktivována." +msgstr "Poslali jsme e-mail na vaši novou adresu. Je třeba kliknout na zaslaný odkaz, aby vaše nová e-mailová adresa byla správně přiřazena." msgid "" "We've sent you an email, and you'll need to click the link in it before you " @@ -3208,17 +3208,17 @@ msgstr "Jaká informace byla požadována?" msgid "" "When you get there, please update the status to say if the response " "\\ncontains any useful information." -msgstr "Až se přihlásíte, aktualizujte status s ohledem na to,\nzda odpověď je dostačující či nikoliv." +msgstr "Přihlašte se na stránky IPV, přečtěte si odpověď a aktualizujte status tohoto dotazu s ohledem na poskytnutou odpověď. Status aktualizujete jednoduše zaškrtnutím jedné z možností.\n\nStav svého dotazu či odpověď instituce včetně svého dotazu můžete také sdílet na sociálních sítích nebo na svých stránkách či blogu. Pokud tak uděláte, vždy sdílejte i link na svůj dotaz na stránkách IPV. Děkujeme Vám." msgid "" "When you receive the paper response, please help\\n others find " "out what it says:" -msgstr "Pokud obdržíte písemnou odpověď, prosíme shrňte\n pro ostatní co se v odpovědi říká:" +msgstr "Pokud obdržíte písemnou odpověď, prosíme shrňte\n pro ostatní, co se v odpovědi říká:" msgid "" "When you're done, <strong>come back here</strong>, <a href=\"%s\">reload " "this page</a> and file your new request." -msgstr "Až budete hotovi, <strong>vraťte se sem</strong>, <a href=\"%s\">obnovte stránku</a> a vzneste svůj nový dotaz." +msgstr "Až budete hotovi, <strong>vraťte se sem</strong>, <a href=\"%s\">obnovte stránku</a> a vzneste nový dotaz." msgid "Which of these is happening?" msgstr "Vyberte nejvhodnější popis z následujících možností." @@ -3245,7 +3245,7 @@ msgid "Write your FOI follow up message to " msgstr "Napište svou odpověď pro " msgid "Write your request in <strong>simple, precise language</strong>." -msgstr "Napište svůj dotaz <strong>jednoduše a jasně</strong>.\nSvůj dotaz formulujte v jasných bodech. \nPokud žádáte o více nesouvisejících informací, rozdělte je do více žádostí. " +msgstr "Napište svůj dotaz <strong>jednoduše a jasně</strong>.\nSvůj dotaz formulujte v jasných bodech. \nPokud žádáte o více nesouvisejících informací, rozdělte je do více dotazů. " msgid "You" msgstr "Vy" @@ -3303,7 +3303,7 @@ msgid "" msgstr "Od této instituce můžete požadovat pouze informace podle zákona o životním prostředí. " msgid "You have a new response to the {{law_used_full}} request " -msgstr "Máte novou odpověďna {{law_used_full}} " +msgstr "Máte novou odpověď na {{law_used_full}} " msgid "" "You have found a bug. Please <a href=\"{{contact_url}}\">contact us</a> to " @@ -3400,10 +3400,10 @@ msgid "" msgstr "Odpověď na váš dotaz obdržíte, pouze pokud odpovíte \nbližším vysvětlením." msgid "You're in. <a href=\"#\" id=\"send-request\">Continue sending your request</a>" -msgstr "" +msgstr "Odesláno. <a href=\"#\" id=\"send-request\"> Můžete vznést další dotaz.</a>" msgid "You're long overdue a response to your FOI request - " -msgstr "Dlouho jste nereagovali na odpověď k vašemu dotazu –" +msgstr "Dlouho jste nereagovali na odpověď ke svému dotazu –" msgid "You're not following anything." msgstr "Nesledujete žádný vznesený dotaz." @@ -3428,7 +3428,7 @@ msgid "" "href=\"%s\">why?</a>)\\n on this website and in search engines. If " "you\\n are thinking of using a pseudonym, please \\n <a " "href=\"%s\">read this first</a>." -msgstr "Vaše<strong> jméno bude uveřejněno</strong> \n (<a href=\"%s\">proč?</a>)\n na těchto stránkách a ve vyhledavačích. Pokud\n chcete použít přezdívku, prosíme, \n <a href=\"%s\">přečtěte nejdříve toto</a>." +msgstr "Vaše<strong> jméno bude uveřejněno</strong> \n (<a href=\"%s\">proč?</a>)\n na těchto stránkách a ve vyhledávačích. Pokud\n chcete použít přezdívku, prosíme, \n <a href=\"%s\">přečtěte si nejdříve toto</a>." msgid "Your annotations" msgstr "Vaše poznámky" @@ -3444,13 +3444,13 @@ msgid "" "Your follow up has not been sent because this request has been stopped to " "prevent spam. Please <a href=\"%s\">contact us</a> if you really want to " "send a follow up message." -msgstr "Vaše odpověď nebyla odeslána, protože tento dotaz byla identifikován jako nevyžádaná zpráva. Prosíme <a href=\"%s\">kontaktujte nás</a> pokud svou zprávu chcete odeslat. " +msgstr "Vaše odpověď nebyla odeslána, protože tento dotaz byl identifikován jako nevyžádaná zpráva. Prosíme <a href=\"%s\">kontaktujte nás</a> pokud svou zprávu chcete odeslat. " msgid "Your follow up message has been sent on its way." msgstr "Zpráva s vaší odpovědí byla odeslána. " msgid "Your internal review request has been sent on its way." -msgstr "Vaše žádost o přezkoumání byla odeslána." +msgstr "Dotaz týkající se doplnění byla odeslána." msgid "" "Your message has been sent. Thank you for getting in touch! We'll get back " @@ -3495,18 +3495,18 @@ msgstr "<strong>Důležité upozornění:</strong> Vaše fotografie bude zveřej msgid "" "Your request was called {{info_request}}. Letting everyone know whether you " "got the information will help us keep tabs on" -msgstr "Informace se týká vašeho dotazu {{info_request}}. Můžete všechny informovat, zda jste požadovanou informaci obdrželi a budeme mít přehled o odpovědích instituce" +msgstr "Informace se týká vašeho dotazu {{info_request}}. Můžete všechny informovat, zda jste požadovanou informaci obdrželi a bude tak přehled o odpovědích této instituce" msgid "Your request:" msgstr "Váš dotaz:" msgid "Your response to an FOI request was not delivered" -msgstr "Vaše odpověď na žádost nebyla doručena" +msgstr "Vaše odpověď na dotaz nebyla doručena" msgid "" "Your response will <strong>appear on the Internet</strong>, <a " "href=\"%s\">read why</a> and answers to other questions." -msgstr "Vaše odpověď <strong>bude uveřejněna na internetu</strong>, <a href=\"%s\">čtěte proč</a>odpovědi na další otázky." +msgstr "Vaše odpověď <strong>bude uveřejněna na internetu</strong>, <a href=\"%s\">čtěte proč</a> spolu s historií konverzace." msgid "" "Your thoughts on what the {{site_name}} <strong>administrators</strong> " @@ -3581,7 +3581,7 @@ msgid "authorities" msgstr "instituce" msgid "awaiting a response" -msgstr "očekává se odpověď" +msgstr "očekává se odpověď " msgid "beginning with ‘{{first_letter}}’" msgstr "Začínající na ‘{{first_letter}}’" @@ -3596,7 +3596,7 @@ msgid "by <strong>{{date}}</strong>" msgstr "od <strong>{{date}}</strong>" msgid "by {{public_body_name}} to {{info_request_user}} on {{date}}." -msgstr "od {{public_body_name}} pro {{info_request_user}} dne {{date}}." +msgstr "od instituce {{public_body_name}} pro uživatele {{info_request_user}} dne {{date}}." msgid "by {{user_link_absolute}}" msgstr "by {{user_link_absolute}}" @@ -3689,7 +3689,7 @@ msgid "please sign in as " msgstr "prosíme přihlašte se jako" msgid "requesting an internal review" -msgstr "požadavek na přezkoumání dotazu" +msgstr "požádat o doplnění dotazu " msgid "requests" msgstr "dotazy" @@ -3700,13 +3700,13 @@ msgstr "dotazy které jsou {{list_of_statuses}}" msgid "" "response as needing administrator attention. Take a look, and reply to " "this\\nemail to let them know what you are going to do about it." -msgstr "jako odpověď, která vyžaduje pozornost administrátora. Podívejte se na ni, odpovězte\nna tento e-mail a oznamte, co budete dělat. ??" +msgstr "adminsitrátorovi. Podívejte se prosím na vznesený dotaz i odpověď. Až uděláte nezbytné kroky, odpovězte na tento e-mail a stručně je popište." msgid "send a follow up message" msgstr "poslat odpověď" msgid "sent to {{public_body_name}} by {{info_request_user}} on {{date}}." -msgstr "posláno {{public_body_name}} od {{info_request_user}} v {{date}}." +msgstr "posláno instituci {{public_body_name}} uživatelem {{info_request_user}} dne {{date}}." msgid "show quoted sections" msgstr "ukázat citované pasáže" @@ -3727,7 +3727,7 @@ msgid "that you made to" msgstr "kterou jste vznesli na" msgid "the main FOI contact address for {{public_body}}" -msgstr "hlavní kontaktní adresa pro poskytování informací institucí {{public_body}}" +msgstr "hlavní kontaktní adresa instituce {{public_body}} pro poskytování informací " msgid "the main FOI contact at {{public_body}}" msgstr "hlavní kontakt pro vznesení dotazu na instituci {{public_body}}" @@ -3791,7 +3791,7 @@ msgid "{{info_request_user_name}} only:" msgstr "Pouze {{info_request_user_name}}:" msgid "{{law_used_full}} request - {{title}}" -msgstr "Žádost o informace podle {{law_used_full}} - {{title}}" +msgstr "Dotaz o informace podle {{law_used_full}} - {{title}}" msgid "{{law_used_full}} request GQ - {{title}}" msgstr "{{law_used_full}} žádejte GQ - {{title}} ??" @@ -3809,10 +3809,10 @@ msgid "{{number_of_comments}} comments" msgstr "{{number_of_comments}} komentářů" msgid "{{public_body_link}} answered a request about" -msgstr "{{public_body_link}} zodpověděl dotaz týkající se" +msgstr "Instituce {{public_body_link}} zodpověděla dotaz týkající se " msgid "{{public_body_link}} was sent a request about" -msgstr "Na {{public_body_link}} byl odeslán dotaz" +msgstr "Na instituci {{public_body_link}} byl vznesen dotaz " msgid "{{public_body_name}} only:" msgstr "Pouze {{public_body_name}}:" @@ -3838,7 +3838,7 @@ msgstr "Stránky {{site_name}} zahrnují dotazy vznesené na {{number_of_authori msgid "" "{{site_name}} sends new requests to <strong>{{request_email}}</strong> for " "this authority." -msgstr "Stránky {{site_name}} vznáší nové dotazy na <strong>{{request_email}}</strong> tuto instituci." +msgstr "Pomocí stránek {{site_name}} vznesete nové dotazy na <strong>{{request_email}}</strong> tuto instituci." msgid "" "{{site_name}} users have made {{number_of_requests}} requests, including:" @@ -3880,7 +3880,7 @@ msgid "" "{{user}} ({{user_admin_link}}) made this {{law_used_full}} request (<a " "href=\"{{request_admin_url}}\">admin</a>) to {{public_body_link}} (<a " "href=\"{{public_body_admin_url}}\">admin</a>)" -msgstr "{{user}} ({{user_admin_link}}) podal tuto {{law_used_full}} (<a href=\"{{request_admin_url}}\">admin</a>) pro {{public_body_link}} (<a href=\"{{public_body_admin_url}}\">admin</a>)" +msgstr "{{user}} ({{user_admin_link}}) vznesl tento {{law_used_full}} dotaz (<a href=\"{{request_admin_url}}\">admin</a>) na instuci {{public_body_link}} (<a href=\"{{public_body_admin_url}}\">admin</a>)" msgid "{{user}} made this {{law_used_full}} request" msgstr "{{user}} vložil tuto {{law_used_full}} " diff --git a/locale/cy/app.po b/locale/cy/app.po index 346bb698e..b55a61b5d 100644 --- a/locale/cy/app.po +++ b/locale/cy/app.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" "POT-Creation-Date: 2012-11-06 16:35+0000\n" -"PO-Revision-Date: 2012-11-06 18:09+0000\n" -"Last-Translator: louisecrow <louise@mysociety.org>\n" +"PO-Revision-Date: 2012-11-20 22:54+0000\n" +"Last-Translator: skenaja <alex@alexskene.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -45,7 +45,7 @@ msgstr "" msgid "" " <strong>Note:</strong>\\n We will send you an email. Follow the " "instructions in it to change\\n your password." -msgstr "" +msgstr " <strong>Sylwer:</strong>\\n Byddwn yn anfon e-bost atoch. Dilynwch y cyfarwyddiadau ynddo i newid eich cyfrinair." msgid " <strong>Privacy note:</strong> Your email address will be given to" msgstr "" @@ -139,7 +139,7 @@ msgstr[2] "" msgstr[3] "" msgid "'Crime statistics by ward level for Wales'" -msgstr "" +msgstr "'Ystadegau troseddu yn ôl lefel ward ar gyfer Cymru'" msgid "'Pollution levels over time for the River Tyne'" msgstr "" @@ -332,7 +332,7 @@ msgstr[3] "" msgid "" "<strong> Can I request information about myself?</strong>\\n\t\t\t<a " "href=\"%s\">No! (Click here for details)</a>" -msgstr "" +msgstr "<strong> A gaf i wneud cais am wybodaeth amdanaf fi fy hun?</strong>\\n\t\t\t<a href=\"%s\">Na chewch! (Cliciwch yma am fanylion)</a>" msgid "" "<strong><code>commented_by:tony_bowden</code></strong> to search annotations" @@ -595,7 +595,7 @@ msgstr "" msgid "" "Ask for <strong>specific</strong> documents or information, this site is not" " suitable for general enquiries." -msgstr "" +msgstr "Gofynnwch am ddogfennau neu wybodaeth <strong>benodol</strong>. Nid yw'r wefan hon yn addas ar gyfer ymholiadau cyffredinol." msgid "" "At the bottom of this page, write a reply to them trying to persuade them to" @@ -631,7 +631,7 @@ msgid "" msgstr "" msgid "Browse all authorities..." -msgstr "" +msgstr "Mwy o awdurdodau..." msgid "" "By law, under all circumstances, {{public_body_link}} should have responded " @@ -689,13 +689,13 @@ msgid "Change your email address used on {{site_name}}" msgstr "" msgid "Change your password" -msgstr "" +msgstr "Newid eich cyfrinair" msgid "Change your password on {{site_name}}" msgstr "Newid eich cyfrinair ar {{site_name}}" msgid "Change your password {{site_name}}" -msgstr "" +msgstr "Newid eich cyfrinair {{site_name}}" msgid "Charity registration" msgstr "Elusen gofrestredig" @@ -823,7 +823,7 @@ msgid "Date:" msgstr "Dyddiad" msgid "Dear {{public_body_name}}," -msgstr "" +msgstr "Annwyl {{public_body_name}}," msgid "Delayed response to your FOI request - " msgstr "" @@ -967,7 +967,7 @@ msgid "" "First, type in the <strong>name of the UK public authority</strong> you'd " "\\n like information from. <strong>By law, they have to " "respond</strong>\\n (<a href=\"%s#%s\">why?</a>)." -msgstr "" +msgstr "Yn gyntaf, teipiwch <strong>enw awdurdod cyhoeddus yn y DU</strong> yr hoffech gael gwybodaeth ganddo. <strong>Yn ôl y gyfraith, mae'n rhaid iddynt ymateb</strong> (<a href=\"%s#%s\">pam?</a>)." msgid "Foi attachment" msgstr "" @@ -1052,7 +1052,7 @@ msgid "" msgstr "" msgid "Forgotten your password?" -msgstr "" +msgstr "Wedi anghofio eich cyfrinair?" msgid "Found %d public authority %s" msgid_plural "Found %d public authorities %s" @@ -1238,7 +1238,7 @@ msgstr "" msgid "" "If you are thinking of using a pseudonym,\\n please <a " "href=\"%s\">read this first</a>." -msgstr "" +msgstr "Os ydych yn ystyried defnyddio ffugenw, <a href=\"%s\">darllenwch hwn yn gyntaf</a> os gwelwch yn dda." msgid "If you are {{user_link}}, please" msgstr "" @@ -1293,10 +1293,10 @@ msgid "" msgstr "" msgid "If you're new to {{site_name}}" -msgstr "" +msgstr "Os ydych yn newydd i {{site_name}}" msgid "If you've used {{site_name}} before" -msgstr "" +msgstr "Os ydych chi wedi defnyddio {{site_name}} o'r blaen " msgid "" "If your browser is set to accept cookies and you are seeing this " @@ -1435,7 +1435,7 @@ msgstr "" msgid "" "Keep it <strong>focused</strong>, you'll be more likely to get what you want" " (<a href=\"%s\">why?</a>)." -msgstr "" +msgstr "Cadwch at <strong>y prif bwynt</strong>. Byddwch yn fwy tebygol o gael beth rydych yn chwilio amdano (<a href=\"%s\">pam?</a>)." msgid "Keywords" msgstr "" @@ -1713,7 +1713,7 @@ msgid "Password:" msgstr "Cyfrinair" msgid "Password: (again)" -msgstr "" +msgstr "Cyfrinair: (eto)" msgid "Paste this link into emails, tweets, and anywhere else:" msgstr "" @@ -1963,7 +1963,7 @@ msgid "Preview your message" msgstr "" msgid "Preview your public request" -msgstr "" +msgstr "Rhagolwg o'ch cais cyhoeddus" msgid "Profile photo" msgstr "" @@ -2102,7 +2102,7 @@ msgstr "" msgid "" "Remember me</label> (keeps you signed in longer;\\n do not use on a " "public computer) " -msgstr "" +msgstr "Cofiwch fi</label> (yn eich cadw wedi eich mewngofnodi yn hwy; peidiwch â defnyddio hwn ar gyfrifiadur cyhoeddus)" msgid "Report abuse" msgstr "" @@ -2277,7 +2277,7 @@ msgid "Showing" msgstr "" msgid "Sign in" -msgstr "" +msgstr "Mewngofnodi" msgid "Sign in or make a new account" msgstr "Mewngofnodi neu gofrestru" @@ -2289,7 +2289,7 @@ msgid "Sign out" msgstr "" msgid "Sign up" -msgstr "" +msgstr "Cofrestrwch" msgid "Similar requests" msgstr "" @@ -2381,7 +2381,7 @@ msgid "" msgstr "" msgid "Summary:" -msgstr "" +msgstr "Crynodeb:" msgid "Table of statuses" msgstr "" @@ -2948,7 +2948,7 @@ msgid "To {{public_body_link_absolute}}" msgstr "" msgid "To:" -msgstr "" +msgstr "I:" msgid "Today" msgstr "" @@ -3164,17 +3164,17 @@ msgstr "" msgid "" "We will not reveal your email address to anybody unless you or\\n the" " law tell us to (<a href=\"%s\">details</a>). " -msgstr "" +msgstr "Ni fyddwn yn datgelu eich cyfeiriad e-bost i neb oni bai eich bod chi neu'r gyfraith yn dweud wrthym i wneud (<a href=\"%s\">manylion</a>)." msgid "" "We will not reveal your email address to anybody unless you\\nor the law " "tell us to." -msgstr "" +msgstr "Ni fyddwn yn datgelu eich cyfeiriad e-bost i neb oni bai eich bod chi neu'r gyfraith yn dweud wrthym i wneud." msgid "" "We will not reveal your email addresses to anybody unless you\\nor the law " "tell us to." -msgstr "" +msgstr "Ni fyddwn yn datgelu eich cyfeiriad e-bost i neb oni bai eich bod chi neu'r gyfraith yn dweud wrthym i wneud." msgid "We're waiting for" msgstr "" @@ -3249,7 +3249,7 @@ msgid "Write your FOI follow up message to " msgstr "" msgid "Write your request in <strong>simple, precise language</strong>." -msgstr "" +msgstr "Ysgrifennwch eich cais mewn <strong>iaith syml, gryno</strong>." msgid "You" msgstr "" @@ -3434,7 +3434,7 @@ msgid "" "href=\"%s\">why?</a>)\\n on this website and in search engines. If " "you\\n are thinking of using a pseudonym, please \\n <a " "href=\"%s\">read this first</a>." -msgstr "" +msgstr "Bydd <strong>eich enw yn ymddangos yn gyhoeddus</strong> ( <a href=\"%s\">pam?</a>) ar y wefan hon ac mewn peiriannau chwilio.\nOs ydych yn ystyried defnyddio ffugenw, os gwelwch yn dda <a href=\"%s\">darllenwch hwn yn gyntaf</a>." msgid "Your annotations" msgstr "" @@ -3444,7 +3444,7 @@ msgid "" msgstr "" msgid "Your e-mail:" -msgstr "" +msgstr "Eich cyfeiriad e-bost:" msgid "" "Your follow up has not been sent because this request has been stopped to " @@ -3482,7 +3482,7 @@ msgid "" msgstr "" msgid "Your name:" -msgstr "" +msgstr "Eich enw:" msgid "Your original message is attached." msgstr "" @@ -3523,7 +3523,7 @@ msgid "Your {{site_name}} email alert" msgstr "" msgid "Yours faithfully," -msgstr "Yn gywir" +msgstr "Yr eiddoch yn gywir," msgid "Yours sincerely," msgstr "Yn gywir" @@ -3543,7 +3543,7 @@ msgid "" msgstr "" msgid "a one line summary of the information you are requesting, \\n\t\t\te.g." -msgstr "" +msgstr "crynodeb un llinell o'r wybodaeth rydych yn gofyn amdano, \n\\n \t\t\tee " msgid "admin" msgstr "" @@ -3718,7 +3718,7 @@ msgid "show quoted sections" msgstr "" msgid "sign in" -msgstr "Mewngofnodi neu gofrestru" +msgstr "Mewngofnodi" msgid "simple_date_format" msgstr "" diff --git a/locale/es/app.po b/locale/es/app.po index c211b65a0..720bab544 100644 --- a/locale/es/app.po +++ b/locale/es/app.po @@ -13,8 +13,8 @@ msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" "POT-Creation-Date: 2012-11-06 16:35+0000\n" -"PO-Revision-Date: 2012-11-06 18:20+0000\n" -"Last-Translator: louisecrow <louise@mysociety.org>\n" +"PO-Revision-Date: 2012-11-29 00:22+0000\n" +"Last-Translator: David Cabo <david.cabo@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -2580,7 +2580,7 @@ msgid "Then you can write your reply to " msgstr "Entonces podrás escribir tu respuesta a " msgid "Then you will be following all new FOI requests." -msgstr "" +msgstr "Entonces recibirás actualizaciones por correo de todas las nuevas solicitudes." msgid "" "Then you will be notified whenever '{{user_name}}' requests something or " @@ -2603,7 +2603,7 @@ msgstr "Entonces vas a ser avisado cuando alguien haga un pedido o " msgid "" "Then you will be updated whenever the request '{{request_title}}' is " "updated." -msgstr "" +msgstr "Entonces recibirás correos siempre que la solicitud '{{request_title}}' se actualice." msgid "Then you'll be allowed to send FOI requests." msgstr "Entonces podrá enviar solicitudes de información." @@ -2777,7 +2777,7 @@ msgid "" "This request has been marked for review by the site administrators, who have" " not hidden it at this time. If you believe it should be hidden, please <a " "href=\"%s\">contact us</a>." -msgstr "" +msgstr "Esta solicitud va a ser revisada por los administradores de la web, que no la han ocultado de momento. Si crees que debe ser ocultada, por favor <a href=\"%s\">contáctanos</a>." msgid "This request has been reported for administrator attention" msgstr "Este pedido ha sido reportado al administrador del sitio." @@ -2859,7 +2859,7 @@ msgid "To follow all successful requests" msgstr "Sigue todos los pedidos exitosos" msgid "To follow new requests" -msgstr "" +msgstr "Seguir nuevas solicitudes" msgid "To follow requests and responses matching your search" msgstr "Para seguir solicitudes y respuestas que encajen con tu búsqueda" @@ -3247,16 +3247,16 @@ msgid "You are already following requests to {{public_body_name}}" msgstr "Tu ya estas siguiendo pedidos a {{public_body_name}}" msgid "You are already following things matching this search" -msgstr "" +msgstr "Ya estás siguiendo esta búsqueda por correo" msgid "You are already following this person" -msgstr "" +msgstr "Ya estás siguiendo a esta persona por correo" msgid "You are already following this request" -msgstr "" +msgstr "Ya estás siguiendo esta solicitud por correo" msgid "You are already following updates about {{track_description}}" -msgstr "" +msgstr "Ya estás recibiendo actualizaciones por correo sobre la solicitud." msgid "" "You are currently receiving notification of new activity on your wall by " @@ -3264,7 +3264,7 @@ msgid "" msgstr "Actualmente estas recibiendo notificaciones de nueva actividad en tu muro por correo electronico." msgid "You are following all new successful responses" -msgstr "" +msgstr "Estás recibiendo correos sobre cualquier nueva respuesta exitosa" msgid "You are no longer following {{track_description}}." msgstr "" @@ -3272,7 +3272,7 @@ msgstr "" msgid "" "You are now <a href=\"{{wall_url_user}}\">following</a> updates about " "{{track_description}}" -msgstr "" +msgstr "Ahora estás recibiendo <a href=\"{{wall_url_user}}\">actualizaciones</a> sobre {{track_description}}" msgid "You can <strong>complain</strong> by" msgstr "Puede <strong>apelar</strong>" @@ -3382,7 +3382,7 @@ msgstr "Ya no recibirá correos para esas alertas" msgid "" "You will now be emailed updates about {{track_description}}. <a " "href=\"{{change_email_alerts_url}}\">Prefer not to receive emails?</a>" -msgstr "" +msgstr "Ahora recibirás actualizaciones por correo sobre {{track_description}}. <a href=\"{{change_email_alerts_url}}\">¿Prefieres no recibir correos?</a>" msgid "" "You will only get an answer to your request if you follow up\\nwith the " @@ -3396,7 +3396,7 @@ msgid "You're long overdue a response to your FOI request - " msgstr "La respuesta a tu solicitud de información está muy retrasada - " msgid "You're not following anything." -msgstr "" +msgstr "No estás recibiendo actualizaciones por correo." msgid "You've now cleared your profile photo" msgstr "Has borrado la foto de tu perfil" @@ -3511,13 +3511,13 @@ msgid "Yours sincerely," msgstr "Un saludo," msgid "[FOI #{{request}} email]" -msgstr "" +msgstr "[Dirección de correo de la solicitud #{{request}}]" msgid "[{{public_body}} request email]" -msgstr "" +msgstr "[Dirección de correo del organismo {{public_body}}]" msgid "[{{site_name}} contact email]" -msgstr "" +msgstr "[Correo de contacto de {{site_name}}]" msgid "" "\\n\\n[ {{site_name}} note: The above text was badly encoded, and has had " @@ -3598,7 +3598,7 @@ msgid "" msgstr "incluyendo tu dirección postal, y pidiéndoles que contesten a tu solicitud.\n O prueba a llamarles por teléfono." msgid "details" -msgstr "" +msgstr "detalles" msgid "display_status only works for incoming and outgoing messages right now" msgstr "display_status sólo funciona para mensajes de entrada y salida ahora mismo" @@ -3625,7 +3625,7 @@ msgid "have delayed." msgstr "han retrasado." msgid "hide quoted sections" -msgstr "" +msgstr "ocultar partes citadas" msgid "in term time" msgstr "durante el periodo escolar" @@ -3697,13 +3697,13 @@ msgid "sent to {{public_body_name}} by {{info_request_user}} on {{date}}." msgstr "enviada a {{public_body_name}} por {{info_request_user}} el {{date}}." msgid "show quoted sections" -msgstr "" +msgstr "mostrar partes citadas" msgid "sign in" msgstr "abrir sesión" msgid "simple_date_format" -msgstr "" +msgstr "simple_date_format" msgid "successful" msgstr "exitosas" @@ -3785,7 +3785,7 @@ msgid "{{law_used_full}} request GQ - {{title}}" msgstr "solicitud {{law_used_full}} - {{title}}" msgid "{{law_used}} requests at {{public_body}}" -msgstr "" +msgstr "Solicitudes de información a {{public_body}}" msgid "{{length_of_time}} ago" msgstr "hace {{length_of_time}}" @@ -3833,7 +3833,7 @@ msgid "" msgstr "Los usuarios de {{site_name}} han hecho {{number_of_requests}} solicitudes, incluyendo:" msgid "{{title}} - a Freedom of Information request to {{public_body}}" -msgstr "" +msgstr "{{title}} - una solicitud de información a {{public_body}}" msgid "{{user_name}} (Account suspended)" msgstr "{{user_name}} (Expulsado)" diff --git a/public/images/quote.png b/public/images/quote.png Binary files differdeleted file mode 100644 index 752b7d4cf..000000000 --- a/public/images/quote.png +++ /dev/null diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 93230cf4f..0bf88b0f2 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -562,7 +562,7 @@ max-width:50em; text-align:left; background-color:#E7E7E7; border-bottom:1px solid #5f5f5f; -height:6%; +height:3em; padding:0.5em 1em; } @@ -744,6 +744,10 @@ padding:4px; margin:0.5em 0; } +#everypage .popup-close { + text-align: right; +} + #game_sidebar { float:right; clear:none; diff --git a/script/handle-mail-replies.rb b/script/handle-mail-replies.rb index f4ffb61f8..73fca33c3 100755 --- a/script/handle-mail-replies.rb +++ b/script/handle-mail-replies.rb @@ -16,17 +16,21 @@ $alaveteli_dir = File.expand_path(File.join(File.dirname(__FILE__), '..')) $:.push(File.join($alaveteli_dir, "commonlib", "rblib")) load "config.rb" $:.push(File.join($alaveteli_dir, "lib")) +$:.push(File.join($alaveteli_dir, "lib", "mail_handler")) require "configuration" MySociety::Config.set_file(File.join($alaveteli_dir, 'config', 'general'), true) MySociety::Config.load_default - -require 'action_mailer' +require 'mail_handler' +if RUBY_VERSION.to_f >= 1.9 + # the default encoding for IO is utf-8, and we use utf-8 internally + Encoding.default_external = Encoding.default_internal = Encoding::UTF_8 +end def main(in_test_mode) Dir.chdir($alaveteli_dir) do raw_message = $stdin.read begin - message = TMail::Mail.parse(raw_message) + message = MailHandler.mail_from_raw_email(raw_message, decode=false) rescue # Error parsing message. Just pass it on, to be on the safe side. forward_on(raw_message) unless in_test_mode @@ -45,16 +49,17 @@ def main(in_test_mode) return 1 end + content_type = MailHandler.get_content_type(message) # If we are still here, there are no permanent failures, # so if the message is a multipart/report then it must be # reporting a temporary failure. In this case we discard it - if message.content_type == "multipart/report" + if content_type == "multipart/report" return 1 end # Another style of temporary failure message - subject = message.header_string("Subject") - if message.content_type == "multipart/mixed" && subject == "Delivery Status Notification (Delay)" + subject = MailHandler.get_header_string("Subject", message) + if content_type == "multipart/mixed" && subject == "Delivery Status Notification (Delay)" return 1 end @@ -70,26 +75,26 @@ def main(in_test_mode) end def permanently_failed_addresses(message) - if message.header_string("Return-Path") == "<>" + if MailHandler.empty_return_path?(message) # Some sort of auto-response # Check for Exim’s X-Failed-Recipients header - failed_recipients = message.header_string("X-Failed-Recipients") + failed_recipients = MailHandler.get_header_string("X-Failed-Recipients", message) if !failed_recipients.nil? # The X-Failed-Recipients header contains the email address that failed # Check for the words "This is a permanent error." in the body, to indicate # a permanent failure - if message.body =~ /This is a permanent error./ + if MailHandler.get_part_body(message) =~ /This is a permanent error./ return failed_recipients.split(/,\s*/) end end # Next, look for multipart/report - if message.content_type == "multipart/report" + if MailHandler.get_content_type(message) == "multipart/report" permanently_failed_recipients = [] message.parts.each do |part| - if part.content_type == "message/delivery-status" - sections = part.body.split(/\r?\n\r?\n/) + if MailHandler.get_content_type(part) == "message/delivery-status" + sections = MailHandler.get_part_body(part).split(/\r?\n\r?\n/) # The first section is a generic header; subsequent sections # represent a particular recipient. Since we sections[1..-1].each do |section| @@ -109,11 +114,11 @@ def permanently_failed_addresses(message) end end - subject = message.header_string("Subject") + subject = MailHandler.get_header_string("Subject", message) # Then look for the style we’ve seen in WebShield bounces # (These do not have a return path of <> in the cases I have seen.) if subject == "Returned Mail: Error During Delivery" - if message.body =~ /^\s*---- Failed Recipients ----\s*((?:<[^>]+>\n)+)/ + if MailHandler.get_part_body(message) =~ /^\s*---- Failed Recipients ----\s*((?:<[^>]+>\n)+)/ return $1.scan(/<([^>]+)>/).flatten end end @@ -124,12 +129,12 @@ end def is_oof?(message) # Check for out-of-office - if message.header_string("X-POST-MessageClass") == "9; Autoresponder" + if MailHandler.get_header_string("X-POST-MessageClass", message) == "9; Autoresponder" return true end - subject = message.header_string("Subject").downcase - if message.header_string("Return-Path") == "<>" + subject = MailHandler.get_header_string("Subject", message).downcase + if MailHandler.empty_return_path?(message) if subject.start_with? "out of office: " return true end @@ -138,7 +143,7 @@ def is_oof?(message) end end - if message.header_string("Auto-Submitted") == "auto-generated" + if MailHandler.get_header_string("Auto-Submitted", message) == "auto-generated" if subject =~ /out of( the)? office/ return true end @@ -167,8 +172,8 @@ def forward_on(raw_message) end def load_rails - require File.join('config', 'boot') - require File.join('config', 'environment') + require File.join($alaveteli_dir, 'config', 'boot') + require File.join($alaveteli_dir, 'config', 'environment') end def record_bounce(email_address, bounce_message) diff --git a/script/request-creation-graph b/script/request-creation-graph index 499e7371e..d49a361b8 100755 --- a/script/request-creation-graph +++ b/script/request-creation-graph @@ -72,7 +72,6 @@ cat >$GPSCRIPT <<END set xdata time set timefmt "%Y-%m-%d" - set xrange ["2007-12-01":] set format x "%d %b %Y" set xtics nomirror set xlabel "status of requests that were created on each calendar day" diff --git a/script/user-use-graph b/script/user-use-graph index 1cf409cb2..205e02416 100755 --- a/script/user-use-graph +++ b/script/user-use-graph @@ -54,7 +54,6 @@ cat >$GPSCRIPT <<END set xdata time set timefmt "%Y-%m-%d" - set xrange ["2007-12-01":] set format x "%d %b %Y" set xtics nomirror diff --git a/spec/controllers/api_controller_spec.rb b/spec/controllers/api_controller_spec.rb index 8d8a39950..1c320f85c 100644 --- a/spec/controllers/api_controller_spec.rb +++ b/spec/controllers/api_controller_spec.rb @@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') def normalise_whitespace(s) - s = s.gsub(/^\s+|\s+$/, "") + s = s.gsub(/\A\s+|\s+\Z/, "") s = s.gsub(/\s+/, " ") return s end @@ -14,23 +14,36 @@ Spec::Matchers.define :be_equal_modulo_whitespace_to do |expected| end describe ApiController, "when using the API" do - it "should check the API key" do - request_data = { + + describe 'checking API keys' do + before do + @number_of_requests = InfoRequest.count + @request_data = { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", } - - number_of_requests = InfoRequest.count + end + + it 'should check that an API key is given as a param' do expect { - post :create_request, :k => "This is not really an API key", :request_json => request_data.to_json + post :create_request, :request_json => @request_data.to_json }.to raise_error ApplicationController::PermissionDenied - - InfoRequest.count.should == number_of_requests + InfoRequest.count.should == @number_of_requests + end + + it "should check the API key" do + expect { + post :create_request, + :k => "This is not really an API key", + :request_json => @request_data.to_json + }.to raise_error ApplicationController::PermissionDenied + InfoRequest.count.should == @number_of_requests + end end - + it "should create a new request from a POST" do number_of_requests = InfoRequest.count( :conditions => [ @@ -38,61 +51,61 @@ describe ApiController, "when using the API" do public_bodies(:geraldine_public_body).id ] ) - + request_data = { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", } - + post :create_request, :k => public_bodies(:geraldine_public_body).api_key, :request_json => request_data.to_json response.should be_success response.content_type.should == "application/json" - + response_body = ActiveSupport::JSON.decode(response.body) response_body["errors"].should be_nil response_body["url"].should =~ /^http/ - + InfoRequest.count(:conditions => [ "public_body_id = ?", public_bodies(:geraldine_public_body).id] ).should == number_of_requests + 1 - + new_request = InfoRequest.find(response_body["id"]) new_request.user_id.should be_nil new_request.external_user_name.should == request_data["external_user_name"] new_request.external_url.should == request_data["external_url"] - + new_request.title.should == request_data["title"] new_request.last_event_forming_initial_request.outgoing_message.body.should == request_data["body"].strip - + new_request.public_body_id.should == public_bodies(:geraldine_public_body).id end - + def _create_request post :create_request, :k => public_bodies(:geraldine_public_body).api_key, :request_json => { "title" => "Tell me about your chickens", "body" => "Dear Sir,\n\nI should like to know about your chickens.\n\nYours in faith,\nBob\n", - + "external_url" => "http://www.example.gov.uk/foi/chickens_23", "external_user_name" => "Bob Smith", }.to_json response.content_type.should == "application/json" return ActiveSupport::JSON.decode(response.body)["id"] end - + it "should add a response to a request" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has no incoming messages IncomingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 0 - + # Now add one sent_at = "2012-05-28T12:35:39+01:00" response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n" @@ -104,13 +117,13 @@ describe ApiController, "when using the API" do "sent_at" => sent_at, "body" => response_body }.to_json - + # And make sure it worked response.should be_success incoming_messages = IncomingMessage.all(:conditions => ["info_request_id = ?", request_id]) incoming_messages.count.should == 1 incoming_message = incoming_messages[0] - + incoming_message.sent_at.should == Time.iso8601(sent_at) incoming_message.get_main_body_text_folded.should be_equal_modulo_whitespace_to(response_body) end @@ -118,10 +131,10 @@ describe ApiController, "when using the API" do it "should add a followup to a request" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has one outgoing message OutgoingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 1 - + # Add another, as a followup sent_at = "2012-05-29T12:35:39+01:00" followup_body = "Pls answer ASAP.\nkthxbye\n" @@ -133,7 +146,7 @@ describe ApiController, "when using the API" do "sent_at" => sent_at, "body" => followup_body }.to_json - + # Make sure it worked response.should be_success followup_messages = OutgoingMessage.all( @@ -141,15 +154,15 @@ describe ApiController, "when using the API" do ) followup_messages.size.should == 1 followup_message = followup_messages[0] - + followup_message.last_sent_at.should == Time.iso8601(sent_at) followup_message.body.should == followup_body.strip end - + it "should not allow internal requests to be updated" do n_incoming_messages = IncomingMessage.count n_outgoing_messages = OutgoingMessage.count - + request_id = info_requests(:naughty_chicken_request).id post :add_correspondence, :k => public_bodies(:geraldine_public_body).api_key, @@ -159,20 +172,20 @@ describe ApiController, "when using the API" do "sent_at" => Time.now.iso8601, "body" => "xxx" }.to_json - + response.status.should == "500 Internal Server Error" ActiveSupport::JSON.decode(response.body)["errors"].should == [ "Request #{request_id} cannot be updated using the API"] - + IncomingMessage.count.should == n_incoming_messages OutgoingMessage.count.should == n_outgoing_messages end - + it "should not allow other people's requests to be updated" do request_id = _create_request n_incoming_messages = IncomingMessage.count n_outgoing_messages = OutgoingMessage.count - + post :add_correspondence, :k => public_bodies(:humpadink_public_body).api_key, :id => request_id, @@ -181,15 +194,15 @@ describe ApiController, "when using the API" do "sent_at" => Time.now.iso8601, "body" => "xxx" }.to_json - + response.status.should == "500 Internal Server Error" ActiveSupport::JSON.decode(response.body)["errors"].should == [ "You do not own request #{request_id}"] - + IncomingMessage.count.should == n_incoming_messages OutgoingMessage.count.should == n_outgoing_messages end - + it "should not allow files to be attached to a followup" do post :add_correspondence, :k => public_bodies(:geraldine_public_body).api_key, @@ -202,21 +215,21 @@ describe ApiController, "when using the API" do :attachments => [ fixture_file_upload("files/tfl.pdf") ] - - + + # Make sure it worked response.status.to_i.should == 500 errors = ActiveSupport::JSON.decode(response.body)["errors"] errors.should == ["You cannot attach files to messages in the 'request' direction"] end - + it "should allow files to be attached to a response" do # First we need an external request request_id = info_requests(:external_request).id - + # Initially it has no incoming messages IncomingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 0 - + # Now add one sent_at = "2012-05-28T12:35:39+01:00" response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n" @@ -231,34 +244,33 @@ describe ApiController, "when using the API" do :attachments => [ fixture_file_upload("files/tfl.pdf") ] - + # And make sure it worked response.should be_success incoming_messages = IncomingMessage.all(:conditions => ["info_request_id = ?", request_id]) incoming_messages.count.should == 1 incoming_message = incoming_messages[0] - + incoming_message.sent_at.should == Time.iso8601(sent_at) incoming_message.get_main_body_text_folded.should be_equal_modulo_whitespace_to(response_body) - + # Get the attachment attachments = incoming_message.get_attachments_for_display attachments.size.should == 1 attachment = attachments[0] - attachment.filename.should == "tfl.pdf" - attachment.body.should == load_file_fixture("tfl.pdf") + attachment.body.should == load_file_fixture("tfl.pdf", as_binary=true) end - + it "should show information about a request" do info_request = info_requests(:naughty_chicken_request) get :show_request, :k => public_bodies(:geraldine_public_body).api_key, :id => info_request.id - + response.should be_success assigns[:request].id.should == info_request.id - + r = ActiveSupport::JSON.decode(response.body) r["title"].should == info_request.title # Let’s not test all the fields here, because it would @@ -266,13 +278,13 @@ describe ApiController, "when using the API" do # assigns them and changing assignment to an equality # check, which does not really test anything at all. end - + it "should show an Atom feed of new request events" do get :body_request_events, :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, :feed_type => "atom" - + response.should be_success response.should render_template("api/request_events.atom") assigns[:events].size.should > 0 @@ -288,7 +300,7 @@ describe ApiController, "when using the API" do :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, :feed_type => "json" - + response.should be_success assigns[:events].size.should > 0 assigns[:events].each do |event| @@ -296,13 +308,13 @@ describe ApiController, "when using the API" do event.outgoing_message.should_not be_nil event.event_type.should satisfy {|x| ['sent', 'followup_sent', 'resent', 'followup_resent'].include?(x)} end - + assigns[:event_data].size.should == assigns[:events].size assigns[:event_data].each do |event_record| event_record[:event_type].should satisfy {|x| ['sent', 'followup_sent', 'resent', 'followup_resent'].include?(x)} end end - + it "should honour the since_event_id parameter" do get :body_request_events, :id => public_bodies(:geraldine_public_body).id, @@ -311,7 +323,7 @@ describe ApiController, "when using the API" do response.should be_success first_event = assigns[:event_data][0] second_event_id = assigns[:event_data][1][:event_id] - + get :body_request_events, :id => public_bodies(:geraldine_public_body).id, :k => public_bodies(:geraldine_public_body).api_key, @@ -320,14 +332,14 @@ describe ApiController, "when using the API" do response.should be_success assigns[:event_data].should == [first_event] end - + it "should honour the since_date parameter for the Atom feed" do get :body_request_events, :id => public_bodies(:humpadink_public_body).id, :k => public_bodies(:humpadink_public_body).api_key, :since_date => "2010-01-01", :feed_type => "atom" - + response.should be_success response.should render_template("api/request_events.atom") assigns[:events].size.should > 0 @@ -335,7 +347,7 @@ describe ApiController, "when using the API" do event.created_at.should >= Date.new(2010, 1, 1) end end - + it "should return a JSON 404 error for non-existent requests" do request_id = 123459876 # Let's hope this doesn't exist! sent_at = "2012-05-28T12:35:39+01:00" @@ -351,7 +363,7 @@ describe ApiController, "when using the API" do response.status.should == "404 Not Found" ActiveSupport::JSON.decode(response.body)["errors"].should == ["Could not find request 123459876"] end - + it "should return a JSON 500 error if we try to add correspondence to a request we don't own" do request_id = info_requests(:naughty_chicken_request).id sent_at = "2012-05-28T12:35:39+01:00" diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 08e68d85e..18341ae6f 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -39,7 +39,14 @@ describe ApplicationController, "when caching fragments" do it "should not fail with long filenames" do long_name = "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah.txt" - path = self.controller.send(:foi_fragment_cache_path, long_name) + params = { :only_path => true, + :file_name => [long_name], + :controller => "request", + :action => "get_attachment_as_html", + :id => "132", + :incoming_message_id => "44", + :part => "2" } + path = self.controller.send(:foi_fragment_cache_path, params) self.controller.send(:foi_fragment_cache_write, path, "whassap") end diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb index 935f8eab6..642ed0e05 100644 --- a/spec/controllers/general_controller_spec.rb +++ b/spec/controllers/general_controller_spec.rb @@ -97,8 +97,57 @@ describe GeneralController, "when showing the frontpage" do response.should be_success end + describe 'when there is more than one locale' do + + describe 'when using the default locale' do + + before do + @default_lang_home_link = /href=".*\/en\// + @other_lang_home_link = /href=".*\/es\// + @old_include_default_locale_in_urls = Configuration::include_default_locale_in_urls + end + + def set_default_locale_in_urls(value) + Configuration.stub!(:include_default_locale_in_urls).and_return(value) + load Rails.root.join("config/initializers/fast_gettext.rb") + end + + describe 'when the config value INCLUDE_DEFAULT_LOCALE_IN_URLS is false' do + + before do + set_default_locale_in_urls(false) + end + + it 'should generate URLs without a locale prepended' do + get :frontpage + response.should_not have_text(@default_lang_home_link) + end + + it 'should render the front page in the default language when no locale param + is present and the session locale is not the default' do + get(:frontpage, {}, {:locale => 'es'}) + response.should_not have_text(@other_lang_home_link) + end + end + + it 'should generate URLs with a locale prepended when the config value + INCLUDE_DEFAULT_LOCALE_IN_URLS is true' do + set_default_locale_in_urls(true) + get :frontpage + response.should have_text(@default_lang_home_link) + end + + after do + set_default_locale_in_urls(@old_include_default_locale_in_urls) + end + + end + end + + describe "when using different locale settings" do home_link_regex = /href=".*\/en\// + it "should generate URLs with a locale prepended when there's more than one locale set" do get :frontpage response.should have_text(home_link_regex) @@ -137,6 +186,7 @@ describe GeneralController, "when showing the frontpage" do FastGettext.default_available_locales = old_fgt_available_locales I18n.available_locales = old_i18n_available_locales end + end end describe GeneralController, "when showing the front page with fixture data" do @@ -144,7 +194,7 @@ describe GeneralController, "when showing the front page with fixture data" do describe 'when constructing the list of recent requests' do before(:each) do - rebuild_xapian_index + get_fixtures_xapian_index end describe 'when there are fewer than five successful requests' do @@ -189,8 +239,8 @@ describe GeneralController, 'when using xapian search' do # rebuild xapian index after fixtures loaded before(:each) do - load_raw_emails_data - rebuild_xapian_index + load_raw_emails_data + get_fixtures_xapian_index end it "should redirect from search query URL to pretty URL" do diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index d12818a1c..29ece18cb 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -6,7 +6,7 @@ describe PublicBodyController, "when showing a body" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should be successful" do @@ -29,14 +29,14 @@ describe PublicBodyController, "when showing a body" do assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( :conditions => ["public_body_id = ?", public_bodies(:geraldine_public_body).id]) end - + it "should assign the requests (2)" do get :show, :url_name => "tgq", :view => 'successful' assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( :conditions => ["described_state = ? and public_body_id = ?", "successful", public_bodies(:geraldine_public_body).id]) end - + it "should assign the requests (3)" do get :show, :url_name => "dfh", :view => 'all' assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( @@ -66,7 +66,7 @@ describe PublicBodyController, "when showing a body" do ActionController::Routing::Routes.filters = old_filters end - + it "should redirect to newest name if you use historic name of public body in URL" do get :show, :url_name => "hdink", :view => 'all' response.should redirect_to(:controller => 'public_body', :action => 'show', :url_name => "dfh") @@ -148,7 +148,7 @@ describe PublicBodyController, "when listing bodies" do get :list, :tag => "other" response.should render_template('list') assigns[:public_bodies].should =~ PublicBody.all(:conditions => "id not in (#{public_bodies(:humpadink_public_body).id}, #{PublicBody.internal_admin_body.id})") - + get :list response.should render_template('list') assigns[:public_bodies].should =~ PublicBody.all(:conditions => "id <> #{PublicBody.internal_admin_body.id}") @@ -194,10 +194,10 @@ end describe PublicBodyController, "when doing type ahead searches" do integrate_views - + before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should return nothing for the empty query string" do @@ -205,7 +205,7 @@ describe PublicBodyController, "when doing type ahead searches" do response.should render_template('public_body/_search_ahead') assigns[:xapian_requests].should be_nil end - + it "should return a body matching the given keyword, but not users with a matching description" do get :search_typeahead, :query => "Geraldine" response.should render_template('public_body/_search_ahead') @@ -230,7 +230,7 @@ describe PublicBodyController, "when doing type ahead searches" do end it "should not return matches for short words" do - get :search_typeahead, :query => "b" + get :search_typeahead, :query => "b" response.should render_template('public_body/_search_ahead') assigns[:xapian_requests].should be_nil end diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 625bf17e7..521ad7b5a 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -5,7 +5,7 @@ describe RequestController, "when listing recent requests" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should be successful" do @@ -767,7 +767,7 @@ describe RequestController, "when showing one request" do assigns[:url_path].should_not == old_path response.location.should have_text(/#{assigns[:url_path]}/) zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", assigns[:url_path])) { |zipfile| - zipfile.count.should == 5 # the message, two hello.txt, the unknown attachment, and its empty message + zipfile.count.should == 4 # the message, two hello.txt plus the unknown attachment } end @@ -859,14 +859,36 @@ describe RequestController, "when changing prominence of a request" do ir.save! receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 2, :skip_cache => 1 + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, + :id => ir.id, + :part => 2, + :skip_cache => 1 response.content_type.should == "text/html" response.should_not have_text(/Second hello/) response.should render_template('request/hidden') - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, :id => ir.id, :part => 3, :skip_cache => 1 + get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, + :id => ir.id, + :part => 3, + :skip_cache => 1 response.content_type.should == "text/html" response.should_not have_text(/First hello/) response.should render_template('request/hidden') + response.code.should == '410' + end + + it 'should not generate an HTML version of an attachment whose prominence is hidden/requester + only even for the requester or an admin but should return a 404' do + ir = info_requests(:fancy_dog_request) + ir.prominence = 'hidden' + ir.save! + receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + session[:user_id] = users(:admin_user).id + lambda do + get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, + :id => ir.id, + :part => 2, + :file_name => ['hello.txt'] + end.should raise_error(ActiveRecord::RecordNotFound) end it 'should not generate an HTML version of an attachment whose prominence is hidden/requester diff --git a/spec/controllers/track_controller_spec.rb b/spec/controllers/track_controller_spec.rb index 7daa23769..c785960b5 100644 --- a/spec/controllers/track_controller_spec.rb +++ b/spec/controllers/track_controller_spec.rb @@ -38,7 +38,7 @@ describe TrackController, "when making a new track on a request" do get :track_request, :url_title => @ir.url_title, :feed => 'track' response.should redirect_to(:controller => 'request', :action => 'show', :url_title => @ir.url_title) end - + it "should 404 for non-existent requests" do session[:user_id] = @user.id lambda { @@ -61,9 +61,9 @@ describe TrackController, "when sending alerts for a track" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end - + it "should send alerts" do # Don't do clever locale-insertion-unto-URL stuff old_filters = ActionController::Routing::Routes.filters @@ -138,7 +138,7 @@ describe TrackController, "when viewing RSS feed for a track" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should get the RSS feed" do @@ -168,7 +168,7 @@ describe TrackController, "when viewing JSON version of a track feed" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should get the feed" do @@ -210,9 +210,9 @@ describe TrackController, "when tracking a public body" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end - + it "should work" do geraldine = public_bodies(:geraldine_public_body) get :track_public_body, :feed => 'feed', :url_name => geraldine.url_name diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 386d1b04b..23006803b 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -8,9 +8,9 @@ describe UserController, "when showing a user" do integrate_views before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end - + it "should be successful" do get :show, :url_name => "bob_smith" response.should be_success @@ -45,7 +45,7 @@ describe UserController, "when showing a user" do get :show, :url_name => "bob_smith" assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ InfoRequest.all( :conditions => "user_id = #{users(:bob_smith_user).id}") - + get :show, :url_name => "bob_smith", :user_query => "money" assigns[:xapian_requests].results.map{|x|x[:model].info_request}.should =~ [ info_requests(:naughty_chicken_request), @@ -218,7 +218,7 @@ describe UserController, "when signing in" do # Get the confirmation URL, and check we’re still Joe get :confirm, :email_token => post_redirect.email_token session[:user_id].should == users(:admin_user).id - + # And the redirect should still work, of course response.should redirect_to(:controller => 'request', :action => 'list', :post_redirect => 1) @@ -232,21 +232,21 @@ describe UserController, "when signing up" do it "should be an error if you type the password differently each time" do post :signup, { :user_signup => { :email => 'new@localhost', :name => 'New Person', - :password => 'sillypassword', :password_confirmation => 'sillypasswordtwo' } + :password => 'sillypassword', :password_confirmation => 'sillypasswordtwo' } } assigns[:user_signup].errors[:password].should == 'Please enter the same password twice' end it "should be an error to sign up with a misformatted email" do post :signup, { :user_signup => { :email => 'malformed-email', :name => 'Mr Malformed', - :password => 'sillypassword', :password_confirmation => 'sillypassword' } + :password => 'sillypassword', :password_confirmation => 'sillypassword' } } assigns[:user_signup].errors[:email].should_not be_nil end it "should send confirmation mail if you fill in the form right" do post :signup, { :user_signup => { :email => 'new@localhost', :name => 'New Person', - :password => 'sillypassword', :password_confirmation => 'sillypassword' } + :password => 'sillypassword', :password_confirmation => 'sillypassword' } } response.should render_template('confirm') @@ -270,13 +270,13 @@ describe UserController, "when signing up" do it "should send special 'already signed up' mail if you fill the form in with existing registered email" do post :signup, { :user_signup => { :email => 'silly@localhost', :name => 'New Person', - :password => 'sillypassword', :password_confirmation => 'sillypassword' } + :password => 'sillypassword', :password_confirmation => 'sillypassword' } } response.should render_template('confirm') deliveries = ActionMailer::Base.deliveries deliveries.size.should == 1 - + # This text may span a line break, depending on the length of the SITE_NAME deliveries[0].body.should match(/when\s+you\s+already\s+have\s+an/) end @@ -377,7 +377,7 @@ describe UserController, "when changing password" do get :signchangepassword response.should render_template('signchangepassword') end - + it "should change the password, if you have right to do so" do session[:user_id] = users(:bob_smith_user).id session[:user_circumstance] = "change_password" @@ -437,8 +437,8 @@ describe UserController, "when changing email address" do it "should be an error if the password is wrong, everything else right" do @user = users(:bob_smith_user) session[:user_id] = @user.id - - post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', + + post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', :password => 'donotknowpassword', :new_email => 'newbob@localhost' }, :submitted_signchangeemail_do => 1 } @@ -455,8 +455,8 @@ describe UserController, "when changing email address" do it "should be an error if old email is wrong, everything else right" do @user = users(:bob_smith_user) session[:user_id] = @user.id - - post :signchangeemail, { :signchangeemail => { :old_email => 'bob@moo', + + post :signchangeemail, { :signchangeemail => { :old_email => 'bob@moo', :password => 'jonespassword', :new_email => 'newbob@localhost' }, :submitted_signchangeemail_do => 1 } @@ -473,8 +473,8 @@ describe UserController, "when changing email address" do it "should work even if the old email had a case difference" do @user = users(:bob_smith_user) session[:user_id] = @user.id - - post :signchangeemail, { :signchangeemail => { :old_email => 'BOB@localhost', + + post :signchangeemail, { :signchangeemail => { :old_email => 'BOB@localhost', :password => 'jonespassword', :new_email => 'newbob@localhost' }, :submitted_signchangeemail_do => 1 } @@ -485,8 +485,8 @@ describe UserController, "when changing email address" do it "should send confirmation email if you get all the details right" do @user = users(:bob_smith_user) session[:user_id] = @user.id - - post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', + + post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', :password => 'jonespassword', :new_email => 'newbob@localhost' }, :submitted_signchangeemail_do => 1 } @@ -521,16 +521,16 @@ describe UserController, "when changing email address" do post_redirect = PostRedirect.find_by_email_token(mail_token) post_redirect.circumstance.should == 'change_email' post_redirect.user.should == users(:bob_smith_user) - post_redirect.post_params.should == {"submitted_signchangeemail_do"=>"1", - "action"=>"signchangeemail", + post_redirect.post_params.should == {"submitted_signchangeemail_do"=>"1", + "action"=>"signchangeemail", "signchangeemail"=>{ - "old_email"=>"bob@localhost", - "new_email"=>"newbob@localhost"}, + "old_email"=>"bob@localhost", + "new_email"=>"newbob@localhost"}, "controller"=>"user"} post :signchangeemail, post_redirect.post_params response.should redirect_to(:controller => 'user', :action => 'show', :url_name => 'bob_smith') - flash[:notice].should match(/You have now changed your email address/) + flash[:notice].should match(/You have now changed your email address/) @user.reload @user.email.should == 'newbob@localhost' @user.email_confirmed.should == true @@ -539,8 +539,8 @@ describe UserController, "when changing email address" do it "should send special 'already signed up' mail if you try to change your email to one already used" do @user = users(:bob_smith_user) session[:user_id] = @user.id - - post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', + + post :signchangeemail, { :signchangeemail => { :old_email => 'bob@localhost', :password => 'jonespassword', :new_email => 'silly@localhost' }, :submitted_signchangeemail_do => 1 } @@ -572,9 +572,9 @@ describe UserController, "when using profile photos" do @uploadedfile_2 = File.open(file_fixture_name("parrot.jpg")) @uploadedfile_2.stub!(:original_filename).and_return('parrot.jpg') end - + it "should not let you change profile photo if you're not logged in as the user" do - post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } + post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } end it "should return a 404 not a 500 when a profile photo has not been set" do @@ -588,10 +588,10 @@ describe UserController, "when using profile photos" do @user.profile_photo.should be_nil session[:user_id] = @user.id - post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } + post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } response.should redirect_to(:controller => 'user', :action => 'show', :url_name => "bob_smith") - flash[:notice].should match(/Thank you for updating your profile photo/) + flash[:notice].should match(/Thank you for updating your profile photo/) @user.reload @user.profile_photo.should_not be_nil @@ -601,13 +601,13 @@ describe UserController, "when using profile photos" do @user.profile_photo.should be_nil session[:user_id] = @user.id - post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } + post :set_profile_photo, { :id => @user.id, :file => @uploadedfile, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } response.should redirect_to(:controller => 'user', :action => 'show', :url_name => "bob_smith") - flash[:notice].should match(/Thank you for updating your profile photo/) + flash[:notice].should match(/Thank you for updating your profile photo/) - post :set_profile_photo, { :id => @user.id, :file => @uploadedfile_2, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } + post :set_profile_photo, { :id => @user.id, :file => @uploadedfile_2, :submitted_draft_profile_photo => 1, :automatically_crop => 1 } response.should redirect_to(:controller => 'user', :action => 'show', :url_name => "bob_smith") - flash[:notice].should match(/Thank you for updating your profile photo/) + flash[:notice].should match(/Thank you for updating your profile photo/) @user.reload @user.profile_photo.should_not be_nil @@ -617,7 +617,7 @@ describe UserController, "when using profile photos" do end describe UserController, "when showing JSON version for API" do - + it "should be successful" do get :show, :url_name => "bob_smith", :format => "json" @@ -634,7 +634,7 @@ describe UserController, "when viewing the wall" do integrate_views before(:each) do - rebuild_xapian_index + get_fixtures_xapian_index end it "should show users stuff on their wall, most recent first" do diff --git a/spec/fixtures/files/dos-linebreaks.email b/spec/fixtures/files/dos-linebreaks.email new file mode 100644 index 000000000..1f5f1473f --- /dev/null +++ b/spec/fixtures/files/dos-linebreaks.email @@ -0,0 +1,31 @@ +From email@example.com Wed Mar 12 14:58:26 2008 +Return-path: email@example.com> +Envelope-to: request-xxx-xxxxxx@whatdotheyknow.com +Delivery-date: Wed, 12 Mar 2008 14:58:26 +0000 +Received: from example.com ([0.0.0.0]:1368 helo=example.com) + by tea.ukcod.org.uk with esmtp (Exim 4.50) + id 1JZSPS-0002yK-Rq + for request-60-3548031c@whatdotheyknow.com; Wed, 12 Mar 2008 14:58:26 +0000 +X-MimeOLE: Produced By Microsoft Exchange V0.0.0.0 +Content-class: urn:content-classes:message +MIME-Version: 1.0 +Content-Type: text/plain; + charset="us-ascii" +Content-Transfer-Encoding: quoted-printable +Disposition-Notification-To: "A Person" email@example.com> +Subject: RE: Freedom of Information request - Plans for the East Oxford Community Centre +Date: Wed, 12 Mar 2008 14:59:04 -0000 +Message-ID: <3D8BEC617D49EF45A9E6D103A83FD30331BF84@local> +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +Thread-Topic: Freedom of Information request +Thread-Index: AciDziuIcYirFQ7GT36VyP2ABE14qgAg1c0w +From: "A Person" email@example.com> +To: FOI Person <EMAIL_TO> +X-OriginalArrivalTime: 12 Mar 2008 14:59:04.0368 (UTC) FILETIME=[9D245300:01C88451] +X-SEF-7853D99-ADF1-478E-8894-213D316B8FFA: 1 +X-SEF-Processed: 6_0_1_111__2008_03_12_14_59_05 + +Thank you for your Freedom of Information request. I have forwarded it=0D=0A= +to the relevant department for their reply.=0D=0A=0D=0A + diff --git a/spec/fixtures/files/humberside-police-odd-mime-type.email b/spec/fixtures/files/humberside-police-odd-mime-type.email index 5514b29da..ae4ceeffe 100644 --- a/spec/fixtures/files/humberside-police-odd-mime-type.email +++ b/spec/fixtures/files/humberside-police-odd-mime-type.email @@ -3,19 +3,20 @@ Return-path: <> Envelope-to: request-5335-xxxxxxxx@whatdotheyknow.com Delivery-date: Thu, 01 Jan 2009 15:56:20 +0000 Received: from earth.karoo.kcom.com ([212.50.160.55]:62894) - by sandwich.ukcod.org.uk with esmtp (Exim 4.63) - id 1LIPuG-0004AJ-B3 - for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:20 +0000 + by sandwich.ukcod.org.uk with esmtp (Exim 4.63) + id 1LIPuG-0004AJ-B3 + for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:20 +0000 Received: from unknown (HELO smtp-in.karoo.kcom.com) ([10.102.8.11]) by earth.karoo.kcom.com with ESMTP; 01 Jan 2009 15:44:42 +0000 Received: from exim by smtp-in.karoo.kcom.comwith local (Exim 4.30) - id 1LIPu0-0004fg-G6 server-id smtp-in4 - for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:04 +0000 + id 1LIPu0-0004fg-G6 server-id smtp-in4 + for request-5335-xxxxxxxx@whatdotheyknow.com; Thu, 01 Jan 2009 15:56:04 +0000 X-Failed-Recipients: clerk@humberside-pa.karoo.co.uk Reply-To: Postmaster <postmaster@karoo.kcom.com> Auto-Submitted: auto-generated From: Mail Delivery System <Mailer-Daemon@karoo.co.uk> To: request-5335-xxxxxxxx@whatdotheyknow.com +Cc: request-5335-xxxxxxxx@whatdotheyknow.com Subject: Mail delivery failed : returning message to sender X-Mailer: Karoo Mailcore [version 2.0-IB] MIME-Version: 1.0 @@ -52,19 +53,19 @@ Content-Transfer-Encoding: 8bit Return-path: <request-5335-xxxxxxxx@whatdotheyknow.com> Received: from [212.50.160.60] (helo=venus.karoo.kcom.com) - by smtp-in.karoo.kcom.comwith esmtp (Exim 4.30) - id 1LIPu0-0004fc-FM server-id smtp-in4 - for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:04 +0000 + by smtp-in.karoo.kcom.comwith esmtp (Exim 4.30) + id 1LIPu0-0004fc-FM server-id smtp-in4 + for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:04 +0000 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnECAF9nXElSb+bUmWdsb2JhbACMZQGHFQEBAQEBCAsKBxG2eIVy -X-IronPort-AV: E=Sophos;i="4.36,313,1228089600"; +X-IronPort-AV: E=Sophos;i="4.36,313,1228089600"; d="scan'208";a="465483300" Received: from sandwich.ukcod.org.uk ([82.111.230.212]) by venus.karoo.kcom.com with ESMTP; 01 Jan 2009 15:46:44 +0000 Received: from foi by sandwich.ukcod.org.uk with local (Exim 4.63) - (envelope-from <request-5335-xxxxxxxx@whatdotheyknow.com>) - id 1LIPtz-0004AG-OC - for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:03 +0000 + (envelope-from <request-5335-xxxxxxxx@whatdotheyknow.com>) + id 1LIPtz-0004AG-OC + for clerk@humberside-pa.karoo.co.uk; Thu, 01 Jan 2009 15:56:03 +0000 From: John Jarman <request-5335-xxxxxxxx@whatdotheyknow.com> To: FOI requests at Humberside Police Authority <clerk@humberside-pa.karoo.co.uk> Subject: Freedom of Information request - Police Injury Award Pensions diff --git a/spec/fixtures/files/incoming-request-attachment-headers.email b/spec/fixtures/files/incoming-request-attachment-headers.email new file mode 100644 index 000000000..80e71556d --- /dev/null +++ b/spec/fixtures/files/incoming-request-attachment-headers.email @@ -0,0 +1,50 @@ +From foi@example.com Mon Oct 06 13:45:38 2008 +Return-path: <foi@example.com> +Envelope-to: foi@sandwich.ukcod.org.uk +Delivery-date: Mon, 06 Oct 2008 13:45:38 +0100 +Message-Id: <s8ea1156.098@example.com> +X-Mailer: Novell GroupWise Internet Agent 6.5.4 +Date: Mon, 06 Oct 2008 13:23:00 +0100 +From: "Steve Knight" <foi@example.com> +To: <request-xxxx-xxxxx@whatdotheyknow.com> +Subject: FOI request +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="=__PartFDD45234.0__=" +X-Proofpoint-Virus-Version: vendor=nai engine=5.2.00 definitions=5398 signatures=473327 +X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 classifier= adjust=0 reason=limit engine=3.1.0-0805090000 definitions=main-0810060054 + +This is a MIME message. If you are reading this text, you may want to +consider changing to a mail reader or gateway that understands how to +properly handle MIME multipart messages. +--=__PartFDD45234.0__= +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Dear Mr Requester, + +Here is some information. + +--=__PartFDD45234.0__= +Content-Type: message/rfc822 + +Date: Fri, 23 May 2008 17:02:11 +0100 +From: "David Bishop" <foi2@example.com> +To: "foi" <foi3@example.com> +Subject: Foi request +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Extra info. + +--=__PartFDD45234.0__= +Content-Type: image/jpeg; name="info.jpg" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="info.jpg" + +xxxx + +--=__PartFDD45234.0__=-- + diff --git a/spec/fixtures/files/incoming-request-attachment-unknown-extension.email b/spec/fixtures/files/incoming-request-attachment-unknown-extension.email index b3485ec2d..aecd9a52c 100644 --- a/spec/fixtures/files/incoming-request-attachment-unknown-extension.email +++ b/spec/fixtures/files/incoming-request-attachment-unknown-extension.email @@ -4,17 +4,16 @@ Subject: Same attachment twice Content-Type: multipart/mixed; boundary="Q68bSM7Ycu6FN28Q" Content-Disposition: inline - --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=utf-8 Content-Disposition: inline - --Q68bSM7Ycu6FN28Q Content-Type: application/x-nonsense Content-Disposition: attachment; filename="hello.qwglhm" This is an unusual sort of file. ---Q68bSM7Ycu6FN28Q +--Q68bSM7Ycu6FN28Q-- + diff --git a/spec/fixtures/files/many-attachments-date-header.email b/spec/fixtures/files/many-attachments-date-header.email new file mode 100644 index 000000000..a241e2456 --- /dev/null +++ b/spec/fixtures/files/many-attachments-date-header.email @@ -0,0 +1,451 @@ +From email@example.com Wed Apr 14 11:23:08 2010 +Return-path: <email@example.com> +Envelope-to: email@example.com +Delivery-date: Wed, 14 Apr 2010 11:23:08 +0100 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from example.com ([0.0.0.0]) by example.com ([0.0.0.0]) with ESMTP (TREND IMSS SMTP Service 7.0) id 1ec0f7ac0002a77f ; Wed, 14 Apr 2010 11:22:52 +0100 +Received: from GWGATE-MTA by example.com + with Novell_GroupWise; Wed, 14 Apr 2010 11:22:53 +0100 +Message-Id: <email@example.com> +X-Mailer: Novell GroupWise Internet Agent 8.0.1 +Date: Wed, 14 Apr 2010 11:22:47 +0100 +From: "A Person" <email@example.com> +To: <email@example.com> +Cc: "FOI FOI" <email@example.com>, + "A Person" <email@example.com> +Subject: Fwd: Re: Freedom of Information request +References: <email@example.com> + <email@example.com> +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="=__Part163C9567.0__=" + +This is a MIME message. If you are reading this text, you may want to +consider changing to a mail reader or gateway that understands how to +properly handle MIME multipart messages. + +--=__Part163C9567.0__= +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +Some information + + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Date: Wed, 10 Mar 2010 14:17:52 +0000 +From: "A Person" <email@example.com> +To: "A Person" <email@example.com> +Subject: Re: xxx +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline + +2 + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Tue, 24 Nov 2009 10:45:58 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from example.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 00660acd00000f42 ; Tue, 24 Nov 2009 10:45:55 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob115.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Tue, 24 Nov 2009 10:45:56 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Tue, 24 Nov 2009 + 10:45:53 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +Date: Tue, 24 Nov 2009 10:45:52 +0000 +Subject: example +Thread-Topic: example +Thread-Index: AcpnbI2i+XAmfHFVTFy0eGDpVJhXoQFhVeZw +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/mixed; + boundary="_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17028.005 +X-TM-AS-Result: No--19.329-5.0-31-1 +X-imss-scan-details: No--19.329-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: multipart/related; + boundary="_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_"; + type="multipart/alternative" + +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + + +3 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: text/html; charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + +4 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- + +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Tue, 17 Nov 2009 09:58:46 GMT"; + modification-date="Tue, 17 Nov 2009 09:58:46 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + +5 +--_005_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_ +Content-Type: application/vnd.ms-excel; + name="particpant list.xls" +Content-Description: particpant list.xls +Content-Disposition: attachment; + filename="particpant list.xls"; size=21504; + creation-date="Mon, 02 Nov 2009 09:42:37 GMT"; + modification-date="Tue, 24 Nov 2009 10:45:52 GMT" +Content-Transfer-Encoding: base64 + +6 + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48FD3549evs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Thu, 03 Dec 2009 09:29:07 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog116.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 0ac1bf1b0001116e ; Thu, 3 Dec 2009 09:29:04 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob116.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Thu, 03 Dec 2009 09:29:06 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Thu, 3 Dec 2009 09:29:03 + +0000 +From: A Person <email@example.com> +To: 'A Person' <email@example.com> +Date: Thu, 3 Dec 2009 09:29:03 +0000 +Subject: RE: example +Thread-Topic: example +Thread-Index: AcpuoEyRvzM8fXw+THuj/617pjnvCgFWqZdQ +Message-ID: <email@example.com> +References: <email@example.com> + <email@example.com> +In-Reply-To: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17046.004 +X-TM-AS-Result: No--16.791-5.0-31-1 +X-imss-scan-details: No--16.791-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +7 +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Wed, 25 Nov 2009 22:26:23 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog105.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 034354c900007016 ; Wed, 25 Nov 2009 22:26:19 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob105.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Wed, 25 Nov 2009 22:26:21 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Wed, 25 Nov 2009 + 22:26:15 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +CC: A Person <email@example.com> +Date: Wed, 25 Nov 2009 22:26:12 +0000 +Subject: As promised - Masterclass info (example) +Thread-Topic: As promised - Masterclass info (example) +Thread-Index: AcpuHcJ4yrR8PBHZTVCU/RLGzwqsDAAACGwQ +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/mixed; + boundary="_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17032.000 +X-TM-AS-Result: No--26.167-5.0-31-1 +X-imss-scan-details: No--26.167-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: multipart/related; + boundary="_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_"; + type="multipart/alternative" + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 + +8 +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: base64 + +9 +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Wed, 25 Nov 2009 22:26:14 GMT"; + modification-date="Wed, 25 Nov 2009 22:26:14 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + + +10 + +--_006_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: application/msword; + name= "Participant List.doc" +Content-Description: Participant List.doc +Content-Disposition: attachment; + filename="Participant List.doc"; size=112640; + creation-date="Wed, 25 Nov 2009 22:17:24 GMT"; + modification-date="Wed, 25 Nov 2009 11:43:48 GMT" +Content-Transfer-Encoding: base64 + +11 +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_ +Content-Type: application/msword; name="Information & Booking Form.doc" +Content-Description: Information & Booking Form.doc +Content-Disposition: attachment; filename="Information & Booking Form.doc"; size=84480; + creation-date="Wed, 25 Nov 2009 22:17:40 GMT"; + modification-date="Wed, 04 Nov 2009 14:42:54 GMT" +Content-Transfer-Encoding: base64 + +12 + +--_007_B3BDF1D06801114FA040D0F1BEE7CF9C48DC6D82evs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Fri, 04 Dec 2009 10:00:05 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog109.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 100473260001a476 ; Fri, 4 Dec 2009 10:00:01 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob109.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Fri, 04 Dec 2009 10:00:04 UTC +Received: from example.com ([::1]) by + example.com ([::1]) with mapi; Fri, 4 Dec 2009 10:00:01 + +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +Date: Fri, 4 Dec 2009 10:00:01 +0000 +Subject: Re: As promised - info (example) +Thread-Topic: As promised - info (example) +Thread-Index: AcpzhLeBjBId8eZATYudOfBgN6CPXQBQ9Pok +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: base64 +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17048.005 +X-TM-AS-Result: No--24.171-5.0-31-1 +X-imss-scan-details: No--24.171-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +13 +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Sun, 21 Mar 2010 21:53:38 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog117.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 1e3611c1000d37df ; Sun, 21 Mar 2010 21:53:32 +0000 +Received: from source ([0.0.0.0]) (using TLSv1) by eu1sys200aob117.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Sun, 21 Mar 2010 21:53:37 UTC +Received: from example.com ([::1]) by exchhub01 + ([0.0.0.0]) with mapi; Sun, 21 Mar 2010 21:53:34 +0000 +From: A Person <email@example.com> +To: email@example.com <email@example.com> +CC: A Person <email@example.com> +Date: Sun, 21 Mar 2010 21:53:32 +0000 +Subject: Thank you from example +Thread-Topic: Thank you from example +Thread-Index: AcrJQPL4xb9zjXMHRJGTjAxo3X/kfA== +Message-ID: <email@example.com> +Accept-Language: en-US, en-GB +Content-Language: en-US +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +acceptlanguage: en-US, en-GB +Content-Type: multipart/related; + boundary="_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_"; + type="multipart/alternative" +MIME-Version: 1.0 +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17266.002 +X-TM-AS-Result: No--26.373-5.0-31-1 +X-imss-scan-details: No--26.373-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + + +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: multipart/alternative; + boundary="_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_" + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +14 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: text/html; charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +15 + +--_000_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_-- + +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_ +Content-Type: image/gif; name="image001.gif" +Content-Description: image001.gif +Content-Disposition: inline; filename="image001.gif"; size=5445; + creation-date="Sun, 21 Mar 2010 21:53:33 GMT"; + modification-date="Sun, 21 Mar 2010 21:53:33 GMT" +Content-ID: <email@example.com> +Content-Transfer-Encoding: base64 + +16 +--_004_B3BDF1D06801114FA040D0F1BEE7CF9C5E14635Bevs02ukcommonpu_-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Tue, 23 Feb 2010 15:33:48 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog112.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id 96f54043000f2e72 ; Tue, 23 Feb 2010 15:33:48 +0000 +Received: from source ([0.0.0.0]) by eu1sys200aob112.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Tue, 23 Feb 2010 15:33:47 UTC +Received: from gla-002561-lap ([0.0.0.0]) by example.com with Microsoft SMTPSVC(0.0.0.0); + Tue, 23 Feb 2010 15:33:46 +0000 +Reply-To: email@example.com +From: email@example.com +To: email@example.com +Subject: example - Meeting - Tuesday 2nd March +Date: 23 February 2010 15:33 +X-Mailer: Internet Professional v1.15 +Return-Path: email@example.com +Message-ID: <email@example.com> +X-OriginalArrivalTime: 23 Feb 2010 15:33:46.0648 (UTC) FILETIME=[96CEC980:01CAB49D] +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17212.000 +X-TM-AS-Result: No--16.146-5.0-31-1 +X-imss-scan-details: No--16.146-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +17 + +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Return-path: <email@example.com> +Received: from example.com ([0.0.0.0]) + by example.com with ESMTP; Mon, 08 Mar 2010 09:21:42 +0000 +X-TM-IMSS-Message-ID:<email@example.com> +Received: from eu1sys200aog117.obsmtp.com ([0.0.0.0]) by example.com ([0.0.0.0]) with SMTP (TREND IMSS SMTP Service 7.0) id d8931aff001580d6 ; Mon, 8 Mar 2010 09:21:40 +0000 +Received: from source ([0.0.0.0]) by eu1sys200aob117.postini.com ([0.0.0.0]) with SMTP + ID email@example.com Mon, 08 Mar 2010 09:21:39 UTC +Received: from gla-002561-lap ([0.0.0.0]) by example.com with Microsoft SMTPSVC(0.0.0.0); + Mon, 8 Mar 2010 09:21:36 +0000 +Reply-To: email@example.com +From: email@example.com +To: email@example.com +Subject: example - Help needed +Date: 08 March 2010 09:21 +X-Mailer: Internet Professional v1.15 +MIME-Version: 1.0 +Content-Type: multipart/mixed;boundary="_NextPart_00009D35-00000F3C-00271781-26DF" +Return-Path: email@example.com +Message-ID: <email@example.com> +X-OriginalArrivalTime: 08 Mar 2010 09:21:36.0283 (UTC) FILETIME=[C03E3EB0:01CABEA0] +X-TM-AS-Product-Ver: IMSS-0.0.0.0-0.0.0.0-17236.006 +X-TM-AS-Result: No--32.111-5.0-31-1 +X-imss-scan-details: No--32.111-5.0-31-1 +X-TM-AS-User-Approved-Sender: No +X-TM-AS-User-Blocked-Sender: No + +This message is in MIME format. Since your mail reader does not +understand this format, some or all of this message may not be legible. +--_NextPart_00009D35-00000F3C-00271781-26DF +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +18 + +--_NextPart_00009D35-00000F3C-00271781-26DF +Content-Type: application/octet-stream;name="Information Pack.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment;filename="Information Pack.pdf";size=106688 + +19 +--_NextPart_00009D35-00000F3C-00271781-26DF-- +--=__Part163C9567.0__= +Content-Type: message/rfc822 + +Date: Wed, 02 Dec 2009 19:21:27 +0000 +From: "A Person" <email@example.com> +To: "A Person" <email@example.com> +Subject: Re: As promised - info (example) +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Content-Disposition: inline + +20 +--=__Part163C9567.0__=-- + diff --git a/spec/fixtures/files/rfc822-attachment.email b/spec/fixtures/files/rfc822-attachment.email new file mode 100644 index 000000000..ae58a06af --- /dev/null +++ b/spec/fixtures/files/rfc822-attachment.email @@ -0,0 +1,147 @@ +From foi.officer@example.com Fri Mar 14 08:39:57 2008 +Return-path: <foi.officer@example.com> +Envelope-to: request-bounce-xx-xxxxx@whatdotheyknow.com +Delivery-date: Fri, 14 Mar 2008 08:39:57 +0000 +Received: from service27.mimecast.com ([213.235.63.79]:55305) + by tea.ukcod.org.uk with smtp (Exim 4.50) + id 1Ja5SH-0005iP-Jm + for xxx@whatdotheyknow.com; Fri, 14 Mar 2008 08:39:57 +0000 +Received: from mailscan.ad.example.com (mailgate.example.com [194.70.143.2]) + by service27.mimecast.com; + Fri, 14 Mar 2008 08:38:47 +0000 +Received: from exch2serv.ad.example.com ([201.234.62.4]) by mailscan.ad.example.com with InterScan Message Security Suite; Fri, 14 Mar 2008 08:38:47 -0000 +X-MIMEOLE: Produced By Microsoft Exchange V6.0.6603.0 +content-class: urn:content-classes:message +MIME-Version: 1.0 +Subject: +Date: Fri, 14 Mar 2008 08:38:46 -0000 +Message-ID: <0F3951EA9DCFB246827E1F6513F6C79D096DDADB@exch2serv.ad.example.com> +X-MS-Has-Attach: yes +X-MS-TNEF-Correlator: +Thread-Index: AciFrtIeS9pyMOhuQdyxkm5305zs9g== +From: "An FOI Officer" <foi.officer@example.com> +To: "On" <request-bounce-xx-xxxxx@whatdotheyknow.com> +X-MC-Unique: 108031408384702301 +Content-Type: multipart/mixed; + boundary="----_=_NextPart_001_01C885AE.D1BF23AC" + +This is a multi-part message in MIME format. + +------_=_NextPart_001_01C885AE.D1BF23AC +Content-Type: multipart/alternative; + boundary="MCBoundary=_108031408384800401" + +--MCBoundary=_108031408384800401 +Content-Type: text/plain; charset=WINDOWS-1252 +Content-Transfer-Encoding: quoted-printable + + + <<Freedom of Information request >>=20 + + +e-mail: foi.officer@example.com=20 + + + + +***************************************************************************= +******** +The information in this Email and any attachments is personal to the +sender and the views of the author may not necessarily reflect those +of Borough Council. The information is strictly confidential +and is intended only for the named person or organisation to whom it is +addressed as it may contain privileged and confidential information. If +you are not the intended recipient do not copy, distribute or use this +Email, and please notify the sender. Please note that we cannot +guarantee that this message or any attachment is virus free or has not +been intercepted and amended. +***************************************************************************= +******** + +Disclaimer=20 +---------------------------------------------------------------------------= +---------------- +This email message has been scanned for viruses by Mimecast. +Mimecast delivers a complete managed email solution from a single web based= + platform. +For more information please visit www.mimecast.com +---------------------------------------------------------------------------= +---------------- +--MCBoundary=_108031408384800401 +Content-Type: text/html; charset=WINDOWS-1252 +Content-Transfer-Encoding: quoted-printable + +<HTML><BODY> =20 + <BR> + <<Freedom of Information request >> <BR> +<BR> +e-mail: <a href=3D"mailto:foi.officer@example.com">foi.officer@example.com</a> <BR> +<BR> +<BR> +<BR> +<BR> +***************************************************************************= +********<BR> +The information in this Email and any attachments is personal to the<B= +R> +sender and the views of the author may not necessarily reflect those<BR= +> +of Borough Council. The information is strictly confidential<B= +R> +and is intended only for the named person or organisation to whom it is<BR> +addressed as it may contain privileged and confidential information. If<B= +R> +you are not the intended recipient do not copy, distribute or use this= +<BR> +Email, and please notify the sender. Please note that we cannot<B= +R> +guarantee that this message or any attachment is virus free or has not<BR> +been intercepted and amended.<BR> +***************************************************************************= +********<BR> + + <BR> + <BR> + <span style=3D"font-family:Arial; Font-size:10.0pt"> + Disclaimer <p> + <hr width=3D"100%"> + This email message has been scanned for viruses by Mimecast.<BR> + Mimecast delivers a complete managed email solution from a single we= +b based platform.<BR> + For more information please visit <a href=3D"http://www.mimecast.com= +">http://www.mimecast.com</a> + <hr width=3D"100%"> + </span> + </BODY></HTML> + + +--MCBoundary=_108031408384800401-- +------_=_NextPart_001_01C885AE.D1BF23AC +Content-Type: message/rfc822 +Content-Transfer-Encoding: 7bit + +X-MIMEOLE: Produced By Microsoft Exchange V6.0.6603.0 +content-class: urn:content-classes:message +MIME-Version: 1.0 +Subject: Freedom of Information request +Date: Thu, 13 Mar 2008 16:57:33 -0000 +Message-ID: <0F3951EA9DCFB246827E1F6513F6C79D098AC8C5@exch2serv.ad.example.com> +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +Thread-Topic: Freedom of Information request +Thread-Index: AciE9w0L7QnQlahDQS+Zjrz40mr8KAAD5KuQAADg+1AABjC9wAAAXtJgAAEHJvAAAHTxwA== +X-Priority: 1 +Priority: Urgent +Importance: high +From: "An FOI Officer" <foi.officer@example.com> +To: <request-bounce-xx-xxxxx@whatdotheyno.com> +Content-Type: text/plain; + charset="utf-8" +Content-Transfer-Encoding: base64 + +c29tZSBleGFtcGxlIHRleHQ= + +------_=_NextPart_001_01C885AE.D1BF23AC-- + + + diff --git a/spec/helpers/link_to_helper_spec.rb b/spec/helpers/link_to_helper_spec.rb index ef89e8bf9..030fd612d 100644 --- a/spec/helpers/link_to_helper_spec.rb +++ b/spec/helpers/link_to_helper_spec.rb @@ -73,4 +73,16 @@ describe LinkToHelper do end end end + + describe 'simple_date' do + it 'should respect time zones' do + Time.use_zone('Australia/Sydney') do + simple_date(Time.utc(2012, 11, 07, 21, 30, 26)).should == 'November 08, 2012' + end + end + + it 'should handle Date objects' do + simple_date(Date.new(2012, 11, 21)).should == 'November 21, 2012' + end + end end diff --git a/spec/integration/create_request_spec.rb b/spec/integration/create_request_spec.rb index 56757c7e0..4efbf94ee 100644 --- a/spec/integration/create_request_spec.rb +++ b/spec/integration/create_request_spec.rb @@ -1,23 +1,30 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "When creating requests" do - it "should associate the request with the requestor, even if it is approved by an admin" do - # This is a test for https://github.com/mysociety/alaveteli/issues/446 - params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, - :title => "Why is your quango called Geraldine?", :tag_string => "" }, - :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, - :submitted_new_request => 1, :preview => 0 - } + def create_request_unregistered + params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, + :title => "Why is your quango called Geraldine?", + :tag_string => "" }, + :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, + :submitted_new_request => 1, + :preview => 0 + } - # Initially we are not logged in. Try to create a new request. - post "/new", params - # We expect to be redirected to the login page - post_redirect = PostRedirect.get_last_post_redirect - response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) - follow_redirect! - response.should render_template("user/sign") + # Initially we are not logged in. Try to create a new request. + post "/new", params + # We expect to be redirected to the login page + post_redirect = PostRedirect.get_last_post_redirect + response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) + follow_redirect! + response.should render_template("user/sign") + response.body.should match(/To send your FOI request, please sign in or make a new account./) + end + it "should associate the request with the requestor, even if it is approved by an admin" do + # This is a test for https://github.com/mysociety/alaveteli/issues/446 + create_request_unregistered + post_redirect = PostRedirect.get_last_post_redirect # Now log in as an unconfirmed user. post "/profile/sign_in", :user_signin => {:email => users(:unconfirmed_user).email, :password => "jonespassword"}, :token => post_redirect.token # This will trigger a confirmation mail. Get the PostRedirect for later. diff --git a/spec/integration/search_request_spec.rb b/spec/integration/search_request_spec.rb index 17a7b4aaa..c564032a6 100644 --- a/spec/integration/search_request_spec.rb +++ b/spec/integration/search_request_spec.rb @@ -4,7 +4,7 @@ describe "When searching" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should not strip quotes from quoted query" do diff --git a/spec/lib/i18n_interpolation.rb b/spec/lib/i18n_interpolation.rb index 8c86413ad..6b745059c 100644 --- a/spec/lib/i18n_interpolation.rb +++ b/spec/lib/i18n_interpolation.rb @@ -1,6 +1,3 @@ -# This is a test of the set_content_type monkey patch in -# lib/tmail_extensions.rb - require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "when using i18n" do diff --git a/spec/lib/mail_handler/mail_handler_spec.rb b/spec/lib/mail_handler/mail_handler_spec.rb new file mode 100644 index 000000000..48c32e2bc --- /dev/null +++ b/spec/lib/mail_handler/mail_handler_spec.rb @@ -0,0 +1,387 @@ +# coding: utf-8 +require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper') + +def create_message_from(from_field) + mail_data = load_file_fixture('incoming-request-plain.email') + mail_data.gsub!('EMAIL_FROM', from_field) + mail = MailHandler.mail_from_raw_email(mail_data) +end + +describe 'when creating a mail object from raw data' do + + it 'should correctly parse a multipart email with a linebreak in the boundary' do + mail = get_fixture_mail('space-boundary.email') + mail.parts.size.should == 2 + mail.multipart?.should == true + end + + it 'should parse multiple to addresses with unqoted display names' do + mail = get_fixture_mail('multiple-unquoted-display-names.email') + mail.to.should == ["request-66666-caa77777@whatdotheyknow.com", "foi@example.com"] + end + + it 'should convert an iso8859 email to utf8' do + mail = get_fixture_mail('iso8859_2_raw_email.email') + mail.subject.should have_text(/gjatë/u) + MailHandler.get_part_body(mail).is_utf8?.should == true + end + +end + +describe 'when asked for the from name' do + + it 'should return nil if there is a blank "From" field' do + mail = create_message_from('') + MailHandler.get_from_name(mail).should == nil + end + + it 'should correctly return an encoded name from the from field' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + MailHandler.get_from_name(mail).should == 'Coordenação de Relacionamento, Pesquisa e Informação/CEDI' + end + + it 'should get a name from a "From" field with a name and address' do + mail = get_fixture_mail('incoming-request-oft-attachments.email') + MailHandler.get_from_name(mail).should == 'Public Authority' + end + + it 'should return nil from a "From" field that is just a name'do + mail = get_fixture_mail('track-response-webshield-bounce.email') + MailHandler.get_from_name(mail).should == nil + end + +end + +describe 'when asked for the from address' do + + it 'should return nil if there is a blank "From" field' do + mail = create_message_from('') + MailHandler.get_from_address(mail).should == nil + end + + it 'should correctly return an address from a mail that has an encoded name in the from field' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + MailHandler.get_from_address(mail).should == 'geraldinequango@localhost' + end + + it 'should return nil if there is no address in the "From" field' do + mail = get_fixture_mail('track-response-webshield-bounce.email') + MailHandler.get_from_address(mail).should == nil + end + + it 'should return the "From" email address if there is one' do + mail = get_fixture_mail('track-response-abcmail-oof.email') + MailHandler.get_from_address(mail).should == 'Name.Removed@example.gov.uk' + end + + it 'should get an address from a "From" field with a name and address' do + mail = get_fixture_mail('incoming-request-oft-attachments.email') + MailHandler.get_from_address(mail).should == 'public@authority.gov.uk' + end +end + +describe 'when asked for all the addresses a mail has been sent to' do + + it 'should return an array containing the envelope-to address and the to address, and the cc address if there is one' do + mail_data = load_file_fixture('humberside-police-odd-mime-type.email') + mail_data.gsub!('Envelope-to: request-5335-xxxxxxxx@whatdotheyknow.com', + 'Envelope-to: request-5555-xxxxxxxx@whatdotheyknow.com') + mail_data.gsub!('Cc: request-5335-xxxxxxxx@whatdotheyknow.com', + 'Cc: request-3333-xxxxxxxx@whatdotheyknow.com') + mail = MailHandler.mail_from_raw_email(mail_data) + MailHandler.get_all_addresses(mail).should == ['request-5335-xxxxxxxx@whatdotheyknow.com', + 'request-3333-xxxxxxxx@whatdotheyknow.com', + 'request-5555-xxxxxxxx@whatdotheyknow.com'] + end + + it 'should only return unique values' do + # envelope-to and to fields are the same + mail = get_fixture_mail('humberside-police-odd-mime-type.email') + MailHandler.get_all_addresses(mail).should == ['request-5335-xxxxxxxx@whatdotheyknow.com'] + end + + it 'should handle the absence of an envelope-to or cc field' do + mail_data = load_file_fixture('autoresponse-header.email') + mail_data.gsub!('To: FOI Person <EMAIL_TO>', + 'To: FOI Person <request-5555-xxxxxxxx@whatdotheyknow.com>') + mail = MailHandler.mail_from_raw_email(mail_data) + MailHandler.get_all_addresses(mail).should == ["request-5555-xxxxxxxx@whatdotheyknow.com"] + end +end + +describe 'when asked for auto_submitted' do + + it 'should return a string value for an email with an auto-submitted header' do + mail = get_fixture_mail('autoresponse-header.email') + MailHandler.get_auto_submitted(mail).should == 'auto-replied' + end + + it 'should return a nil value for an email with no auto-submitted header' do + mail = get_fixture_mail('incoming-request-plain.email') + MailHandler.get_auto_submitted(mail).should == nil + end + +end + +describe 'when asked if there is an empty return path' do + + it 'should return true if there is an empty return-path specified' do + mail = get_fixture_mail('empty-return-path.email') + MailHandler.empty_return_path?(mail).should == true + end + + it 'should return false if there is no return-path header' do + mail = get_fixture_mail('incoming-request-attach-attachments.email') + MailHandler.empty_return_path?(mail).should == false + end + + it 'should return false if there is a return path address' do + mail = get_fixture_mail('autoresponse-header.email') + MailHandler.empty_return_path?(mail).should == false + end +end + +describe 'when deriving a name, email and formatted address from a message from a line' do + + def should_render_from_address(from_line, expected_result) + mail = create_message_from(from_line) + name = MailHandler.get_from_name(mail) + email = MailHandler.get_from_address(mail) + address = MailHandler.address_from_name_and_email(name, email).to_s + [name, email, address].should == expected_result + end + + it 'should correctly render a name with quoted commas' do + should_render_from_address('"Clare College, Cambridge" <test@test.test>', + ['Clare College, Cambridge', + 'test@test.test', + '"Clare College, Cambridge" <test@test.test>']) + end + + it 'should correctly reproduce a simple name and email that does not need quotes' do + should_render_from_address('"FOI Person" <foiperson@localhost>', + ['FOI Person', + 'foiperson@localhost', + 'FOI Person <foiperson@localhost>']) + end + + it 'should render an address with no name' do + should_render_from_address("foiperson@localhost", + [nil, + "foiperson@localhost", + "foiperson@localhost"]) + end + + it 'should quote a name with a square bracked in it' do + should_render_from_address('"FOI [ Person" <foiperson@localhost>', + ['FOI [ Person', + 'foiperson@localhost', + '"FOI [ Person" <foiperson@localhost>']) + end + + it 'should quote a name with an @ in it' do + should_render_from_address('"FOI @ Person" <foiperson@localhost>', + ['FOI @ Person', + 'foiperson@localhost', + '"FOI @ Person" <foiperson@localhost>']) + end + + + it 'should quote a name with quotes in it' do + should_render_from_address('"FOI \" Person" <foiperson@localhost>', + ['FOI " Person', + 'foiperson@localhost', + '"FOI \" Person" <foiperson@localhost>']) + end + +end + +describe 'when getting the content type of a mail part' do + + def expect_content_type(fixture_file, content_type) + mail = get_fixture_mail(fixture_file) + MailHandler.get_content_type(mail).should == content_type + end + + it 'should correctly return a type of "multipart/report"' do + expect_content_type('track-response-multipart-report.email', 'multipart/report') + end + + it 'should correctly return a type of "text/plain"' do + expect_content_type('track-response-abcmail-oof.email', 'text/plain') + end + + it 'should correctly return a type of "multipart/mixed"' do + expect_content_type('track-response-messageclass-oof.email', 'multipart/mixed') + end + + it 'should correctly return the types in an example bounce report' do + mail = get_fixture_mail('track-response-ms-bounce.email') + report = mail.parts.detect{ |part| MailHandler.get_content_type(part) == 'multipart/report'} + MailHandler.get_content_type(report.parts[0]).should == 'text/plain' + MailHandler.get_content_type(report.parts[1]).should == 'message/delivery-status' + MailHandler.get_content_type(report.parts[2]).should == 'message/rfc822' + end + +end + +describe 'when getting header strings' do + + def expect_header_string(fixture_file, header, header_string) + mail = get_fixture_mail(fixture_file) + MailHandler.get_header_string(header, mail).should == header_string + end + + it 'should return the contents of a "Subject" header' do + expect_header_string('track-response-ms-bounce.email', + 'Subject', + 'Delivery Status Notification (Delay)') + end + + it 'should return the contents of an "X-Failed-Recipients" header' do + expect_header_string('autoresponse-header.email', + 'X-Failed-Recipients', + 'enquiries@cheese.com') + end + + it 'should return the contents of an example "" header' do + expect_header_string('track-response-messageclass-oof.email', + 'X-POST-MessageClass', + '9; Autoresponder') + end + +end + +describe "when parsing HTML mail" do + it "should display UTF-8 characters in the plain text version correctly" do + html = "<html><b>foo</b> është" + plain_text = MailHandler.get_attachment_text_one_file('text/html', html) + plain_text.should match(/është/) + end + +end + +describe "when getting the attachment text" do + it "should not raise an error if the expansion of a zip file raises an error" do + mock_entry = mock('ZipFile entry', :file? => true) + mock_entries = [mock_entry] + mock_entries.stub!(:close) + mock_entry.stub!(:get_input_stream).and_raise("invalid distance too far back") + Zip::ZipFile.stub!(:open).and_return(mock_entries) + MailHandler.get_attachment_text_one_file('application/zip', "some string") + end + +end + +describe 'when getting attachment attributes' do + + it 'should get two attachment parts from a multipart mail with text and html alternatives + and an image' do + mail = get_fixture_mail('quoted-subject-iso8859-1.email') + attributes = MailHandler.get_attachment_attributes(mail) + attributes.size.should == 2 + end + + it 'should expand a mail attached as text' do + # Note that this spec will only pass using Tmail in the timezone set as datetime headers + # are rendered out in the local time - using the Mail gem this is not necessary + with_env_tz('London') do + mail = get_fixture_mail('rfc822-attachment.email') + attributes = MailHandler.get_attachment_attributes(mail) + attributes.size.should == 2 + rfc_attachment = attributes[1] + rfc_attachment[:within_rfc822_subject].should == 'Freedom of Information request' + headers = ['Date: Thu, 13 Mar 2008 16:57:33 +0000', + 'Subject: Freedom of Information request', + 'From: An FOI Officer <foi.officer@example.com>', + 'To: request-bounce-xx-xxxxx@whatdotheyno.com'] + rfc_attachment[:body].should == "#{headers.join("\n")}\n\nsome example text" + end + end + + it 'should handle a mail which causes Tmail to generate a blank header value' do + mail = get_fixture_mail('many-attachments-date-header.email') + attributes = MailHandler.get_attachment_attributes(mail) + end + + it 'should produce a consistent set of url_part_numbers, content_types, within_rfc822_subjects + and filenames from an example mail with lots of attachments' do + mail = get_fixture_mail('many-attachments-date-header.email') + attributes = MailHandler.get_attachment_attributes(mail) + + expected_attributes = [ { :content_type=>"text/plain", + :url_part_number=>1, + :within_rfc822_subject=>nil, + :filename=>nil}, + { :content_type=>"text/plain", + :url_part_number=>2, + :within_rfc822_subject=>"Re: xxx", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>4, + :within_rfc822_subject=>"example", + :filename=>nil}, + { :content_type=>"image/gif", :url_part_number=>5, + :within_rfc822_subject=>"example", + :filename=>"image001.gif"}, + { :content_type=>"application/vnd.ms-excel", + :url_part_number=>6, + :within_rfc822_subject=>"example", + :filename=>"particpant list.xls"}, + { :content_type=>"text/plain", + :url_part_number=>7, + :within_rfc822_subject=>"RE: example", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>9, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>nil}, + { :content_type=>"image/gif", + :url_part_number=>10, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"image001.gif"}, + { :content_type=>"application/vnd.ms-word", + :url_part_number=>11, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"Participant List.doc"}, + { :content_type=>"application/vnd.ms-word", + :url_part_number=>12, + :within_rfc822_subject=>"As promised - Masterclass info (example)", + :filename=>"Information & Booking Form.doc"}, + { :content_type=>"text/plain", + :url_part_number=>13, + :within_rfc822_subject=>"Re: As promised - info (example)", + :filename=>nil}, + { :content_type=>"text/html", + :url_part_number=>15, + :within_rfc822_subject=>"Thank you from example", + :filename=>nil}, + { :content_type=>"image/gif", + :url_part_number=>16, + :within_rfc822_subject=>"Thank you from example", + :filename=>"image001.gif"}, + { :content_type=>"text/plain", + :url_part_number=>17, + :within_rfc822_subject=>"example - Meeting - Tuesday 2nd March", + :filename=>nil}, + { :content_type=>"text/plain", + :url_part_number=>18, + :within_rfc822_subject=>"example - Help needed", + :filename=>nil}, + { :content_type=>"application/pdf", + :url_part_number=>19, + :within_rfc822_subject=>"example - Help needed", + :filename=>"Information Pack.pdf"}, + { :content_type=>"text/plain", + :url_part_number=>20, + :within_rfc822_subject=>"Re: As promised - info (example)", + :filename=>nil} ] + + attributes.each_with_index do |attr, index| + attr.delete(:charset) + attr.delete(:body) + attr.delete(:hexdigest) + attr.should == expected_attributes[index] + end + end +end diff --git a/spec/lib/timezone_fixes_spec.rb b/spec/lib/timezone_fixes_spec.rb index a2bea5f64..525bd7561 100644 --- a/spec/lib/timezone_fixes_spec.rb +++ b/spec/lib/timezone_fixes_spec.rb @@ -92,22 +92,6 @@ describe "when doing things with timezones" do end end - - protected - - def with_env_tz(new_tz = 'US/Eastern') - old_tz, ENV['TZ'] = ENV['TZ'], new_tz - yield - ensure - old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') - end - - def with_active_record_default_timezone(zone) - old_zone, ActiveRecord::Base.default_timezone = ActiveRecord::Base.default_timezone, zone - yield - ensure - ActiveRecord::Base.default_timezone = old_zone - end end diff --git a/spec/lib/tmail_extensions_spec.rb b/spec/lib/tmail_extensions_spec.rb deleted file mode 100644 index bd89e6a84..000000000 --- a/spec/lib/tmail_extensions_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 -# This is a test of the set_content_type monkey patch in -# lib/tmail_extensions.rb - -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') - -describe "when using TMail" do - - before(:each) do - ActionMailer::Base.deliveries.clear - end - - it "should load an email with funny MIME settings" do - # just send it to the holding pen - InfoRequest.holding_pen_request.incoming_messages.size.should == 0 - receive_incoming_mail("humberside-police-odd-mime-type.email", 'dummy') - InfoRequest.holding_pen_request.incoming_messages.size.should == 1 - - # clear the notification of new message in holding pen - deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - deliveries.clear - - incoming_message = InfoRequest.holding_pen_request.incoming_messages[0] - - # This will raise an error if the bug in TMail hasn't been fixed - incoming_message.get_body_for_html_display() - end - - it 'should parse multiple to addresses with unqoted display names' do - mail = TMail::Mail.parse(load_file_fixture('multiple-unquoted-display-names.email')) - mail.to.should == ["request-66666-caa77777@whatdotheyknow.com", "foi@example.com"] - end - - it 'should convert to utf8' do - # NB this isn't actually a TMail extension, but is core TMail; - # this was just a convenient place to assert the UTF8 - # conversion is working - mail = TMail::Mail.parse(load_file_fixture('iso8859_2_raw_email.email')) - mail.subject.should have_text(/gjatë/u) - mail.body.is_utf8?.should == true - end - -end - diff --git a/spec/models/application_mailer_spec.rb b/spec/models/application_mailer_spec.rb index a90f79c01..acf5f43bc 100644 --- a/spec/models/application_mailer_spec.rb +++ b/spec/models/application_mailer_spec.rb @@ -80,7 +80,8 @@ describe ApplicationMailer do it 'should raise an error if the template is in neither core nor theme' do prepend_theme_views('theme_one') - lambda{ ApplicationMailer.create_neither() }.should raise_error('Missing template application_mailer/neither.erb in view path spec/fixtures/theme_views/theme_one:spec/fixtures/theme_views/core') + expected_error = 'Missing template application_mailer/neither.erb in view path' + lambda{ ApplicationMailer.create_neither() }.should raise_error(/#{expected_error}/) end it 'should render a multipart email using a theme template' do @@ -125,7 +126,8 @@ describe ApplicationMailer do it 'should raise an error if the template is in neither core nor theme' do append_theme_views('theme_one') - lambda{ ApplicationMailer.create_neither() }.should raise_error('Missing template application_mailer/neither.erb in view path spec/fixtures/theme_views/core:spec/fixtures/theme_views/theme_one') + expected_error = 'Missing template application_mailer/neither.erb in view path' + lambda{ ApplicationMailer.create_neither() }.should raise_error(/#{expected_error}/) end it 'should render a multipart email using a core template' do diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index b038c43d9..6fc0ff3cc 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -26,11 +26,6 @@ describe IncomingMessage, " when dealing with incoming mail" do @im.sent_at.should == @im.mail.date end - it "should be able to parse emails with quoted commas in" do - em = "\"Clare College, Cambridge\" <test@test.test>" - TMail::Address.parse(em) - end - it "should correctly fold various types of footer" do Dir.glob(File.join(Spec::Runner.configuration.fixture_path, "files", "email-folding-example-*.txt")).each do |file| message = File.read(file) @@ -73,6 +68,14 @@ describe IncomingMessage, " when dealing with incoming mail" do message.get_main_body_text_internal.should include("The above text was badly encoded") end + it 'should convert DOS-style linebreaks to Unix style' do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('dos-linebreaks.email', ir.incoming_email) + message = ir.incoming_messages[1] + message.parse_raw_email! + message.get_main_body_text_internal.should_not match(/\r\n/) + end + it "should fold multiline sections" do { "foo\n--------\nconfidential" => "foo\nFOLDED_QUOTED_SECTION\n", # basic test @@ -85,28 +88,27 @@ describe IncomingMessage, " when dealing with incoming mail" do end end -end -describe IncomingMessage, "when parsing HTML mail" do - it "should display UTF-8 characters in the plain text version correctly" do - html = "<html><b>foo</b> është" - plain_text = IncomingMessage._get_attachment_text_internal_one_file('text/html', html) - plain_text.should match(/është/) - end + it "should load an email with funny MIME settings" do + ActionMailer::Base.deliveries.clear + # just send it to the holding pen + InfoRequest.holding_pen_request.incoming_messages.size.should == 0 + receive_incoming_mail("humberside-police-odd-mime-type.email", 'dummy') + InfoRequest.holding_pen_request.incoming_messages.size.should == 1 -end + # clear the notification of new message in holding pen + deliveries = ActionMailer::Base.deliveries + deliveries.size.should == 1 + deliveries.clear -describe IncomingMessage, "when getting the attachment text" do + incoming_message = InfoRequest.holding_pen_request.incoming_messages[0] - it "should not raise an error if the expansion of a zip file raises an error" do - mock_entry = mock('ZipFile entry', :file? => true) - mock_entry.stub!(:get_input_stream).and_raise("invalid distance too far back") - Zip::ZipFile.stub!(:open).and_return([mock_entry]) - IncomingMessage._get_attachment_text_internal_one_file('application/zip', "some string") - end + # This will raise an error if the bug in TMail hasn't been fixed + incoming_message.get_body_for_html_display() + end -end +end describe IncomingMessage, " display attachments" do @@ -123,7 +125,7 @@ describe IncomingMessage, " display attachments" do # http://www.whatdotheyknow.com/request/post_commercial_manager_librarie#incoming-17233 foi_attachment.within_rfc822_subject = "FOI/09/066 RESPONSE TO FOI REQUEST RECEIVED 21st JANUARY 2009" foi_attachment.content_type = 'text/plain' - foi_attachment.ensure_filename! + foi_attachment.ensure_filename! expected_display_filename = foi_attachment.within_rfc822_subject.gsub(/\//, " ") + ".txt" foi_attachment.display_filename.should == expected_display_filename end @@ -174,59 +176,50 @@ describe IncomingMessage, " folding quoted parts of emails" do end describe IncomingMessage, " checking validity to reply to" do - def test_email(result, email, return_path, autosubmitted = nil) - @address = mock(TMail::Address) - @address.stub!(:spec).and_return(email) - - @return_path = mock(TMail::ReturnPathHeader) - @return_path.stub!(:addr).and_return(return_path) - if !autosubmitted.nil? - @autosubmitted = TMail::UnstructuredHeader.new("auto-submitted", autosubmitted) - end - @mail = mock(TMail::Mail) - @mail.stub!(:from_addrs).and_return( [ @address ] ) - @mail.stub!(:[]).with("return-path").and_return(@return_path) - @mail.stub!(:[]).with("auto-submitted").and_return(@autosubmitted) - + def test_email(result, email, empty_return_path, autosubmitted = nil) + @mail = mock('mail') + MailHandler.stub!(:get_from_address).and_return(email) + MailHandler.stub!(:empty_return_path?).with(@mail).and_return(empty_return_path) + MailHandler.stub!(:get_auto_submitted).with(@mail).and_return(autosubmitted) @incoming_message = IncomingMessage.new() @incoming_message.stub!(:mail).and_return(@mail) @incoming_message._calculate_valid_to_reply_to.should == result end it "says a valid email is fine" do - test_email(true, "team@mysociety.org", nil) + test_email(true, "team@mysociety.org", false) end it "says postmaster email is bad" do - test_email(false, "postmaster@mysociety.org", nil) + test_email(false, "postmaster@mysociety.org", false) end it "says Mailer-Daemon email is bad" do - test_email(false, "Mailer-Daemon@mysociety.org", nil) + test_email(false, "Mailer-Daemon@mysociety.org", false) end it "says case mangled MaIler-DaemOn email is bad" do - test_email(false, "MaIler-DaemOn@mysociety.org", nil) + test_email(false, "MaIler-DaemOn@mysociety.org", false) end it "says Auto_Reply email is bad" do - test_email(false, "Auto_Reply@mysociety.org", nil) + test_email(false, "Auto_Reply@mysociety.org", false) end it "says DoNotReply email is bad" do - test_email(false, "DoNotReply@tube.tfl.gov.uk", nil) + test_email(false, "DoNotReply@tube.tfl.gov.uk", false) end it "says a filled-out return-path is fine" do - test_email(true, "team@mysociety.org", "Return-path: <foo@baz.com>") + test_email(true, "team@mysociety.org", false) end it "says an empty return-path is bad" do - test_email(false, "team@mysociety.org", "<>") + test_email(false, "team@mysociety.org", true) end it "says an auto-submitted keyword is bad" do - test_email(false, "team@mysociety.org", nil, "auto-replied") + test_email(false, "team@mysociety.org", false, "auto-replied") end end @@ -320,12 +313,12 @@ describe IncomingMessage, " when censoring data" do orig_pdf = load_file_fixture('tfl.pdf') pdf = orig_pdf.dup - orig_text = IncomingMessage._get_attachment_text_internal_one_file('application/pdf', pdf) + orig_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) orig_text.should match(/foi@tfl.gov.uk/) @im.binary_mask_stuff!(pdf, "application/pdf") - masked_text = IncomingMessage._get_attachment_text_internal_one_file('application/pdf', pdf) + masked_text = MailHandler.get_attachment_text_one_file('application/pdf', pdf) masked_text.should_not match(/foi@tfl.gov.uk/) masked_text.should match(/xxx@xxx.xxx.xx/) config['USE_GHOSTSCRIPT_COMPRESSION'] = previous @@ -399,14 +392,8 @@ end describe IncomingMessage, " when uudecoding bad messages" do - before(:each) do - load_raw_emails_data - end - it "should be able to do it at all" do - mail_body = load_file_fixture('incoming-request-bad-uuencoding.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode + mail = get_fixture_mail('incoming-request-bad-uuencoding.email') im = incoming_messages(:useless_incoming_message) im.stub!(:mail).and_return(mail) im.extract_attachments! @@ -418,9 +405,7 @@ describe IncomingMessage, " when uudecoding bad messages" do end it "should apply censor rules" do - mail_body = load_file_fixture('incoming-request-bad-uuencoding.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode + mail = get_fixture_mail('incoming-request-bad-uuencoding.email') im = incoming_messages(:useless_incoming_message) im.stub!(:mail).and_return(mail) @@ -443,14 +428,30 @@ end describe IncomingMessage, "when messages are attached to messages" do - before(:each) do - load_raw_emails_data + it 'should expand an RFC822 attachment' do + # Note that this spec will only pass using Tmail in the timezone set as datetime headers + # are rendered out in the local time - using the Mail gem this is not necessary + with_env_tz('London') do + mail_body = load_file_fixture('rfc822-attachment.email') + mail = MailHandler.mail_from_raw_email(mail_body) + + im = incoming_messages(:useless_incoming_message) + im.stub!(:mail).and_return(mail) + + attachments = im.get_attachments_for_display + attachments.size.should == 1 + attachment = attachments.first + + attachment.content_type.should == 'text/plain' + attachment.filename.should == "Freedom of Information request.txt" + attachment.charset.should == "utf-8" + attachment.within_rfc822_subject.should == "Freedom of Information request" + attachment.hexdigest.should == 'f10fe56e4f2287685a58b71329f09639' + end end it "should flatten all the attachments out" do - mail_body = load_file_fixture('incoming-request-attach-attachments.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode + mail = get_fixture_mail('incoming-request-attach-attachments.email') im = incoming_messages(:useless_incoming_message) im.stub!(:mail).and_return(mail) @@ -464,18 +465,29 @@ describe IncomingMessage, "when messages are attached to messages" do 'hello.txt', ] end -end -describe IncomingMessage, "when Outlook messages are attached to messages" do + it 'should add headers to attached plain text message bodies' do + # Note that this spec will only pass using Tmail in the timezone set as datetime headers + # are rendered out in the local time - using the Mail gem this is not necessary + with_env_tz('London') do + mail_body = load_file_fixture('incoming-request-attachment-headers.email') + mail = MailHandler.mail_from_raw_email(mail_body) - before(:each) do - load_raw_emails_data + im = incoming_messages(:useless_incoming_message) + im.stub!(:mail).and_return(mail) + + attachments = im.get_attachments_for_display + attachments.size.should == 2 + attachments[0].body.should match('Date: Fri, 23 May 2008') + end end +end + +describe IncomingMessage, "when Outlook messages are attached to messages" do + it "should flatten all the attachments out" do - mail_body = load_file_fixture('incoming-request-oft-attachments.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode + mail = get_fixture_mail('incoming-request-oft-attachments.email') im = incoming_messages(:useless_incoming_message) im.stub!(:mail).and_return(mail) @@ -490,14 +502,8 @@ end describe IncomingMessage, "when TNEF attachments are attached to messages" do - before(:each) do - load_raw_emails_data - end - it "should flatten all the attachments out" do - mail_body = load_file_fixture('incoming-request-tnef-attachments.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode + mail = get_fixture_mail('incoming-request-tnef-attachments.email') im = incoming_messages(:useless_incoming_message) im.stub!(:mail).and_return(mail) diff --git a/spec/models/info_request_event_spec.rb b/spec/models/info_request_event_spec.rb index 7352f3be0..796f8b840 100644 --- a/spec/models/info_request_event_spec.rb +++ b/spec/models/info_request_event_spec.rb @@ -54,36 +54,71 @@ describe InfoRequestEvent do end - describe "doing search/index stuff" do + describe "doing search/index stuff" do before(:each) do load_raw_emails_data parse_all_incoming_messages end - it 'should get search text for outgoing messages' do + it 'should get search text for outgoing messages' do event = info_request_events(:useless_outgoing_message_event) message = outgoing_messages(:useless_outgoing_message).body event.search_text_main.should == message + "\n\n" end - it 'should get search text for incoming messages' do + it 'should get search text for incoming messages' do event = info_request_events(:useless_incoming_message_event) event.search_text_main.strip.should == "No way! I'm not going to tell you that in a month of Thursdays.\n\nThe Geraldine Quango" end - it 'should get clipped text for incoming messages, and cache it too' do + it 'should get clipped text for incoming messages, and cache it too' do event = info_request_events(:useless_incoming_message_event) - + event.incoming_message_selective_columns("cached_main_body_text_folded").cached_main_body_text_folded = nil event.search_text_main(true).strip.should == "No way! I'm not going to tell you that in a month of Thursdays.\n\nThe Geraldine Quango" event.incoming_message_selective_columns("cached_main_body_text_folded").cached_main_body_text_folded.should_not == nil end - end + describe 'when asked if it has the same email as a previous send' do + + before do + @info_request_event = InfoRequestEvent.new + end + + it 'should return true if the email in its params and the previous email the request was sent to are both nil' do + @info_request_event.stub!(:params).and_return({}) + @info_request_event.stub_chain(:info_request, :get_previous_email_sent_to).and_return(nil) + @info_request_event.same_email_as_previous_send?.should be_true + end + + it 'should return false if one email address exists and the other does not' do + @info_request_event.stub!(:params).and_return(:email => 'test@example.com') + @info_request_event.stub_chain(:info_request, :get_previous_email_sent_to).and_return(nil) + @info_request_event.same_email_as_previous_send?.should be_false + end + it 'should return true if the addresses are identical' do + @info_request_event.stub!(:params).and_return(:email => 'test@example.com') + @info_request_event.stub_chain(:info_request, :get_previous_email_sent_to).and_return('test@example.com') + @info_request_event.same_email_as_previous_send?.should be_true + end + + it 'should return false if the addresses are different' do + @info_request_event.stub!(:params).and_return(:email => 'test@example.com') + @info_request_event.stub_chain(:info_request, :get_previous_email_sent_to).and_return('different@example.com') + @info_request_event.same_email_as_previous_send?.should be_false + end + + it 'should return true if the addresses have different formats' do + @info_request_event.stub!(:params).and_return(:email => 'A Test <test@example.com>') + @info_request_event.stub_chain(:info_request, :get_previous_email_sent_to).and_return('test@example.com') + @info_request_event.same_email_as_previous_send?.should be_true + end + + end end diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 2aeac2fec..544852f91 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -2,6 +2,22 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe InfoRequest do + describe 'when generating a user name slug' do + + before do + @public_body = mock_model(PublicBody, :url_name => 'example_body', + :eir_only? => false) + @info_request = InfoRequest.new(:external_url => 'http://www.example.com', + :external_user_name => 'Example User', + :public_body => @public_body) + end + + it 'should generate a slug for an example user name' do + @info_request.user_name_slug.should == 'example_body_example_user' + end + + end + describe "guessing a request from an email" do before(:each) do diff --git a/spec/models/request_mailer_spec.rb b/spec/models/request_mailer_spec.rb index 906756784..0f09e6926 100644 --- a/spec/models/request_mailer_spec.rb +++ b/spec/models/request_mailer_spec.rb @@ -98,7 +98,7 @@ describe RequestMailer, " when receiving incoming mail" do mail.multipart?.should == true mail.parts.size.should == 2 message_part = mail.parts[0].to_s - bounced_mail = TMail::Mail.parse(mail.parts[1].body) + bounced_mail = MailHandler.mail_from_raw_email(mail.parts[1].body, decode=false) bounced_mail.to.should == [ ir.incoming_email ] bounced_mail.from.should == [ 'geraldinequango@localhost' ] bounced_mail.body.include?("That's so totally a rubbish question").should be_true diff --git a/spec/models/track_mailer_spec.rb b/spec/models/track_mailer_spec.rb index 1bf77dab5..9bf03c3d0 100644 --- a/spec/models/track_mailer_spec.rb +++ b/spec/models/track_mailer_spec.rb @@ -169,7 +169,7 @@ describe TrackMailer do it 'should deliver one email, with right headers' do @user = mock_model(User, - :name_and_email => TMail::Address.address_from_name_and_email('Tippy Test', 'tippy@localhost'), + :name_and_email => MailHandler.address_from_name_and_email('Tippy Test', 'tippy@localhost'), :url_name => 'tippy_test' ) diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb index 195b39eee..8c99d550f 100644 --- a/spec/models/xapian_spec.rb +++ b/spec/models/xapian_spec.rb @@ -4,9 +4,9 @@ describe User, " when indexing users with Xapian" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end - + it "should search by name" do # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) xapian_object = InfoRequest.full_search([User], "Silly", 'created_at', true, nil, 100, 1) @@ -21,7 +21,7 @@ describe User, " when indexing users with Xapian" do xapian_object = InfoRequest.full_search([User], "stuff", 'created_at', true, nil, 100, 1) xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == user - + user.about_me = "I am really an aardvark, true story." user.save! update_xapian_index @@ -38,7 +38,7 @@ end describe PublicBody, " when indexing public bodies with Xapian" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should search index the main name field" do @@ -71,7 +71,7 @@ describe PublicBody, " when indexing requests by body they are to" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find requests to the body" do @@ -126,7 +126,7 @@ end describe User, " when indexing requests by user they are from" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find requests from the user" do @@ -204,7 +204,7 @@ end describe User, " when indexing comments by user they are by" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find requests from the user" do @@ -239,7 +239,7 @@ end describe InfoRequest, " when indexing requests by their title" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find events for the request" do @@ -268,7 +268,7 @@ end describe InfoRequest, " when indexing requests by tag" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find request by tag, even when changes" do @@ -289,7 +289,7 @@ end describe PublicBody, " when indexing authorities by tag" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should find request by tag, even when changes" do @@ -313,7 +313,7 @@ end describe PublicBody, " when only indexing selected things on a rebuild" do before(:each) do load_raw_emails_data - rebuild_xapian_index + get_fixtures_xapian_index end it "should only index what we ask it to" do diff --git a/spec/script/handle-mail-replies_spec.rb b/spec/script/handle-mail-replies_spec.rb index 406af9ee3..90a8de27c 100644 --- a/spec/script/handle-mail-replies_spec.rb +++ b/spec/script/handle-mail-replies_spec.rb @@ -5,7 +5,7 @@ def mail_reply_test(email_filename) Dir.chdir Rails.root do xc = ExternalCommand.new("script/handle-mail-replies", "--test") xc.run(load_file_fixture(email_filename)) - + xc.err.should == "" return xc end @@ -14,7 +14,7 @@ end describe "When filtering" do it "should not fail when not in test mode" do xc = ExternalCommand.new("script/handle-mail-replies") - xc.run(load_file_fixture("track-response-exim-bounce.email")) + xc.run(load_file_fixture("track-response-exim-bounce.email")) xc.err.should == "" end @@ -23,19 +23,19 @@ describe "When filtering" do r.status.should == 1 r.out.should == "user@example.com\n" end - + it "should detect a WebShield delivery error message" do r = mail_reply_test("track-response-webshield-bounce.email") r.status.should == 1 r.out.should == "failed.user@example.co.uk\n" end - + it "should detect a MS Exchange non-permanent delivery error message" do r = mail_reply_test("track-response-ms-bounce.email") r.status.should == 1 r.out.should == "" end - + it "should pass on a non-bounce message" do r = mail_reply_test("incoming-request-bad-uuencoding.email") r.status.should == 0 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 248dff70e..561a75da6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,7 +23,6 @@ FakeWeb.register_uri(:purge, %r|varnish.localdomain|, :body => "OK") # Use test-specific translations FastGettext.add_text_domain 'app', :path => File.join(File.dirname(__FILE__), 'fixtures', 'locale'), :type => :po FastGettext.default_text_domain = 'app' - Spec::Runner.configure do |config| # If you're not using ActiveRecord you should remove these # lines, delete config/database.yml and disable :active_record @@ -47,6 +46,21 @@ Spec::Runner.configure do |config| :holidays, :track_things_sent_emails + # This section makes the garbage collector run less often to speed up tests + last_gc_run = Time.now + + config.before(:each) do + GC.disable + end + + config.after(:each) do + if Time.now - last_gc_run > 4 + GC.enable + GC.start + last_gc_run = Time.now + end + end + # == Fixtures # # You can declare fixtures for each example_group like this: @@ -93,12 +107,30 @@ def file_fixture_name(file_name) return File.join(Spec::Runner.configuration.fixture_path, "files", file_name) end -def load_file_fixture(file_name) +def load_file_fixture(file_name, as_binary=false) file_name = file_fixture_name(file_name) - content = File.read(file_name) + content = File.open(file_name, 'r') do |file| + if as_binary + file.set_encoding(Encoding::BINARY) if file.respond_to?(:set_encoding) + end + file.read + end return content end +def parse_all_incoming_messages + IncomingMessage.find(:all).each{ |x| x.parse_raw_email! } +end + +def load_raw_emails_data + raw_emails_yml = File.join(Spec::Runner.configuration.fixture_path, "raw_emails.yml") + for raw_email_id in YAML::load_file(raw_emails_yml).map{|k,v| v["id"]} do + raw_email = RawEmail.find(raw_email_id) + raw_email.data = load_file_fixture("raw_emails/%d.email" % [raw_email_id]) + end +end + +# Rebuild the current xapian index def rebuild_xapian_index(terms = true, values = true, texts = true, dropfirst = true) if dropfirst begin @@ -110,16 +142,35 @@ def rebuild_xapian_index(terms = true, values = true, texts = true, dropfirst = ActsAsXapian.writable_db.close end parse_all_incoming_messages - verbose = false # safe_rebuild=true, which involves forking to avoid memory leaks, doesn't work well with rspec. # unsafe is significantly faster, and we can afford possible memory leaks while testing. - safe_rebuild = false - ActsAsXapian.rebuild_index(["PublicBody", "User", "InfoRequestEvent"].map{|m| m.constantize}, verbose, terms, values, texts, safe_rebuild) + models = [PublicBody, User, InfoRequestEvent] + ActsAsXapian.rebuild_index(models, verbose=false, terms, values, texts, safe_rebuild=false) +end + +# Create a clean xapian index based on the fixture files and the raw_email data. +def create_fixtures_xapian_index + load_raw_emails_data + rebuild_xapian_index end def update_xapian_index - verbose = false - ActsAsXapian.update_index(flush_to_disk=false, verbose) + ActsAsXapian.update_index(flush_to_disk=false, verbose=false) +end + +# Copy the xapian index created in create_fixtures_xapian_index to a temporary +# copy at the same level and point xapian at the copy +def get_fixtures_xapian_index() + # Create a base index for the fixtures if not already created + $existing_xapian_db ||= create_fixtures_xapian_index + # Store whatever the xapian db path is originally + $original_xapian_path ||= ActsAsXapian.db_path + path_array = $original_xapian_path.split(File::Separator) + path_array.pop + temp_path = File.join(path_array, 'test.temp') + FileUtils.remove_entry_secure(temp_path, force=true) + FileUtils.cp_r($original_xapian_path, temp_path) + ActsAsXapian.db_path = temp_path end # Validate an entire HTML page @@ -200,16 +251,8 @@ def safe_mock_model(model, args = {}) mock end -def load_raw_emails_data - raw_emails_yml = File.join(Spec::Runner.configuration.fixture_path, "raw_emails.yml") - for raw_email_id in YAML::load_file(raw_emails_yml).map{|k,v| v["id"]} do - raw_email = RawEmail.find(raw_email_id) - raw_email.data = load_file_fixture("raw_emails/%d.email" % [raw_email_id]) - end -end - -def parse_all_incoming_messages - IncomingMessage.find(:all).each{|x| x.parse_raw_email!} +def get_fixture_mail(filename) + MailHandler.mail_from_raw_email(load_file_fixture(filename)) end def load_test_categories @@ -232,3 +275,18 @@ class ApplicationController < ActionController::Base @popup_banner = nil end end + + +def with_env_tz(new_tz = 'US/Eastern') + old_tz, ENV['TZ'] = ENV['TZ'], new_tz + yield +ensure + old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') +end + +def with_active_record_default_timezone(zone) + old_zone, ActiveRecord::Base.default_timezone = ActiveRecord::Base.default_timezone, zone + yield +ensure + ActiveRecord::Base.default_timezone = old_zone +end diff --git a/vendor/gems/fakeweb-1.3.0/.gitignore b/vendor/gems/fakeweb-1.3.0/.gitignore deleted file mode 100644 index 63be0c5de..000000000 --- a/vendor/gems/fakeweb-1.3.0/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/doc -/rdoc -/html -/coverage -/pkg -/.idea -*.rbc diff --git a/vendor/gems/fakeweb-1.3.0/.specification b/vendor/gems/fakeweb-1.3.0/.specification deleted file mode 100644 index b69e9d545..000000000 --- a/vendor/gems/fakeweb-1.3.0/.specification +++ /dev/null @@ -1,135 +0,0 @@ ---- !ruby/object:Gem::Specification -name: fakeweb -version: !ruby/object:Gem::Version - hash: 27 - prerelease: - segments: - - 1 - - 3 - - 0 - version: 1.3.0 -platform: ruby -authors: -- Chris Kampmeier -- Blaine Cook -autorequire: -bindir: bin -cert_chain: [] - -date: 2010-08-22 00:00:00 +01:00 -default_executable: -dependencies: -- !ruby/object:Gem::Dependency - name: mocha - prerelease: false - requirement: &id001 !ruby/object:Gem::Requirement - none: false - requirements: - - - ">=" - - !ruby/object:Gem::Version - hash: 49 - segments: - - 0 - - 9 - - 5 - version: 0.9.5 - type: :development - version_requirements: *id001 -description: FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs. -email: -- chris@kampers.net -- romeda@gmail.com -executables: [] - -extensions: [] - -extra_rdoc_files: [] - -files: -- test/test_allow_net_connect.rb -- test/test_deprecations.rb -- test/test_fake_authentication.rb -- test/test_fake_web.rb -- test/test_fake_web_open_uri.rb -- test/test_helper.rb -- test/test_last_request.rb -- test/test_missing_open_uri.rb -- test/test_missing_pathname.rb -- test/test_other_net_http_libraries.rb -- test/test_precedence.rb -- test/test_query_string.rb -- test/test_regexes.rb -- test/test_response_headers.rb -- test/test_trailing_slashes.rb -- test/test_utility.rb -- test/vendor/right_http_connection-1.2.4/lib/net_fix.rb -- test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb -- test/vendor/right_http_connection-1.2.4/setup.rb -- test/vendor/samuel-0.2.1/lib/samuel/net_http.rb -- test/vendor/samuel-0.2.1/lib/samuel/request.rb -- test/vendor/samuel-0.2.1/lib/samuel.rb -- test/vendor/samuel-0.2.1/test/request_test.rb -- test/vendor/samuel-0.2.1/test/samuel_test.rb -- test/vendor/samuel-0.2.1/test/test_helper.rb -- test/vendor/samuel-0.2.1/test/thread_test.rb -has_rdoc: true -homepage: http://github.com/chrisk/fakeweb -licenses: [] - -post_install_message: -rdoc_options: [] - -require_paths: -- lib -required_ruby_version: !ruby/object:Gem::Requirement - none: false - requirements: - - - ">=" - - !ruby/object:Gem::Version - hash: 3 - segments: - - 0 - version: "0" -required_rubygems_version: !ruby/object:Gem::Requirement - none: false - requirements: - - - ">=" - - !ruby/object:Gem::Version - hash: 3 - segments: - - 0 - version: "0" -requirements: [] - -rubyforge_project: fakeweb -rubygems_version: 1.6.2 -signing_key: -specification_version: 3 -summary: A tool for faking responses to HTTP requests -test_files: -- test/test_allow_net_connect.rb -- test/test_deprecations.rb -- test/test_fake_authentication.rb -- test/test_fake_web.rb -- test/test_fake_web_open_uri.rb -- test/test_helper.rb -- test/test_last_request.rb -- test/test_missing_open_uri.rb -- test/test_missing_pathname.rb -- test/test_other_net_http_libraries.rb -- test/test_precedence.rb -- test/test_query_string.rb -- test/test_regexes.rb -- test/test_response_headers.rb -- test/test_trailing_slashes.rb -- test/test_utility.rb -- test/vendor/right_http_connection-1.2.4/lib/net_fix.rb -- test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb -- test/vendor/right_http_connection-1.2.4/setup.rb -- test/vendor/samuel-0.2.1/lib/samuel/net_http.rb -- test/vendor/samuel-0.2.1/lib/samuel/request.rb -- test/vendor/samuel-0.2.1/lib/samuel.rb -- test/vendor/samuel-0.2.1/test/request_test.rb -- test/vendor/samuel-0.2.1/test/samuel_test.rb -- test/vendor/samuel-0.2.1/test/test_helper.rb -- test/vendor/samuel-0.2.1/test/thread_test.rb diff --git a/vendor/gems/fakeweb-1.3.0/CHANGELOG b/vendor/gems/fakeweb-1.3.0/CHANGELOG deleted file mode 100644 index e626352f6..000000000 --- a/vendor/gems/fakeweb-1.3.0/CHANGELOG +++ /dev/null @@ -1,215 +0,0 @@ -fakeweb (1.3.0) - -* improve response header registration so you can pass an array to set a header - more than once [Myron Marston] - -* fix an exception when the response's :body option was set to nil [Chris Zingel] - -* fix that stubbed requests weren't mutating the Net::HTTP request object to set - the body and content-length, like real requests do [Chris Kampmeier] - -* add FakeWeb.last_request [Chris Kampmeier] - -* assigning a String or Regexp to FakeWeb.allow_net_connect= sets a whitelist - for outbound requests [Dan Dofter, Tim Carey-Smith, Ben Woosley] - - -fakeweb (1.2.8) - -* support Pathname objects where a filename is expected [Chris Kampmeier] - -* fix compatibility with Ruby 1.9.2 [Chris Kampmeier] - -* simplify storage of FakeWeb::VERSION [Josh Peek, Woody Peterson, Ben Woosley] - - -fakeweb (1.2.7) - -* revert to sorting query params before matching requests against regexps, - instead of the 1.2.6 behavior that tried every possible order combination; - that was factorial-time, which made matching hang for requests with long query - strings [Jason Wadsworth, David Dollar, Blaine Cook] - -* print a warning when FakeWeb is loaded before RightHttpConnection or after - Samuel, other libs that patch Net::HTTP [Chris Kampmeier, Ben Brinckerhoff] - - -fakeweb (1.2.6) - -* fix that query params in a regex would have to be sorted for it to ever match - a request URI [Chris Kampmeier, Ben Hall] - -* improve regex handling so registration with an explicit port (like - /example.com:80/) matches a request that uses an implied port - (like "http://example.com/") [Chris Kampmeier, Dan Dofter] - -* refactor URI registry to reduce duplication; now about twice as fast at - handling requests [Chris Kampmeier] - -* Add FakeWeb::VERSION so you can programmatically determine what version of - FakeWeb is loaded without using RubyGems [Chris Kampmeier, Chris Wanstrath] - - -fakeweb (1.2.5) - -* fix handling of userinfo strings that contain percent-encoded unsafe - characters [Chris Kampmeier, Ken Mayer] - -* fix that exact matches against strings/URIs with the :any method had a lower - precedence than regex matches using a real HTTP method (exact matches now - always take precedence) [Chris Kampmeier] - -* change request handling to raise an exception when more than one registered - regex matches a request URI [Chris Kampmeier] - - -fakeweb (1.2.4) - -* add experimental support for matching URIs via regular expressions - [Jacqui Maher, Tiago Albineli Motta, Peter Wagene] - -* fix an exception when registering with the :response option and a string that - is the same as the name of a directory in the current path [Chris Kampmeier] - -* DEPRECATION: Calling FakeWeb.register_uri with a :string or :file option is - now deprecated. Both options have been replaced with a unified :body option, - since they supply the response body (as opposed to :response, which supplies - the full response including headers) [Chris Kampmeier] - -* add support for specifying HTTP headers as options to FakeWeb.register_uri - when using the :string or :file response types, since those methods only - specify a response body [David Michael, Chris Kampmeier] - -* DEPRECATION: Calling FakeWeb.register_uri and FakeWeb.registered_uri? without - an HTTP method as the first argument is now deprecated. To match against any - HTTP method (the pre-1.2.0 behavior), use :any [Chris Kampmeier] - - -fakeweb (1.2.3) - -* fix the #http_version of :file and :string responses, which was returning the - request URI instead of something sensible like "1.0" [Chris Kampmeier] - -* add method aliases in the Net::HTTP patch to eliminate warnings when running - with -w [Joshua Clingenpeel] - -* fix that removing the redefinition of OpenURI::HTTPError in 1.2.0 caused - :exception responses to raise when OpenURI isn't available [Chris Kampmeier] - -* fix registering an :exception response with classes that require arguments for - instantiation, like Interrupt's subclasses [Chris Kampmeier] - - -fakeweb (1.2.2) - -* fix that HTTP Digest and OAuth requests could raise URI::InvalidURIErrors - [Bill Kocik, Chris Kampmeier] - - -fakeweb (1.2.1) - -* fix that query parameters are handled correctly when registering with a URI - object [Anselmo Alves, Chris Kampmeier] - -* fix an exception when registering with the :response option and a string - containing "\0" [Jonathan Baudanza, Chris Kampmeier] - -* fix that trailing slashes were considered significant for requests to the root - of a domain [Chris Kampmeier] - -* add support for HTTP basic authentication via userinfo strings in URIs - [Michael Bleigh] - - -fakeweb (1.2.0) - -* add lib/fakeweb.rb so you can require "fakeweb" as well [Chris Kampmeier] - -* fix compatibility with Ruby 1.9.1 [Chris Kampmeier] - -* fix that newlines in file-based responses could be doubled in the response - object's body [Mark Menard, Chris Kampmeier] - -* fix unnecessary munging of the transfer-encoding header, which improves - compatibility with mechanize [Mark Menard] - -* fix a test and the RCov dependency to be compatible with JRuby [Mark Menard] - -* remove an unnecessary redefinition of OpenURI::HTTPError [Josh Nichols] - -* rearrange implementation code into separate files, one per class [Josh Nichols] - -* fix a bug where FakeWeb.response_for would raise if the request wasn't - registered [Chris Kampmeier] - -* add HTTP method support, so FakeWeb takes both the URI and method into - account for registration, requests, and responses. Backwards-compatible with - the old method signatures, which didn't have a method param. [Chris Kampmeier] - -* start work on Ruby 1.9 compatibility [Chris Kampmeier] - -* add FakeWeb.allow_net_connect= to enable/disable the pass-through to - Net::HTTP for unregistered URIs [Mislav Marohnić, Chris Kampmeier] - -* remove setup.rb, since most people use RubyGems [Mislav Marohnić] - -* fix that 'http://example.com/?' (empty query) matches a registered - 'http://example.com/', and vice-versa [Mislav Marohnić] - -* improve the test suite to not rely on an internet connection [Chris Kampmeier] - -* use `rake test` instead of `rake tests` [Josh Nichols] - -* fix an incompatibility with Ruby 1.8.6 p36 where you'd get "Errno::EINTR: - Interrupted system call" exceptions in Socket#sysread for any non-faked - request [Chris Kampmeier] - -* response rotation: you can now optionally call FakeWeb.register_uri with an - array of options hashes; these are used, in order, to respond to - repeated requests (to repeat a response more than once before rotating, use - the :times option). Once you run out of responses, further requests always - receive the last response. [Michael Shapiro] - -* add support for Net::HTTP's undocumented full-URI request style (fixes - URI::InvalidURIErrors that you might see in older libraries) [Chris Kampmeier] - -* sort query params before storing internally, so that - http://example.com/?a=1&b=2 and http://example.com/?b=2&a=1 are considered the - same URL (although this is technically incorrect, it's much more - convenient--most web apps work that way, and Net::HTTP's use of a hash to pass - query params means that the order in which FakeWeb stores them can be - unpredictable) [Chris Kampmeier] - -* add support for ports in URLs, so that http://example.com/ and - http://example.com:3000/ are not the same [Chris Kampmeier] - -* fix for non-faked SSL requests failing with "Unable to create local socket" - [Chris Kampmeier] - -* update Rakefile to fix warning about deprecated code [Chris Kampmeier] - - -fakeweb (1.1.2) - -* add required dependencies to GemSpec to ensure that tests pass in firebrigade - (http://firebrigade.seattlerb.org/) [Blaine Cook] - - -fakeweb (1.1.1) - -* fix for non-existence of :string method on File as presented by open-uri - [Blaine Cook] - -* fix for curl example test - google redirects to ccTLDs for those outside US - [Blaine Cook] - - -fakeweb (1.1.0) - -* update code to correspond to ruby 1.8.4 (breaks compatibility with ruby 1.8.2) - [Blaine Cook] - - -fakeweb (1.0.0) - - * initial import [Blaine Cook] diff --git a/vendor/gems/fakeweb-1.3.0/LICENSE.txt b/vendor/gems/fakeweb-1.3.0/LICENSE.txt deleted file mode 100644 index ecae84703..000000000 --- a/vendor/gems/fakeweb-1.3.0/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright 2006-2010 Blaine Cook, Chris Kampmeier, and other contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/gems/fakeweb-1.3.0/README.rdoc b/vendor/gems/fakeweb-1.3.0/README.rdoc deleted file mode 100644 index 33115325b..000000000 --- a/vendor/gems/fakeweb-1.3.0/README.rdoc +++ /dev/null @@ -1,189 +0,0 @@ -= FakeWeb - -FakeWeb is a helper for faking web requests in Ruby. It works at a global -level, without modifying code or writing extensive stubs. - - -== Installation - - gem install fakeweb - -Note: the gem was previously available as +FakeWeb+ (capital letters), but now -all versions are simply registered as +fakeweb+. If you have any old +FakeWeb+ -gems lying around, remove them: <tt>gem uninstall FakeWeb</tt> - - -== Help and discussion - -RDocs for the current release are available at http://fakeweb.rubyforge.org. - -There's a mailing list for questions and discussion at -http://groups.google.com/group/fakeweb-users. - -The main source repository is http://github.com/chrisk/fakeweb. - -== Examples - -Start by requiring FakeWeb: - - require 'fakeweb' - -=== Registering basic string responses - - FakeWeb.register_uri(:get, "http://example.com/test1", :body => "Hello World!") - - Net::HTTP.get(URI.parse("http://example.com/test1")) - => "Hello World!" - - Net::HTTP.get(URI.parse("http://example.com/test2")) - => FakeWeb is bypassed and the response from a real request is returned - -You can also call <tt>register_uri</tt> with a regular expression, to match -more than one URI. - - FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "Hello World!") - - Net::HTTP.get(URI.parse("http://example.com/test3")) - => "Hello World!" - -=== Replaying a recorded response - - page = `curl -is http://www.google.com/` - FakeWeb.register_uri(:get, "http://www.google.com/", :response => page) - - Net::HTTP.get(URI.parse("http://www.google.com/")) - # => Full response, including headers - -=== Adding a custom status to the response - - FakeWeb.register_uri(:get, "http://example.com/", :body => "Nothing to be found 'round here", - :status => ["404", "Not Found"]) - - Net::HTTP.start("example.com") do |req| - response = req.get("/") - response.code # => "404" - response.message # => "Not Found" - response.body # => "Nothing to be found 'round here" - end - -=== Responding to any HTTP method - - FakeWeb.register_uri(:any, "http://example.com", :body => "response for any HTTP method") - -If you use the <tt>:any</tt> symbol, the URI you specify will be completely -stubbed out (regardless of the HTTP method of the request). This can be useful -for RPC-style services, where the HTTP method isn't significant. (Older -versions of FakeWeb always behaved like this, and didn't accept the first -+method+ argument above; this syntax is now deprecated.) - -=== Rotating responses - -You can optionally call <tt>FakeWeb.register_uri</tt> with an array of options -hashes; these are used, in order, to respond to repeated requests. Once you run -out of responses, further requests always receive the last response. (You can -also send a response more than once before rotating, by specifying a -<tt>:times</tt> option for that response.) - - FakeWeb.register_uri(:delete, "http://example.com/posts/1", - [{:body => "Post 1 deleted.", :status => ["200", "OK"]}, - {:body => "Post not found", :status => ["404", "Not Found"]}]) - - Net::HTTP.start("example.com") do |req| - req.delete("/posts/1").body # => "Post 1 deleted" - req.delete("/posts/1").body # => "Post not found" - req.delete("/posts/1").body # => "Post not found" - end - -=== Using HTTP basic authentication - -You can fake requests that use basic authentication by adding +userinfo+ strings -to your URIs: - - FakeWeb.register_uri(:get, "http://example.com/secret", :body => "Unauthorized", :status => ["401", "Unauthorized"]) - FakeWeb.register_uri(:get, "http://user:pass@example.com/secret", :body => "Authorized") - - Net::HTTP.start("example.com") do |http| - req = Net::HTTP::Get.new("/secret") - http.request(req) # => "Unauthorized" - req.basic_auth("user", "pass") - http.request(req) # => "Authorized" - end - -=== Clearing registered URIs - -The FakeWeb registry is a singleton that lasts for the duration of your program, -maintaining every fake response you register. If needed, you can clean out the -registry and remove all registered URIs: - - FakeWeb.clean_registry - -=== Blocking all real requests - -When you're using FakeWeb to replace _all_ of your requests, it's useful to -catch when requests are made for unregistered URIs (unlike the default -behavior, which is to pass those requests through to Net::HTTP as usual). - - FakeWeb.allow_net_connect = false - Net::HTTP.get(URI.parse("http://example.com/")) - => raises FakeWeb::NetConnectNotAllowedError - - FakeWeb.allow_net_connect = true - Net::HTTP.get(URI.parse("http://example.com/")) - => FakeWeb is bypassed and the response from a real request is returned - -It's recommended that you set <tt>FakeWeb.allow_net_connect = false</tt> in the -setup for your tests. - -==== Allowing requests to a specific server - -If you want to prevent your tests from hitting the internet while allowing -access to a specific server for integration testing, you can assign a URI or -+Regexp+ to be used as a whitelist for outbound requests: - - FakeWeb.allow_net_connect = %r[^https?://localhost] - Net::HTTP.get(URI.parse("http://localhost/path")) # => allowed - Net::HTTP.get(URI.parse("http://example.com/")) # => raises FakeWeb::NetConnectNotAllowedError - -=== Specifying HTTP response headers - -When you register a response using the <tt>:body</tt> option, you're only -setting the body of the response. If you want to add headers to these responses, -simply add the header as an option to +register_uri+: - - FakeWeb.register_uri(:get, "http://example.com/hello.txt", :body => "Hello", :content_type => "text/plain") - -This sets the "Content-Type" header in the response. - -=== Checking the last request - -It's often useful to retrieve the last request made by your code, so you can -write tests for its content. FakeWeb keeps track of the last request, whether it -was stubbed or not: - - Net::HTTP.get(URI.parse("http://example.com")) - FakeWeb.last_request # => Net::HTTP::Get request object - -== More info - -FakeWeb lets you decouple your test environment from live services without -modifying code or writing extensive stubs. - -In addition to the conceptual advantage of having idempotent request -behaviour, FakeWeb makes tests run faster than if they were made to remote (or -even local) web servers. It also makes it possible to run tests without a -network connection or in situations where the server is behind a firewall or -has host-based access controls. - -FakeWeb works with anything based on Net::HTTP--both higher-level wrappers, -like OpenURI, as well as a ton of libraries for popular web services. - - -== Known Issues - -* Request bodies are ignored, including PUT and POST parameters. If you need - different responses for different request bodies, you need to request - different URLs, and register different responses for each. (Query strings are - fully supported, though.) We're currently considering how the API should - change to add support for request bodies in 1.3.0. Your input would be really - helpful: see http://groups.google.com/group/fakeweb-users/browse_thread/thread/44d190a6b12e4273 - for a discussion of some different options. Thanks! diff --git a/vendor/gems/fakeweb-1.3.0/Rakefile b/vendor/gems/fakeweb-1.3.0/Rakefile deleted file mode 100644 index e3c5298c6..000000000 --- a/vendor/gems/fakeweb-1.3.0/Rakefile +++ /dev/null @@ -1,67 +0,0 @@ -require 'rubygems' -require 'rake' - -version = '1.3.0' - -begin - require 'jeweler' - Jeweler::Tasks.new do |gem| - gem.name = "fakeweb" - gem.rubyforge_project = "fakeweb" - gem.version = version - gem.summary = "A tool for faking responses to HTTP requests" - gem.description = "FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs." - gem.email = ["chris@kampers.net", "romeda@gmail.com"] - gem.authors = ["Chris Kampmeier", "Blaine Cook"] - gem.homepage = "http://github.com/chrisk/fakeweb" - gem.add_development_dependency "mocha", ">= 0.9.5" - end -rescue LoadError - puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" -end - - -require 'rake/testtask' -Rake::TestTask.new(:test) do |test| - test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb", "test/vendor") - test.libs << "test" - test.verbose = false - test.warning = true -end - -task :default => [:check_dependencies, :test] - - -begin - require 'rcov/rcovtask' - Rcov::RcovTask.new do |t| - t.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb", "test/vendor") - t.libs << "test" - t.rcov_opts << "--sort coverage" - t.rcov_opts << "--exclude gems" - t.warning = true - end -rescue LoadError - print "rcov support disabled " - if RUBY_PLATFORM =~ /java/ - puts "(running under JRuby)" - else - puts "(install RCov to enable the `rcov` task)" - end -end - - -begin - require 'sdoc' - require 'rdoc/task' - Rake::RDocTask.new do |rdoc| - rdoc.main = "README.rdoc" - rdoc.rdoc_files.include("README.rdoc", "CHANGELOG", "LICENSE.txt", "lib/*.rb") - rdoc.title = "FakeWeb #{version} API Documentation" - rdoc.rdoc_dir = "doc" - rdoc.template = "direct" - rdoc.options << "--line-numbers" << "--show-hash" << "--charset=utf-8" - end -rescue LoadError - puts "SDoc (or a dependency) not available. Install it with: gem install sdoc" -end diff --git a/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec b/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec deleted file mode 100644 index 39b23f001..000000000 --- a/vendor/gems/fakeweb-1.3.0/fakeweb.gemspec +++ /dev/null @@ -1,126 +0,0 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command -# -*- encoding: utf-8 -*- - -Gem::Specification.new do |s| - s.name = %q{fakeweb} - s.version = "1.3.0" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Chris Kampmeier", "Blaine Cook"] - s.date = %q{2010-08-22} - s.description = %q{FakeWeb is a helper for faking web requests in Ruby. It works at a global level, without modifying code or writing extensive stubs.} - s.email = ["chris@kampers.net", "romeda@gmail.com"] - s.extra_rdoc_files = [ - "LICENSE.txt", - "README.rdoc" - ] - s.files = [ - ".autotest", - ".gitignore", - "CHANGELOG", - "LICENSE.txt", - "README.rdoc", - "Rakefile", - "fakeweb.gemspec", - "lib/fake_web.rb", - "lib/fake_web/ext/net_http.rb", - "lib/fake_web/registry.rb", - "lib/fake_web/responder.rb", - "lib/fake_web/response.rb", - "lib/fake_web/stub_socket.rb", - "lib/fake_web/utility.rb", - "lib/fakeweb.rb", - "test/fixtures/google_response_from_curl", - "test/fixtures/google_response_with_transfer_encoding", - "test/fixtures/google_response_without_transfer_encoding", - "test/fixtures/test_example.txt", - "test/fixtures/test_txt_file", - "test/test_allow_net_connect.rb", - "test/test_deprecations.rb", - "test/test_fake_authentication.rb", - "test/test_fake_web.rb", - "test/test_fake_web_open_uri.rb", - "test/test_helper.rb", - "test/test_last_request.rb", - "test/test_missing_open_uri.rb", - "test/test_missing_pathname.rb", - "test/test_other_net_http_libraries.rb", - "test/test_precedence.rb", - "test/test_query_string.rb", - "test/test_regexes.rb", - "test/test_response_headers.rb", - "test/test_trailing_slashes.rb", - "test/test_utility.rb", - "test/vendor/right_http_connection-1.2.4/History.txt", - "test/vendor/right_http_connection-1.2.4/Manifest.txt", - "test/vendor/right_http_connection-1.2.4/README.txt", - "test/vendor/right_http_connection-1.2.4/Rakefile", - "test/vendor/right_http_connection-1.2.4/lib/net_fix.rb", - "test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb", - "test/vendor/right_http_connection-1.2.4/setup.rb", - "test/vendor/samuel-0.2.1/.document", - "test/vendor/samuel-0.2.1/.gitignore", - "test/vendor/samuel-0.2.1/LICENSE", - "test/vendor/samuel-0.2.1/README.rdoc", - "test/vendor/samuel-0.2.1/Rakefile", - "test/vendor/samuel-0.2.1/VERSION", - "test/vendor/samuel-0.2.1/lib/samuel.rb", - "test/vendor/samuel-0.2.1/lib/samuel/net_http.rb", - "test/vendor/samuel-0.2.1/lib/samuel/request.rb", - "test/vendor/samuel-0.2.1/samuel.gemspec", - "test/vendor/samuel-0.2.1/test/request_test.rb", - "test/vendor/samuel-0.2.1/test/samuel_test.rb", - "test/vendor/samuel-0.2.1/test/test_helper.rb", - "test/vendor/samuel-0.2.1/test/thread_test.rb" - ] - s.homepage = %q{http://github.com/chrisk/fakeweb} - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.rubyforge_project = %q{fakeweb} - s.rubygems_version = %q{1.3.7} - s.summary = %q{A tool for faking responses to HTTP requests} - s.test_files = [ - "test/test_allow_net_connect.rb", - "test/test_deprecations.rb", - "test/test_fake_authentication.rb", - "test/test_fake_web.rb", - "test/test_fake_web_open_uri.rb", - "test/test_helper.rb", - "test/test_last_request.rb", - "test/test_missing_open_uri.rb", - "test/test_missing_pathname.rb", - "test/test_other_net_http_libraries.rb", - "test/test_precedence.rb", - "test/test_query_string.rb", - "test/test_regexes.rb", - "test/test_response_headers.rb", - "test/test_trailing_slashes.rb", - "test/test_utility.rb", - "test/vendor/right_http_connection-1.2.4/lib/net_fix.rb", - "test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb", - "test/vendor/right_http_connection-1.2.4/setup.rb", - "test/vendor/samuel-0.2.1/lib/samuel/net_http.rb", - "test/vendor/samuel-0.2.1/lib/samuel/request.rb", - "test/vendor/samuel-0.2.1/lib/samuel.rb", - "test/vendor/samuel-0.2.1/test/request_test.rb", - "test/vendor/samuel-0.2.1/test/samuel_test.rb", - "test/vendor/samuel-0.2.1/test/test_helper.rb", - "test/vendor/samuel-0.2.1/test/thread_test.rb" - ] - - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q<mocha>, [">= 0.9.5"]) - else - s.add_dependency(%q<mocha>, [">= 0.9.5"]) - end - else - s.add_dependency(%q<mocha>, [">= 0.9.5"]) - end -end - diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb deleted file mode 100644 index 77fbdaec4..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web.rb +++ /dev/null @@ -1,215 +0,0 @@ -require 'singleton' - -require 'fake_web/ext/net_http' -require 'fake_web/registry' -require 'fake_web/response' -require 'fake_web/responder' -require 'fake_web/stub_socket' -require 'fake_web/utility' - -FakeWeb::Utility.record_loaded_net_http_replacement_libs -FakeWeb::Utility.puts_warning_for_net_http_around_advice_libs_if_needed - -module FakeWeb - - # Returns the version string for the copy of FakeWeb you have loaded. - VERSION = '1.3.0' - - # Resets the FakeWeb Registry. This will force all subsequent web requests to - # behave as real requests. - def self.clean_registry - Registry.instance.clean_registry - end - - # Enables or disables real HTTP connections for requests that don't match - # registered URIs. - # - # If you set <tt>FakeWeb.allow_net_connect = false</tt> and subsequently try - # to make a request to a URI you haven't registered with #register_uri, a - # NetConnectNotAllowedError will be raised. This is handy when you want to - # make sure your tests are self-contained, or want to catch the scenario - # when a URI is changed in implementation code without a corresponding test - # change. - # - # When <tt>FakeWeb.allow_net_connect = true</tt> (the default), requests to - # URIs not stubbed with FakeWeb are passed through to Net::HTTP. - # - # If you assign a +String+, +URI+, or +Regexp+ object, unstubbed requests - # will be allowed if they match that value. This is useful when you want to - # allow access to a local server for integration testing, while still - # preventing your tests from using the internet. - def self.allow_net_connect=(allowed) - case allowed - when String, URI, Regexp - @allow_all_connections = false - Registry.instance.register_passthrough_uri(allowed) - else - @allow_all_connections = allowed - Registry.instance.remove_passthrough_uri - end - end - - # Enable pass-through to Net::HTTP by default. - self.allow_net_connect = true - - # Returns +true+ if requests to URIs not registered with FakeWeb are passed - # through to Net::HTTP for normal processing (the default). Returns +false+ - # if an exception is raised for these requests. - # - # If you've assigned a +String+, +URI+, or +Regexp+ to - # <tt>FakeWeb.allow_net_connect=</tt>, you must supply a URI to check - # against that filter. Otherwise, an ArgumentError will be raised. - def self.allow_net_connect?(uri = nil) - if Registry.instance.passthrough_uri_map.any? - raise ArgumentError, "You must supply a URI to test" if uri.nil? - Registry.instance.passthrough_uri_matches?(uri) - else - @allow_all_connections - end - end - - # This exception is raised if you set <tt>FakeWeb.allow_net_connect = - # false</tt> and subsequently try to make a request to a URI you haven't - # stubbed. - class NetConnectNotAllowedError < StandardError; end; - - # This exception is raised if a Net::HTTP request matches more than one of - # the stubs you've registered. To fix the problem, remove a duplicate - # registration or disambiguate any regular expressions by making them more - # specific. - class MultipleMatchingURIsError < StandardError; end; - - # call-seq: - # FakeWeb.register_uri(method, uri, options) - # - # Register requests using the HTTP method specified by the symbol +method+ - # for +uri+ to be handled according to +options+. If you specify the method - # <tt>:any</tt>, the response will be reigstered for any request for +uri+. - # +uri+ can be a +String+, +URI+, or +Regexp+ object. +options+ must be either - # a +Hash+ or an +Array+ of +Hashes+ (see below), which must contain one of - # these two keys: - # - # <tt>:body</tt>:: - # A string which is used as the body of the response. If the string refers - # to a valid filesystem path, the contents of that file will be read and used - # as the body of the response instead. (This used to be two options, - # <tt>:string</tt> and <tt>:file</tt>, respectively. These are now deprecated.) - # <tt>:response</tt>:: - # Either a <tt>Net::HTTPResponse</tt>, an +IO+, or a +String+ which is used - # as the full response for the request. - # - # The easier way by far is to pass the <tt>:response</tt> option to - # +register_uri+ as a +String+ or an (open for reads) +IO+ object which - # will be used as the complete HTTP response, including headers and body. - # If the string points to a readable file, this file will be used as the - # content for the request. - # - # To obtain a complete response document, you can use the +curl+ command, - # like so: - # - # curl -i http://example.com > response_from_example.com - # - # which can then be used in your test environment like so: - # - # FakeWeb.register_uri(:get, "http://example.com", :response => "response_from_example.com") - # - # See the <tt>Net::HTTPResponse</tt> - # documentation[http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTPResponse.html] - # for more information on creating custom response objects. - # - # +options+ may also be an +Array+ containing a list of the above-described - # +Hash+. In this case, FakeWeb will rotate through each response. You can - # optionally repeat a response more than once before rotating: - # - # <tt>:times</tt>:: - # The number of times this response will be used before moving on to the - # next one. The last response will be repeated indefinitely, regardless of - # its <tt>:times</tt> parameter. - # - # Two optional arguments are also accepted: - # - # <tt>:status</tt>:: - # Passing <tt>:status</tt> as a two-value array will set the response code - # and message. The defaults are <tt>200</tt> and <tt>OK</tt>, respectively. - # Example: - # FakeWeb.register_uri(:get, "http://example.com", :body => "Go away!", :status => [404, "Not Found"]) - # <tt>:exception</tt>:: - # The argument passed via <tt>:exception</tt> will be raised when the - # specified URL is requested. Any +Exception+ class is valid. Example: - # FakeWeb.register_uri(:get, "http://example.com", :exception => Net::HTTPError) - # - # If you're using the <tt>:body</tt> response type, you can pass additional - # options to specify the HTTP headers to be used in the response. Example: - # - # FakeWeb.register_uri(:get, "http://example.com/index.txt", :body => "Hello", :content_type => "text/plain") - # - # You can also pass an array of header values to include a header in the - # response more than once: - # - # FakeWeb.register_uri(:get, "http://example.com", :set_cookie => ["name=value", "example=1"]) - def self.register_uri(*args) - case args.length - when 3 - Registry.instance.register_uri(*args) - when 2 - print_missing_http_method_deprecation_warning(*args) - Registry.instance.register_uri(:any, *args) - else - raise ArgumentError.new("wrong number of arguments (#{args.length} for 3)") - end - end - - # call-seq: - # FakeWeb.response_for(method, uri) - # - # Returns the faked Net::HTTPResponse object associated with +method+ and +uri+. - def self.response_for(*args, &block) #:nodoc: :yields: response - case args.length - when 2 - Registry.instance.response_for(*args, &block) - when 1 - print_missing_http_method_deprecation_warning(*args) - Registry.instance.response_for(:any, *args, &block) - else - raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)") - end - end - - # call-seq: - # FakeWeb.registered_uri?(method, uri) - # - # Returns true if a +method+ request for +uri+ is registered with FakeWeb. - # Specify a method of <tt>:any</tt> to check against all HTTP methods. - def self.registered_uri?(*args) - case args.length - when 2 - Registry.instance.registered_uri?(*args) - when 1 - print_missing_http_method_deprecation_warning(*args) - Registry.instance.registered_uri?(:any, *args) - else - raise ArgumentError.new("wrong number of arguments (#{args.length} for 2)") - end - end - - # Returns the request object from the last request made via Net::HTTP. - def self.last_request - @last_request - end - - def self.last_request=(request) #:nodoc: - @last_request = request - end - - private - - def self.print_missing_http_method_deprecation_warning(*args) - method = caller.first.match(/`(.*?)'/)[1] - new_args = args.map { |a| a.inspect }.unshift(":any") - new_args.last.gsub!(/^\{|\}$/, "").gsub!("=>", " => ") if args.last.is_a?(Hash) - $stderr.puts - $stderr.puts "Deprecation warning: FakeWeb requires an HTTP method argument (or use :any). Try this:" - $stderr.puts " FakeWeb.#{method}(#{new_args.join(', ')})" - $stderr.puts "Called at #{caller[1]}" - end -end diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb deleted file mode 100644 index 4ff3e9a10..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'net/http' -require 'net/https' -require 'stringio' - -module Net #:nodoc: all - - class BufferedIO - def initialize_with_fakeweb(io, debug_output = nil) - @read_timeout = 60 - @rbuf = '' - @debug_output = debug_output - - @io = case io - when Socket, OpenSSL::SSL::SSLSocket, IO - io - when String - if !io.include?("\0") && File.exists?(io) && !File.directory?(io) - File.open(io, "r") - else - StringIO.new(io) - end - end - raise "Unable to create local socket" unless @io - end - alias_method :initialize_without_fakeweb, :initialize - alias_method :initialize, :initialize_with_fakeweb - end - - class HTTP - class << self - def socket_type_with_fakeweb - FakeWeb::StubSocket - end - alias_method :socket_type_without_fakeweb, :socket_type - alias_method :socket_type, :socket_type_with_fakeweb - end - - def request_with_fakeweb(request, body = nil, &block) - FakeWeb.last_request = request - - uri = FakeWeb::Utility.request_uri_as_string(self, request) - method = request.method.downcase.to_sym - - if FakeWeb.registered_uri?(method, uri) - @socket = Net::HTTP.socket_type.new - FakeWeb::Utility.produce_side_effects_of_net_http_request(request, body) - FakeWeb.response_for(method, uri, &block) - elsif FakeWeb.allow_net_connect?(uri) - connect_without_fakeweb - request_without_fakeweb(request, body, &block) - else - uri = FakeWeb::Utility.strip_default_port_from_uri(uri) - raise FakeWeb::NetConnectNotAllowedError, - "Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}" - end - end - alias_method :request_without_fakeweb, :request - alias_method :request, :request_with_fakeweb - - - def connect_with_fakeweb - unless @@alredy_checked_for_net_http_replacement_libs ||= false - FakeWeb::Utility.puts_warning_for_net_http_replacement_libs_if_needed - @@alredy_checked_for_net_http_replacement_libs = true - end - nil - end - alias_method :connect_without_fakeweb, :connect - alias_method :connect, :connect_with_fakeweb - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb deleted file mode 100644 index 9a4a34e68..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/registry.rb +++ /dev/null @@ -1,127 +0,0 @@ -module FakeWeb - class Registry #:nodoc: - include Singleton - - attr_accessor :uri_map, :passthrough_uri_map - - def initialize - clean_registry - end - - def clean_registry - self.uri_map = Hash.new { |hash, key| hash[key] = {} } - end - - def register_uri(method, uri, options) - uri_map[normalize_uri(uri)][method] = [*[options]].flatten.collect do |option| - FakeWeb::Responder.new(method, uri, option, option[:times]) - end - end - - def registered_uri?(method, uri) - !responders_for(method, uri).empty? - end - - def response_for(method, uri, &block) - responders = responders_for(method, uri) - return nil if responders.empty? - - next_responder = responders.last - responders.each do |responder| - if responder.times and responder.times > 0 - responder.times -= 1 - next_responder = responder - break - end - end - - next_responder.response(&block) - end - - def register_passthrough_uri(uri) - self.passthrough_uri_map = {normalize_uri(uri) => {:any => true}} - end - - def remove_passthrough_uri - self.passthrough_uri_map = {} - end - - def passthrough_uri_matches?(uri) - uri = normalize_uri(uri) - uri_map_matches(passthrough_uri_map, :any, uri, URI) || - uri_map_matches(passthrough_uri_map, :any, uri, Regexp) - end - - private - - def responders_for(method, uri) - uri = normalize_uri(uri) - - uri_map_matches(uri_map, method, uri, URI) || - uri_map_matches(uri_map, :any, uri, URI) || - uri_map_matches(uri_map, method, uri, Regexp) || - uri_map_matches(uri_map, :any, uri, Regexp) || - [] - end - - def uri_map_matches(map, method, uri, type_to_check = URI) - uris_to_check = variations_of_uri_as_strings(uri) - - matches = map.select { |registered_uri, method_hash| - registered_uri.is_a?(type_to_check) && method_hash.has_key?(method) - }.select { |registered_uri, method_hash| - if type_to_check == URI - uris_to_check.include?(registered_uri.to_s) - elsif type_to_check == Regexp - uris_to_check.any? { |u| u.match(registered_uri) } - end - } - - if matches.size > 1 - raise MultipleMatchingURIsError, - "More than one registered URI matched this request: #{method.to_s.upcase} #{uri}" - end - - matches.map { |_, method_hash| method_hash[method] }.first - end - - - def variations_of_uri_as_strings(uri_object) - normalized_uri = normalize_uri(uri_object.dup) - normalized_uri_string = normalized_uri.to_s - - variations = [normalized_uri_string] - - # if the port is implied in the original, add a copy with an explicit port - if normalized_uri.default_port == normalized_uri.port - variations << normalized_uri_string.sub( - /#{Regexp.escape(normalized_uri.request_uri)}$/, - ":#{normalized_uri.port}#{normalized_uri.request_uri}") - end - - variations - end - - def normalize_uri(uri) - return uri if uri.is_a?(Regexp) - normalized_uri = - case uri - when URI then uri - when String - uri = 'http://' + uri unless uri.match('^https?://') - URI.parse(uri) - end - normalized_uri.query = sort_query_params(normalized_uri.query) - normalized_uri.normalize - end - - def sort_query_params(query) - if query.nil? || query.empty? - nil - else - query.split('&').sort.join('&') - end - end - - end -end diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb deleted file mode 100644 index 573fec3d4..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/responder.rb +++ /dev/null @@ -1,122 +0,0 @@ -module FakeWeb - class Responder #:nodoc: - - attr_accessor :method, :uri, :options, :times - KNOWN_OPTIONS = [:body, :exception, :response, :status].freeze - - def initialize(method, uri, options, times) - self.method = method - self.uri = uri - self.options = options - self.times = times ? times : 1 - - if options.has_key?(:file) || options.has_key?(:string) - print_file_string_options_deprecation_warning - options[:body] = options.delete(:file) || options.delete(:string) - end - end - - def response(&block) - if has_baked_response? - response = baked_response - else - code, msg = meta_information - response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) - response.instance_variable_set(:@body, body) - headers_extracted_from_options.each do |name, value| - if value.respond_to?(:each) - value.each { |v| response.add_field(name, v) } - else - response[name] = value - end - end - end - - response.instance_variable_set(:@read, true) - response.extend FakeWeb::Response - - optionally_raise(response) - - yield response if block_given? - - response - end - - private - - def headers_extracted_from_options - options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value| - [name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value] - } - end - - def body - return '' if options[:body].nil? - - options[:body] = options[:body].to_s if defined?(Pathname) && options[:body].is_a?(Pathname) - - if !options[:body].include?("\0") && File.exists?(options[:body]) && !File.directory?(options[:body]) - File.read(options[:body]) - else - options[:body] - end - end - - def baked_response - return options[:response] if options[:response].is_a?(Net::HTTPResponse) - - if options[:response].is_a?(String) || (defined?(Pathname) && options[:response].is_a?(Pathname)) - socket = Net::BufferedIO.new(options[:response].to_s) - r = Net::HTTPResponse.read_new(socket) - - # Store the original transfer-encoding - saved_transfer_encoding = r.instance_eval { - @header['transfer-encoding'] if @header.key?('transfer-encoding') - } - - # Read the body of response - r.instance_eval { @header['transfer-encoding'] = nil } - r.reading_body(socket, true) {} - - # Delete the transfer-encoding key from r.@header if there wasn't one; - # otherwise, restore the saved_transfer_encoding - if saved_transfer_encoding.nil? - r.instance_eval { @header.delete('transfer-encoding') } - else - r.instance_eval { @header['transfer-encoding'] = saved_transfer_encoding } - end - r - else - raise StandardError, "Handler unimplemented for response #{options[:response]}" - end - end - - def has_baked_response? - options.has_key?(:response) - end - - def optionally_raise(response) - return unless options.has_key?(:exception) - - case options[:exception].to_s - when "Net::HTTPError", "OpenURI::HTTPError" - raise options[:exception].new('Exception from FakeWeb', response) - else - raise options[:exception].new('Exception from FakeWeb') - end - end - - def meta_information - options.has_key?(:status) ? options[:status] : [200, 'OK'] - end - - def print_file_string_options_deprecation_warning - which = options.has_key?(:file) ? :file : :string - $stderr.puts - $stderr.puts "Deprecation warning: FakeWeb's :#{which} option has been renamed to :body." - $stderr.puts "Just replace :#{which} with :body in your FakeWeb.register_uri calls." - $stderr.puts "Called at #{caller[6]}" - end - - end -end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb deleted file mode 100644 index 41ba2557b..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/response.rb +++ /dev/null @@ -1,10 +0,0 @@ -module FakeWeb - module Response #:nodoc: - - def read_body(*args, &block) - yield @body if block_given? - @body - end - - end -end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb deleted file mode 100644 index 008681ca6..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/stub_socket.rb +++ /dev/null @@ -1,15 +0,0 @@ -module FakeWeb - class StubSocket #:nodoc: - - def initialize(*args) - end - - def closed? - @closed ||= true - end - - def readuntil(*args) - end - - end -end
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb b/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb deleted file mode 100644 index bd5d7161c..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fake_web/utility.rb +++ /dev/null @@ -1,87 +0,0 @@ -module FakeWeb - module Utility #:nodoc: - - def self.decode_userinfo_from_header(header) - header.sub(/^Basic /, "").unpack("m").first - end - - def self.encode_unsafe_chars_in_userinfo(userinfo) - unsafe_in_userinfo = /[^#{URI::REGEXP::PATTERN::UNRESERVED};&=+$,]|^(#{URI::REGEXP::PATTERN::ESCAPED})/ - userinfo.split(":").map { |part| uri_escape(part, unsafe_in_userinfo) }.join(":") - end - - def self.strip_default_port_from_uri(uri) - case uri - when %r{^http://} then uri.sub(%r{:80(/|$)}, '\1') - when %r{^https://} then uri.sub(%r{:443(/|$)}, '\1') - else uri - end - end - - # Returns a string with a normalized version of a Net::HTTP request's URI. - def self.request_uri_as_string(net_http, request) - protocol = net_http.use_ssl? ? "https" : "http" - - path = request.path - path = URI.parse(request.path).request_uri if request.path =~ /^http/ - - if request["authorization"] =~ /^Basic / - userinfo = FakeWeb::Utility.decode_userinfo_from_header(request["authorization"]) - userinfo = FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@" - else - userinfo = "" - end - - uri = "#{protocol}://#{userinfo}#{net_http.address}:#{net_http.port}#{path}" - end - - # Wrapper for URI escaping that switches between URI::Parser#escape and - # URI.escape for 1.9-compatibility - def self.uri_escape(*args) - if URI.const_defined?(:Parser) - URI::Parser.new.escape(*args) - else - URI.escape(*args) - end - end - - def self.produce_side_effects_of_net_http_request(request, body) - request.set_body_internal(body) - request.content_length = request.body.length unless request.body.nil? - end - - def self.puts_warning_for_net_http_around_advice_libs_if_needed - libs = {"Samuel" => defined?(Samuel)} - warnings = libs.select { |_, loaded| loaded }.map do |name, _| - <<-TEXT.gsub(/ {10}/, '') - \e[1mWarning: FakeWeb was loaded after #{name}\e[0m - * #{name}'s code is being ignored when a request is handled by FakeWeb, - because both libraries work by patching Net::HTTP. - * To fix this, just reorder your requires so that FakeWeb is before #{name}. - TEXT - end - $stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any? - end - - def self.record_loaded_net_http_replacement_libs - libs = {"RightHttpConnection" => defined?(RightHttpConnection)} - @loaded_net_http_replacement_libs = libs.map { |name, loaded| name if loaded }.compact - end - - def self.puts_warning_for_net_http_replacement_libs_if_needed - libs = {"RightHttpConnection" => defined?(RightHttpConnection)} - warnings = libs.select { |_, loaded| loaded }. - reject { |name, _| @loaded_net_http_replacement_libs.include?(name) }. - map do |name, _| - <<-TEXT.gsub(/ {10}/, '') - \e[1mWarning: #{name} was loaded after FakeWeb\e[0m - * FakeWeb's code is being ignored, because #{name} replaces parts of - Net::HTTP without deferring to other libraries. This will break Net::HTTP requests. - * To fix this, just reorder your requires so that #{name} is before FakeWeb. - TEXT - end - $stderr.puts "\n" + warnings.join("\n") + "\n" if warnings.any? - end - - end -end diff --git a/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb b/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb deleted file mode 100644 index 6982966bf..000000000 --- a/vendor/gems/fakeweb-1.3.0/lib/fakeweb.rb +++ /dev/null @@ -1,2 +0,0 @@ -# So you can require "fakeweb" instead of "fake_web" -require "fake_web"
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl deleted file mode 100644 index fe2fe3945..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_from_curl +++ /dev/null @@ -1,12 +0,0 @@ -HTTP/1.1 200 OK
-Cache-Control: private, max-age=0
-Date: Sun, 01 Feb 2009 02:16:24 GMT
-Expires: -1
-Content-Type: text/html; charset=ISO-8859-1
-Set-Cookie: PREF=ID=a6d9b5f5a4056dfe:TM=1233454584:LM=1233454584:S=U9pSwSu4eQwOPenX; expires=Tue, 01-Feb-2011 02:16:24 GMT; path=/; domain=.google.com
-Server: gws
-Transfer-Encoding: chunked
-
-<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; -window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"-AWFSZ6qFYuUswO9j5HIDQ",kEXPI:"17259,19547",kHL:"en"}; -google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CYhslHwSFSZH6LIHusAPEsc2eBfv77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QbUVlfOdxZw&num=1&sig=AGiWqtwRgqw8y_kza6RGKxBrCstaXkDJ7A&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html>
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding deleted file mode 100644 index 82025d36e..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_with_transfer_encoding +++ /dev/null @@ -1,17 +0,0 @@ -HTTP/1.1 200 OK -Cache-Control: private, max-age=0 -Date: Sun, 01 Feb 2009 01:54:36 GMT -Expires: -1 -Content-Type: text/html; charset=ISO-8859-1 -Set-Cookie: PREF=ID=4320bcaa30d097de:TM=1233453276:LM=1233453276:S=Eio39bg_nIabTxzL; expires=Tue, 01-Feb-2011 01:54:36 GMT; path=/; domain=.google.com -Server: gws -Transfer-Encoding: chunked - -fef -<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; -window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"3ACFSYC6EKTcswOL4_nBDQ",kEXPI:"17259,19463",kHL:"en"}; -google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http -a27 -://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=CFL7HzwCFSZCnCJSwsQPm842HB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_Q1sTewQNSbw&num=1&sig=AGiWqtyz-UiOD3EpsSp4k3n8A7zooeg48g&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgVLCswDjgELCswGDgDLA/L3N5xu59nDE.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html> -0 - diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding b/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding deleted file mode 100644 index 51433c990..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/fixtures/google_response_without_transfer_encoding +++ /dev/null @@ -1,11 +0,0 @@ -HTTP/1.0 200 OK -Cache-Control: private, max-age=0 -Date: Sun, 01 Feb 2009 01:55:33 GMT -Expires: -1 -Content-Type: text/html; charset=ISO-8859-1 -Set-Cookie: PREF=ID=3c140c3eb4c4f516:TM=1233453333:LM=1233453333:S=OH7sElk2hOWkb9ot; expires=Tue, 01-Feb-2011 01:55:33 GMT; path=/; domain=.google.com -Server: gws - -<html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Google</title><script>var _gjwl=location;function _gjuc(){var a=_gjwl.hash;if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var e=a.substring(d,b);if(e.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(e=="cad=h")return 0;c=b}_gjwl.href="search?"+a+"&cad=h";return 1}}return 0}; -window._gjuc && location.hash && _gjuc();</script><style>body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}#gbar{height:22px;padding-left:2px}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbi,#gbs{background:#fff;left:0;position:absolute;top:24px;visibility:hidden;z-index:1000}#gbi{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}#guser{padding-bottom:7px !important}#gbar,#guser{font-size:13px;padding-top:1px !important}@media all{.gb1,.gb3{height:22px;margin-right:.73em;vertical-align:top}#gbar{float:left}}.gb2{display:block;padding:.2em .5em}a.gb1,a.gb2,a.gb3{color:#00c !important}.gb2,.gb3{text-decoration:none}a.gb2:hover{background:#36c;color:#fff !important}</style><script>window.google={kEI:"FQGFSY2rG5eSswOKpsHeDQ",kEXPI:"17259",kHL:"en"}; -google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};window.gbar={};(function(){var b=window.gbar,f,h;b.qs=function(a){var c=window.encodeURIComponent&&(document.forms[0].q||"").value;if(c)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(i,g){return(g||"&")+"q="+encodeURIComponent(c)})};function j(a,c){a.visibility=h?"hidden":"visible";a.left=c+"px"}b.tg=function(a){a=a||window.event;var c=0,i,g=window.navExtra,d=document.getElementById("gbi"),e=a.target||a.srcElement;a.cancelBubble=true;if(!f){f=document.createElement(Array.every||window.createPopup?"iframe":"div");f.frameBorder="0";f.src="#";d.parentNode.appendChild(f).id="gbs";if(g)for(i in g)d.insertBefore(g[i],d.firstChild).className="gb2";document.onclick=b.close}if(e.className!="gb3")e=e.parentNode;do c+=e.offsetLeft;while(e=e.offsetParent);j(d.style,c);f.style.width=d.offsetWidth+"px";f.style.height=d.offsetHeight+"px";j(f.style,c);h=!h};b.close=function(a){h&&b.tg(a)}})();</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/nav_logo3.png'" topmargin=3 marginheight=3><div id=gbar><nobr><b class=gb1>Web</b> <a href="http://images.google.com/imghp?hl=en&tab=wi" onclick=gbar.qs(this) class=gb1>Images</a> <a href="http://maps.google.com/maps?hl=en&tab=wl" onclick=gbar.qs(this) class=gb1>Maps</a> <a href="http://news.google.com/nwshp?hl=en&tab=wn" onclick=gbar.qs(this) class=gb1>News</a> <a href="http://www.google.com/prdhp?hl=en&tab=wf" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href="http://mail.google.com/mail/?hl=en&tab=wm" class=gb1>Gmail</a> <a href="http://www.google.com/intl/en/options/" onclick="this.blur();gbar.tg(event);return !1" class=gb3><u>more</u> <small>▼</small></a><div id=gbi> <a href="http://video.google.com/?hl=en&tab=wv" onclick=gbar.qs(this) class=gb2>Video</a> <a href="http://groups.google.com/grphp?hl=en&tab=wg" onclick=gbar.qs(this) class=gb2>Groups</a> <a href="http://books.google.com/bkshp?hl=en&tab=wp" onclick=gbar.qs(this) class=gb2>Books</a> <a href="http://scholar.google.com/schhp?hl=en&tab=ws" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href="http://finance.google.com/finance?hl=en&tab=we" onclick=gbar.qs(this) class=gb2>Finance</a> <a href="http://blogsearch.google.com/?hl=en&tab=wb" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.youtube.com/?hl=en&tab=w1" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href="http://www.google.com/calendar/render?hl=en&tab=wc" class=gb2>Calendar</a> <a href="http://picasaweb.google.com/home?hl=en&tab=wq" onclick=gbar.qs(this) class=gb2>Photos</a> <a href="http://docs.google.com/?hl=en&tab=wo" class=gb2>Documents</a> <a href="http://www.google.com/reader/view/?hl=en&tab=wy" class=gb2>Reader</a> <a href="http://sites.google.com/?hl=en&tab=w3" class=gb2>Sites</a> <div class=gb2><div class=gbd></div></div> <a href="http://www.google.com/intl/en/options/" class=gb2>even more »</a></div> </nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><div align=right id=guser style="font-size:84%;padding:0 0 4px" width=100%><nobr><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg">iGoogle</a> | <a href="https://www.google.com/accounts/Login?continue=http://www.google.com/&hl=en">Sign in</a></nobr></div><center><br clear=all id=lgpd><img alt="Google" height=110 src="/intl/en_ALL/images/logo.gif" width=276><br><br><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input type=hidden name=ie value="ISO-8859-1"><input autocomplete="off" maxlength=2048 name=q size=55 title="Google Search" value=""><br><input name=btnG type=submit value="Google Search"><input name=btnI type=submit value="I'm Feeling Lucky"></td><td nowrap width=25%><font size=-2> <a href=/advanced_search?hl=en>Advanced Search</a><br> <a href=/preferences?hl=en>Preferences</a><br> <a href=/language_tools?hl=en>Language Tools</a></font></td></tr></table></form><br><font size=-1>Share what you know. <a href="/aclk?sa=L&ai=ClyBp_v-EScTWD4W2tQOxoqSkB_v77nqP3YC9CsHZnNkTEAEgwVRQypDftPn_____AWDJBqoECU_QphTjHaZ5QA&num=1&sig=AGiWqtwtBqZ-zra3DJd_1chQKhKGf7lMVg&q=http://knol.google.com">Write a Knol</a>.</font><br><br><br><font size=-1><a href="/intl/en/ads/">Advertising Programs</a> - <a href="/services/">Business Solutions</a> - <a href="/intl/en/about.html">About Google</a></font><p><font size=-2>©2009 - <a href="/intl/en/privacy.html">Privacy</a></font></p></center></body><script>if(google.y)google.y.first=[];window.setTimeout(function(){var xjs=document.createElement('script');xjs.src='/extern_js/f/CgJlbhICdXMgACswCjgNLCswDjgELCswGDgDLA/oTKXc0xdkmY.js';document.getElementsByTagName('head')[0].appendChild(xjs)},0);google.y.first.push(function(){google.ac.i(document.f,document.f.q,'','')})</script><script>function _gjp() {!(location.hash && _gjuc()) && setTimeout(_gjp, 500);}window._gjuc && _gjp();</script></html>
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt deleted file mode 100644 index 6310da9df..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_example.txt +++ /dev/null @@ -1 +0,0 @@ -test example content
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file b/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file deleted file mode 100644 index 8cf2f17fe..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/fixtures/test_txt_file +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3
\ No newline at end of file diff --git a/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb b/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb deleted file mode 100644 index 25f4d3d64..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_allow_net_connect.rb +++ /dev/null @@ -1,168 +0,0 @@ -require 'test_helper' - -class TestFakeWebAllowNetConnect < Test::Unit::TestCase - def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_true - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request - Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) - end - - def test_raises_for_unregistered_requests_when_allow_net_connect_is_false - FakeWeb.allow_net_connect = false - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com/")) - end - end - - def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_string - FakeWeb.allow_net_connect = "http://images.apple.com/main/rss/hotnews/hotnews.rss" - setup_expectations_for_real_apple_hot_news_request - Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) - end - - def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_string_with_default_port - FakeWeb.allow_net_connect = "http://images.apple.com:80/main/rss/hotnews/hotnews.rss" - setup_expectations_for_real_apple_hot_news_request - Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) - end - - def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_the_same_uri - FakeWeb.allow_net_connect = URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss") - setup_expectations_for_real_apple_hot_news_request - Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) - end - - def test_unregistered_requests_are_passed_through_when_allow_net_connect_is_a_matching_regexp - FakeWeb.allow_net_connect = %r[^http://images\.apple\.com] - setup_expectations_for_real_apple_hot_news_request - Net::HTTP.get(URI.parse("http://images.apple.com/main/rss/hotnews/hotnews.rss")) - end - - def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_different_string - FakeWeb.allow_net_connect = "http://example.com" - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com/path")) - end - end - - def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_different_uri - FakeWeb.allow_net_connect = URI.parse("http://example.com") - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com/path")) - end - end - - def test_raises_for_unregistered_requests_when_allow_net_connect_is_a_non_matching_regexp - FakeWeb.allow_net_connect = %r[example\.net] - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com")) - end - end - - def test_changing_allow_net_connect_from_string_to_false_corretly_removes_whitelist - FakeWeb.allow_net_connect = "http://example.com" - FakeWeb.allow_net_connect = false - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com")) - end - end - - def test_changing_allow_net_connect_from_true_to_string_corretly_limits_connections - FakeWeb.allow_net_connect = true - FakeWeb.allow_net_connect = "http://example.com" - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.net")) - end - end - - def test_exception_message_includes_unregistered_request_method_and_uri_but_no_default_port - FakeWeb.allow_net_connect = false - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.get(URI.parse("http://example.com/")) - end - assert exception.message.include?("GET http://example.com/") - - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - http = Net::HTTP.new("example.com", 443) - http.use_ssl = true - http.get("/") - end - assert exception.message.include?("GET https://example.com/") - end - - def test_exception_message_includes_unregistered_request_port_when_not_default - FakeWeb.allow_net_connect = false - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.start("example.com", 8000) { |http| http.get("/") } - end - assert exception.message.include?("GET http://example.com:8000/") - - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - http = Net::HTTP.new("example.com", 4433) - http.use_ssl = true - http.get("/") - end - assert exception.message.include?("GET https://example.com:4433/") - end - - def test_exception_message_includes_unregistered_request_port_when_not_default_with_path - FakeWeb.allow_net_connect = false - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.start("example.com", 8000) { |http| http.get("/test") } - end - assert exception.message.include?("GET http://example.com:8000/test") - - exception = assert_raise FakeWeb::NetConnectNotAllowedError do - http = Net::HTTP.new("example.com", 4433) - http.use_ssl = true - http.get("/test") - end - assert exception.message.include?("GET https://example.com:4433/test") - end - - def test_question_mark_method_returns_true_after_setting_allow_net_connect_to_true - FakeWeb.allow_net_connect = true - assert FakeWeb.allow_net_connect? - end - - def test_question_mark_method_returns_false_after_setting_allow_net_connect_to_false - FakeWeb.allow_net_connect = false - assert !FakeWeb.allow_net_connect? - end - - def test_question_mark_method_raises_with_no_argument_when_allow_net_connect_is_a_whitelist - FakeWeb.allow_net_connect = "http://example.com" - exception = assert_raise ArgumentError do - FakeWeb.allow_net_connect? - end - assert_equal "You must supply a URI to test", exception.message - end - - def test_question_mark_method_returns_true_when_argument_is_same_uri_as_allow_net_connect_string - FakeWeb.allow_net_connect = "http://example.com" - assert FakeWeb.allow_net_connect?("http://example.com/") - end - - def test_question_mark_method_returns_true_when_argument_matches_allow_net_connect_regexp - FakeWeb.allow_net_connect = %r[^https?://example.com/] - assert FakeWeb.allow_net_connect?("http://example.com/path") - assert FakeWeb.allow_net_connect?("https://example.com:443/") - end - - def test_question_mark_method_returns_false_when_argument_does_not_match_allow_net_connect_regexp - FakeWeb.allow_net_connect = %r[^http://example.com/] - assert !FakeWeb.allow_net_connect?("http://example.com:8080") - end -end - - -class TestFakeWebAllowNetConnectWithCleanState < Test::Unit::TestCase - # Our test_helper.rb sets allow_net_connect = false in an inherited #setup - # method. Disable that here to test the default setting. - def setup; end - def teardown; end - - def test_allow_net_connect_is_true_by_default - assert FakeWeb.allow_net_connect? - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb b/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb deleted file mode 100644 index e5b8953c5..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_deprecations.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'test_helper' - -class TestDeprecations < Test::Unit::TestCase - - def test_register_uri_without_method_argument_prints_deprecation_warning - warning = capture_stderr do - FakeWeb.register_uri("http://example.com", :body => "test") - end - assert_match %r(deprecation warning: fakeweb)i, warning - end - - def test_registered_uri_without_method_argument_prints_deprecation_warning - warning = capture_stderr do - FakeWeb.registered_uri?("http://example.com") - end - assert_match %r(deprecation warning: fakeweb)i, warning - end - - def test_response_for_without_method_argument_prints_deprecation_warning - warning = capture_stderr do - FakeWeb.response_for("http://example.com") - end - assert_match %r(deprecation warning: fakeweb)i, warning - end - - def test_register_uri_without_method_argument_prints_deprecation_warning_with_correct_caller - warning = capture_stderr do - FakeWeb.register_uri("http://example.com", :body => "test") - end - assert_match %r(Called at.*?test_deprecations\.rb)i, warning - end - - def test_register_uri_with_string_option_prints_deprecation_warning - warning = capture_stderr do - FakeWeb.register_uri(:get, "http://example.com", :string => "test") - end - assert_match %r(deprecation warning: fakeweb's :string option)i, warning - end - - def test_register_uri_with_file_option_prints_deprecation_warning - warning = capture_stderr do - FakeWeb.register_uri(:get, "http://example.com", :file => fixture_path("test_example.txt")) - end - assert_match %r(deprecation warning: fakeweb's :file option)i, warning - end - - def test_register_uri_with_string_option_prints_deprecation_warning_with_correct_caller - warning = capture_stderr do - FakeWeb.register_uri(:get, "http://example.com", :string => "test") - end - assert_match %r(Called at.*?test_deprecations\.rb)i, warning - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb deleted file mode 100644 index cff276441..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_fake_authentication.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'test_helper' - -class TestFakeAuthentication < Test::Unit::TestCase - - def test_register_uri_with_authentication - FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") - assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/test_example.txt') - end - - def test_register_uri_with_authentication_doesnt_trigger_without - FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") - assert !FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') - end - - def test_register_uri_with_authentication_doesnt_trigger_with_incorrect_credentials - FakeWeb.register_uri(:get, 'http://user:pass@mock/test_example.txt', :body => "example") - assert !FakeWeb.registered_uri?(:get, 'http://user:wrong@mock/test_example.txt') - end - - def test_unauthenticated_request - FakeWeb.register_uri(:get, 'http://mock/auth.txt', :body => 'unauthorized') - http = Net::HTTP.new('mock', 80) - req = Net::HTTP::Get.new('/auth.txt') - assert_equal 'unauthorized', http.request(req).body - end - - def test_authenticated_request - FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'authorized') - http = Net::HTTP.new('mock',80) - req = Net::HTTP::Get.new('/auth.txt') - req.basic_auth 'user', 'pass' - assert_equal 'authorized', http.request(req).body - end - - def test_authenticated_request_where_only_userinfo_differs - FakeWeb.register_uri(:get, 'http://user:pass@mock/auth.txt', :body => 'first user') - FakeWeb.register_uri(:get, 'http://user2:pass@mock/auth.txt', :body => 'second user') - http = Net::HTTP.new('mock') - req = Net::HTTP::Get.new('/auth.txt') - req.basic_auth 'user2', 'pass' - assert_equal 'second user', http.request(req).body - end - - def test_basic_auth_support_is_transparent_to_oauth - FakeWeb.register_uri(:get, "http://sp.example.com/protected", :body => "secret") - - # from http://oauth.net/core/1.0/#auth_header - auth_header = <<-HEADER - OAuth realm="http://sp.example.com/", - oauth_consumer_key="0685bd9184jfhq22", - oauth_token="ad180jjd733klru7", - oauth_signature_method="HMAC-SHA1", - oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", - oauth_timestamp="137131200", - oauth_nonce="4572616e48616d6d65724c61686176", - oauth_version="1.0" - HEADER - auth_header.gsub!(/\s+/, " ").strip! - - http = Net::HTTP.new("sp.example.com", 80) - response = nil - http.start do |request| - response = request.get("/protected", {"authorization" => auth_header}) - end - assert_equal "secret", response.body - end - - def test_basic_auth_when_userinfo_contains_allowed_unencoded_characters - FakeWeb.register_uri(:get, "http://roses&hel1o,(+$):so;longs=@example.com", :body => "authorized") - http = Net::HTTP.new("example.com") - request = Net::HTTP::Get.new("/") - request.basic_auth("roses&hel1o,(+$)", "so;longs=") - assert_equal "authorized", http.request(request).body - end - - def test_basic_auth_when_userinfo_contains_encoded_at_sign - FakeWeb.register_uri(:get, "http://user%40example.com:secret@example.com", :body => "authorized") - http = Net::HTTP.new("example.com") - request = Net::HTTP::Get.new("/") - request.basic_auth("user@example.com", "secret") - assert_equal "authorized", http.request(request).body - end - - def test_basic_auth_when_userinfo_contains_allowed_encoded_characters - FakeWeb.register_uri(:get, "http://us%20er:sec%20%2F%2Fret%3F@example.com", :body => "authorized") - http = Net::HTTP.new("example.com") - request = Net::HTTP::Get.new("/") - request.basic_auth("us er", "sec //ret?") - assert_equal "authorized", http.request(request).body - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb deleted file mode 100644 index c6e6b59eb..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_fake_web.rb +++ /dev/null @@ -1,590 +0,0 @@ -require 'test_helper' - -class TestFakeWeb < Test::Unit::TestCase - - def test_register_uri - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "example") - assert FakeWeb.registered_uri?(:get, 'http://mock/test_example.txt') - end - - def test_register_uri_with_wrong_number_of_arguments - assert_raises ArgumentError do - FakeWeb.register_uri("http://example.com") - end - assert_raises ArgumentError do - FakeWeb.register_uri(:get, "http://example.com", "/example", :body => "example") - end - end - - def test_registered_uri_with_wrong_number_of_arguments - assert_raises ArgumentError do - FakeWeb.registered_uri? - end - assert_raises ArgumentError do - FakeWeb.registered_uri?(:get, "http://example.com", "/example") - end - end - - def test_response_for_with_wrong_number_of_arguments - assert_raises ArgumentError do - FakeWeb.response_for - end - assert_raises ArgumentError do - FakeWeb.response_for(:get, "http://example.com", "/example") - end - end - - def test_register_uri_without_domain_name - assert_raises URI::InvalidURIError do - FakeWeb.register_uri(:get, 'test_example2.txt', fixture_path("test_example.txt")) - end - end - - def test_register_uri_with_port_and_check_with_port - FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com:3000/') - end - - def test_register_uri_with_port_and_check_without_port - FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'foo') - assert !FakeWeb.registered_uri?(:get, 'http://example.com/') - end - - def test_register_uri_with_default_port_for_http_and_check_without_port - FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com/') - end - - def test_register_uri_with_default_port_for_https_and_check_without_port - FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'https://example.com/') - end - - def test_register_uri_with_no_port_for_http_and_check_with_default_port - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com:80/') - end - - def test_register_uri_with_no_port_for_https_and_check_with_default_port - FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'https://example.com:443/') - end - - def test_register_uri_with_no_port_for_https_and_check_with_443_on_http - FakeWeb.register_uri(:get, 'https://example.com/', :body => 'foo') - assert !FakeWeb.registered_uri?(:get, 'http://example.com:443/') - end - - def test_register_uri_with_no_port_for_http_and_check_with_80_on_https - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') - assert !FakeWeb.registered_uri?(:get, 'https://example.com:80/') - end - - def test_register_uri_for_any_method_explicitly - FakeWeb.register_uri(:any, "http://example.com/rpc_endpoint", :body => "OK") - assert FakeWeb.registered_uri?(:get, "http://example.com/rpc_endpoint") - assert FakeWeb.registered_uri?(:post, "http://example.com/rpc_endpoint") - assert FakeWeb.registered_uri?(:put, "http://example.com/rpc_endpoint") - assert FakeWeb.registered_uri?(:delete, "http://example.com/rpc_endpoint") - assert FakeWeb.registered_uri?(:any, "http://example.com/rpc_endpoint") - capture_stderr do # silence deprecation warning - assert FakeWeb.registered_uri?("http://example.com/rpc_endpoint") - end - end - - def test_register_uri_for_get_method_only - FakeWeb.register_uri(:get, "http://example.com/users", :body => "User list") - assert FakeWeb.registered_uri?(:get, "http://example.com/users") - assert !FakeWeb.registered_uri?(:post, "http://example.com/users") - assert !FakeWeb.registered_uri?(:put, "http://example.com/users") - assert !FakeWeb.registered_uri?(:delete, "http://example.com/users") - assert !FakeWeb.registered_uri?(:any, "http://example.com/users") - capture_stderr do # silence deprecation warning - assert !FakeWeb.registered_uri?("http://example.com/users") - end - end - - def test_clean_registry_affects_registered_uri - FakeWeb.register_uri(:get, "http://example.com", :body => "registered") - assert FakeWeb.registered_uri?(:get, "http://example.com") - FakeWeb.clean_registry - assert !FakeWeb.registered_uri?(:get, "http://example.com") - end - - def test_clean_registry_affects_net_http_requests - FakeWeb.register_uri(:get, "http://example.com", :body => "registered") - response = Net::HTTP.start("example.com") { |query| query.get("/") } - assert_equal "registered", response.body - FakeWeb.clean_registry - assert_raise FakeWeb::NetConnectNotAllowedError do - Net::HTTP.start("example.com") { |query| query.get("/") } - end - end - - def test_response_for_with_registered_uri - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body - end - - def test_response_for_with_unknown_uri - assert_nil FakeWeb.response_for(:get, 'http://example.com/') - end - - def test_response_for_with_put_method - FakeWeb.register_uri(:put, "http://example.com", :body => "response") - assert_equal 'response', FakeWeb.response_for(:put, "http://example.com").body - end - - def test_response_for_with_any_method_explicitly - FakeWeb.register_uri(:any, "http://example.com", :body => "response") - assert_equal 'response', FakeWeb.response_for(:get, "http://example.com").body - assert_equal 'response', FakeWeb.response_for(:any, "http://example.com").body - end - - def test_content_for_registered_uri_with_port_and_request_with_port - FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'test example content') - response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } - assert_equal 'test example content', response.body - end - - def test_content_for_registered_uri_with_default_port_for_http_and_request_without_port - FakeWeb.register_uri(:get, 'http://example.com:80/', :body => 'test example content') - response = Net::HTTP.start('example.com') { |http| http.get('/') } - assert_equal 'test example content', response.body - end - - def test_content_for_registered_uri_with_no_port_for_http_and_request_with_default_port - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'test example content') - response = Net::HTTP.start('example.com', 80) { |http| http.get('/') } - assert_equal 'test example content', response.body - end - - def test_content_for_registered_uri_with_default_port_for_https_and_request_with_default_port - FakeWeb.register_uri(:get, 'https://example.com:443/', :body => 'test example content') - http = Net::HTTP.new('example.com', 443) - http.use_ssl = true - response = http.get('/') - assert_equal 'test example content', response.body - end - - def test_content_for_registered_uri_with_no_port_for_https_and_request_with_default_port - FakeWeb.register_uri(:get, 'https://example.com/', :body => 'test example content') - http = Net::HTTP.new('example.com', 443) - http.use_ssl = true - response = http.get('/') - assert_equal 'test example content', response.body - end - - def test_content_for_registered_uris_with_ports_on_same_domain_and_request_without_port - FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') - response = Net::HTTP.start('example.com') { |http| http.get('/') } - assert_equal 'port 80', response.body - end - - def test_content_for_registered_uris_with_ports_on_same_domain_and_request_with_port - FakeWeb.register_uri(:get, 'http://example.com:3000/', :body => 'port 3000') - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'port 80') - response = Net::HTTP.start('example.com', 3000) { |http| http.get('/') } - assert_equal 'port 3000', response.body - end - - def test_content_for_registered_uri_with_get_method_only - FakeWeb.allow_net_connect = false - FakeWeb.register_uri(:get, "http://example.com/", :body => "test example content") - http = Net::HTTP.new('example.com') - assert_equal 'test example content', http.get('/').body - assert_raises(FakeWeb::NetConnectNotAllowedError) { http.post('/', nil) } - assert_raises(FakeWeb::NetConnectNotAllowedError) { http.put('/', nil) } - assert_raises(FakeWeb::NetConnectNotAllowedError) { http.delete('/') } - end - - def test_content_for_registered_uri_with_any_method_explicitly - FakeWeb.allow_net_connect = false - FakeWeb.register_uri(:any, "http://example.com/", :body => "test example content") - http = Net::HTTP.new('example.com') - assert_equal 'test example content', http.get('/').body - assert_equal 'test example content', http.post('/', nil).body - assert_equal 'test example content', http.put('/', nil).body - assert_equal 'test example content', http.delete('/').body - end - - def test_content_for_registered_uri_with_any_method_implicitly - FakeWeb.allow_net_connect = false - capture_stderr do # silence deprecation warning - FakeWeb.register_uri("http://example.com/", :body => "test example content") - end - - http = Net::HTTP.new('example.com') - assert_equal 'test example content', http.get('/').body - assert_equal 'test example content', http.post('/', nil).body - assert_equal 'test example content', http.put('/', nil).body - assert_equal 'test example content', http.delete('/').body - end - - def test_mock_request_with_block - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } - assert_equal 'test example content', response.body - end - - def test_request_with_registered_body_yields_the_response_body_to_a_request_block - FakeWeb.register_uri(:get, "http://example.com", :body => "content") - body = nil - Net::HTTP.start("example.com") do |http| - http.get("/") do |response_body| - body = response_body - end - end - assert_equal "content", body - end - - def test_request_with_registered_response_yields_the_response_body_to_a_request_block - fake_response = Net::HTTPOK.new('1.1', '200', 'OK') - fake_response.instance_variable_set(:@body, "content") - FakeWeb.register_uri(:get, 'http://example.com', :response => fake_response) - body = nil - Net::HTTP.start("example.com") do |http| - http.get("/") do |response_body| - body = response_body - end - end - assert_equal "content", body - end - - def test_mock_request_with_undocumented_full_uri_argument_style - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt') } - assert_equal 'test example content', response.body - end - - def test_mock_request_with_undocumented_full_uri_argument_style_and_query - FakeWeb.register_uri(:get, 'http://mock/test_example.txt?a=b', :body => 'test query content') - response = Net::HTTP.start('mock') { |query| query.get('http://mock/test_example.txt?a=b') } - assert_equal 'test query content', response.body - end - - def test_mock_post - FakeWeb.register_uri(:post, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - response = Net::HTTP.start('mock') { |query| query.post('/test_example.txt', '') } - assert_equal 'test example content', response.body - end - - def test_mock_post_with_string_as_registered_uri - FakeWeb.register_uri(:post, 'http://mock/test_string.txt', :body => 'foo') - response = Net::HTTP.start('mock') { |query| query.post('/test_string.txt', '') } - assert_equal 'foo', response.body - end - - def test_mock_post_with_body_sets_the_request_body - FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"]) - http = Net::HTTP.new("example.com") - request = Net::HTTP::Post.new("/posts") - http.request(request, "title=Test") - assert_equal "title=Test", request.body - assert_equal 10, request.content_length - end - - def test_mock_post_with_body_using_other_syntax_sets_the_request_body - FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"]) - http = Net::HTTP.new("example.com") - request = Net::HTTP::Post.new("/posts") - request.body = "title=Test" - http.request(request) - assert_equal "title=Test", request.body - assert_equal 10, request.content_length - end - - def test_real_post_with_body_sets_the_request_body - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request :method => "POST", - :path => "/posts", :request_body => "title=Test" - http = Net::HTTP.new("images.apple.com") - request = Net::HTTP::Post.new("/posts") - request["Content-Type"] = "application/x-www-form-urlencoded" - http.request(request, "title=Test") - assert_equal "title=Test", request.body - assert_equal 10, request.content_length - end - - def test_mock_get_with_request_as_registered_uri - fake_response = Net::HTTPOK.new('1.1', '200', 'OK') - FakeWeb.register_uri(:get, 'http://mock/test_response', :response => fake_response) - response = Net::HTTP.start('mock') { |query| query.get('/test_response') } - assert_equal fake_response, response - end - - def test_mock_get_with_request_from_file_as_registered_uri - FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) - response = Net::HTTP.start('www.google.com') { |query| query.get('/') } - assert_equal '200', response.code - assert response.body.include?('<title>Google</title>') - end - - def test_mock_post_with_request_from_file_as_registered_uri - FakeWeb.register_uri(:post, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) - response = Net::HTTP.start('www.google.com') { |query| query.post('/', '') } - assert_equal "200", response.code - assert response.body.include?('<title>Google</title>') - end - - def test_proxy_request - FakeWeb.register_uri(:get, 'http://www.example.com/', :body => "hello world") - FakeWeb.register_uri(:get, 'http://your.proxy.host/', :body => "lala") - - response = nil - Net::HTTP::Proxy('your.proxy.host', 8080).start('www.example.com') do |http| - response = http.get('/') - end - assert_equal "hello world", response.body - end - - def test_https_request - FakeWeb.register_uri(:get, 'https://www.example.com/', :body => "Hello World") - http = Net::HTTP.new('www.example.com', 443) - http.use_ssl = true - response = http.get('/') - assert_equal "Hello World", response.body - end - - def test_register_unimplemented_response - FakeWeb.register_uri(:get, 'http://mock/unimplemented', :response => 1) - assert_raises StandardError do - Net::HTTP.start('mock') { |q| q.get('/unimplemented') } - end - end - - def test_specifying_nil_for_body - FakeWeb.register_uri(:head, "http://example.com", :body => nil) - response = Net::HTTP.start("example.com") { |query| query.head("/") } - assert_equal "", response.body - end - - def test_real_http_request - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request - - resp = nil - Net::HTTP.start('images.apple.com') do |query| - resp = query.get('/main/rss/hotnews/hotnews.rss') - end - assert resp.body.include?('Apple') - assert resp.body.include?('News') - end - - def test_real_http_request_with_undocumented_full_uri_argument_style - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request(:path => 'http://images.apple.com/main/rss/hotnews/hotnews.rss') - - resp = nil - Net::HTTP.start('images.apple.com') do |query| - resp = query.get('http://images.apple.com/main/rss/hotnews/hotnews.rss') - end - assert resp.body.include?('Apple') - assert resp.body.include?('News') - end - - def test_real_https_request - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request(:port => 443) - - http = Net::HTTP.new('images.apple.com', 443) - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE # silence certificate warning - response = http.get('/main/rss/hotnews/hotnews.rss') - assert response.body.include?('Apple') - assert response.body.include?('News') - end - - def test_real_request_on_same_domain_as_mock - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request - - FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') - - resp = nil - Net::HTTP.start('images.apple.com') do |query| - resp = query.get('/main/rss/hotnews/hotnews.rss') - end - assert resp.body.include?('Apple') - assert resp.body.include?('News') - end - - def test_mock_request_on_real_domain - FakeWeb.register_uri(:get, 'http://images.apple.com/test_string.txt', :body => 'foo') - resp = nil - Net::HTTP.start('images.apple.com') do |query| - resp = query.get('/test_string.txt') - end - assert_equal 'foo', resp.body - end - - def test_mock_post_that_raises_exception - FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => StandardError) - assert_raises(StandardError) do - Net::HTTP.start('mock') do |query| - query.post('/raising_exception.txt', 'some data') - end - end - end - - def test_mock_post_that_raises_an_http_error - FakeWeb.register_uri(:post, 'http://mock/raising_exception.txt', :exception => Net::HTTPError) - assert_raises(Net::HTTPError) do - Net::HTTP.start('mock') do |query| - query.post('/raising_exception.txt', '') - end - end - end - - def test_raising_an_exception_that_requires_an_argument_to_instantiate - FakeWeb.register_uri(:get, "http://example.com/timeout.txt", :exception => Timeout::Error) - assert_raises(Timeout::Error) do - Net::HTTP.get(URI.parse("http://example.com/timeout.txt")) - end - end - - def test_mock_instance_syntax - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - response = nil - uri = URI.parse('http://mock/test_example.txt') - http = Net::HTTP.new(uri.host, uri.port) - response = http.start do - http.get(uri.path) - end - - assert_equal 'test example content', response.body - end - - def test_mock_via_nil_proxy - response = nil - proxy_address = nil - proxy_port = nil - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - uri = URI.parse('http://mock/test_example.txt') - http = Net::HTTP::Proxy(proxy_address, proxy_port).new( - uri.host, (uri.port or 80)) - response = http.start do - http.get(uri.path) - end - - assert_equal 'test example content', response.body - end - - def test_response_type - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => "test") - response = Net::HTTP.start('mock') { |http| http.get('/test_example.txt') } - assert_kind_of Net::HTTPSuccess, response - end - - def test_mock_request_that_raises_an_http_error_with_a_specific_status - FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => Net::HTTPError, :status => ['404', 'Not Found']) - exception = assert_raises(Net::HTTPError) do - Net::HTTP.start('mock') { |http| http.get('/raising_exception.txt') } - end - assert_equal '404', exception.response.code - assert_equal 'Not Found', exception.response.msg - end - - def test_mock_rotate_responses - FakeWeb.register_uri(:get, 'http://mock/multiple_test_example.txt', - [ {:body => fixture_path("test_example.txt"), :times => 2}, - {:body => "thrice", :times => 3}, - {:body => "ever_more"} ]) - - uri = URI.parse('http://mock/multiple_test_example.txt') - 2.times { assert_equal 'test example content', Net::HTTP.get(uri) } - 3.times { assert_equal 'thrice', Net::HTTP.get(uri) } - 4.times { assert_equal 'ever_more', Net::HTTP.get(uri) } - end - - def test_mock_request_using_response_with_transfer_encoding_header_has_valid_transfer_encoding_header - FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_with_transfer_encoding")) - response = Net::HTTP.start('www.google.com') { |query| query.get('/') } - assert_not_nil response['transfer-encoding'] - assert response['transfer-encoding'] == 'chunked' - end - - def test_mock_request_using_response_without_transfer_encoding_header_does_not_have_a_transfer_encoding_header - FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_without_transfer_encoding")) - response = nil - response = Net::HTTP.start('www.google.com') { |query| query.get('/') } - assert !response.key?('transfer-encoding') - end - - def test_mock_request_using_response_from_curl_has_original_transfer_encoding_header - FakeWeb.register_uri(:get, 'http://www.google.com/', :response => fixture_path("google_response_from_curl")) - response = Net::HTTP.start('www.google.com') { |query| query.get('/') } - assert_not_nil response['transfer-encoding'] - assert response['transfer-encoding'] == 'chunked' - end - - def test_txt_file_should_have_three_lines - FakeWeb.register_uri(:get, 'http://www.google.com/', :body => fixture_path("test_txt_file")) - response = Net::HTTP.start('www.google.com') { |query| query.get('/') } - assert response.body.split(/\n/).size == 3, "response has #{response.body.split(/\n/).size} lines should have 3" - end - - def test_requiring_fakeweb_instead_of_fake_web - require "fakeweb" - end - - def test_registering_with_string_containing_null_byte - # Regression test for File.exists? raising an ArgumentError ("string - # contains null byte") since :response first tries to find by filename. - # The string should be treated as a response body, instead, and an - # EOFError is raised when the byte is encountered. - FakeWeb.register_uri(:get, "http://example.com", :response => "test\0test") - assert_raise EOFError do - Net::HTTP.get(URI.parse("http://example.com")) - end - - FakeWeb.register_uri(:get, "http://example.com", :body => "test\0test") - body = Net::HTTP.get(URI.parse("http://example.com")) - assert_equal "test\0test", body - end - - def test_registering_with_string_that_is_a_directory_name - # Similar to above, but for Errno::EISDIR being raised since File.exists? - # returns true for directories - FakeWeb.register_uri(:get, "http://example.com", :response => File.dirname(__FILE__)) - assert_raise EOFError do - body = Net::HTTP.get(URI.parse("http://example.com")) - end - - FakeWeb.register_uri(:get, "http://example.com", :body => File.dirname(__FILE__)) - body = Net::HTTP.get(URI.parse("http://example.com")) - assert_equal File.dirname(__FILE__), body - end - - def test_registering_with_a_body_pointing_to_a_pathname - path = Pathname.new(fixture_path("test_example.txt")) - FakeWeb.register_uri(:get, "http://example.com", :body => path) - response = Net::HTTP.start("example.com") { |http| http.get("/") } - assert_equal "test example content", response.body - end - - def test_registering_with_a_response_pointing_to_a_pathname - path = Pathname.new(fixture_path("google_response_without_transfer_encoding")) - FakeWeb.register_uri(:get, "http://google.com", :response => path) - response = Net::HTTP.start("google.com") { |http| http.get("/") } - assert response.body.include?("<title>Google</title>") - end - - def test_http_version_from_string_response - FakeWeb.register_uri(:get, "http://example.com", :body => "example") - response = Net::HTTP.start("example.com") { |http| http.get("/") } - assert_equal "1.0", response.http_version - end - - def test_http_version_from_file_response - FakeWeb.register_uri(:get, "http://example.com", :body => fixture_path("test_example.txt")) - response = Net::HTTP.start("example.com") { |http| http.get("/") } - assert_equal "1.0", response.http_version - end - - def test_version - assert_equal "1.3.0", FakeWeb::VERSION - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb b/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb deleted file mode 100644 index 699a64762..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_fake_web_open_uri.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'test_helper' - -class TestFakeWebOpenURI < Test::Unit::TestCase - - def test_content_for_registered_uri - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - assert_equal 'test example content', FakeWeb.response_for(:get, 'http://mock/test_example.txt').body - end - - def test_mock_open - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - assert_equal 'test example content', open('http://mock/test_example.txt').read - end - - def test_mock_open_with_string_as_registered_uri - FakeWeb.register_uri(:get, 'http://mock/test_string.txt', :body => 'foo') - assert_equal 'foo', open('http://mock/test_string.txt').string - end - - def test_real_open - FakeWeb.allow_net_connect = true - setup_expectations_for_real_apple_hot_news_request - resp = open('http://images.apple.com/main/rss/hotnews/hotnews.rss') - assert_equal "200", resp.status.first - body = resp.read - assert body.include?('Apple') - assert body.include?('News') - end - - def test_mock_open_that_raises_exception - FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => StandardError) - assert_raises(StandardError) do - open('http://mock/raising_exception.txt') - end - end - - def test_mock_open_that_raises_an_http_error - FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError) - assert_raises(OpenURI::HTTPError) do - open('http://mock/raising_exception.txt') - end - end - - def test_mock_open_that_raises_an_http_error_with_a_specific_status - FakeWeb.register_uri(:get, 'http://mock/raising_exception.txt', :exception => OpenURI::HTTPError, :status => ['123', 'jodel']) - exception = assert_raises(OpenURI::HTTPError) do - open('http://mock/raising_exception.txt') - end - assert_equal '123', exception.io.code - assert_equal 'jodel', exception.io.message - end - - def test_mock_open_with_block - FakeWeb.register_uri(:get, 'http://mock/test_example.txt', :body => fixture_path("test_example.txt")) - body = open('http://mock/test_example.txt') { |f| f.readlines } - assert_equal 'test example content', body.first - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_helper.rb b/vendor/gems/fakeweb-1.3.0/test/test_helper.rb deleted file mode 100644 index b181391b1..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_helper.rb +++ /dev/null @@ -1,90 +0,0 @@ -require 'test/unit' -require 'open-uri' -require 'pathname' -require 'fake_web' -require 'rbconfig' -require 'rubygems' -require 'mocha' - - -# Give all tests a common setup and teardown that prevents shared state -class Test::Unit::TestCase - alias setup_without_fakeweb setup - def setup - FakeWeb.clean_registry - @original_allow_net_connect = FakeWeb.allow_net_connect? - FakeWeb.allow_net_connect = false - end - - alias teardown_without_fakeweb teardown - def teardown - FakeWeb.allow_net_connect = @original_allow_net_connect - end -end - - -module FakeWebTestHelper - - def fixture_path(basename) - "test/fixtures/#{basename}" - end - - def capture_stderr - $stderr = StringIO.new - yield - $stderr.rewind && $stderr.read - ensure - $stderr = STDERR - end - - # The path to the current ruby interpreter. Adapted from Rake's FileUtils. - def ruby_path - ext = ((RbConfig::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ? "" : RbConfig::CONFIG['EXEEXT']) - File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + ext).sub(/.*\s.*/m, '"\&"') - end - - # Sets several expectations (using Mocha) that a real HTTP request makes it - # past FakeWeb to the socket layer. You can use this when you need to check - # that a request isn't handled by FakeWeb. - def setup_expectations_for_real_request(options = {}) - # Socket handling - if options[:port] == 443 - socket = mock("SSLSocket") - OpenSSL::SSL::SSLSocket.expects(:===).with(socket).returns(true).at_least_once - OpenSSL::SSL::SSLSocket.expects(:new).with(socket, instance_of(OpenSSL::SSL::SSLContext)).returns(socket).at_least_once - socket.stubs(:sync_close=).returns(true) - socket.expects(:connect).with().at_least_once - else - socket = mock("TCPSocket") - Socket.expects(:===).with(socket).at_least_once.returns(true) - end - - TCPSocket.expects(:open).with(options[:host], options[:port]).returns(socket).at_least_once - socket.stubs(:closed?).returns(false) - socket.stubs(:close).returns(true) - - # Request/response handling - request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"] - socket.expects(:write).with(all_of(includes(request_parts[0]), includes(request_parts[1]))).returns(100) - if !options[:request_body].nil? - socket.expects(:write).with(options[:request_body]).returns(100) - end - - read_method = RUBY_VERSION >= "1.9.2" ? :read_nonblock : :sysread - socket.expects(read_method).at_least_once.returns("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}").then.raises(EOFError) - end - - - # A helper that calls #setup_expectations_for_real_request for you, using - # defaults for our commonly used test request to images.apple.com. - def setup_expectations_for_real_apple_hot_news_request(options = {}) - defaults = { :host => "images.apple.com", :port => 80, :method => "GET", - :path => "/main/rss/hotnews/hotnews.rss", - :response_code => 200, :response_message => "OK", - :response_body => "<title>Apple Hot News</title>" } - setup_expectations_for_real_request(defaults.merge(options)) - end - -end - -Test::Unit::TestCase.send(:include, FakeWebTestHelper) diff --git a/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb b/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb deleted file mode 100644 index 7868c83a1..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_last_request.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'test_helper' - -class TestLastRequest < Test::Unit::TestCase - - def test_last_request_returns_correct_net_http_request_class - FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"]) - Net::HTTP.start("example.com") { |http| http.get("/") } - assert_instance_of Net::HTTP::Get, FakeWeb.last_request - end - - def test_last_request_has_correct_method_path_and_body_for_get - FakeWeb.register_uri(:get, "http://example.com", :status => [200, "OK"]) - Net::HTTP.start("example.com") { |http| http.get("/") } - assert_equal "GET", FakeWeb.last_request.method - assert_equal "/", FakeWeb.last_request.path - assert_nil FakeWeb.last_request.body - assert_nil FakeWeb.last_request.content_length - end - - def test_last_request_has_correct_method_path_and_body_for_post - FakeWeb.register_uri(:post, "http://example.com/posts", :status => [201, "Created"]) - Net::HTTP.start("example.com") { |http| http.post("/posts", "title=Test") } - assert_equal "POST", FakeWeb.last_request.method - assert_equal "/posts", FakeWeb.last_request.path - assert_equal "title=Test", FakeWeb.last_request.body - assert_equal 10, FakeWeb.last_request.content_length - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb b/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb deleted file mode 100644 index 029ba1cab..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_missing_open_uri.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'test_helper' - -class TestMissingOpenURI < Test::Unit::TestCase - - def setup - super - @saved_open_uri = OpenURI - Object.send(:remove_const, :OpenURI) - end - - def teardown - super - Object.const_set(:OpenURI, @saved_open_uri) - end - - - def test_register_using_exception_without_open_uri - # regression test for Responder needing OpenURI::HTTPError to be defined - FakeWeb.register_uri(:get, "http://example.com/", :exception => StandardError) - assert_raises(StandardError) do - Net::HTTP.start("example.com") { |http| http.get("/") } - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb b/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb deleted file mode 100644 index ee16a0d7b..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_missing_pathname.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'test_helper' - -class TestMissingPathname < Test::Unit::TestCase - - def setup - super - @saved_pathname = Pathname - Object.send(:remove_const, :Pathname) - end - - def teardown - super - Object.const_set(:Pathname, @saved_pathname) - end - - # FakeWeb supports using Pathname objects where filenames are expected, but - # Pathname isn't required to use FakeWeb. Make sure everything still works - # when Pathname isn't in use. - - def test_register_using_body_without_pathname - FakeWeb.register_uri(:get, "http://example.com/", :body => fixture_path("test_example.txt")) - Net::HTTP.start("example.com") { |http| http.get("/") } - end - - def test_register_using_response_without_pathname - FakeWeb.register_uri(:get, "http://example.com/", :response => fixture_path("google_response_without_transfer_encoding")) - Net::HTTP.start("example.com") { |http| http.get("/") } - end - - def test_register_using_unsupported_response_without_pathname - FakeWeb.register_uri(:get, "http://example.com/", :response => 1) - assert_raise StandardError do - Net::HTTP.start("example.com") { |http| http.get("/") } - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb b/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb deleted file mode 100644 index af7e5e276..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_other_net_http_libraries.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'test_helper' - -class TestOtherNetHttpLibraries < Test::Unit::TestCase - - def capture_output_from_requiring(libs, additional_code = "") - requires = libs.map { |lib| "require '#{lib}'" }.join("; ") - fakeweb_dir = "#{File.dirname(__FILE__)}/../lib" - vendor_dirs = Dir["#{File.dirname(__FILE__)}/vendor/*/lib"] - load_path_opts = vendor_dirs.unshift(fakeweb_dir).map { |dir| "-I#{dir}" }.join(" ") - - `#{ruby_path} #{load_path_opts} -e "#{requires}; #{additional_code}" 2>&1` - end - - def test_requiring_samuel_before_fakeweb_prints_warning - output = capture_output_from_requiring %w(samuel fakeweb) - assert_match %r(Warning: FakeWeb was loaded after Samuel), output - end - - def test_requiring_samuel_after_fakeweb_does_not_print_warning - output = capture_output_from_requiring %w(fakeweb samuel) - assert output.empty? - end - - def test_requiring_right_http_connection_before_fakeweb_and_then_connecting_does_not_print_warning - additional_code = "Net::HTTP.start('example.com')" - output = capture_output_from_requiring %w(right_http_connection fakeweb), additional_code - assert output.empty? - end - - def test_requiring_right_http_connection_after_fakeweb_and_then_connecting_prints_warning - additional_code = "Net::HTTP.start('example.com')" - output = capture_output_from_requiring %w(fakeweb right_http_connection), additional_code - assert_match %r(Warning: RightHttpConnection was loaded after FakeWeb), output - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb b/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb deleted file mode 100644 index 388b9f8a1..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_precedence.rb +++ /dev/null @@ -1,79 +0,0 @@ -require 'test_helper' - -class TestPrecedence < Test::Unit::TestCase - - def test_matching_get_strings_have_precedence_over_matching_get_regexes - FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") - FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "regex") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "string", response.body - end - - def test_matching_any_strings_have_precedence_over_matching_any_regexes - FakeWeb.register_uri(:any, "http://example.com/test", :body => "string") - FakeWeb.register_uri(:any, %r|http://example\.com/test|, :body => "regex") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "string", response.body - end - - def test_matching_get_strings_have_precedence_over_matching_any_strings - FakeWeb.register_uri(:get, "http://example.com/test", :body => "get method") - FakeWeb.register_uri(:any, "http://example.com/test", :body => "any method") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "get method", response.body - - # registration order should not matter - FakeWeb.register_uri(:any, "http://example.com/test2", :body => "any method") - FakeWeb.register_uri(:get, "http://example.com/test2", :body => "get method") - response = Net::HTTP.start("example.com") { |query| query.get('/test2') } - assert_equal "get method", response.body - end - - def test_matching_any_strings_have_precedence_over_matching_get_regexes - FakeWeb.register_uri(:any, "http://example.com/test", :body => "any string") - FakeWeb.register_uri(:get, %r|http://example\.com/test|, :body => "get regex") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "any string", response.body - end - - def test_registered_strings_and_uris_are_equivalent_so_second_takes_precedence - FakeWeb.register_uri(:get, "http://example.com/test", :body => "string") - FakeWeb.register_uri(:get, URI.parse("http://example.com/test"), :body => "uri") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "uri", response.body - - FakeWeb.register_uri(:get, URI.parse("http://example.com/test2"), :body => "uri") - FakeWeb.register_uri(:get, "http://example.com/test2", :body => "string") - response = Net::HTTP.start("example.com") { |query| query.get('/test2') } - assert_equal "string", response.body - end - - def test_identical_registration_replaces_previous_registration - FakeWeb.register_uri(:get, "http://example.com/test", :body => "first") - FakeWeb.register_uri(:get, "http://example.com/test", :body => "second") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "second", response.body - end - - def test_identical_registration_replaces_previous_registration_accounting_for_normalization - FakeWeb.register_uri(:get, "http://example.com/test?", :body => "first") - FakeWeb.register_uri(:get, "http://example.com:80/test", :body => "second") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "second", response.body - end - - def test_identical_registration_replaces_previous_registration_accounting_for_query_params - FakeWeb.register_uri(:get, "http://example.com/test?a=1&b=2", :body => "first") - FakeWeb.register_uri(:get, "http://example.com/test?b=2&a=1", :body => "second") - response = Net::HTTP.start("example.com") { |query| query.get('/test?a=1&b=2') } - assert_equal "second", response.body - end - - def test_identical_registration_replaces_previous_registration_with_regexes - FakeWeb.register_uri(:get, /test/, :body => "first") - FakeWeb.register_uri(:get, /test/, :body => "second") - response = Net::HTTP.start("example.com") { |query| query.get('/test') } - assert_equal "second", response.body - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb b/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb deleted file mode 100644 index 11a211848..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_query_string.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'test_helper' - -class TestFakeWebQueryString < Test::Unit::TestCase - - def test_register_uri_string_with_query_params - FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com/?a=1&b=1') - - FakeWeb.register_uri(:post, URI.parse("http://example.org/?a=1&b=1"), :body => "foo") - assert FakeWeb.registered_uri?(:post, "http://example.org/?a=1&b=1") - end - - def test_register_uri_with_query_params_and_check_in_different_order - FakeWeb.register_uri(:get, 'http://example.com/?a=1&b=1', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com/?b=1&a=1') - - FakeWeb.register_uri(:post, URI.parse('http://example.org/?a=1&b=1'), :body => 'foo') - assert FakeWeb.registered_uri?(:post, 'http://example.org/?b=1&a=1') - end - - def test_registered_uri_gets_recognized_with_empty_query_params - FakeWeb.register_uri(:get, 'http://example.com/', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com/?') - - FakeWeb.register_uri(:post, URI.parse('http://example.org/'), :body => 'foo') - assert FakeWeb.registered_uri?(:post, 'http://example.org/?') - end - - def test_register_uri_with_empty_query_params_and_check_with_none - FakeWeb.register_uri(:get, 'http://example.com/?', :body => 'foo') - assert FakeWeb.registered_uri?(:get, 'http://example.com/') - - FakeWeb.register_uri(:post, URI.parse('http://example.org/?'), :body => 'foo') - assert FakeWeb.registered_uri?(:post, 'http://example.org/') - end - - def test_registry_sort_query_params - assert_equal "a=1&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "b=2&a=1") - end - - def test_registry_sort_query_params_sorts_by_value_if_keys_collide - assert_equal "a=1&a=2&b=2", FakeWeb::Registry.instance.send(:sort_query_params, "a=2&b=2&a=1") - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb b/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb deleted file mode 100644 index e2eba1db8..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_regexes.rb +++ /dev/null @@ -1,157 +0,0 @@ -require 'test_helper' - -class TestRegexes < Test::Unit::TestCase - - def test_registered_uri_with_pattern - FakeWeb.register_uri(:get, %r|http://example.com/test_example/\d+|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://example.com/test_example/25") - assert !FakeWeb.registered_uri?(:get, "http://example.com/test_example/abc") - end - - def test_response_for_with_matching_registered_uri - FakeWeb.register_uri(:get, %r|http://www.google.com|, :body => "Welcome to Google!") - assert_equal "Welcome to Google!", FakeWeb.response_for(:get, "http://www.google.com").body - end - - def test_response_for_with_matching_registered_uri_and_get_method_matching_to_any_method - FakeWeb.register_uri(:any, %r|http://www.example.com|, :body => "example") - assert_equal "example", FakeWeb.response_for(:get, "http://www.example.com").body - end - - def test_registered_uri_with_authentication_and_pattern - FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") - assert FakeWeb.registered_uri?(:get, 'http://user:pass@mock/example.txt') - end - - def test_registered_uri_with_authentication_and_pattern_handles_case_insensitivity - FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") - assert FakeWeb.registered_uri?(:get, 'http://uSeR:PAss@mock/example.txt') - end - - def test_request_with_authentication_and_pattern_handles_case_insensitivity - FakeWeb.register_uri(:get, %r|http://user:pass@mock/example\.\w+|i, :body => "example") - http = Net::HTTP.new('mock', 80) - req = Net::HTTP::Get.new('/example.txt') - req.basic_auth 'uSeR', 'PAss' - assert_equal "example", http.request(req).body - end - - def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error - FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") - FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") - assert_raise FakeWeb::MultipleMatchingURIsError do - Net::HTTP.start("example.com") { |query| query.get('/a') } - end - end - - def test_requesting_a_uri_that_matches_two_registered_regexes_raises_an_error_including_request_info - FakeWeb.register_uri(:get, %r|http://example\.com/|, :body => "first") - FakeWeb.register_uri(:get, %r|http://example\.com/a|, :body => "second") - begin - Net::HTTP.start("example.com") { |query| query.get('/a') } - rescue FakeWeb::MultipleMatchingURIsError => exception - end - assert exception.message.include?("GET http://example.com/a") - end - - def test_registry_does_not_find_using_mismatched_protocols_or_ports_when_registered_with_both - FakeWeb.register_uri(:get, %r|http://www.example.com:80|, :body => "example") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com:80") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443") - end - - def test_registry_finds_using_non_default_port - FakeWeb.register_uri(:get, %r|example\.com:8080|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:8080/path") - assert FakeWeb.registered_uri?(:get, "https://www.example.com:8080/path") - end - - def test_registry_finds_using_default_port_and_http_when_registered_with_explicit_port_80 - FakeWeb.register_uri(:get, %r|example\.com:80|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://www.example.com/path") - - # check other permutations, too - assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/path") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:8080/path") - assert FakeWeb.registered_uri?(:get, "https://www.example.com:80/path") - assert FakeWeb.registered_uri?(:get, "https://www.example.com:8080/path") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com/path") - end - - def test_registry_finds_using_default_port_and_https_when_registered_with_explicit_port_443 - FakeWeb.register_uri(:get, %r|example\.com:443|, :body => "example") - assert FakeWeb.registered_uri?(:get, "https://www.example.com/path") - - # check other permutations, too - assert FakeWeb.registered_uri?(:get, "https://www.example.com:443/path") - assert FakeWeb.registered_uri?(:get, "https://www.example.com:44321/path") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:443/path") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:44321/path") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com/path") - end - - def test_registry_only_finds_using_default_port_when_registered_without_if_protocol_matches - FakeWeb.register_uri(:get, %r|http://www.example.com/test|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/test") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443/test") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443/test") - FakeWeb.register_uri(:get, %r|https://www.example.org/test|, :body => "example") - assert FakeWeb.registered_uri?(:get, "https://www.example.org:443/test") - assert !FakeWeb.registered_uri?(:get, "https://www.example.org:80/test") - assert !FakeWeb.registered_uri?(:get, "http://www.example.org:80/test") - end - - def test_registry_matches_using_mismatched_port_when_registered_without - FakeWeb.register_uri(:get, %r|http://www.example.com|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:80") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:443") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:12345") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com:443") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com") - end - - def test_registry_matches_using_default_port_for_protocol_when_registered_without_protocol_or_port - FakeWeb.register_uri(:get, %r|www.example.com/home|, :body => "example") - assert FakeWeb.registered_uri?(:get, "http://www.example.com/home") - assert FakeWeb.registered_uri?(:get, "https://www.example.com/home") - assert FakeWeb.registered_uri?(:get, "http://www.example.com:80/home") - assert FakeWeb.registered_uri?(:get, "https://www.example.com:443/home") - assert !FakeWeb.registered_uri?(:get, "https://www.example.com:80/home") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com:443/home") - end - - def test_registry_matches_with_query_params - FakeWeb.register_uri(:get, %r[example.com/list\?(.*&|)important=1], :body => "example") - assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=1&unimportant=2") - assert FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=12&unimportant=2") - assert FakeWeb.registered_uri?(:get, "http://example.com/list?important=1&unimportant=2") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?important=2&unimportant=1") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?hash=123&important=2&unimportant=1") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?notimportant=1&unimportant=1") - end - - def test_registry_does_not_match_when_regex_has_unsorted_query_params - FakeWeb.register_uri(:get, %r[example\.com/list\?b=2&a=1], :body => "example") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?b=2&a=1") - assert !FakeWeb.registered_uri?(:get, "http://example.com/list?a=1&b=2") - assert !FakeWeb.registered_uri?(:get, "https://example.com:443/list?b=2&a=1") - end - - def test_registry_matches_when_regex_has_sorted_query_params - FakeWeb.register_uri(:get, %r[example\.com/list\?a=1&b=2], :body => "example") - assert FakeWeb.registered_uri?(:get, "http://example.com/list?b=2&a=1") - assert FakeWeb.registered_uri?(:get, "http://example.com/list?a=1&b=2") - assert FakeWeb.registered_uri?(:get, "https://example.com:443/list?b=2&a=1") - end - - def test_registry_matches_quickly_with_lots_of_query_params - # regression test for code that tried to calculate the permutations of the - # query params, which hangs with a large number of params - FakeWeb.register_uri(:get, %r[example.com], :body => "example") - Timeout::timeout(1) do - FakeWeb.registered_uri?(:get, "http://example.com/?a=1&b=2&c=3&d=4&e=5&f=6&g=7&h=8") - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb b/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb deleted file mode 100644 index 45f3f5a99..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_response_headers.rb +++ /dev/null @@ -1,79 +0,0 @@ -require 'test_helper' - -class TestResponseHeaders < Test::Unit::TestCase - def test_content_type_when_registering_with_string_and_content_type_header_as_symbol_option - FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]', :content_type => "application/json") - response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } - assert_equal '[{"username": "chrisk"}]', response.body - assert_equal "application/json", response['Content-Type'] - end - - def test_content_type_when_registering_with_string_and_content_type_header_as_string_option - FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]', 'Content-Type' => "application/json") - response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } - assert_equal "application/json", response['Content-Type'] - end - - def test_content_type_when_registering_with_string_only - FakeWeb.register_uri(:get, "http://example.com/users.json", :body => '[{"username": "chrisk"}]') - response = Net::HTTP.start("example.com") { |query| query.get("/users.json") } - assert_equal '[{"username": "chrisk"}]', response.body - assert_nil response['Content-Type'] - end - - def test_cookies_when_registering_with_file_and_set_cookie_header - FakeWeb.register_uri(:get, "http://example.com/", :body => fixture_path("test_example.txt"), - :set_cookie => "user_id=1; example=yes") - response = Net::HTTP.start("example.com") { |query| query.get("/") } - assert_equal "test example content", response.body - assert_equal "user_id=1; example=yes", response['Set-Cookie'] - end - - def test_multiple_set_cookie_headers - FakeWeb.register_uri(:get, "http://example.com", :set_cookie => ["user_id=1", "example=yes"]) - response = Net::HTTP.start("example.com") { |query| query.get("/") } - assert_equal ["user_id=1", "example=yes"], response.get_fields('Set-Cookie') - assert_equal "user_id=1, example=yes", response['Set-Cookie'] - end - - def test_registering_with_baked_response_ignores_header_options - fake_response = Net::HTTPOK.new('1.1', '200', 'OK') - fake_response["Server"] = "Apache/1.3.27 (Unix)" - FakeWeb.register_uri(:get, "http://example.com/", :response => fake_response, - :server => "FakeWeb/1.2.3 (Ruby)") - response = Net::HTTP.start("example.com") { |query| query.get("/") } - assert_equal "200", response.code - assert_equal "OK", response.message - assert_equal "Apache/1.3.27 (Unix)", response["Server"] - end - - def test_headers_are_rotated_when_registering_with_response_rotation - FakeWeb.register_uri(:get, "http://example.com", - [{:body => 'test1', :expires => "Thu, 14 Jun 2009 16:00:00 GMT", - :content_type => "text/plain"}, - {:body => 'test2', :expires => "Thu, 14 Jun 2009 16:00:01 GMT"}]) - - first_response = second_response = nil - Net::HTTP.start("example.com") do |query| - first_response = query.get("/") - second_response = query.get("/") - end - assert_equal 'test1', first_response.body - assert_equal "Thu, 14 Jun 2009 16:00:00 GMT", first_response['Expires'] - assert_equal "text/plain", first_response['Content-Type'] - assert_equal 'test2', second_response.body - assert_equal "Thu, 14 Jun 2009 16:00:01 GMT", second_response['Expires'] - assert_nil second_response['Content-Type'] - end - - def test_registering_with_status_option_and_response_headers - FakeWeb.register_uri(:get, "http://example.com", :status => ["301", "Moved Permanently"], - :location => "http://www.example.com") - - response = Net::HTTP.start("example.com") { |query| query.get("/") } - assert_equal "301", response.code - assert_equal "Moved Permanently", response.message - assert_equal "http://www.example.com", response["Location"] - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb b/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb deleted file mode 100644 index 564d807dc..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_trailing_slashes.rb +++ /dev/null @@ -1,53 +0,0 @@ -require 'test_helper' - -class TestFakeWebTrailingSlashes < Test::Unit::TestCase - - def test_registering_root_without_slash_and_ask_predicate_method_with_slash - FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") - assert FakeWeb.registered_uri?(:get, "http://www.example.com/") - end - - def test_registering_root_without_slash_and_request - FakeWeb.register_uri(:get, "http://www.example.com", :body => "root") - response = Net::HTTP.start("www.example.com") { |query| query.get('/') } - assert_equal "root", response.body - end - - def test_registering_root_with_slash_and_ask_predicate_method_without_slash - FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") - assert FakeWeb.registered_uri?(:get, "http://www.example.com") - end - - def test_registering_root_with_slash_and_request - FakeWeb.register_uri(:get, "http://www.example.com/", :body => "root") - response = Net::HTTP.start("www.example.com") { |query| query.get('/') } - assert_equal "root", response.body - end - - def test_registering_path_without_slash_and_ask_predicate_method_with_slash - FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users/") - end - - def test_registering_path_without_slash_and_request_with_slash - FakeWeb.allow_net_connect = false - FakeWeb.register_uri(:get, "http://www.example.com/users", :body => "User list") - assert_raise FakeWeb::NetConnectNotAllowedError do - response = Net::HTTP.start("www.example.com") { |query| query.get('/users/') } - end - end - - def test_registering_path_with_slash_and_ask_predicate_method_without_slash - FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") - assert !FakeWeb.registered_uri?(:get, "http://www.example.com/users") - end - - def test_registering_path_with_slash_and_request_without_slash - FakeWeb.allow_net_connect = false - FakeWeb.register_uri(:get, "http://www.example.com/users/", :body => "User list") - assert_raise FakeWeb::NetConnectNotAllowedError do - response = Net::HTTP.start("www.example.com") { |query| query.get('/users') } - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/test_utility.rb b/vendor/gems/fakeweb-1.3.0/test/test_utility.rb deleted file mode 100644 index 891de875b..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/test_utility.rb +++ /dev/null @@ -1,83 +0,0 @@ -require 'test_helper' - -class TestUtility < Test::Unit::TestCase - - def test_decode_userinfo_from_header_handles_basic_auth - authorization_header = "Basic dXNlcm5hbWU6c2VjcmV0" - userinfo = FakeWeb::Utility.decode_userinfo_from_header(authorization_header) - assert_equal "username:secret", userinfo - end - - def test_encode_unsafe_chars_in_userinfo_does_not_encode_userinfo_safe_punctuation - userinfo = "user;&=+$,:secret" - assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) - end - - def test_encode_unsafe_chars_in_userinfo_does_not_encode_rfc_3986_unreserved_characters - userinfo = "-_.!~*'()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:secret" - assert_equal userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) - end - - def test_encode_unsafe_chars_in_userinfo_does_encode_other_characters - userinfo, safe_userinfo = 'us#rn@me:sec//ret?"', 'us%23rn%40me:sec%2F%2Fret%3F%22' - assert_equal safe_userinfo, FakeWeb::Utility.encode_unsafe_chars_in_userinfo(userinfo) - end - - def test_strip_default_port_from_uri_strips_80_from_http_with_path - uri = "http://example.com:80/foo/bar" - stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) - assert_equal "http://example.com/foo/bar", stripped_uri - end - - def test_strip_default_port_from_uri_strips_80_from_http_without_path - uri = "http://example.com:80" - stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) - assert_equal "http://example.com", stripped_uri - end - - def test_strip_default_port_from_uri_strips_443_from_https_without_path - uri = "https://example.com:443" - stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) - assert_equal "https://example.com", stripped_uri - end - - def test_strip_default_port_from_uri_strips_443_from_https - uri = "https://example.com:443/foo/bar" - stripped_uri = FakeWeb::Utility.strip_default_port_from_uri(uri) - assert_equal "https://example.com/foo/bar", stripped_uri - end - - def test_strip_default_port_from_uri_does_not_strip_8080_from_http - uri = "http://example.com:8080/foo/bar" - assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) - end - - def test_strip_default_port_from_uri_does_not_strip_443_from_http - uri = "http://example.com:443/foo/bar" - assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) - end - - def test_strip_default_port_from_uri_does_not_strip_80_from_query_string - uri = "http://example.com/?a=:80&b=c" - assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) - end - - def test_strip_default_port_from_uri_does_not_modify_strings_that_do_not_start_with_http_or_https - uri = "httpz://example.com:80/" - assert_equal uri, FakeWeb::Utility.strip_default_port_from_uri(uri) - end - - def test_request_uri_as_string - http = Net::HTTP.new("www.example.com", 80) - request = Net::HTTP::Get.new("/index.html") - expected = "http://www.example.com:80/index.html" - assert_equal expected, FakeWeb::Utility.request_uri_as_string(http, request) - end - - def test_uri_escape_delegates_to_uri_parser_when_available - parsing_object = URI.const_defined?(:Parser) ? URI::Parser.any_instance : URI - parsing_object.expects(:escape).with("string", /unsafe/).returns("escaped") - assert_equal "escaped", FakeWeb::Utility.uri_escape("string", /unsafe/) - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt deleted file mode 100644 index e06bcd0a2..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/History.txt +++ /dev/null @@ -1,59 +0,0 @@ -== 0.0.1 2007-05-15 -* 1 major enhancement: - * Initial release - -== 0.1.2 2007-06-27 - -* No major changes. - -== 0.1.3 2007-07-09 - -* No change. - -== 0.1.4 2007-08-10 - -* r1442, todd, 2007-08-07 15:45:24 - * # 373, Add support in right_http_connection for bailing out to a block while - reading the HTTP response (to support GET streaming...) - -* r1411, todd, 2007-08-03 15:14:45 - * # 373, Stream uploads (PUTs) if the source is a file, stream, or anything - read()-able - -== 1.1.0 2007-08-15 -Initial public release - -== 1.2.0 2007-10-05 - -* r1867, konstantin, 2007-10-05 06:19:45 - * # 220, (re)open connection to server if none exists or connection params - have changed - -== 1.2.1 - -* r2648, konstantin, 01-24-08 11:12:00 - * net_fix.rb moved from right_aws gem to fix the problem with uploading the streamable - objects to S3 - -* r2764, konstantin, 02-08-08 00:05:00 +03:00 - * "RightAws: incompatible Net::HTTP monkey-patch" exception is raised if our net_fix - patch was overriden (by attachment_fu for example, to avoid this load attachment_fu - before loading the right_http_connection gem). - -== 1.2.2 - -* r3524, konstantin, 2008-04-17 11:35:42 +0400 - * Fixed a problem with incorrect error handling (connection retries always failed). - -== 1.2.3 - -- Added support for setting retry & timeout parameters in the constructor -- Improve handling of data streams during upload: if there is a failure and a retry, reset - the seek pointer for the subsequent re-request - -== 1.2.4 - -* r4984, konstantin, 2008-08-11 14:49:18 +0400 - * fixed a bug: <NoMethodError: You have a nil object when you didn't expect it! - The error occurred while evaluating nil.body_stream> - diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt deleted file mode 100644 index 20f193b21..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Manifest.txt +++ /dev/null @@ -1,7 +0,0 @@ -History.txt -Manifest.txt -README.txt -Rakefile -lib/net_fix.rb -lib/right_http_connection.rb -setup.rb diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt deleted file mode 100644 index 46c97e57a..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/README.txt +++ /dev/null @@ -1,54 +0,0 @@ -RightScale::HttpConnection - by RightScale, Inc. - www.RightScale.com - -== DESCRIPTION: - -Rightscale::HttpConnection is a robust HTTP/S library. It implements a retry -algorithm for low-level network errors. - -== FEATURES: - -- provides put/get streaming -- does configurable retries on connect and read timeouts, DNS failures, etc. -- HTTPS certificate checking - -== SYNOPSIS: - - -== REQUIREMENTS: - -- 2/11/08: If you use RightScale::HttpConnection in conjunction with attachment_fu, the - HttpConnection gem must be included (using the require statement) AFTER - attachment_fu. - This is due to a conflict between the HttpConnection gem and another - gem required by attachment_fu. - - - -== INSTALL: - -sudo gem install right_http_connection - -== LICENSE: - -Copyright (c) 2007-2008 RightScale, Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile deleted file mode 100644 index 0ae50977c..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/Rakefile +++ /dev/null @@ -1,103 +0,0 @@ -require 'rubygems' -require 'rake' -require 'rake/clean' -require 'rake/testtask' -require 'rake/packagetask' -require 'rake/gempackagetask' -require 'rake/rdoctask' -require 'rake/contrib/rubyforgepublisher' -require 'fileutils' -require 'hoe' -include FileUtils -require File.join(File.dirname(__FILE__), 'lib', 'right_http_connection') - -AUTHOR = 'RightScale' # can also be an array of Authors -EMAIL = "rubygems@rightscale.com" -DESCRIPTION = "RightScale's robust HTTP/S connection module" -GEM_NAME = 'right_http_connection' # what ppl will type to install your gem -RUBYFORGE_PROJECT = 'rightscale' # The unix name for your project -HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org" -DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}" - -NAME = "right_http_connection" -REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil -VERS = RightHttpConnection::VERSION::STRING + (REV ? ".#{REV}" : "") -CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] -RDOC_OPTS = ['--quiet', '--title', 'right_http_connection documentation', - "--opname", "index.html", - "--line-numbers", - "--main", "README", - "--inline-source"] - -# Suppress Hoe's self-inclusion as a dependency for our Gem. This also keeps -# Rake & rubyforge out of the dependency list. Users must manually install -# these gems to run tests, etc. -# TRB 2/19/09: also do this for the extra_dev_deps array present in newer hoes. -# Older versions of RubyGems will try to install developer-dependencies as -# required runtime dependencies.... -class Hoe - def extra_deps - @extra_deps.reject do |x| - Array(x).first == 'hoe' - end - end - def extra_dev_deps - @extra_dev_deps.reject do |x| - Array(x).first == 'hoe' - end - end -end - -# Generate all the Rake tasks -# Run 'rake -T' to see list of generated tasks (from gem root directory) -hoe = Hoe.new(GEM_NAME, VERS) do |p| - p.author = AUTHOR - p.description = DESCRIPTION - p.email = EMAIL - p.summary = DESCRIPTION - p.url = HOMEPATH - p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT - p.test_globs = ["test/**/test_*.rb"] - p.clean_globs = CLEAN #An array of file patterns to delete on clean. - p.remote_rdoc_dir = "right_http_gem_doc" - - # == Optional - p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n") - #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ] - #p.spec_extras = {} # A hash of extra values to set in the gemspec. -end - - -desc 'Generate website files' -task :website_generate do - Dir['website/**/*.txt'].each do |txt| - sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} } - end -end - -desc 'Upload website files to rubyforge' -task :website_upload do - config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml"))) - host = "#{config["username"]}@rubyforge.org" - remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/" - # remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}" - local_dir = 'website' - sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}} -end - -desc 'Generate and upload website files' -task :website => [:website_generate, :website_upload] - -desc 'Release the website and new gem version' -task :deploy => [:check_version, :website, :release] - -task :check_version do - unless ENV['VERSION'] - puts 'Must pass a VERSION=x.y.z release version' - exit - end - unless ENV['VERSION'] == VERS - puts "Please update your version.rb to match the release version, currently #{VERS}" - exit - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb deleted file mode 100644 index ad54f8a2a..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/net_fix.rb +++ /dev/null @@ -1,160 +0,0 @@ -# -# Copyright (c) 2008 RightScale Inc -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# - -# Net::HTTP and Net::HTTPGenericRequest fixes to support 100-continue on -# POST and PUT. The request must have 'expect' field set to '100-continue'. - - -module Net - - class BufferedIO #:nodoc: - # Monkey-patch Net::BufferedIO to read > 1024 bytes from the socket at a time - - # Default size (in bytes) of the max read from a socket into the user space read buffers for socket IO - DEFAULT_SOCKET_READ_SIZE = 16*1024 - - @@socket_read_size = DEFAULT_SOCKET_READ_SIZE - - def self.socket_read_size=(readsize) - if(readsize <= 0) - return - end - @@socket_read_size = readsize - end - - def self.socket_read_size?() - @@socket_read_size - end - - def rbuf_fill - timeout(@read_timeout) { - @rbuf << @io.sysread(@@socket_read_size) - } - end - end - - - #-- Net::HTTPGenericRequest -- - - class HTTPGenericRequest - # Monkey-patch Net::HTTPGenericRequest to read > 1024 bytes from the local data - # source at a time (used in streaming PUTs) - - # Default size (in bytes) of the max read from a local source (File, String, - # etc.) to the user space write buffers for socket IO. - DEFAULT_LOCAL_READ_SIZE = 16*1024 - - @@local_read_size = DEFAULT_LOCAL_READ_SIZE - - def self.local_read_size=(readsize) - if(readsize <= 0) - return - end - @@local_read_size = readsize - end - - def self.local_read_size?() - @@local_read_size - end - - def exec(sock, ver, path, send_only=nil) #:nodoc: internal use only - if @body - send_request_with_body sock, ver, path, @body, send_only - elsif @body_stream - send_request_with_body_stream sock, ver, path, @body_stream, send_only - else - write_header(sock, ver, path) - end - end - - private - - def send_request_with_body(sock, ver, path, body, send_only=nil) - self.content_length = body.length - delete 'Transfer-Encoding' - supply_default_content_type - write_header(sock, ver, path) unless send_only == :body - sock.write(body) unless send_only == :header - end - - def send_request_with_body_stream(sock, ver, path, f, send_only=nil) - unless content_length() or chunked? - raise ArgumentError, - "Content-Length not given and Transfer-Encoding is not `chunked'" - end - supply_default_content_type - write_header(sock, ver, path) unless send_only == :body - unless send_only == :header - if chunked? - while s = f.read(@@local_read_size) - sock.write(sprintf("%x\r\n", s.length) << s << "\r\n") - end - sock.write "0\r\n\r\n" - else - while s = f.read(@@local_read_size) - sock.write s - end - end - end - end - end - - - #-- Net::HTTP -- - - class HTTP - def request(req, body = nil, &block) # :yield: +response+ - unless started? - start { - req['connection'] ||= 'close' - return request(req, body, &block) - } - end - if proxy_user() - unless use_ssl? - req.proxy_basic_auth proxy_user(), proxy_pass() - end - end - # set body - req.set_body_internal body - begin_transport req - # if we expect 100-continue then send a header first - send_only = ((req.is_a?(Post)||req.is_a?(Put)) && (req['expect']=='100-continue')) ? :header : nil - req.exec @socket, @curr_http_version, edit_path(req.path), send_only - begin - res = HTTPResponse.read_new(@socket) - # if we expected 100-continue then send a body - if res.is_a?(HTTPContinue) && send_only && req['content-length'].to_i > 0 - req.exec @socket, @curr_http_version, edit_path(req.path), :body - end - end while res.kind_of?(HTTPContinue) - res.reading_body(@socket, req.response_body_permitted?) { - yield res if block_given? - } - end_transport req, res - res - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb deleted file mode 100644 index 0151ae685..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb +++ /dev/null @@ -1,435 +0,0 @@ -# -# Copyright (c) 2007-2008 RightScale Inc -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -require "net/https" -require "uri" -require "time" -require "logger" - -$:.unshift(File.dirname(__FILE__)) -require "net_fix" - - -module RightHttpConnection #:nodoc: - module VERSION #:nodoc: - MAJOR = 1 - MINOR = 2 - TINY = 4 - - STRING = [MAJOR, MINOR, TINY].join('.') - end -end - - -module Rightscale - -=begin rdoc -HttpConnection maintains a persistent HTTP connection to a remote -server. Each instance maintains its own unique connection to the -HTTP server. HttpConnection makes a best effort to receive a proper -HTTP response from the server, although it does not guarantee that -this response contains a HTTP Success code. - -On low-level errors (TCP/IP errors) HttpConnection invokes a reconnect -and retry algorithm. Note that although each HttpConnection object -has its own connection to the HTTP server, error handling is shared -across all connections to a server. For example, if there are three -connections to www.somehttpserver.com, a timeout error on one of those -connections will cause all three connections to break and reconnect. -A connection will not break and reconnect, however, unless a request -becomes active on it within a certain amount of time after the error -(as specified by HTTP_CONNECTION_RETRY_DELAY). An idle connection will not -break even if other connections to the same server experience errors. - -A HttpConnection will retry a request a certain number of times (as -defined by HTTP_CONNNECTION_RETRY_COUNT). If all the retries fail, -an exception is thrown and all HttpConnections associated with a -server enter a probationary period defined by HTTP_CONNECTION_RETRY_DELAY. -If the user makes a new request subsequent to entering probation, -the request will fail immediately with the same exception thrown -on probation entry. This is so that if the HTTP server has gone -down, not every subsequent request must wait for a connect timeout -before failing. After the probation period expires, the internal -state of the HttpConnection is reset and subsequent requests have -the full number of potential reconnects and retries available to -them. -=end - - class HttpConnection - - # Number of times to retry the request after encountering the first error - HTTP_CONNECTION_RETRY_COUNT = 3 - # Throw a Timeout::Error if a connection isn't established within this number of seconds - HTTP_CONNECTION_OPEN_TIMEOUT = 5 - # Throw a Timeout::Error if no data have been read on this connnection within this number of seconds - HTTP_CONNECTION_READ_TIMEOUT = 120 - # Length of the post-error probationary period during which all requests will fail - HTTP_CONNECTION_RETRY_DELAY = 15 - - #-------------------- - # class methods - #-------------------- - # - @@params = {} - @@params[:http_connection_retry_count] = HTTP_CONNECTION_RETRY_COUNT - @@params[:http_connection_open_timeout] = HTTP_CONNECTION_OPEN_TIMEOUT - @@params[:http_connection_read_timeout] = HTTP_CONNECTION_READ_TIMEOUT - @@params[:http_connection_retry_delay] = HTTP_CONNECTION_RETRY_DELAY - - # Query the global (class-level) parameters: - # - # :user_agent => 'www.HostName.com' # String to report as HTTP User agent - # :ca_file => 'path_to_file' # Path to a CA certification file in PEM format. The file can contain several CA certificates. If this parameter isn't set, HTTPS certs won't be verified. - # :logger => Logger object # If omitted, HttpConnection logs to STDOUT - # :exception => Exception to raise # The type of exception to raise - # # if a request repeatedly fails. RuntimeError is raised if this parameter is omitted. - # :http_connection_retry_count # by default == Rightscale::HttpConnection::HTTP_CONNECTION_RETRY_COUNT - # :http_connection_open_timeout # by default == Rightscale::HttpConnection::HTTP_CONNECTION_OPEN_TIMEOUT - # :http_connection_read_timeout # by default == Rightscale::HttpConnection::HTTP_CONNECTION_READ_TIMEOUT - # :http_connection_retry_delay # by default == Rightscale::HttpConnection::HTTP_CONNECTION_RETRY_DELAY - def self.params - @@params - end - - # Set the global (class-level) parameters - def self.params=(params) - @@params = params - end - - #------------------ - # instance methods - #------------------ - attr_accessor :http - attr_accessor :server - attr_accessor :params # see @@params - attr_accessor :logger - - # Params hash: - # :user_agent => 'www.HostName.com' # String to report as HTTP User agent - # :ca_file => 'path_to_file' # A path of a CA certification file in PEM format. The file can contain several CA certificates. - # :logger => Logger object # If omitted, HttpConnection logs to STDOUT - # :exception => Exception to raise # The type of exception to raise if a request repeatedly fails. RuntimeError is raised if this parameter is omitted. - # :http_connection_retry_count # by default == Rightscale::HttpConnection.params[:http_connection_retry_count] - # :http_connection_open_timeout # by default == Rightscale::HttpConnection.params[:http_connection_open_timeout] - # :http_connection_read_timeout # by default == Rightscale::HttpConnection.params[:http_connection_read_timeout] - # :http_connection_retry_delay # by default == Rightscale::HttpConnection.params[:http_connection_retry_delay] - # - def initialize(params={}) - @params = params - @params[:http_connection_retry_count] ||= @@params[:http_connection_retry_count] - @params[:http_connection_open_timeout] ||= @@params[:http_connection_open_timeout] - @params[:http_connection_read_timeout] ||= @@params[:http_connection_read_timeout] - @params[:http_connection_retry_delay] ||= @@params[:http_connection_retry_delay] - @http = nil - @server = nil - @logger = get_param(:logger) || - (RAILS_DEFAULT_LOGGER if defined?(RAILS_DEFAULT_LOGGER)) || - Logger.new(STDOUT) - end - - def get_param(name) - @params[name] || @@params[name] - end - - # Query for the maximum size (in bytes) of a single read from the underlying - # socket. For bulk transfer, especially over fast links, this is value is - # critical to performance. - def socket_read_size? - Net::BufferedIO.socket_read_size? - end - - # Set the maximum size (in bytes) of a single read from the underlying - # socket. For bulk transfer, especially over fast links, this is value is - # critical to performance. - def socket_read_size=(newsize) - Net::BufferedIO.socket_read_size=(newsize) - end - - # Query for the maximum size (in bytes) of a single read from local data - # sources like files. This is important, for example, in a streaming PUT of a - # large buffer. - def local_read_size? - Net::HTTPGenericRequest.local_read_size? - end - - # Set the maximum size (in bytes) of a single read from local data - # sources like files. This can be used to tune the performance of, for example, a streaming PUT of a - # large buffer. - def local_read_size=(newsize) - Net::HTTPGenericRequest.local_read_size=(newsize) - end - - private - #-------------- - # Retry state - Keep track of errors on a per-server basis - #-------------- - @@state = {} # retry state indexed by server: consecutive error count, error time, and error - @@eof = {} - - # number of consecutive errors seen for server, 0 all is ok - def error_count - @@state[@server] ? @@state[@server][:count] : 0 - end - - # time of last error for server, nil if all is ok - def error_time - @@state[@server] && @@state[@server][:time] - end - - # message for last error for server, "" if all is ok - def error_message - @@state[@server] ? @@state[@server][:message] : "" - end - - # add an error for a server - def error_add(message) - @@state[@server] = { :count => error_count+1, :time => Time.now, :message => message } - end - - # reset the error state for a server (i.e. a request succeeded) - def error_reset - @@state.delete(@server) - end - - # Error message stuff... - def banana_message - return "#{@server} temporarily unavailable: (#{error_message})" - end - - def err_header - return "#{self.class.name} :" - end - - # Adds new EOF timestamp. - # Returns the number of seconds to wait before new conection retry: - # 0.5, 1, 2, 4, 8 - def add_eof - (@@eof[@server] ||= []).unshift Time.now - 0.25 * 2 ** @@eof[@server].size - end - - # Returns first EOF timestamp or nul if have no EOFs being tracked. - def eof_time - @@eof[@server] && @@eof[@server].last - end - - # Returns true if we are receiving EOFs during last @params[:http_connection_retry_delay] seconds - # and there were no successful response from server - def raise_on_eof_exception? - @@eof[@server].blank? ? false : ( (Time.now.to_i-@params[:http_connection_retry_delay]) > @@eof[@server].last.to_i ) - end - - # Reset a list of EOFs for this server. - # This is being called when we have got an successful response from server. - def eof_reset - @@eof.delete(@server) - end - - # Detects if an object is 'streamable' - can we read from it, and can we know the size? - def setup_streaming(request) - if(request.body && request.body.respond_to?(:read)) - body = request.body - request.content_length = body.respond_to?(:lstat) ? body.lstat.size : body.size - request.body_stream = request.body - true - end - end - - def get_fileptr_offset(request_params) - request_params[:request].body.pos - rescue Exception => e - # Probably caught this because the body doesn't support the pos() method, like if it is a socket. - # Just return 0 and get on with life. - 0 - end - - def reset_fileptr_offset(request, offset = 0) - if(request.body_stream && request.body_stream.respond_to?(:pos)) - begin - request.body_stream.pos = offset - rescue Exception => e - @logger.warn("Failed file pointer reset; aborting HTTP retries." + - " -- #{err_header} #{e.inspect}") - raise e - end - end - end - - # Start a fresh connection. The object closes any existing connection and - # opens a new one. - def start(request_params) - # close the previous if exists - finish - # create new connection - @server = request_params[:server] - @port = request_params[:port] - @protocol = request_params[:protocol] - - @logger.info("Opening new #{@protocol.upcase} connection to #@server:#@port") - @http = Net::HTTP.new(@server, @port) - @http.open_timeout = @params[:http_connection_open_timeout] - @http.read_timeout = @params[:http_connection_read_timeout] - - if @protocol == 'https' - verifyCallbackProc = Proc.new{ |ok, x509_store_ctx| - code = x509_store_ctx.error - msg = x509_store_ctx.error_string - #debugger - @logger.warn("##### #{@server} certificate verify failed: #{msg}") unless code == 0 - true - } - @http.use_ssl = true - ca_file = get_param(:ca_file) - if ca_file - @http.verify_mode = OpenSSL::SSL::VERIFY_PEER - @http.verify_callback = verifyCallbackProc - @http.ca_file = ca_file - end - end - # open connection - @http.start - end - - public - -=begin rdoc - Send HTTP request to server - - request_params hash: - :server => 'www.HostName.com' # Hostname or IP address of HTTP server - :port => '80' # Port of HTTP server - :protocol => 'https' # http and https are supported on any port - :request => 'requeststring' # Fully-formed HTTP request to make - - Raises RuntimeError, Interrupt, and params[:exception] (if specified in new). - -=end - def request(request_params, &block) - # We save the offset here so that if we need to retry, we can return the file pointer to its initial position - mypos = get_fileptr_offset(request_params) - loop do - # if we are inside a delay between retries: no requests this time! - if error_count > @params[:http_connection_retry_count] && - error_time + @params[:http_connection_retry_delay] > Time.now - # store the message (otherwise it will be lost after error_reset and - # we will raise an exception with an empty text) - banana_message_text = banana_message - @logger.warn("#{err_header} re-raising same error: #{banana_message_text} " + - "-- error count: #{error_count}, error age: #{Time.now.to_i - error_time.to_i}") - exception = get_param(:exception) || RuntimeError - raise exception.new(banana_message_text) - end - - # try to connect server(if connection does not exist) and get response data - begin - request_params[:protocol] ||= (request_params[:port] == 443 ? 'https' : 'http') - - request = request_params[:request] - request['User-Agent'] = get_param(:user_agent) || '' - - # (re)open connection to server if none exists or params has changed - unless @http && - @http.started? && - @server == request_params[:server] && - @port == request_params[:port] && - @protocol == request_params[:protocol] - start(request_params) - end - - # Detect if the body is a streamable object like a file or socket. If so, stream that - # bad boy. - setup_streaming(request) - response = @http.request(request, &block) - - error_reset - eof_reset - return response - - # We treat EOF errors and the timeout/network errors differently. Both - # are tracked in different statistics blocks. Note below that EOF - # errors will sleep for a certain (exponentially increasing) period. - # Other errors don't sleep because there is already an inherent delay - # in them; connect and read timeouts (for example) have already - # 'slept'. It is still not clear which way we should treat errors - # like RST and resolution failures. For now, there is no additional - # delay for these errors although this may change in the future. - - # EOFError means the server closed the connection on us. - rescue EOFError => e - @logger.debug("#{err_header} server #{@server} closed connection") - @http = nil - - # if we have waited long enough - raise an exception... - if raise_on_eof_exception? - exception = get_param(:exception) || RuntimeError - @logger.warn("#{err_header} raising #{exception} due to permanent EOF being received from #{@server}, error age: #{Time.now.to_i - eof_time.to_i}") - raise exception.new("Permanent EOF is being received from #{@server}.") - else - # ... else just sleep a bit before new retry - sleep(add_eof) - # We will be retrying the request, so reset the file pointer - reset_fileptr_offset(request, mypos) - end - rescue Exception => e # See comment at bottom for the list of errors seen... - @http = nil - # if ctrl+c is pressed - we have to reraise exception to terminate proggy - if e.is_a?(Interrupt) && !( e.is_a?(Errno::ETIMEDOUT) || e.is_a?(Timeout::Error)) - @logger.debug( "#{err_header} request to server #{@server} interrupted by ctrl-c") - raise - elsif e.is_a?(ArgumentError) && e.message.include?('wrong number of arguments (5 for 4)') - # seems our net_fix patch was overriden... - exception = get_param(:exception) || RuntimeError - raise exception.new('incompatible Net::HTTP monkey-patch') - end - # oops - we got a banana: log it - error_add(e.message) - @logger.warn("#{err_header} request failure count: #{error_count}, exception: #{e.inspect}") - - # We will be retrying the request, so reset the file pointer - reset_fileptr_offset(request, mypos) - - end - end - end - - def finish(reason = '') - if @http && @http.started? - reason = ", reason: '#{reason}'" unless reason.blank? - @logger.info("Closing #{@http.use_ssl? ? 'HTTPS' : 'HTTP'} connection to #{@http.address}:#{@http.port}#{reason}") - @http.finish - end - end - - # Errors received during testing: - # - # #<Timeout::Error: execution expired> - # #<Errno::ETIMEDOUT: Connection timed out - connect(2)> - # #<SocketError: getaddrinfo: Name or service not known> - # #<SocketError: getaddrinfo: Temporary failure in name resolution> - # #<EOFError: end of file reached> - # #<Errno::ECONNRESET: Connection reset by peer> - # #<OpenSSL::SSL::SSLError: SSL_write:: bad write retry> - end - -end - diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb deleted file mode 100644 index 424a5f37c..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/right_http_connection-1.2.4/setup.rb +++ /dev/null @@ -1,1585 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2005 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -unless Errno.const_defined?(:ENOTEMPTY) # Windows? - module Errno - class ENOTEMPTY - # We do not raise this exception, implementation is not needed. - end - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted Windows' stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class ConfigTable - - include Enumerable - - def initialize(rbconfig) - @rbconfig = rbconfig - @items = [] - @table = {} - # options - @install_prefix = nil - @config_opt = nil - @verbose = true - @no_harm = false - end - - attr_accessor :install_prefix - attr_accessor :config_opt - - attr_writer :verbose - - def verbose? - @verbose - end - - attr_writer :no_harm - - def no_harm? - @no_harm - end - - def [](key) - lookup(key).resolve(self) - end - - def []=(key, val) - lookup(key).set val - end - - def names - @items.map {|i| i.name } - end - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or setup_rb_error "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def load_script(path, inst = nil) - if File.file?(path) - MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path - end - end - - def savefile - '.config' - end - - def load_savefile - begin - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - self[k] = v.strip - end - rescue Errno::ENOENT - setup_rb_error $!.message + "\n#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value? and i.value - end - } - end - - def load_standard_entries - standard_entries(@rbconfig).each do |ent| - add ent - end - end - - def standard_entries(rbconfig) - c = rbconfig - - rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) - - major = c['MAJOR'].to_i - minor = c['MINOR'].to_i - teeny = c['TEENY'].to_i - version = "#{major}.#{minor}" - - # ruby ver. >= 1.4.4? - newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - - if c['rubylibdir'] - # V > 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = c['rubylibdir'] - librubyverarch = c['archdir'] - siteruby = c['sitedir'] - siterubyver = c['sitelibdir'] - siterubyverarch = c['sitearchdir'] - elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = c['sitedir'] - siterubyver = "$siteruby/#{version}" - siterubyverarch = "$siterubyver/#{c['arch']}" - else - # V < 1.4.4 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" - siterubyver = siteruby - siterubyverarch = "$siterubyver/#{c['arch']}" - end - parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') - } - - if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] - else - makeprog = 'make' - end - - [ - ExecItem.new('installdirs', 'std/site/home', - 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ - {|val, table| - case val - when 'std' - table['rbdir'] = '$librubyver' - table['sodir'] = '$librubyverarch' - when 'site' - table['rbdir'] = '$siterubyver' - table['sodir'] = '$siterubyverarch' - when 'home' - setup_rb_error '$HOME was not set' unless ENV['HOME'] - table['prefix'] = ENV['HOME'] - table['rbdir'] = '$libdir/ruby' - table['sodir'] = '$libdir/ruby' - end - }, - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', parameterize.call(c['libdir']), - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for system configuration files'), - PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), - 'the directory for local state data'), - PathItem.new('libruby', 'path', libruby, - 'the directory for ruby libraries'), - PathItem.new('librubyver', 'path', librubyver, - 'the directory for standard ruby libraries'), - PathItem.new('librubyverarch', 'path', librubyverarch, - 'the directory for standard ruby extensions'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') - ] - end - private :standard_entries - - def load_multipackage_entries - multipackage_entries().each do |ent| - add ent - end - end - - def multipackage_entries - [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') - ] - end - private :multipackage_entries - - ALIASES = { - 'std-ruby' => 'librubyver', - 'stdruby' => 'librubyver', - 'rubylibdir' => 'librubyver', - 'archdir' => 'librubyverarch', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } - - def fixup - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - @items.freeze - @table.freeze - @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ - end - - def parse_opt(opt) - m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" - m.to_a[1,2] - end - - def dllext - @rbconfig['DLEXT'] - end - - def value_config?(name) - lookup(name).value? - end - - class Item - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value? - true - end - - def value - @value - end - - def resolve(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end - end - - class BoolItem < Item - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - case val - when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' - when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' - else - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - end - end - - class PathItem < Item - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end - end - - class ProgramItem < Item - def config_type - 'program' - end - end - - class SelectItem < Item - def initialize(name, selection, default, desc) - super - @ok = selection.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end - end - - class ExecItem < Item - def initialize(name, selection, desc, &block) - super name, selection, nil, desc - @ok = selection.split('/') - @action = block - end - - def config_type - 'exec' - end - - def value? - false - end - - def resolve(table) - setup_rb_error "$#{name()} wrongly used as option value" - end - - undef set - - def evaluate(val, table) - v = val.strip.downcase - unless @ok.include?(v) - setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" - end - @action.call v, table - end - end - - class PackageSelectionItem < Item - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end - end - - class MetaConfigEnvironment - def initialize(config, installer) - @config = config - @installer = installer - end - - def config_names - @config.names - end - - def config?(name) - @config.key?(name) - end - - def bool_config?(name) - @config.lookup(name).config_type == 'bool' - end - - def path_config?(name) - @config.lookup(name).config_type == 'path' - end - - def value_config?(name) - @config.lookup(name).config_type != 'exec' - end - - def add_config(item) - @config.add item - end - - def add_bool_config(name, default, desc) - @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - @config.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - @config.lookup(name).default = default - end - - def remove_config(name) - @config.remove(name) - end - - # For only multipackage - def packages - raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer - @installer.packages - end - - # For only multipackage - def declare_packages(list) - raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer - @installer.packages = list - end - end - -end # class ConfigTable - - -# This module requires: #verbose?, #no_harm? -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # Does not check '/', it's too abnormal. - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(path) - $stderr.puts "rm -f #{path}" if verbose? - return if no_harm? - force_remove_file path - end - - def rm_rf(path) - $stderr.puts "rm -rf #{path}" if verbose? - return if no_harm? - remove_tree path - end - - def remove_tree(path) - if File.symlink?(path) - remove_file path - elsif File.dir?(path) - remove_tree0 path - else - force_remove_file path - end - end - - def remove_tree0(path) - Dir.foreach(path) do |ent| - next if ent == '.' - next if ent == '..' - entpath = "#{path}/#{ent}" - if File.symlink?(entpath) - remove_file entpath - elsif File.dir?(entpath) - remove_tree0 entpath - else - force_remove_file entpath - end - end - begin - Dir.rmdir path - rescue Errno::ENOTEMPTY - # directory may not be empty - end - end - - def move_file(src, dest) - force_remove_file dest - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| - f.write File.binread(src) - } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def force_remove_file(path) - begin - remove_file path - rescue - end - end - - def remove_file(path) - File.chmod 0777, path - File.unlink path - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(*args) - $stderr.puts args.join(' ') if verbose? - system(*args) or raise RuntimeError, - "system(#{args.map{|a| a.inspect }.join(' ')}) failed" - end - - def ruby(*args) - command config('rubyprog'), *args - end - - def make(task = nil) - command(*[config('makeprog'), task].compact) - end - - def extdir?(dir) - File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") - end - - def files_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.file?("#{dir}/#{ent}") } - } - end - - DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) - - def directories_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT - } - end - -end - - -# This module requires: #srcdir_root, #objdir_root, #relpath -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - # obsolete: use metaconfig to change configuration - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file?(srcfile(path)) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.4.1' - Copyright = 'Copyright (c) 2000-2005 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'test', 'run all tests in test/' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - config = ConfigTable.new(load_rbconfig()) - config.load_standard_entries - config.load_multipackage_entries if multipackage? - config.fixup - klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) - klass.new(File.dirname($0), config).invoke - end - - def ToplevelInstaller.multipackage? - File.dir?(File.dirname($0) + '/packages') - end - - def ToplevelInstaller.load_rbconfig - if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - load File.expand_path(arg.split(/=/, 2)[1]) - $".push 'rbconfig.rb' - else - require 'rbconfig' - end - ::Config::CONFIG - end - - def initialize(ardir_root, config) - @ardir = File.expand_path(ardir_root) - @config = config - # cache - @valid_task_re = nil - end - - def config(key) - @config[key] - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - case task - when 'config', 'test' - ; - when 'clean', 'distclean' - @config.load_savefile if File.exist?(@config.savefile) - else - @config.load_savefile - end - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig" - end - - def init_installers - @installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) - return arg - when '-q', '--quiet' - @config.verbose = false - when '--verbose' - @config.verbose = true - when '--help' - print_usage $stdout - exit 0 - when '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - when '--copyright' - puts Copyright - exit 0 - else - setup_rb_error "unknown global option '#{arg}'" - end - end - nil - end - - def valid_task?(t) - valid_task_re() =~ t - end - - def valid_task_re - @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ - end - - def parsearg_no_options - unless ARGV.empty? - task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) - setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_test parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - evalopt = [] - set = [] - @config.config_opt = [] - while i = ARGV.shift - if /\A--?\z/ =~ i - @config.config_opt = ARGV.dup - break - end - name, value = *@config.parse_opt(i) - if @config.value_config?(name) - @config[name] = value - else - evalopt.push [name, value] - end - set.push name - end - evalopt.each do |name, value| - @config.lookup(name).evaluate value, @config - end - # Check if configuration is valid - set.each do |n| - @config[n] if @config.value_config?(n) - end - end - - def parsearg_install - @config.no_harm = false - @config.install_prefix = '' - while a = ARGV.shift - case a - when '--no-harm' - @config.no_harm = true - when /\A--prefix=/ - path = a.split(/=/, 2)[1] - path = File.expand_path(path) unless path[0,1] == '/' - @config.install_prefix = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} <global option>" - out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, ' --help', 'print this message' - out.printf fmt, ' --version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - @config.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_test - @installer.exec_test - end - - def exec_show - @config.each do |i| - printf "%-20s %s\n", i.name, i.value if i.value? - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end # class ToplevelInstaller - - -class ToplevelInstallerMulti < ToplevelInstaller - - include FileOperations - - def initialize(ardir_root, config) - super - @packages = directories_of("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig", self - @packages.each do |name| - @config.load_script "#{@ardir}/packages/#{name}/metaconfig" - end - end - - attr_reader :packages - - def packages=(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_test - run_hook 'pre-test' - each_selected_installers {|inst| inst.exec_test } - run_hook 'post-test' - end - - def exec_clean - rm_f @config.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f @config.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if verbose? - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def run_hook(id) - @root_installer.run_hook id - end - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - -end # class ToplevelInstallerMulti - - -class Installer - - FILETYPES = %w( bin lib ext data conf man ) - - include FileOperations - include HookScriptAPI - - def initialize(config, srcroot, objroot) - @config = config - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - def noop(rel) - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # Config Access - # - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - - def verbose_off - begin - save, @config.verbose = @config.verbose?, false - yield - ensure - @config.verbose = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - alias config_dir_bin noop - alias config_dir_lib noop - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - alias config_dir_data noop - alias config_dir_conf noop - alias config_dir_man noop - - def extconf - ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - files_of(curr_srcdir()).each do |fname| - update_shebang_line "#{curr_srcdir()}/#{fname}" - end - end - - alias setup_dir_lib noop - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - alias setup_dir_data noop - alias setup_dir_conf noop - alias setup_dir_man noop - - def update_shebang_line(path) - return if no_harm? - return if config('shebang') == 'never' - old = Shebang.load(path) - if old - $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 - new = new_shebang(old) - return if new.to_s == old.to_s - else - return unless config('shebang') == 'all' - new = Shebang.new(config('rubypath')) - end - $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? - open_atomic_writer(path) {|output| - File.open(path, 'rb') {|f| - f.gets if old # discard - output.puts new.to_s - output.print f.read - } - } - end - - def new_shebang(old) - if /\Aruby/ =~ File.basename(old.cmd) - Shebang.new(config('rubypath'), old.args) - elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' - Shebang.new(config('rubypath'), old.args[1..-1]) - else - return old unless config('shebang') == 'all' - Shebang.new(config('rubypath')) - end - end - - def open_atomic_writer(path, &block) - tmpfile = File.basename(path) + '.tmp' - begin - File.open(tmpfile, 'wb', &block) - File.rename tmpfile, File.basename(path) - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - class Shebang - def Shebang.load(path) - line = nil - File.open(path) {|f| - line = f.gets - } - return nil unless /\A#!/ =~ line - parse(line) - end - - def Shebang.parse(line) - cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') - new(cmd, args) - end - - def initialize(cmd, args = []) - @cmd = cmd - @args = args - end - - attr_reader :cmd - attr_reader :args - - def to_s - "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") - end - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files rubyextentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_dir_conf(rel) - # FIXME: should not remove current config files - # (rename previous file to .old/.org) - install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 - end - - def install_dir_man(rel) - install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @config.install_prefix - list.each do |fname| - install fname, dest, mode, @config.install_prefix - end - end - - def libfiles - glob_reject(%w(*.y *.output), targetfiles()) - end - - def rubyextentions(dir) - ents = glob_select("*.#{@config.dllext}", targetfiles()) - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - ents - end - - def targetfiles - mapdir(existfiles() - hookfiles()) - end - - def mapdir(ents) - ents.map {|ent| - if File.exist?(ent) - then ent # objdir - else "#{curr_srcdir()}/#{ent}" # srcdir - end - } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - JUNK_FILES = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - - def existfiles - glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def glob_select(pat, ents) - re = globs2re([pat]) - ents.select {|ent| re =~ ent } - end - - def glob_reject(pats, ents) - re = globs2re(pats) - ents.reject {|ent| re =~ ent } - end - - GLOB2REGEX = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - - def globs2re(pats) - /\A(?:#{ - pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') - })\z/ - end - - # - # TASK test - # - - TESTDIR = 'test' - - def exec_test - unless File.directory?('test') - $stderr.puts 'no test in this package' if verbose? - return - end - $stderr.puts 'Running tests...' if verbose? - begin - require 'test/unit' - rescue LoadError - setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' - end - runner = Test::Unit::AutoRunner.new(true) - runner.to_run << TESTDIR - runner.run - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias clean_dir_bin noop - alias clean_dir_lib noop - alias clean_dir_data noop - alias clean_dir_conf noop - alias clean_dir_man noop - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias distclean_dir_bin noop - alias distclean_dir_lib noop - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - alias distclean_dir_data noop - alias distclean_dir_conf noop - alias distclean_dir_man noop - - # - # Traversing - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if type == 'ext' and config('without-ext') == 'yes' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - directories_of(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - - def run_hook(id) - path = [ "#{curr_srcdir()}/#{id}", - "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } - return unless path - begin - instance_eval File.read(path), path, 1 - rescue - raise if $DEBUG - setup_rb_error "hook #{path} failed:\n" + $!.message - end - end - -end # class Installer - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -if $0 == __FILE__ - begin - ToplevelInstaller.invoke - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document deleted file mode 100644 index ecf367319..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.document +++ /dev/null @@ -1,5 +0,0 @@ -README.rdoc -lib/**/*.rb -bin/* -features/**/*.feature -LICENSE diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore deleted file mode 100644 index 482f92bf7..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -.yardoc -/coverage -/doc -/pkg diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE deleted file mode 100644 index 590bcb6fa..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2009 Chris Kampmeier - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc deleted file mode 100644 index cfab5434f..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/README.rdoc +++ /dev/null @@ -1,70 +0,0 @@ -= Samuel - -Samuel is a gem for automatic logging of your Net::HTTP requests. It's named for -the serial diarist Mr. Pepys, who was known to reliably record events both -quotidian and remarkable. - -Should a Great Plague, Fire, or Whale befall an important external web service -you use, you'll be sure to have a tidy record of it. - -== Usage: - -When Rails is loaded, Samuel configures a few things automatically. So all you -need to do is this: - - # config/environment.rb - config.gem "samuel" - -And Samuel will automatically use Rails's logger and an ActiveRecord-like format. - -For non-Rails projects, you'll have to manually configure logging, like this: - - require 'samuel' - Samuel.logger = Logger.new('http_requests.log') - -If you don't assign a logger, Samuel will configure a default logger on +STDOUT+. - -== Configuration - -There are two ways to specify configuration options for Samuel: global and -inline. Global configs look like this: - - Samuel.config[:labels] = {"example.com" => "Example API"} - Samuel.config[:filtered_params] = :password - -You should put global configuration somewhere early-on in your program. If -you're using Rails, <tt>config/initializers/samuel.rb</tt> will do the trick. - -Alternatively, an inline configuration block temporarily overrides any global -configuration for a set of HTTP requests: - - Samuel.with_config :label => "Twitter API" do - Net::HTTP.start("twitter.com") { |http| http.get("/help/test") } - end - -Right now, there are three configuration changes you can make in either style: - -* +:labels+ - This is a hash with domain substrings as keys and log labels as - values. If a request domain includes one of the domain substrings, the - corresponding label will be used for the first part of that log entry. By - default this is set to <tt>\{"" => "HTTP"}</tt>, so that all requests are - labeled with <tt>"HTTP Request"</tt>. -* +:label+ - As an alternative to the +:labels+ hash, this is simply a string. - If set, it takes precedence over any +:labels+ (by default, it's not set). It - gets <tt>"Request"</tt> appended to it as well -- so if you want your log to - always say +Twitter API Request+ instead of the default +HTTP Request+, you - can set this to <tt>"Twitter API"</tt>. I'd recommend using this setting - globally if you're only making requests to one service, or inline if you just - need to temporarily override the global +:labels+. -* +:filtered_params+ - This works just like Rails's +filter_parameter_logging+ - method. Set it to a symbol, string, or array of them, and Samuel will filter - the value of query parameters that have any of these patterns as a substring - by replacing the value with <tt>[FILTERED]</tt> in your logs. By default, no - filtering is enabled. - -Samuel logs successful HTTP requests at the +INFO+ level; Failed requests log at -the +WARN+ level. This isn't currently configurable, but it's on the list. - -== License - -Copyright 2009 Chris Kampmeier. See +LICENSE+ for details. diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile deleted file mode 100644 index ffbe60384..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/Rakefile +++ /dev/null @@ -1,62 +0,0 @@ -require 'rubygems' -require 'rake' - -begin - require 'jeweler' - Jeweler::Tasks.new do |gem| - gem.name = "samuel" - gem.summary = %Q{An automatic logger for HTTP requests in Ruby} - gem.description = %Q{An automatic logger for HTTP requests in Ruby. Adds Net::HTTP request logging to your Rails logs, and more.} - gem.email = "chris@kampers.net" - gem.homepage = "http://github.com/chrisk/samuel" - gem.authors = ["Chris Kampmeier"] - gem.rubyforge_project = "samuel" - gem.add_development_dependency "thoughtbot-shoulda" - gem.add_development_dependency "yard" - gem.add_development_dependency "mocha" - gem.add_development_dependency "fakeweb" - end - Jeweler::GemcutterTasks.new - Jeweler::RubyforgeTasks.new do |rubyforge| - rubyforge.doc_task = "yardoc" - end -rescue LoadError - puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" -end - -require 'rake/testtask' -Rake::TestTask.new(:test) do |test| - test.libs << 'lib' << 'test' - test.pattern = 'test/**/*_test.rb' - test.verbose = false - test.warning = true -end - -begin - require 'rcov/rcovtask' - Rcov::RcovTask.new do |test| - test.libs << 'test' - test.pattern = 'test/**/*_test.rb' - test.rcov_opts << "--sort coverage" - test.rcov_opts << "--exclude gems" - test.verbose = false - test.warning = true - end -rescue LoadError - task :rcov do - abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" - end -end - -task :test => :check_dependencies - -task :default => :test - -begin - require 'yard' - YARD::Rake::YardocTask.new -rescue LoadError - task :yardoc do - abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard" - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION deleted file mode 100644 index 0c62199f1..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.2.1 diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb deleted file mode 100644 index 5c8fed6f6..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "logger" -require "net/http" -require "net/https" -require "benchmark" - -require "samuel/net_http" -require "samuel/request" - - -module Samuel - extend self - - attr_writer :config, :logger - - def logger - @logger = nil if !defined?(@logger) - return @logger if !@logger.nil? - - if defined?(RAILS_DEFAULT_LOGGER) - @logger = RAILS_DEFAULT_LOGGER - else - @logger = Logger.new(STDOUT) - end - end - - def config - Thread.current[:__samuel_config] ? Thread.current[:__samuel_config] : @config - end - - def log_request(http, request, &block) - request = Request.new(http, request, block) - request.perform_and_log! - request.response - end - - def with_config(options = {}) - original_config = config.dup - nested = !Thread.current[:__samuel_config].nil? - - Thread.current[:__samuel_config] = original_config.merge(options) - yield - Thread.current[:__samuel_config] = nested ? original_config : nil - end - - def reset_config - Thread.current[:__samuel_config] = nil - @config = {:label => nil, :labels => {"" => "HTTP"}, :filtered_params => []} - end - -end - -Samuel.reset_config diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb deleted file mode 100644 index 2ffadf220..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/net_http.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Net::HTTP - - alias request_without_samuel request - def request(req, body = nil, &block) - Samuel.log_request(self, req) do - request_without_samuel(req, body, &block) - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb deleted file mode 100644 index e10ecb44e..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/lib/samuel/request.rb +++ /dev/null @@ -1,96 +0,0 @@ -module Samuel - class Request - - attr_accessor :response - - def initialize(http, request, proc) - @http, @request, @proc = http, request, proc - end - - def perform_and_log! - # If an exception is raised in the Benchmark block, it'll interrupt the - # benchmark. Instead, use an inner block to record it as the "response" - # for raising after the benchmark (and logging) is done. - @seconds = Benchmark.realtime do - begin; @response = @proc.call; rescue Exception => @response; end - end - Samuel.logger.add(log_level, log_message) - raise @response if @response.is_a?(Exception) - end - - private - - def log_message - bold = "\e[1m" - blue = "\e[34m" - underline = "\e[4m" - reset = "\e[0m" - " #{bold}#{blue}#{underline}#{label} request (#{milliseconds}ms) " + - "#{response_summary}#{reset} #{method} #{uri}" - end - - def milliseconds - (@seconds * 1000).round - end - - def uri - "#{scheme}://#{@http.address}#{port_if_not_default}#{filtered_path}" - end - - def filtered_path - path_without_query, query = @request.path.split("?") - if query - patterns = [Samuel.config[:filtered_params]].flatten - patterns.map { |pattern| - pattern_for_regex = Regexp.escape(pattern.to_s) - [/([^&]*#{pattern_for_regex}[^&=]*)=(?:[^&]+)/, '\1=[FILTERED]'] - }.each { |filter| query.gsub!(*filter) } - "#{path_without_query}?#{query}" - else - @request.path - end - end - - def scheme - @http.use_ssl? ? "https" : "http" - end - - def port_if_not_default - ssl, port = @http.use_ssl?, @http.port - if (!ssl && port == 80) || (ssl && port == 443) - "" - else - ":#{port}" - end - end - - def method - @request.method.to_s.upcase - end - - def label - return Samuel.config[:label] if Samuel.config[:label] - - pair = Samuel.config[:labels].detect { |domain, label| @http.address.include?(domain) } - pair[1] if pair - end - - def response_summary - if response.is_a?(Exception) - response.class - else - "[#{response.code} #{response.message}]" - end - end - - def log_level - error_classes = [Exception, Net::HTTPClientError, Net::HTTPServerError] - if error_classes.any? { |klass| response.is_a?(klass) } - level = Logger::WARN - else - level = Logger::INFO - end - end - - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec deleted file mode 100644 index 3a3719bf8..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/samuel.gemspec +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE -# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec` -# -*- encoding: utf-8 -*- - -Gem::Specification.new do |s| - s.name = %q{samuel} - s.version = "0.2.1" - - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Chris Kampmeier"] - s.date = %q{2009-09-15} - s.description = %q{An automatic logger for HTTP requests in Ruby. Adds Net::HTTP request logging to your Rails logs, and more.} - s.email = %q{chris@kampers.net} - s.extra_rdoc_files = [ - "LICENSE", - "README.rdoc" - ] - s.files = [ - ".document", - ".gitignore", - "LICENSE", - "README.rdoc", - "Rakefile", - "VERSION", - "lib/samuel.rb", - "lib/samuel/net_http.rb", - "lib/samuel/request.rb", - "samuel.gemspec", - "test/request_test.rb", - "test/samuel_test.rb", - "test/test_helper.rb", - "test/thread_test.rb" - ] - s.homepage = %q{http://github.com/chrisk/samuel} - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.rubyforge_project = %q{samuel} - s.rubygems_version = %q{1.3.5} - s.summary = %q{An automatic logger for HTTP requests in Ruby} - s.test_files = [ - "test/request_test.rb", - "test/samuel_test.rb", - "test/test_helper.rb", - "test/thread_test.rb" - ] - - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"]) - s.add_development_dependency(%q<yard>, [">= 0"]) - s.add_development_dependency(%q<mocha>, [">= 0"]) - s.add_development_dependency(%q<fakeweb>, [">= 0"]) - else - s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"]) - s.add_dependency(%q<yard>, [">= 0"]) - s.add_dependency(%q<mocha>, [">= 0"]) - s.add_dependency(%q<fakeweb>, [">= 0"]) - end - else - s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"]) - s.add_dependency(%q<yard>, [">= 0"]) - s.add_dependency(%q<mocha>, [">= 0"]) - s.add_dependency(%q<fakeweb>, [">= 0"]) - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb deleted file mode 100644 index 4e905d1ec..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/request_test.rb +++ /dev/null @@ -1,193 +0,0 @@ -require 'test_helper' - -class RequestTest < Test::Unit::TestCase - - context "making an HTTP request" do - setup { setup_test_logger - FakeWeb.clean_registry - Samuel.reset_config } - teardown { teardown_test_logger } - - context "to GET http://example.com/test, responding with a 200 in 53ms" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Benchmark.stubs(:realtime).yields.returns(0.053) - open "http://example.com/test" - end - - should_log_lines 1 - should_log_at_level :info - should_log_including "HTTP request" - should_log_including "(53ms)" - should_log_including "[200 OK]" - should_log_including "GET http://example.com/test" - end - - context "on a non-standard port" do - setup do - FakeWeb.register_uri(:get, "http://example.com:8080/test", :status => [200, "OK"]) - open "http://example.com:8080/test" - end - - should_log_including "GET http://example.com:8080/test" - end - - context "with SSL" do - setup do - FakeWeb.register_uri(:get, "https://example.com/test", :status => [200, "OK"]) - open "https://example.com/test" - end - - should_log_including "HTTP request" - should_log_including "GET https://example.com/test" - end - - context "with SSL on a non-standard port" do - setup do - FakeWeb.register_uri(:get, "https://example.com:80/test", :status => [200, "OK"]) - open "https://example.com:80/test" - end - - should_log_including "HTTP request" - should_log_including "GET https://example.com:80/test" - end - - context "that raises" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :exception => Errno::ECONNREFUSED) - begin - Net::HTTP.start("example.com") { |http| http.get("/test") } - rescue Errno::ECONNREFUSED => @exception - end - end - - should_log_at_level :warn - should_log_including "HTTP request" - should_log_including "GET http://example.com/test" - should_log_including "Errno::ECONNREFUSED" - should_log_including %r|\d+ms| - should_raise_exception Errno::ECONNREFUSED - end - - context "that responds with a 500-level code" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [502, "Bad Gateway"]) - Net::HTTP.start("example.com") { |http| http.get("/test") } - end - - should_log_at_level :warn - end - - context "that responds with a 400-level code" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [404, "Not Found"]) - Net::HTTP.start("example.com") { |http| http.get("/test") } - end - - should_log_at_level :warn - end - - context "inside a configuration block with :label => 'Example'" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.with_config :label => "Example" do - open "http://example.com/test" - end - end - - should_log_including "Example request" - should_have_config_afterwards_including :labels => {"" => "HTTP"}, - :label => nil - end - - context "inside a configuration block with :filter_params" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test?password=secret&username=chrisk", - :status => [200, "OK"]) - @uri = "http://example.com/test?password=secret&username=chrisk" - end - - context "=> :password" do - setup { Samuel.with_config(:filtered_params => :password) { open @uri } } - should_log_including "http://example.com/test?password=[FILTERED]&username=chrisk" - end - - context "=> :as" do - setup { Samuel.with_config(:filtered_params => :ass) { open @uri } } - should_log_including "http://example.com/test?password=[FILTERED]&username=chrisk" - end - - context "=> ['pass', 'name']" do - setup { Samuel.with_config(:filtered_params => %w(pass name)) { open @uri } } - should_log_including "http://example.com/test?password=[FILTERED]&username=[FILTERED]" - end - end - - context "with a global config including :label => 'Example'" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.config[:label] = "Example" - open "http://example.com/test" - end - - should_log_including "Example request" - should_have_config_afterwards_including :labels => {"" => "HTTP"}, - :label => "Example" - end - - context "with a global config including :label => 'Example' but inside config block that changes it to 'Example 2'" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.config[:label] = "Example" - Samuel.with_config(:label => "Example 2") { open "http://example.com/test" } - end - - should_log_including "Example 2 request" - should_have_config_afterwards_including :labels => {"" => "HTTP"}, - :label => "Example" - end - - context "inside a config block of :label => 'Example 2' nested inside a config block of :label => 'Example'" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.with_config :label => "Example" do - Samuel.with_config :label => "Example 2" do - open "http://example.com/test" - end - end - end - - should_log_including "Example 2 request" - should_have_config_afterwards_including :labels => {"" => "HTTP"}, - :label => nil - end - - context "wth a global config including :labels => {'example.com' => 'Example'} but inside a config block of :label => 'Example 3' nested inside a config block of :label => 'Example 2'" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.config[:labels] = {'example.com' => 'Example'} - Samuel.with_config :label => "Example 2" do - Samuel.with_config :label => "Example 3" do - open "http://example.com/test" - end - end - end - - should_log_including "Example 3 request" - should_have_config_afterwards_including :labels => {'example.com' => 'Example'}, - :label => nil - end - - context "with a global config including :labels => {'example.com' => 'Example API'}" do - setup do - FakeWeb.register_uri(:get, "http://example.com/test", :status => [200, "OK"]) - Samuel.config[:labels] = {'example.com' => 'Example API'} - open "http://example.com/test" - end - - should_log_including "Example API request" - end - - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb deleted file mode 100644 index 4a3665fa6..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/samuel_test.rb +++ /dev/null @@ -1,42 +0,0 @@ -require 'test_helper' - -class SamuelTest < Test::Unit::TestCase - - context "logger configuration" do - setup do - Samuel.logger = nil - if Object.const_defined?(:RAILS_DEFAULT_LOGGER) - Object.send(:remove_const, :RAILS_DEFAULT_LOGGER) - end - end - - teardown do - Samuel.logger = nil - end - - context "when Rails's logger is available" do - setup { Object.const_set(:RAILS_DEFAULT_LOGGER, :mock_logger) } - - should "use the same logger" do - assert_equal :mock_logger, Samuel.logger - end - end - - context "when Rails's logger is not available" do - should "use a new Logger instance pointed to STDOUT" do - assert_instance_of Logger, Samuel.logger - assert_equal STDOUT, Samuel.logger.instance_variable_get(:"@logdev").dev - end - end - end - - - context ".reset_config" do - should "reset the config to default vaules" do - Samuel.config = {:foo => "bar"} - Samuel.reset_config - assert_equal({:label => nil, :labels => {"" => "HTTP"}, :filtered_params => []}, Samuel.config) - end - end - -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb deleted file mode 100644 index 2862051b9..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/test_helper.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'rubygems' -require 'test/unit' -require 'shoulda' -require 'mocha' -require 'open-uri' -require 'fakeweb' - -FakeWeb.allow_net_connect = false - -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -$LOAD_PATH.unshift(File.dirname(__FILE__)) -require 'samuel' - -class Test::Unit::TestCase - TEST_LOG_PATH = File.join(File.dirname(__FILE__), 'test.log') - - def self.should_log_lines(expected_count) - should "log #{expected_count} line#{'s' unless expected_count == 1}" do - lines = File.readlines(TEST_LOG_PATH) - assert_equal expected_count, lines.length - end - end - - def self.should_log_including(what) - should "log a line including #{what.inspect}" do - contents = File.read(TEST_LOG_PATH) - if what.is_a?(Regexp) - assert_match what, contents - else - assert contents.include?(what), - "Expected #{contents.inspect} to include #{what.inspect}" - end - end - end - - def self.should_log_at_level(level) - level = level.to_s.upcase - should "log at the #{level} level" do - assert File.read(TEST_LOG_PATH).include?(" #{level} -- :") - end - end - - def self.should_raise_exception(klass) - should "raise an #{klass} exception" do - assert @exception.is_a?(klass) - end - end - - def self.should_have_config_afterwards_including(config) - config.each_pair do |key, value| - should "continue afterwards with Samuel.config[#{key.inspect}] set to #{value.inspect}" do - assert_equal value, Samuel.config[key] - end - end - end - - def setup_test_logger - FileUtils.rm_rf TEST_LOG_PATH - FileUtils.touch TEST_LOG_PATH - Samuel.logger = Logger.new(TEST_LOG_PATH) - end - - def teardown_test_logger - FileUtils.rm_rf TEST_LOG_PATH - end -end diff --git a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb b/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb deleted file mode 100644 index d030cb973..000000000 --- a/vendor/gems/fakeweb-1.3.0/test/vendor/samuel-0.2.1/test/thread_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'test_helper' - -class ThreadTest < Test::Unit::TestCase - - context "when logging multiple requests at once" do - setup do - @log = StringIO.new - Samuel.logger = Logger.new(@log) - FakeWeb.register_uri(:get, /example\.com/, :status => [200, "OK"]) - threads = [] - 5.times do |i| - threads << Thread.new(i) do |n| - Samuel.with_config :label => "Example #{n}" do - Thread.pass - open "http://example.com/#{n}" - end - end - end - threads.each { |t| t.join } - @log.rewind - end - - should "not let configuration blocks interfere with eachother" do - @log.each_line do |line| - matches = %r|Example (\d+).*example\.com/(\d+)|.match(line) - assert_not_nil matches - assert_equal matches[1], matches[2] - end - end - end - -end diff --git a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb index d5c0e89c6..374fcd65b 100644 --- a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb +++ b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb @@ -16,7 +16,7 @@ begin require 'xapian' $acts_as_xapian_bindings_available = true rescue LoadError - STDERR.puts "acts_as_xapian: No Ruby bindings for Xapian installed" + STDERR.puts "acts_as_xapian: No Ruby bindings for Xapian installed" $acts_as_xapian_bindings_available = false end @@ -46,6 +46,9 @@ module ActsAsXapian def ActsAsXapian.db @@db end + def ActsAsXapian.db_path=(db_path) + @@db_path = db_path + end def ActsAsXapian.db_path @@db_path end @@ -110,14 +113,14 @@ module ActsAsXapian end # Opens / reopens the db for reading - # XXX we perhaps don't need to rebuild database and enquire and queryparser - + # XXX we perhaps don't need to rebuild database and enquire and queryparser - # but db.reopen wasn't enough by itself, so just do everything it's easier. def ActsAsXapian.readable_init raise NoXapianRubyBindingsError.new("Xapian Ruby bindings not installed") unless ActsAsXapian.bindings_available raise "acts_as_xapian hasn't been called in any models" if @@init_values.empty? - + prepare_environment - + # We need to reopen the database each time, so Xapian gets changes to it. # Calling reopen() does not always pick up changes for reasons that I can # only speculate about at the moment. (It is easy to reproduce this by @@ -126,7 +129,7 @@ module ActsAsXapian if !@@db.nil? @@db.close end - + # basic Xapian objects begin @@db = Xapian::Database.new(@@db_path) @@ -188,7 +191,7 @@ module ActsAsXapian # If making acts_as_xapian generic, would really need to make the :terms have # another option that lets people choose non-boolean for terms that need it # (i.e. searching explicitly within a free text field) - @@query_parser.add_boolean_prefix(term[2], term[1]) + @@query_parser.add_boolean_prefix(term[2], term[1]) end end if options[:values] @@ -198,9 +201,9 @@ module ActsAsXapian # date types are special, mark them so the first model they're seen for if !@@values_by_number.include?(value[1]) - if value[3] == :date + if value[3] == :date value_range = Xapian::DateValueRangeProcessor.new(value[1]) - elsif value[3] == :string + elsif value[3] == :string value_range = Xapian::StringValueRangeProcessor.new(value[1]) elsif value[3] == :number value_range = Xapian::NumberValueRangeProcessor.new(value[1]) @@ -212,7 +215,7 @@ module ActsAsXapian # stop it being garbage collected, as # add_valuerangeprocessor ref is outside Ruby's GC - @@value_ranges_store.push(value_range) + @@value_ranges_store.push(value_range) end @@values_by_number[value[1]] = value[2] @@ -230,7 +233,7 @@ module ActsAsXapian # again XXX reopen it each time, xapian_spec.rb needs this so database # gets written twice correctly. # return unless @@writable_db.nil? - + prepare_environment full_path = @@db_path + suffix @@ -246,7 +249,7 @@ module ActsAsXapian ###################################################################### # Search with a query or for similar models - + # Base class for Search and Similar below class QueryBase attr_accessor :offset @@ -271,12 +274,12 @@ module ActsAsXapian # Set self.query before calling this def initialize_query(options) #raise options.to_yaml - + self.runtime += Benchmark::realtime { offset = options[:offset] || 0; offset = offset.to_i limit = options[:limit] raise "please specifiy maximum number of results to return with parameter :limit" if not limit - limit = limit.to_i + limit = limit.to_i sort_by_prefix = options[:sort_by_prefix] || nil sort_by_ascending = options[:sort_by_ascending].nil? ? true : options[:sort_by_ascending] collapse_by_prefix = options[:collapse_by_prefix] || nil @@ -313,7 +316,7 @@ module ActsAsXapian tries += 1 delay *= 2 delay = MSET_MAX_DELAY if delay > MSET_MAX_DELAY - + ActsAsXapian.db.reopen() retry else @@ -336,7 +339,7 @@ module ActsAsXapian for t in self.query.terms term = t.term #x = x + term.to_yaml + term.size.to_s + term[0..0] + "*" - if term.size >= 2 && term[0..0] == 'Z' + if term.size >= 2 && term[0..0] == 'Z' # normal terms begin Z (for stemmed), then have no capital letter prefix if term[1..1] == term[1..1].downcase ret = true @@ -372,8 +375,8 @@ module ActsAsXapian # Pull out all the results iter = self.matches._begin while not iter.equals(self.matches._end) - docs.push({:data => iter.document.data, - :percent => iter.percent, + docs.push({:data => iter.document.data, + :percent => iter.percent, :weight => iter.weight, :collapse_count => iter.collapse_count}) iter.next @@ -403,14 +406,14 @@ module ActsAsXapian end # now get them in right order again results = [] - docs.each do |doc| + docs.each do |doc| k = doc[:data].split('-') model_instance = chash[[k[0], k[1].to_i]] if model_instance results << { :model => model_instance, - :percent => doc[:percent], - :weight => doc[:weight], - :collapse_count => doc[:collapse_count] } + :percent => doc[:percent], + :weight => doc[:weight], + :collapse_count => doc[:collapse_count] } end end self.cached_results = results @@ -428,7 +431,7 @@ module ActsAsXapian # essential to make sure the classes have been loaded, and thus # acts_as_xapian called on them, so we know the fields for the query # parser. - + # model_classes - model classes to search within, e.g. [PublicBody, # User]. Can take a single model class, or you can express the model # class names in strings if you like. @@ -443,7 +446,7 @@ module ActsAsXapian new_model_classes.push(model_class) end model_classes = new_model_classes - + # Set things up self.initialize_db @@ -518,7 +521,7 @@ module ActsAsXapian # object. This explains what exactly it does, which is to exclude # terms in the existing query. # http://thread.gmane.org/gmane.comp.search.xapian.general/3673/focus=3681 - eset = ActsAsXapian.enquire.eset(40, selection) + eset = ActsAsXapian.enquire.eset(40, selection) # Do main search for them self.important_terms = [] @@ -548,8 +551,8 @@ module ActsAsXapian ###################################################################### # Index - - # Offline indexing job queue model, create with migration made + + # Offline indexing job queue model, create with migration made # using "script/generate acts_as_xapian" as described in ../README.txt class ActsAsXapianJob < ActiveRecord::Base end @@ -561,7 +564,7 @@ module ActsAsXapian # logging in the database that it has been. def ActsAsXapian.update_index(flush = false, verbose = false) # STDOUT.puts("start of ActsAsXapian.update_index") if verbose - + # Before calling writable_init we have to make sure every model class has been initialized. # i.e. has had its class code loaded, so acts_as_xapian has been called inside it, and # we have the info from acts_as_xapian. @@ -621,17 +624,17 @@ module ActsAsXapian STDERR.puts(detail.backtrace.join("\n") + "\nFAILED ActsAsXapian.update_index job #{id} #{$!} " + (job.nil? ? "" : "model " + job.model + " id " + job.model_id.to_s)) end end - # We close the database when we're finished to remove the lock file. Since writable_init - # reopens it and recreates the environment every time we don't need to do further cleanup + # We close the database when we're finished to remove the lock file. Since writable_init + # reopens it and recreates the environment every time we don't need to do further cleanup ActsAsXapian.writable_db.flush ActsAsXapian.writable_db.close end - + def ActsAsXapian._is_xapian_db(path) is_db = File.exist?(File.join(path, "iamflint")) || File.exist?(File.join(path, "iamchert")) return is_db end - + # You must specify *all* the models here, this totally rebuilds the Xapian # database. You'll want any readers to reopen the database after this. # @@ -672,7 +675,7 @@ module ActsAsXapian end ActsAsXapian.writable_db.flush ActsAsXapian.writable_db.close - end + end # Rename into place temp_path = old_path + ".tmp" @@ -728,7 +731,7 @@ module ActsAsXapian model.xapian_index(terms, values, texts) end ActsAsXapian.writable_db.flush - ActsAsXapian.writable_db.close + ActsAsXapian.writable_db.close # database connection won't survive a fork, so shut it down ActiveRecord::Base.connection.disconnect! # brutal exit, so other shutdown code not run (for speed and safety) @@ -741,7 +744,7 @@ module ActsAsXapian ###################################################################### # Instance methods that get injected into your model. - + module InstanceMethods # Used internally def xapian_document_term @@ -755,7 +758,7 @@ module ActsAsXapian else values = [] for locale in self.translations.map{|x| x.locale} - self.class.with_locale(locale) do + self.class.with_locale(locale) do values << single_xapian_value(field, type=type) end end @@ -866,7 +869,7 @@ module ActsAsXapian end end end - + for term in terms_to_index value = xapian_value(term[0]) if value.kind_of?(Array) @@ -877,11 +880,11 @@ module ActsAsXapian doc.add_term(term[1] + value) end end - + if values - doc.clear_values + doc.clear_values for value in values_to_index - doc.add_value(value[1], xapian_value(value[0], value[3])) + doc.add_value(value[1], xapian_value(value[0], value[3])) end end if texts @@ -889,7 +892,7 @@ module ActsAsXapian for text in texts_to_index ActsAsXapian.term_generator.increase_termpos # stop phrases spanning different text fields # XXX the "1" here is a weight that could be varied for a boost function - ActsAsXapian.term_generator.index_text(xapian_value(text, nil, true), 1) + ActsAsXapian.term_generator.index_text(xapian_value(text, nil, true), 1) end end @@ -914,13 +917,13 @@ module ActsAsXapian job.save! end end - + # Allow reindexing to be skipped if a flag is set def xapian_mark_needs_index_if_reindex return true if (self.respond_to?(:no_xapian_reindex) && self.no_xapian_reindex == true) xapian_mark_needs_index end - + def xapian_mark_needs_destroy model = self.class.base_class.to_s model_id = self.id @@ -937,7 +940,7 @@ module ActsAsXapian ###################################################################### # Main entry point, add acts_as_xapian to your model. - + module ActsMethods # See top of this file for docs def acts_as_xapian(options) @@ -957,7 +960,7 @@ module ActsAsXapian after_destroy :xapian_mark_needs_destroy end end - + end # Reopen ActiveRecord and include the acts_as_xapian method |