iterationlabs-my_obfuscate 0.3.3 → 0.3.4
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/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