@@ -378,7 +378,7 @@ def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc:
378378 File . dirname destination
379379 end
380380
381- FileUtils . mkdir_p mkdir , mkdir_options
381+ mkdir_p_safe mkdir , mkdir_options , destination_dir , entry . full_name
382382
383383 File . open destination , 'wb' do |out |
384384 out . write entry . read
@@ -416,13 +416,10 @@ def install_location filename, destination_dir # :nodoc:
416416 raise Gem ::Package ::PathError . new ( filename , destination_dir ) if
417417 filename . start_with? '/'
418418
419- destination_dir = File . realpath destination_dir if
420- File . respond_to? :realpath
419+ destination_dir = realpath destination_dir
421420 destination_dir = File . expand_path destination_dir
422421
423422 destination = File . join destination_dir , filename
424- destination = File . realpath destination if
425- File . respond_to? :realpath
426423 destination = File . expand_path destination
427424
428425 raise Gem ::Package ::PathError . new ( destination , destination_dir ) unless
@@ -432,6 +429,22 @@ def install_location filename, destination_dir # :nodoc:
432429 destination
433430 end
434431
432+ def mkdir_p_safe mkdir , mkdir_options , destination_dir , file_name
433+ destination_dir = realpath File . expand_path ( destination_dir )
434+ parts = mkdir . split ( File ::SEPARATOR )
435+ parts . reduce do |path , basename |
436+ path = realpath path unless path == ""
437+ path = File . expand_path ( path + File ::SEPARATOR + basename )
438+ lstat = File . lstat path rescue nil
439+ if !lstat || !lstat . directory?
440+ unless path . start_with? destination_dir and ( FileUtils . mkdir path , mkdir_options rescue false )
441+ raise Gem ::Package ::PathError . new ( file_name , destination_dir )
442+ end
443+ end
444+ path
445+ end
446+ end
447+
435448 ##
436449 # Loads a Gem::Specification from the TarEntry +entry+
437450
@@ -622,6 +635,16 @@ def verify_gz entry # :nodoc:
622635 raise Gem ::Package ::FormatError . new ( e . message , entry . full_name )
623636 end
624637
638+ if File . respond_to? :realpath
639+ def realpath file
640+ File . realpath file
641+ end
642+ else
643+ def realpath file
644+ file
645+ end
646+ end
647+
625648end
626649
627650require 'rubygems/package/digest_io'
0 commit comments