app-info 2.0.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95e08bfdce22bf0efdc7670b4a05259d7b3963fa3800072e42db5d2e09b9f372
4
- data.tar.gz: 9a4d648e7df8135213a0a4419a219701b83bc44580d528a634a02eb3fa09b816
3
+ metadata.gz: 1c792e9fab37d4beadae7e0d8d6d955e4b51b8d64d8328cbd423ab65b56ae61a
4
+ data.tar.gz: 617c4f5bdee5412285f17dc2e97f22e9a6f325ba4efbaf50373030473c9f588a
5
5
  SHA512:
6
- metadata.gz: bff8b795e451f05af53cf5b278ec72eda4108c68f369f7cb3c2910a102cdd58d52cc868bc4fb23c1b08d1db59bab666b2c5c95f6e672bd201e066732bc1723e4
7
- data.tar.gz: dc44a77545d74c2911d533a8ebbe384a4a31a15c6386bd45d4dddb9600d55b4385040eda9d9b5ee58d1df449fcc440b4b995cfba8c24549e2f7121f83247ac19
6
+ metadata.gz: d9940cf07799f61c12e386799fbebd9273201a936b238d22d6fb9b75edf2e6e6588f19f4782856d6e28b521e89631da86becc791a6b95e5f691c786d7e27b0d4
7
+ data.tar.gz: c362a553bdf45c253c2f1fa6c6f25d68da5108bde5cb59670ab759989077771671bb8ad89bdf4750c36440a67b0ac0049acdcadcec5176e5c6104906499d397e
@@ -0,0 +1,41 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md
11
+
12
+ AllCops:
13
+ TargetRubyVersion: 2.3
14
+ Exclude:
15
+ - 'spec/**/*'
16
+ - 'Rakefile'
17
+ - 'app_info.gemspec'
18
+ - 'lib/app-info.rb'
19
+
20
+ Metrics/AbcSize:
21
+ Max: 100
22
+
23
+ Metrics/BlockLength:
24
+ Max: 35
25
+
26
+ Metrics/MethodLength:
27
+ Max: 20
28
+
29
+ Metrics/LineLength:
30
+ Max: 100
31
+
32
+ Metrics/ClassLength:
33
+ CountComments: false
34
+ Max: 300
35
+
36
+ Metrics/CyclomaticComplexity:
37
+ Max: 10
38
+
39
+
40
+ Style/Documentation:
41
+ Enabled: false
@@ -9,6 +9,13 @@ 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.1.0] (2019-10-31)
13
+
14
+ ### Added
15
+
16
+ - Added `.[]` and `missing_method` to find and match in `AppInfo::InfoPlist` and `AppInfo::MobileProvision'.
17
+ - Added `AppInfo::MobileProvision.developer_certs` . #[17](https://github.com/icyleaf/app-info/pull/17)
18
+
12
19
  ## [2.0.0] (2019-10-29)
13
20
 
14
21
  ### Added
@@ -43,7 +50,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
43
50
 
44
51
  - Updated dependency of CFPropertly list be a range between 2.3.4. (thanks @[cschroed](https://github.com/cschroed))
45
52
 
46
- [Unreleased]: https://github.com/icyleaf/app-info/compare/v1.1.0..HEAD
53
+ [Unreleased]: https://github.com/icyleaf/app-info/compare/v2.1.0..HEAD
54
+ [2.1.0]: https://github.com/icyleaf/app-info/compare/v2.0.0...v2.1.0
55
+ [2.0.0]: https://github.com/icyleaf/app-info/compare/v1.1.2...v2.0.0
56
+ [1.1.2]: https://github.com/icyleaf/app-info/compare/v1.0.5...v1.1.2
47
57
  [1.1.0]: https://github.com/icyleaf/app-info/compare/v1.0.5...v1.1.0
48
58
  [1.0.5]: https://github.com/icyleaf/app-info/compare/v0.9.0...v1.0.5
49
59
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
  # source 'https://gems.ruby-china.com'
3
5
 
@@ -2,11 +2,14 @@
2
2
 
3
3
  require 'ruby_apk'
4
4
  require 'image_size'
5
+ require 'forwardable'
5
6
  require 'app_info/util'
6
7
 
7
8
  module AppInfo
8
9
  # Parse APK file
9
10
  class APK
11
+ extend Forwardable
12
+
10
13
  attr_reader :file, :apk
11
14
 
12
15
  # APK Devices
@@ -33,10 +36,14 @@ module AppInfo
33
36
  end
34
37
  alias file_type os
35
38
 
36
- def version_name
37
- manifest.version_name
38
- end
39
+ def_delegators :@apk, :manifest, :resource, :dex
40
+
41
+ def_delegators :manifest, :version_name, :package_name,
42
+ :use_permissions, :components
43
+
39
44
  alias release_version version_name
45
+ alias identifier package_name
46
+ alias bundle_id package_name
40
47
 
41
48
  def version_code
42
49
  manifest.version_code.to_s
@@ -47,11 +54,7 @@ module AppInfo
47
54
  resource.find('@string/app_name')
48
55
  end
49
56
 
50
- def package_name
51
- manifest.package_name
52
- end
53
- alias identifier package_name
54
- alias bundle_id package_name
57
+
55
58
 
56
59
  def device_type
57
60
  if wear?
@@ -87,10 +90,6 @@ module AppInfo
87
90
  .to_i
88
91
  end
89
92
 
90
- def use_permissions
91
- manifest.use_permissions
92
- end
93
-
94
93
  def use_features
95
94
  manifest_values('/manifest/uses-feature')
96
95
  end
@@ -115,22 +114,6 @@ module AppInfo
115
114
  components.select { |c| c.type == 'service' }
116
115
  end
117
116
 
118
- def components
119
- manifest.components
120
- end
121
-
122
- def manifest
123
- @apk.manifest
124
- end
125
-
126
- def resource
127
- @apk.resource
128
- end
129
-
130
- def dex
131
- @apk.dex
132
- end
133
-
134
117
  def icons
135
118
  unless @icons
136
119
  tmp_path = File.join(Dir.mktmpdir, "AppInfo-android-#{SecureRandom.hex}")
@@ -1,27 +1,114 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Copyrights rails
4
+ # Copy from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb
5
+
3
6
  module AppInfo
4
- # Monkey Patch for Object
5
- module Tryable
6
- def try(*a, &b)
7
- try!(*a, &b) if a.empty? || respond_to?(a.first)
7
+ module Tryable #:nodoc:
8
+ def try(method_name = nil, *args, &block)
9
+ if method_name.nil? && block_given?
10
+ if block.arity.zero?
11
+ instance_eval(&b)
12
+ else
13
+ yield self
14
+ end
15
+ elsif respond_to?(method_name)
16
+ public_send(method_name, *args, &block)
17
+ end
8
18
  end
9
19
 
10
- def try!(*a, &b)
11
- if a.empty? && block_given?
12
- if b.arity.zero?
13
- instance_eval(&b)
20
+ def try!(method_name = nil, *args, &block)
21
+ if method_name.nil? && block_given?
22
+ if block.arity.zero?
23
+ instance_eval(&block)
14
24
  else
15
25
  yield self
16
26
  end
17
27
  else
18
- public_send(*a, &b)
28
+ public_send(method_name, *args, &block)
19
29
  end
20
30
  end
21
31
  end
22
32
  end
23
33
 
24
- # :nodoc:
25
34
  class Object
26
35
  include AppInfo::Tryable
36
+
37
+ ##
38
+ # :method: try
39
+ #
40
+ # :call-seq:
41
+ # try(*a, &b)
42
+ #
43
+ # Invokes the public method whose name goes as first argument just like
44
+ # +public_send+ does, except that if the receiver does not respond to it the
45
+ # call returns +nil+ rather than raising an exception.
46
+ #
47
+ # This method is defined to be able to write
48
+ #
49
+ # @person.try(:name)
50
+ #
51
+ # instead of
52
+ #
53
+ # @person.name if @person
54
+ #
55
+ # +try+ calls can be chained:
56
+ #
57
+ # @person.try(:spouse).try(:name)
58
+ #
59
+ # instead of
60
+ #
61
+ # @person.spouse.name if @person && @person.spouse
62
+ #
63
+ # +try+ will also return +nil+ if the receiver does not respond to the method:
64
+ #
65
+ # @person.try(:non_existing_method) # => nil
66
+ #
67
+ # instead of
68
+ #
69
+ # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
70
+ #
71
+ # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
72
+ # to the method:
73
+ #
74
+ # nil.try(:to_i) # => nil, rather than 0
75
+ #
76
+ # Arguments and blocks are forwarded to the method if invoked:
77
+ #
78
+ # @posts.try(:each_slice, 2) do |a, b|
79
+ # ...
80
+ # end
81
+ #
82
+ # The number of arguments in the signature must match. If the object responds
83
+ # to the method the call is attempted and +ArgumentError+ is still raised
84
+ # in case of argument mismatch.
85
+ #
86
+ # If +try+ is called without arguments it yields the receiver to a given
87
+ # block unless it is +nil+:
88
+ #
89
+ # @person.try do |p|
90
+ # ...
91
+ # end
92
+ #
93
+ # You can also call try with a block without accepting an argument, and the block
94
+ # will be instance_eval'ed instead:
95
+ #
96
+ # @person.try { upcase.truncate(50) }
97
+ #
98
+ # Please also note that +try+ is defined on +Object+. Therefore, it won't work
99
+ # with instances of classes that do not have +Object+ among their ancestors,
100
+ # like direct subclasses of +BasicObject+.
101
+
102
+ ##
103
+ # :method: try!
104
+ #
105
+ # :call-seq:
106
+ # try!(*a, &b)
107
+ #
108
+ # Same as #try, but raises a +NoMethodError+ exception if the receiver is
109
+ # not +nil+ and does not implement the tried method.
110
+ #
111
+ # "a".try!(:upcase) # => "A"
112
+ # nil.try!(:upcase) # => nil
113
+ # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
27
114
  end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: true`
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'macho'
4
4
  require 'app_info/util'
