1 /++
2 Escape special characters in MySQL strings.
3 
4 Note, it is strongly recommended to use prepared statements instead of relying
5 on manual escaping, as prepared statements are always safer, better and more
6 reliable (see `mysql.prepared`). But if you absolutely must escape manually,
7 the functionality is provided here.
8 +/
9 module mysql.escape;
10 
11 
12 /++
13 Simple escape function for dangerous SQL characters
14 
15 Params:
16 	input = string to escape
17 	buffer = buffer to use for the output
18 +/
19 void mysql_escape ( Buffer, Input ) ( Input input, Buffer buffer )
20 {
21 	import std.string : translate;
22 
23 	immutable string[dchar] transTable = [
24 		'\\' : "\\\\",
25 		'\'' : "\\'",
26 		'\0' : "\\0",
27 		'\n' : "\\n",
28 		'\r' : "\\r",
29 		'"'  : "\\\"",
30 		'\032' : "\\Z"
31 	];
32 
33 	translate(input, transTable, null, buffer);
34 }
35 
36 
37 /++
38 Struct to wrap around a string so it can be passed to formattedWrite and be
39 properly escaped all using the buffer that formattedWrite provides.
40 
41 Params:
42 	Input = (Template Param) Type of the input
43 +/
44 struct MysqlEscape ( Input )
45 {
46 	Input input;
47 
48 	const void toString ( scope void delegate(const(char)[]) sink )
49 	{
50 		struct SinkOutputRange
51 		{
52 			void put ( const(char)[] t ) { sink(t); }
53 		}
54 
55 		SinkOutputRange r;
56 		mysql_escape(input, r);
57 	}
58 }
59 
60 /++
61 Helper function to easily construct a escape wrapper struct
62 
63 Params:
64 	T = (Template Param) Type of the input
65 	input = Input to escape
66 +/
67 MysqlEscape!(T) mysqlEscape ( T ) ( T input )
68 {
69 	return MysqlEscape!(T)(input);
70 }
71 
72 @("mysqlEscape")
73 debug(MYSQLN_TESTS)
74 unittest
75 {
76 	import std.array : appender;
77 
78 	auto buf = appender!string();
79 
80 	import std.format : formattedWrite;
81 
82 	formattedWrite(buf, "%s, %s, %s, mkay?", 1, 2,
83 			mysqlEscape("\0, \r, \n, \", \\"));
84 
85 	assert(buf.data() == `1, 2, \0, \r, \n, \", \\, mkay?`);
86 }