rubyzip 0.9.9 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +284 -41
  3. data/Rakefile +11 -6
  4. data/TODO +0 -1
  5. data/lib/zip/central_directory.rb +208 -0
  6. data/lib/zip/compressor.rb +1 -2
  7. data/lib/zip/constants.rb +59 -7
  8. data/lib/zip/crypto/encryption.rb +11 -0
  9. data/lib/zip/crypto/null_encryption.rb +43 -0
  10. data/lib/zip/crypto/traditional_encryption.rb +99 -0
  11. data/lib/zip/decompressor.rb +4 -4
  12. data/lib/zip/deflater.rb +17 -13
  13. data/lib/zip/dos_time.rb +13 -14
  14. data/lib/zip/entry.rb +700 -0
  15. data/lib/zip/entry_set.rb +86 -0
  16. data/lib/zip/errors.rb +18 -0
  17. data/lib/zip/extra_field/generic.rb +43 -0
  18. data/lib/zip/extra_field/ntfs.rb +90 -0
  19. data/lib/zip/extra_field/old_unix.rb +44 -0
  20. data/lib/zip/extra_field/universal_time.rb +47 -0
  21. data/lib/zip/extra_field/unix.rb +37 -0
  22. data/lib/zip/extra_field/zip64.rb +68 -0
  23. data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
  24. data/lib/zip/extra_field.rb +101 -0
  25. data/lib/zip/file.rb +443 -0
  26. data/lib/zip/{zipfilesystem.rb → filesystem.rb} +162 -157
  27. data/lib/zip/inflater.rb +29 -28
  28. data/lib/zip/input_stream.rb +173 -0
  29. data/lib/zip/ioextras/abstract_input_stream.rb +111 -0
  30. data/lib/zip/ioextras/abstract_output_stream.rb +43 -0
  31. data/lib/zip/ioextras.rb +21 -149
  32. data/lib/zip/null_compressor.rb +2 -2
  33. data/lib/zip/null_decompressor.rb +8 -6
  34. data/lib/zip/null_input_stream.rb +3 -2
  35. data/lib/zip/output_stream.rb +189 -0
  36. data/lib/zip/pass_thru_compressor.rb +6 -6
  37. data/lib/zip/pass_thru_decompressor.rb +19 -19
  38. data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +3 -3
  39. data/lib/zip/streamable_stream.rb +56 -0
  40. data/lib/zip/version.rb +3 -0
  41. data/lib/zip.rb +71 -0
  42. data/samples/example.rb +44 -32
  43. data/samples/example_filesystem.rb +16 -18
  44. data/samples/example_recursive.rb +33 -28
  45. data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +26 -28
  46. data/samples/qtzip.rb +22 -31
  47. data/samples/write_simple.rb +12 -13
  48. data/samples/zipfind.rb +31 -39
  49. data/test/basic_zip_file_test.rb +60 -0
  50. data/test/case_sensitivity_test.rb +69 -0
  51. data/test/central_directory_entry_test.rb +69 -0
  52. data/test/central_directory_test.rb +100 -0
  53. data/test/crypto/null_encryption_test.rb +57 -0
  54. data/test/crypto/traditional_encryption_test.rb +80 -0
  55. data/test/data/WarnInvalidDate.zip +0 -0
  56. data/test/data/file1.txt +46 -0
  57. data/test/data/file1.txt.deflatedData +0 -0
  58. data/test/data/file2.txt +1504 -0
  59. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  60. data/test/data/globTest/foo.txt +0 -0
  61. data/test/data/globTest/food.txt +0 -0
  62. data/test/data/globTest.zip +0 -0
  63. data/test/data/gpbit3stored.zip +0 -0
  64. data/test/data/mimetype +1 -0
  65. data/test/data/notzippedruby.rb +7 -0
  66. data/test/data/ntfs.zip +0 -0
  67. data/test/data/oddExtraField.zip +0 -0
  68. data/test/data/path_traversal/Makefile +10 -0
  69. data/test/data/path_traversal/jwilk/README.md +5 -0
  70. data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
  71. data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
  72. data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
  73. data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
  74. data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
  75. data/test/data/path_traversal/jwilk/relative0.zip +0 -0
  76. data/test/data/path_traversal/jwilk/relative2.zip +0 -0
  77. data/test/data/path_traversal/jwilk/symlink.zip +0 -0
  78. data/test/data/path_traversal/relative1.zip +0 -0
  79. data/test/data/path_traversal/tilde.zip +0 -0
  80. data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
  81. data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
  82. data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
  83. data/test/data/rubycode.zip +0 -0
  84. data/test/data/rubycode2.zip +0 -0
  85. data/test/data/test.xls +0 -0
  86. data/test/data/testDirectory.bin +0 -0
  87. data/test/data/zip64-sample.zip +0 -0
  88. data/test/data/zipWithDirs.zip +0 -0
  89. data/test/data/zipWithEncryption.zip +0 -0
  90. data/test/deflater_test.rb +65 -0
  91. data/test/encryption_test.rb +42 -0
  92. data/test/entry_set_test.rb +163 -0
  93. data/test/entry_test.rb +154 -0
  94. data/test/errors_test.rb +35 -0
  95. data/test/extra_field_test.rb +76 -0
  96. data/test/file_extract_directory_test.rb +54 -0
  97. data/test/file_extract_test.rb +145 -0
  98. data/test/file_permissions_test.rb +65 -0
  99. data/test/file_split_test.rb +57 -0
  100. data/test/file_test.rb +666 -0
  101. data/test/filesystem/dir_iterator_test.rb +58 -0
  102. data/test/filesystem/directory_test.rb +139 -0
  103. data/test/filesystem/file_mutating_test.rb +87 -0
  104. data/test/filesystem/file_nonmutating_test.rb +508 -0
  105. data/test/filesystem/file_stat_test.rb +64 -0
  106. data/test/gentestfiles.rb +126 -0
  107. data/test/inflater_test.rb +14 -0
  108. data/test/input_stream_test.rb +182 -0
  109. data/test/ioextras/abstract_input_stream_test.rb +102 -0
  110. data/test/ioextras/abstract_output_stream_test.rb +106 -0
  111. data/test/ioextras/fake_io_test.rb +18 -0
  112. data/test/local_entry_test.rb +154 -0
  113. data/test/output_stream_test.rb +128 -0
  114. data/test/pass_thru_compressor_test.rb +30 -0
  115. data/test/pass_thru_decompressor_test.rb +14 -0
  116. data/test/path_traversal_test.rb +141 -0
  117. data/test/samples/example_recursive_test.rb +37 -0
  118. data/test/settings_test.rb +95 -0
  119. data/test/test_helper.rb +234 -0
  120. data/test/unicode_file_names_and_comments_test.rb +62 -0
  121. data/test/zip64_full_test.rb +51 -0
  122. data/test/zip64_support_test.rb +14 -0
  123. metadata +274 -41
  124. data/NEWS +0 -172
  125. data/lib/zip/settings.rb +0 -10
  126. data/lib/zip/tempfile_bugfixed.rb +0 -195
  127. data/lib/zip/zip.rb +0 -56
  128. data/lib/zip/zip_central_directory.rb +0 -135
  129. data/lib/zip/zip_entry.rb +0 -638
  130. data/lib/zip/zip_entry_set.rb +0 -77
  131. data/lib/zip/zip_extra_field.rb +0 -213
  132. data/lib/zip/zip_file.rb +0 -340
  133. data/lib/zip/zip_input_stream.rb +0 -144
  134. data/lib/zip/zip_output_stream.rb +0 -173
  135. data/lib/zip/zip_streamable_stream.rb +0 -47
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $: << "../lib"
3
+ $: << '../lib'
4
4
 
