cocoapods-privacy 0.2.5 → 0.3.1

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: 17bcbadaa7fac402b93e8895f8122c527873f24c25698809657999163ad7a5b5
4
- data.tar.gz: 511460533641f68349937f6b1bbb90ab65fe51eccc8eb2154eb41926169cf008
3
+ metadata.gz: f53ab1a6e9bcc1fba9dd87e461f210987d811c275cf06e8a0d135fd26dde68d7
4
+ data.tar.gz: b5052cb3dfa12e1a94d8dc388c0d477744198a2ac797fa663f016ef7e757ef1c
5
5
  SHA512:
6
- metadata.gz: cd028ae88664c51755d97bc79023e2eccf3245646dce468784197284a287ad525195e8a205cab60b8c36d9e46f3f88935627fa84f1e247e96c1efc72d5fa0841
7
- data.tar.gz: a0ba51fe193e4415b1103e03401946acc3db965c594a990a34e1d24927404e583a4557fce182cd62a96f295b7841fc64bd4530572f65ba4d0773a50678540f94
6
+ metadata.gz: 487d62cd0804642bd8cf744c20b2c454b2893568e52d640ceefcb62ef8175fbe09732b1afb7118f59535e825f993623b727a3929ed5c032bc3c9091285e8bd53
7
+ data.tar.gz: c398225bbecd92614e5b99d63d5b520c66ba6d0ff6cd270db6674724b6d56e6c492d4b4284e3dd3f23bdf38d77525ef63f35efeafbc8ce13d05de7991bb8243d
data/README.md CHANGED
@@ -24,6 +24,10 @@ There has 3 keys in defalut config, you should custom it!
24
24
  "source.black.list": ["replace me such as github.com"],
25
25
  "api.template.url": "https://raw.githubusercontent.com/ymoyao/cocoapods-privacy/main/resources/NSPrivacyAccessedAPITypes.plist"
26
26
  ```
27
+ After custom,you can set local config like this
28
+ ```
29
+ $ pod privacy config /yourfilepath/config.json
30
+ ```
27
31
 
28
32
  #### To Component
29
33
  ```
@@ -1,3 +1,3 @@
1
1
  module CocoapodsPrivacy
2
- VERSION = "0.2.5"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -36,12 +36,12 @@ module PrivacyHunter
36
36
  [apis,keyword_type_map]
37
37
  end
38
38
 
39
- def self.search_pricacy_apis(source_folders)
39
+ def self.search_pricacy_apis(source_folders,exclude_folders=[])
40
40
  apis,keyword_type_map = formatter_privacy_template()
41
41
 
42
42
  # 优化写法,一次循环完成所有查询
43
43
  datas = []
44
- apis_found = search_files(source_folders, apis)
44
+ apis_found = search_files(source_folders, exclude_folders, apis)
45
45
  unless apis_found.empty?
46
46
  apis_found.each do |keyword,reason|
47
47
  reasons = reason.split(',')
@@ -197,7 +197,7 @@ module PrivacyHunter
197
197
  end
198
198
 
199
199
  #搜索所有子文件夹
200
- def self.search_files(folder_paths, apis)
200
+ def self.search_files(folder_paths, exclude_folders, apis)
201
201
  # 获取文件夹下所有文件(包括子文件夹)
202
202
  all_files = []
203
203
  folder_paths.each do |folder|
@@ -212,9 +212,20 @@ module PrivacyHunter
212
212
  # 过滤掉目录路径,只保留文件路径,并将其添加到 all_files 数组中
213
213
  all_files += files_in_folder.reject { |file| File.directory?(file) }
214
214
  end
215
+
216
+ # 获取需要排除的文件
217
+ exclude_files = []
218
+ exclude_folders.each do |folder|
219
+ files_in_folder = Dir.glob(folder, File::FNM_DOTMATCH)
220
+ exclude_files += files_in_folder.reject { |file| File.directory?(file) }
221
+ end
222
+
223
+ # 剔除掉需要排除的文件
224
+ all_files = all_files.uniq - exclude_files.uniq
225
+
215
226
  # 遍历文件进行检索
216
227
  apis_found = {}
