mootool 0.2.3 → 0.2.4

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: 4cb92ea5d0aabdbcf38f13ad689433f8b68ca590f33dbf5c9df2faaa5f4c3903
4
- data.tar.gz: 583f08dc949bd8f0cb597128b1c25728ec579c6b726330db082cba89fdd1e2c5
3
+ metadata.gz: 9706bb658f685c95928c3df7cc944657976d13fcd7bd08bdd1306a4715340eff
4
+ data.tar.gz: e275e9e729b7a8a75d4dc7f1c2ae413315963be2cff388c598216e63d9dd1a51
5
5
  SHA512:
6
- metadata.gz: b1f196cb6d8487d32861467204cc8ff59e4447141b0a18e867d43a6afa0ca0e18923ab121767b06bcf8143faabfa2a9b7c4490737195a5f8b81068de24c6d5dc
7
- data.tar.gz: 6e52e6278cdb716c6cfe377ad7199c0adaed6aa7b365f082bf19f0f09f69370f0690caa6ec165c2d36f4793c8fc837455131cbcfe2b3513f5c61c7452f87e161
6
+ metadata.gz: cdb68cf6de5600620c85922edefef776fcee8585b05b9240fa457625742d877593ee07e047a3fcb3f655c424cc17a711573aff62f922cee497a8d428d1f8925a
7
+ data.tar.gz: 7a6d65c21a8417429b3314d6605798d988dbb43e8fdb52c012a48d5ed62e750e0a3c8a98c5226595bc05d524b15cff86ece61644a0b67598d4cc578118753032
data/Gemfile.lock CHANGED
@@ -1,8 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mootool (0.2.3)
4
+ mootool (0.2.4)
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.3'
4
+ VERSION = '0.2.4'
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.3
4
+ version: 0.2.4
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-23 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