5
5
  $VERBOSE = true
6
6
 
7
7
  require 'gtk'
8
- require 'zip/zip'
8
+ require 'zip'
9
9
 
10
10
  class MainApp < Gtk::Window
11
11
  def initialize
12
12
  super()
13
13
  set_usize(400, 256)
14
- set_title("rubyzip")
14
+ set_title('rubyzip')
15
15
  signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit }
16
16
 
17
17
  box = Gtk::VBox.new(false, 0)
@@ -19,26 +19,25 @@ class MainApp < Gtk::Window
19
19
 
20
20
  @zipfile = nil
21
21
  @buttonPanel = ButtonPanel.new
22
- @buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
22
+ @buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
23
23
  show_file_selector
24
- }
25
- @buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
26
- puts "Not implemented!"
27
- }
24
+ end
25
+ @buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
26
+ puts 'Not implemented!'
27
+ end
28
28
  box.pack_start(@buttonPanel, false, false, 0)
29
-
29
+
30
30
  sw = Gtk::ScrolledWindow.new
31
31
  sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
32
32
  box.pack_start(sw, true, true, 0)
33
33
 
34
- @clist = Gtk::CList.new(["Name", "Size", "Compression"])
34
+ @clist = Gtk::CList.new(%w[Name Size Compression])
35
35
  @clist.set_selection_mode(Gtk::SELECTION_BROWSE)
