my_obfuscate 0.4.2 → 0.5.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.
- data/CHANGES +1 -0
- data/Gemfile +2 -0
- data/README.rdoc +6 -0
- data/lib/my_obfuscate/config_applicator.rb +146 -0
- data/lib/my_obfuscate/copy_statement_parser.rb +45 -0
- data/lib/my_obfuscate/insert_statement_parser.rb +22 -0
- data/lib/my_obfuscate/mysql.rb +76 -2
- data/lib/my_obfuscate/postgres.rb +37 -7
- data/lib/my_obfuscate/sql_server.rb +6 -1
- data/lib/my_obfuscate/version.rb +1 -1
- data/lib/my_obfuscate.rb +7 -163
- data/spec/my_obfuscate/config_applicator_spec.rb +276 -0
- data/spec/my_obfuscate/mysql_spec.rb +59 -2
- data/spec/my_obfuscate/postgres_spec.rb +30 -10
- data/spec/my_obfuscate_spec.rb +67 -253
- metadata +13 -5
- data/lib/my_obfuscate/database_helper_shared.rb +0 -76
- data/spec/my_obfuscate/database_helper_shared_examples.rb +0 -63
data/spec/my_obfuscate_spec.rb
CHANGED
@@ -23,259 +23,91 @@ describe MyObfuscate do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
describe "
|
27
|
-
it "should work on email addresses" do
|
28
|
-
100.times do
|
29
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else"], {:a => {:type => :email}}, [:a, :b])
|
30
|
-
new_row.length.should == 2
|
31
|
-
new_row.first.should =~ /^[\w\.]+\@(\w+\.){2,3}[a-f0-9]{5}\.example\.com$/
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should work on strings" do
|
36
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "something crazy"], {:b => {:type => :string, :length => 7}}, [:a, :b, :c])
|
37
|
-
new_row.length.should == 3
|
38
|
-
new_row[1].length.should == 7
|
39
|
-
new_row[1].should_not == "something_else"
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "conditional directives" do
|
43
|
-
it "should honor :unless conditionals" do
|
44
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :unless => lambda { |row| row[:a] == "blah" }}}, [:a, :b, :c])
|
45
|
-
new_row[0].should_not == "123"
|
46
|
-
new_row[0].should == "blah"
|
47
|
-
|
48
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :unless => lambda { |row| row[:a] == "not blah" }}}, [:a, :b, :c])
|
49
|
-
new_row[0].should == "123"
|
50
|
-
|
51
|
-
new_row = MyObfuscate.apply_table_config([nil, "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :unless => :nil}, :b=> {:type => :fixed, :string => "123", :unless => :nil}}, [:a, :b, :c])
|
52
|
-
new_row[0].should == nil
|
53
|
-
new_row[1].should == "123"
|
26
|
+
describe "#obfuscate" do
|
54
27
|
|
55
|
-
|
56
|
-
|
57
|
-
|
28
|
+
describe "when using Postgres" do
|
29
|
+
let(:dump) do
|
30
|
+
StringIO.new(<<-SQL)
|
31
|
+
COPY some_table (id, email, name, something, age) FROM stdin;
|
32
|
+
1 hello monkey moose 14
|
33
|
+
\.
|
34
|
+
|
35
|
+
COPY single_column_table (id) FROM stdin;
|
36
|
+
1
|
37
|
+
2
|
38
|
+
\\N
|
39
|
+
\.
|
40
|
+
|
41
|
+
COPY another_table (a, b, c, d) FROM stdin;
|
42
|
+
1 2 3 4
|
43
|
+
1 2 3 4
|
44
|
+
\.
|
45
|
+
|
46
|
+
COPY some_table_to_keep (a, b) FROM stdin;
|
47
|
+
5 6
|
48
|
+
\.
|
49
|
+
SQL
|
58
50
|
end
|
59
51
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
52
|
+
let(:obfuscator) do
|
53
|
+
MyObfuscate.new({
|
54
|
+
:some_table => {
|
55
|
+
:email => {:type => :email, :skip_regexes => [/^[\w\.\_]+@honk\.com$/i, /^dontmurderme@direwolf.com$/]},
|
56
|
+
:name => {:type => :string, :length => 8, :chars => MyObfuscate::USERNAME_CHARS},
|
57
|
+
:age => {:type => :integer, :between => 10...80, :unless => :nil },
|
58
|
+
},
|
59
|
+
:single_column_table => {
|
60
|
+
:id => {:type => :integer, :between => 1...8, :unless => :nil}
|
61
|
+
},
|
62
|
+
:another_table => :truncate,
|
63
|
+
:some_table_to_keep => :keep
|
64
|
+
}).tap do |obfuscator|
|
65
|
+
obfuscator.database_type = :postgres
|
66
|
+
end
|
75
67
|
end
|
76
68
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
69
|
+
let(:output_string) do
|
70
|
+
output = StringIO.new
|
71
|
+
obfuscator.obfuscate(dump, output)
|
72
|
+
output.rewind
|
73
|
+
output.read
|
81
74
|
end
|
82
75
|
|
83
|
-
it "
|
84
|
-
|
85
|
-
|
86
|
-
new_row[0].should == "blah"
|
87
|
-
|
88
|
-
#both false
|
89
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :if => lambda { |row| row[:a] == "not blah" }, :unless => lambda { |row| row[:b] == "not something_else" }}}, [:a, :b, :c])
|
90
|
-
new_row[0].should == "blah"
|
91
|
-
|
92
|
-
#if true, #unless false
|
93
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :if => lambda { |row| row[:a] == "blah" }, :unless => lambda { |row| row[:b] == "not something_else" }}}, [:a, :b, :c])
|
94
|
-
new_row[0].should == "123"
|
95
|
-
|
96
|
-
#if false, #unless true
|
97
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a=> {:type => :fixed, :string => "123", :if => lambda { |row| row[:a] == "not blah" }, :unless => lambda { |row| row[:b] == "something_else" }}}, [:a, :b, :c])
|
98
|
-
new_row[0].should == "blah"
|
76
|
+
it "is able to obfuscate single column tables" do
|
77
|
+
output_string.should_not include("1\n2\n")
|
78
|
+
output_string.should match(/\d\n\d\n/)
|
99
79
|
end
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should be able to generate random integers in ranges" do
|
103
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:c => {:type => :integer, :between => 10..100}}, [:a, :b, :c])
|
104
|
-
new_row.length.should == 3
|
105
|
-
new_row[2].to_i.to_s.should == new_row[2] # It should be an integer.
|
106
|
-
new_row[2].should_not == "5"
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should be able to substitute fixed strings" do
|
110
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => {:type => :fixed, :string => "hello"}}, [:a, :b, :c])
|
111
|
-
new_row.length.should == 3
|
112
|
-
new_row[1].should == "hello"
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should be able to substitute a proc that returns a string" do
|
116
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => {:type => :fixed, :string => proc { "Hello World" }}}, [:a, :b, :c])
|
117
|
-
new_row.length.should == 3
|
118
|
-
new_row[1].should == "Hello World"
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should provide the row to the proc" do
|
122
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => {:type => :fixed, :string => proc { |a| a[:b] }}}, [:a, :b, :c])
|
123
|
-
new_row.length.should == 3
|
124
|
-
new_row[1].should == "something_else"
|
125
|
-
end
|
126
80
|
|
127
|
-
|
128
|
-
|
129
|
-
original_looking_for = looking_for.dup
|
130
|
-
guard = 0
|
131
|
-
while !looking_for.empty? && guard < 1000
|
132
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => {:type => :fixed, :one_of => ["hello", "world"]}}, [:a, :b, :c])
|
133
|
-
new_row.length.should == 3
|
134
|
-
original_looking_for.should include(new_row[0])
|
135
|
-
looking_for.delete new_row[0]
|
136
|
-
guard += 1
|
81
|
+
it "is able to truncate tables" do
|
82
|
+
output_string.should_not include("1\t2\t3\t4")
|
137
83
|
end
|
138
|
-
looking_for.should be_empty
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should treat a symbol in the column definition as an implicit { :type => symbol }" do
|
142
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => :null, :a => :keep}, [:a, :b, :c])
|
143
|
-
new_row.length.should == 3
|
144
|
-
new_row[0].should == "blah"
|
145
|
-
new_row[1].should == nil
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should be able to set things NULL" do
|
149
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => {:type => :null}}, [:a, :b, :c])
|
150
|
-
new_row.length.should == 3
|
151
|
-
new_row[1].should == nil
|
152
|
-
end
|
153
84
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should keep the value when given an unknown type, but should display a warning" do
|
161
|
-
$stderr = error_output = StringIO.new
|
162
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:b => {:type => :unknown_type}}, [:a, :b, :c])
|
163
|
-
$stderr = STDERR
|
164
|
-
new_row.length.should == 3
|
165
|
-
new_row[1].should == "something_else"
|
166
|
-
error_output.rewind
|
167
|
-
error_output.read.should =~ /Keeping a column value by.*?unknown_type/
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should be able to substitute lorem ipsum text" do
|
171
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :lorem, :b => {:type => :lorem, :number => 2}}, [:a, :b, :c])
|
172
|
-
new_row.length.should == 3
|
173
|
-
new_row[0].should_not == "blah"
|
174
|
-
new_row[0].should_not =~ /\w\.(?!\Z)/
|
175
|
-
new_row[1].should_not == "something_else"
|
176
|
-
new_row[1].should =~ /\w\.(?!\Z)/
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should be able to generate an :company" do
|
180
|
-
new_row = MyObfuscate.apply_table_config(["Smith and Sons", "something_else", "5"], {:a => :company}, [:a, :b, :c])
|
181
|
-
new_row.length.should == 3
|
182
|
-
new_row[0].should_not == "Smith and Sons"
|
183
|
-
new_row[0].should =~ /\w+/
|
184
|
-
end
|
185
|
-
|
186
|
-
it "should be able to generate an :url" do
|
187
|
-
new_row = MyObfuscate.apply_table_config(["http://mystuff.blogger.com", "something_else", "5"], {:a => :url}, [:a, :b, :c])
|
188
|
-
new_row.length.should == 3
|
189
|
-
new_row[0].should_not == "http://mystuff.blogger.com"
|
190
|
-
new_row[0].should =~ /http:\/\/\w+/
|
191
|
-
end
|
192
|
-
|
193
|
-
it "should be able to generate an :ipv4" do
|
194
|
-
new_row = MyObfuscate.apply_table_config(["1.2.3.4", "something_else", "5"], {:a => :ipv4}, [:a, :b, :c])
|
195
|
-
new_row.length.should == 3
|
196
|
-
new_row[0].should_not == "1.2.3.4"
|
197
|
-
new_row[0].should =~ /\d+\.\d+\.\d+\.\d+/
|
198
|
-
end
|
199
|
-
|
200
|
-
it "should be able to generate an :ipv6" do
|
201
|
-
new_row = MyObfuscate.apply_table_config(["fe80:0000:0000:0000:0202:b3ff:fe1e:8329", "something_else", "5"], {:a => :ipv6}, [:a, :b, :c])
|
202
|
-
new_row.length.should == 3
|
203
|
-
new_row[0].should_not == "fe80:0000:0000:0000:0202:b3ff:fe1e:8329"
|
204
|
-
new_row[0].should =~ /[0-9a-f:]+/
|
205
|
-
end
|
206
|
-
|
207
|
-
it "should be able to generate an :address" do
|
208
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :address}, [:a, :b, :c])
|
209
|
-
new_row.length.should == 3
|
210
|
-
new_row[0].should_not == "blah"
|
211
|
-
new_row[0].should =~ /\d+ \w/
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should be able to generate a :name" do
|
215
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :name}, [:a, :b, :c])
|
216
|
-
new_row.length.should == 3
|
217
|
-
new_row[0].should_not == "blah"
|
218
|
-
new_row[0].should =~ / /
|
219
|
-
end
|
220
|
-
|
221
|
-
it "should be able to generate just a street address" do
|
222
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :street_address}, [:a, :b, :c])
|
223
|
-
new_row.length.should == 3
|
224
|
-
new_row[0].should_not == "blah"
|
225
|
-
new_row[0].should =~ /\d+ \w/
|
226
|
-
end
|
227
|
-
|
228
|
-
it "should be able to generate a city" do
|
229
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :city}, [:a, :b, :c])
|
230
|
-
new_row.length.should == 3
|
231
|
-
new_row[0].should_not == "blah"
|
232
|
-
end
|
233
|
-
|
234
|
-
it "should be able to generate a state" do
|
235
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :state}, [:a, :b, :c])
|
236
|
-
new_row.length.should == 3
|
237
|
-
new_row[0].should_not == "blah"
|
238
|
-
end
|
239
|
-
|
240
|
-
it "should be able to generate a zip code" do
|
241
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :zip_code}, [:a, :b, :c])
|
242
|
-
new_row.length.should == 3
|
243
|
-
new_row[0].should_not == "blah"
|
244
|
-
new_row[0].should =~ /\d+/
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should be able to generate a phone number" do
|
248
|
-
new_row = MyObfuscate.apply_table_config(["blah", "something_else", "5"], {:a => :phone}, [:a, :b, :c])
|
249
|
-
new_row.length.should == 3
|
250
|
-
new_row[0].should_not == "blah"
|
251
|
-
new_row[0].should =~ /\d+/
|
252
|
-
end
|
85
|
+
it "can obfuscate the tables" do
|
86
|
+
output_string.should include("COPY some_table (id, email, name, something, age) FROM stdin;\n")
|
87
|
+
output_string.should match(/1\t.*\t\S{8}\tmoose\t\d{2}\n/)
|
88
|
+
end
|
253
89
|
|
254
|
-
|
255
|
-
|
256
|
-
Faker::Address.stub(:city).and_return("O'ReillyTown")
|
257
|
-
Faker::Name.stub(:name).and_return("Foo O'Reilly")
|
258
|
-
Faker::Name.stub(:first_name).and_return("O'Foo")
|
259
|
-
Faker::Name.stub(:last_name).and_return("O'Reilly")
|
260
|
-
Faker::Lorem.stub(:sentences).with(any_args).and_return(["Foo bar O'Thingy"])
|
90
|
+
it "can skip nils" do
|
91
|
+
output_string.should match(/\d\n\d\n\\N/)
|
261
92
|
end
|
262
93
|
|
263
|
-
it "
|
264
|
-
|
265
|
-
{:a => :address, :b => :city, :c => :first_name, :d => :last_name, :e => :name, :f => :lorem},
|
266
|
-
[:a, :b, :c, :d, :e, :f])
|
267
|
-
new_row.each {|value| value.should_not include("'")}
|
94
|
+
it "is able to keep tables" do
|
95
|
+
output_string.should include("5\t6")
|
268
96
|
end
|
269
|
-
end
|
270
|
-
end
|
271
97
|
|
272
|
-
|
273
|
-
|
274
|
-
|
98
|
+
context "when dump contains INSERT statement" do
|
99
|
+
let(:dump) do
|
100
|
+
StringIO.new(<<-SQL)
|
101
|
+
INSERT INTO some_table (email, name, something, age) VALUES ('','', '', 25);
|
102
|
+
SQL
|
103
|
+
end
|
104
|
+
|
105
|
+
it "raises an error if using postgres with insert statements" do
|
106
|
+
expect { output_string }.to raise_error RuntimeError
|
107
|
+
end
|
108
|
+
end
|
275
109
|
end
|
276
|
-
end
|
277
110
|
|
278
|
-
describe "#obfuscate" do
|
279
111
|
describe "when using MySQL" do
|
280
112
|
context "when there is nothing to obfuscate" do
|
281
113
|
it "should accept an IO object for input and output, and copy the input to the output" do
|
@@ -560,22 +392,4 @@ describe MyObfuscate do
|
|
560
392
|
end
|
561
393
|
end
|
562
394
|
|
563
|
-
describe "MyObfuscate.random_english_sentences" do
|
564
|
-
before do
|
565
|
-
File.should_receive(:read).once.and_return("hello 2")
|
566
|
-
end
|
567
|
-
|
568
|
-
after do
|
569
|
-
MyObfuscate.class_variable_set(:@@walker_method, nil)
|
570
|
-
end
|
571
|
-
|
572
|
-
it "should only load file data once" do
|
573
|
-
MyObfuscate.random_english_sentences(1)
|
574
|
-
MyObfuscate.random_english_sentences(1)
|
575
|
-
end
|
576
|
-
|
577
|
-
it "should make random sentences" do
|
578
|
-
MyObfuscate.random_english_sentences(2).should =~ /^(Hello( hello)+\.\s*){2}$/
|
579
|
-
end
|
580
|
-
end
|
581
395
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: my_obfuscate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2013-
|
17
|
+
date: 2013-07-17 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: ffaker
|
@@ -81,14 +81,16 @@ files:
|
|
81
81
|
- README.rdoc
|
82
82
|
- Rakefile
|
83
83
|
- lib/my_obfuscate.rb
|
84
|
+
- lib/my_obfuscate/config_applicator.rb
|
85
|
+
- lib/my_obfuscate/copy_statement_parser.rb
|
84
86
|
- lib/my_obfuscate/data/en_50K.txt
|
85
|
-
- lib/my_obfuscate/
|
87
|
+
- lib/my_obfuscate/insert_statement_parser.rb
|
86
88
|
- lib/my_obfuscate/mysql.rb
|
87
89
|
- lib/my_obfuscate/postgres.rb
|
88
90
|
- lib/my_obfuscate/sql_server.rb
|
89
91
|
- lib/my_obfuscate/version.rb
|
90
92
|
- my_obfuscate.gemspec
|
91
|
-
- spec/my_obfuscate/
|
93
|
+
- spec/my_obfuscate/config_applicator_spec.rb
|
92
94
|
- spec/my_obfuscate/mysql_spec.rb
|
93
95
|
- spec/my_obfuscate/postgres_spec.rb
|
94
96
|
- spec/my_obfuscate/sql_server_spec.rb
|
@@ -106,12 +108,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
108
|
- - ! '>='
|
107
109
|
- !ruby/object:Gem::Version
|
108
110
|
version: '0'
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
hash: -3837317956098697569
|
109
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
115
|
none: false
|
111
116
|
requirements:
|
112
117
|
- - ! '>='
|
113
118
|
- !ruby/object:Gem::Version
|
114
119
|
version: '0'
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
hash: -3837317956098697569
|
115
123
|
requirements: []
|
116
124
|
rubyforge_project:
|
117
125
|
rubygems_version: 1.8.25
|
@@ -120,7 +128,7 @@ specification_version: 3
|
|
120
128
|
summary: Standalone Ruby code for the selective rewriting of MySQL dumps in order
|
121
129
|
to protect user privacy.
|
122
130
|
test_files:
|
123
|
-
- spec/my_obfuscate/
|
131
|
+
- spec/my_obfuscate/config_applicator_spec.rb
|
124
132
|
- spec/my_obfuscate/mysql_spec.rb
|
125
133
|
- spec/my_obfuscate/postgres_spec.rb
|
126
134
|
- spec/my_obfuscate/sql_server_spec.rb
|
@@ -1,76 +0,0 @@
|
|
1
|
-
class MyObfuscate
|
2
|
-
module DatabaseHelperShared
|
3
|
-
|
4
|
-
def rows_to_be_inserted(line)
|
5
|
-
line = line.gsub(insert_regex, '').gsub(/\s*;\s*$/, '')
|
6
|
-
context_aware_mysql_string_split(line)
|
7
|
-
end
|
8
|
-
|
9
|
-
def make_valid_value_string(value)
|
10
|
-
if value.nil?
|
11
|
-
"NULL"
|
12
|
-
elsif value =~ /^0x[0-9a-fA-F]+$/
|
13
|
-
value
|
14
|
-
else
|
15
|
-
"'" + value + "'"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# Be aware, strings must be quoted in single quotes!
|
20
|
-
def context_aware_mysql_string_split(string)
|
21
|
-
in_sub_insert = false
|
22
|
-
in_quoted_string = false
|
23
|
-
escaped = false
|
24
|
-
current_field = nil
|
25
|
-
length = string.length
|
26
|
-
fields = []
|
27
|
-
output = []
|
28
|
-
|
29
|
-
string.each_char do |i|
|
30
|
-
if escaped
|
31
|
-
escaped = false
|
32
|
-
current_field ||= ""
|
33
|
-
current_field << i
|
34
|
-
else
|
35
|
-
if i == "\\"
|
36
|
-
escaped = true
|
37
|
-
current_field ||= ""
|
38
|
-
current_field << i
|
39
|
-
elsif i == "(" && !in_quoted_string && !in_sub_insert
|
40
|
-
in_sub_insert = true
|
41
|
-
elsif i == ")" && !in_quoted_string && in_sub_insert
|
42
|
-
fields << current_field unless current_field.nil?
|
43
|
-
output << fields unless fields.length == 0
|
44
|
-
in_sub_insert = false
|
45
|
-
fields = []
|
46
|
-
current_field = nil
|
47
|
-
elsif i == "'" && !in_quoted_string
|
48
|
-
fields << current_field unless current_field.nil?
|
49
|
-
current_field = ''
|
50
|
-
in_quoted_string = true
|
51
|
-
elsif i == "'" && in_quoted_string
|
52
|
-
fields << current_field unless current_field.nil?
|
53
|
-
current_field = nil
|
54
|
-
in_quoted_string = false
|
55
|
-
elsif i == "," && !in_quoted_string && in_sub_insert
|
56
|
-
fields << current_field unless current_field.nil?
|
57
|
-
current_field = nil
|
58
|
-
elsif i == "L" && !in_quoted_string && in_sub_insert && current_field == "NUL"
|
59
|
-
current_field = nil
|
60
|
-
fields << current_field
|
61
|
-
elsif (i == " " || i == "\t") && !in_quoted_string
|
62
|
-
# Don't add whitespace not in a string
|
63
|
-
elsif in_sub_insert
|
64
|
-
current_field ||= ""
|
65
|
-
current_field << i
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
fields << current_field unless current_field.nil?
|
71
|
-
output << fields unless fields.length == 0
|
72
|
-
output
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
shared_examples MyObfuscate::DatabaseHelperShared do
|
2
|
-
|
3
|
-
describe "#rows_to_be_inserted" do
|
4
|
-
it "should split a mysql string into fields" do
|
5
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES ('bob@bob.com','bob', 'somethingelse1', 25, '2', 10, 'hi') ; "
|
6
|
-
fields = [['bob@bob.com', 'bob', 'somethingelse1', '25', '2', '10', "hi"]]
|
7
|
-
subject.rows_to_be_inserted(string).should == fields
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should work ok with escaped characters" do
|
11
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES ('bob,@bob.c , om', 'bo\\', b', 'some\"thin\\gel\\\\\\'se1', 25, '2', 10, 'hi', 5) ; "
|
12
|
-
fields = [['bob,@bob.c , om', 'bo\\\', b', 'some"thin\\gel\\\\\\\'se1', '25', '2', '10', "hi", "5"]]
|
13
|
-
subject.rows_to_be_inserted(string).should == fields
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should work with multiple subinserts" do
|
17
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES (1,2,3, '((m))(oo()s,e'), ('bob,@bob.c , om', 'bo\\', b', 'some\"thin\\gel\\\\\\'se1', 25, '2', 10, 'hi', 5) ;"
|
18
|
-
fields = [["1", "2", "3", "((m))(oo()s,e"], ['bob,@bob.c , om', 'bo\\\', b', 'some"thin\\gel\\\\\\\'se1', '25', '2', '10', "hi", "5"]]
|
19
|
-
subject.rows_to_be_inserted(string).should == fields
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should work ok with NULL values" do
|
23
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES (NULL , 'bob@bob.com','bob', NULL, 25, '2', NULL, 'hi', NULL ); "
|
24
|
-
fields = [[nil, 'bob@bob.com', 'bob', nil, '25', '2', nil, "hi", nil]]
|
25
|
-
subject.rows_to_be_inserted(string).should == fields
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should work with empty strings" do
|
29
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES (NULL , '', '' , '', 25, '2','', 'hi','') ;"
|
30
|
-
fields = [[nil, '', '', '', '25', '2', '', "hi", '']]
|
31
|
-
subject.rows_to_be_inserted(string).should == fields
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should work with hex encoded blobs" do
|
35
|
-
string = "INSERT INTO `some_table` (thing1,thing2) VALUES ('bla' , 'blobdata', 'blubb' , 0xACED00057372001F6A6176612E7574696C2E436F6C6C656) ;"
|
36
|
-
fields = [['bla', 'blobdata', 'blubb', '0xACED00057372001F6A6176612E7574696C2E436F6C6C656']]
|
37
|
-
subject.rows_to_be_inserted(string).should == fields
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "#make_valid_value_string" do
|
42
|
-
it "should work with nil values" do
|
43
|
-
value = nil
|
44
|
-
subject.make_valid_value_string(value).should == 'NULL'
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should work with hex-encoded blob data" do
|
48
|
-
value = "0xACED00057372001F6A6176612E7574696C2E436F6C6C656"
|
49
|
-
subject.make_valid_value_string(value).should == '0xACED00057372001F6A6176612E7574696C2E436F6C6C656'
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should quote hex-encoded ALIKE data" do
|
53
|
-
value = "40x17x7"
|
54
|
-
subject.make_valid_value_string(value).should == "'40x17x7'"
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should quote all other values" do
|
58
|
-
value = "hello world"
|
59
|
-
subject.make_valid_value_string(value).should == "'hello world'"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|