app_parser 0.1.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.
@@ -0,0 +1,30 @@
1
+ require "app_parser/version"
2
+ require "app_parser/ipa"
3
+ require "app_parser/apk"
4
+
5
+ module AppParser
6
+ class NotFoundError < StandardError; end
7
+ class NotAppError < StandardError; end
8
+
9
+ def self.parse(file_name)
10
+ fail NotFoundError, file_name unless File.exist?(file_name)
11
+
12
+ case detect_os(file_name)
13
+ when "ios"
14
+ AppParser::Ipa.new(file_name)
15
+ when "android"
16
+ AppParser::Apk.new(file_name)
17
+ else
18
+ fail NotAppError, file_name
19
+ end
20
+ end
21
+
22
+ def self.detect_os(file_name)
23
+ case File.extname(file_name.to_s).downcase
24
+ when ".ipa"
25
+ "ios"
26
+ when ".apk"
27
+ "android"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ require "ruby_apk"
2
+ require "image_size"
3
+ require "app_parser/app_icon"
4
+
5
+ class AppParser::Apk
6
+ include AppParser::AppIcon
7
+ attr_reader :icons
8
+
9
+ def initialize(file_name)
10
+ @apk = Android::Apk.new(file_name)
11
+
12
+ @icons = @apk.icon.each_with_object([]) do |(name, data), obj|
13
+ tempfile = Tempfile.new(File.basename(name))
14
+ tempfile.binmode
15
+ tempfile.write(data)
16
+ tempfile.close # closeしないと画像サイズが取れない
17
+ size = ImageSize.path(tempfile.path).size
18
+ obj << { dimensions: size, file_name: name }
19
+ tempfile.unlink
20
+ end
21
+ end
22
+
23
+ def os
24
+ "android"
25
+ end
26
+
27
+ def version
28
+ @apk.manifest.version_code.to_s
29
+ end
30
+
31
+ def version_string
32
+ @apk.manifest.version_name
33
+ end
34
+
35
+ def display_name
36
+ @apk.resource.find("@string/app_name")
37
+ end
38
+
39
+ def bundle_id
40
+ @apk.manifest.package_name
41
+ end
42
+
43
+ def provisioned_devices
44
+ []
45
+ end
46
+
47
+ def provisions_all_devices
48
+ false
49
+ end
50
+
51
+ def icon_data(file_name)
52
+ @apk.icon.find { |name, _data| name == file_name }.try(:last)
53
+ end
54
+
55
+ def iphone_icons
56
+ []
57
+ end
58
+
59
+ def ipad_icons
60
+ []
61
+ end
62
+ end
@@ -0,0 +1,18 @@
1
+ module AppParser::AppIcon
2
+ def icon(dimensions:)
3
+ dimensions = [dimensions, dimensions] unless dimensions.is_a? Array
4
+ icons.find { |icon| icon[:dimensions] == dimensions }
5
+ end
6
+
7
+ def largest_icon
8
+ sorted_icons.last
9
+ end
10
+
11
+ def smallest_icon
12
+ sorted_icons.first
13
+ end
14
+
15
+ def sorted_icons
16
+ icons.sort_by { |icon| icon[:dimensions].first * icon[:dimensions].last }
17
+ end
18
+ end
@@ -0,0 +1,101 @@
1
+ require "zip"
2
+ require "cfpropertylist"
3
+ require "active_support/core_ext/object/try"
4
+ require "pngdefry"
5
+ require "tempfile"
6
+ require "app_parser/app_icon"
7
+
8
+ class AppParser::Ipa
9
+ include AppParser::AppIcon
10
+
11
+ attr_reader :iphone_icons, :ipad_icons
12
+
13
+ def initialize(file_name)
14
+ @zip_file = Zip::File.new(file_name)
15
+ @iphone_icons = search_icons
16
+ @ipad_icons = search_icons(ipad: true)
17
+ end
18
+
19
+ def os
20
+ "ios"
21
+ end
22
+
23
+ def version
24
+ info_plist["CFBundleVersion"]
25
+ end
26
+
27
+ def version_string
28
+ info_plist["CFBundleShortVersionString"]
29
+ end
30
+
31
+ def display_name
32
+ info_plist["CFBundleDisplayName"] || info_plist["CFBundleName"]
33
+ end
34
+
35
+ def bundle_id
36
+ info_plist["CFBundleIdentifier"]
37
+ end
38
+
39
+ def provisioned_devices
40
+ mobileprovision["ProvisionedDevices"]
41
+ end
42
+
43
+ # true if In-House
44
+ def provisions_all_devices
45
+ mobileprovision["ProvisionsAllDevices"] || false
46
+ end
47
+
48
+ def icons
49
+ @iphone_icons + @ipad_icons
50
+ end
51
+
52
+ def icon_data(file_name)
53
+ Dir.mktmpdir do |tmp_dir|
54
+ src_file = "#{tmp_dir}/src"
55
+ dest_file = "#{tmp_dir}/dest"
56
+ find_entry(file_name).extract(src_file)
57
+ Pngdefry.defry(src_file, dest_file)
58
+ File.binread(dest_file)
59
+ end
60
+ end
61
+
62
+ def info_plist
63
+ @info_plist ||= CFPropertyList.native_types(
64
+ CFPropertyList::List.new(data: read_file("Info.plist"), format: CFPropertyList::List::FORMAT_AUTO).value
65
+ )
66
+ end
67
+
68
+ def mobileprovision
69
+ @mobileprovision ||= CFPropertyList.native_types(
70
+ CFPropertyList::List.new(data: read_file("embedded.mobileprovision").match(%r{<\?xml.*</plist>}m)[0], format: CFPropertyList::List::FORMAT_AUTO).value
71
+ )
72
+ end
73
+
74
+ private
75
+
76
+ def find_entries(path)
77
+ @zip_file.glob("Payload/*.app/#{path}")
78
+ end
79
+
80
+ def find_entry(path)
81
+ find_entries(path).first
82
+ end
83
+
84
+ def read_file(path)
85
+ entry = find_entry(path)
86
+ entry.get_input_stream.read unless entry.nil?
87
+ end
88
+
89
+ def search_icons(ipad: false)
90
+ Dir.mktmpdir do |tmp_dir|
91
+ info_plist.try(:[], "CFBundleIcons#{'~ipad' if ipad}").try(:[], "CFBundlePrimaryIcon").try(:[], "CFBundleIconFiles").each_with_object([]) do |icons, obj|
92
+ find_entries(icons + "*").find_all { |entry| entry.name.index("~ipad").nil? != ipad }.each do |entry|
93
+ tmp_file_name = "#{tmp_dir}/#{File.basename(entry.name)}"
94
+ entry.extract(tmp_file_name)
95
+
96
+ obj << { dimensions: Pngdefry.dimensions(tmp_file_name), file_name: File.basename(entry.name) }
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module AppParser
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: app_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - tkycule
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.4.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.4.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubyzip
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'
69
+ - !ruby/object:Gem::Dependency
70
+ name: CFPropertyList
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pngdefry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby_android
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: image_size
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Analysis tool for iOS ipa and Android apk.
140
+ email:
141
+ - tky.cule+github@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".codeclimate.yml"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".travis.yml"
151
+ - CODE_OF_CONDUCT.md
152
+ - Gemfile
153
+ - Gemfile.lock
154
+ - Guardfile
155
+ - LICENSE.txt
156
+ - README.md
157
+ - Rakefile
158
+ - app_parser.gemspec
159
+ - bin/console
160
+ - bin/setup
161
+ - lib/app_parser.rb
162
+ - lib/app_parser/apk.rb
163
+ - lib/app_parser/app_icon.rb
164
+ - lib/app_parser/ipa.rb
165
+ - lib/app_parser/version.rb
166
+ homepage: https://github.com/tkycule/app_parser
167
+ licenses:
168
+ - MIT
169
+ metadata: {}
170
+ post_install_message:
171
+ rdoc_options: []
172
+ require_paths:
173
+ - lib
174
+ required_ruby_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubyforge_project:
186
+ rubygems_version: 2.4.5.1
187
+ signing_key:
188
+ specification_version: 4
189
+ summary: Analysis tool for iOS ipa and Android apk.
190
+ test_files: []