36
36
  @clist.set_column_width(0, 120)
37
37
  @clist.set_column_width(1, 120)
38
- @clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) {
39
- |w, row, column, event|
38
+ @clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) do |_w, row, _column, _event|
40
39
  @selected_row = row
41
- }
40
+ end
42
41
  sw.add(@clist)
43
42
  end
44
43
 
@@ -48,38 +47,37 @@ class MainApp < Gtk::Window
48
47
  super
49
48
  set_layout(Gtk::BUTTONBOX_START)
50
49
  set_spacing(0)
51
- @openButton = Gtk::Button.new("Open archive")
52
- @extractButton = Gtk::Button.new("Extract entry")
50
+ @openButton = Gtk::Button.new('Open archive')
51
+ @extractButton = Gtk::Button.new('Extract entry')
53
52
  pack_start(@openButton)
54
53
  pack_start(@extractButton)
55
54
  end
56
55
  end
57
56
 
58
57
  def show_file_selector
59
- @fileSelector = Gtk::FileSelection.new("Open zip file")
58
+ @fileSelector = Gtk::FileSelection.new('Open zip file')
60
59
  @fileSelector.show
61
- @fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
60
+ @fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
62
61
  open_zip(@fileSelector.filename)
63
62
  @fileSelector.destroy
64
- }
65
- @fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) {
63
+ end
64
+ @fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
66
65
  @fileSelector.destroy
67
- }
66
+ end
68
67
  end
69
68
 
70
69
  def open_zip(filename)
71
- @zipfile = Zip::ZipFile.open(filename)
70
+ @zipfile = Zip::File.open(filename)
72
71
  @clist.clear
73
- @zipfile.each {
74
- |entry|
75
- @clist.append([ entry.name,
76
- entry.size.to_s,
77
- (100.0*entry.compressedSize/entry.size).to_s+"%" ])
78
- }
72
+ @zipfile.each do |entry|
73
+ @clist.append([entry.name,
74
+ entry.size.to_s,
75
+ (100.0 * entry.compressedSize / entry.size).to_s + '%'])
76
+ end
79
77
  end
80
78
  end
81
79
 
82
- mainApp = MainApp.new()
80
+ mainApp = MainApp.new
83
81
 
84
82
  mainApp.show_all
85
83
 
data/samples/qtzip.rb CHANGED
@@ -1,22 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $VERBOSE=true
3
+ $VERBOSE = true
4
4
 
5
- $: << "../lib"
5
+ $: << '../lib'
6
6
 
7
7
  require 'Qt'
8
8
  system('rbuic -o zipdialogui.rb zipdialogui.ui')
9
9
  require 'zipdialogui.rb'
10
- require 'zip/zip'
11
-
12
-
10
+ require 'zip'
13
11
 
14
12
  a = Qt::Application.new(ARGV)
15
13
 
16
14
  class ZipDialog < ZipDialogUI
17
-
18
-
19
- def initialize()
15
+ def initialize
20
16
  super()
21
17
  connect(child('add_button'), SIGNAL('clicked()'),
22
18
  self, SLOT('add_files()'))
@@ -25,23 +21,21 @@ class ZipDialog < ZipDialogUI
25
21
  end
26
22
 
27
23
  def zipfile(&proc)
28
- Zip::ZipFile.open(@zip_filename, &proc)
24
+ Zip::File.open(@zip_filename, &proc)
29
25
  end
30
26
 
31
27
  def each(&proc)
32
- Zip::ZipFile.foreach(@zip_filename, &proc)
28
+ Zip::File.foreach(@zip_filename, &proc)
33
29
  end
34
-
35
- def refresh()
36
- lv = child("entry_list_view")
30
+
31
+ def refresh
32
+ lv = child('entry_list_view')
37
33
  lv.clear
