diff --git a/.gitignore b/.gitignore index a6f254da74142..71ff25774a691 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ railties/doc/guides/html/images railties/doc/guides/html/stylesheets railties/guides/output .idea +pkg/*.gem diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 88d3ee7900c23..0000000000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -1.8.7 diff --git a/Gemfile b/Gemfile index 61d650044591f..63c7166937a2a 100644 --- a/Gemfile +++ b/Gemfile @@ -6,10 +6,10 @@ gem 'mocha', '=0.9.7' gem 'RedCloth', '=4.2.3' gem 'sqlite3', '=1.3.7' gem 'mysql', '=2.8.1' -gem 'rack', '=1.1.0' +gem 'rack', '< 1.5' gem 'pg', '=0.9.0' gem 'nokogiri', '1.3.3' gem 'libxml-ruby', '=1.1.4' # This is for running tests only. Update via "bundle update rails-version". -gem 'railslts-version' +gem 'railslts-version', '<3' diff --git a/Gemfile.lock b/Gemfile.lock index 3b29cd668731a..89657c0f43df7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,8 +8,8 @@ GEM mysql (2.8.1) nokogiri (1.3.3) pg (0.9.0) - rack (1.1.0) - railslts-version (2.3.18.8) + rack (1.4.6) + railslts-version (2.3.18.12) rake (0.8.7) rdoc (2.5.11) sqlite3 (1.3.7) @@ -24,8 +24,8 @@ DEPENDENCIES mysql (= 2.8.1) nokogiri (= 1.3.3) pg (= 0.9.0) - rack (= 1.1.0) - railslts-version + rack (< 1.5) + railslts-version (< 3) rake (= 0.8.7) rdoc (= 2.5.11) sqlite3 (= 1.3.7) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000..397d2681a640a --- /dev/null +++ b/LICENSE @@ -0,0 +1,40 @@ +The code in this project is based on Ruby on Rails 2.3 +with additional changes by makandra GmbH. + + Additional changes Copyright (c) 2013 makandra GmbH + + Permission is hereby granted as a sublicense of the original + MIT license of Ruby on Rails 2.3.18 (found below) to any person + obtaining a copy of this software and associated documentation + files (the "Software"), except the right to publish, distribute, + and/or sell copies of the Software before February 05, 2016. + + +The original code for Ruby on Rails 2.3 is licensed under the MIT license: + + Copyright (c) 2004-2010 David Heinemeier Hansson + + 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. + + +The original code for Ruby on Rails 2.3.18 can be obtained under the +following URL: + + https://github.com/rails/rails/tree/2-3-stable diff --git a/README.md b/README.md index 615158b4aad65..f2ef885360941 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ Rails LTS 2.3 ============= -Rails LTS 2.3 is a maintained release of Rails 2.3.18 that includes additional security fixes. See [https://railslts.com/](https://railslts.com) for more information. - -This is the public repository for the "Community Edition". It receives security patches with a 10 day delay. - +Rails LTS 2.3 is a maintained release of Rails 2.3 that includes additional security fixes. +See [https://railslts.com/](https://railslts.com) for more information. Pull Requests diff --git a/Rakefile b/Rakefile index c23104aadf17a..9cd24114e6a07 100644 --- a/Rakefile +++ b/Rakefile @@ -1,86 +1,27 @@ require 'rake' - -env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD'] - -PROJECTS = %w(activesupport railties actionpack actionmailer activeresource activerecord) - -Dir["#{File.dirname(__FILE__)}/*/lib/*/version.rb"].each do |version_path| - require version_path -end - -desc 'Run all tests by default' -task :default => :test - -%w(test rdoc pgem package release gem).each do |task_name| - desc "Run #{task_name} task for all projects" - task task_name do - PROJECTS.each do |project| - warn 'When running tests for Rails LTS, prefer running the "railslts:test" task.' - system %(cd #{project} && #{env} rake _#{RAKEVERSION}_ #{task_name}) or raise 'failed' - end - end -end - -if RAKEVERSION == '0.8.0' - require 'rake/rdoctask' - - # In order to generate the API please install Ruby 1.8.7 and rake 0.8.0. Then: - # - # rake _0.8.0_ task_name - # - # Reason is the Jamis template used for the API needs RDoc 1.x. Recent rake libs - # do not provide rake/rdoctask, and RDoc 1.x provides no alternative task. This - # is easy to setup with a Ruby version manager. - desc "Generate documentation for the Rails framework" - Rake::RDocTask.new do |rdoc| - rdoc.rdoc_dir = 'doc/rdoc' - rdoc.title = "Ruby on Rails Documentation" - rdoc.main = "railties/README" - - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.options << '-A cattr_accessor=object' - rdoc.options << '--charset' << 'utf-8' - rdoc.options << '--main' << 'railties/README' - - rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : './doc/template/horo' - - rdoc.rdoc_files.include('railties/CHANGELOG') - rdoc.rdoc_files.include('railties/LICENSE') - rdoc.rdoc_files.include('railties/README') - rdoc.rdoc_files.include('railties/lib/{*.rb,commands/*.rb,rails/*.rb,rails_generator/*.rb}') - - rdoc.rdoc_files.include('activerecord/README') - rdoc.rdoc_files.include('activerecord/CHANGELOG') - rdoc.rdoc_files.include('activerecord/lib/active_record/**/*.rb') - rdoc.rdoc_files.exclude('activerecord/lib/active_record/vendor/*') - - rdoc.rdoc_files.include('activeresource/README') - rdoc.rdoc_files.include('activeresource/CHANGELOG') - rdoc.rdoc_files.include('activeresource/lib/active_resource.rb') - rdoc.rdoc_files.include('activeresource/lib/active_resource/*') - - rdoc.rdoc_files.include('actionpack/README') - rdoc.rdoc_files.include('actionpack/CHANGELOG') - rdoc.rdoc_files.include('actionpack/lib/action_controller/**/*.rb') - rdoc.rdoc_files.include('actionpack/lib/action_view/**/*.rb') - rdoc.rdoc_files.exclude('actionpack/lib/action_controller/vendor/*') - - rdoc.rdoc_files.include('actionmailer/README') - rdoc.rdoc_files.include('actionmailer/CHANGELOG') - rdoc.rdoc_files.include('actionmailer/lib/action_mailer/base.rb') - rdoc.rdoc_files.exclude('actionmailer/lib/action_mailer/vendor/*') - - rdoc.rdoc_files.include('activesupport/README') - rdoc.rdoc_files.include('activesupport/CHANGELOG') - rdoc.rdoc_files.include('activesupport/lib/active_support/**/*.rb') - rdoc.rdoc_files.exclude('activesupport/lib/active_support/vendor/*') - end - - # Enhance rdoc task to copy referenced images also - task :rdoc do - FileUtils.mkdir_p "doc/rdoc/files/examples/" - FileUtils.copy "activerecord/examples/associations.png", "doc/rdoc/files/examples/associations.png" - end +require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' +require File.expand_path('../railslts-version/lib/railslts-version', __FILE__) + +BRANCH = '2-3-lts' +SUB_PROJECT_PATHS = %w(activesupport railties actionpack actionmailer activeresource activerecord railslts-version) +ALL_PROJECT_PATHS = ['.', *SUB_PROJECT_PATHS] + +fail = lambda { |message| + STDERR.puts "\e[31m#{message}\e[0m" # red + exit(1) +} + +run = lambda { |command| + info = command.sub(/:\/\/\w+\:[^@]+@/, '://...@') + puts "\e[35m#{info}\e[0m" # pink + result = system(command) + result or fail.call("Failed to execute `#{info}`") + true +} + +rails_gemspec = eval(File.read('rails.gemspec')) +Gem::PackageTask.new(rails_gemspec) do |p| + p.gem_spec = rails_gemspec end namespace :railslts do @@ -89,85 +30,109 @@ namespace :railslts do task :test do puts '', "\033[44m#{'activesupport'}\033[0m", '' - system('cd activesupport && rake test') or raise 'failed' + run.call('cd activesupport && rake test') puts '', "\033[44m#{'actionmailer'}\033[0m", '' - system('cd actionmailer && rake test') or raise 'failed' + run.call('cd actionmailer && rake test') puts '', "\033[44m#{'actionpack'}\033[0m", '' - system('cd actionpack && rake test') or raise 'failed' + run.call('cd actionpack && rake test') puts '', "\033[44m#{'activerecord (mysql)'}\033[0m", '' - system('cd activerecord && rake test_mysql') or raise 'failed' + run.call('cd activerecord && rake test_mysql') puts '', "\033[44m#{'activerecord (sqlite3)'}\033[0m", '' - system('cd activerecord && rake test_sqlite3') or raise 'failed' + run.call('cd activerecord && rake test_sqlite3') puts '', "\033[44m#{'activerecord (postgres)'}\033[0m", '' - system('cd activerecord && rake test_postgresql') or raise 'failed' + run.call('cd activerecord && rake test_postgresql') puts '', "\033[44m#{'activeresource'}\033[0m", '' - system('cd activeresource && rake test') or raise 'failed' + run.call('cd activeresource && rake test') puts '', "\033[44m#{'railties'}\033[0m", '' - system('cd railties && rake test') or raise 'failed' + run.call('cd railties && rake test') + + puts '', "\033[44m#{'railslts-version'}\033[0m", '' + run.call('cd railslts-version && rake test') end - task :clean_gems do - PROJECTS.each do |project| - pkg_folder = "#{project}/pkg" - puts "Emptying packages folder #{pkg_folder}..." - FileUtils.mkdir_p(pkg_folder) - system("rm -rf #{pkg_folder}/*") or raise "failed" + namespace :gems do + + # Clean previous .gem files in pkg/ folder of root and sub-projects + task :delete do + ALL_PROJECT_PATHS.each do |project| + pkg_folder = "#{project}/pkg" + puts "Emptying packages folder #{pkg_folder}..." + FileUtils.mkdir_p(pkg_folder) + run.call("rm -f #{pkg_folder}/*.gem") + end end - end - task :clean_building_artifacts do - PROJECTS.each do |project| - pkg_folder = "#{project}/pkg" - puts "Deleting building artifacts from #{pkg_folder}..." - system("rm -rf #{pkg_folder}/*.tgz") or raise "failed" # TGZ - system("rm -rf #{pkg_folder}/*.zip") or raise "failed" # ZIP - system("rm -rf #{pkg_folder}/*/") or raise "failed" # Folder + # Call :package task in sub-projects + task :package_all do + ALL_PROJECT_PATHS.each do |project| + run.call("cd #{project} && rake package") + end end - end - task :zip_gems do - puts "Zipping archive for manual installation..." - archive_name = "railslts.tar.gz" - system("cd dist && rm -f #{archive_name} && tar -czvhf #{archive_name} railslts/ && cd ..") or raise "failed" - end + # Clean up building artifacts left by :package tasks + task :clean_building_artifacts do + ALL_PROJECT_PATHS.each do |project| + pkg_folder = "#{project}/pkg" + puts "Deleting building artifacts from #{pkg_folder}..." + run.call("rm -rf #{pkg_folder}/*.tgz") # TGZ + run.call("rm -rf #{pkg_folder}/*.zip") # ZIP + run.call("rm -rf #{pkg_folder}/*/") # Folder + end + end + + # Move *.gem packages from sub-projects's pkg to root's pkg for easier releasing + task :consolidate do + SUB_PROJECT_PATHS.each do |project| + pkg_folder = "#{project}/pkg" + gem_path = "#{pkg_folder}/#{project}-#{RailsLts::VERSION::STRING}.gem" + puts "Moving .gem from #{gem_path} to pkg ..." + File.file?(gem_path) or fail.call("Not found: #{gem_path}") + consolidated_pkg_folder = 'pkg' + FileUtils.mkdir_p(consolidated_pkg_folder) + FileUtils.mv(gem_path, consolidated_pkg_folder) + end + end + + desc 'Builds *.gem packages for distribution without Git' + task :build => [:delete, :package_all, :consolidate, :clean_building_artifacts] do + puts 'Done.' + end - desc 'Builds *.gem packages for static distribution without Git' - task :build_gems => [:clean_gems, :package, :clean_building_artifacts, :zip_gems] do - puts "Done." end desc 'Updates the LICENSE file in individual sub-projects' task :update_license do require 'date' last_change = Date.parse(`git log -1 --format=%cd`) - PROJECTS.each do |project| + ALL_PROJECT_PATHS.each do |project| + next if project == 'railslts-version' # has no LICENSE file license_path = "#{project}/LICENSE" puts "Updating license #{license_path}..." - File.exists?(license_path) or raise "Could not find license: #{license_path}" + File.exists?(license_path) or fail.call("Could not find license: #{license_path}") license = File.read(license_path) - license.sub!(/ before(.*?)\./ , " before #{(last_change + 10).strftime("%B %d, %Y")}.") or raise "Couldn't find timestamp." + license.sub!(/ before(.*?)\./ , " before #{(last_change + 10).strftime("%B %d, %Y")}.") or fail.call("Couldn't find timestamp.") File.open(license_path, "w") { |w| w.write(license) } end end - namespace :release do + namespace :customer do task :ensure_ready do jobs = [ - 'Did you release a new version of https://github.com/makandra/railslts-version ?', - 'Did you bump the required "railslts-version" dependency in railties.gemspec?', - 'Did you update the LICENSE files using `rake railslts:update_license`?', - 'Did you build static gems using `rake railslts:build_gems`?', + "Did you update the version in railslts-version/lib/railslts-version.rb (currently #{RailsLts::VERSION::STRING})?", + 'Did you update the LICENSE files using `rake railslts:update_license?', 'Did you commit and push your changes, as well as the changes by the Rake tasks mentioned above?', - 'Are you sure the 3-0-lts branch is either unchanged or ready to release as well?', + 'Did you build static gems using `rake railslts:gems:build` (those are not pushed to Git)?', + 'Did you activate key forwarding for *.gems.makandra.de?', + "We will now publish the Rails LTS #{RailsLts::VERSION::STRING} for customers. Ready?", ] puts @@ -177,41 +142,81 @@ namespace :railslts do answer = STDIN.gets puts unless answer.strip == 'y' - $stderr.puts "Aborting. Nothing was released." + $stderr.puts 'Aborting. Nothing was released.' puts exit end end end - - desc "Publish new Rails LTS customer release on gems.makandra.de/railslts" - task :customer => :ensure_ready do - for hostname in %w[c23 c42] + task :push_to_git_repo do + %w[c23 c42 c32 c24].each do |hostname| fqdn = "#{hostname}.gems.makandra.de" puts "\033[1mUpdating #{fqdn}...\033[0m" - command = '/opt/update_railslts.sh' - system "ssh deploy-gems_p@#{fqdn} '#{command}'" - puts "done." + command = "cd /var/www/railslts && git fetch origin #{BRANCH}:#{BRANCH}" + run.call "ssh deploy-gems_p@#{fqdn} '#{command}'" + puts 'Done.' end - puts "Deployment done." - puts "Check https://gem.makandra.de/railtslts" + puts 'Gems pushed to customer Git repo.' + puts "Now run `git clone -b #{BRANCH} https://gems.makandra.de/railslts #{BRANCH}-test-checkout`" + puts 'and make sure your commits are present.' + end + + task :push_to_gem_server do + print 'Enter password for railslts-gems-admin.makandra.de: ' + begin + system('stty -echo') + password = $stdin.gets.chomp + ensure + system('stty echo') + end + server_url = "https://admin:#{password}@railslts-gems-admin.makandra.de" + gem_paths = Dir.glob('pkg/*.gem') + gem_paths.size == ALL_PROJECT_PATHS.size or fail.call("Expected #{ALL_PROJECT_PATHS.size} .gem files, but only got #{gem_paths.inspect}") + gem_paths.each do |gem_path| + puts "Publishing #{gem_path}" + # Hide STDOUT since that will print the server URL including the password + run.call("gem push #{gem_path} --host #{server_url} > /dev/null") + end end - desc "Publish new Rails LTS community release on github.com/makandra/rails" - task :community => :ensure_ready do + desc "Publish Rails LTS #{RailsLts::VERSION::STRING} for customers" + task :release => [:ensure_ready, :push_to_git_repo, :push_to_gem_server] + + end + + namespace :community do + + task :push_to_git_repo do existing_remotes = `git remote` unless existing_remotes.include?('community') - system('git remote add community git@github.com:makandra/rails.git') or raise "Couldn't add remote'" + run.call('git remote add community git@github.com:makandra/rails.git') end - system('git fetch community && git push community 2-3-lts') or raise 'Error while publishing' - puts "Deployment done." - puts "Check https://github.com/makandra/rails/tree/2-3-lts" + run.call('git fetch community') + + puts 'We will now publish the following changes to GitHub:' + puts + run.call("git log --oneline community/#{BRANCH}..HEAD") + puts + + puts 'Do you want to proceed? [y/n]' + answer = STDIN.gets + puts + unless answer.strip == 'y' + $stderr.puts 'Aborting. Nothing was released.' + puts + exit + end + + run.call("git push community #{BRANCH}") + puts 'Gems pushed to community github repo.' + puts "Check https://github.com/makandra/rails/tree/#{BRANCH} and make sure your commits are present" end + desc "Publish Rails LTS #{RailsLts::VERSION::STRING} for community subscribers" + task :release => :push_to_git_repo + end end - - diff --git a/actionmailer/LICENSE b/actionmailer/LICENSE index a33dc476de368..397d2681a640a 100644 --- a/actionmailer/LICENSE +++ b/actionmailer/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,10 +7,10 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. -The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: +The original code for Ruby on Rails 2.3 is licensed under the MIT license: Copyright (c) 2004-2010 David Heinemeier Hansson diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index 76870954ec226..ed329f2e6ff61 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -4,10 +4,11 @@ require 'rake/testtask' require 'rake/packagetask' require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' require File.join(File.dirname(__FILE__), 'lib', 'action_mailer', 'version') +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'actionmailer' -PKG_VERSION = ActionMailer::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" RELEASE_NAME = "REL #{PKG_VERSION}" @@ -55,7 +56,7 @@ spec = Gem::Specification.new do |s| s.rubyforge_project = "actionmailer" s.homepage = "http://www.rubyonrails.org" - s.add_dependency('actionpack', '= 2.3.18' + PKG_BUILD) + s.add_dependency('actionpack', "= #{PKG_VERSION}") s.has_rdoc = true s.requirements << 'none' @@ -73,23 +74,3 @@ package_task.new(spec) do |p| p.need_tar = true p.need_zip = true end - - -desc "Publish the API documentation" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 09c79f35da00d..449e69433d735 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -1,6 +1,8 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| s.name = 'actionmailer' - s.version = '2.3.18' + s.version = RailsLts::VERSION::STRING s.summary = 'Service layer for easy email delivery and testing.' s.description = 'Makes it trivial to test and deliver emails sent from a single service layer.' @@ -10,5 +12,5 @@ Gem::Specification.new do |s| s.require_path = 'lib' - s.add_dependency 'actionpack', '= 2.3.18' + s.add_dependency 'actionpack', "= #{RailsLts::VERSION::STRING}" end diff --git a/actionmailer/pkg/actionmailer-2.3.18.gem b/actionmailer/pkg/actionmailer-2.3.18.gem deleted file mode 100644 index d0d3b9dbd5584..0000000000000 Binary files a/actionmailer/pkg/actionmailer-2.3.18.gem and /dev/null differ diff --git a/actionpack/LICENSE b/actionpack/LICENSE index a33dc476de368..397d2681a640a 100644 --- a/actionpack/LICENSE +++ b/actionpack/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,10 +7,10 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. -The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: +The original code for Ruby on Rails 2.3 is licensed under the MIT license: Copyright (c) 2004-2010 David Heinemeier Hansson diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 66cd6d72955d9..076ceedb64553 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -4,10 +4,11 @@ require 'rake/testtask' require 'rake/packagetask' require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' require File.join(File.dirname(__FILE__), 'lib', 'action_pack', 'version') +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'actionpack' -PKG_VERSION = ActionPack::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" RELEASE_NAME = "REL #{PKG_VERSION}" @@ -81,8 +82,8 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.requirements << 'none' - s.add_dependency('activesupport', '= 2.3.18' + PKG_BUILD) - s.add_dependency('rack', '~> 1.1.0') + s.add_dependency('activesupport', "= #{PKG_VERSION}") + s.add_dependency('rack', '< 1.5') s.require_path = 'lib' s.autorequire = 'action_controller' @@ -123,35 +124,3 @@ task :lines do puts "Total: Lines #{total_lines}, LOC #{total_codelines}" end - -# Publishing ------------------------------------------------------ - -task :update_scriptaculous do - for js in %w( controls dragdrop effects ) - system("svn export --force http://dev.rubyonrails.org/svn/rails/spinoffs/scriptaculous/src/#{js}.js #{File.dirname(__FILE__)}/lib/action_view/helpers/javascripts/#{js}.js") - end -end - -desc "Updates actionpack to the latest version of the javascript spinoffs" -task :update_js => [ :update_scriptaculous ] - -# Publishing ------------------------------------------------------ - -desc "Publish the API documentation" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 0172ab7473772..d71a7e5351f61 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -1,6 +1,8 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| s.name = 'actionpack' - s.version = '2.3.18' + s.version = RailsLts::VERSION::STRING s.summary = 'Web-flow and rendering framework putting the VC in MVC.' s.description = 'Eases web-request routing, handling, and response as a half-way front, half-way page controller. Implemented with specific emphasis on enabling easy unit/integration testing that doesn\'t require a browser.' @@ -10,6 +12,6 @@ Gem::Specification.new do |s| s.require_path = 'lib' - s.add_dependency 'activesupport', '= 2.3.18' - s.add_dependency 'rack', '~> 1.2.0' + s.add_dependency 'activesupport', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'rack', '< 1.5' end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index f3c00d5c61b11..bd79df5b06481 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -31,7 +31,7 @@ end end -gem 'rack', '~> 1.2.0' +gem 'rack', '< 1.5' require 'rack' require 'action_controller/cgi_ext' diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb index 017626ba272af..faeb76ab2bc98 100644 --- a/actionpack/lib/action_controller/mime_type.rb +++ b/actionpack/lib/action_controller/mime_type.rb @@ -2,8 +2,8 @@ module Mime SET = [] - EXTENSION_LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? } - LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? } + EXTENSION_LOOKUP = {} + LOOKUP = {} # Encapsulates the notion of a mime type. Can be used at render time, for example, with: # @@ -27,7 +27,7 @@ class Type # only needs to protect against these types. @@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text] cattr_reader :browser_generated_types - + attr_reader :symbol @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml] def self.unverifiable_types @@ -63,11 +63,16 @@ def ==(item) class << self def lookup(string) - LOOKUP[string] + type = LOOKUP[string] + type ||= Type.new(string) if string.present? + type end def lookup_by_extension(extension) - EXTENSION_LOOKUP[extension] + extension = extension.to_s + type = EXTENSION_LOOKUP[extension] + type ||= Type.new(extension) if extension.present? + type end # Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for @@ -143,10 +148,13 @@ def parse(accept_header) end end end + + attr_reader :hash def initialize(string, symbol = nil, synonyms = []) @symbol, @synonyms = symbol, synonyms @string = string + @hash = [@string, @synonyms, @symbol].hash end def to_s @@ -176,6 +184,13 @@ def ==(mime_type) end end + def eql?(other) + super || (self.class == other.class && + @string == other.string && + @synonyms == other.synonyms && + @symbol == other.symbol) + end + def =~(mime_type) return false if mime_type.blank? regexp = Regexp.new(Regexp.quote(mime_type.to_s)) @@ -198,6 +213,14 @@ def browser_generated? @@browser_generated_types.include?(to_sym) end + def respond_to?(method, include_private = false) #:nodoc: + super || method.to_s =~ /(\w+)\?$/ + end + + protected + + attr_reader :string, :synonyms + private def method_missing(method, *args) if method.to_s =~ /(\w+)\?$/ diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index ccee26047ee50..f06365e36c8ce 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -568,11 +568,11 @@ def to_time_zone_select_tag(priority_zones, options, html_options) private def add_options(option_tags, options, value = nil) if options[:include_blank] - option_tags = content_tag('option', options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, :value => '') + "\n" + option_tags + option_tags = content_tag_string('option', options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, :value => '') + "\n".html_safe + option_tags end if value.blank? && options[:prompt] prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('support.select.prompt', :default => 'Please select') - option_tags = content_tag('option', prompt, :value => '') + "\n" + option_tags + option_tags = content_tag_string('option', prompt, :value => '') + "\n".html_safe + option_tags end option_tags end diff --git a/actionpack/pkg/actionpack-2.3.18.gem b/actionpack/pkg/actionpack-2.3.18.gem deleted file mode 100644 index 33bdf39680a6e..0000000000000 Binary files a/actionpack/pkg/actionpack-2.3.18.gem and /dev/null differ diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb index f517fdfe135b9..a9146ace494ed 100644 --- a/actionpack/test/controller/cookie_test.rb +++ b/actionpack/test/controller/cookie_test.rb @@ -123,7 +123,7 @@ def test_not_setting_cookie_with_secure def test_multiple_cookies get :set_multiple_cookies assert_equal 2, @response.cookies.size - assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT", @response.headers["Set-Cookie"][0] + assert_equal "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT\n", @response.headers["Set-Cookie"][0] assert_equal "login=XJ-122; path=/", @response.headers["Set-Cookie"][1] assert_equal({"login" => "XJ-122", "user_name" => "david"}, @response.cookies) end diff --git a/actionpack/test/controller/html-scanner/sanitizer_test.rb b/actionpack/test/controller/html-scanner/sanitizer_test.rb index f72f66efa8f84..6edbe8b19f92f 100644 --- a/actionpack/test/controller/html-scanner/sanitizer_test.rb +++ b/actionpack/test/controller/html-scanner/sanitizer_test.rb @@ -82,6 +82,27 @@ def test_should_allow_anchors assert_sanitized %(), %() end + # Test for CVE-2015-7578 + # The sanitizer of this version of Rails LTS is not affected. We add some tests to confirm this. + # While the video tag is not officially supported by the sanitizer of this version of Rails LTS, + # applications might have been configured to allow videos tags containing poster URIs as below. + def test_video_poster_sanitization + old_allowed_tags = HTML::WhiteListSanitizer.allowed_tags + old_allowed_attributes = HTML::WhiteListSanitizer.allowed_attributes + old_uri_attributes = HTML::WhiteListSanitizer.uri_attributes + + HTML::WhiteListSanitizer.allowed_tags = ['video'] + HTML::WhiteListSanitizer.allowed_attributes = ['poster', 'src'] + HTML::WhiteListSanitizer.uri_attributes << 'poster' + + assert_sanitized %(), %() + assert_sanitized %(), %() + ensure + HTML::WhiteListSanitizer.allowed_tags = old_allowed_tags + HTML::WhiteListSanitizer.allowed_attributes = old_allowed_attributes + HTML::WhiteListSanitizer.uri_attributes = old_uri_attributes + end + # RFC 3986, sec 4.2 def test_allow_colons_in_path_component assert_sanitized("foo") @@ -284,7 +305,54 @@ def test_x03a assert_sanitized %(), %() end + def test_sanitize_data_attributes + assert_sanitized %(foo), %(foo) + assert_sanitized %(Launch the missiles), %(Launch the missiles) + end + + def test_allow_data_attribute_if_requested + text = %(foo) + assert_equal %(foo), white_list_sanitize(text, :attributes => ['data-foo']) + end + + # Test for CVE-2015-7579 + # The sanitizer of this version of Rails LTS is not affected. We add some tests to confirm this. + def test_full_sanitize_respect_html_escaping_of_the_given_string + sanitizer = HTML::FullSanitizer.new + assert_equal 'test\r\nstring', sanitizer.sanitize('test\r\nstring') + assert_equal '&', sanitizer.sanitize('&', :encode_special_chars => false) + assert_equal '&', sanitizer.sanitize('&') + assert_equal '&amp;', sanitizer.sanitize('&amp;') + assert_equal 'omg <script>BOM</script>', sanitizer.sanitize('omg <script>BOM</script>') + end + + # Test for CVE-2015-7580 + # The sanitizer of this version of Rails LTS is not affected. We add some tests to confirm this. + def test_sanitize_nested_script + sanitizer = HTML::WhiteListSanitizer.new + assert_equal '', sanitizer.sanitize('alert("XSS");/', :tags => %w(em)) + assert_equal '', sanitizer.sanitize('alert("XSS");/', :tags => %w(em)) + end + + # Test for CVE-2015-7580 + # The sanitizer of this version of Rails LTS is not affected. We add some tests to confirm this. + def test_sanitize_nested_script_in_style + sanitizer = HTML::WhiteListSanitizer.new + + # Behaves differently than rails-html-sanitizer; output is still acceptable as it does not allow XSS. + assert_equal 'alert("XSS");</script>', sanitizer.sanitize('alert("XSS");/', :tags => %w(em)) + + # Another test to confirm that the style tags' cdata will be sanitized well enough to avoid XSS: + assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('scriptalert("XSS");/script', :tags => %w(em)) + assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('scriptalert("XSS");/script', :tags => %w(em)) + end + protected + + def white_list_sanitize(input, options = {}) + HTML::WhiteListSanitizer.new.sanitize(input, options) + end + def assert_sanitized(input, expected = nil) @sanitizer ||= HTML::WhiteListSanitizer.new if input diff --git a/actionpack/test/controller/mime_type_test.rb b/actionpack/test/controller/mime_type_test.rb index c7faa621d96da..15d9c29e8c622 100644 --- a/actionpack/test/controller/mime_type_test.rb +++ b/actionpack/test/controller/mime_type_test.rb @@ -60,6 +60,7 @@ def test_type_convenience_methods types.each do |type| mime = Mime.const_get(type.to_s.upcase) + assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?" assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?" invalid_types = types - [type] invalid_types.delete(:html) if Mime::Type.html_types.include?(type) diff --git a/actionpack/test/controller/request/multipart_params_parsing_test.rb b/actionpack/test/controller/request/multipart_params_parsing_test.rb index 46aee37831395..0d2bc62f11b2f 100644 --- a/actionpack/test/controller/request/multipart_params_parsing_test.rb +++ b/actionpack/test/controller/request/multipart_params_parsing_test.rb @@ -98,9 +98,8 @@ def teardown assert_equal %w(files foo), params.keys.sort assert_equal 'bar', params['foo'] - # Ruby CGI doesn't handle multipart/mixed for us. + # Rack doesn't handle multipart/mixed for us. files = params['files'] - assert_kind_of Tempfile, files files.force_encoding('ASCII-8BIT') if files.respond_to?(:force_encoding) assert_equal 19756, files.size end diff --git a/actionpack/test/controller/session/cookie_store_test.rb b/actionpack/test/controller/session/cookie_store_test.rb index 8d02fffa7d200..c59c4b6088d4d 100644 --- a/actionpack/test/controller/session/cookie_store_test.rb +++ b/actionpack/test/controller/session/cookie_store_test.rb @@ -5,8 +5,6 @@ class CookieStoreTest < ActionController::IntegrationTest SessionKey = '_myapp_session' SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' - DispatcherApp = ActionController::Dispatcher.new - Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1') SignedBar = "BAh7BjoIZm9vIghiYXI%3D--fef868465920f415f2c0652d6910d3af288a0367" @@ -137,7 +135,7 @@ def test_getting_session_id get '/get_session_id' assert_response :success assert_equal "foo: \"bar\"; id: #{session_id}", response.body - + get '/get_session_id_only' assert_response :success assert_equal "id: #{session_id}", response.body, "should be able to read session id without accessing the session hash" @@ -279,9 +277,9 @@ def test_getting_from_nonexistent_session end end - # {:foo=>#, :session_id=>"ce8b0752a6ab7c7af3cdb8a80e6b9e46"} + # {:foo=>#, :session_id=>"ce8b0752a6ab7c7af3cdb8a80e6b9e46"} SignedSerializedCookie = "BAh7BzoIZm9vbzodU2Vzc2lvbkF1dG9sb2FkVGVzdDo6Rm9vBjoJQGJhciIIYmF6Og9zZXNzaW9uX2lkIiVjZThiMDc1MmE2YWI3YzdhZjNjZGI4YTgwZTZiOWU0Ng==--2bf3af1ae8bd4e52b9ac2099258ace0c380e601c" - + def test_deserializes_unloaded_classes_on_get_id with_test_route_set do with_autoload_path "session_autoload_test" do @@ -291,11 +289,11 @@ def test_deserializes_unloaded_classes_on_get_id assert_equal 'id: ce8b0752a6ab7c7af3cdb8a80e6b9e46', response.body, "should auto-load unloaded class" end end - end - + end + def test_deserializes_unloaded_classes_on_get_value with_test_route_set do - with_autoload_path "session_autoload_test" do + with_autoload_path "session_autoload_test" do cookies[SessionKey] = SignedSerializedCookie get '/get_session_value' assert_response :success @@ -335,10 +333,12 @@ def with_test_route_set(options = {}) c.connect "/:action" end end - + + app = ActionController::Dispatcher.new + options = { :key => SessionKey, :secret => SessionSecret }.merge!(options) - @integration_session = open_session(ActionController::Session::CookieStore.new(DispatcherApp, options)) - + @integration_session = open_session(ActionController::Session::CookieStore.new(app, options)) + yield end end diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index e2df39b439d9c..33c202bede796 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -801,25 +801,50 @@ def test_grouped_collection_select_under_fields_for ) end - def test_select_escapes_options + def test_select_escapes_options_with_xss_enabled + @post = Post.new assert_dom_equal( '', select_with_rails_xss('post', 'title', '') ) + assert_dom_equal( + '', + select_without_rails_xss('post', 'title', '') + ) end - def test_select_escapes_prompt + def test_select_escapes_prompt_with_xss_enabled + @post = Post.new assert_dom_equal( '', select_with_rails_xss('post', 'title', '', :prompt => '') ) + assert_dom_equal( + '', + select_without_rails_xss('post', 'title', '', :prompt => '') + ) end - def test_select_include_blank + def test_select_escapes_include_blank_with_xss_enabled + @post = Post.new assert_dom_equal( '', select_with_rails_xss('post', 'title', '', :include_blank => '') ) + + assert_dom_equal( + '', + select_without_rails_xss('post', 'title', '', :include_blank => '') + ) + end + + def test_select_does_not_wrap_option_in_error_proc + @post = Post.new + @post.stubs(:errors).returns(stub('errors', :on => ['an error'])) + assert_dom_equal( + '
', + select_with_rails_xss('post', 'title', '', :include_blank => '') + ) end private @@ -833,4 +858,8 @@ def dummy_posts def select_with_rails_xss(object, method, choices, options = {}, html_options = {}) RailsXssEmulation::InstanceTagWithRailsXss.new(object, method, self, options.delete(:object)).to_select_tag(choices, options, html_options) end + + def select_without_rails_xss(object, method, choices, options = {}, html_options = {}) + ActionView::Helpers::InstanceTag.new(object, method, self, options.delete(:object)).to_select_tag(choices, options, html_options) + end end diff --git a/activerecord/LICENSE b/activerecord/LICENSE index a33dc476de368..397d2681a640a 100644 --- a/activerecord/LICENSE +++ b/activerecord/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,10 +7,10 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. -The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: +The original code for Ruby on Rails 2.3 is licensed under the MIT license: Copyright (c) 2004-2010 David Heinemeier Hansson diff --git a/activerecord/Rakefile b/activerecord/Rakefile index c1c18245212f5..794f422fe9908 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -6,10 +6,11 @@ require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' require File.join(File.dirname(__FILE__), 'lib', 'active_record', 'version') require File.expand_path(File.dirname(__FILE__)) + "/test/config" +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'activerecord' -PKG_VERSION = ActiveRecord::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" RELEASE_NAME = "REL #{PKG_VERSION}" @@ -193,7 +194,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.3.18' + PKG_BUILD) + s.add_dependency('activesupport', "= #{PKG_VERSION}") s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" @@ -242,25 +243,3 @@ task :lines do puts "Total: Lines #{total_lines}, LOC #{total_codelines}" end - - -# Publishing ------------------------------------------------------ - -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 262524e14feab..9084b49f82506 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -1,6 +1,8 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| s.name = 'activerecord' - s.version = '2.3.18' + s.version = RailsLts::VERSION::STRING s.summary = 'Implements the ActiveRecord pattern for ORM.' s.description = 'Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.' @@ -13,5 +15,5 @@ Gem::Specification.new do |s| s.rdoc_options = ['--main', 'README'] s.extra_rdoc_files = ['README'] - s.add_dependency 'activesupport', '= 2.3.18' + s.add_dependency 'activesupport', "= #{RailsLts::VERSION::STRING}" end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 6b6d055b5a8c7..adebbe22ea0fc 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -517,7 +517,7 @@ def self.reset_subclasses #:nodoc: @@timestamped_migrations = true # Determine whether to store the full constant name including namespace when using STI - class_attribute :store_full_sti_class + class_attribute :store_full_sti_class, :instance_writer => false self.store_full_sti_class = false # Stores the default scope for the class @@ -1286,7 +1286,7 @@ def set_sequence_name(value = nil, &block) alias :sequence_name= :set_sequence_name # Turns the +table_name+ back into a class name following the reverse rules of +table_name+. - def class_name(table_name = table_name) # :nodoc: + def class_name(table_name = table_name()) # :nodoc: ActiveSupport::Deprecation.warn("ActiveRecord::Base#class_name is deprecated and will be removed in Rails 3.", caller) # remove any prefix and/or suffix from the table name diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index 535498f16b528..1d1444cc04fcd 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -10,7 +10,7 @@ def initialize (config, adapter_method) ## # :singleton-method: # The connection handler - class_attribute :connection_handler + class_attribute :connection_handler, :instance_writer => false self.connection_handler = ConnectionAdapters::ConnectionHandler.new # Returns the connection currently associated with the class. This can diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index a348318994743..fbf26b63f425b 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -352,9 +352,9 @@ def quote(value, column = nil) #:nodoc: "'#{value.to_s}'" elsif value.kind_of?(String) && column && column.sql_type =~ /^bit/ case value - when /^[01]*$/ + when /\A[01]*\z$/ "B'#{value}'" # Bit-string notation - when /^[0-9A-F]*$/i + when /\A[0-9A-F]*\z$/i "X'#{value}'" # Hexadecimal notation end else diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb index 1db8fef676c81..0d17e4e915125 100644 --- a/activerecord/lib/active_record/dirty.rb +++ b/activerecord/lib/active_record/dirty.rb @@ -44,7 +44,7 @@ def self.included(base) base.alias_method_chain :update, :dirty base.alias_method_chain :reload, :dirty - base.class_attribute :partial_updates + base.class_attribute :partial_updates, :instance_writer => false base.partial_updates = true base.send(:extend, ClassMethods) diff --git a/activerecord/pkg/activerecord-2.3.18.gem b/activerecord/pkg/activerecord-2.3.18.gem deleted file mode 100644 index 0f3dc7b9b709a..0000000000000 Binary files a/activerecord/pkg/activerecord-2.3.18.gem and /dev/null differ diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index f439f11c8a618..1ca7fe87756aa 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -111,6 +111,27 @@ def test_reject_if_with_indifferent_keys pirate.ship_attributes = { :name => 'Hello Pearl' } assert_difference('Ship.count') { pirate.save! } end + + # This test is all we can do for Rails 2.3 in regard to + # [CVE-2015-7577] Nested attributes rejection proc bypass in Active Record. + # + # In Rails 3+ you could skip over a :reject_if proc when the nested association + # had :allow_destroy => false and you're updating an existing record with :_destroy => 1. + # This might be used to change a record that the developer considers to be off limits + # due to the :reject_if condition. + # + # However, the Rails 2.3 API defines that :reject_if is never called for existing records, + # only for new records. Hence the developer cannot trust in any protection from :reject_if + # for existing record. + # + # The only (slightly awkward) test we can write for Rails 2.3 is that new records with + # :_destroy => true are immediately destroyed, even if :allow_destroy is false. + def test_reject_if_is_not_short_circuited_if_allow_destroy_is_false + Pirate.accepts_nested_attributes_for :ship, :reject_if => proc { |a| a[:name] == "The Golden Hind" }, :allow_destroy => false + pirate = Pirate.new(:catchphrase => "Arrr", :ship_attributes => { :name => "The Golden Hind", :_destroy => "1"}) + assert_no_difference('Ship.count') { pirate.save! } + end + end class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase diff --git a/activerecord/test/cases/quoting_test_postgresql.rb b/activerecord/test/cases/quoting_test_postgresql.rb new file mode 100644 index 0000000000000..f6fb12e18c40f --- /dev/null +++ b/activerecord/test/cases/quoting_test_postgresql.rb @@ -0,0 +1,46 @@ +require "cases/helper" +require 'models/bird' + +module ActiveRecord + module ConnectionAdapters + class PostgreSQLAdapter + class QuotingTest < ActiveRecord::TestCase + def setup + @conn = ActiveRecord::Base.connection + end + + def test_quote_true + c = PostgreSQLColumn.new(nil, 1, 'boolean') + assert_equal "'t'", @conn.quote(true, nil) + assert_equal "'t'", @conn.quote(true, c) + end + + def test_quote_false + c = PostgreSQLColumn.new(nil, 1, 'boolean') + assert_equal "'f'", @conn.quote(false, nil) + assert_equal "'f'", @conn.quote(false, c) + end + + def test_quote_range + # There is no range support on 2.3's PG adapter, but we still want to + # make sure that SQL injection is not possible since it was an issue + # on Rails 4.x. + # https://groups.google.com/d/msg/rubyonrails-security/wDxePLJGZdI/WP7EasCJTA4J + # + # Note that we can not test this using Connection#quote because + # ActiveRecord expands ranges into two bind variables that are + # quoted individually. + range = "1,2]'; SELECT * FROM users; --".."a" + sql = Bird.scoped(:conditions => { :name => range }).construct_finder_sql({}) + expected_sql = %{SELECT * FROM "birds" WHERE ("birds"."name" BETWEEN '1,2]''; SELECT * FROM users; --' AND 'a') } + assert_equal expected_sql, sql + end + + def test_quote_bit_string + c = PostgreSQLColumn.new(nil, 1, 'bit') + assert_equal nil, @conn.quote("'); SELECT * FORM users; /*\n01\n*/--", c) + end + end + end + end +end diff --git a/activeresource/LICENSE b/activeresource/LICENSE index a33dc476de368..20854341a1479 100644 --- a/activeresource/LICENSE +++ b/activeresource/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,7 +7,7 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: diff --git a/activeresource/Rakefile b/activeresource/Rakefile index 7e707929e4848..afd2c198815b9 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -5,10 +5,11 @@ require 'rake/packagetask' require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' require File.join(File.dirname(__FILE__), 'lib', 'active_resource', 'version') +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'activeresource' -PKG_VERSION = ActiveResource::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" RELEASE_NAME = "REL #{PKG_VERSION}" @@ -67,7 +68,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.3.18' + PKG_BUILD) + s.add_dependency('activesupport', "= #{PKG_VERSION}") s.require_path = 'lib' s.autorequire = 'active_resource' @@ -112,24 +113,3 @@ task :lines do puts "Total: Lines #{total_lines}, LOC #{total_codelines}" end - - -# Publishing ------------------------------------------------------ - -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - `rubyforge login` - - for ext in %w( gem tgz zip ) - release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" - puts release_command - system(release_command) - end -end diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec index b66a8205528fe..87d746d6d8e21 100644 --- a/activeresource/activeresource.gemspec +++ b/activeresource/activeresource.gemspec @@ -1,6 +1,8 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| s.name = 'activeresource' - s.version = '2.3.18' + s.version = RailsLts::VERSION::STRING s.summary = 'Think Active Record for web resources.' s.description = 'Wraps web resources in model classes that can be manipulated through XML over REST.' @@ -13,5 +15,5 @@ Gem::Specification.new do |s| s.rdoc_options = ['--main', 'README'] s.extra_rdoc_files = ['README'] - s.add_dependency 'activesupport', '= 2.3.18' + s.add_dependency 'activesupport', "= #{RailsLts::VERSION::STRING}" end diff --git a/activeresource/pkg/activeresource-2.3.18.gem b/activeresource/pkg/activeresource-2.3.18.gem deleted file mode 100644 index 586d5268e7b3c..0000000000000 Binary files a/activeresource/pkg/activeresource-2.3.18.gem and /dev/null differ diff --git a/activesupport/LICENSE b/activesupport/LICENSE index a33dc476de368..397d2681a640a 100644 --- a/activesupport/LICENSE +++ b/activesupport/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,10 +7,10 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. -The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: +The original code for Ruby on Rails 2.3 is licensed under the MIT license: Copyright (c) 2004-2010 David Heinemeier Hansson diff --git a/activesupport/Rakefile b/activesupport/Rakefile index b0b77a8711e13..1dd3f6ed2ef34 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -2,10 +2,11 @@ require 'rake/testtask' require RAKEVERSION == '0.8.0' ? 'rake/gempackagetask' : 'rubygems/package_task' require File.join(File.dirname(__FILE__), 'lib', 'active_support', 'version') +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'activesupport' -PKG_VERSION = ActiveSupport::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" RELEASE_NAME = "REL #{PKG_VERSION}" @@ -65,25 +66,6 @@ package_task.new(spec) do |p| p.need_zip = true end -desc "Publish the beta gem" -task :pgem => [:package] do - require 'rake/contrib/sshpublisher' - Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload - `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` -end - -desc "Publish the release files to RubyForge." -task :release => [ :package ] do - require 'rubyforge' - require 'rake/contrib/rubyforgepublisher' - - packages = %w( gem tgz zip ).collect{ |ext| "pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}" } - - rubyforge = RubyForge.new - rubyforge.login - rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages) -end - namespace :tzinfo do desc "Update bundled tzinfo gem. Only copies the subset of classes and definitions required to support Rails time zone features." task :update => ['tzinfo:copy_classes', 'tzinfo:copy_definitions'] do diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 7c326dd7ded92..d56bdb1603b28 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -1,6 +1,8 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| s.name = 'activesupport' - s.version = '2.3.18' + s.version = RailsLts::VERSION::STRING s.summary = 'Support and utility classes used by the Rails framework.' s.description = 'Utility library which carries commonly used classes and goodies from the Rails framework' diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 60587b9043073..eafe1dd10c5f0 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -73,7 +73,7 @@ def secure_compare(a, b) def generate_digest(data) require 'openssl' unless defined?(OpenSSL) - OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@digest), @secret, data) + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new(@digest), @secret, data) end end end diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index ccd1349491169..23e023d3b9cca 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -8,6 +8,9 @@ module XmlMini extend self attr_reader :backend + attr_accessor :depth + self.depth = 100 + delegate :parse, :to => :backend def backend=(name) diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index d795d556909e6..d499af6281ac6 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -35,7 +35,7 @@ def parse(string) xml_string_reader = StringReader.new(string) xml_input_source = InputSource.new(xml_string_reader) doc = @dbf.new_document_builder.parse(xml_input_source) - merge_element!({}, doc.document_element) + merge_element!({}, doc.document_element, XmlMini.depth) end end @@ -48,21 +48,22 @@ def parse(string) # element:: # XML element to merge into hash def merge_element!(hash, element) - merge!(hash, element.tag_name, collapse(element)) + raise 'Document too deep!' if depth == 0 + merge!(hash, element.tag_name, collapse(element, depth)) end # Actually converts an XML document element into a data structure. # # element:: # The document element to be collapsed. - def collapse(element) + def collapse(element, depth) hash = get_attributes(element) child_nodes = element.child_nodes if child_nodes.length > 0 for i in 0...child_nodes.length child = child_nodes.item(i) - merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE + merge_element!(hash, child, depth - 1) unless child.node_type == Node.TEXT_NODE end merge_texts!(hash, element) unless empty_content?(element) hash diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index a8fdeca9671ed..1700a6e7f1ec0 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -15,7 +15,7 @@ module XmlMini_REXML #:nodoc: def parse(string) require 'rexml/document' unless defined?(REXML::Document) doc = REXML::Document.new(string) - merge_element!({}, doc.root) + merge_element!({}, doc.root, XmlMini.depth) end private @@ -25,19 +25,20 @@ def parse(string) # Hash to merge the converted element into. # element:: # XML element to merge into hash - def merge_element!(hash, element) - merge!(hash, element.name, collapse(element)) + def merge_element!(hash, element, depth) + raise REXML::ParseException, "The document is too deep" if depth == 0 + merge!(hash, element.name, collapse(element, depth)) end # Actually converts an XML document element into a data structure. # # element:: # The document element to be collapsed. - def collapse(element) + def collapse(element, depth) hash = get_attributes(element) if element.has_elements? - element.each_element {|child| merge_element!(hash, child) } + element.each_element {|child| merge_element!(hash, child, depth - 1) } merge_texts!(hash, element) unless empty_content?(element) hash else diff --git a/activesupport/pkg/activesupport-2.3.18.gem b/activesupport/pkg/activesupport-2.3.18.gem deleted file mode 100644 index 6b3d85f26f4d9..0000000000000 Binary files a/activesupport/pkg/activesupport-2.3.18.gem and /dev/null differ diff --git a/activesupport/test/core_ext/file_test.rb b/activesupport/test/core_ext/file_test.rb index eedc6b592b2a5..45193581df633 100644 --- a/activesupport/test/core_ext/file_test.rb +++ b/activesupport/test/core_ext/file_test.rb @@ -23,6 +23,10 @@ def test_atomic_write_doesnt_write_when_block_raises end def test_atomic_write_preserves_file_permissions + if Dir.pwd.starts_with?('/vagrant') + $stderr.puts "Can't test file permissions on a vagrant share" + return + end contents = "Atomic Text" File.open(file_name, "w", 0755) do |file| file.write(contents) @@ -44,6 +48,10 @@ def test_atomic_write_preserves_file_permissions end def test_atomic_write_preserves_default_file_permissions + if Dir.pwd.starts_with?('/vagrant') + $stderr.puts "Can't test file permissions on a vagrant share" + return + end contents = "Atomic Text" File.atomic_write(file_name, Dir.pwd) do |file| file.write(contents) diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index b8bc22652edff..cdb68d9b68039 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -78,6 +78,13 @@ def test_hash_encoding assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json end + def test_hash_keys_encoding + ActiveSupport.escape_html_entities_in_json = true + assert_equal "{\"\\u003C\\u003E\":\"\\u003C\\u003E\"}", ActiveSupport::JSON.encode("<>" => "<>") + ensure + ActiveSupport.escape_html_entities_in_json = false + end + def test_utf8_string_encoded_properly_when_kcode_is_utf8 with_kcode 'UTF8' do result = ActiveSupport::JSON.encode('€2.99') diff --git a/activesupport/test/xml_mini/jdom_engine_test.rb b/activesupport/test/xml_mini/jdom_engine_test.rb index b745228994a55..4f7be109e7c92 100644 --- a/activesupport/test/xml_mini/jdom_engine_test.rb +++ b/activesupport/test/xml_mini/jdom_engine_test.rb @@ -141,11 +141,27 @@ def test_children_with_non_adjacent_text eoxml end + def test_maximum_document_depth + attack_xml = '' + excessive_depth = 150 + excessive_depth.times do + attack_xml << '' + end + excessive_depth.times do + attack_xml << '' + end + assert_raise RuntimeError do + XmlMini.parse(attack_xml) + end + end + private + def assert_equal_rexml(xml) hash = XmlMini.with_backend('REXML') { XmlMini.parse(xml) } assert_equal(hash, XmlMini.parse(xml)) end + end else diff --git a/activesupport/test/xml_mini/rexml_engine_test.rb b/activesupport/test/xml_mini/rexml_engine_test.rb index a412d8ca05690..2331498948007 100644 --- a/activesupport/test/xml_mini/rexml_engine_test.rb +++ b/activesupport/test/xml_mini/rexml_engine_test.rb @@ -12,4 +12,19 @@ def test_set_rexml_as_backend XmlMini.backend = 'REXML' assert_equal XmlMini_REXML, XmlMini.backend end + + def test_maximum_document_depth + attack_xml = '' + excessive_depth = 150 + excessive_depth.times do + attack_xml << '' + end + excessive_depth.times do + attack_xml << '' + end + assert_raise REXML::ParseException do + XmlMini.parse(attack_xml) + end + end + end diff --git a/dist/railslts.tar.gz b/dist/railslts.tar.gz deleted file mode 100644 index babe35dd02431..0000000000000 Binary files a/dist/railslts.tar.gz and /dev/null differ diff --git a/dist/railslts/install b/dist/railslts/install deleted file mode 100755 index 72d8f5c7fe243..0000000000000 --- a/dist/railslts/install +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -echo "Installing Rails LTS gems..." -gem install --no-ri --no-rdoc pkg/activesupport*.gem && \ -gem install --no-ri --no-rdoc pkg/activerecord*.gem && \ -gem install --no-ri --no-rdoc pkg/actionpack*.gem && \ -gem install --no-ri --no-rdoc pkg/actionmailer*.gem && \ -gem install --no-ri --no-rdoc pkg/activeresource*.gem && \ -gem install --no-ri --no-rdoc pkg/rails*.gem -echo "Rails LTS gems installed." - diff --git a/dist/railslts/pkg/actionmailer.gem b/dist/railslts/pkg/actionmailer.gem deleted file mode 120000 index 6c630326496f1..0000000000000 --- a/dist/railslts/pkg/actionmailer.gem +++ /dev/null @@ -1 +0,0 @@ -../../../actionmailer/pkg/actionmailer-2.3.18.gem \ No newline at end of file diff --git a/dist/railslts/pkg/actionpack.gem b/dist/railslts/pkg/actionpack.gem deleted file mode 120000 index e1cda67213253..0000000000000 --- a/dist/railslts/pkg/actionpack.gem +++ /dev/null @@ -1 +0,0 @@ -../../../actionpack/pkg/actionpack-2.3.18.gem \ No newline at end of file diff --git a/dist/railslts/pkg/activerecord.gem b/dist/railslts/pkg/activerecord.gem deleted file mode 120000 index cb405e52c2cae..0000000000000 --- a/dist/railslts/pkg/activerecord.gem +++ /dev/null @@ -1 +0,0 @@ -../../../activerecord/pkg/activerecord-2.3.18.gem \ No newline at end of file diff --git a/dist/railslts/pkg/activeresource.gem b/dist/railslts/pkg/activeresource.gem deleted file mode 120000 index a5ddfc98904e4..0000000000000 --- a/dist/railslts/pkg/activeresource.gem +++ /dev/null @@ -1 +0,0 @@ -../../../activeresource/pkg/activeresource-2.3.18.gem \ No newline at end of file diff --git a/dist/railslts/pkg/activesupport.gem b/dist/railslts/pkg/activesupport.gem deleted file mode 120000 index eff54acce359a..0000000000000 --- a/dist/railslts/pkg/activesupport.gem +++ /dev/null @@ -1 +0,0 @@ -../../../activesupport/pkg/activesupport-2.3.18.gem \ No newline at end of file diff --git a/dist/railslts/pkg/rails.gem b/dist/railslts/pkg/rails.gem deleted file mode 120000 index 2abf7e761a483..0000000000000 --- a/dist/railslts/pkg/rails.gem +++ /dev/null @@ -1 +0,0 @@ -../../../railties/pkg/rails-2.3.18.gem \ No newline at end of file diff --git a/pushgems.rb b/pushgems.rb deleted file mode 100755 index 784aa5de68960..0000000000000 --- a/pushgems.rb +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby - -unless ARGV.first == "no_build" - build_number = Time.now.strftime("%Y%m%d%H%M%S").to_i -end - -%w( activeresource actionmailer actionpack activerecord railties activesupport ).each do |pkg| - puts "Pushing: #{pkg} (#{build_number})" - if build_number - `cd #{pkg} && rm -rf pkg && PKG_BUILD=#{build_number} rake pgem && cd ..` - else - `cd #{pkg} && rm -rf pkg && rake pgem && cd ..` - end -end \ No newline at end of file diff --git a/rails.gemspec b/rails.gemspec new file mode 100644 index 0000000000000..e7b606ee53508 --- /dev/null +++ b/rails.gemspec @@ -0,0 +1,22 @@ +require File.expand_path('../railslts-version/lib/railslts-version', __FILE__) + +Gem::Specification.new do |s| + s.name = 'rails' + s.version = RailsLts::VERSION::STRING + s.summary = 'Full-stack web application framework.' + s.description = 'Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.' + + s.author = 'David Heinemeier Hansson' + s.email = 'david@loudthinking.com' + s.homepage = 'http://www.rubyonrails.org' + + s.files = [ "README.md", "LICENSE" ] + + s.add_dependency 'activesupport', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'activerecord', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'actionpack', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'actionmailer', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'activeresource', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'railties', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'railslts-version', "= #{RailsLts::VERSION::STRING}" +end diff --git a/railslts-version/Rakefile b/railslts-version/Rakefile new file mode 100644 index 0000000000000..fcba1ba0517c0 --- /dev/null +++ b/railslts-version/Rakefile @@ -0,0 +1,11 @@ +require "bundler/gem_tasks" + +task :package => :build do + # Building gems from the project root expects all subprojects + # to have a :package task. Since the task from bundler/gem_tasks + # is named :build, we simply delegate by depending on :build. +end + +task :test do + RailsLts::VERSION::STRING =~ /^2\.3\.\d+\.\d+$/ or raise 'Unexpected version string' +end diff --git a/railslts-version/lib/railslts-version.rb b/railslts-version/lib/railslts-version.rb new file mode 100644 index 0000000000000..ab791b445ea48 --- /dev/null +++ b/railslts-version/lib/railslts-version.rb @@ -0,0 +1,19 @@ +module RailsLts + module VERSION + # Because of the we way we're requiring this files in .gemspecs, + # it might be loaded multiple times when installing over Git. + unless defined?(STRING) + + MAJOR = 2 + MINOR = 3 + TINY = 18 + LTS = 15 + STRING = [MAJOR, MINOR, TINY, LTS].join('.') + + def self.to_s + STRING + end + + end + end +end diff --git a/railslts-version/railslts-version.gemspec b/railslts-version/railslts-version.gemspec new file mode 100644 index 0000000000000..2d918ba751eb7 --- /dev/null +++ b/railslts-version/railslts-version.gemspec @@ -0,0 +1,23 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'railslts-version' + +Gem::Specification.new do |spec| + spec.name = "railslts-version" + spec.version = RailsLts::VERSION::STRING + spec.authors = ["Arne Hartherz"] + spec.email = ["arne.hartherz@makandra.de"] + spec.summary = "Gem to track your current Rails LTS version." + spec.description = "Note that this gem will neither install nor upgrade Rails LTS for you. Visit https://railslts.com/ to find out more about Rails LTS." + spec.homepage = "https://railslts.com/" + spec.license = "MIT" + + spec.files = `git ls-files -z`.split("\x0") + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ["lib"] + + spec.add_development_dependency "bundler", "~> 1.5" + spec.add_development_dependency "rake" +end diff --git a/railties/LICENSE b/railties/LICENSE index a33dc476de368..397d2681a640a 100644 --- a/railties/LICENSE +++ b/railties/LICENSE @@ -1,4 +1,4 @@ -The code in this project is based on Ruby on Rails 2.3.18 +The code in this project is based on Ruby on Rails 2.3 with additional changes by makandra GmbH. Additional changes Copyright (c) 2013 makandra GmbH @@ -7,10 +7,10 @@ with additional changes by makandra GmbH. MIT license of Ruby on Rails 2.3.18 (found below) to any person obtaining a copy of this software and associated documentation files (the "Software"), except the right to publish, distribute, - and/or sell copies of the Software before May 30, 2014. + and/or sell copies of the Software before February 05, 2016. -The original code for Ruby on Rails 2.3.18 is licensed under the MIT license: +The original code for Ruby on Rails 2.3 is licensed under the MIT license: Copyright (c) 2004-2010 David Heinemeier Hansson diff --git a/railties/Rakefile b/railties/Rakefile index 066aba4853d27..fd20ce2414059 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -6,10 +6,11 @@ require 'date' require 'rbconfig' require File.join(File.dirname(__FILE__), 'lib/rails', 'version') +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'rails' -PKG_VERSION = Rails::VERSION::STRING + PKG_BUILD +PKG_VERSION = RailsLts::VERSION::STRING + PKG_BUILD PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" PKG_DESTINATION = ENV["RAILS_PKG_DESTINATION"] || "../#{PKG_NAME}" @@ -308,21 +309,14 @@ PKG_FILES = FileList[ spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY - s.name = 'rails' + s.name = 'railties' s.version = PKG_VERSION - s.summary = "Web-application framework with template engine, control-flow layer, and ORM." - s.description = <<-EOF - Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick - on top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates. - EOF + s.summary = 'Tools for creating, working with, and running Rails applications.' + s.description = 'Rails internals: application bootup, plugins, generators, and rake tasks.' s.add_dependency('rake', '>= 0.8.3') - s.add_dependency('activesupport', '= 2.3.18' + PKG_BUILD) - s.add_dependency('activerecord', '= 2.3.18' + PKG_BUILD) - s.add_dependency('actionpack', '= 2.3.18' + PKG_BUILD) - s.add_dependency('actionmailer', '= 2.3.18' + PKG_BUILD) - s.add_dependency('activeresource', '= 2.3.18' + PKG_BUILD) - s.add_dependency('railslts-version', '= 2.3.18.10') + s.add_dependency('activesupport', "= #{RailsLts::VERSION::STRING}") + s.add_dependency('actionpack', "= #{RailsLts::VERSION::STRING}") s.rdoc_options << '--exclude' << '.' s.has_rdoc = false @@ -336,7 +330,6 @@ spec = Gem::Specification.new do |s| s.author = "David Heinemeier Hansson" s.email = "david@loudthinking.com" s.homepage = "http://www.rubyonrails.org" - s.rubyforge_project = "rails" end package_task = RAKEVERSION == '0.8.0' ? Rake::GemPackageTask : Gem::PackageTask diff --git a/railties/lib/rails/rack/static.rb b/railties/lib/rails/rack/static.rb index f07c6beb5e4db..3c4eb3f024961 100644 --- a/railties/lib/rails/rack/static.rb +++ b/railties/lib/rails/rack/static.rb @@ -15,13 +15,13 @@ def call(env) method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - if file_exist?(path) + if file_exist_within_root?(path) return @file_server.call(env) else cached_path = directory_exist?(path) ? "#{path}/index" : path cached_path += ::ActionController::Base.page_cache_extension - if file_exist?(cached_path) + if file_exist_within_root?(cached_path) env['PATH_INFO'] = cached_path return @file_server.call(env) end @@ -32,8 +32,26 @@ def call(env) end private - def file_exist?(path) - full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path)) + + PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact) + + def clean_path_info(path_info) + parts = path_info.split PATH_SEPS + + clean = [] + + parts.each do |part| + next if part.empty? || part == '.' + part == '..' ? clean.pop : clean << part + end + + clean.unshift '/' if parts.empty? || parts.first.empty? + + ::File.join(*clean) + end + + def file_exist_within_root?(path) + full_path = File.join(@file_server.root, clean_path_info(::Rack::Utils.unescape(path))) File.file?(full_path) && File.readable?(full_path) end diff --git a/railties/pkg/rails-2.3.18.gem b/railties/pkg/rails-2.3.18.gem deleted file mode 100644 index f49ce64115339..0000000000000 Binary files a/railties/pkg/rails-2.3.18.gem and /dev/null differ diff --git a/railties/railties.gemspec b/railties/railties.gemspec index 83007a7fd83cd..c80a098cb2b5d 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -1,8 +1,10 @@ +require File.expand_path('../../railslts-version/lib/railslts-version', __FILE__) + Gem::Specification.new do |s| - s.name = 'rails' - s.version = '2.3.18' - s.summary = 'Web-application framework with template engine, control-flow layer, and ORM.' - s.description = "Rails is a framework for building web-application using CGI, FCGI, mod_ruby, or WEBrick\non top of either MySQL, PostgreSQL, SQLite, DB2, SQL Server, or Oracle with eRuby- or Builder-based templates." + s.name = 'railties' + s.version = RailsLts::VERSION::STRING + s.summary = 'Tools for creating, working with, and running Rails applications.' + s.description = 'Rails internals: application bootup, plugins, generators, and rake tasks.' s.author = 'David Heinemeier Hansson' s.email = 'david@loudthinking.com' @@ -14,10 +16,6 @@ Gem::Specification.new do |s| s.rdoc_options = ['--exclude', '.'] s.add_dependency 'rake', '>= 0.8.3' - s.add_dependency 'activesupport', '= 2.3.18' - s.add_dependency 'activerecord', '= 2.3.18' - s.add_dependency 'actionpack', '= 2.3.18' - s.add_dependency 'actionmailer', '= 2.3.18' - s.add_dependency 'activeresource', '= 2.3.18' - s.add_dependency 'railslts-version', '= 2.3.18.10' + s.add_dependency 'activesupport', "= #{RailsLts::VERSION::STRING}" + s.add_dependency 'actionpack', "= #{RailsLts::VERSION::STRING}" end diff --git a/railties/test/rack_static_test.rb b/railties/test/rack_static_test.rb index b1bcef97fe7ed..6f0cad9204f89 100644 --- a/railties/test/rack_static_test.rb +++ b/railties/test/rack_static_test.rb @@ -5,12 +5,18 @@ require 'fileutils' class RackStaticTest < ActiveSupport::TestCase + def setup + @non_public_path = "#{RAILS_ROOT}/non_public_file.html" FileUtils.cp_r "#{RAILS_ROOT}/fixtures/public", "#{RAILS_ROOT}/public" + File.open(@non_public_path, 'w') do |file| + file.puts "non public content" + end end def teardown FileUtils.rm_rf "#{RAILS_ROOT}/public" + FileUtils.rm(@non_public_path) end DummyApp = lambda { |env| @@ -40,6 +46,38 @@ def teardown assert_equal "/foo/index.html", get("/foo") end + test "does not betray the existance of files outside root" do + path = "../non_public_file.html" + assert File.exist?(File.join(RAILS_ROOT, 'public', path)) + assert_equal get("/nofile"), get(path) + end + + test "does not betray the existance of unreadable files" do + begin + filename = 'unreadable.html.erb' + target = File.join(RAILS_ROOT, 'public', filename) + FileUtils.touch target + File.expects(:readable?).with(target).returns(false).at_least_once + assert File.exist? target + assert !File.readable?(target) + path = "/#{filename}" + assert_equal get("/nofile"), get(path) + ensure + File.unlink target + end + end + + test "does not betray the existance of files outside root when using alternate path separators" do + if Dir.pwd.starts_with?('/vagrant') + $stderr.puts "Can't test file permissions on a vagrant share" + return + end + filename = 'non_public_file.html' + assert File.exist?(File.join(RAILS_ROOT, filename)) + path = "/%5C..%2F#{filename}" + assert_equal get("/nofile"), get(path) + end + private def get(path) Rack::MockRequest.new(App).request("GET", path).body diff --git a/release.rb b/release.rb deleted file mode 100755 index e8e6c01c35575..0000000000000 --- a/release.rb +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env ruby - -VERSION = ARGV.first -PACKAGES = %w(activesupport activerecord actionpack actionmailer activeresource) - -# Copy source -`mkdir release` -(PACKAGES + %w(railties)).each do |p| - `cp -R #{p} release/#{p}` -end - -# Create Rails packages -`cd release/railties && rake template=jamis package` - -# Upload documentation -`cd release/rails/doc/api && scp -r * davidhh@wrath.rubyonrails.com:public_html/api` - -# Upload packages -(PACKAGES + %w(railties)).each do |p| - `cd release/#{p} && echo "Releasing #{p}" && rake release` -end - -# Upload rails tgz/zip -`rubyforge add_release rails rails 'REL #{VERSION}' release/rails-#{VERSION}.tgz` -`rubyforge add_release rails rails 'REL #{VERSION}' release/rails-#{VERSION}.zip` \ No newline at end of file