pprof 0.3.7 → 0.4.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 +5 -5
- data/bin/pprof +52 -41
- data/lib/pprof/entitlements.rb +6 -3
- data/lib/pprof/output_formatter.rb +61 -47
- data/lib/pprof/provisioning_profile.rb +21 -18
- data/lib/pprof/version.rb +3 -1
- data/lib/pprof.rb +2 -0
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b8843e85a32a30167805e1aa3cef04d1626b05f7f1d1c130b1558d9e3bfaa809
|
|
4
|
+
data.tar.gz: 4ef87037d3779a327d32bb87fb73fc3501d94d4406bb9529fc1049775a23f93e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 19fe84e13c4007da01357055deb1350eb0108fe31dd45466827208d7d59f9a858dedc8450e1f0cc2f7863db567263638371ce97536d66b5db054c021c5caa612
|
|
7
|
+
data.tar.gz: 065fbe7cd8cc1af06ca4e739ca1e901694cf711039c345cd2bd9086090b80af503b616ce2babeedf0120bb692c8d425472e8ad8b2d645efb4569f42771cd63bc
|
data/bin/pprof
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
require 'pprof'
|
|
4
5
|
require 'optparse'
|
|
@@ -7,7 +8,7 @@ require 'optparse'
|
|
|
7
8
|
# Or a standard match if the string is bare.
|
|
8
9
|
#
|
|
9
10
|
def matcher(string)
|
|
10
|
-
m = string.match(%r
|
|
11
|
+
m = string.match(%r{^/(.*)/(.*)$})
|
|
11
12
|
if m.nil?
|
|
12
13
|
Regexp.new(Regexp.escape(string))
|
|
13
14
|
else
|
|
@@ -19,136 +20,146 @@ end
|
|
|
19
20
|
|
|
20
21
|
filters = {}
|
|
21
22
|
options = {}
|
|
22
|
-
list_options = { :
|
|
23
|
+
list_options = { mode: :table }
|
|
23
24
|
|
|
25
|
+
# rubocop:disable Metrics/BlockLength
|
|
24
26
|
parser = OptionParser.new do |opts|
|
|
25
|
-
opts.banner = <<-BANNER.gsub(/^ *\|/,'')
|
|
27
|
+
opts.banner = <<-BANNER.gsub(/^ *\|/, '')
|
|
26
28
|
|Usage:
|
|
27
29
|
| pprof [print_options] (PATH|UUID)
|
|
28
30
|
| pprof [list_options] [filters]
|
|
29
31
|
|
|
|
30
|
-
|
|
|
32
|
+
|Notes:
|
|
33
|
+
| - All filters expecting a string are interpreted as regular expressions if surrounded by slashes
|
|
34
|
+
| e.g. `pprof --name /.*InHouse.*Distribution.*/
|
|
35
|
+
| - When using slashes to use a RegEx, you can also specify option flags.
|
|
36
|
+
| Especially, use `/InHouse/i` for case-insensitive search
|
|
37
|
+
| - Without slashes, the filter matches if the corresponding field _contains_ the searched string.
|
|
38
|
+
| e.g. `pprof --name InHouse` matches any profile whose name _contains_ "InHouse"
|
|
39
|
+
|
|
|
40
|
+
|Tips:
|
|
41
|
+
| - If you want to search for _exact_ match, you can use and anchored RegEx like `/^InHouse$/i`
|
|
42
|
+
| - To remove all expired certificates, you can use `#{opts.program_name} -e0 | xargs -0 rm`
|
|
31
43
|
BANNER
|
|
32
44
|
|
|
33
|
-
opts.separator
|
|
34
|
-
opts.separator
|
|
45
|
+
opts.separator ''
|
|
46
|
+
opts.separator 'Print options (when file given)'
|
|
35
47
|
|
|
36
|
-
opts.on(
|
|
48
|
+
opts.on('-i', '--info', 'Print general info (default)') do
|
|
37
49
|
options[:info] = true
|
|
38
50
|
end
|
|
39
|
-
opts.on(
|
|
51
|
+
opts.on('-c', '--certs', 'Print certificates') do
|
|
40
52
|
options[:certs] = true
|
|
41
53
|
end
|
|
42
|
-
opts.on(
|
|
54
|
+
opts.on('-d', '--devices', 'Print provisioned devices') do
|
|
43
55
|
options[:devices] = true
|
|
44
56
|
end
|
|
45
57
|
|
|
46
|
-
opts.separator
|
|
47
|
-
opts.separator
|
|
58
|
+
opts.separator ''
|
|
59
|
+
opts.separator 'List options (when no file given)'
|
|
48
60
|
|
|
49
|
-
opts.on(
|
|
61
|
+
opts.on('-l', '--list', 'Print only the UUIDs, one per line (instead of an ASCII table)') do
|
|
50
62
|
list_options[:mode] = :list
|
|
51
63
|
end
|
|
52
|
-
opts.on(
|
|
64
|
+
opts.on('-p', '--path', 'Print only the paths, one per line (instead of an ASCII table)') do
|
|
53
65
|
list_options[:mode] = :path
|
|
54
66
|
end
|
|
55
|
-
opts.on(
|
|
67
|
+
opts.on('-0', '--print0', 'Separate each found entry by \\0, to be used by `xargs -0`') do
|
|
56
68
|
list_options[:zero] = true
|
|
57
69
|
end
|
|
58
70
|
|
|
59
|
-
opts.separator
|
|
60
|
-
opts.separator
|
|
71
|
+
opts.separator ''
|
|
72
|
+
opts.separator 'Filters (when no file given)'
|
|
61
73
|
|
|
62
|
-
opts.on(
|
|
74
|
+
opts.on('--name NAME', 'Filter by name') do |name|
|
|
63
75
|
filters[:name] = matcher(name)
|
|
64
76
|
end
|
|
65
77
|
|
|
66
|
-
opts.on(
|
|
78
|
+
opts.on('--appid-name APPID', 'Filter by App ID Name') do |appid_name|
|
|
67
79
|
filters[:appid_name] = matcher(appid_name)
|
|
68
80
|
end
|
|
69
81
|
|
|
70
|
-
opts.on(
|
|
82
|
+
opts.on('--appid APPID', 'Filter by App ID') do |appid|
|
|
71
83
|
filters[:appid] = matcher(appid)
|
|
72
84
|
end
|
|
73
85
|
|
|
74
|
-
opts.on(
|
|
86
|
+
opts.on('--uuid UUID', 'Filter by UUID') do |uuid|
|
|
75
87
|
filters[:uuid] = matcher(uuid)
|
|
76
88
|
end
|
|
77
89
|
|
|
78
|
-
opts.on(
|
|
90
|
+
opts.on('--team TEAM', 'Filter by team name or ID') do |team|
|
|
79
91
|
filters[:team] = matcher(team)
|
|
80
92
|
end
|
|
81
93
|
|
|
82
|
-
opts.on(
|
|
94
|
+
opts.on('--[no-]exp', 'Only profiles (not) expired') do |flag|
|
|
83
95
|
filters[:exp] = flag
|
|
84
96
|
end
|
|
85
97
|
|
|
86
|
-
opts.on(
|
|
98
|
+
opts.on('--[no-]has-devices', 'Filter by profiles having (no) provisioned devices') do |d|
|
|
87
99
|
filters[:has_devices] = d
|
|
88
100
|
end
|
|
89
101
|
|
|
90
|
-
opts.on(
|
|
102
|
+
opts.on('--[no-]all-devices', 'Filter by profiles (not) provisioning all devices') do |d|
|
|
91
103
|
filters[:all_devices] = d
|
|
92
104
|
end
|
|
93
105
|
|
|
94
|
-
opts.on(
|
|
106
|
+
opts.on('--aps [ENV]', 'Only profiles having Push entitlements (or a specific aps env)') do |env|
|
|
95
107
|
filters[:aps_env] = env.nil? ? true : matcher(env)
|
|
96
108
|
end
|
|
97
109
|
|
|
110
|
+
opts.separator ''
|
|
111
|
+
opts.separator 'Misc'
|
|
98
112
|
|
|
99
|
-
opts.
|
|
100
|
-
opts.separator "Misc"
|
|
101
|
-
|
|
102
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
|
113
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
|
103
114
|
puts opts
|
|
104
115
|
exit
|
|
105
116
|
end
|
|
106
117
|
|
|
107
|
-
opts.on_tail(
|
|
118
|
+
opts.on_tail('-v', '--version', 'Show version') do
|
|
108
119
|
puts PProf::VERSION
|
|
109
120
|
exit
|
|
110
121
|
end
|
|
111
122
|
end
|
|
123
|
+
# rubocop:enable Metrics/BlockLength
|
|
112
124
|
|
|
113
125
|
# Parse the options, catching parse errors nicely
|
|
114
126
|
begin
|
|
115
127
|
parser.parse!
|
|
116
|
-
rescue OptionParser::InvalidOption =>
|
|
117
|
-
puts
|
|
118
|
-
puts parser.help
|
|
128
|
+
rescue OptionParser::InvalidOption => e
|
|
129
|
+
puts e
|
|
130
|
+
puts parser.help
|
|
119
131
|
exit 1
|
|
120
132
|
end
|
|
121
133
|
|
|
122
134
|
# Don't mix filters and options together, that doesn't make sense
|
|
123
135
|
|
|
124
136
|
unless filters.empty? || ARGV.empty?
|
|
125
|
-
puts
|
|
137
|
+
puts 'You should use either filter flags to filter the whole list, or an specific path, not both.'
|
|
126
138
|
puts parser # Usage
|
|
127
139
|
exit
|
|
128
140
|
end
|
|
129
141
|
|
|
130
142
|
unless options.empty? || !ARGV.empty?
|
|
131
|
-
puts
|
|
143
|
+
puts 'You should use option flags only when providing an specific path.'
|
|
132
144
|
puts parser # Usage
|
|
133
145
|
exit
|
|
134
146
|
end
|
|
135
147
|
|
|
136
148
|
# Call the appropriate action
|
|
137
149
|
|
|
150
|
+
o = PProf::OutputFormatter.new
|
|
138
151
|
if ARGV.empty?
|
|
139
152
|
# Print list of matching profiles
|
|
140
|
-
o = PProf::OutputFormatter.new
|
|
141
153
|
list_options[:mode] = :path if list_options[:zero] && list_options[:mode] == :table
|
|
142
154
|
o.print_filtered_list(PProf::ProvisioningProfile::DEFAULT_DIR, filters, list_options)
|
|
143
155
|
else
|
|
144
|
-
# Print info about given profile path/UUID
|
|
145
|
-
o = PProf::OutputFormatter.new
|
|
146
156
|
begin
|
|
157
|
+
# Print info about given profile path/UUID
|
|
147
158
|
p = PProf::ProvisioningProfile.new(ARGV[0])
|
|
148
|
-
|
|
149
|
-
options = { :
|
|
159
|
+
|
|
160
|
+
options = { info: true } if options.empty?
|
|
150
161
|
o.print_info(p, options)
|
|
151
|
-
rescue
|
|
162
|
+
rescue StandardError => e
|
|
152
163
|
o.print_error(e, ARGV[0])
|
|
153
164
|
end
|
|
154
165
|
end
|
data/lib/pprof/entitlements.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Module for the pprof tool to manipulate Provisioning Profiles
|
|
2
4
|
module PProf
|
|
3
5
|
# Represents the list of entitlements in a Provisioning Profile
|
|
@@ -23,7 +25,7 @@ module PProf
|
|
|
23
25
|
# True if we can attach a debugger to the executable, false if not.
|
|
24
26
|
#
|
|
25
27
|
# @return [Bool]
|
|
26
|
-
def get_task_allow
|
|
28
|
+
def get_task_allow # rubocop:disable Naming/AccessorMethodName
|
|
27
29
|
@dict['get-task-allow']
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -98,9 +100,10 @@ module PProf
|
|
|
98
100
|
# @param [#to_s] key
|
|
99
101
|
# The key to check
|
|
100
102
|
#
|
|
101
|
-
def
|
|
102
|
-
@dict.
|
|
103
|
+
def key?(key)
|
|
104
|
+
@dict.key?(key.to_s)
|
|
103
105
|
end
|
|
106
|
+
alias has_key? key?
|
|
104
107
|
|
|
105
108
|
# The list of all entitlement keys, as String
|
|
106
109
|
#
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Module for the pprof tool to manipulate Provisioning Profiles
|
|
2
4
|
module PProf
|
|
3
5
|
# A helper tool to pretty-print Provisioning Profile informations
|
|
@@ -27,14 +29,16 @@ module PProf
|
|
|
27
29
|
# @param [String...] cols
|
|
28
30
|
# The content of each column of the row to add
|
|
29
31
|
def row(*cols)
|
|
30
|
-
|
|
32
|
+
justified_cols = cols.zip(@widths).map do |c, w|
|
|
31
33
|
(c || '<nil>').to_s.ljust(w)[0...w]
|
|
32
|
-
end
|
|
34
|
+
end
|
|
35
|
+
"| #{justified_cols.join(' | ')} |"
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
# Add a separator line to the ASCII table
|
|
36
39
|
def separator
|
|
37
|
-
|
|
40
|
+
columns_dashes = @widths.map { |w| '-' * (w + 2) }
|
|
41
|
+
"+#{columns_dashes.join('+')}+"
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
@@ -57,25 +61,36 @@ module PProf
|
|
|
57
61
|
# Decide what to print. Valid keys are :info, :certs and :devices
|
|
58
62
|
#
|
|
59
63
|
def print_info(profile, options = nil)
|
|
60
|
-
options ||= { :
|
|
64
|
+
options ||= { info: true }
|
|
61
65
|
if options[:info]
|
|
62
|
-
keys = [
|
|
66
|
+
keys = %i[name uuid app_id_name app_id_prefix creation_date expiration_date ttl team_ids
|
|
67
|
+
team_name]
|
|
63
68
|
keys.each do |key|
|
|
64
|
-
@output.puts "- #{key
|
|
69
|
+
@output.puts "- #{key}: #{profile.send(key.to_sym)}"
|
|
65
70
|
end
|
|
66
|
-
@output.puts
|
|
67
|
-
@output.puts
|
|
71
|
+
@output.puts '- Entitlements:'
|
|
72
|
+
@output.puts(profile.entitlements.to_s.split("\n").map { |line| " #{line}" })
|
|
68
73
|
end
|
|
69
74
|
|
|
70
|
-
|
|
75
|
+
# rubocop:disable Style/GuardClause
|
|
76
|
+
if options[:info] || options[:certs]
|
|
71
77
|
@output.puts "- #{profile.developer_certificates.count} Developer Certificates"
|
|
72
|
-
|
|
78
|
+
if options[:certs]
|
|
79
|
+
profile.developer_certificates.each do |cert|
|
|
80
|
+
@output.puts " - #{cert.subject}"
|
|
81
|
+
@output.puts " issuer: #{cert.issuer}"
|
|
82
|
+
@output.puts " serial: #{cert.serial}"
|
|
83
|
+
@output.puts " expires: #{cert.not_after}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
73
86
|
end
|
|
87
|
+
|
|
74
88
|
if options[:info] || options[:devices]
|
|
75
89
|
@output.puts "- #{(profile.provisioned_devices || []).count} Provisioned Devices"
|
|
76
90
|
profile.provisioned_devices.each { |udid| @output.puts " - #{udid}" } if options[:devices]
|
|
77
91
|
@output.puts "- Provision all devices: #{profile.provisions_all_devices.inspect}"
|
|
78
92
|
end
|
|
93
|
+
# rubocop:enable Style/GuardClause
|
|
79
94
|
end
|
|
80
95
|
|
|
81
96
|
# Prints the filtered list of Provisioning Profiles
|
|
@@ -97,18 +112,18 @@ module PProf
|
|
|
97
112
|
# * Valid values for key `:zero` are `true` or `false` to decide if we print `\0` at the end of each output.
|
|
98
113
|
# Only used by `:list` and `:path` modes
|
|
99
114
|
#
|
|
100
|
-
def print_filtered_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, filters = {}, list_options = { :
|
|
115
|
+
def print_filtered_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, filters = {}, list_options = { mode: :table })
|
|
101
116
|
filter_func = lambda do |p|
|
|
102
117
|
(filters[:name].nil? || p.name =~ filters[:name]) &&
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
(filters[:appid_name].nil? || p.app_id_name =~ filters[:appid_name]) &&
|
|
119
|
+
(filters[:appid].nil? || p.entitlements.app_id =~ filters[:appid]) &&
|
|
120
|
+
(filters[:uuid].nil? || p.uuid =~ filters[:uuid]) &&
|
|
121
|
+
(filters[:team].nil? || p.team_name =~ filters[:team] || p.team_ids.any? { |id| id =~ filters[:team] }) &&
|
|
122
|
+
(filters[:exp].nil? || (p.expiration_date < DateTime.now) == filters[:exp]) &&
|
|
123
|
+
(filters[:has_devices].nil? || !(p.provisioned_devices || []).empty? == filters[:has_devices]) &&
|
|
124
|
+
(filters[:all_devices].nil? || p.provisions_all_devices == filters[:all_devices]) &&
|
|
125
|
+
(filters[:aps_env].nil? || match_aps_env(p.entitlements.aps_environment, filters[:aps_env])) &&
|
|
126
|
+
true
|
|
112
127
|
end
|
|
113
128
|
|
|
114
129
|
case list_options[:mode]
|
|
@@ -138,16 +153,17 @@ module PProf
|
|
|
138
153
|
@output.puts table.row('UUID', 'Name', 'AppID', 'Expiration Date', ' ', 'Team Name')
|
|
139
154
|
@output.puts table.separator
|
|
140
155
|
|
|
141
|
-
Dir[
|
|
156
|
+
Dir['*.mobileprovision', base: dir].each do |file_name|
|
|
157
|
+
file = File.join(dir, file_name)
|
|
142
158
|
begin
|
|
143
159
|
p = PProf::ProvisioningProfile.new(file)
|
|
144
|
-
|
|
160
|
+
|
|
145
161
|
next if block_given? && !yield(p)
|
|
146
162
|
|
|
147
163
|
state = DateTime.now < p.expiration_date ? "\u{2705}" : "\u{274c}" # 2705=checkmark, 274C=red X
|
|
148
164
|
@output.puts table.row(p.uuid, p.name, p.entitlements.app_id, p.expiration_date.to_time, state, p.team_name)
|
|
149
|
-
rescue
|
|
150
|
-
errors << { :
|
|
165
|
+
rescue StandardError => e
|
|
166
|
+
errors << { message: e, file: file }
|
|
151
167
|
end
|
|
152
168
|
count += 1
|
|
153
169
|
end
|
|
@@ -155,9 +171,7 @@ module PProf
|
|
|
155
171
|
@output.puts table.separator
|
|
156
172
|
@output.puts "#{count} Provisioning Profiles found."
|
|
157
173
|
|
|
158
|
-
unless errors.empty?
|
|
159
|
-
errors.each { |e| print_error(e[:message], e[:file]) }
|
|
160
|
-
end
|
|
174
|
+
errors.each { |e| print_error(e[:message], e[:file]) } unless errors.empty?
|
|
161
175
|
end
|
|
162
176
|
|
|
163
177
|
# Prints the filtered list of UUIDs or Paths only
|
|
@@ -165,35 +179,35 @@ module PProf
|
|
|
165
179
|
# @param [String] dir
|
|
166
180
|
# The directory containing the mobileprovision files to list.
|
|
167
181
|
# Defaults to '~/Library/MobileDevice/Provisioning Profiles'
|
|
182
|
+
# @param [Hash] options
|
|
183
|
+
# The options hash typically filled while parsing the command line arguments.
|
|
184
|
+
# - :mode: will print the UUIDs if set to `:uuid`, the file path otherwise
|
|
185
|
+
# - :zero: will concatenate the entries with `\0` instead of `\n` if set
|
|
168
186
|
#
|
|
169
|
-
# @yield each provisioning
|
|
187
|
+
# @yield each provisioning profile for filtering/validation
|
|
170
188
|
# The block is given ProvisioningProfile object and should
|
|
171
189
|
# return true to display the row, false to filter it out
|
|
172
190
|
#
|
|
173
|
-
def print_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, options)
|
|
191
|
+
def print_list(dir = PProf::ProvisioningProfile::DEFAULT_DIR, options) # rubocop:disable Style/OptionalArguments
|
|
174
192
|
errors = []
|
|
175
|
-
Dir[
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
unless errors.empty?
|
|
187
|
-
errors.each { |e| print_error(e[:message], e[:file]) }
|
|
193
|
+
Dir['*.mobileprovision', base: dir].each do |file_name|
|
|
194
|
+
file = File.join(dir, file_name)
|
|
195
|
+
p = PProf::ProvisioningProfile.new(file)
|
|
196
|
+
next if block_given? && !yield(p)
|
|
197
|
+
|
|
198
|
+
@output.print options[:mode] == :uuid ? p.uuid.chomp : file.chomp
|
|
199
|
+
@output.print options[:zero] ? "\0" : "\n"
|
|
200
|
+
rescue StandardError => e
|
|
201
|
+
errors << { message: e, file: file }
|
|
188
202
|
end
|
|
203
|
+
errors.each { |e| print_error(e[:message], e[:file]) } unless errors.empty?
|
|
189
204
|
end
|
|
190
205
|
|
|
191
|
-
|
|
192
|
-
private
|
|
193
206
|
def self.match_aps_env(actual, expected)
|
|
194
|
-
return false if actual.nil?
|
|
195
|
-
return true if expected
|
|
196
|
-
|
|
207
|
+
return false if actual.nil? # false if no Push entitlements
|
|
208
|
+
return true if expected == true # true if Push present but we don't filter on specific env
|
|
209
|
+
|
|
210
|
+
actual =~ expected # true if Push present and we filter on specific env
|
|
197
211
|
end
|
|
198
212
|
end
|
|
199
213
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'openssl'
|
|
2
4
|
require 'plist'
|
|
3
5
|
require 'time'
|
|
@@ -7,7 +9,7 @@ module PProf
|
|
|
7
9
|
# Represents the content of a Provisioning Profile file
|
|
8
10
|
class ProvisioningProfile
|
|
9
11
|
# The default location where all the Provisioning Profiles are stored on a Mac
|
|
10
|
-
DEFAULT_DIR="#{ENV['HOME']}/Library/MobileDevice/Provisioning Profiles"
|
|
12
|
+
DEFAULT_DIR = "#{ENV['HOME']}/Library/MobileDevice/Provisioning Profiles"
|
|
11
13
|
|
|
12
14
|
# Create a new ProvisioningProfile object from a file path or UUID
|
|
13
15
|
#
|
|
@@ -19,25 +21,26 @@ module PProf
|
|
|
19
21
|
# File path or UUID of the ProvisioningProfile
|
|
20
22
|
#
|
|
21
23
|
def initialize(file)
|
|
22
|
-
if file =~
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
path = if file =~ /^[0-9A-F-]*$/i
|
|
25
|
+
"#{PProf::ProvisioningProfile::DEFAULT_DIR}/#{file}.mobileprovision"
|
|
26
|
+
else
|
|
27
|
+
file
|
|
28
|
+
end
|
|
27
29
|
xml = nil
|
|
28
30
|
begin
|
|
29
31
|
pkcs7 = OpenSSL::PKCS7.new(File.read(path))
|
|
30
32
|
pkcs7.verify([], OpenSSL::X509::Store.new)
|
|
31
33
|
xml = pkcs7.data
|
|
32
|
-
|
|
34
|
+
raise 'Empty PKCS7 payload' if xml.nil? || xml.empty?
|
|
35
|
+
rescue StandardError
|
|
33
36
|
# Seems like sometimes OpenSSL fails to parse the PKCS7 payload
|
|
34
37
|
# Besides, OpenSSL is deprecated on macOS so might not be up-to-date on all machines
|
|
35
38
|
# So as a fallback, we run the `security` command line.
|
|
36
|
-
# (We could use `security` everytime, but invoking a command line is generally less
|
|
39
|
+
# (We could use `security` everytime, but invoking a command line is generally less
|
|
37
40
|
# efficient than calling the OpenSSL gem if available, so for now it's just used as fallback)
|
|
38
41
|
xml = `security cms -D -i "#{path}" 2> /dev/null`
|
|
39
42
|
end
|
|
40
|
-
@plist = Plist
|
|
43
|
+
@plist = Plist.parse_xml(xml)
|
|
41
44
|
raise "Unable to parse file #{file}." if @plist.nil?
|
|
42
45
|
end
|
|
43
46
|
|
|
@@ -100,7 +103,7 @@ module PProf
|
|
|
100
103
|
def team_ids
|
|
101
104
|
@plist['TeamIdentifier']
|
|
102
105
|
end
|
|
103
|
-
|
|
106
|
+
|
|
104
107
|
# The name of the Team associated with this Provisioning Profile
|
|
105
108
|
#
|
|
106
109
|
# @return [String]
|
|
@@ -108,7 +111,7 @@ module PProf
|
|
|
108
111
|
@plist['TeamName']
|
|
109
112
|
end
|
|
110
113
|
|
|
111
|
-
# The list of X509 Developer
|
|
114
|
+
# The list of X509 Developer Certificates associated with this profile
|
|
112
115
|
#
|
|
113
116
|
# @return [Array<OpenSSL::X509::Certificate>]
|
|
114
117
|
def developer_certificates
|
|
@@ -151,14 +154,14 @@ module PProf
|
|
|
151
154
|
#
|
|
152
155
|
# @return [String]
|
|
153
156
|
def to_s
|
|
154
|
-
lines = [
|
|
155
|
-
"- #{key
|
|
157
|
+
lines = %i[name uuid app_id_name app_id_prefix creation_date expiration_date ttl team_ids team_name].map do |key|
|
|
158
|
+
"- #{key}: #{send(key.to_sym)}"
|
|
156
159
|
end +
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
[
|
|
161
|
+
"- #{developer_certificates.count} Developer Certificates",
|
|
162
|
+
"- #{provisioned_devices.count} Provisioned Devices",
|
|
163
|
+
'- Entitlements:'
|
|
164
|
+
] + entitlements.to_hash.map { |key, value| " - #{key}: #{value}" }
|
|
162
165
|
lines.join("\n")
|
|
163
166
|
end
|
|
164
167
|
end
|
data/lib/pprof/version.rb
CHANGED
data/lib/pprof.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pprof
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Olivier Halligon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-02-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: plist
|
|
@@ -42,7 +42,8 @@ files:
|
|
|
42
42
|
homepage: https://github.com/AliSoftware/pprof
|
|
43
43
|
licenses:
|
|
44
44
|
- MIT
|
|
45
|
-
metadata:
|
|
45
|
+
metadata:
|
|
46
|
+
rubygems_mfa_required: 'true'
|
|
46
47
|
post_install_message:
|
|
47
48
|
rdoc_options: []
|
|
48
49
|
require_paths:
|
|
@@ -51,15 +52,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
51
52
|
requirements:
|
|
52
53
|
- - ">="
|
|
53
54
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 2.
|
|
55
|
+
version: 2.7.0
|
|
55
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
57
|
requirements:
|
|
57
58
|
- - ">="
|
|
58
59
|
- !ruby/object:Gem::Version
|
|
59
60
|
version: '0'
|
|
60
61
|
requirements: []
|
|
61
|
-
|
|
62
|
-
rubygems_version: 2.5.2
|
|
62
|
+
rubygems_version: 3.2.19
|
|
63
63
|
signing_key:
|
|
64
64
|
specification_version: 4
|
|
65
65
|
summary: A Provisioning Profiles library
|