app-info 2.6.4 → 2.7.0.beta5

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: f97c42670196b47aacccbaf9fcee52b7bd4a8e3f21cd2f1f8c8ccfb5fdd7f3dc
4
- data.tar.gz: 6f6a3dad1fdf80548e9d65a6ca84df7ac5a2123081e08912546202b8c03ef026
3
+ metadata.gz: 87af7ee3238f0c866c3d4ad7110bba74ae1950e28f1619049ec52470253bf45a
4
+ data.tar.gz: 8eeaaa20c0f5e4036e2c2138f51f42554d0e5b73dc340c9a71ea9ce344d0c55a
5
5
  SHA512:
6
- metadata.gz: f11aea895a604a5cd9452e923a028514dfa36853c4ec7448b7d0dade327a63815c326aff4aa5532514c0b2f90dd966a688feef2f01c709b5d98a182ce81dbadd
7
- data.tar.gz: 54be915b94a47906df35e4149b99136a1bc82da6549890b01a5dd60320208ebd2ccd35fc70b32620a7a2f56f6f6f1566411dca27f9d7aac09d4512051f713d24
6
+ metadata.gz: c61cf34da0123d9cd6e0df63f3f342d61858c3dfc9dfd8e57cfce7a18af9bae5fbc85b8a20e79a9e8b54a630b240105ce036b0f03c49fd96df8945fa472ae148
7
+ data.tar.gz: ae7f4064095ad2c1518095876532c7c6364a785209fefb9e8fbf1fa7c3fe02fe3027df20572db55b5fb72d8cdadd70e59738ec0458a3fd391c264b168f744ff5
data/.rubocop.yml CHANGED
@@ -20,10 +20,12 @@ AllCops:
20
20
  Exclude:
21
21
  - 'bin/*'
22
22
  - 'spec/**/*'
23
- - vendor/bundle/**/*
23
+ - 'vendor/bundle/**/*'
24
24
  - 'Rakefile'
25
25
  - 'app_info.gemspec'
26
26
  - 'lib/app-info.rb'
27
+ - 'lib/app_info/protobuf/models/*_pb.rb'
28
+ - 'main.rb'
27
29
 
28
30
  Metrics/AbcSize:
29
31
  Max: 100
@@ -56,4 +58,19 @@ Lint/AssignmentInCondition:
56
58
  Enabled: false
57
59
 
58
60
  Style/Documentation:
59
- Enabled: false
61
+ Enabled: false
62
+
63
+ Style/PerlBackrefs:
64
+ Exclude:
65
+ - 'lib/app_info/core_ext/string/inflector.rb'
66
+
67
+ Style/DocumentDynamicEvalDefinition:
68
+ Enabled: false
69
+
70
+ Metrics/BlockNesting:
71
+ Exclude:
72
+ - 'lib/app_info/dsym.rb'
73
+
74
+
75
+ Style/SlicingWithRange:
76
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -9,6 +9,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
9
9
 
10
10
  > List all changes before release a new version.
11
11
 