217
- all_files.uniq.each_with_index do |file_path, index|
228
+ all_files.each_with_index do |file_path, index|
218
229
  api_contains = contains_apis?(file_path, apis)
219
230
  apis_found = apis_found.merge(api_contains)
220
231
 
@@ -3,6 +3,10 @@ require 'cocoapods-core/specification/dsl/attribute_support'
3
3
  require 'cocoapods-core/specification/dsl/attribute'
4
4
  require 'xcodeproj'
5
5
 
6
+ KSource_Files_Key = 'source_files' #不存在单数 source_file
7
+ KExclude_Files_Key = 'exclude_files' #不存在单数 exclude_file
8
+ KResource_Bundle_Key = 'resource_bundle' #resource_bundle 和 resource_bundles 这两个参数本质上是一样的,resource_bundle 也能指向多个参数
9
+
6
10
  class BBRow
7
11
  attr_accessor :content, :is_comment, :is_spec_start, :is_spec_end, :key, :value
8
12
 
@@ -29,11 +33,10 @@ class BBRow
29
33
  end
30
34
 
31
35
  class BBSpec
32
- attr_accessor :name, :alias_name, :full_name, :parent, :rows, :privacy_sources, :privacy_file
36
+ attr_accessor :name, :alias_name, :full_name, :parent, :rows, :privacy_sources_files, :privacy_exclude_files, :privacy_file
33
37
 
34
38
  def initialize(name,alias_name,full_name)
35
39
  @rows = []
36
- @privacy_sources = nil
37
40
  @name = name
38
41
  @alias_name = alias_name
39
42
  @full_name = full_name
@@ -57,103 +60,139 @@ class BBSpec
57
60
  "#{@full_name}.#{name}"
58
61
  end
59
62
 
63
+ # 单独属性转成spec字符串,方便解析
64
+ def assemble_single_property_to_complex(property_name)
65
+ property_name += "s" if property_name == KResource_Bundle_Key #检测到单数resource_bundle,直接转成复数,功能一致
66
+ property_name
67
+ end
68
+
60
69
  def privacy_handle(podspec_file_path)
61
- source_files_index = 1
62
70
  @rows.each_with_index do |line, index|
63
71
  if !line || line.is_a?(BBSpec) || !line.key || line.key.empty?
64
72
  next
65
73
  end
66
74
 
67
- if !line.is_comment && line.key.include?(".resource_bundle")
75
+ if !line.is_comment && line.key.include?("." + KResource_Bundle_Key)
68
76
  @has_resource_bundle = true
69
- elsif !line.is_comment && line.key.include?(".source_files")
70
- begin
71
- code = "Pod::Spec.new do |s|; s.source_files = #{line.value}; end;"
72
- RubyVM::InstructionSequence.compile(code)
73
- spec = eval(code)
74
- rescue SyntaxError, StandardError => e
75
- raise Pod::Informative, "source_files字段 不支持多行拼写,请修改成成单行格式,重新执行pod privacy spec 命令"
76
- end
77
-
78
- if spec && !spec.attributes_hash['source_files'].nil?
79
- source_files_value = spec.attributes_hash['source_files']
80
- if source_files_value.is_a?(String) && !source_files_value.empty?
81
- source_files_array = [source_files_value]
82
- elsif source_files_value.is_a?(Array)
83
- # 如果已经是数组,直接使用
84
- source_files_array = source_files_value
85
- else
86
- # 其他情况,默认为空数组
87
- source_files_array = []
88
- end
89
-
90
- source_files_index = index
91
- @privacy_sources = source_files_array.map do |file_path|
92
- File.join(File.dirname(podspec_file_path), file_path.strip)
93
- end
94
- end
77
+ elsif !line.is_comment && line.key.include?("." + KSource_Files_Key)
78
+ @source_files_index = index
95
79
  end
96
80
  end
97
81
  create_privacy_file_if_need(podspec_file_path)
98
- modify_privacy_resource_bundle_if_need(source_files_index)
82
+ modify_privacy_resource_bundle_if_need(podspec_file_path)
99
83
  end
100
84
 
101
85
  # 对应Spec新增隐私文件
102
86
  def create_privacy_file_if_need(podspec_file_path)
103
- if @privacy_sources
87
+ if @source_files_index
104
88
  PrivacyUtils.create_privacy_if_empty(File.join(File.dirname(podspec_file_path), @privacy_file))
