dbd/common.c

1
#include <dbd/common.h>
2
 
3
const char *strlower(char *in) {
4
    char *s = in;
5
 
6
    while(*s) {
7
	*s= (*s <= 'Z' && *s >= 'A') ? (*s - 'A') + 'a' : *s;
8
	s++;
9
    }
10
 
11
    return in;
12
}
13
 
14
/*
15
 * replace '?' placeholders with {native_prefix}\d+ placeholders
16
 * to be compatible with native API
17
 */
18
char *replace_placeholders(lua_State *L, char native_prefix, const char *sql) {
19
    size_t len = strlen(sql);
20
    int num_placeholders = 0;
21
    int extra_space = 0;
22
    int i;
23
    char *newsql;
24
    int newpos = 1;
25
    int ph_num = 1;
26
    int in_quote = 0;
27
    char format_str[4];
28
 
29
    format_str[0] = native_prefix;
30
    format_str[1] = '%';
31
    format_str[2] = 'u';
32
    format_str[3] = '\0';
33
 
34
    /*
35
     * dumb count of all '?'
36
     * this will match more placeholders than necessesary
37
     * but it's safer to allocate more placeholders at the
38
     * cost of a few bytes than risk a buffer overflow
39
     */ 
40
    for (i = 1; i < len; i++) {
41
	if (sql[i] == '?') {
42
	    num_placeholders++;
43
	}
44
    }
45
    
46
    /*
47
     * this is MAX_PLACEHOLDER_SIZE-1 because the '?' is 
48
     * replaced with '{native_prefix}'
49
     */ 
50
    extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1); 
51
 
52
    /*
53
     * allocate a new string for the converted SQL statement
54
     */
55
    newsql = malloc(sizeof(char) * (len+extra_space+1));
56
    memset(newsql, 0, sizeof(char) * (len+extra_space+1));
57
    
58
    /* 
59
     * copy first char. In valid SQL this cannot be a placeholder
60
     */
61
    newsql[0] = sql[0];
62
 
63
    /* 
64
     * only replace '?' not in a single quoted string
65
     */
66
    for (i = 1; i < len; i++) {
67
	/*
68
	 * don't change the quote flag if the ''' is preceded 
69
	 * by a '\' to account for escaping
70
	 */
71
	if (sql[i] == '\'' && sql[i-1] != '\\') {
72
	    in_quote = !in_quote;
73
	}
74
 
75
	if (sql[i] == '?' && !in_quote) {
76
	    size_t n;
77
 
78
	    if (ph_num > MAX_PLACEHOLDERS) {
79
		luaL_error(L, "Sorry, you are using more than %d placeholders. Use %c{num} format instead", MAX_PLACEHOLDERS, native_prefix);
80
	    }
81
 
82
	    n = snprintf(&newsql[newpos], MAX_PLACEHOLDER_SIZE, format_str, ph_num++);
83
 
84
	    newpos += n;
85
	} else {
86
	    newsql[newpos] = sql[i];
87
	    newpos++;
88
	}
89
    }
90
 
91
    /* 
92
     * terminate string on the last position 
93
     */
94
    newsql[newpos] = '\0';
95
 
96
    /* fprintf(stderr, "[%s]\n", newsql); */
97
    return newsql;
98
}