@@ -3,12 +3,15 @@
3
3
  require 'macho'
4
4
  require 'pngdefry'
5
5
  require 'fileutils'
6
+ require 'forwardable'
6
7
  require 'cfpropertylist'
7
8
  require 'app_info/util'
8
9
 
9
10
  module AppInfo
10
11
  # IPA parser
11
12
  class IPA
13
+ extend Forwardable
14
+
12
15
  attr_reader :file
13
16
 
14
17
  # iOS Export types
@@ -33,76 +36,12 @@ module AppInfo
33
36
  end
34
37
  alias file_type os
35
38
 
36
- def iphone?
37
- info.iphone?
38
- end
39
-
40
- def ipad?
41
- info.ipad?
42
- end
43
-
44
- def universal?
45
- info.universal?
46
- end
47
-
48
- def build_version
49
- info.build_version
50
- end
51
-
52
- def release_version
53
- info.release_version
54
- end
55
-
56
- def identifier
57
- info.identifier
58
- end
59
-
60
- def name
61
- display_name || bundle_name
62
- end
63
-
64
- def display_name
65
- info.display_name
66
- end
67
-
68
- def bundle_name
69
- info.bundle_name
70
- end
39
+ def_delegators :info, :iphone?, :ipad?, :universal?, :build_version, :name,
40
+ :release_version, :identifier, :bundle_id, :display_name,
41
+ :bundle_name, :icons, :min_sdk_version, :device_type
71
42
 