105
89
  end
106
90
  end
107
91
 
108
- # 把新增的隐私文件 映射给 podspec
109
- def modify_privacy_resource_bundle_if_need(source_files_index)
110
- if @privacy_sources
111
- privacy_resource_bundle = { "#{full_name}.privacy" => @privacy_file }
112
- if @has_resource_bundle
113
- line_incomplete = nil
114
- @rows.each_with_index do |line, index|
115
- if !line || line.is_a?(BBSpec)
116
- next
92
+ # 这里处理所有多行参数的解析,目前处理 source_files\exclude_files\resource_bundle 这三种
93
+ # 输入格式 ['.source_files':false,'.exclude_files':true......] => true 代表会根据获取的重置属性,需要把多行多余的进行删除
94
+ # 返回格式 {'.source_files':BBRow,......}
95
+ def fetch_mul_line_property(propertys_mul_line_hash)
96
+ property_hash = {}
97
+ line_processing = nil
98
+ property_config_processing = nil
99
+ @rows.each_with_index do |line, index|
100
+ if !line || line.is_a?(BBSpec) || line.is_comment
101
+ next
102
+ end
103
+
104
+ property_find = propertys_mul_line_hash.find { |key, _| line.key && line.key.include?(key) } #查找不到返回nil 查到返回数组,key, value 分别在第一和第二个参数
105
+ if property_find
106
+ property_config_processing = property_find
107
+ end
108
+
109
+ if property_config_processing
110
+ begin
111
+ property_name = property_config_processing.first
112
+ is_replace_line = property_config_processing.second
113
+ if line_processing
114
+ code = "#{line_processing.value}#{line.content}"
115
+ else
116
+ code = "#{line.value}"
117
117
  end
118
118
 
119
- is_resource_bundle_line = line.key && line.key.include?(".resource_bundle")
120
- if !line.is_comment && (is_resource_bundle_line || line_incomplete)
121
- begin
122
- if line_incomplete
123
- code = "#{line_incomplete.value}#{line.content}"
124
- else
125
- code = "#{line.value}"
126
- end
127
-
128
- # 清除 content 和 value, 后面会把所有的resource_bundle 组装起来,多余的内容要清除,避免重复
129
- line.content = ''
130
- line.value = nil
131
-
132
- RubyVM::InstructionSequence.compile(code)
133
- origin_resource_bundle = eval(code)
134
- rescue SyntaxError, StandardError => e
135
- unless line_incomplete
136
- line_incomplete = line
137
- end
138
- line_incomplete.value = code if line_incomplete #存储当前残缺的value,和后面完整的进行拼接
139
- next
140
- end
141
-
142
- final_line = (line_incomplete ? line_incomplete : line)
143
-
144
- merged_resource_bundle = origin_resource_bundle.merge(privacy_resource_bundle)
145
- @resource_bundle = merged_resource_bundle
146
- final_line.value = merged_resource_bundle
147
- final_line.content = "#{final_line.key}= #{final_line.value}"
148
- break
119
+ # 清除 content value, 后面会把所有的content 组装起来,多余的内容要清除,避免重复
120
+ if is_replace_line
121
+ line.content = ''
122
+ line.value = nil
149
123
  end
124
+
125
+ property_name_complex = assemble_single_property_to_complex(property_name)
126
+ spec_str = "Pod::Spec.new do |s|; s.#{property_name_complex} = #{code}; end;"
127
+ RubyVM::InstructionSequence.compile(spec_str)
128
+ spec = eval(spec_str)
129
+ property_value = spec.attributes_hash[property_name_complex]
130
+ rescue SyntaxError, StandardError => e
131
+ unless line_processing
132
+ line_processing = line
133
+ end
134
+ line_processing.value = code if line_processing #存储当前残缺的value,和后面完整的进行拼接
135
+ next
150
136
  end
