codeobscure 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/codeobscure +3 -0
- data/filtSymbols +0 -0
- data/filtSymbols_standard +0 -0
- data/lib/codeobscure.rb +107 -0
- data/lib/codeobscure/filtsymbols.rb +47 -0
- data/lib/codeobscure/funclist.rb +159 -0
- data/lib/codeobscure/obscure.rb +89 -0
- data/lib/codeobscure/version.rb +3 -0
- data/test/codeobscure_test.rb +50 -0
- data/test/test_helper.rb +4 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d45e95289d085a0efdd2c8597a5a5aa2cce266d
|
4
|
+
data.tar.gz: b1ca9ac495f2742f6a0d98629c4e0a6f66147807
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e475da848a16558d2cb66723a10ef58233e9e76a3599a0158fc9907360db5a58c0c84a5f173cb7c511ef4ff39e866b7ddfaf2ac99e5c8887c4b7650585ffc022
|
7
|
+
data.tar.gz: bb113db57be6ab97f88f5cefc3ad1840a8930448a511d0bf9c7b3b9105288fba88de9477874ef4d9e03344807b749551f05449e4607b272e32f9dfeff28ce8af
|
data/bin/codeobscure
ADDED
data/filtSymbols
ADDED
Binary file
|
Binary file
|
data/lib/codeobscure.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require "codeobscure/version"
|
2
|
+
require "codeobscure/funclist"
|
3
|
+
require "codeobscure/obscure"
|
4
|
+
require "codeobscure/filtsymbols"
|
5
|
+
require "colorize"
|
6
|
+
require 'xcodeproj'
|
7
|
+
require 'fileutils'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
module Codeobscure
|
11
|
+
|
12
|
+
def self.root
|
13
|
+
File.dirname __dir__
|
14
|
+
end
|
15
|
+
|
16
|
+
#waiting for add optionparse and add class obscure
|
17
|
+
def self.obscure
|
18
|
+
|
19
|
+
options = {}
|
20
|
+
OptionParser.new do |opts|
|
21
|
+
opts.banner = "Usage: obscure code for object-c project"
|
22
|
+
|
23
|
+
opts.on("-o", "--obscure XcodeprojPath", "obscure code") do |v|
|
24
|
+
options[:obscure] = v
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-l", "--load path1,path2,path3",Array,"load filt symbols from path") do |v|
|
28
|
+
options[:load] = v
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-r", "--reset", "reset loaded symbols") do |v|
|
32
|
+
options[:reset] = true
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-f", "--fetch type1,type2,type3", "fetch and replace type,default type is [c,p,f].c for class,p for property,f for function") do |v|
|
36
|
+
options[:fetch] = v
|
37
|
+
end
|
38
|
+
|
39
|
+
end.parse!
|
40
|
+
|
41
|
+
if options[:reset]
|
42
|
+
`rm -f #{root_dir}/filtSymbols`
|
43
|
+
`cp #{root_dir}/filtSymbols_standard #{root_dir}/filtSymbols`
|
44
|
+
end
|
45
|
+
|
46
|
+
#only load, execute load only
|
47
|
+
#only obscure, execute obscure only
|
48
|
+
#load and obscure at same time,load firt,then obscure.That's mean you can get rid of some directoies.
|
49
|
+
load_pathes = options[:load]
|
50
|
+
if load_pathes
|
51
|
+
load_pathes.each do |load_path|
|
52
|
+
if File.exist? load_path
|
53
|
+
FiltSymbols.loadFiltSymbols load_path
|
54
|
+
puts "加载完毕!".colorize(:green)
|
55
|
+
else
|
56
|
+
puts "指定的目录不存在:#{path}".colorize(:red)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
fetch_types = ["p","c","f"]
|
62
|
+
if options[:fetch].length > 0
|
63
|
+
fetch_types = options[:fetch]
|
64
|
+
end
|
65
|
+
|
66
|
+
if options[:obscure]
|
67
|
+
|
68
|
+
xpj_path = options[:obscure]
|
69
|
+
if File.exist? xpj_path
|
70
|
+
root_dir = xpj_path.split("/")[0...-1].join "/"
|
71
|
+
FuncList.genFuncList root_dir , "all", true, fetch_types
|
72
|
+
header_file = Obscure.run root_dir
|
73
|
+
project = Xcodeproj::Project.open xpj_path
|
74
|
+
project_name = xpj_path.split("/").last
|
75
|
+
main_group = project.main_group
|
76
|
+
if !main_group.find_file_by_path("codeObfuscation.h")
|
77
|
+
main_group.new_reference header_file
|
78
|
+
end
|
79
|
+
project.targets.each do |target|
|
80
|
+
if target.name = project_name
|
81
|
+
build_configs = target.build_configurations
|
82
|
+
build_configs.each do |build_config|
|
83
|
+
build_settings = build_config.build_settings
|
84
|
+
prefix_key = "GCC_PREFIX_HEADER"
|
85
|
+
prefix_header = build_settings[prefix_key]
|
86
|
+
if prefix_header.nil? || prefix_header.empty?
|
87
|
+
build_config.build_settings[prefix_key] = "./codeObfuscation.h"
|
88
|
+
elsif prefix_header.include? "codeObfuscation.h"
|
89
|
+
puts "#{target.name}:#{build_config}配置文件已配置完成".colorize(:green)
|
90
|
+
else
|
91
|
+
puts "请在#{prefix_header.class.name}中#import \"codeObfuscation.h\"".colorize(:green)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
project.save
|
97
|
+
puts "配置完成!".colorize(:green)
|
98
|
+
puts "请直接运行项目,如果项目中出现类似: `+[LoremIpsum PyTJvHwWNmeaaVzp:]: unrecognized selector sent to class`。在codeObfuscation.h中查询PyTJvHwWNmeaaVzp并删除它!".colorize(:yellow)
|
99
|
+
else
|
100
|
+
puts "指定的目录不存在:#{path}".colorize(:red)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative "funclist.rb"
|
2
|
+
require "colorize"
|
3
|
+
module FiltSymbols
|
4
|
+
@@filt_db_path = "#{File.expand_path '../../..', __FILE__}/filtSymbols"
|
5
|
+
@@table_name = "symbols"
|
6
|
+
@@key_words = ["interface","NSInteger","BOOL","Class","free","M_PI_2","abort","change","top","bottom","NSUIntegerMax","intoString"]
|
7
|
+
|
8
|
+
def self.createTable
|
9
|
+
if !File.exist? @@filt_db_path
|
10
|
+
`echo "create table #{@@table_name}(src text,PRIMARY KEY (src));" | sqlite3 #{@@filt_db_path}`
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.insertValue(line)
|
15
|
+
`echo "insert or ignore into #{@@table_name} values('#{line}');" | sqlite3 #{@@filt_db_path}`
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.query(line)
|
19
|
+
`echo "select * from #{@@table_name} where src='#{line}';" | sqlite3 #{@@filt_db_path}`
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.loadFiltSymbols(path)
|
23
|
+
|
24
|
+
createTable
|
25
|
+
|
26
|
+
funclist_path = FuncList.genFuncList path , "h" , false
|
27
|
+
|
28
|
+
puts "处理中,可能需要一段时间,耐心等候...".colorize(:yellow)
|
29
|
+
symbol_file = File.open(funclist_path).read
|
30
|
+
symbol_file.each_line do |line|
|
31
|
+
line_content = line.rstrip.split(":").last
|
32
|
+
insertValue line_content
|
33
|
+
end
|
34
|
+
|
35
|
+
@@key_words.each do |word|
|
36
|
+
insertValue word
|
37
|
+
end
|
38
|
+
|
39
|
+
if File.exist? funclist_path
|
40
|
+
`rm -f #{funclist_path}`
|
41
|
+
end
|
42
|
+
|
43
|
+
`sqlite3 #{@@filt_db_path} .dump`
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module FuncList
|
2
|
+
|
3
|
+
@@func_regex = /\s*(\w+)\s*:\s*\(\s*\w*\s*\s*\w+\s*\*?\s*\)\s*\w+\s*/
|
4
|
+
@@func_simple_regex = /\s*[-\+]\s*\(\s*\w+\s*\*?\)\s*(\w+)\s*;*/
|
5
|
+
@@hcls_regex = /@interface\s+(\w+)\s*/
|
6
|
+
@@mcls_regex = /@implementation\s+(\w+)\s*/
|
7
|
+
@@property_regex = /\s*@property\s*\(.*?getter=(\w+).*?\)\s*\w+\s*\*?\s*\w+\s*.*;/
|
8
|
+
@@property_regex2 = /\s*@property\s*\(.*?\)\s*\w+\s*\*?\s*(\w+)\s*.*;/
|
9
|
+
@@property_regex3 = /\s*@property\s*\(.*?\)\s*\w+\s*<.*>\s*\*?\s*(\w+)\s*.*;/
|
10
|
+
|
11
|
+
def self.to_utf8(str)
|
12
|
+
str = str.force_encoding('UTF-8')
|
13
|
+
return str if str.valid_encoding?
|
14
|
+
str.encode("UTF-8", 'binary', invalid: :replace, undef: :replace, replace: '')
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.capture(content_str,type = "m",fetch_types=["p","f","c"])
|
18
|
+
results = []
|
19
|
+
str = to_utf8 content_str
|
20
|
+
if fetch_types.include? "f"
|
21
|
+
str.scan @@func_regex do |curr_match|
|
22
|
+
md = Regexp.last_match
|
23
|
+
whole_match = md[0]
|
24
|
+
captures = md.captures
|
25
|
+
|
26
|
+
captures.each do |capture|
|
27
|
+
results << "f:#{capture}"
|
28
|
+
#p [whole_match, capture]
|
29
|
+
p "f:[#{capture}]"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
#no arguments function
|
33
|
+
str.scan @@func_simple_regex do |curr_match|
|
34
|
+
md = Regexp.last_match
|
35
|
+
whole_match = md[0]
|
36
|
+
captures = md.captures
|
37
|
+
|
38
|
+
captures.each do |capture|
|
39
|
+
results << "f:#{capture}"
|
40
|
+
#p [whole_match, capture]
|
41
|
+
p "f:[#{capture}]"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
cls_regex = ""
|
46
|
+
if type == "h"
|
47
|
+
cls_regex = @@hcls_regex
|
48
|
+
else
|
49
|
+
cls_regex = @@mcls_regex
|
50
|
+
end
|
51
|
+
if fetch_types.include? "c"
|
52
|
+
str.scan cls_regex do |curr_match|
|
53
|
+
md = Regexp.last_match
|
54
|
+
whole_match = md[0]
|
55
|
+
captures = md.captures
|
56
|
+
|
57
|
+
captures.each do |capture|
|
58
|
+
results << "c:#{capture}"
|
59
|
+
#p [whole_match, capture]
|
60
|
+
p "c:[#{capture}]"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if fetch_types.include? "p"
|
65
|
+
str.scan @@property_regex do |curr_match|
|
66
|
+
md = Regexp.last_match
|
67
|
+
whole_match = md[0]
|
68
|
+
captures = md.captures
|
69
|
+
|
70
|
+
captures.each do |capture|
|
71
|
+
results << "p:#{capture}"
|
72
|
+
#p [whole_match, capture]
|
73
|
+
p "p:[#{capture}]"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
str.scan @@property_regex2 do |curr_match|
|
77
|
+
md = Regexp.last_match
|
78
|
+
whole_match = md[0]
|
79
|
+
captures = md.captures
|
80
|
+
|
81
|
+
captures.each do |capture|
|
82
|
+
results << "p:#{capture}"
|
83
|
+
#p [whole_match, capture]
|
84
|
+
p "p:[#{capture}]"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
str.scan @@property_regex3 do |curr_match|
|
88
|
+
md = Regexp.last_match
|
89
|
+
whole_match = md[0]
|
90
|
+
captures = md.captures
|
91
|
+
|
92
|
+
captures.each do |capture|
|
93
|
+
results << "p:#{capture}"
|
94
|
+
#p [whole_match, capture]
|
95
|
+
p "p:[#{capture}]"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
results
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.genFuncList(path,type = "m",need_filt=true,fetch_types=["p","f","c"])
|
104
|
+
puts "#######################{fetch_types}"
|
105
|
+
capture_methods = []
|
106
|
+
p_methods = []
|
107
|
+
funclist_path = "#{path}/func.list"
|
108
|
+
file = File.open(funclist_path, "w")
|
109
|
+
file_pathes = []
|
110
|
+
if type == "h" || type == "m"
|
111
|
+
file_pathes = `find #{path} -name "*.#{type}" -d`.split "\n"
|
112
|
+
elsif type == "all"
|
113
|
+
file_pathes += `find #{path} -name "*.h" -d`.split "\n"
|
114
|
+
file_pathes += `find #{path} -name "*.m" -d`.split "\n"
|
115
|
+
end
|
116
|
+
file_pathes.each do |file_path|
|
117
|
+
content = File.read file_path
|
118
|
+
captures = capture content , type , fetch_types
|
119
|
+
captures.each do |capture_method|
|
120
|
+
method_type = capture_method.split(":").first
|
121
|
+
method_content = capture_method.split(":").last
|
122
|
+
if !(method_content.start_with?("init") || method_content.start_with?("set") || method_content.start_with?("_") || method_content.length < 4) || !need_filt
|
123
|
+
if method_type == "c" || method_type == "f"
|
124
|
+
if !capture_methods.include? capture_method
|
125
|
+
capture_methods << capture_method
|
126
|
+
end
|
127
|
+
elsif method_type == "p"
|
128
|
+
if !p_methods.include? capture_method
|
129
|
+
p_methods << capture_method
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
p_methods.each do |capture_method|
|
137
|
+
method_type = capture_method.split(":").first
|
138
|
+
method_content = capture_method.split(":").last
|
139
|
+
c_method = "c:#{method_content}"
|
140
|
+
f_method = "f:#{method_content}"
|
141
|
+
if capture_methods.include? c_method
|
142
|
+
capture_methods.delete c_method
|
143
|
+
end
|
144
|
+
if capture_methods.include? f_method
|
145
|
+
capture_methods.delete f_method
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
capture_methods += p_methods
|
150
|
+
|
151
|
+
if capture_methods.length > 0
|
152
|
+
file.write(capture_methods.join "\n")
|
153
|
+
end
|
154
|
+
file.close
|
155
|
+
funclist_path
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative 'filtsymbols.rb'
|
2
|
+
|
3
|
+
class String
|
4
|
+
def upcase_first_letter
|
5
|
+
self.slice(0,1).capitalize + self.slice(1..-1)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Obscure
|
10
|
+
|
11
|
+
|
12
|
+
@@TABLENAME="symbols"
|
13
|
+
@@SYMBOL_DB_FILE="symbols"
|
14
|
+
@@STRING_SYMBOL_FILE="func.list"
|
15
|
+
|
16
|
+
#维护数据库方便日后作排重
|
17
|
+
def self.createTable
|
18
|
+
if !File.exist? @@SYMBOL_DB_FILE
|
19
|
+
`echo "create table #{@@TABLENAME}(src text, des text,PRIMARY KEY (src));" | sqlite3 #{@@SYMBOL_DB_FILE}`
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.insertValue(line,ramdom)
|
24
|
+
`echo "insert or ignore into #{@@TABLENAME} values('#{line}' ,'#{ramdom}');" | sqlite3 #{@@SYMBOL_DB_FILE}`
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.query(line)
|
28
|
+
`echo "select * from #{@@TABLENAME} where src='#{line}';" | sqlite3 #{@@SYMBOL_DB_FILE}`
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.ramdomString
|
32
|
+
`openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16`
|
33
|
+
end
|
34
|
+
|
35
|
+
#有define重复的问题等待解决
|
36
|
+
def self.run(root_dir)
|
37
|
+
|
38
|
+
@@HEAD_FILE="#{root_dir}/codeObfuscation.h"
|
39
|
+
@@SYMBOL_DB_FILE = "#{root_dir}/#{@@SYMBOL_DB_FILE}"
|
40
|
+
@@STRING_SYMBOL_FILE = "#{root_dir}/#{@@STRING_SYMBOL_FILE}"
|
41
|
+
|
42
|
+
if File.exist? @@SYMBOL_DB_FILE
|
43
|
+
`rm -f #{@@SYMBOL_DB_FILE}`
|
44
|
+
end
|
45
|
+
if File.exists? @@HEAD_FILE
|
46
|
+
`rm -f #{@@HEAD_FILE}`
|
47
|
+
end
|
48
|
+
createTable
|
49
|
+
|
50
|
+
date = `date`
|
51
|
+
file = File.new @@HEAD_FILE , 'w'
|
52
|
+
file.puts "#ifndef co_codeObfuscation_h"
|
53
|
+
file.puts "#define co_codeObfuscation_h"
|
54
|
+
file.puts "//confuse string at #{date.to_s}"
|
55
|
+
|
56
|
+
symbol_file = File.open(@@STRING_SYMBOL_FILE).read
|
57
|
+
symbol_file.each_line do |line|
|
58
|
+
line_type = line.rstrip.split(":").first
|
59
|
+
line_content = line.rstrip.split(":").last
|
60
|
+
result = FiltSymbols.query(line_content)
|
61
|
+
if result.nil? || result.empty?
|
62
|
+
ramdom = ramdomString
|
63
|
+
insertValue line_content , ramdom
|
64
|
+
if line_type == "p"
|
65
|
+
result = FiltSymbols.query("set#{line_content.upcase_first_letter}")
|
66
|
+
if result.nil? || result.empty?
|
67
|
+
file.puts "#define #{line_content} #{ramdom}"
|
68
|
+
file.puts "#define _#{line_content} _#{ramdom}"
|
69
|
+
file.puts "#define set#{line_content.upcase_first_letter} set#{ramdom.upcase_first_letter}"
|
70
|
+
end
|
71
|
+
else
|
72
|
+
file.puts "#define #{line_content} #{ramdom}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
file.puts "#endif"
|
78
|
+
file.close
|
79
|
+
|
80
|
+
`sqlite3 #{@@SYMBOL_DB_FILE} .dump`
|
81
|
+
if File.exist? @@SYMBOL_DB_FILE
|
82
|
+
`rm -f #{@@SYMBOL_DB_FILE}`
|
83
|
+
end
|
84
|
+
if File.exist? @@STRING_SYMBOL_FILE
|
85
|
+
`rm -f #{@@STRING_SYMBOL_FILE}`
|
86
|
+
end
|
87
|
+
@@HEAD_FILE
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CodeobscureTest < Minitest::Test
|
4
|
+
def test_that_it_has_a_version_number
|
5
|
+
refute_nil ::Codeobscure::VERSION
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_it_funclist_capture
|
9
|
+
result = FuncList.capture '+ (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view'
|
10
|
+
#因为没有去重
|
11
|
+
assert_equal result , ['f:pickerView','f:viewForRow','f:forComponent','f:reusingView','f:pickerView']
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_it_funclist_genFuncList
|
15
|
+
test_dir = "#{File.dirname(__FILE__)}/objcTemple"
|
16
|
+
funclist_path = "#{test_dir}/func.list"
|
17
|
+
if File.exist? funclist_path
|
18
|
+
File.delete funclist_path
|
19
|
+
end
|
20
|
+
FuncList.genFuncList(test_dir)
|
21
|
+
is_exist = File.exist? funclist_path
|
22
|
+
assert is_exist , "generate func.list file failed"
|
23
|
+
|
24
|
+
content = File.read funclist_path
|
25
|
+
puts "=========#{content.split "\n"}"
|
26
|
+
expect_result = "f:addItem\nf:getClusters\nf:getRectWithPt\nf:Span\nf:getDistanceSquared\nf:point\nf:clearItems\nc:BMKClusterAlgorithm"
|
27
|
+
assert_equal expect_result , content
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_it_obscure_run
|
31
|
+
test_dir = "#{File.dirname(__FILE__)}/objcTemple"
|
32
|
+
FuncList.genFuncList(test_dir)
|
33
|
+
path = "#{test_dir}/codeObfuscation.h"
|
34
|
+
if File.exist? path
|
35
|
+
File.delete path
|
36
|
+
end
|
37
|
+
Obscure.run test_dir
|
38
|
+
is_exist = File.exist? path
|
39
|
+
assert is_exist , "generate codeObfuscation.h failed"
|
40
|
+
end
|
41
|
+
|
42
|
+
#def test_it_filtsymbols_load
|
43
|
+
#test_dir = "#{File.dirname(__FILE__)}/objcTemple"
|
44
|
+
#FiltSymbols.loadFiltSymbols test_dir
|
45
|
+
#path = "#{File.expand_path '../..', __FILE__}/filtSymbols"
|
46
|
+
#is_exist = File.exist? path
|
47
|
+
#assert is_exist , "generate filtSymbols failed"
|
48
|
+
#end
|
49
|
+
|
50
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: codeobscure
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kaich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-02 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.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
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: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: colorize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.7'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.7.7
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0.7'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.7.7
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: xcodeproj
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.0.0
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.0.0
|
89
|
+
description: Code Obscure Tool.You can use it simplely
|
90
|
+
email:
|
91
|
+
- chengkai1853@163.com
|
92
|
+
executables:
|
93
|
+
- codeobscure
|
94
|
+
extensions: []
|
95
|
+
extra_rdoc_files: []
|
96
|
+
files:
|
97
|
+
- bin/codeobscure
|
98
|
+
- filtSymbols
|
99
|
+
- filtSymbols_standard
|
100
|
+
- lib/codeobscure.rb
|
101
|
+
- lib/codeobscure/filtsymbols.rb
|
102
|
+
- lib/codeobscure/funclist.rb
|
103
|
+
- lib/codeobscure/obscure.rb
|
104
|
+
- lib/codeobscure/version.rb
|
105
|
+
- test/codeobscure_test.rb
|
106
|
+
- test/test_helper.rb
|
107
|
+
homepage: https://github.com/kaich/codeobscure
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata:
|
111
|
+
allowed_push_host: https://rubygems.org
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
- bin
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.4.5
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Code Obscure For Xcode Project
|
133
|
+
test_files:
|
134
|
+
- test/codeobscure_test.rb
|
135
|
+
- test/test_helper.rb
|