72
- def icons
73
- info.icons
74
- end
75
-
76
- #
77
- # Return the minimum OS version for the given application
78
- #
79
- def min_sdk_version
80
- info.min_sdk_version
81
- end
82
-
83
- def device_type
84
- info.device_type
85
- end
86
-
87
- def devices
88
- mobileprovision.devices
89
- end
90
-
91
- def team_name
92
- mobileprovision.team_name
93
- end
94
-
95
- def team_identifier
96
- mobileprovision.team_identifier
97
- end
98
-
99
- def profile_name
100
- mobileprovision.profile_name
101
- end
102
-
103
- def expired_date
104
- mobileprovision.expired_date
105
- end
43
+ def_delegators :mobileprovision, :devices, :team_name, :team_identifier,
44
+ :profile_name, :expired_date
106
45
 
107
46
  def distribution_name
108
47
  "#{profile_name} - #{team_name}" if profile_name && team_name
@@ -211,8 +150,6 @@ module AppInfo
211
150
  @info = nil
212
151
  end
213
152
 
214
- alias bundle_id identifier
215
-
216
153
  private
217
154
 
218
155
  def contents
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cfpropertylist'
4
+ require 'app_info/util'
4
5
 
5
6
  module AppInfo
6
7
  # iOS Info.plist parser