151
- else
152
- space = PrivacyUtils.count_spaces_before_first_character(rows[source_files_index].content)
137
+
138
+ final_line = (line_processing ? line_processing : line)
139
+ final_line.value = property_value
140
+ property_hash[property_name] = final_line
141
+ line_processing = nil
142
+ property_config_processing = nil
143
+ end
144
+ end
145
+
146
+ property_hash
147
+ end
148
+
149
+ # 处理字符串或者数组,使其全都转为数组,并转成实际文件夹地址
150
+ def handle_string_or_array_files(podspec_file_path,line)
151
+ value = line.value
152
+ if value.is_a?(String) && !value.empty?
153
+ array = [value]
154
+ elsif value.is_a?(Array)
155
+ array = value
156
+ else
157
+ array = []
158
+ end
159
+
160
+ files = array.map do |file_path|
161
+ File.join(File.dirname(podspec_file_path), file_path.strip)
162
+ end
163
+ files
164
+ end
165
+
166
+ # 把新增的隐私文件 映射给 podspec && 解析 privacy_sources_files && 解析 privacy_exclude_files
167
+ def modify_privacy_resource_bundle_if_need(podspec_file_path)
168
+ if @source_files_index
169
+ privacy_resource_bundle = { "#{full_name}.privacy" => @privacy_file }
170
+
171
+ # 这里处理所有多行参数的解析,目前处理 source_files\exclude_files\resource_bundle 这三种
172
+ propertys_mul_line_hash = {}
173
+ propertys_mul_line_hash[KSource_Files_Key] = false
174
+ propertys_mul_line_hash[KExclude_Files_Key] = false
175
+ if @has_resource_bundle
176
+ propertys_mul_line_hash[KResource_Bundle_Key] = true #需要根据生成的重置属性
177
+ else # 如果原先没有resource_bundle,需要单独加一行resource_bundle
178
+ space = PrivacyUtils.count_spaces_before_first_character(rows[@source_files_index].content)
153
179
  line = "#{alias_name}.resource_bundle = #{privacy_resource_bundle}"
154
180
  line = PrivacyUtils.add_spaces_to_string(line,space)
155
181
  row = BBRow.new(line)
156
- @rows.insert(source_files_index+1, row)
182
+ @rows.insert(@source_files_index+1, row)
183
+ end
184
+ property_value_hash = fetch_mul_line_property(propertys_mul_line_hash)
185
+ property_value_hash.each do |property, line|
186
+ if property == KSource_Files_Key #处理 source_files
187
+ @privacy_sources_files = handle_string_or_array_files(podspec_file_path,line)
188
+ elsif property == KExclude_Files_Key #处理 exclude_files
189
+ @privacy_exclude_files = handle_string_or_array_files(podspec_file_path,line)
190
+ elsif property == KResource_Bundle_Key #处理 原有resource_bundle 合并隐私清单文件映射
191
+ merged_resource_bundle = line.value.merge(privacy_resource_bundle)
192
+ @resource_bundle = merged_resource_bundle
193
+ line.value = merged_resource_bundle
194
+ line.content = "#{line.key}= #{line.value}"
195
+ end
157
196
  end
158
197
  end
159
198
  end
@@ -165,7 +204,7 @@ module PrivacyModule
165
204
  public
166
205
 
167
206
  # 处理工程
168
- def self.load_project(folds)
207
+ def self.load_project(folds,exclude_folds)
169
208
  project_path = PrivacyUtils.project_path()
170
209
  resources_folder_path = File.join(File.basename(project_path, File.extname(project_path)),'Resources')
171
210
  privacy_file_path = File.join(resources_folder_path,PrivacyUtils.privacy_name)
@@ -198,7 +237,7 @@ module PrivacyModule
198
237
 
199
238
  # 开始检索api,并返回json 字符串数据
200
239
  PrivacyLog.clean_result_log()
201
- json_data = PrivacyHunter.search_pricacy_apis(folds)
240
+ json_data = PrivacyHunter.search_pricacy_apis(folds,exclude_folds)
202
241
 
203
242
  # 将数据写入隐私清单文件
204
243
  PrivacyHunter.write_to_privacy(json_data,privacy_file_path)
@@ -210,9 +249,11 @@ module PrivacyModule
210
249
  puts "👇👇👇👇👇👇 Start analysis component privacy 👇👇👇👇👇👇"
211
250
  PrivacyLog.clean_result_log()
212
251
  privacy_hash = PrivacyModule.check(podspec_file_path)
