mootool 0.2.2 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a3b78029772e10d48f7e6c2937c241ff0783f03be555234cd77c5b72cbf10eb
4
- data.tar.gz: d1303b8e5bfdf05bb7a10c86d161fb5ffafa237586f25137e556a35f49b8ec75
3
+ metadata.gz: 4cfbbe3c322b64f68aa32ecfd9373b4158cabb53cec3c6ba392f6c8e1d9a7761
4
+ data.tar.gz: 9ec26119e06df11ccae1aa7eb28796db2d8a6b3af889ba20882ca22847274bff
5
5
  SHA512:
6
- metadata.gz: ae85a488ccf2023d087ae7fc3a6f63b09f3cff51a14555f0e49742e5556b33e898dbafd377ec481a42a23801eb4987155aad924e7e461b5578fff4efc215a35d
7
- data.tar.gz: bed2644636530b161772dc0fa430845fbebfcf057b1bdb47aa0b898129def0eeef0b0434bbea3922de9b88bf8b44d02cc8dd874f8329f7b976d03691c3e1bb84
6
+ metadata.gz: eeed0e6c5d966626700309b618f517169b14d643e76ba9af7f48d66e1c6fae173129011e81f425c9eb209d312f0007ce03be2978520df4d8ebbf1eef585d437a
7
+ data.tar.gz: 7501f0bd4de48f2decc42d5c62ebdcaedf3a9e1720c72a316060eb02a3943032f87120927ac3bebd3b3e068691e3ed42c27b833884141ffbb2ec6a3fdad30046
@@ -16,8 +16,9 @@ on:
16
16
  jobs:
17
17
  test:
18
18
 
19
- runs-on: ubuntu-22.04
19
+ runs-on: ubuntu-latest
20
20
  strategy:
21
+ fail-fast: false
21
22
  matrix:
22
23
  ruby-version: [ '3.0', '3.1.2', '3.2.0-preview1' ]
23
24
 
@@ -27,7 +28,7 @@ jobs:
27
28
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
28
29
  # change this to (see https://github.com/ruby/setup-ruby#versioning):
29
30
  # uses: ruby/setup-ruby@v1
30
- uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
31
+ uses: ruby/setup-ruby@v1
31
32
  with:
32
33
  ruby-version: ${{ matrix.ruby-version }}
33
34
  bundler-cache: true # runs 'bundle install' and caches installed gems automatically
data/Gemfile.lock CHANGED
@@ -1,8 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mootool (0.2.2)
4
+ mootool (0.2.5)
5
+ lzfse
6
+ lzss
5
7
  plist (~> 3)
8
+ ruby-lzma
6
9
  ruby-macho (~> 3)
7
10
  rubyzip (~> 2)
8
11
  sorbet-runtime (~> 0)
@@ -17,6 +20,8 @@ GEM
17
20
  docile (1.4.0)
18
21
  iniparse (1.5.0)
19
22
  json (2.6.2)
23
+ lzfse (0.0.1)
24
+ lzss (0.1)
20
25
  method_source (1.0.0)
21
26
  netrc (0.11.0)
22
27
  overcommit (0.59.1)
@@ -68,6 +73,7 @@ GEM
68
73
  rubocop (~> 1.0)
69
74
  rubocop-rspec (2.12.1)
70
75
  rubocop (~> 1.31)
76
+ ruby-lzma (0.4.3)
71
77
  ruby-macho (3.0.0)
72
78
  ruby-progressbar (1.11.0)
73
79
  rubyzip (2.3.2)
@@ -90,7 +96,7 @@ GEM
90
96
  sorbet (>= 0.5.9204)
91
97
  sorbet-runtime (>= 0.5.9204)
92
98
  thor (>= 0.19.2)
93
- tapioca (0.9.3)
99
+ tapioca (0.9.4)
94
100
  bundler (>= 1.17.3)
95
101
  netrc (>= 0.11.0)
96
102
  parallel (>= 1.21.0)
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lzfse'
4
+ require 'lzma'
5
+ require 'compress/lzss'
6
+
7
+ module MooTool
8
+ # The magic Apple decompressor (as in it uses magics)
9
+ class Decompressor
10
+ COMPRESSION_LZSS = 'lzss'
11
+ COMPRESSION_LZVN = 'lzvn'
12
+ COMPRESSION_LZFSE = 'bvx2'
13
+ COMPRESSION_LZMA = 'lzma'
14
+
15
+ attr_reader :value
16
+
17
+ def initialize(data)
18
+ @value = case data[0..3]
19
+ when COMPRESSION_LZFSE
20
+ LZFSE.lzfse_decompress(data)
21
+ when COMPRESSION_LZVN
22
+ LZFSE.lzvn_decompress(data)
23
+ when COMPRESSION_LZSS
24
+ Compress::LZSS.decompress(data)
25
+ when COMPRESSION_LZMA
26
+ LZMA.decompress(data)
27
+ else
28
+ data
29
+ end
30
+ end
31
+ end
32
+ end
@@ -4,82 +4,114 @@
4
4
  require 'sorbet-runtime'