@@ -106,6 +107,18 @@ module AppInfo
106
107
  info.try(:[], key.to_s)
107
108
  end
108
109
 
110
+ def method_missing(method_name, *args, &block)
111
+ info.try(:[], Util.format_key(method_name)) ||
112
+ info.send(method_name) ||
113
+ super
114
+ end
115
+
116
+ def respond_to_missing?(method_name, *args)
117
+ info.key?(Util.format_key(method_name)) ||
118
+ info.respond_to?(method_name) ||
119
+ super
120
+ end
121
+
109
122
  private
110
123
 
111
124
  def info
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'openssl'
3
4
  require 'cfpropertylist'
5
+ require 'app_info/util'
4
6
 
5
7
  module AppInfo
6
8
  # .mobileprovision file parser
@@ -45,17 +47,17 @@ module AppInfo
45
47
  mobileprovision.try(:[], 'Entitlements')
46
48
  end
47
49
 
48
- def method_missing(method_name, *args, &block)
49
- key = if method_name.to_s.include?('_')
50
- method_name.to_s
51
- .split('_')
52
- .map(&:capitalize)
53
- .join('')
54
- else
55
- method_name.to_s
56
- end
50
+ def developer_certs
51
+ certs = mobileprovision.try(:[], 'DeveloperCertificates')
52
+ return if certs.empty?
53
+
54
+ certs.each_with_object([]) do |cert, obj|
55
+ obj << DeveloperCertificate.new(cert)
56
+ end
57
+ end
57
58
 
58
- mobileprovision.try(:[], key)
59
+ def [](key)
60
+ mobileprovision.try(:[], key.to_s)
59
61
  end
60
62
 
61
63
  def empty?
@@ -73,6 +75,18 @@ module AppInfo
73
75
  @mobileprovision = nil
74
76
  end
75
77
 
78
+ def method_missing(method_name, *args, &block)
79
+ mobileprovision.try(:[], Util.format_key(method_name)) ||
80
+ mobileprovision.send(method_name) ||
81
+ super
82
+ end
83
+
84
+ def respond_to_missing?(method_name, *args)
85
+ mobileprovision.key?(Util.format_key(method_name)) ||
86
+ mobileprovision.respond_to?(method_name) ||
87
+ super
88
+ end
89
+
76
90
  private
77
91
 
78
92
  def bplist?(raw)
@@ -85,5 +99,26 @@ module AppInfo
85
99
  end_point = raw.index(end_tag) + end_tag.size - 1
86
100
  raw[start_point..end_point]
87
101
  end
102
+
103
+ # Developer Certificate
104
+ class DeveloperCertificate
105
+ attr_reader :raw
106
+
107
+ def initialize(data)
108
+ @raw = OpenSSL::X509::Certificate.new(data)
109
+ end
110
+
111
+ def name
112
+ @raw.subject.to_a.find { |name, _, _| name == 'CN' }[1]
113
+ end
114
+
115
+ def created_date
116
+ @raw.not_after
117
+ end
118
+
119
+ def expired_date
120
+ @raw.not_before
121
+ end
122
+ end
88
123
  end
89
124
  end
@@ -9,6 +9,13 @@ module AppInfo
9
9
  module Util
10
10
  FILE_SIZE_UNITS = %w[B KB MB GB TB].freeze
11
11
 
12
+ def self.format_key(key)
13
+ key = key.to_s
14
+ return key unless key.include?('_')
15
+
16
+ key.split('_').map(&:capitalize).join('')
17
+ end
18
+
12
19
  def self.file_size(file, humanable)
13
20
  file_size = File.size(file)
14
21
  humanable ? size_to_humanable(file_size) : file_size
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppInfo
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
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.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - icyleaf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-29 00:00:00.000000000 Z
11
+ date: 2019-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: CFPropertyList
@@ -178,6 +178,7 @@ extra_rdoc_files: []
178
178
  files:
179
179
  - ".gitignore"
180
180
  - ".rspec"
181
+ - ".rubocop.yml"
181
182
  - ".travis.yml"
182
183
  - CHANGELOG.md
183
184
  - CODE_OF_CONDUCT.md