38
- each {
39
- |e|
34
+ each do |e|
40
35
  lv.insert_item(Qt::ListViewItem.new(lv, e.name, e.size.to_s))
41
- }
36
+ end
42
37
  end
43
38
 
44
-
45
39
  def load(zipfile)
46
40
  @zip_filename = zipfile
47
41
  refresh
@@ -49,13 +43,11 @@ class ZipDialog < ZipDialogUI
49
43
 
50
44
  def add_files
51
45
  l = Qt::FileDialog.getOpenFileNames(nil, nil, self)
52
- zipfile {
53
- |zf|
54
- l.each {
55
- |path|
46
+ zipfile do |zf|
47
+ l.each do |path|
56
48
  zf.add(File.basename(path), path)
57
- }
58
- }
49
+ end
50
+ end
59
51
  refresh
60
52
  end
61
53
 
@@ -63,7 +55,7 @@ class ZipDialog < ZipDialogUI
63
55
  selected_items = []
64
56
  unselected_items = []
65
57
  lv_item = entry_list_view.first_child
66
- while (lv_item)
58
+ while lv_item
67
59
  if entry_list_view.is_selected(lv_item)
68
60
  selected_items << lv_item.text(0)
69
61
  else
@@ -73,22 +65,21 @@ class ZipDialog < ZipDialogUI
73
65
  end
74
66
  puts "selected_items.size = #{selected_items.size}"
75
67
  puts "unselected_items.size = #{unselected_items.size}"
76
- items = selected_items.size > 0 ? selected_items : unselected_items
68
+ items = !selected_items.empty? ? selected_items : unselected_items
77
69
  puts "items.size = #{items.size}"
78
70
 
79
71
  d = Qt::FileDialog.get_existing_directory(nil, self)
80
- if (!d)
81
- puts "No directory chosen"
72
+ if !d
73
+ puts 'No directory chosen'
82
74
  else
83
75
  zipfile { |zf| items.each { |e| zf.extract(e, File.join(d, e)) } }
84
76
  end
85
-
86
77
  end
87
78
 
88
79
  slots 'add_files()', 'extract_files()'
89
80
  end
90
81
 
91
- if !ARGV[0]
82
+ unless ARGV[0]
92
83
  puts "usage: #{$0} zipname"
93
84
  exit
94
85
  end
@@ -97,5 +88,5 @@ zd = ZipDialog.new
97
88
  zd.load(ARGV[0])
98
89
 
99
90
  a.mainWidget = zd
100
- zd.show()
101
- a.exec()
91
+ zd.show
92
+ a.exec
@@ -1,13 +1,12 @@
1
- #!/usr/bin/env ruby
2
-
3
- $: << "../lib"
4
-
5
- require 'zip/zip'
6
-
7
- include Zip
8
-
9
- ZipOutputStream.open('simple.zip') {
10
- |zos|
11
- ze = zos.put_next_entry 'entry.txt'
12
- zos.puts "Hello world"
13
- }
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << '../lib'
4
+
5
+ require 'zip'
6
+
7
+ include Zip
8
+
9
+ OutputStream.open('simple.zip') do |zos|
10
+ zos.put_next_entry 'entry.txt'
11
+ zos.puts 'Hello world'
12
+ end
data/samples/zipfind.rb CHANGED
@@ -2,72 +2,64 @@
2
2
 
3
3
  $VERBOSE = true
4
4
 
5
- $: << "../lib"
5
+ $: << '../lib'
6
6
 
7
- require 'zip/zip'
7
+ require 'zip'
8
8
  require 'find'
9
9
 
10
10
  module Zip
11
11
  module ZipFind
12
12
  def self.find(path, zipFilePattern = /\.zip$/i)
13
- Find.find(path) {
14
- |fileName|
15
- yield(fileName)
16
- if zipFilePattern.match(fileName) && File.file?(fileName)
17
- begin
18
- Zip::ZipFile.foreach(fileName) {
19
- |zipEntry|
20
- yield(fileName + File::SEPARATOR + zipEntry.to_s)
21
- }
22
- rescue Errno::EACCES => ex
23
- puts ex
24
- end
25
- end
26
- }
13
+ Find.find(path) do |fileName|
14
+ yield(fileName)
15
+ next unless zipFilePattern.match(fileName) && File.file?(fileName)
16
+ begin
17
+ Zip::File.foreach(fileName) do |zipEntry|
18
+ yield(fileName + File::SEPARATOR + zipEntry.to_s)
19
+ end
20
+ rescue Errno::EACCES => ex
21
+ puts ex
22
+ end
23
+ end
27
24
  end