5
5
 
6
6
  module MooTool
7
- module Models
8
- # DeviceTree is a Apple Device Tree node that has been parsed
9
- class DeviceTree
10
- extend T::Sig
7
+ # DeviceTree is a Apple Device Tree node that has been parsed
8
+ class DeviceTree
9
+ extend T::Sig
10
+
11
+ NODE_FORMAT = 'VV'
12
+ PROP_FORMAT = 'A32V'
11
13
 
12
- NODE_FORMAT = 'VV'
13
- PROP_FORMAT = 'A32V'
14
+ PHANDLE_PROP = 'AAPL,phandle'
15
+ COMPATIBLE_PROP = 'compatible'
14
16
 
15
- # Represents a single node in the device tree
16
- class Node
17
- extend T::Sig
17
+ # Represents a single node in the device tree
18
+ class Node
19
+ extend T::Sig
18
20
 
19
- attr_reader :children, :properties
21
+ attr_reader :children, :properties
20
22
 
21
- sig { params(data: T.any(IO, StringIO)).void }
22
- def initialize(data)
23
- vals = T.must(data.read(8)).unpack(NODE_FORMAT)
24
- property_count = T.cast(vals[0], Integer)
25
- child_count = T.cast(vals[1], Integer)
23
+ sig { params(tree: DeviceTree, data: T.any(IO, StringIO)).void }
24
+ def initialize(tree, data)
25
+ @tree = tree
26
+ vals = T.must(data.read(8)).unpack(NODE_FORMAT)
27
+ property_count = T.cast(vals[0], Integer)
28
+ child_count = T.cast(vals[1], Integer)
26
29
 
27
- @properties = T.let({}, T::Hash[String, Property])
28
- @children = T.let([], T::Array[Node])
30
+ @properties = T.let({}, T::Hash[String, Property])
31
+ @children = T.let([], T::Array[Node])
29
32
 
30
- property_count.times do
31
- prop = Property.new(data)
32
- @properties[prop.name] = prop
33
- end
34
- child_count.times { @children << Node.new(data) }
33
+ property_count.times do
34
+ prop = Property.new(data)
35
+ @properties[prop.name] = prop
35
36
  end
37
+ child_count.times { @children << Node.new(tree, data) }
38
+
39
+ @tree.add_handle(self, @properties[PHANDLE_PROP].value) if @properties.key? PHANDLE_PROP
36
40
  end
37
41
 
38
- # Represents a single property and it's value
39
- class Property
40
- extend T::Sig
42
+ def to_h
43
+ props = @properties.transform_values(&:value)
44
+ if @children.any?
45
+ props.merge({ children: @children.map(&:to_h) })
46
+ else
47
+ props
48
+ end
49
+ end
50
+ end
41
51
 
42
- attr_accessor :name, :value
52
+ # Represents a single property and it's value
53
+ class Property
54
+ extend T::Sig
43
55
 
44
- sig { params(data: T.any(StringIO, IO)).void }
45
- def initialize(data)
46
- args = T.must(data.read(36)).unpack(PROP_FORMAT)
56
+ attr_accessor :name, :value
47
57
 
48
- @name = T.let(T.cast(args[0], String), String)
49
- @size = T.let(T.cast(args[1], Integer), Integer)
58
+ sig { params(data: T.any(StringIO, IO)).void }
59
+ def initialize(data)
60
+ args = T.must(data.read(36)).unpack(PROP_FORMAT)
50
61
 
51
- if @size & 0x80000000 != 0
52
- @template = true
53
- @size &= 0x7fffffff
54
- end
62
+ @name = T.let(T.cast(args[0], String), String)
63
+ @size = T.let(T.cast(args[1], Integer), Integer)
55
64
 
56
- @value = data.read(@size.align(4))
57
- @value = T.must(@value)[0..@size]
65
+ if @size & 0x80000000 != 0
66
+ @template = true
67
+ @size &= 0x7fffffff
58
68
  end