213
- privacy_hash.each do |privacy_file_path, source_files|
252
+ privacy_hash.each do |privacy_file_path, hash|
214
253
  PrivacyLog.write_to_result_log("#{privacy_file_path}: \n")
215
- data = PrivacyHunter.search_pricacy_apis(source_files)
254
+ source_files = hash[KSource_Files_Key]
255
+ exclude_files = hash[KExclude_Files_Key]
256
+ data = PrivacyHunter.search_pricacy_apis(source_files,exclude_files)
216
257
  PrivacyHunter.write_to_privacy(data,privacy_file_path) unless data.empty?
217
258
  end
218
259
  PrivacyLog.result_log_tip()
@@ -353,9 +394,10 @@ module PrivacyModule
353
394
 
354
395
  def self.fetch_privacy_hash(rows,podspec_file_path)
355
396
  privacy_hash = {}
356
- filtered_rows = rows.select { |row| row.is_a?(BBSpec) }
357
- filtered_rows.each do |spec|
358
- privacy_hash[File.join(File.dirname(podspec_file_path),spec.privacy_file)] = spec.privacy_sources
397
+ specs = rows.select { |row| row.is_a?(BBSpec) }
398
+ specs.each do |spec|
399
+ value = spec.privacy_sources_files ? {KSource_Files_Key => spec.privacy_sources_files,KExclude_Files_Key => spec.privacy_exclude_files || []} : {}
400
+ privacy_hash[File.join(File.dirname(podspec_file_path),spec.privacy_file)] = value
359
401
  privacy_hash.merge!(fetch_privacy_hash(spec.rows,podspec_file_path))
360
402
  end
361
403
  privacy_hash
@@ -83,16 +83,19 @@ module Pod
83
83
 
84
84
  # 存储本地调试组件
85
85
  development_folds = []
86
+ exclude_folds = []
86
87
 
87
88
  # 获取组件所在工程的pods 目录
88
89
  pod_folds = modules.map{ |spec|
89
90
  name = spec.name.split('/').first
91
+
90
92
  fold = File.join(@sandbox.root,name)
91
93
  podspec_file_path_develop = validate_development_pods(name)
92
94
  # 先验证是否是指向本地的组件(发现有的情况下 组件指向本地Pods 下依旧还是会有该组件,所以这里先判断本地的)
93
95
  if podspec_file_path_develop
94
96
  podspec_fold_path = File.dirname(podspec_file_path_develop)
95
97
  source_files = spec.attributes_hash['source_files']
98
+ exclude_files = spec.attributes_hash['exclude_files']
96
99
  if source_files && !source_files.empty?
97
100
  if source_files.is_a?(String) && !source_files.empty?
98
101
  development_folds << File.join(podspec_fold_path,source_files)
@@ -101,6 +104,17 @@ module Pod
101
104
  development_folds << File.join(podspec_fold_path,file)
102
105
  end
103
106
  end
107
+
108
+ # 处理exclude_files 排除文件夹
109
+ if exclude_files && !exclude_files.empty?
110
+ if exclude_files.is_a?(String) && !exclude_files.empty?
111
+ exclude_folds << File.join(podspec_fold_path,exclude_files)
112
+ elsif exclude_files.is_a?(Array)
113
+ exclude_files.each do |file|
114
+ exclude_folds << File.join(podspec_fold_path,file)
115
+ end
116
+ end
117
+ end
104
118
  end
105
119
  nil
106
120
  elsif Dir.exist?(fold)
@@ -118,7 +132,7 @@ module Pod
118
132
  puts "无组件或工程目录, 请检查工程"
119
133
  else
120
134
  # 处理工程隐私协议
121
- PrivacyModule.load_project(pod_folds)
135
+ PrivacyModule.load_project(pod_folds,exclude_folds.uniq)
122
136
  end
123
137
  puts "👆👆👆👆👆👆 End analysis project privacy 👆👆👆👆👆👆"
124
138
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-privacy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - youhui
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-18 00:00:00.000000000 Z
11
+ date: 2024-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -77,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
77
77
  requirements:
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
- version: '0'
80
+ version: 2.7.0
81
81
  required_rubygems_version: !ruby/object:Gem::Requirement
82
82
  requirements:
83
83
  - - ">="