28
25
 
29
26
  def self.find_file(path, fileNamePattern, zipFilePattern = /\.zip$/i)
30
- self.find(path, zipFilePattern) {
31
- |fileName|
32
- yield(fileName) if fileNamePattern.match(fileName)
33
- }
27
+ find(path, zipFilePattern) do |fileName|
28
+ yield(fileName) if fileNamePattern.match(fileName)
29
+ end
34
30
  end
35
-
36
31
  end
37
32
  end
38
33
 
39
- if __FILE__ == $0
34
+ if $0 == __FILE__
40
35
  module ZipFindConsoleRunner
41
-
42
- PATH_ARG_INDEX = 0;
43
- FILENAME_PATTERN_ARG_INDEX = 1;
44
- ZIPFILE_PATTERN_ARG_INDEX = 2;
45
-
36
+ PATH_ARG_INDEX = 0
37
+ FILENAME_PATTERN_ARG_INDEX = 1
38
+ ZIPFILE_PATTERN_ARG_INDEX = 2
39
+
46
40
  def self.run(args)
47
41
  check_args(args)
48
- Zip::ZipFind.find_file(args[PATH_ARG_INDEX],
49
- args[FILENAME_PATTERN_ARG_INDEX],
50
- args[ZIPFILE_PATTERN_ARG_INDEX]) {
51
- |fileName|
52
- report_entry_found fileName
53
- }
42
+ Zip::ZipFind.find_file(args[PATH_ARG_INDEX],
43
+ args[FILENAME_PATTERN_ARG_INDEX],
44
+ args[ZIPFILE_PATTERN_ARG_INDEX]) do |fileName|
45
+ report_entry_found fileName
46
+ end
54
47
  end
55
-
48
+
56
49
  def self.check_args(args)
57
- if (args.size != 3)
58
- usage
59
- exit
50
+ if args.size != 3
51
+ usage
52
+ exit
60
53
  end
61
54
  end
62
55
 
63
56
  def self.usage
64
57
  puts "Usage: #{$0} PATH ZIPFILENAME_PATTERN FILNAME_PATTERN"
65
58
  end
66
-
59
+
67
60
  def self.report_entry_found(fileName)
68
61
  puts fileName
69
62
  end
70
-
71
63
  end
72
64
 
