app-info 2.4.2 → 2.5.4
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/CHANGELOG.md +32 -1
- data/Gemfile +4 -0
- data/README.md +7 -2
- data/app_info.gemspec +2 -2
- data/lib/app_info/apk.rb +1 -1
- data/lib/app_info/ipa/info_plist.rb +22 -9
- data/lib/app_info/png_uncrush.rb +181 -0
- data/lib/app_info/util.rb +1 -1
- data/lib/app_info/version.rb +1 -1
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b79b22cebadeb4bb9b7f0a2febe6d996cb47b7a399bc0d25fa2132c1b7a260f9
|
4
|
+
data.tar.gz: 87547d3dba6b1972a5875d0e3daf269b3e0d694b9a852caf8f99bbdd2336b715
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 468aedb4563c48b03a0e9e2a58bb7191f69168c46cad443d8f0e9ab01d5114d19b205d25e111a481119b5510b337208475e15cfb1c09106fde48d287c7b65cfe
|
7
|
+
data.tar.gz: 567e84b8577840273235212c3c1d03f9861f3c674adcd52017c54266304dd7510dbed41913c89cbb2d228fdb6a6541ed1438c4ea9b3a83de61411c3014e6cc02
|
data/CHANGELOG.md
CHANGED
@@ -9,6 +9,34 @@ 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.5.3] (2021-06-16)
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
- Fix decompress png error (mostly because of it is a normal png file) [#32](https://github.com/icyleaf/app_info/pull/32) thanks @[莫小七](https://github.com/mxq0923)
|
17
|
+
|
18
|
+
## [2.5.2] (2021-04-15)
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
|
22
|
+
- Fix handle get Android application name from manifest first [#29](https://github.com/icyleaf/app_info/issues/29) thanks @[DreamPWJ](https://github.com/DreamPWJ)
|
23
|
+
|
24
|
+
## [2.5.1] (2021-04-14)
|
25
|
+
|
26
|
+
### Add
|
27
|
+
|
28
|
+
- Restore `dimensions` key from icons method and icon pnguncrush back.
|
29
|
+
|
30
|
+
## [2.4.3] (2021-04-12)
|
31
|
+
|
32
|
+
### Fixed
|
33
|
+
|
34
|
+
- Fix throws an exception 'IHDR not in place for PNG' during parse ipa file.
|
35
|
+
|
36
|
+
### Changed
|
37
|
+
|
38
|
+
- Temporary remove `dimensions` key from icons method (Only ipa file)
|
39
|
+
|
12
40
|
## [2.4.2] (2021-04-06)
|
13
41
|
|
14
42
|
### Changed
|
@@ -108,7 +136,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
108
136
|
|
109
137
|
- Updated dependency of CFPropertly list be a range between 2.3.4. (thanks @[cschroed](https://github.com/cschroed))
|
110
138
|
|
111
|
-
[Unreleased]: https://github.com/icyleaf/app-info/compare/v2.
|
139
|
+
[Unreleased]: https://github.com/icyleaf/app-info/compare/v2.5.2..HEAD
|
140
|
+
[2.5.2]: https://github.com/icyleaf/app-info/compare/v2.5.1...v2.5.2
|
141
|
+
[2.5.1]: https://github.com/icyleaf/app-info/compare/v2.4.3...v2.5.1
|
142
|
+
[2.4.3]: https://github.com/icyleaf/app-info/compare/v2.4.2...v2.4.3
|
112
143
|
[2.4.2]: https://github.com/icyleaf/app-info/compare/v2.4.1...v2.4.2
|
113
144
|
[2.4.1]: https://github.com/icyleaf/app-info/compare/v2.3.0...v2.4.1
|
114
145
|
[2.3.0]: https://github.com/icyleaf/app-info/compare/v2.2.0...v2.3.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -82,7 +82,7 @@ ipa.bundle_id
|
|
82
82
|
|
83
83
|
# get app icons
|
84
84
|
ipa.icons
|
85
|
-
# => [{:name=>"AppIcon29x29@2x~ipad.png", :file=>"/var/folders/mb/8cm0fz4d499968yss9y1j8bc0000gp/T/d20160728-69669-1xnub30/AppInfo-ios-a5369339399e62046d7d59c52254dac6/Payload/bundle.app/AppIcon29x29@2x~ipad.png", :dimensions=>[
|
85
|
+
# => [{:name=>"AppIcon29x29@2x~ipad.png", :file=>"/var/folders/mb/8cm0fz4d499968yss9y1j8bc0000gp/T/d20160728-69669-1xnub30/AppInfo-ios-a5369339399e62046d7d59c52254dac6/Payload/bundle.app/AppIcon29x29@2x~ipad.png"}, :dimensions=>[29, 29], :uncrushed_file=>"..." ...]
|
86
86
|
|
87
87
|
# get provisioning profile devices
|
88
88
|
ipa.devices
|
@@ -239,6 +239,11 @@ apk.tv?
|
|
239
239
|
apk.wear?
|
240
240
|
```
|
241
241
|
|
242
|
+
## Best Practice
|
243
|
+
|
244
|
+
- [fastlane-plugin-app_info](https://github.com/icyleaf/fastlane-plugin-app_info): fastlane plugin
|
245
|
+
- [zealot](https://github.com/tryzealot/zealot/): Over The Air Server for deployment of Android and iOS apps
|
246
|
+
|
242
247
|
## Development
|
243
248
|
|
244
249
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -247,7 +252,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
247
252
|
|
248
253
|
## Contributing
|
249
254
|
|
250
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
255
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/icyleaf/app-info. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
251
256
|
|
252
257
|
## License
|
253
258
|
|
data/app_info.gemspec
CHANGED
@@ -19,9 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
spec.required_ruby_version = '>= 2.3'
|
21
21
|
|
22
|
-
spec.add_dependency 'CFPropertyList',
|
22
|
+
spec.add_dependency 'CFPropertyList', '< 3.1.0', '>= 2.3.4'
|
23
23
|
spec.add_dependency 'image_size', '>= 1.5', '< 2.2'
|
24
|
-
spec.add_dependency 'ruby-macho', '
|
24
|
+
spec.add_dependency 'ruby-macho', '< 3', '>= 1.4'
|
25
25
|
spec.add_dependency 'ruby_android', '~> 0.7.7'
|
26
26
|
spec.add_dependency 'rubyzip', '>= 1.2', '< 3.0'
|
27
27
|
spec.add_dependency 'uuidtools', '>= 2.1.5', '< 2.3.0'
|
data/lib/app_info/apk.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'image_size'
|
4
3
|
require 'cfpropertylist'
|
4
|
+
require 'app_info/png_uncrush'
|
5
5
|
require 'app_info/util'
|
6
6
|
|
7
7
|
module AppInfo
|
@@ -43,7 +43,7 @@ module AppInfo
|
|
43
43
|
info.try(:[], 'MinimumOSVersion')
|
44
44
|
end
|
45
45
|
|
46
|
-
def icons
|
46
|
+
def icons(uncrush = true)
|
47
47
|
return @icons if @icons
|
48
48
|
|
49
49
|
@icons = []
|
@@ -56,13 +56,7 @@ module AppInfo
|
|
56
56
|
|
57
57
|
icon_array.each do |items|
|
58
58
|
Dir.glob(File.join(@app_path, "#{items}*")).find_all.each do |file|
|
59
|
-
|
60
|
-
name: File.basename(file),
|
61
|
-
file: file,
|
62
|
-
dimensions: ImageSize.path(file).size
|
63
|
-
}
|
64
|
-
|
65
|
-
@icons.push(dict)
|
59
|
+
@icons << icon_info(file, uncrush)
|
66
60
|
end
|
67
61
|
end
|
68
62
|
end
|
@@ -122,6 +116,25 @@ module AppInfo
|
|
122
116
|
|
123
117
|
private
|
124
118
|
|
119
|
+
def icon_info(file, uncrush = true)
|
120
|
+
uncrushed_file = nil
|
121
|
+
if uncrush
|
122
|
+
path = File.join(File.dirname(file), 'uncrushed')
|
123
|
+
Dir.mkdir(path, 0700) unless Dir.exist?(path)
|
124
|
+
|
125
|
+
uncrushed_file = File.join(path, File.basename(file))
|
126
|
+
PngUncrush.decompress(file, uncrushed_file)
|
127
|
+
uncrushed_file = nil unless File.exists?(uncrushed_file)
|
128
|
+
end
|
129
|
+
|
130
|
+
{
|
131
|
+
name: File.basename(file),
|
132
|
+
file: file,
|
133
|
+
uncrushed_file: uncrushed_file,
|
134
|
+
dimensions: PngUncrush.dimensions(file)
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
125
138
|
def info
|
126
139
|
return unless File.file?(info_path)
|
127
140
|
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright @ Wenwei Cai on 26 Aug 2012.
|
4
|
+
# https://github.com/swcai/iphone-png-normalizer
|
5
|
+
|
6
|
+
require 'zlib'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
module AppInfo
|
10
|
+
class PngUncrush
|
11
|
+
class Error < StandardError; end
|
12
|
+
class FormatError < Error; end
|
13
|
+
|
14
|
+
class PngReader # :nodoc:
|
15
|
+
PNG_HEADER = "\x89PNG\r\n\x1a\n".bytes
|
16
|
+
CHUNK = 1024
|
17
|
+
|
18
|
+
attr_reader :data
|
19
|
+
|
20
|
+
def initialize(raw)
|
21
|
+
@io = if raw.is_a?(String)
|
22
|
+
StringIO.new(raw)
|
23
|
+
elsif raw.respond_to?(:read) && raw.respond_to?(:eof?)
|
24
|
+
raw
|
25
|
+
else
|
26
|
+
raise ArgumentError, "expected data as String or an object responding to read, got #{raw.class}"
|
27
|
+
end
|
28
|
+
|
29
|
+
@data = String.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
@io.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def unpack(a)
|
37
|
+
@io.unpack(a)
|
38
|
+
end
|
39
|
+
|
40
|
+
def header
|
41
|
+
@header ||= self[0, 8]
|
42
|
+
end
|
43
|
+
|
44
|
+
def png?
|
45
|
+
PNG_HEADER == header.bytes
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](offset, length)
|
49
|
+
while !@io.eof? && @data.length < offset + length
|
50
|
+
data = @io.read(CHUNK)
|
51
|
+
break unless data
|
52
|
+
|
53
|
+
data.force_encoding(@data.encoding) if data.respond_to?(:encoding)
|
54
|
+
@data << data
|
55
|
+
end
|
56
|
+
|
57
|
+
@data[offset, length]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.decompress(input, output)
|
62
|
+
new(input).decompress(output)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.dimensions(input)
|
66
|
+
new(input).dimensions
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(filename)
|
70
|
+
@io = PngReader.new(File.open(filename))
|
71
|
+
raise FormatError, 'not a png file' unless @io.png?
|
72
|
+
end
|
73
|
+
|
74
|
+
def dimensions
|
75
|
+
_dump_sections(dimensions: true)
|
76
|
+
end
|
77
|
+
|
78
|
+
def decompress(output)
|
79
|
+
content = _remap(_dump_sections)
|
80
|
+
return false unless content
|
81
|
+
|
82
|
+
write_file(output, content)
|
83
|
+
rescue Zlib::DataError
|
84
|
+
# perhops thi is a normal png image file
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def _dump_sections(dimensions: false)
|
91
|
+
pos = @io.header.size
|
92
|
+
optimized = false
|
93
|
+
[].tap do |sections|
|
94
|
+
while pos < @io.size
|
95
|
+
type = @io[pos + 4, 4]
|
96
|
+
length = @io[pos, 4].unpack('N')[0]
|
97
|
+
data = @io[pos + 8, length]
|
98
|
+
crc = @io[pos + 8 + length, 4].unpack('N')[0]
|
99
|
+
pos += length + 12
|
100
|
+
|
101
|
+
if type == 'CgBI'
|
102
|
+
optimized = true
|
103
|
+
next
|
104
|
+
end
|
105
|
+
|
106
|
+
if type == 'IHDR'
|
107
|
+
width = data[0, 4].unpack("N")[0]
|
108
|
+
height = data[4, 4].unpack("N")[0]
|
109
|
+
return [width, height] if dimensions
|
110
|
+
end
|
111
|
+
|
112
|
+
break if type == 'IEND'
|
113
|
+
|
114
|
+
if type == 'IDAT' && sections.size > 0 && sections.last.first == 'IDAT'
|
115
|
+
# Append to the previous IDAT
|
116
|
+
sections.last[1] += length
|
117
|
+
sections.last[2] += data
|
118
|
+
else
|
119
|
+
sections << [type, length, data, crc, width, height]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def write_file(path, content)
|
126
|
+
File.open(path, 'wb') do |file|
|
127
|
+
file.puts content
|
128
|
+
end
|
129
|
+
|
130
|
+
true
|
131
|
+
end
|
132
|
+
|
133
|
+
def _remap(sections)
|
134
|
+
newPNG = String.new(@io.header)
|
135
|
+
sections.map do |(type, length, data, crc, width, height)|
|
136
|
+
if type == 'IDAT'
|
137
|
+
bufSize = width * height * 4 + height
|
138
|
+
data = inflate(data[0, bufSize])
|
139
|
+
# duplicate the content of old data at first to avoid creating too many string objects
|
140
|
+
newdata = String.new(data)
|
141
|
+
pos = 0
|
142
|
+
|
143
|
+
(0...height).each do |y|
|
144
|
+
newdata[pos] = data[pos, 1]
|
145
|
+
pos += 1
|
146
|
+
(0...width).each do |x|
|
147
|
+
newdata[pos+0] = data[pos+2, 1]
|
148
|
+
newdata[pos+1] = data[pos+1, 1]
|
149
|
+
newdata[pos+2] = data[pos+0, 1]
|
150
|
+
newdata[pos+3] = data[pos+3, 1]
|
151
|
+
pos += 4
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
data = deflate(newdata)
|
156
|
+
length = data.length
|
157
|
+
crc = Zlib::crc32(type)
|
158
|
+
crc = Zlib::crc32(data, crc)
|
159
|
+
crc = (crc + 0x100000000) % 0x100000000
|
160
|
+
end
|
161
|
+
|
162
|
+
newPNG += [length].pack("N") + type + (data if length > 0) + [crc].pack("N")
|
163
|
+
end
|
164
|
+
|
165
|
+
newPNG
|
166
|
+
end
|
167
|
+
|
168
|
+
def inflate(data)
|
169
|
+
# make zlib not check the header
|
170
|
+
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
171
|
+
buf = zstream.inflate(data)
|
172
|
+
zstream.finish
|
173
|
+
zstream.close
|
174
|
+
buf
|
175
|
+
end
|
176
|
+
|
177
|
+
def deflate(data)
|
178
|
+
Zlib::Deflate.deflate(data)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/lib/app_info/util.rb
CHANGED
data/lib/app_info/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app-info
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4
|
4
|
+
version: 2.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- icyleaf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: CFPropertyList
|
@@ -54,16 +54,22 @@ dependencies:
|
|
54
54
|
name: ruby-macho
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - "
|
57
|
+
- - "<"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '3'
|
60
|
+
- - ">="
|
58
61
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
62
|
+
version: '1.4'
|
60
63
|
type: :runtime
|
61
64
|
prerelease: false
|
62
65
|
version_requirements: !ruby/object:Gem::Requirement
|
63
66
|
requirements:
|
64
|
-
- - "
|
67
|
+
- - "<"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3'
|
70
|
+
- - ">="
|
65
71
|
- !ruby/object:Gem::Version
|
66
|
-
version:
|
72
|
+
version: '1.4'
|
67
73
|
- !ruby/object:Gem::Dependency
|
68
74
|
name: ruby_android
|
69
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -189,6 +195,7 @@ files:
|
|
189
195
|
- lib/app_info/ipa/info_plist.rb
|
190
196
|
- lib/app_info/ipa/mobile_provision.rb
|
191
197
|
- lib/app_info/ipa/plugin.rb
|
198
|
+
- lib/app_info/png_uncrush.rb
|
192
199
|
- lib/app_info/proguard.rb
|
193
200
|
- lib/app_info/util.rb
|
194
201
|
- lib/app_info/version.rb
|