iterationlabs-my_obfuscate 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -2
- data/lib/my_obfuscate/mysql.rb +73 -71
- data/lib/my_obfuscate/sql_server.rb +64 -62
- data/lib/my_obfuscate/version.rb +1 -1
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -49,8 +49,11 @@ Make an obfuscator.rb script:
|
|
49
49
|
obfuscator.obfuscate(STDIN, STDOUT)
|
50
50
|
|
51
51
|
And to get an obfuscated dump:
|
52
|
-
|
53
|
-
|
52
|
+
|
53
|
+
mysqldump -c --add-drop-table -u user -ppassword database | ruby obfuscator.rb > obfuscated_dump.sql
|
54
|
+
|
55
|
+
Note that the -c option on mysqldump is required to use my_obfuscator. If you get MySQL errors due to very long lines,
|
56
|
+
try some combination of `--max_allowed_packet=128M`, `--single-transaction`, `--skip-extended-insert`, and `--quick`.
|
54
57
|
|
55
58
|
== Database Server
|
56
59
|
|
data/lib/my_obfuscate/mysql.rb
CHANGED
@@ -1,87 +1,89 @@
|
|
1
|
-
class MyObfuscate
|
2
|
-
|
1
|
+
class MyObfuscate
|
2
|
+
class Mysql
|
3
|
+
INSERT_REGEX = /^\s*INSERT INTO `(.*?)` \((.*?)\) VALUES\s*/i
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def parse_insert_statement(line)
|
6
|
+
if regex_match = INSERT_REGEX.match(line)
|
7
|
+
{
|
8
|
+
:table_name => regex_match[1].to_sym,
|
9
|
+
:column_names => regex_match[2].split(/`\s*,\s*`/).map { |col| col.gsub('`', "").to_sym }
|
10
|
+
}
|
11
|
+
end
|
10
12
|
end
|
11
|
-
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def rows_to_be_inserted(line)
|
15
|
+
line = line.gsub(INSERT_REGEX, '').gsub(/\s*;\s*$/, '')
|
16
|
+
context_aware_mysql_string_split(line)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def make_valid_value_string(value)
|
20
|
+
if value.nil?
|
21
|
+
"NULL"
|
22
|
+
else
|
23
|
+
"'" + value + "'"
|
24
|
+
end
|
23
25
|
end
|
24
|
-
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
def make_insert_statement(table_name, column_names, values_strings)
|
28
|
+
"INSERT INTO `#{table_name}` (`#{column_names.join('`, `')}`) VALUES #{values_strings};"
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
+
private
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
33
|
+
# Be aware, strings must be quoted in single quotes!
|
34
|
+
def context_aware_mysql_string_split(string)
|
35
|
+
in_sub_insert = false
|
36
|
+
in_quoted_string = false
|
37
|
+
escaped = false
|
38
|
+
current_field = nil
|
39
|
+
length = string.length
|
40
|
+
fields = []
|
41
|
+
output = []
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
current_field ||= ""
|
46
|
-
current_field << i
|
47
|
-
else
|
48
|
-
if i == "\\"
|
49
|
-
escaped = true
|
50
|
-
current_field ||= ""
|
51
|
-
current_field << i
|
52
|
-
elsif i == "(" && !in_quoted_string && !in_sub_insert
|
53
|
-
in_sub_insert = true
|
54
|
-
elsif i == ")" && !in_quoted_string && in_sub_insert
|
55
|
-
fields << current_field unless current_field.nil?
|
56
|
-
output << fields unless fields.length == 0
|
57
|
-
in_sub_insert = false
|
58
|
-
fields = []
|
59
|
-
current_field = nil
|
60
|
-
elsif i == "'" && !in_quoted_string
|
61
|
-
fields << current_field unless current_field.nil?
|
62
|
-
current_field = ''
|
63
|
-
in_quoted_string = true
|
64
|
-
elsif i == "'" && in_quoted_string
|
65
|
-
fields << current_field unless current_field.nil?
|
66
|
-
current_field = nil
|
67
|
-
in_quoted_string = false
|
68
|
-
elsif i == "," && !in_quoted_string && in_sub_insert
|
69
|
-
fields << current_field unless current_field.nil?
|
70
|
-
current_field = nil
|
71
|
-
elsif i == "L" && !in_quoted_string && in_sub_insert && current_field == "NUL"
|
72
|
-
current_field = nil
|
73
|
-
fields << current_field
|
74
|
-
elsif (i == " " || i == "\t") && !in_quoted_string
|
75
|
-
# Don't add whitespace not in a string
|
76
|
-
elsif in_sub_insert
|
43
|
+
string.each_char do |i|
|
44
|
+
if escaped
|
45
|
+
escaped = false
|
77
46
|
current_field ||= ""
|
78
47
|
current_field << i
|
48
|
+
else
|
49
|
+
if i == "\\"
|
50
|
+
escaped = true
|
51
|
+
current_field ||= ""
|
52
|
+
current_field << i
|
53
|
+
elsif i == "(" && !in_quoted_string && !in_sub_insert
|
54
|
+
in_sub_insert = true
|
55
|
+
elsif i == ")" && !in_quoted_string && in_sub_insert
|
56
|
+
fields << current_field unless current_field.nil?
|
57
|
+
output << fields unless fields.length == 0
|
58
|
+
in_sub_insert = false
|
59
|
+
fields = []
|
60
|
+
current_field = nil
|
61
|
+
elsif i == "'" && !in_quoted_string
|
62
|
+
fields << current_field unless current_field.nil?
|
63
|
+
current_field = ''
|
64
|
+
in_quoted_string = true
|
65
|
+
elsif i == "'" && in_quoted_string
|
66
|
+
fields << current_field unless current_field.nil?
|
67
|
+
current_field = nil
|
68
|
+
in_quoted_string = false
|
69
|
+
elsif i == "," && !in_quoted_string && in_sub_insert
|
70
|
+
fields << current_field unless current_field.nil?
|
71
|
+
current_field = nil
|
72
|
+
elsif i == "L" && !in_quoted_string && in_sub_insert && current_field == "NUL"
|
73
|
+
current_field = nil
|
74
|
+
fields << current_field
|
75
|
+
elsif (i == " " || i == "\t") && !in_quoted_string
|
76
|
+
# Don't add whitespace not in a string
|
77
|
+
elsif in_sub_insert
|
78
|
+
current_field ||= ""
|
79
|
+
current_field << i
|
80
|
+
end
|
79
81
|
end
|
80
82
|
end
|
81
|
-
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
fields << current_field unless current_field.nil?
|
85
|
+
output << fields unless fields.length == 0
|
86
|
+
output
|
87
|
+
end
|
86
88
|
end
|
87
89
|
end
|
@@ -1,79 +1,81 @@
|
|
1
|
-
class MyObfuscate
|
2
|
-
|
1
|
+
class MyObfuscate
|
2
|
+
class SqlServer
|
3
|
+
INSERT_REGEX = /^\s*INSERT (?:INTO )?\[dbo\]\.\[(.*?)\] \((.*?)\) VALUES\s*/i
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def parse_insert_statement(line)
|
6
|
+
if regex_match = INSERT_REGEX.match(line)
|
7
|
+
{
|
8
|
+
:table_name => regex_match[1].to_sym,
|
9
|
+
:column_names => regex_match[2].split(/\]\s*,\s*\[/).map { |col| col.gsub(/[\[\]]/, "").to_sym }
|
10
|
+
}
|
11
|
+
end
|
10
12
|
end
|
11
|
-
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
def rows_to_be_inserted(line)
|
15
|
+
line = line.gsub(INSERT_REGEX, '').gsub(/\s*;?\s*$/, '').gsub(/^\(/, '').gsub(/\)$/, '')
|
16
|
+
context_aware_sql_server_string_split(line)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def make_valid_value_string(value)
|
20
|
+
if value.nil?
|
21
|
+
"NULL"
|
22
|
+
elsif value.match(/^[A-Z]+\(.*?\)$/)
|
23
|
+
value
|
24
|
+
else
|
25
|
+
"N'#{value}'"
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def make_insert_statement(table_name, column_names, values_strings)
|
30
|
+
"INSERT [dbo].[#{table_name}] ([#{column_names.join("], [")}]) VALUES #{values_strings};"
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
+
private
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def context_aware_sql_server_string_split(string)
|
36
|
+
in_quoted_string = false
|
37
|
+
backslash_escape = false
|
38
|
+
previous_char_single_quote = false
|
39
|
+
current_field_value = nil
|
40
|
+
completed_fields = []
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
string.each_char do |char|
|
43
|
+
if char == "'" && !in_quoted_string
|
44
|
+
if current_field_value != "N"
|
45
|
+
completed_fields << current_field_value unless current_field_value.nil?
|
46
|
+
end
|
47
|
+
current_field_value = ""
|
48
|
+
in_quoted_string = true
|
49
|
+
elsif previous_char_single_quote
|
50
|
+
previous_char_single_quote = false
|
51
|
+
if char == "'"
|
52
|
+
current_field_value << "''"
|
53
|
+
else
|
54
|
+
completed_fields << current_field_value unless current_field_value.nil?
|
55
|
+
in_quoted_string = false
|
56
|
+
current_field_value = nil
|
57
|
+
end
|
58
|
+
elsif char == "'" && in_quoted_string
|
59
|
+
previous_char_single_quote = true
|
60
|
+
elsif char == "," && !in_quoted_string
|
44
61
|
completed_fields << current_field_value unless current_field_value.nil?
|
45
|
-
end
|
46
|
-
current_field_value = ""
|
47
|
-
in_quoted_string = true
|
48
|
-
elsif previous_char_single_quote
|
49
|
-
previous_char_single_quote = false
|
50
|
-
if char == "'"
|
51
|
-
current_field_value << "''"
|
52
|
-
else
|
53
|
-
completed_fields << current_field_value unless current_field_value.nil?
|
54
|
-
in_quoted_string = false
|
55
62
|
current_field_value = nil
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
if !current_field_value.nil? && current_field_value.start_with?("CAST(")
|
63
|
+
elsif char == "L" && !in_quoted_string && current_field_value == "NUL"
|
64
|
+
current_field_value = nil
|
65
|
+
completed_fields << current_field_value
|
66
|
+
elsif (char == " " || char == "\t") && !in_quoted_string
|
67
|
+
if !current_field_value.nil? && current_field_value.start_with?("CAST(")
|
68
|
+
current_field_value << char
|
69
|
+
end
|
70
|
+
# Don't add whitespace not in a string
|
71
|
+
else
|
72
|
+
current_field_value ||= ""
|
67
73
|
current_field_value << char
|
68
74
|
end
|
69
|
-
# Don't add whitespace not in a string
|
70
|
-
else
|
71
|
-
current_field_value ||= ""
|
72
|
-
current_field_value << char
|
73
75
|
end
|
74
|
-
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
completed_fields << current_field_value unless current_field_value.nil?
|
78
|
+
[completed_fields]
|
79
|
+
end
|
78
80
|
end
|
79
81
|
end
|
data/lib/my_obfuscate/version.rb
CHANGED