73
65
  ZipFindConsoleRunner.run(ARGV)
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ class BasicZipFileTest < MiniTest::Test
4
+ include AssertEntry
5
+
6
+ def setup
7
+ @zip_file = ::Zip::File.new(TestZipFile::TEST_ZIP2.zip_name)
8
+ @testEntryNameIndex = 0
9
+ end
10
+
11
+ def test_entries
12
+ assert_equal(TestZipFile::TEST_ZIP2.entry_names.sort,
13
+ @zip_file.entries.entries.sort.map { |e| e.name })
14
+ end
15
+
16
+ def test_each
17
+ count = 0
18
+ visited = {}
19
+ @zip_file.each do |entry|
20
+ assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
21
+ assert(!visited.include?(entry.name))
22
+ visited[entry.name] = nil
23
+ count = count.succ
24
+ end
25
+ assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
26
+ end
27
+
28
+ def test_foreach
29
+ count = 0
30
+ visited = {}
31
+ ::Zip::File.foreach(TestZipFile::TEST_ZIP2.zip_name) do |entry|
32
+ assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name))
33
+ assert(!visited.include?(entry.name))
34
+ visited[entry.name] = nil
35
+ count = count.succ
36
+ end
37
+ assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
38
+ end
39
+
40
+ def test_get_input_stream
41
+ count = 0
42
+ visited = {}
43
+ @zip_file.each do |entry|
44
+ assert_entry(entry.name, @zip_file.get_input_stream(entry), entry.name)
45
+ assert(!visited.include?(entry.name))
46
+ visited[entry.name] = nil
47
+ count = count.succ
48
+ end
49
+ assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count)
50
+ end
51
+
52
+ def test_get_input_stream_block
53
+ fileAndEntryName = @zip_file.entries.first.name
54
+ @zip_file.get_input_stream(fileAndEntryName) do |zis|
55
+ assert_entry_contents_for_stream(fileAndEntryName,
56
+ zis,
57
+ fileAndEntryName)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class ZipCaseSensitivityTest < MiniTest::Test
4
+ include CommonZipFileFixture
5
+
6
+ SRC_FILES = [['test/data/file1.txt', 'testfile.rb'],
7
+ ['test/data/file2.txt', 'testFILE.rb']]
8
+
9
+ def teardown
10
+ ::Zip.case_insensitive_match = false
11
+ end
12
+
13
+ # Ensure that everything functions normally when +case_insensitive_match = false+
14
+ def test_add_case_sensitive
15
+ ::Zip.case_insensitive_match = false
16
+
17
+ SRC_FILES.each { |fn, _en| assert(::File.exist?(fn)) }
18
+ zf = ::Zip::File.new(EMPTY_FILENAME, ::Zip::File::CREATE)
19
+
20
+ SRC_FILES.each { |fn, en| zf.add(en, fn) }
21
+ zf.close
22
+
23
+ zfRead = ::Zip::File.new(EMPTY_FILENAME)
24
+ assert_equal(SRC_FILES.size, zfRead.entries.length)
25
+ SRC_FILES.each_with_index { |a, i|
26
+ assert_equal(a.last, zfRead.entries[i].name)
27
+ AssertEntry.assert_contents(a.first,
28
+ zfRead.get_input_stream(a.last) { |zis| zis.read })
29
+ }
30
+ end
31
+
32
+ # Ensure that names are treated case insensitively when adding files and +case_insensitive_match = false+
33
+ def test_add_case_insensitive
34
+ ::Zip.case_insensitive_match = true
35
+
36
+ SRC_FILES.each { |fn, _en| assert(::File.exist?(fn)) }
37
+ zf = ::Zip::File.new(EMPTY_FILENAME, ::Zip::File::CREATE)
38
+
39
+ assert_raises Zip::EntryExistsError do
40
+ SRC_FILES.each { |fn, en| zf.add(en, fn) }
41
+ end
42
+ end
43
+
44
+ # Ensure that names are treated case insensitively when reading files and +case_insensitive_match = true+
45
+ def test_add_case_sensitive_read_case_insensitive
46
+ ::Zip.case_insensitive_match = false
47
+
48
+ SRC_FILES.each { |fn, _en| assert(::File.exist?(fn)) }
49
+ zf = ::Zip::File.new(EMPTY_FILENAME, ::Zip::File::CREATE)
50
+
51
+ SRC_FILES.each { |fn, en| zf.add(en, fn) }
52
+ zf.close
53
+
54
+ ::Zip.case_insensitive_match = true
55
+
56
+ zfRead = ::Zip::File.new(EMPTY_FILENAME)
57
+ assert_equal(SRC_FILES.collect { |_fn, en| en.downcase }.uniq.size, zfRead.entries.length)
58
+ assert_equal(SRC_FILES.last.last.downcase, zfRead.entries.first.name.downcase)
59
+ AssertEntry.assert_contents(SRC_FILES.last.first,
60
+ zfRead.get_input_stream(SRC_FILES.last.last) { |zis| zis.read })
61
+ end
62
+
63
+ private
64
+
65
+ def assert_contains(zf, entryName, filename = entryName)
66
+ assert(zf.entries.detect { |e| e.name == entryName } != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}")
67
+ assert_entry_contents(zf, entryName, filename) if File.exist?(filename)
68
+ end
69
+ end
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class ZipCentralDirectoryEntryTest < MiniTest::Test
4
+ def test_read_from_stream
5
+ File.open('test/data/testDirectory.bin', 'rb') do |file|
6
+ entry = ::Zip::Entry.read_c_dir_entry(file)
7
+
8
+ assert_equal('longAscii.txt', entry.name)
9
+ assert_equal(::Zip::Entry::DEFLATED, entry.compression_method)
10
+ assert_equal(106_490, entry.size)
11
+ assert_equal(3784, entry.compressed_size)
12
+ assert_equal(0xfcd1799c, entry.crc)
13
+ assert_equal('', entry.comment)
14
+
15
+ entry = ::Zip::Entry.read_c_dir_entry(file)
16
+ assert_equal('empty.txt', entry.name)
17
+ assert_equal(::Zip::Entry::STORED, entry.compression_method)
18
+ assert_equal(0, entry.size)
19
+ assert_equal(0, entry.compressed_size)
20
+ assert_equal(0x0, entry.crc)
21
+ assert_equal('', entry.comment)
22
+
23
+ entry = ::Zip::Entry.read_c_dir_entry(file)
24
+ assert_equal('short.txt', entry.name)
25
+ assert_equal(::Zip::Entry::STORED, entry.compression_method)
26
+ assert_equal(6, entry.size)
27
+ assert_equal(6, entry.compressed_size)
28
+ assert_equal(0xbb76fe69, entry.crc)
29
+ assert_equal('', entry.comment)
30
+
31
+ entry = ::Zip::Entry.read_c_dir_entry(file)
32
+ assert_equal('longBinary.bin', entry.name)
33
+ assert_equal(::Zip::Entry::DEFLATED, entry.compression_method)
34
+ assert_equal(1_000_024, entry.size)
35
+ assert_equal(70_847, entry.compressed_size)
36
+ assert_equal(0x10da7d59, entry.crc)
37
+ assert_equal('', entry.comment)
38
+
39
+ entry = ::Zip::Entry.read_c_dir_entry(file)
40
+ assert_nil(entry)
41
+ # Fields that are not check by this test:
42
+ # version made by 2 bytes
43
+ # version needed to extract 2 bytes
44
+ # general purpose bit flag 2 bytes
45
+ # last mod file time 2 bytes
46
+ # last mod file date 2 bytes
47
+ # compressed size 4 bytes
48
+ # uncompressed size 4 bytes
49
+ # disk number start 2 bytes
50
+ # internal file attributes 2 bytes
51
+ # external file attributes 4 bytes
52
+ # relative offset of local header 4 bytes
53
+
54
+ # file name (variable size)
55
+ # extra field (variable size)
56
+ # file comment (variable size)
57
+ end
58
+ end
59
+
60
+ def test_read_entry_from_truncated_zip_file
61
+ fragment = ''
62
+ File.open('test/data/testDirectory.bin') { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes
63
+ fragment.extend(IOizeString)
64
+ entry = ::Zip::Entry.new
65
+ entry.read_c_dir_entry(fragment)
66
+ fail 'ZipError expected'
67
+ rescue ::Zip::Error
68
+ end
69
+ end
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+
3
+ class ZipCentralDirectoryTest < MiniTest::Test
4
+ def teardown
5
+ ::Zip.reset!
6
+ end
7
+
8
+ def test_read_from_stream
9
+ ::File.open(TestZipFile::TEST_ZIP2.zip_name, 'rb') do |zipFile|
10
+ cdir = ::Zip::CentralDirectory.read_from_stream(zipFile)
11
+
12
+ assert_equal(TestZipFile::TEST_ZIP2.entry_names.size, cdir.size)
13
+ assert(cdir.entries.sort.compare_enumerables(TestZipFile::TEST_ZIP2.entry_names.sort) do |cdirEntry, testEntryName|
14
+ cdirEntry.name == testEntryName
15
+ end)
16
+ assert_equal(TestZipFile::TEST_ZIP2.comment, cdir.comment)
17
+ end
18
+ end
19
+
20
+ def test_read_from_invalid_stream
21
+ File.open('test/data/file2.txt', 'rb') do |zipFile|
22
+ cdir = ::Zip::CentralDirectory.new
23
+ cdir.read_from_stream(zipFile)
24
+ end
25
+ fail 'ZipError expected!'
26
+ rescue ::Zip::Error
27
+ end
28
+
29
+ def test_read_from_truncated_zip_file
30
+ fragment = ''
31
+ File.open('test/data/testDirectory.bin', 'rb') { |f| fragment = f.read }
32
+ fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete
33
+ fragment.extend(IOizeString)
34
+ entry = ::Zip::CentralDirectory.new
35
+ entry.read_from_stream(fragment)
36
+ fail 'ZipError expected'
37
+ rescue ::Zip::Error
38
+ end
39
+
40
+ def test_write_to_stream
41
+ entries = [::Zip::Entry.new('file.zip', 'flimse', 'myComment', 'somethingExtra'),
42
+ ::Zip::Entry.new('file.zip', 'secondEntryName'),
43
+ ::Zip::Entry.new('file.zip', 'lastEntry.txt', 'Has a comment too')]
44
+ cdir = ::Zip::CentralDirectory.new(entries, 'my zip comment')
45
+ File.open('test/data/generated/cdirtest.bin', 'wb') { |f| cdir.write_to_stream(f) }
46
+ cdirReadback = ::Zip::CentralDirectory.new
47
+ File.open('test/data/generated/cdirtest.bin', 'rb') { |f| cdirReadback.read_from_stream(f) }
48
+
49
+ assert_equal(cdir.entries.sort, cdirReadback.entries.sort)
50
+ end
51
+
52
+ def test_write64_to_stream
53
+ ::Zip.write_zip64_support = true
54
+ entries = [::Zip::Entry.new('file.zip', 'file1-little', 'comment1', '', 200, 101, ::Zip::Entry::STORED, 200),
55
+ ::Zip::Entry.new('file.zip', 'file2-big', 'comment2', '', 18_000_000_000, 102, ::Zip::Entry::DEFLATED, 20_000_000_000),
56
+ ::Zip::Entry.new('file.zip', 'file3-alsobig', 'comment3', '', 15_000_000_000, 103, ::Zip::Entry::DEFLATED, 21_000_000_000),
57
+ ::Zip::Entry.new('file.zip', 'file4-little', 'comment4', '', 100, 104, ::Zip::Entry::DEFLATED, 121)]
58
+ [0, 250, 18_000_000_300, 33_000_000_350].each_with_index do |offset, index|
59
+ entries[index].local_header_offset = offset
60
+ end
61
+ cdir = ::Zip::CentralDirectory.new(entries, 'zip comment')
62
+ File.open('test/data/generated/cdir64test.bin', 'wb') { |f| cdir.write_to_stream(f) }
63
+ cdirReadback = ::Zip::CentralDirectory.new
64
+ File.open('test/data/generated/cdir64test.bin', 'rb') { |f| cdirReadback.read_from_stream(f) }
65
+
66
+ assert_equal(cdir.entries.sort, cdirReadback.entries.sort)
67
+ assert_equal(::Zip::VERSION_NEEDED_TO_EXTRACT_ZIP64, cdirReadback.instance_variable_get(:@version_needed_for_extract))
68
+ end
69
+
70
+ def test_equality
71
+ cdir1 = ::Zip::CentralDirectory.new([::Zip::Entry.new('file.zip', 'flimse', nil,
72
+ 'somethingExtra'),
73
+ ::Zip::Entry.new('file.zip', 'secondEntryName'),
74
+ ::Zip::Entry.new('file.zip', 'lastEntry.txt')],
75
+ 'my zip comment')
76
+ cdir2 = ::Zip::CentralDirectory.new([::Zip::Entry.new('file.zip', 'flimse', nil,
77
+ 'somethingExtra'),
78
+ ::Zip::Entry.new('file.zip', 'secondEntryName'),
79
+ ::Zip::Entry.new('file.zip', 'lastEntry.txt')],
80
+ 'my zip comment')
81
+ cdir3 = ::Zip::CentralDirectory.new([::Zip::Entry.new('file.zip', 'flimse', nil,
82
+ 'somethingExtra'),
83
+ ::Zip::Entry.new('file.zip', 'secondEntryName'),
84
+ ::Zip::Entry.new('file.zip', 'lastEntry.txt')],
85
+ 'comment?')
86
+ cdir4 = ::Zip::CentralDirectory.new([::Zip::Entry.new('file.zip', 'flimse', nil,
87
+ 'somethingExtra'),
88
+ ::Zip::Entry.new('file.zip', 'lastEntry.txt')],
89
+ 'comment?')
90
+ assert_equal(cdir1, cdir1)
91
+ assert_equal(cdir1, cdir2)
92
+
93
+ assert(cdir1 != cdir3)
94
+ assert(cdir2 != cdir3)
95
+ assert(cdir2 != cdir3)
96
+ assert(cdir3 != cdir4)
97
+
98
+ assert(cdir3 != 'hello')
99
+ end
100
+ end