69
+
70
+ @value = T.must(data.read(@size.align(4)))[0..(@size - 1)]
71
+
72
+ normalize
59
73
  end
60
74
 
61
- attr_reader :root
75
+ private
62
76
 
63
- # @param [String] data
64
- sig { params(data: T.any(IO, String, StringIO, Pathname)).void }
65
- def initialize(data)
66
- case data
67
- when Pathname
68
- data = T.assert_type!(data, Pathname)
69
- @data = File.open(data.realpath, 'rb')
70
- when String
71
- data = T.assert_type!(data, String)
72
- @data = StringIO.new(data)
73
- when IO
74
- @data = T.cast(data, IO)
75
- end
76
- @root = Node.new(@data)
77
+ def normalize
78
+ @value = @value.split("\x00").map(&:chomp) if @name == COMPATIBLE_PROP
79
+ @value = @value.unpack1('V') if @size == 4
80
+
81
+ @value = @value.chomp("\x00") if @value.is_a?(String) && @value.count("\x00") == 1 && @value.end_with?("\x00")
77
82
  end
83
+ end
78
84
 
79
- sig { params(path: String).returns(DeviceTree) }
80
- def self.open(path)
81
- DeviceTree.new(Pathname.new(path))
85
+ attr_reader :root
86
+
87
+ # @param [String] data
88
+ sig { params(data: T.any(IO, String, StringIO, Pathname)).void }
89
+ def initialize(data)
90
+ @handles = {}
91
+ case data
92
+ when Pathname
93
+ data = T.assert_type!(data, Pathname)
94
+ @data = File.open(data.realpath, 'rb')
95
+ when String
96
+ data = T.assert_type!(data, String)
97
+ @data = StringIO.new(data)
98
+ when IO
99
+ @data = T.cast(data, IO)
82
100
  end
101
+ @root = Node.new(self, @data)
102
+ end
103
+
104
+ def add_handle(node, handle)
105
+ @handles[handle] = node
106
+ end
107
+
108
+ sig { params(path: String).returns(DeviceTree) }
109
+ def self.open(path)
110
+ MooTool::DeviceTree.new(Pathname.new(path))
111
+ end
112
+
113
+ def to_h
114
+ @root.to_h
83
115
  end
84
116
  end
85
117
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
+ require_relative 'decompressor'
4
5
 
5
6
  module MooTool
6
7
  # Module for Apple's IMG4 encryption and signing format
@@ -18,12 +19,14 @@ module MooTool
18
19
  when 'IM4P'
19
20
  @type = @data.value[1].value
20
21
  @build = @data.value[2].value
21
- @payload = @data.value[3].value
22
+ @payload = MooTool::Decompressor.new(@data.value[3].value).value
22
23
  when 'IMG4', 'IM4M'
23
24
  raise 'Not implemented'
24
25
  else
25
26
  raise "Unknown IMG4 type #{@data.first.value}"
26
27
  end
28
+
29
+ @manifest = Manifest.new(@payload) if @payload.start_with?('IM4M')
27
30
  end
28
31
 
29
32
  def payload?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MooTool
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.5'
5
5
  end
data/mootool.gemspec CHANGED
@@ -37,7 +37,10 @@ Gem::Specification.new do |spec|
37
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
38
  spec.require_paths = ['lib']
39
39
 
40
+ spec.add_runtime_dependency 'lzfse'
41
+ spec.add_runtime_dependency 'lzss'
40
42
  spec.add_runtime_dependency 'plist', '~> 3'
43
+ spec.add_runtime_dependency 'ruby-lzma'
41
44
  spec.add_runtime_dependency 'ruby-macho', '~> 3'
42
45
  spec.add_runtime_dependency 'rubyzip', '~> 2'
43
46
  spec.add_runtime_dependency 'sorbet-runtime', '~> 0'
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mootool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Mark
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-22 00:00:00.000000000 Z
11
+ date: 2022-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lzfse
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lzss
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: plist
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +52,20 @@ dependencies:
24
52
  - - "~>"
25
53
  - !ruby/object:Gem::Version
26
54
  version: '3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby-lzma
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: ruby-macho
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -104,6 +146,7 @@ files:
104
146
  - lib/mootool/controllers/kernel_collection.rb
105
147
  - lib/mootool/controllers/sections.rb
106
148
  - lib/mootool/core_extensions.rb
149
+ - lib/mootool/models/decompressor.rb
107
150
  - lib/mootool/models/device_tree.rb
108
151
  - lib/mootool/models/img4.rb
109
152
  - lib/mootool/models/ipsw.rb