cocoapods-privacy 0.5.3 → 0.6.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: ce64995902a9af9f853ce1d4018748b714f47a771289f8da33b1c9827a0fef59
4
- data.tar.gz: 7e7203d0324d3ccb00c1219fdbcf14edb32074f8d11099e1fe9d5b0117481ba4
3
+ metadata.gz: 149efd9549824e388ee859167394477eabe82e7a715ef49ba43b195d9b501746
4
+ data.tar.gz: 2949e52fffbefec5c2cb401711533e8a6e38d7f9cf53a1d19919a794a3a6dc8f
5
5
  SHA512:
6
- metadata.gz: 15cde8d4d59ac209bb6077aba1fd0f4fd05b84f63a34c4b1eb5400f2629062fd698d4160cb1fe53d15886eda618e949b15bfda03b801926f8c1ab31bd6753db8
7
- data.tar.gz: e51e757e36de17ce7142d9b4fbefb3fc244d0f57ab9cb02302bde26a7e8ae749f013535574b5036082c2d8fc6fd0735a91c8939c461a626502fd652ea8f68cab
6
+ metadata.gz: ff8fbcab1c042ea1bf24e503d75b593f7f6a2adc59836cd822ed5e2ddf58f6a1e3efc91cd7c8e79d8647f42936d8e21c215d25a9c943a940df86e4ed090149c9
7
+ data.tar.gz: 5037a9f32b471b8ec69172389969a568a7f63adc31f0278379a5d048828eaaa92d5457082809723db438ef39a155a61cbdac8dbf998e5e91b92dcf412ff5d09d
data/README.md CHANGED
@@ -103,7 +103,13 @@ $ pod privacy install
103
103
  ```
104
104
  <img width="298" alt="截屏2024-02-02 10 59 59" src="https://github.com/ymoyao/cocoapods-privacy/assets/13619221/c6f10e36-0f62-497a-93d4-f8b336dc8df4">
105
105
 
106
- After command, a PrivacyInfo.xcprivacy will create to you project Resources if empty. and it will search component that configuration files allow and do not have their own privacy manifest file.
106
+ After command, a PrivacyInfo.xcprivacy will create to you project Resources if empty.
107
+
108
+ Components that meet all of the following items will be processed.
109
+ * do not have their own privacy manifest file components
110
+ * in white list and not in black list components
111
+ * source code components(binary components please deal with command `pod privacy spec` )
112
+
107
113
 
108
114
  ## Notice
109
115
  The plugin is focus on NSPrivacyAccessedAPITypes and automatically search and create workflow.
@@ -0,0 +1,34 @@
1
+ module Pod
2
+ class Command
3
+ class Confuse < Command
4
+ class Spec < Confuse
5
+ self.summary = '根据 podspec 创建对应混淆文件'
6
+
7
+ self.description = <<-DESC
8
+ 根据podspec 创建对应混淆文件,并自动修改podspec文件。
9
+ DESC
10
+
11
+ self.arguments = [
12
+ CLAide::Argument.new('podspec_file', false, true),
13
+ ]
14
+
15
+ def initialize(argv)
16
+ @podspec_file = argv.arguments!.first
17
+ super
18
+ end
19
+
20
+ def validate!
21
+ @podspec_file = @podspec_file ? @podspec_file : PrivacyUtils.podspec_file_path
22
+ unless @podspec_file && !@podspec_file.empty?
23
+ raise Informative, 'no podspec file were found, please run pod confuse podspec_file_path'
24
+ end
25
+ end
26
+
27
+ def run
28
+ ConfuseModule.load_module(@podspec_file)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -1,5 +1,5 @@
1
1
  require 'cocoapods-privacy/command'
2
-
2
+ #### 以下是隐私协议部分 ####
3
3
  module Pod
4
4
  class Config
5
5
  attr_accessor :privacy_folds
@@ -18,8 +18,8 @@ module Pod
18
18
  [
19
19
  ['--privacy', '使用该参数,会自动生成并更新PrivacyInfo.xcprivacy'],
20
20
  ['--privacy-folds=folds', '指定文件夹检索,多个文件夹使用逗号","分割'],
21
- ['--query', '仅查询隐私api,不做写入'],
22
- ['--all', '忽略黑名单和白名单限制,查询工程所有组件'],
21
+ ['--privacy-query', '仅查询隐私api,不做写入'],
22
+ ['--privacy-all', '忽略黑名单和白名单限制,查询工程所有组件'],
23
23
  ].concat(origin_options)
24
24
  end
25
25
  end
@@ -27,9 +27,9 @@ module Pod
27
27
  alias_method :privacy_origin_initialize, :initialize
28
28
  def initialize(argv)
29
29
  privacy_folds = argv.option('privacy-folds', '').split(',')
30
+ is_query = argv.flag?('privacy-query',false)
31
+ is_all = argv.flag?('privacy-all',false)
30
32
  is_privacy = argv.flag?('privacy',false)
31
- is_query = argv.flag?('query',false)
32
- is_all = argv.flag?('all',false)
33
33
  privacy_origin_initialize(argv)
34
34
  instance = Pod::Config.instance
35
35
  instance.privacy_folds = privacy_folds
@@ -39,4 +39,37 @@ module Pod
39
39
  end
40
40
  end
41
41
  end
42
+ end
43
+
44
+ #### 以下是混淆部分 ####
45
+ module Pod
46
+ class Config
47
+ attr_accessor :confuse_pattern
48
+ end
49
+ end
50
+
51
+ module Pod
52
+ class Command
53
+ class Install < Command
54
+ class << self
55
+ alias_method :confuse_origin_options, :options
56
+ def options
57
+ [
58
+ ['--confuse=enable', '使用该参数,开启工程混淆'],
59
+ ['--confuse=disable', '使用该参数,移除工程混淆配置'],
60
+ # ['--confuse-folds=folds', '指定额外文件夹检索,多个文件夹使用逗号","分割'],
61
+ # ['--confuse-all', '忽略黑名单和白名单限制,查询工程所有组件'],
62
+ ].concat(origin_options)
63
+ end
64
+ end
65
+
66
+ alias_method :confuse_origin_initialize, :initialize
67
+ def initialize(argv)
68
+ confuse_pattern = argv.option('confuse', '') #混淆模式
69
+ confuse_origin_initialize(argv)
70
+ instance = Pod::Config.instance
71
+ instance.confuse_pattern = confuse_pattern
72
+ end
73
+ end
74
+ end
42
75
  end
@@ -36,7 +36,7 @@ module Pod
36
36
 
37
37
  def download_remote_config
38
38
  # 配置文件目录
39
- cache_config_file = PrivacyUtils.cache_config_file
39
+ cache_config_file = Common::Config.instance.cache_config_file
40
40
 
41
41
  # 开始下载
42
42
  system("curl -o #{cache_config_file} #{@config}")
@@ -50,7 +50,7 @@ module Pod
50
50
 
51
51
  def copy_local_config
52
52
  # 配置文件目录
53
- cache_config_file = PrivacyUtils.cache_config_file
53
+ cache_config_file = Common::Config.instance.cache_config_file
54
54
 
55
55
  # 复制本地文件
56
56
  FileUtils.cp(@config, cache_config_file)
@@ -1,15 +1,30 @@
1
+ ### common
2
+ require 'cocoapods-privacy/common/config'
3
+ require 'cocoapods-privacy/common/BBSpec'
4
+ require 'cocoapods-privacy/common/BBSpecManager'
5
+
6
+
7
+ ### privacy
1
8
  require 'cocoapods-privacy/command/privacy'
2
9
  require 'cocoapods-privacy/command/privacy/config'
3
10
  require 'cocoapods-privacy/command/privacy/install'
4
11
  require 'cocoapods-privacy/command/privacy/spec'
5
12
  require 'cocoapods-privacy/command/install'
6
-
7
13
  require 'cocoapods-privacy/privacy/privacy_specification_hook'
8
14
  require 'cocoapods-privacy/privacy/privacy_installer_hook'
9
15
  require 'cocoapods-privacy/privacy/PrivacyUtils'
10
16
  require 'cocoapods-privacy/privacy/PrivacyModule'
11
17
  require 'cocoapods-privacy/privacy/PrivacyHunter'
12
- require 'cocoapods-privacy/privacy/PrivacyConfig'
13
18
  require 'cocoapods-privacy/privacy/PrivacyLog'
14
19
 
20
+ ## mix
21
+ require 'cocoapods-privacy/command/confuse/spec'
22
+ require 'cocoapods-privacy/confuse/confuse_installer_hook'
23
+ require 'cocoapods-privacy/confuse/confuse_specification_hook'
24
+ require 'cocoapods-privacy/confuse/ConfuseUtils'
25
+ require 'cocoapods-privacy/confuse/ConfuseModule'
26
+ require 'cocoapods-privacy/confuse/ConfuseHunter'
27
+ require 'cocoapods-privacy/confuse/ObjCMethodAPIConverter'
28
+ require 'cocoapods-privacy/confuse/SwiftCallAssembly'
29
+
15
30
 
@@ -0,0 +1,234 @@
1
+ require 'cocoapods-privacy/command'
2
+
3
+ KSpecTypePrivacy = 'bb_privacy'
4
+ KSpecTypeConfuse = 'bb_confuse'
5
+
6
+
7
+ KSource_Files_Key = 'source_files' #不存在单数 source_file
8
+ KExclude_Files_Key = 'exclude_files' #不存在单数 exclude_file
9
+ KResource_Bundle_Key = 'resource_bundle' #resource_bundle 和 resource_bundles 这两个参数本质上是一样的,resource_bundle 也能指向多个参数
10
+
11
+ class BBRow
12
+ attr_accessor :content, :is_comment, :is_spec_start, :is_spec_end, :key, :value
13
+
14
+ def initialize(content, is_comment=false, is_spec_start=false, is_spec_end=false)
15
+ @content = content
16
+ @is_comment = is_comment
17
+ @is_spec_start = is_spec_start
18
+ @is_spec_end = is_spec_end
19
+
20
+ parse_key_value
21
+ end
22
+
23
+ def parse_key_value
24
+ # 在这里添加提取 key 和 value 的逻辑
25
+ if @content.include?('=')
26
+ key_value_split = @content.split('=')
27
+ @key = key_value_split[0]
28
+ @value = key_value_split[1..-1].join('=')
29
+ else
30
+ @key = nil
31
+ @value = nil
32
+ end
33
+ end
34
+ end
35
+
36
+ class BBSpec
37
+ attr_accessor :name, :alias_name, :full_name, :parent, :rows, :sources_files, :exclude_files, :type, :privacy_file, :confuse_file
38
+
39
+ def initialize(name,alias_name,full_name,type)
40
+ @rows = []
41
+ @name = name
42
+ @alias_name = alias_name
43
+ @full_name = full_name
44
+ @type = type
45
+ @privacy_file = "Pod/Privacy/#{full_name}/PrivacyInfo.xcprivacy"
46
+ confuse_file_name = @full_name.tr('.','_')
47
+ @confuse_file = "Pod/Confuse/#{full_name}/#{confuse_file_name}_Confuse"
48
+ end
49
+
50
+
51
+ def uniq_full_name_in_parent(name)
52
+ names = []
53
+ @rows.each_with_index do |line, index|
54
+ if line && line.is_a?(BBSpec)
55
+ names << line.name
56
+ end
57
+ end
58
+
59
+ #判断names 中是否包含 name,如果包含,那么给name 添加一个 “.diff” 后缀,一直到names 中没有包含name为止
60
+ while names.include?(name)
61
+ name = "#{name}.diff"
62
+ end
63
+
64
+ "#{@full_name}.#{name}"
65
+ end
66
+
67
+ # 单独属性转成spec字符串,方便解析
68
+ def assemble_single_property_to_complex(property_name)
69
+ property_name += "s" if property_name == KResource_Bundle_Key #检测到单数resource_bundle,直接转成复数,功能一致
70
+ property_name
71
+ end
72
+
73
+ def privacy_handle(podspec_file_path)
74
+ @rows.each_with_index do |line, index|
75
+ if !line || line.is_a?(BBSpec) || !line.key || line.key.empty?
76
+ next
77
+ end
78
+
79
+ if !line.is_comment && line.key.include?("." + KResource_Bundle_Key)
80
+ @has_resource_bundle = true
81
+ elsif !line.is_comment && line.key.include?("." + KSource_Files_Key)
82
+ @source_files_index = index
83
+ end
84
+ end
85
+ create_file_if_need(podspec_file_path)
86
+ modify_resource_bundle_if_need(podspec_file_path)
87
+ end
88
+
89
+ # 对应Spec新增隐私文件
90
+ def create_file_if_need(podspec_file_path)
91
+ if @source_files_index
92
+ if is_handle_privacy
93
+ PrivacyUtils.create_privacy_if_empty(File.join(File.dirname(podspec_file_path), @privacy_file))
94
+ elsif is_handle_confuse
95
+ ConfuseUtils.create_confuse_if_empty(File.join(File.dirname(podspec_file_path), "#{@confuse_file}.h"))
96
+ ConfuseUtils.create_confuse_if_empty(File.join(File.dirname(podspec_file_path), "#{@confuse_file}.swift"))
97
+ end
98
+ end
99
+ end
100
+
101
+ def is_handle_privacy
102
+ @type.include?(KSpecTypePrivacy)
103
+ end
104
+
105
+ def is_handle_confuse
106
+ @type.include?(KSpecTypeConfuse)
107
+ end
108
+
109
+ # 这里处理所有多行参数的解析,目前处理 source_files\exclude_files\resource_bundle 这三种
110
+ # 输入格式 ['.source_files':false,'.exclude_files':true......] => true 代表会根据获取的重置属性,需要把多行多余的进行删除
111
+ # 返回格式 {'.source_files':BBRow,......}
112
+ def fetch_mul_line_property(propertys_mul_line_hash)
113
+ property_hash = {}
114
+ line_processing = nil
115
+ property_config_processing = nil
116
+ @rows.each_with_index do |line, index|
117
+ if !line || line.is_a?(BBSpec) || line.is_comment
118
+ next
119
+ end
120
+
121
+ property_find = propertys_mul_line_hash.find { |key, _| line.key && line.key.include?(key) } #查找不到返回nil 查到返回数组,key, value 分别在第一和第二个参数
122
+ if property_find
123
+ property_config_processing = property_find
124
+ end
125
+
126
+ if property_config_processing
127
+ begin
128
+ property_name = property_config_processing.first
129
+ is_replace_line = property_config_processing.second
130
+ if line_processing
131
+ code = "#{line_processing.value}#{line.content}"
132
+ else
133
+ code = "#{line.value}"
134
+ end
135
+
136
+ # 清除 content 和 value, 后面会把所有的content 组装起来,多余的内容要清除,避免重复
137
+ if is_replace_line
138
+ line.content = ''
139
+ line.value = nil
140
+ end
141
+
142
+ property_name_complex = assemble_single_property_to_complex(property_name)
143
+ spec_str = "Pod::Spec.new do |s|; s.#{property_name_complex} = #{code}; end;"
144
+ RubyVM::InstructionSequence.compile(spec_str)
145
+ spec = eval(spec_str)
146
+ property_value = spec.attributes_hash[property_name_complex]
147
+ rescue SyntaxError, StandardError => e
148
+ unless line_processing
149
+ line_processing = line
150
+ end
151
+ line_processing.value = code if line_processing #存储当前残缺的value,和后面完整的进行拼接
152
+ next
153
+ end
154
+
155
+ final_line = (line_processing ? line_processing : line)
156
+ final_line.value = property_value
157
+ property_hash[property_name] = final_line
158
+ line_processing = nil
159
+ property_config_processing = nil
160
+ end
161
+ end
162
+
163
+ property_hash
164
+ end
165
+
166
+ # 处理字符串或者数组,使其全都转为数组,并转成实际文件夹地址
167
+ def handle_string_or_array_files(podspec_file_path,line)
168
+ value = line.value
169
+ array = fetch_string_or_array_files(podspec_file_path,line)
170
+
171
+ files = array.map do |file_path|
172
+ File.join(File.dirname(podspec_file_path), file_path.strip)
173
+ end
174
+ files
175
+ end
176
+
177
+ def fetch_string_or_array_files(podspec_file_path,line)
178
+ value = line.value
179
+ if value.is_a?(String) && !value.empty?
180
+ array = [value]
181
+ elsif value.is_a?(Array)
182
+ array = value
183
+ else
184
+ array = []
185
+ end
186
+ array
187
+ end
188
+
189
+ # 把新增的隐私文件 映射给 podspec && 解析 sources_files && 解析 exclude_files
190
+ def modify_resource_bundle_if_need(podspec_file_path)
191
+ if @source_files_index
192
+
193
+ # 这里处理所有多行参数的解析,目前处理 source_files\exclude_files\resource_bundle 这三种
194
+ propertys_mul_line_hash = {}
195
+ propertys_mul_line_hash[KSource_Files_Key] = false
196
+ propertys_mul_line_hash[KExclude_Files_Key] = false
197
+ propertys_mul_line_hash[KResource_Bundle_Key] = false
198
+
199
+ property_value_hash = fetch_mul_line_property(propertys_mul_line_hash)
200
+ property_value_hash.each do |property, line|
201
+ if property == KSource_Files_Key #处理 source_files
202
+ @sources_files = handle_string_or_array_files(podspec_file_path,line)
203
+ # puts "originSource = #{sources_files}"
204
+ if is_handle_confuse
205
+ source_array = fetch_string_or_array_files(podspec_file_path,line)
206
+ source_array.push("#{@confuse_file}.{h,swift}")
207
+ line.value = source_array.uniq
208
+ line.content = "#{line.key}= #{line.value}"
209
+ end
210
+ elsif property == KExclude_Files_Key #处理 exclude_files
211
+ @exclude_files = handle_string_or_array_files(podspec_file_path,line)
212
+ elsif property == KResource_Bundle_Key #处理 原有resource_bundle 合并隐私清单文件映射
213
+ # 仅在隐私清单时才去解析 resource_bundle
214
+ privacy_resource_bundle = { "#{full_name}.privacy" => @privacy_file }
215
+ if is_handle_privacy
216
+ if @has_resource_bundle
217
+ merged_resource_bundle = line.value.merge(privacy_resource_bundle)
218
+ @resource_bundle = merged_resource_bundle
219
+ line.value = merged_resource_bundle
220
+ line.content = "#{line.key}= #{line.value}"
221
+ else # 如果原先没有resource_bundle,需要单独加一行resource_bundle
222
+ space = PrivacyUtils.count_spaces_before_first_character(rows[@source_files_index].content)
223
+ line = "#{alias_name}.resource_bundle = #{privacy_resource_bundle}"
224
+ line = PrivacyUtils.add_spaces_to_string(line,space)
225
+ row = BBRow.new(line)
226
+ @rows.insert(@source_files_index+1, row)
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
234
+
@@ -0,0 +1,166 @@
1
+ require 'cocoapods-privacy/command'
2
+
3
+ module BB
4
+ class BBSpecManager
5
+ def initialize(type)
6
+ @type = type
7
+ end
8
+
9
+
10
+ def check(podspec_file_path)
11
+ # Step 1: 读取podspec
12
+ lines = read_podspec(podspec_file_path)
13
+
14
+ # Step 2: 逐行解析并转位BBRow 模型
15
+ rows = parse_row(lines)
16
+
17
+ # Step 3.1:如果Row 是属于Spec 内,那么聚拢成BBSpec,
18
+ # Step 3.2:BBSpec 内使用数组存储其Spec 内的行
19
+ # Step 3.3 在合适位置给每个有效的spec都创建一个 隐私模版,并修改其podspec 引用
20
+ combin_sepcs_and_rows = combin_sepc_if_need(rows,podspec_file_path)
21
+
22
+ # Step 4: 展开修改后的Spec,重新转换成 BBRow
23
+ rows = unfold_sepc_if_need(combin_sepcs_and_rows)
24
+
25
+ # Step 5: 打开隐私模版,并修改其podspec文件,并逐行写入
26
+ File.open(podspec_file_path, 'w') do |file|
27
+ # 逐行写入 rows
28
+ rows.each do |row|
29
+ file.puts(row.content)
30
+ end
31
+ end
32
+
33
+
34
+ # Step 6: 获取privacy 相关信息,传递给后续处理
35
+ hash = fetch_hash(combin_sepcs_and_rows,podspec_file_path).compact
36
+ filtered_hash = hash.reject { |_, value| value.empty? }
37
+ filtered_hash
38
+ end
39
+
40
+
41
+ def read_podspec(file_path)
42
+ # puts "read_podspec = #{file_path}"
43
+ File.readlines(file_path)
44
+ end
45
+
46
+ def parse_row(lines)
47
+ rows = []
48
+ code_stack = [] #栈,用来排除if end 等对spec 的干扰
49
+
50
+ lines.each do |line|
51
+ content = line.strip
52
+ is_comment = content.start_with?('#')
53
+ is_spec_start = !is_comment && (content.include?('Pod::Spec.new') || content.include?('.subspec'))
54
+ is_if = !is_comment && content.start_with?('if')
55
+ is_end = !is_comment && content.start_with?('end')
56
+
57
+ # 排除if end 对spec_end 的干扰
58
+ code_stack.push('spec') if is_spec_start
59
+ code_stack.push('if') if is_if
60
+ stack_last = code_stack.last
61
+ is_spec_end = is_end && stack_last && stack_last == 'spec'
62
+ is_if_end = is_end && stack_last && stack_last == 'if'
63
+ code_stack.pop if is_spec_end || is_if_end
64
+
65
+ row = BBRow.new(line, is_comment, is_spec_start, is_spec_end)
66
+ rows << row
67
+ end
68
+ rows
69
+ end
70
+
71
+ # 数据格式:
72
+ # [
73
+ # BBRow
74
+ # BBRow
75
+ # BBSpec
76
+ # rows
77
+ # [
78
+ # BBRow
79
+ # BBSpec
80
+ # BBRow
81
+ # BBRow
82
+ # ]
83
+ # BBRow
84
+ # ......
85
+ # ]
86
+ # 合并Row -> Spec(会存在部分行不在Spec中:Spec new 之前的注释)
87
+ def combin_sepc_if_need(rows,podspec_file_path)
88
+ spec_stack = []
89
+ result_rows = []
90
+ default_name = File.basename(podspec_file_path, File.extname(podspec_file_path))
91
+
92
+ rows.each do |row|
93
+ if row.is_spec_start
94
+ # 获取父spec
95
+ parent_spec = spec_stack.last
96
+
97
+ # 创建 spec
98
+ name = row.content.split("'")[1]&.strip || default_name
99
+ alias_name = row.content.split("|")[1]&.strip
100
+ full_name = parent_spec ? parent_spec.uniq_full_name_in_parent(name) : name
101
+
102
+ spec = BBSpec.new(name,alias_name,full_name,@type)
103
+ spec.rows << row
104
+ spec.parent = parent_spec
105
+
106
+ # 当存在 spec 时,存储在 spec.rows 中;不存在时,直接存储在外层
107
+ (parent_spec ? parent_spec.rows : result_rows ) << spec
108
+
109
+ # spec 入栈
110
+ spec_stack.push(spec)
111
+ elsif row.is_spec_end
112
+ # 当前 spec 的 rows 加入当前行
113
+ spec_stack.last&.rows << row
114
+
115
+ #执行隐私协议修改
116
+ spec_stack.last.privacy_handle(podspec_file_path)
117
+
118
+ # spec 出栈
119
+ spec_stack.pop
120
+ else
121
+ # 当存在 spec 时,存储在 spec.rows 中;不存在时,直接存储在外层
122
+ (spec_stack.empty? ? result_rows : spec_stack.last.rows) << row
123
+ end
124
+ end
125
+
126
+ result_rows
127
+ end
128
+
129
+ # 把所有的spec中的rows 全部展开,拼接成一级数组【BBRow】
130
+ def unfold_sepc_if_need(rows)
131
+ result_rows = []
132
+ rows.each do |row|
133
+ if row.is_a?(BBSpec)
134
+ result_rows += unfold_sepc_if_need(row.rows)
135
+ else
136
+ result_rows << row
137
+ end
138
+ end
139
+ result_rows
140
+ end
141
+
142
+
143
+ def fetch_hash(rows,podspec_file_path)
144
+ hash = {}
145
+ specs = rows.select { |row| row.is_a?(BBSpec) }
146
+ specs.each do |spec|
147
+ value = spec.sources_files ? {KSource_Files_Key => spec.sources_files,KExclude_Files_Key => spec.exclude_files || []} : {}
148
+ if is_handle_privacy
149
+ hash[File.join(File.dirname(podspec_file_path),spec.privacy_file)] = value
150
+ elsif is_handle_confuse
151
+ hash[File.join(File.dirname(podspec_file_path),spec.confuse_file)] = value
152
+ end
153
+ hash.merge!(fetch_hash(spec.rows,podspec_file_path))
154
+ end
155
+ hash
156
+ end
157
+
158
+ def is_handle_privacy
159
+ @type.include?(KSpecTypePrivacy)
160
+ end
161
+
162
+ def is_handle_confuse
163
+ @type.include?(KSpecTypeConfuse)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,69 @@
1
+ require 'cocoapods-privacy/command'
2
+ require 'digest'
3
+
4
+ module Common
5
+ class Config
6
+ def initialize()
7
+ load_config_content_if_exist()
8
+ end
9
+
10
+ def api_template_url
11
+ load_config_content_if_exist()
12
+ return @json['api.template.url'] || ""
13
+ end
14
+
15
+ def source_black_list
16
+ load_config_content_if_exist()
17
+ return @json['source.black.list'] || []
18
+ end
19
+
20
+ def source_white_list
21
+ load_config_content_if_exist()
22
+ return @json['source.white.list'] || []
23
+ end
24
+
25
+ def self.instance
26
+ @instance ||= new
27
+ end
28
+
29
+ def cache_privacy_fold
30
+ # 本地缓存目录
31
+ cache_directory = File.expand_path('~/.cache')
32
+
33
+ # 目标文件夹路径
34
+ target_directory = File.join(cache_directory, 'cocoapods-privacy', 'privacy')
35
+
36
+ # 如果文件夹不存在,则创建
37
+ FileUtils.mkdir_p(target_directory) unless Dir.exist?(target_directory)
38
+
39
+ target_directory
40
+ end
41
+
42
+ # etag 文件夹
43
+ def cache_privacy_etag_fold
44
+ File.join(cache_privacy_fold,'etag')
45
+ end
46
+
47
+ # config.json 文件
48
+ def cache_config_file
49
+ File.join(cache_privacy_fold, 'config.json')
50
+ end
51
+
52
+ # config.json 文件
53
+ def cache_log_file
54
+ File.join(cache_privacy_fold, 'privacy.log')
55
+ end
56
+
57
+ private
58
+ def load_config_content_if_exist
59
+ unless @json
60
+ if File.exist?(cache_config_file)
61
+ config_content = File.read(cache_config_file)
62
+ @json = JSON.parse(config_content)
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ end
69
+ end