epzip 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6532a1347f807c8b3ef8a83b43defb9793ae7648eb3c350533230191c93f13ea
4
+ data.tar.gz: 955f21763b1b83e0808508843d852bc222fd205ca81631fa38d545267f0153ac
5
+ SHA512:
6
+ metadata.gz: 2e2a63c218531a117aac7c423f2e7aeb99fd76ba513cb86d8288986b77ea80016f8fd389b6cbcffb1dba544749a42f3154b36555c7806da4ff175986858bade8
7
+ data.tar.gz: 52861041f0025cb7f9f6d68cb6ddb34c81f93930287e6290b1517129f2eac3919c22833480adf6626b6401c4f8d5ead8e1da522a0edaf3e3b88a6aa219d586fa
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "20:00"
8
+ open-pull-requests-limit: 10
@@ -0,0 +1,37 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', '4.0']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v7
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ uses: ruby/setup-ruby@v1
33
+ with:
34
+ ruby-version: ${{ matrix.ruby-version }}
35
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
36
+ - name: Run tests
37
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -17,5 +17,7 @@ tmtags
17
17
  coverage
18
18
  rdoc
19
19
  pkg
20
+ *.gem
21
+ /Gemfile.lock
20
22
 
21
23
  ## PROJECT::SPECIFIC
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Runtime dependencies are declared in epzip.gemspec.
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'rake'
8
+ gem 'test-unit'
9
+ end
data/Rakefile CHANGED
@@ -1,55 +1,10 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "epzip"
8
- gem.summary = %Q{simple EPUB packing tool}
9
- gem.description = %Q{epzip is EPUB packing tool. It's just only to do 'zip.'}
10
- gem.email = "takahashimm@gmail.com"
11
- gem.homepage = "http://github.com/takahashim/epzip"
12
- gem.authors = ["Masayoshi Takahashi"]
13
-
14
- gem.add_dependency('rubyzip', '>= 0.9.4')
15
-
16
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
- end
18
- Jeweler::GemcutterTasks.new
19
- rescue LoadError
20
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
- end
22
-
1
+ require "bundler/gem_tasks"
23
2
  require 'rake/testtask'
24
- Rake::TestTask.new(:test) do |test|
25
- test.libs << 'lib' << 'test'
26
- test.pattern = 'test/**/test_*.rb'
27
- test.verbose = true
28
- end
29
3
 
30
- begin
31
- require 'rcov/rcovtask'
32
- Rcov::RcovTask.new do |test|
33
- test.libs << 'test'
34
- test.pattern = 'test/**/test_*.rb'
35
- test.verbose = true
36
- end
37
- rescue LoadError
38
- task :rcov do
39
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
- end
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'lib' << 'test'
6
+ t.pattern = 'test/**/test_*.rb'
7
+ t.verbose = true
41
8
  end
42
9
 
43
- task :test => :check_dependencies
44
-
45
- task :default => :test
46
-
47
- require 'rake/rdoctask'
48
- Rake::RDocTask.new do |rdoc|
49
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
-
51
- rdoc.rdoc_dir = 'rdoc'
52
- rdoc.title = "epzip #{version}"
53
- rdoc.rdoc_files.include('README*')
54
- rdoc.rdoc_files.include('lib/**/*.rb')
55
- end
10
+ task default: :test
data/bin/epunzip CHANGED
@@ -1,12 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
3
2
 
4
- require 'rubygems'
5
3
  require 'epzip'
6
4
 
7
5
  def error_and_exit(msg)
8
- STDERR.puts msg
9
- exit
6
+ warn msg
7
+ exit 1
10
8
  end
11
9
 
12
10
  def usage()
@@ -18,12 +16,12 @@ if !(ARGV.size == 1 or ARGV.size == 2)
18
16
  end
19
17
 
20
18
  file = ARGV.shift
21
- if !File.exists? file
19
+ if !File.exist? file
22
20
  error_and_exit "No such file: #{file}"
23
21
  end
24
22
 
25
23
  dir = ARGV.shift
26
- if dir and File.exists? dir
24
+ if dir and File.exist? dir
27
25
  error_and_exit "Directory already exists: #{dir}"
28
26
  end
29
27
 
data/bin/epzip CHANGED
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
3
2
 
4
- require 'rubygems'
5
3
  require 'epzip'
6
4
 
7
5
  def error_and_exit(msg)
8
- STDERR.puts msg
9
- exit
10
- end
6
+ warn msg
7
+ exit 1
8
+ end
11
9
 
12
10
  def usage()
13
11
  error_and_exit "usage: epzip <srcdir> [filename]"
@@ -18,12 +16,12 @@ if !(ARGV.size == 1 or ARGV.size == 2)
18
16
  end
19
17
 
20
18
  dir = ARGV.shift
21
- if !File.exists? dir
19
+ if !File.exist? dir
22
20
  error_and_exit "No such directory: #{dir}"
23
21
  end
24
22
 
25
23
  file = ARGV.shift
26
- if file and File.exists? file
24
+ if file and File.exist? file
27
25
  error_and_exit "File already exists: #{file}"
28
26
  end
29
27
 
data/epzip.gemspec CHANGED
@@ -1,57 +1,22 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
5
2
 
3
+ require_relative "lib/epzip/version"
4
+
6
5
  Gem::Specification.new do |s|
7
- s.name = %q{epzip}
8
- s.version = "0.7.1"
6
+ s.name = "epzip"
7
+ s.version = Epzip::VERSION
8
+ s.authors = ["Masayoshi Takahashi"]
9
+ s.email = "takahashimm@gmail.com"
10
+ s.homepage = "https://github.com/takahashim/epzip"
11
+ s.summary = "simple EPUB packing tool"
12
+ s.description = "epzip is an EPUB packing tool. It's just only to do 'zip.'"
13
+ s.license = "MIT"
14
+
15
+ s.required_ruby_version = ">= 2.6"
9
16
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Masayoshi Takahashi"]
12
- s.date = %q{2010-10-03}
13
- s.description = %q{epzip is EPUB packing tool. It's just only to do 'zip.'}
14
- s.email = %q{takahashimm@gmail.com}
17
+ s.files = `git ls-files -z`.split("\x0")
15
18
  s.executables = ["epunzip", "epzip"]
16
- s.extra_rdoc_files = [
17
- "LICENSE",
18
- "README.rdoc"
19
- ]
20
- s.files = [
21
- ".document",
22
- ".gitignore",
23
- "LICENSE",
24
- "README.rdoc",
25
- "Rakefile",
26
- "VERSION",
27
- "bin/epunzip",
28
- "bin/epzip",
29
- "epzip.gemspec",
30
- "lib/epzip.rb",
31
- "test/helper.rb",
32
- "test/test_epzip.rb"
33
- ]
34
- s.homepage = %q{http://github.com/takahashim/epzip}
35
- s.rdoc_options = ["--charset=UTF-8"]
36
19
  s.require_paths = ["lib"]
37
- s.rubygems_version = %q{1.3.7}
38
- s.summary = %q{simple EPUB packing tool}
39
- s.test_files = [
40
- "test/helper.rb",
41
- "test/test_epzip.rb"
42
- ]
43
20
 
44
- if s.respond_to? :specification_version then
45
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
- s.specification_version = 3
47
-
48
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
- s.add_runtime_dependency(%q<rubyzip>, [">= 0.9.4"])
50
- else
51
- s.add_dependency(%q<rubyzip>, [">= 0.9.4"])
52
- end
53
- else
54
- s.add_dependency(%q<rubyzip>, [">= 0.9.4"])
55
- end
21
+ s.add_runtime_dependency "rubyzip", ">= 1.0", "< 3.0"
56
22
  end
57
-
@@ -0,0 +1,3 @@
1
+ class Epzip
2
+ VERSION = "0.9.0"
3
+ end
data/lib/epzip.rb CHANGED
@@ -1,59 +1,60 @@
1
- require 'rubygems'
2
- require 'zip/zip'
1
+ require 'zip'
2
+ require 'fileutils'
3
+ require 'epzip/version'
3
4
 
4
5
  class Epzip
5
- MIMETYPE_FILENAME = 'mimetype'
6
-
6
+ MIMETYPE_FILENAME = 'mimetype'.freeze
7
+ MIMETYPE_CONTENT = 'application/epub+zip'.freeze
8
+
7
9
  def self.zip(epubdir, epubfile = nil)
8
- if !File.exists? epubdir
10
+ unless File.exist?(epubdir)
9
11
  raise ArgumentError, "No such directory -- #{epubdir}"
10
12
  end
11
13
 
12
- epubfile ||= epubdir+".epub"
13
-
14
- Zip::ZipOutputStream.open(epubfile) do |f|
14
+ epubfile ||= epubdir + ".epub"
15
15
 
16
- f.put_next_entry(MIMETYPE_FILENAME, nil, nil, Zip::ZipEntry::STORED)
17
- f << "application/epub+zip"
18
- puts MIMETYPE_FILENAME
16
+ Zip::OutputStream.open(epubfile) do |zos|
17
+ # The mimetype entry must come first and be stored uncompressed.
18
+ zos.put_next_entry(MIMETYPE_FILENAME, nil, nil, Zip::Entry::STORED)
19
+ zos << MIMETYPE_CONTENT
19
20
 
20
21
  Dir.chdir(epubdir) do
21
- Dir.glob("**/*") do |dir|
22
- next if dir == MIMETYPE_FILENAME
23
- next if !File.file? dir
24
- puts dir
25
- f.put_next_entry dir
26
- f << File.read(dir)
22
+ Dir.glob("**/*") do |path|
23
+ next if path == MIMETYPE_FILENAME
24
+ next unless File.file?(path)
25
+
26
+ zos.put_next_entry(path)
27
+ zos << File.binread(path)
27
28
  end
28
29
  end
29
30
  end
30
31
 
31
32
  epubfile
32
-
33
33
  end
34
34
 
35
35
  def self.unzip(epubfile, epubdir = nil)
36
- if epubdir
37
- FileUtils.mkdir_p(epubdir)
38
- else
39
- epubdir = Dir.pwd
40
- end
36
+ epubdir ||= Dir.pwd
37
+ FileUtils.mkdir_p(epubdir)
41
38
 
42
- Zip::ZipInputStream.open(epubfile) do |f|
43
- while entry = f.get_next_entry
44
- next if entry.directory?
45
- next if entry.name[-1] == "/"
46
- sep = "/"
47
- if entry.name[0] == "/"
48
- sep = ""
39
+ root = File.expand_path(epubdir)
40
+
41
+ Zip::File.open(epubfile) do |zip|
42
+ zip.each do |entry|
43
+ next if entry.name_is_directory?
44
+
45
+ filepath = File.expand_path(File.join(epubdir, entry.name))
46
+ # Guard against Zip Slip: rubyzip skips its own name check when an
47
+ # explicit destination path is given, so reject entries that would
48
+ # escape the target directory.
49
+ unless filepath == root || filepath.start_with?(root + File::SEPARATOR)
50
+ raise ArgumentError, "Illegal entry name -- #{entry.name}"
49
51
  end
50
- filepath = epubdir + sep + entry.name
51
- dir = File.dirname(filepath)
52
- FileUtils.mkdir_p(dir)
53
- entry.extract(filepath)
52
+
53
+ FileUtils.mkdir_p(File.dirname(filepath))
54
+ entry.extract(filepath) { true }
54
55
  end
55
56
  end
56
57
 
58
+ epubdir
57
59
  end
58
-
59
60
  end
data/test/helper.rb CHANGED
@@ -1,9 +1,2 @@
1
- require 'rubygems'
2
1
  require 'test/unit'
3
-
4
- $LOAD_PATH.unshift(File.dirname(__FILE__))
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
2
  require 'epzip'
7
-
8
- class Test::Unit::TestCase
9
- end
data/test/test_epzip.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'helper'
2
+ require 'tmpdir'
3
+ require 'fileutils'
2
4
 
3
5
  class TestEpzip < Test::Unit::TestCase
4
6
  def test_zip_should_use_existed_dir
@@ -6,4 +8,63 @@ class TestEpzip < Test::Unit::TestCase
6
8
  Epzip.zip("unknown_dir")
7
9
  end
8
10
  end
11
+
12
+ def test_unzip_rejects_path_traversal_entry
13
+ Dir.mktmpdir do |base|
14
+ # Craft an archive with an entry that escapes the target directory.
15
+ evil = File.join(base, "evil.zip")
16
+ Zip::File.open(evil, Zip::File::CREATE) do |zip|
17
+ zip.get_output_stream("../escaped.txt") { |os| os.write("pwned") }
18
+ end
19
+
20
+ dest = File.join(base, "out")
21
+ assert_raise ArgumentError do
22
+ Epzip.unzip(evil, dest)
23
+ end
24
+ assert !File.exist?(File.join(base, "escaped.txt")), "must not write outside dest"
25
+ end
26
+ end
27
+
28
+ def test_zip_and_unzip_roundtrip
29
+ Dir.mktmpdir do |base|
30
+ src = File.join(base, "book")
31
+ FileUtils.mkdir_p(File.join(src, "META-INF"))
32
+ FileUtils.mkdir_p(File.join(src, "OEBPS"))
33
+ File.write(File.join(src, "META-INF", "container.xml"), "<container/>\n")
34
+ File.write(File.join(src, "OEBPS", "content.opf"), "<package/>\n")
35
+ File.binwrite(File.join(src, "OEBPS", "img.bin"), (0..255).to_a.pack("C*"))
36
+
37
+ epub = File.join(base, "out.epub")
38
+ assert_equal epub, Epzip.zip(src, epub)
39
+ assert File.exist?(epub)
40
+
41
+ dest = File.join(base, "unpacked")
42
+ Epzip.unzip(epub, dest)
43
+
44
+ %w[META-INF/container.xml OEBPS/content.opf OEBPS/img.bin].each do |rel|
45
+ assert File.exist?(File.join(dest, rel)), "#{rel} extracted"
46
+ assert_equal File.binread(File.join(src, rel)),
47
+ File.binread(File.join(dest, rel)),
48
+ "#{rel} content matches"
49
+ end
50
+ end
51
+ end
52
+
53
+ def test_zip_stores_mimetype_first_and_uncompressed
54
+ Dir.mktmpdir do |base|
55
+ src = File.join(base, "book")
56
+ FileUtils.mkdir_p(File.join(src, "OEBPS"))
57
+ File.write(File.join(src, "OEBPS", "content.opf"), "<package/>\n")
58
+
59
+ epub = File.join(base, "out.epub")
60
+ Epzip.zip(src, epub)
61
+
62
+ Zip::File.open(epub) do |zip|
63
+ first = zip.entries.first
64
+ assert_equal Epzip::MIMETYPE_FILENAME, first.name
65
+ assert_equal Zip::Entry::STORED, first.compression_method
66
+ assert_equal Epzip::MIMETYPE_CONTENT, first.get_input_stream.read
67
+ end
68
+ end
69
+ end
9
70
  end
metadata CHANGED
@@ -1,92 +1,75 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: epzip
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 7
8
- - 1
9
- version: 0.7.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Masayoshi Takahashi
13
- autorequire:
14
8
  bindir: bin
15
9
  cert_chain: []
16
-
17
- date: 2010-10-03 00:00:00 +09:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
21
13
  name: rubyzip
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
26
16
  - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 9
31
- - 4
32
- version: 0.9.4
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
33
22
  type: :runtime
34
- version_requirements: *id001
35
- description: epzip is EPUB packing tool. It's just only to do 'zip.'
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '1.0'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '3.0'
32
+ description: epzip is an EPUB packing tool. It's just only to do 'zip.'
36
33
  email: takahashimm@gmail.com
37
- executables:
34
+ executables:
38
35
  - epunzip
39
36
  - epzip
40
37
  extensions: []
41
-
42
- extra_rdoc_files:
43
- - LICENSE
44
- - README.rdoc
45
- files:
46
- - .document
47
- - .gitignore
38
+ extra_rdoc_files: []
39
+ files:
40
+ - ".github/dependabot.yml"
41
+ - ".github/workflows/ruby.yml"
42
+ - ".gitignore"
43
+ - Gemfile
48
44
  - LICENSE
49
45
  - README.rdoc
50
46
  - Rakefile
51
- - VERSION
52
47
  - bin/epunzip
53
48
  - bin/epzip
54
49
  - epzip.gemspec
55
50
  - lib/epzip.rb
51
+ - lib/epzip/version.rb
56
52
  - test/helper.rb
57
53
  - test/test_epzip.rb
58
- has_rdoc: true
59
- homepage: http://github.com/takahashim/epzip
60
- licenses: []
61
-
62
- post_install_message:
63
- rdoc_options:
64
- - --charset=UTF-8
65
- require_paths:
54
+ homepage: https://github.com/takahashim/epzip
55
+ licenses:
56
+ - MIT
57
+ metadata: {}
58
+ rdoc_options: []
59
+ require_paths:
66
60
  - lib
67
- required_ruby_version: !ruby/object:Gem::Requirement
68
- none: false
69
- requirements:
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
70
63
  - - ">="
71
- - !ruby/object:Gem::Version
72
- segments:
73
- - 0
74
- version: "0"
75
- required_rubygems_version: !ruby/object:Gem::Requirement
76
- none: false
77
- requirements:
64
+ - !ruby/object:Gem::Version
65
+ version: '2.6'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
78
68
  - - ">="
79
- - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
- version: "0"
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
83
71
  requirements: []
84
-
85
- rubyforge_project:
86
- rubygems_version: 1.3.7
87
- signing_key:
88
- specification_version: 3
72
+ rubygems_version: 4.0.10
73
+ specification_version: 4
89
74
  summary: simple EPUB packing tool
90
- test_files:
91
- - test/helper.rb
92
- - test/test_epzip.rb
75
+ test_files: []
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.7.1