From 0df1b8663e9bd79525bee3b7f2ae1d777c72ecac Mon Sep 17 00:00:00 2001 From: Kenshi Muto Date: Sun, 2 Sep 2018 00:07:55 +0900 Subject: [PATCH 1/2] add a feature to review-init to take/extract zip package from local and network. Closes #1102 --- lib/review/init.rb | 72 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/lib/review/init.rb b/lib/review/init.rb index c2575a08c..931349c3a 100644 --- a/lib/review/init.rb +++ b/lib/review/init.rb @@ -8,6 +8,8 @@ require 'fileutils' require 'optparse' +require 'net/http' +require 'tempfile' require 'review' module ReVIEW @@ -38,6 +40,7 @@ def execute(*args) generate_rakefile(dir) generate_gemfile(dir) generate_doc(dir) unless @without_doc + download_and_extract_archive(dir, @archive) if @archive end end @@ -58,12 +61,15 @@ def parse_options(args) opts.on('--latex-template name', 'specify LaTeX template name. (default: review-jsbook)') do |tname| @template = tname end - opts.on('', '--epub-version VERSION', 'define EPUB version') do |version| + opts.on('', '--epub-version VERSION', 'define EPUB version.') do |version| @epub_version = version end - opts.on('', '--without-doc', "don't generate doc files") do + opts.on('', '--without-doc', "don't generate doc files.") do @without_doc = true end + opts.on('-p', '--package archivefile', 'extract from local or network archive.') do |archive| + @archive = archive + end begin opts.parse!(args) @@ -190,5 +196,67 @@ def generate_doc(dir) md_files = Dir.glob(@review_dir + '/doc/*.md').map.to_a FileUtils.cp md_files, docdir end + + def download_and_extract_archive(dir, filename) + begin + require 'zip' + rescue LoadError + @logger.error 'extracting needs rubyzip.' + exit 1 + end + + if filename =~ %r{\Ahttps?://} + begin + @logger.info "Downloading from #{filename}" + zipdata = Net::HTTP.get(URI.parse(filename)) + rescue StandardError => err + @logger.error "Failed to download #{filename}: #{err.message}" + exit 1 + end + + begin + f = Tempfile.new('reviewinit') + zipfilename = f.path + f.write zipdata + f.close + + extract_archive(dir, zipfilename, filename) + ensure + f.unlink + end + else + unless File.readable?(filename) + @logger.error "Failed to open #{filename}" + exit 1 + end + extract_archive(dir, filename, filename) + end + end + + def extract_archive(dir, filename, originalfilename) + made = nil + begin + Zip::File.open(filename) do |zip| + zip.each do |entry| + fname = entry.name.gsub('\\', '/') + if fname =~ /__MACOSX/ || fname =~ /\.DS_Store/ + next + end + + if fname =~ %r{\A/} || fname =~ %r{/\.\./} # simple fool proof + made = nil + break + end + + # `true' means override + entry.extract(File.join(dir, fname)) { true } + end + made = true + end + raise Zip::Error unless made + rescue Zip::Error => err + @logger.error "#{originalfilename} seems invalid or broken zip file: #{err.message}" + end + end end end From f4735ad84ae144b1c820b93fcf9eaefb5a207e73 Mon Sep 17 00:00:00 2001 From: Kenshi Muto Date: Sun, 2 Sep 2018 12:43:28 +0900 Subject: [PATCH 2/2] reject .. in name. --- lib/review/init.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/review/init.rb b/lib/review/init.rb index 931349c3a..9f13006a9 100644 --- a/lib/review/init.rb +++ b/lib/review/init.rb @@ -243,7 +243,7 @@ def extract_archive(dir, filename, originalfilename) next end - if fname =~ %r{\A/} || fname =~ %r{/\.\./} # simple fool proof + if fname =~ %r{\A/} || fname =~ /\.\./ # simple fool proof made = nil break end