Add source and destination directory protection #535

Merged
merged 2 commits into from Dec 26, 2012
View
10 lib/jekyll/site.rb
@@ -70,6 +70,12 @@ def reset
def setup
require 'classifier' if self.lsi
+ # Check that the destination dir isn't the source dir or a directory
+ # parent to the source dir.
+ if self.source =~ /^#{self.dest}/
+ raise FatalException.new "Destination directory cannot be or contain the Source directory."
+ end
+
# If safe mode is off, load in any Ruby files under the plugins
# directory.
unless self.safe
@@ -215,8 +221,8 @@ def render
def cleanup
# all files and directories in destination, including hidden ones
dest_files = Set.new
- Dir.glob(File.join(self.dest, "**", "*"), File::FNM_DOTMATCH) do |file|
- dest_files << file unless file =~ /\/\.{1,2}$/
+ Dir.glob(File.join(self.dest, "**", "*")) do |file|
+ dest_files << file
end
# files to be written
View
26 test/test_site.rb
@@ -166,13 +166,33 @@ class TestSite < Test::Unit::TestCase
assert_equal files, @site.filter_entries(files)
end
+ context 'error handling' do
+ should "raise if destination is included in source" do
+ stub(Jekyll).configuration do
+ Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => source_dir})
+ end
+
+ assert_raise Jekyll::FatalException do
+ site = Site.new(Jekyll.configuration)
+ end
+ end
+
+ should "raise if destination is source" do
+ stub(Jekyll).configuration do
+ Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => File.join(source_dir, "..")})
+ end
+
+ assert_raise Jekyll::FatalException do
+ site = Site.new(Jekyll.configuration)
+ end
+ end
+ end
+
context 'with orphaned files in destination' do
setup do
clear_dest
@site.process
# generate some orphaned files:
- # hidden file
- File.open(dest_dir('.htpasswd'), 'w')
# single file
File.open(dest_dir('obsolete.html'), 'w')
# single file in sub directory
@@ -183,15 +203,13 @@ class TestSite < Test::Unit::TestCase
end
teardown do
- FileUtils.rm_f(dest_dir('.htpasswd'))
FileUtils.rm_f(dest_dir('obsolete.html'))
FileUtils.rm_rf(dest_dir('qux'))
FileUtils.rm_f(dest_dir('quux'))
end
should 'remove orphaned files in destination' do
@site.process
- assert !File.exist?(dest_dir('.htpasswd'))
assert !File.exist?(dest_dir('obsolete.html'))
assert !File.exist?(dest_dir('qux'))
assert !File.exist?(dest_dir('quux'))