read_ipa 0.2.1 → 0.3.0
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/lib/read_ipa/info_plist.rb +76 -0
- data/lib/read_ipa/ipa_file.rb +115 -0
- data/lib/read_ipa.rb +2 -136
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91cd397b8c156a0a78eae91cf99b2f75e08e0ba8
|
4
|
+
data.tar.gz: 5ceb6d6776743369bf0fafbd5b42810b82f6725f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ab8707c5c186db752bb13413b4e370fb4df0b1a99d9521e1f3fcc06ac34af3602cc96d862330c06b5c6fa41f29be956bb2af9540e0692ca7e801c2cf941276e
|
7
|
+
data.tar.gz: aa2094b5a776bdad4684f1744157e5c928099452c96190a92b7909334702dc91cf8bd70399b0d1c051464cef2fc006b6640249d7fe67b1703df7deb2ebccf413
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'CFPropertyList'
|
2
|
+
|
3
|
+
module ReadIpa
|
4
|
+
class InfoPlist
|
5
|
+
def initialize(plist_str)
|
6
|
+
@plist = CFPropertyList::List.new(data: plist_str, format: CFPropertyList::List::FORMAT_AUTO).value.to_rb
|
7
|
+
end
|
8
|
+
|
9
|
+
def version
|
10
|
+
@plist["CFBundleVersion"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def short_version
|
14
|
+
@plist["CFBundleShortVersionString"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
@plist["CFBundleDisplayName"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def target_os_version
|
22
|
+
@plist["DTPlatformVersion"].match(/[\d\.]*/)[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def minimum_os_version
|
26
|
+
@plist["MinimumOSVersion"].match(/[\d\.]*/)[0]
|
27
|
+
end
|
28
|
+
|
29
|
+
def url_schemes
|
30
|
+
if @plist["CFBundleURLTypes"] && @plist["CFBundleURLTypes"][0] && @plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
|
31
|
+
@plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
|
32
|
+
else
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def icon_files
|
38
|
+
icon_files = [@plist["CFBundleIconFile"]].compact
|
39
|
+
icon_files += @plist["CFBundleIconFiles"] || []
|
40
|
+
if @plist["CFBundleIcons"]
|
41
|
+
dict = @plist["CFBundleIcons"]
|
42
|
+
primary_icons = dict["CFBundlePrimaryIcon"]
|
43
|
+
return nil unless primary_icons
|
44
|
+
icons = primary_icons.to_rb["CFBundleIconFiles"]
|
45
|
+
return nil unless icons
|
46
|
+
icon_files += icons
|
47
|
+
end
|
48
|
+
icon_files
|
49
|
+
end
|
50
|
+
|
51
|
+
def executable_file_name
|
52
|
+
@plist["CFBundleExecutable"]
|
53
|
+
end
|
54
|
+
|
55
|
+
def bundle_identifier
|
56
|
+
@plist["CFBundleIdentifier"]
|
57
|
+
end
|
58
|
+
|
59
|
+
def icon_prerendered
|
60
|
+
@plist["UIPrerenderedIcon"] == true
|
61
|
+
end
|
62
|
+
|
63
|
+
def for_ipad?
|
64
|
+
return true if @plist["UIDeviceFamily"] && (@plist["UIDeviceFamily"] == 2 || @plist["UIDeviceFamily"].include?(2))
|
65
|
+
return true if @plist["UIDeviceFamily"] && (@plist["UIDeviceFamily"] == "2" || @plist["UIDeviceFamily"].include?("2"))
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
|
69
|
+
def for_iphone?
|
70
|
+
return true if @plist["UIDeviceFamily"]
|
71
|
+
return true if @plist["UIDeviceFamily"] == 1 || @plist["UIDeviceFamily"].include?(1)
|
72
|
+
return true if @plist["UIDeviceFamily"] == "1" || @plist["UIDeviceFamily"].include?("1")
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'zip/zip'
|
2
|
+
require 'read_ipa/plist_binary'
|
3
|
+
require 'apple_png'
|
4
|
+
require 'chunky_png'
|
5
|
+
require 'CFPropertyList'
|
6
|
+
|
7
|
+
module ReadIpa
|
8
|
+
class IpaFile
|
9
|
+
attr_accessor :plist, :file_path
|
10
|
+
def initialize(file_path)
|
11
|
+
self.file_path = file_path
|
12
|
+
@app_folder = Zip::ZipFile.foreach(file_path).find { |e| /.*\.app\/Info\.plist$/ =~ e.to_s }.to_s.gsub(/Info\.plist$/, '')
|
13
|
+
@zipfile = Zip::ZipFile.open(file_path)
|
14
|
+
|
15
|
+
plist_str = @zipfile.read(@app_folder + "Info.plist")
|
16
|
+
@info_plist = InfoPlist.new(plist_str)
|
17
|
+
|
18
|
+
cf_plist = CFPropertyList::List.new(data: plist_str, format: CFPropertyList::List::FORMAT_AUTO)
|
19
|
+
self.plist = cf_plist.value.to_rb
|
20
|
+
end
|
21
|
+
|
22
|
+
def version
|
23
|
+
@info_plist.version
|
24
|
+
end
|
25
|
+
|
26
|
+
def short_version
|
27
|
+
@info_plist.short_version
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
@info_plist.name
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_os_version
|
35
|
+
@info_plist.target_os_version
|
36
|
+
end
|
37
|
+
|
38
|
+
def minimum_os_version
|
39
|
+
@info_plist.minimum_os_version
|
40
|
+
end
|
41
|
+
|
42
|
+
def url_schemes
|
43
|
+
@info_plist.url_schemes
|
44
|
+
end
|
45
|
+
|
46
|
+
def read_png(data)
|
47
|
+
begin
|
48
|
+
return ApplePng.new(data)
|
49
|
+
rescue NotValidApplePngError
|
50
|
+
return ChunkyPng::Image.from_datastream(ChunkyPNG::Datastream.from_blob(data))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_highest_res_icon(icons_file_names)
|
55
|
+
icon_names = icons_file_names
|
56
|
+
.map{ |icon_path| find_existing_path(icon_path) }
|
57
|
+
.compact
|
58
|
+
.uniq(&:name)
|
59
|
+
highest_res_icon = icon_names
|
60
|
+
.map{|entry| entry.get_input_stream.read}
|
61
|
+
.max_by{|data| read_png(data).width }
|
62
|
+
|
63
|
+
return nil if highest_res_icon.nil?
|
64
|
+
begin
|
65
|
+
return ApplePng.new(highest_res_icon).data
|
66
|
+
rescue NotValidApplePngError
|
67
|
+
highest_res_icon
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def icon_file
|
72
|
+
get_highest_res_icon(@info_plist.icon_files)
|
73
|
+
end
|
74
|
+
|
75
|
+
def executable_file_name
|
76
|
+
@info_plist.executable_file_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def executable_file
|
80
|
+
read_file(executable_file_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def mobile_provision_file
|
84
|
+
read_file("embedded.mobileprovision")
|
85
|
+
end
|
86
|
+
|
87
|
+
def bundle_identifier
|
88
|
+
@info_plist.bundle_identifier
|
89
|
+
end
|
90
|
+
|
91
|
+
def icon_prerendered
|
92
|
+
@info_plist.icon_prerendered
|
93
|
+
end
|
94
|
+
|
95
|
+
def for_ipad?
|
96
|
+
@info_plist.for_ipad?
|
97
|
+
end
|
98
|
+
|
99
|
+
def for_iphone?
|
100
|
+
@info_plist.for_iphone?
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_existing_path(icon_path)
|
104
|
+
without_extension = icon_path.gsub(/\.png$/i, '')
|
105
|
+
regex = /#{Regexp.quote(@app_folder)}#{Regexp.quote(without_extension)}[(\.png)@~]/
|
106
|
+
@zipfile.entries.find{|e| e.name =~ regex}
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def read_file(entry)
|
112
|
+
@zipfile.read(@app_folder + entry)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/lib/read_ipa.rb
CHANGED
@@ -1,136 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
rescue LoadError
|
4
|
-
require 'rubygems'
|
5
|
-
require 'zip/zip'
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'read_ipa/plist_binary'
|
9
|
-
require 'apple_png'
|
10
|
-
require 'chunky_png'
|
11
|
-
|
12
|
-
module ReadIpa
|
13
|
-
class IpaFile
|
14
|
-
attr_accessor :plist, :file_path
|
15
|
-
def initialize(file_path)
|
16
|
-
self.file_path = file_path
|
17
|
-
@app_folder = Zip::ZipFile.foreach(file_path).find { |e| /.*\.app\/Info\.plist$/ =~ e.to_s }.to_s.gsub(/Info\.plist$/, '')
|
18
|
-
@zipfile = Zip::ZipFile.open(file_path)
|
19
|
-
|
20
|
-
cf_plist = CFPropertyList::List.new(data: @zipfile.read(@app_folder + "Info.plist"), format: CFPropertyList::List::FORMAT_AUTO)
|
21
|
-
self.plist = cf_plist.value.to_rb
|
22
|
-
end
|
23
|
-
|
24
|
-
def version
|
25
|
-
plist["CFBundleVersion"]
|
26
|
-
end
|
27
|
-
|
28
|
-
def short_version
|
29
|
-
plist["CFBundleShortVersionString"]
|
30
|
-
end
|
31
|
-
|
32
|
-
def name
|
33
|
-
plist["CFBundleDisplayName"]
|
34
|
-
end
|
35
|
-
|
36
|
-
def target_os_version
|
37
|
-
plist["DTPlatformVersion"].match(/[\d\.]*/)[0]
|
38
|
-
end
|
39
|
-
|
40
|
-
def minimum_os_version
|
41
|
-
plist["MinimumOSVersion"].match(/[\d\.]*/)[0]
|
42
|
-
end
|
43
|
-
|
44
|
-
def url_schemes
|
45
|
-
if plist["CFBundleURLTypes"] && plist["CFBundleURLTypes"][0] && plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
|
46
|
-
plist["CFBundleURLTypes"][0]["CFBundleURLSchemes"]
|
47
|
-
else
|
48
|
-
[]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def read_png(data)
|
53
|
-
begin
|
54
|
-
return ApplePng.new(data)
|
55
|
-
rescue NotValidApplePngError
|
56
|
-
return ChunkyPng::Image.from_datastream(ChunkyPNG::Datastream.from_blob(data))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def get_highest_res_icon(icons_file_names)
|
61
|
-
icon_names = icons_file_names
|
62
|
-
.map{ |icon_path| find_existing_path(icon_path) }
|
63
|
-
.compact
|
64
|
-
.uniq(&:name)
|
65
|
-
highest_res_icon = icon_names
|
66
|
-
.map{|entry| entry.get_input_stream.read}
|
67
|
-
.max_by{|data| read_png(data).width }
|
68
|
-
|
69
|
-
return nil if highest_res_icon.nil?
|
70
|
-
begin
|
71
|
-
return ApplePng.new(highest_res_icon).data
|
72
|
-
rescue NotValidApplePngError
|
73
|
-
highest_res_icon
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def icon_file
|
78
|
-
icon_files = [plist["CFBundleIconFile"]].compact
|
79
|
-
icon_files += plist["CFBundleIconFiles"] || []
|
80
|
-
if plist["CFBundleIcons"]
|
81
|
-
dict = plist["CFBundleIcons"]
|
82
|
-
primary_icons = dict["CFBundlePrimaryIcon"]
|
83
|
-
return nil unless primary_icons
|
84
|
-
icons = primary_icons.to_rb["CFBundleIconFiles"]
|
85
|
-
return nil unless icons
|
86
|
-
icon_files += icons
|
87
|
-
end
|
88
|
-
get_highest_res_icon(icon_files)
|
89
|
-
end
|
90
|
-
|
91
|
-
def executable_file_name
|
92
|
-
plist["CFBundleExecutable"]
|
93
|
-
end
|
94
|
-
|
95
|
-
def executable_file
|
96
|
-
read_file(executable_file_name)
|
97
|
-
end
|
98
|
-
|
99
|
-
def mobile_provision_file
|
100
|
-
read_file("embedded.mobileprovision")
|
101
|
-
end
|
102
|
-
|
103
|
-
def bundle_identifier
|
104
|
-
plist["CFBundleIdentifier"]
|
105
|
-
end
|
106
|
-
|
107
|
-
def icon_prerendered
|
108
|
-
plist["UIPrerenderedIcon"] == true
|
109
|
-
end
|
110
|
-
|
111
|
-
def for_ipad?
|
112
|
-
return true if plist["UIDeviceFamily"] && (plist["UIDeviceFamily"] == 2 || plist["UIDeviceFamily"].include?(2))
|
113
|
-
return true if plist["UIDeviceFamily"] && (plist["UIDeviceFamily"] == "2" || plist["UIDeviceFamily"].include?("2"))
|
114
|
-
return false
|
115
|
-
end
|
116
|
-
|
117
|
-
def for_iphone?
|
118
|
-
return true if !plist["UIDeviceFamily"]
|
119
|
-
return true if plist["UIDeviceFamily"] == 1 || plist["UIDeviceFamily"].include?(1)
|
120
|
-
return true if plist["UIDeviceFamily"] == "1" || plist["UIDeviceFamily"].include?("1")
|
121
|
-
return false
|
122
|
-
end
|
123
|
-
|
124
|
-
def find_existing_path(icon_path)
|
125
|
-
without_extension = icon_path.gsub(/\.png$/i, '')
|
126
|
-
regex = /#{Regexp.quote(@app_folder)}#{Regexp.quote(without_extension)}[(\.png)@~]/
|
127
|
-
@zipfile.entries.find{|e| e.name =~ regex}
|
128
|
-
end
|
129
|
-
|
130
|
-
private
|
131
|
-
|
132
|
-
def read_file(entry)
|
133
|
-
@zipfile.read(@app_folder + entry)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
1
|
+
require 'read_ipa/ipa_file'
|
2
|
+
require 'read_ipa/info_plist'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: read_ipa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marvin Killing
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -118,6 +118,8 @@ files:
|
|
118
118
|
- README.md
|
119
119
|
- Rakefile
|
120
120
|
- lib/read_ipa.rb
|
121
|
+
- lib/read_ipa/info_plist.rb
|
122
|
+
- lib/read_ipa/ipa_file.rb
|
121
123
|
- lib/read_ipa/plist_binary.rb
|
122
124
|
- test/test_read_ipa.rb
|
123
125
|
homepage: https://github.com/playtestcloud/read_ipa
|