read_ipa 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|