1 /**********************************************************************
2 * perditionb_mysql.c December 1999
3 * Horms horms@verge.net.au
4 *
5 * Access a MySQL database
6 *
7 * Adapted from code contributed by:
8 * Frederic Delchambre October 1999
9 * N.T.S. / Freegates dedel@freegates.be
10 * http://www.freegates.be/
11 * http://www.nts.be/
12 * perdition
13 * Mail retrieval proxy server, MySQL support
14 * Copyright (C) 1999-2005 Horms and Frederic Delchambre
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of the
19 * License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software Foundation,
28 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
29 *
30 **********************************************************************/
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "perditiondb_mysql.h"
37 #include "unused.h"
38
39 #ifdef DMALLOC
40 #include <dmalloc.h>
41 #endif
42
43
44 static vanessa_dynamic_array_t *a=NULL;
45 static vanessa_dynamic_array_t *dbhosts_array=NULL;
46 static size_t dbhosts_count = 0;
47 static char *dbhosts = PERDITIONDB_MYSQL_DEFAULT_DBHOSTS;
48 static char *dbname = PERDITIONDB_MYSQL_DEFAULT_DBNAME;
49 static unsigned int dbport = PERDITIONDB_MYSQL_DEFAULT_DBPORT;
50 static char *dbtable = PERDITIONDB_MYSQL_DEFAULT_DBTABLE;
51 static char *dbuser = PERDITIONDB_MYSQL_DEFAULT_DBUSER;
52 static char *dbpwd = PERDITIONDB_MYSQL_DEFAULT_DBPWD;
53 static char *db_user_col = PERDITIONDB_MYSQL_DEFAULT_DBUSERCOL;
54 static char *db_srv_col = PERDITIONDB_MYSQL_DEFAULT_DBSRVCOL;
55 static char *db_port_col = PERDITIONDB_MYSQL_DEFAULT_DBPORTCOL;
56
57
58 /**********************************************************************
59 * perditiondb_mysql_log
60 * Show an error message with mysql errors
61 * pre: msg_str: message to prepent to message
62 * db: mysql database that error is for
63 * post: msg_str is logged to VANESSA_LOGGER_DEBUG with mysql error appended
64 * return: none
65 **********************************************************************/
66
67 #define perditiondb_mysql_log(msg_str, db) \
68 VANESSA_LOGGER_DEBUG_UNSAFE("%s: %s", msg_str, mysql_error(db))
69
70
71 /**********************************************************************
72 * dbserver_fini
73 * Free static vanessa_dynamic_array_t a if it has been initialised
74 * pre: none
75 * post: static vanessa_dynamic_array_t a and its contents are freed
76 * return: 0 on success
77 * -1 on db access error
78 * This inclides file, connection and other data access
79 * errors. It does not cover memory allocation problems.
80 * -2 if key cannot be found in map
81 * -3 on other error
82 **********************************************************************/
83
dbserver_fini(void)84 int dbserver_fini(void){
85 if(a!=NULL){
86 vanessa_dynamic_array_destroy(a);
87 a=NULL;
88 }
89 return(0);
90 }
91
92
93 /**********************************************************************
94 * dbserver_init
95 * Parse options string.
96 * pre: options_str: Options string. String is of the form
97 * [dbhost1[,dbhost2[,...]][:port[:dbname[:dbtable[:dbuser[:dbpwd[:dbsrvcol[:dbusercol[:dbportcol]]]]]]]]]
98 * post: Options string is parsed if not null into
99 * static vanessa_dynamic_array_t a and
100 * static char *dbhosts, *dbname, *dbtable, *dbuser, *dbpwd are
101 * set to pointers insiside a or defaults as neccesary.
102 * return: 0 on success
103 * -1 on db access error
104 * This inclides file, connection and other data access
105 * errors. It does not cover memory allocation problems.
106 * -2 if key cannot be found in map
107 * -3 on other error
108 **********************************************************************/
109
dbserver_init(char * options_str)110 int dbserver_init(char *options_str){
111 int count;
112 char *tmp_str;
113
114 if(options_str==NULL || a!=NULL){
115 return(0);
116 }
117
118 if((tmp_str=strdup(options_str))==NULL) {
119 VANESSA_LOGGER_DEBUG_ERRNO("strdup");
120 a=NULL;
121 return(-1);
122 }
123
124 if((a=vanessa_dynamic_array_split_str(
125 tmp_str,
126 PERDITIONDB_MYSQL_FIELD_DELIMITER
127 ))==NULL){
128 VANESSA_LOGGER_DEBUG("vanessa_dynamic_array_split_str");
129 a=NULL;
130 free(tmp_str);
131 return(-1);
132 }
133
134 count=vanessa_dynamic_array_get_count(a);
135 if(count>PERDITIONDB_MYSQL_DBHOSTS){
136 dbhosts=vanessa_dynamic_array_get_element(a, PERDITIONDB_MYSQL_DBHOSTS);
137 if ((dbhosts_array = vanessa_dynamic_array_split_str(dbhosts,
138 PERDITIONDB_MYSQL_HOSTS_DELIMITER)) == NULL) {
139 VANESSA_LOGGER_DEBUG("vanessa_dynamic_array_split_str");
140 a=NULL;
141 free(tmp_str);
142 return(-1);
143 }
144 dbhosts_count = vanessa_dynamic_array_get_count(dbhosts_array);
145 }
146 if(count>PERDITIONDB_MYSQL_DBNAME){
147 dbname=vanessa_dynamic_array_get_element(a, PERDITIONDB_MYSQL_DBNAME);
148 }
149 if(count>PERDITIONDB_MYSQL_DBPORT){
150 dbport=atoi(vanessa_dynamic_array_get_element(a,
151 PERDITIONDB_MYSQL_DBPORT));
152 }
153 if(count>PERDITIONDB_MYSQL_DBTABLE){
154 dbtable=vanessa_dynamic_array_get_element(a, PERDITIONDB_MYSQL_DBTABLE);
155 }
156 if(count>PERDITIONDB_MYSQL_DBUSER){
157 dbuser=vanessa_dynamic_array_get_element(a, PERDITIONDB_MYSQL_DBUSER);
158 }
159 if(count>PERDITIONDB_MYSQL_DBPWD){
160 dbpwd=vanessa_dynamic_array_get_element(a, PERDITIONDB_MYSQL_DBPWD);
161 }
162 if(count>PERDITIONDB_MYSQL_DBSRVCOL){
163 db_srv_col=vanessa_dynamic_array_get_element(a,
164 PERDITIONDB_MYSQL_DBSRVCOL
165 );
166 }
167 if(count>PERDITIONDB_MYSQL_DBUSERCOL){
168 db_user_col=vanessa_dynamic_array_get_element(a,
169 PERDITIONDB_MYSQL_DBUSERCOL
170 );
171 }
172 if(count>PERDITIONDB_MYSQL_DBPORTCOL){
173 db_port_col=vanessa_dynamic_array_get_element(
174 a,
175 PERDITIONDB_MYSQL_DBPORTCOL
176 );
177 }
178
179 free(tmp_str);
180
181 return(0);
182 }
183
184
185 /**********************************************************************
186 * dbserver_get
187 * Read the server information for a given key from the MySQL db
188 * specified in the options string. If fields are missing
189 * from the options string, or it is NULL then defaults are
190 * used as necessary.
191 * pre: key_str: Key as a null terminated string
192 * options_str: Options string. The usage of this is
193 * implementation dependant.
194 * str_return: Value is returned here
195 * len_return: Length of value is returned here
196 * post: The str_key is looked up and the corresponding value is
197 * returned in str_return and len_return.
198 * return: 0 on success
199 * -1 on db access error
200 * This inclides file, connection and other data access
201 * errors. It does not cover memory allocation problems.
202 * -2 if key cannot be found in map
203 * -3 on other error
204 * Note: The string returned in str_return should be of the
205 * form <servername>[:<port>].
206 * E.g.: localhost:110
207 * localhost
208 **********************************************************************/
209
dbserver_get(const char * key_str,const char * UNUSED (options_str),char ** str_return,size_t * len_return)210 int dbserver_get(
211 const char *key_str,
212 const char *UNUSED(options_str),
213 char **str_return,
214 size_t *len_return
215 ){
216 MYSQL db;
217 MYSQL *rc;
218 MYSQL_RES *res;
219 MYSQL_ROW row;
220 char sqlstr[PERDITIONDB_MYSQL_QUERY_LENGTH];
221 char key_str_escaped[2*PERDITIONDB_MYSQL_QUERY_LENGTH+1];
222 size_t servername_len;
223 size_t hcnt = 0;
224
225 if (!mysql_init(&db)) {
226 perditiondb_mysql_log("mysql_init", &db);
227 vanessa_dynamic_array_destroy(a);
228 return(-1);
229 }
230
231 rc = NULL;
232 while (hcnt < dbhosts_count
233 && !(rc=mysql_real_connect(&db,
234 vanessa_dynamic_array_get_element(dbhosts_array, hcnt),
235 dbuser,dbpwd,dbname,dbport,NULL,0))) {
236 perditiondb_mysql_log("mysql_connect", &db);
237 hcnt++;
238 }
239 if(!rc){
240 perditiondb_mysql_log("mysql_connect", &db);
241 mysql_close(&db);
242 return(-1);
243 }
244
245 mysql_real_escape_string(&db,key_str_escaped,key_str,strlen(key_str));
246
247 if (db_port_col && db_port_col[0]) {
248 if(snprintf(
249 sqlstr,
250 PERDITIONDB_MYSQL_QUERY_LENGTH,
251 "select %s,%s,%s from %s where %s='%s';",
252 db_user_col,
253 db_srv_col,
254 db_port_col,
255 dbtable,
256 db_user_col,
257 key_str_escaped
258 )<0){
259 VANESSA_LOGGER_DEBUG("query truncated, aborting");
260 return(-3);
261 }
262 }
263 else {
264 if(snprintf(
265 sqlstr,
266 PERDITIONDB_MYSQL_QUERY_LENGTH,
267 "select %s,%s from %s where %s='%s';",
268 db_user_col, db_srv_col,
269 dbtable, db_user_col,
270 key_str_escaped
271 )<0){
272 VANESSA_LOGGER_DEBUG("query truncated, aborting");
273 return(-3);
274 }
275 }
276
277 if (mysql_query(&db, sqlstr)) {
278 perditiondb_mysql_log("mysql_query", &db);
279 mysql_close(&db);
280 return(-1);
281 }
282
283 res = mysql_store_result(&db);
284 if(!res){
285 perditiondb_mysql_log("mysql_store_result", &db);
286 mysql_close(&db);
287 return(-3);
288 }
289
290 if(mysql_num_rows(res) == 0){
291 mysql_free_result(res);
292 mysql_close(&db);
293 return(-2);
294 }
295
296 if((row=mysql_fetch_row(res))==NULL){
297 perditiondb_mysql_log("mysql_fetch_row", &db);
298 mysql_close(&db);
299 return(-3);
300 }
301
302 if(row[1]==NULL || row[1][0]=='\0'){
303 VANESSA_LOGGER_DEBUG("row[1] is empty");
304 mysql_free_result(res);
305 mysql_close(&db);
306 return(-3);
307 }
308 servername_len=*len_return=1+strlen(row[1]);
309
310 if (db_port_col && db_port_col[0]){
311 if(row[2]!=NULL && row[2][0]!='\0'){
312 *len_return+=1+strlen(row[2]);
313 }
314 }
315
316 if((*str_return=(char *)malloc(*len_return))==NULL){
317 VANESSA_LOGGER_DEBUG_ERRNO("malloc");
318 mysql_free_result(res);
319 mysql_close(&db);
320 return(-3);
321 }
322
323 strcpy(*str_return,row[1]);
324 if (db_port_col && db_port_col[0]){
325 if(row[2]!=NULL && row[2][0]!='\0'){
326 *((*str_return)+servername_len-1)=PERDITIONDB_MYSQL_FIELD_DELIMITER;
327 strcpy((*str_return)+servername_len,row[2]);
328 }
329 }
330
331 mysql_free_result(res);
332 mysql_close(&db);
333 return(0);
334 }
335