excavate 1.0.1 → 1.0.2
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 +4 -4
- data/.rubocop_todo.yml +13 -9
- data/lib/excavate/archive.rb +7 -3
- data/lib/excavate/extractors/ole_extractor.rb +2 -0
- data/lib/excavate/extractors/xz_extractor.rb +22 -5
- data/lib/excavate/file_magic.rb +22 -19
- data/lib/excavate/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed5cec17e4c8c985ae34d044fa170ccbecdc3bd783a0cd0916454a8c567149d7
|
|
4
|
+
data.tar.gz: 750dcde7f88158d2e107763a5fc733c4a72ac1030b53e91c6fd7e2697b167686
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b62877409f75d68041b7b973ee364356e6e47b09bd714ebd4430f0df627643213bd8ff2dc3ca40d4b8d141c2fda3ff6b9b686f4720fc8997424b169effff169e
|
|
7
|
+
data.tar.gz: e3b0dee5b195329ecbc6cc85ffc5fc64c7b4c736481ac3c964b0353828c59e0176b71ad3c70ba53b7503a01419f5e6f205e28fd3531fe3584449ad8b39a66082
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-
|
|
3
|
+
# on 2026-03-17 11:57:02 UTC using RuboCop version 1.85.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -37,16 +37,10 @@ Lint/DuplicateBranch:
|
|
|
37
37
|
Exclude:
|
|
38
38
|
- 'lib/excavate/utils.rb'
|
|
39
39
|
|
|
40
|
-
# Offense count:
|
|
41
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
42
|
-
Lint/ScriptPermission:
|
|
43
|
-
Exclude:
|
|
44
|
-
- 'scripts/create_multi_nested_fixture.rb'
|
|
45
|
-
|
|
46
|
-
# Offense count: 5
|
|
40
|
+
# Offense count: 4
|
|
47
41
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
48
42
|
Metrics/MethodLength:
|
|
49
|
-
Max:
|
|
43
|
+
Max: 12
|
|
50
44
|
|
|
51
45
|
# Offense count: 46
|
|
52
46
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
|
@@ -71,6 +65,16 @@ RSpec/MultipleExpectations:
|
|
|
71
65
|
RSpec/NestedGroups:
|
|
72
66
|
Max: 4
|
|
73
67
|
|
|
68
|
+
# Offense count: 2
|
|
69
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
70
|
+
# Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames.
|
|
71
|
+
# RedundantRestArgumentNames: args, arguments
|
|
72
|
+
# RedundantKeywordRestArgumentNames: kwargs, options, opts
|
|
73
|
+
# RedundantBlockArgumentNames: blk, block, proc
|
|
74
|
+
Style/ArgumentsForwarding:
|
|
75
|
+
Exclude:
|
|
76
|
+
- 'lib/excavate/archive.rb'
|
|
77
|
+
|
|
74
78
|
# Offense count: 2
|
|
75
79
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
76
80
|
Style/IdenticalConditionalBranches:
|
data/lib/excavate/archive.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Excavate
|
|
|
18
18
|
@archive = archive
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def files(recursive_packages: false, files: [], filter: nil, &
|
|
21
|
+
def files(recursive_packages: false, files: [], filter: nil, &)
|
|
22
22
|
# Auto-enable recursive_packages when extracting specific files
|
|
23
23
|
recursive_packages = true if files.any?
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ module Excavate
|
|
|
26
26
|
extract(target, recursive_packages: recursive_packages,
|
|
27
27
|
files: files, filter: filter)
|
|
28
28
|
|
|
29
|
-
all_files_in(target).map(&
|
|
29
|
+
all_files_in(target).map(&)
|
|
30
30
|
ensure
|
|
31
31
|
windows_safe_rm_rf(target)
|
|
32
32
|
end
|
|
@@ -218,7 +218,11 @@ module Excavate
|
|
|
218
218
|
replace_archive_with_contents(archive, target)
|
|
219
219
|
rescue StandardError
|
|
220
220
|
FileUtils.rm_rf(target)
|
|
221
|
-
|
|
221
|
+
# During recursive extraction of nested archives, silently skip
|
|
222
|
+
# any that fail (e.g. .msi files that aren't real OLE, .cab files
|
|
223
|
+
# with incompatible format, .exe files with unsupported compression).
|
|
224
|
+
# Only re-raise for file types we don't recognize as archives.
|
|
225
|
+
raise unless TYPES.key?(normalized_extension(archive))
|
|
222
226
|
end
|
|
223
227
|
|
|
224
228
|
def replace_archive_with_contents(archive, target)
|
|
@@ -28,20 +28,37 @@ module Excavate
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def extract_tar_xz(target)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
tar_data = Zlib::GzipReader.new(StringIO.new(gzip_data)).read
|
|
31
|
+
data = Omnizip::Formats::Xz.decompress(@archive)
|
|
32
|
+
data = strip_compression(data)
|
|
33
|
+
validate_tar!(data)
|
|
35
34
|
|
|
36
35
|
# Write tar file and extract
|
|
37
36
|
temp_tar = File.join(target, ".temp_#{Time.now.to_i}_#{rand(1000)}.tar")
|
|
38
|
-
File.binwrite(temp_tar,
|
|
37
|
+
File.binwrite(temp_tar, data)
|
|
39
38
|
|
|
40
39
|
TarExtractor.new(temp_tar).extract(target)
|
|
41
40
|
ensure
|
|
42
41
|
File.delete(temp_tar) if temp_tar && File.exist?(temp_tar)
|
|
43
42
|
end
|
|
44
43
|
|
|
44
|
+
def strip_compression(data)
|
|
45
|
+
if FileMagic.detect_bytes(data) == :gzip
|
|
46
|
+
return Zlib::GzipReader.new(StringIO.new(data)).read
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
data
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def validate_tar!(data)
|
|
53
|
+
inner_type = FileMagic.detect_bytes(data)
|
|
54
|
+
return if inner_type == :tar
|
|
55
|
+
|
|
56
|
+
inner_type ||= "unknown format"
|
|
57
|
+
|
|
58
|
+
raise UnknownArchiveError,
|
|
59
|
+
"Expected tar inside #{@archive}, got #{inner_type}"
|
|
60
|
+
end
|
|
61
|
+
|
|
45
62
|
def extract_pure_xz(target)
|
|
46
63
|
# Decompress XZ
|
|
47
64
|
data = Omnizip::Formats::Xz.decompress(@archive)
|
data/lib/excavate/file_magic.rb
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Excavate
|
|
2
4
|
class FileMagic
|
|
5
|
+
# [offset, magic_bytes, type]
|
|
6
|
+
SIGNATURES = [
|
|
7
|
+
[0, "MSCF\x00\x00\x00\x00".b, :cab],
|
|
8
|
+
[0, "\xFD7zXZ\x00".b, :xz],
|
|
9
|
+
[0, "\x1F\x8B".b, :gzip],
|
|
10
|
+
[257, "ustar".b, :tar],
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
MAX_READ = SIGNATURES.map { |o, m, _| o + m.bytesize }.max
|
|
14
|
+
|
|
3
15
|
def self.detect(path)
|
|
4
|
-
|
|
16
|
+
beginning = File.read(path, MAX_READ, mode: "rb")
|
|
17
|
+
detect_bytes(beginning)
|
|
5
18
|
end
|
|
6
19
|
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
def self.detect_bytes(data)
|
|
21
|
+
return nil if data.nil? || data.empty?
|
|
22
|
+
|
|
23
|
+
SIGNATURES.each do |offset, magic, type|
|
|
24
|
+
next if data.bytesize < offset + magic.bytesize
|
|
10
25
|
|
|
11
|
-
|
|
12
|
-
beginning = File.read(@path, 8, mode: "rb")
|
|
13
|
-
case beginning
|
|
14
|
-
when "MSCF\x00\x00\x00\x00".force_encoding("BINARY")
|
|
15
|
-
:cab
|
|
16
|
-
else
|
|
17
|
-
case beginning.byteslice(0, 6)
|
|
18
|
-
when "\xFD7zXZ\x00".force_encoding("BINARY")
|
|
19
|
-
:xz
|
|
20
|
-
else
|
|
21
|
-
case beginning.byteslice(0, 2)
|
|
22
|
-
when "\x1F\x8B".force_encoding("BINARY")
|
|
23
|
-
:gzip
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
+
return type if data.byteslice(offset, magic.bytesize) == magic
|
|
26
27
|
end
|
|
28
|
+
|
|
29
|
+
nil
|
|
27
30
|
end
|
|
28
31
|
end
|
|
29
32
|
end
|
data/lib/excavate/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: excavate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cabriolet
|