12
+ ## [2.7.0.beta5] (2021-10-14)
13
+
14
+ ### Fixed
15
+
16
+ - Renamed methods of inflector (Conflicts with similar external methods, such like ActiveSupport Core Extensions)
17
+ - Keep same behavior methods between apk and aab
18
+
19
+ ## [2.7.0.beta2] (2021-09-29)
20
+
21
+ ### Fixed
22
+
23
+ - Fix allocator undefined data class [#38](https://github.com/icyleaf/app_info/pull/38)
24
+
25
+ ## [2.7.0.beta1] (2021-09-27)
26
+
27
+ ### Added
28
+
29
+ - Android App Bundle a.k.a `aab` file parts support [#36](https://github.com/icyleaf/app_info/pull/36)
30
+
31
+ ## [2.6.5] (2021-09-17)
32
+
33
+ ### Added
34
+
35
+ - Add ability to retrieve manifest metadata (depend on playtestcloud/ruby_apk forked one)
36
+
12
37
  ## [2.6.4] (2021-09-10)
13
38
 
14
39
  ### Fixed
@@ -179,7 +204,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
179
204
 
180
205
  - Updated dependency of CFPropertly list be a range between 2.3.4. (thanks @[cschroed](https://github.com/cschroed))
181
206
 
182
- [Unreleased]: https://github.com/icyleaf/app-info/compare/v2.6.4..HEAD
207
+ [Unreleased]: https://github.com/icyleaf/app-info/compare/v2.7.0.beta5..HEAD
208
+ [2.7.0.beta5]: https://github.com/icyleaf/app-info/compare/v2.7.0.beta2...v2.7.0.beta5
209
+ [2.7.0.beta2]: https://github.com/icyleaf/app-info/compare/v2.7.0.beta1...v2.7.0.beta2
210
+ [2.7.0.beta1]: https://github.com/icyleaf/app-info/compare/v2.6.5...v2.7.0.beta1
211
+ [2.6.5]: https://github.com/icyleaf/app-info/compare/v2.6.4...v2.6.5
183
212
  [2.6.4]: https://github.com/icyleaf/app-info/compare/v2.6.3...v2.6.4
184
213
  [2.6.3]: https://github.com/icyleaf/app-info/compare/v2.6.1...v2.6.3
185
214
  [2.6.1]: https://github.com/icyleaf/app-info/compare/v2.6.0...v2.6.1
data/README.md CHANGED
@@ -5,16 +5,18 @@
5
5
  [![Gem version](https://img.shields.io/gem/v/app-info.svg?style=flat)](https://rubygems.org/gems/app_info)
6
6
  [![License](https://img.shields.io/badge/license-MIT-red.svg?style=flat)](LICENSE)
7
7
 
8
- Teardown tool for mobile(ipa/apk) app, macOS app and dSYM.zip file, analysis metedata like version, name, icon etc.
8
+ Teardown tool for mobile app (ipa, apk and aab file), macOS app and dSYM.zip file, analysis metedata like version, name, icon etc.
9
9
 
10
10
  ## Support
11
11
 
12
- - Android apk file
12
+ - Android file
13
+ - `.apk`
14
+ - `.aab` (Androld App Bundle)
13
15
  - iOS ipa file
14
- - Info.plist file
15
- - .mobileprovision/.provisionprofile file
16
- - macOS App(.zip) file
17
- - dSYM(.zip) file
16
+ - `Info.plist` file
17
+ - `.mobileprovision`/`.provisionprofile` file
18
+ - Zipped macOS App file
19
+ - Zipped dSYMs file
18
20
 
19
21
  ## Installation
20
22
 
@@ -54,6 +56,7 @@ parser = AppInfo.parse('App.dSYm.zip')
54
56
  # If detect file type failed, you can parse in other way
55
57
  parser = AppInfo::IPA.new('iphone.ipa')
56
58
  parser = AppInfo::APK.new('android.apk')
59
+ parser = AppInfo::AAB.new('android.aab')
57
60
  parser = AppInfo::InfoPlist.new('Info.plist')
58
61
  parser = AppInfo::MobileProvision.new('uuid.mobileprovision')
59
62
  parser = AppInfo::Macos.new('App.dSYm.zip')
data/app_info.gemspec CHANGED
@@ -23,10 +23,11 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency 'CFPropertyList', '< 3.1.0', '>= 2.3.4'
24
24
  spec.add_dependency 'image_size', '>= 1.5', '< 2.2'
25
25
  spec.add_dependency 'ruby-macho', '< 3', '>= 1.4'
26
- spec.add_dependency 'ruby_android', '~> 0.7.7'
26
+ spec.add_dependency 'android_parser', '~> 2.4.1'
27
27
  spec.add_dependency 'rubyzip', '>= 1.2', '< 3.0'
28
28
  spec.add_dependency 'uuidtools', '>= 2.1.5', '< 2.3.0'
29
29
  spec.add_dependency 'icns', '~> 0.2.0'
30
+ spec.add_dependency 'google-protobuf', '~> 3.18.0'
30
31
 
31
32
  spec.add_development_dependency 'bundler', '>= 1.12'
32
33
  spec.add_development_dependency 'rake', '>= 10.0'
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'app_info/protobuf/manifest'
4
+ require 'image_size'
5
+ require 'forwardable'
6
+
7
+ module AppInfo
8
+ # Parse APK file
9
+ class AAB
10
+ include Helper::HumanFileSize
11
+ extend Forwardable
12
+
13
+ attr_reader :file
14
+
15
+ # APK Devices
16
+ module Device
17
+ PHONE = 'Phone'
18
+ TABLET = 'Tablet'
19
+ WATCH = 'Watch'
20
+ TV = 'Television'
21
+ end
22
+
23
+ BASE_PATH = 'base'
24
+ BASE_MANIFEST = "#{BASE_PATH}/manifest/AndroidManifest.xml"
25
+ BASE_RESOURCES = "#{BASE_PATH}/resources.pb"
26
+
27
+ def initialize(file)
28
+ @file = file
29
+ end
30
+
31
+ def size(human_size: false)
32
+ file_to_human_size(@file, human_size: human_size)
33
+ end
34
+
35
+ def os
36
+ Platform::ANDROID
37
+ end
38
+ alias file_type os
39
+
40
+ def_delegators :manifest, :version_name
41
+
42
+ alias release_version version_name
43
+
44
+ def package_name
45
+ manifest.package
46
+ end
47
+ alias identifier package_name
48
+ alias bundle_id package_name
49
+
50
+ def version_code
51
+ manifest.version_code.to_s
52
+ end
53
+ alias build_version version_code
54
+
55
+ def name
56
+ manifest.label
57
+ end
58
+
59
+ def device_type
60
+ if wear?
61
+ Device::WATCH
62
+ elsif tv?
63
+ Device::TV
64
+ else
65
+ Device::PHONE
66
+ end
67
+ end
68
+
69
+ # TODO: find a way to detect
70
+ # Found answer but not works: https://stackoverflow.com/questions/9279111/determine-if-the-device-is-a-smartphone-or-tablet
71
+ # def tablet?
72
+ # resource.first_package
73
+ # .entries('bool')
74
+ # .select{|e| e.name == 'isTablet' }
75
+ # .size >= 1
76
+ # end
77
+
78
+ def wear?
79
+ use_features.include?('android.hardware.type.watch')
80
+ end
81
+
82
+ def tv?
83
+ use_features.include?('android.software.leanback')
84
+ end
85
+
86
+ def min_sdk_version
87
+ manifest.uses_sdk.min_sdk_version
88
+ end
89
+ alias min_os_version min_sdk_version
90
+
91
+ def target_sdk_version
92
+ manifest.uses_sdk.target_sdk_version
93
+ end
94
+
95
+ def use_features
96
+ @use_features ||= manifest&.uses_feature&.map(&:name)
97
+ end
98
+
99
+ def use_permissions
100
+ @use_permissions ||= manifest&.uses_permission&.map(&:name)
101
+ end
102
+
103
+ def activities
104
+ @activities ||= manifest.activities
105
+ end
106
+
107
+ def services
108
+ @services ||= manifest.services
109
+ end
110
+
111
+ def components
112
+ @components ||= manifest.components.transform_values
113
+ end
114
+
115
+ def signs
116
+ return @signs if @signs
117
+
118
+ @signs = []
119
+ each_file do |path, data|
120
+ # find META-INF/xxx.{RSA|DSA}
121
+ next unless path =~ %r{^META-INF/} && data.unpack('CC') == [0x30, 0x82]
122
+
123
+ @signs << APK::Sign.new(path, OpenSSL::PKCS7.new(data))
124
+ end
125
+
126
+ @signs
127
+ end
128
+
129
+ def certificates
130
+ @certificates ||= signs.each_with_object([]) do |sign, obj|
131
+ obj << APK::Certificate.new(sign.path, sign.sign.certificates[0])
132
+ end
133
+ end
134
+
135
+ def each_file
136
+ zip.each do |entry|
137
+ next unless entry.file?
138
+
139
+ yield entry.name, @zip.read(entry)
140
+ end
141
+ end
142
+
143
+ def read_file(name, base_path: BASE_PATH)
144
+ content = @zip.read(entry(name, base_path: base_path))
145
+ return parse_binary_xml(content) if xml_file?(name)
146
+
147
+ content
148
+ end
149
+
150
+ def entry(name, base_path: BASE_PATH)
151
+ entry = @zip.find_entry(File.join(base_path, name))
152
+ raise NotFoundError, "'#{name}'" if entry.nil?
153
+
154
+ entry
155
+ end
156
+
157
+ def manifest
158
+ io = zip.read(zip.find_entry(BASE_MANIFEST))
159
+ @manifest ||= Protobuf::Manifest.parse(io, resource)
160
+ end
161
+
162
+ def resource
163
+ io = zip.read(zip.find_entry(BASE_RESOURCES))
164
+ @resource ||= Protobuf::Resources.parse(io)
165
+ end
166
+
167
+ def zip
168
+ @zip ||= Zip::File.open(@file)
169
+ end
170
+
171
+ def icons
172
+ @icons ||= manifest.icons.each_with_object([]) do |res, obj|
173
+ path = res.value
174
+ filename = File.basename(path)
175
+ filepath = File.join(contents, File.dirname(path))
176
+ file = File.join(filepath, filename)
177
+ FileUtils.mkdir_p filepath
178
+
179
+ binary_data = read_file(path)
180
+ File.write(file, binary_data, encoding: Encoding::BINARY)
181
+
182
+ obj << {
183
+ name: filename,
184
+ file: file,
185
+ dimensions: ImageSize.path(file).size
186
+ }
187
+ end
188
+ end
189
+
190
+ def clear!
191
+ return unless @contents
192
+
193
+ FileUtils.rm_rf(@contents)
194
+
195
+ @aab = nil
196
+ @contents = nil
197
+ @icons = nil
198
+ @app_path = nil
199
+ @info = nil
200
+ end
201
+
202
+ def contents
203
+ @contents ||= File.join(Dir.mktmpdir, "AppInfo-android-#{SecureRandom.hex}")
204
+ end
205
+
206
+ private
207
+
208
+ def xml_file?(file)
209
+ File.extname(file) == '.xml'
210
+ end
211
+
212
+ # TODO: how to convert xml content after decode protoubufed content
213
+ def parse_binary_xml(io)
214
+ io
215
+ # Aapt::Pb::XmlNode.decode(io)
216
+ end
217
+ end
218
+ end
data/lib/app_info/apk.rb CHANGED
@@ -7,6 +7,7 @@ require 'forwardable'
7
7
  module AppInfo
8
8
  # Parse APK file
9
9
  class APK
10
+ include Helper::HumanFileSize
10
11
  extend Forwardable
11
12
 
12
13
  attr_reader :file
@@ -24,11 +25,11 @@ module AppInfo
24
25
  end
25
26
 
26
27
  def size(human_size: false)
27
- AppInfo::Util.file_size(@file, human_size)
28
+ file_to_human_size(@file, human_size: human_size)
28
29
  end
29
30
 
30
31
  def os
31
- AppInfo::Platform::ANDROID
32
+ Platform::ANDROID
32
33
  end
33
34
  alias file_type os
34
35
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppInfo
4
+ module Inflector
5
+ def ai_snakecase
6
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
7
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
8
+ .tr('-', '_')
9
+ .gsub(/\s/, '_')
10
+ .gsub(/__+/, '_')
11
+ .downcase
12
+ end
13
+
14
+ def ai_camelcase(first_letter: :upper, separators: ['-', '_', '\s'])
15
+ str = dup
16
+
17
+ separators.each do |s|
18
+ str = str.gsub(/(?:#{s}+)([a-z])/) { $1.upcase }
19
+ end
20
+
21
+ case first_letter
22
+ when :upper, true
23
+ str = str.gsub(/(\A|\s)([a-z])/) { $1 + $2.upcase }
24
+ when :lower, false
25
+ str = str.gsub(/(\A|\s)([A-Z])/) { $1 + $2.downcase }
26
+ end
27
+
28
+ str
29
+ end
30
+ end
31
+ end
32
+
33
+ class String
34
+ include AppInfo::Inflector
35
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'app_info/core_ext/object/try'
4
+ require 'app_info/core_ext/string/inflector'
data/lib/app_info/dsym.rb CHANGED
@@ -5,6 +5,8 @@ require 'macho'
5
5
  module AppInfo
6
6
  # DSYM parser
7
7
  class DSYM
8
+ include Helper::Archive
9
+
8
10
  attr_reader :file
9
11
 
10
12
  def initialize(file)
@@ -12,7 +14,7 @@ module AppInfo
12
14
  end
13
15
 
14
16
  def file_type
15
- AppInfo::Platform::DSYM
17
+ Platform::DSYM
16
18
  end
17
19
 
18
20
  def object
@@ -91,7 +93,7 @@ module AppInfo
91
93
  @contents = @file
92
94
  else
93
95
  dsym_dir = nil
94
- @contents = Util.unarchive(@file, path: 'dsym') do |path, zip_file|
96
+ @contents = unarchive(@file, path: 'dsym') do |path, zip_file|
95
97
  zip_file.each do |f|
96
98
  unless dsym_dir
97
99
  dsym_dir = f.name
@@ -114,6 +116,8 @@ module AppInfo
114
116
 
115
117
  # DSYM Mach-O
116
118
  class MachO
119
+ include Helper::HumanFileSize
120
+
117
121
  def initialize(file, size = 0)
118
122
  @file = file
119
123
  @size = size
@@ -132,7 +136,7 @@ module AppInfo
132
136
  end
133
137
 
134
138
  def size(human_size: false)
135
- return Util.size_to_human_size(@size) if human_size
139
+ return number_to_human_size(@size) if human_size
136
140
 
137
141
  @size
138
142
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zip'
4
+ require 'fileutils'
5
+ require 'securerandom'
6
+
7
+ module AppInfo
8
+ class Error < StandardError; end
9
+
10
+ class NotFoundError < Error; end
11
+
12
+ class UnkownFileTypeError < Error; end
13
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AppInfo
4
+ # App Platform
5
+ module Platform
6
+ MACOS = 'macOS'
7
+ IOS = 'iOS'
8
+ ANDROID = 'Android'
9
+ DSYM = 'dSYM'
10
+ PROGUARD = 'Proguard'
11
+ end
12
+
13
+ # Device Type
14
+ module Device
15
+ MACOS = 'macOS'
16
+ IPHONE = 'iPhone'
17
+ IPAD = 'iPad'
18
+ UNIVERSAL = 'Universal'
19
+ end
20
+
21
+ module AndroidDevice
22
+ PHONE = 'Phone'
23
+ TABLET = 'Tablet'
24
+ WATCH = 'Watch'
25
+ TV = 'Television'
26
+ end
27
+
28
+ # Icon Key
29
+ ICON_KEYS = {
30
+ Device::IPHONE => ['CFBundleIcons'],
31
+ Device::IPAD => ['CFBundleIcons~ipad'],
32
+ Device::UNIVERSAL => ['CFBundleIcons', 'CFBundleIcons~ipad'],
33
+ Device::MACOS => %w[CFBundleIconFile CFBundleIconName]
34
+ }.freeze
35
+
36
+ module Helper
37
+ module HumanFileSize
38
+ def file_to_human_size(file, human_size:)
39
+ number = File.size(file)
40
+ human_size ? number_to_human_size(number) : number
41
+ end
42
+
43
+ FILE_SIZE_UNITS = %w[B KB MB GB TB].freeze
44
+
45
+ def number_to_human_size(number)
46
+ if number.to_i < 1024
47
+ exponent = 0
48
+ else
49
+ max_exp = FILE_SIZE_UNITS.size - 1
50
+ exponent = (Math.log(number) / Math.log(1024)).to_i
51
+ exponent = max_exp if exponent > max_exp
52
+ number = format('%<number>.2f', number: (number / (1024**exponent.to_f)))
53
+ end
54
+
55
+ "#{number} #{FILE_SIZE_UNITS[exponent]}"
56
+ end
57
+ end
58
+
59
+ module Archive
60
+ require 'zip'
61
+ require 'fileutils'
62
+ require 'securerandom'
63
+
64
+ # Unarchive zip file
65
+ #
66
+ # source: https://github.com/soffes/lagunitas/blob/master/lib/lagunitas/ipa.rb
67
+ def unarchive(file, path: nil)
68
+ path = path ? "#{path}-" : ''
69
+ root_path = "#{Dir.mktmpdir}/AppInfo-#{path}#{SecureRandom.hex}"
70
+ Zip::File.open(file) do |zip_file|
71
+ if block_given?
72
+ yield root_path, zip_file
73
+ else
74
+ zip_file.each do |f|
75
+ f_path = File.join(root_path, f.name)
76
+ FileUtils.mkdir_p(File.dirname(f_path))
77
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
78
+ end
79
+ end
80
+ end
81
+
82
+ root_path
83
+ end
84
+
85
+ def tempdir(file, prefix:)
86
+ dest_path ||= File.join(File.dirname(file), prefix)
87
+ dest_file = File.join(dest_path, File.basename(file))
88
+
89
+ Dir.mkdir(dest_path, 0_700) unless Dir.exist?(dest_path)
90
+
91
+ dest_file
92
+ end
93
+ end
94
+
95
+ module Defines
96
+ def create_class(klass_name, parent_class, namespace:)
97
+ klass = Class.new(parent_class) do
98
+ yield if block_given?
99
+ end
100
+
101
+ name = namespace.to_s.empty? ? klass_name : "#{namespace}::#{klass_name}"
102
+ if Object.const_get(namespace).const_defined?(klass_name)
103
+ Object.const_get(namespace).const_get(klass_name)
104
+ elsif Object.const_defined?(name)
105
+ Object.const_get(name)
106
+ else
107
+ Object.const_get(namespace).const_set(klass_name, klass)
108
+ end
109
+ end
110
+
111
+ def define_instance_method(key, value)
112
+ instance_variable_set("@#{key}", value)
113
+ self.class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
114
+ def #{key}
115
+ @#{key}
116
+ end
117
+ RUBY
118
+ end
119
+ end
120
+
121
+ module ReferenceParser
122
+ def reference_segments(value)
123
+ new_value = value.is_a?(Aapt::Pb::Reference) ? value.name : value
124
+ return new_value.split('/', 2) if new_value.include?('/')
125
+
126
+ [nil, new_value]
127
+ end
128
+ end
129
+ end
130
+ end
@@ -67,13 +67,13 @@ module AppInfo
67
67
  def device_type
68
68
  device_family = info.try(:[], 'UIDeviceFamily')
69
69
  if device_family == [1]
70
- AppInfo::Device::IPHONE
70
+ Device::IPHONE
71
71
  elsif device_family == [2]
72
- AppInfo::Device::IPAD
72
+ Device::IPAD
73
73
  elsif device_family == [1, 2]
74
- AppInfo::Device::UNIVERSAL
74
+ Device::UNIVERSAL
75
75
  elsif !info.try(:[], 'DTSDKName').nil? || !info.try(:[], 'DTPlatformName').nil?
76
- AppInfo::Device::MACOS
76
+ Device::MACOS
77
77
  end
78
78
  end
79
79
 
@@ -112,13 +112,13 @@ module AppInfo
112
112
  def_delegators :info, :to_h
113
113
 
114
114
  def method_missing(method_name, *args, &block)
115
- info.try(:[], Util.format_key(method_name)) ||
115
+ info.try(:[], method_name.to_s.ai_camelcase) ||
116
116
  info.send(method_name) ||
117
117
  super
118
118
  end
119
119
 
120
120
  def respond_to_missing?(method_name, *args)
121
- info.key?(Util.format_key(method_name)) ||
121
+ info.key?(method_name.to_s.ai_camelcase) ||
122
122
  info.respond_to?(method_name) ||
123
123
  super
124
124
  end
data/lib/app_info/ipa.rb CHANGED
@@ -8,6 +8,8 @@ require 'cfpropertylist'
8
8
  module AppInfo
9
9
  # IPA parser
10
10
  class IPA
11
+ include Helper::HumanFileSize
12
+ include Helper::Archive
11
13
  extend Forwardable
12
14
 
13
15
  attr_reader :file
@@ -28,11 +30,11 @@ module AppInfo
28
30
  end
29
31
 
30
32
  def size(human_size: false)
31
- AppInfo::Util.file_size(@file, human_size)
33
+ file_to_human_size(@file, human_size: human_size)
32
34
  end
33
35
 
34
36
  def os
35
- AppInfo::Platform::IOS
37
+ Platform::IOS
36
38
  end
37
39
  alias file_type os
38
40
 
@@ -195,7 +197,7 @@ module AppInfo
195
197
  end
196
198
 
197
199
  def contents
198
- @contents ||= Util.unarchive(@file, path: 'ios')
200
+ @contents ||= unarchive(@file, path: 'ios')
199
201
  end
200
202
 
201
203
  private
@@ -213,7 +215,7 @@ module AppInfo
213
215
 
214
216
  # Uncrush png to normal png file (iOS)
215
217
  def uncrush_png(src_file)
216
- dest_file = Util.tempdir(src_file, prefix: 'uncrushed')
218
+ dest_file = tempdir(src_file, prefix: 'uncrushed')
217
219
  PngUncrush.decompress(src_file, dest_file)
218
220
  File.exist?(dest_file) ? dest_file : nil
219
221
  end