1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,809 +0,0 @@ |
1 |
-/* |
|
2 |
- * $Id$ |
|
3 |
- * |
|
4 |
- * Copyright (C) 2001-2003 FhG Fokus |
|
5 |
- * |
|
6 |
- * This file is part of ser, a free SIP server. |
|
7 |
- * |
|
8 |
- * ser is free software; you can redistribute it and/or modify |
|
9 |
- * it under the terms of the GNU General Public License as published by |
|
10 |
- * the Free Software Foundation; either version 2 of the License, or |
|
11 |
- * (at your option) any later version |
|
12 |
- * |
|
13 |
- * For a license to use the ser software under conditions |
|
14 |
- * other than those described here, or to purchase support for this |
|
15 |
- * software, please contact iptel.org by e-mail at the following addresses: |
|
16 |
- * info@iptel.org |
|
17 |
- * |
|
18 |
- * ser is distributed in the hope that it will be useful, |
|
19 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
20 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
21 |
- * GNU General Public License for more details. |
|
22 |
- * |
|
23 |
- * You should have received a copy of the GNU General Public License |
|
24 |
- * along with this program; if not, write to the Free Software |
|
25 |
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
26 |
- * |
|
27 |
- * History: |
|
28 |
- * -------- |
|
29 |
- * 2003-10-21 file created (bogdan) |
|
30 |
- * 2004-06-06 init_db_fifo added, DB api updated (andrei) |
|
31 |
- */ |
|
32 |
- |
|
33 |
- |
|
34 |
- |
|
35 |
-#include <stdio.h> |
|
36 |
-#include <stdlib.h> |
|
37 |
-#include <strings.h> |
|
38 |
-#include <string.h> |
|
39 |
-#include <ctype.h> |
|
40 |
-#include <time.h> |
|
41 |
- |
|
42 |
-#include "../mem/mem.h" |
|
43 |
-#include "../fifo_server.h" |
|
44 |
-#include "../dprint.h" |
|
45 |
-#include "../str.h" |
|
46 |
-#include "db.h" |
|
47 |
-#include "db_fifo.h" |
|
48 |
- |
|
49 |
-#define MAX_SIZE_LINE 512 |
|
50 |
-#define MAX_ARRAY 32 |
|
51 |
- |
|
52 |
-#define SELECT_CMD 1 |
|
53 |
-#define DELETE_CMD 2 |
|
54 |
-#define INSERT_CMD 3 |
|
55 |
-#define UPDATE_CMD 4 |
|
56 |
-#define RAWQUERY_CMD 5 |
|
57 |
-#define RAWQUERYRES_CMD 6 |
|
58 |
- |
|
59 |
-#define SELECT_STR "select" |
|
60 |
-#define SELECT_STR_LEN (sizeof(SELECT_STR)-1) |
|
61 |
-#define DELETE_STR "delete" |
|
62 |
-#define DELETE_STR_LEN (sizeof(DELETE_STR)-1) |
|
63 |
-#define INSERT_STR "insert" |
|
64 |
-#define INSERT_STR_LEN (sizeof(INSERT_STR)-1) |
|
65 |
-#define UPDATE_STR "update" |
|
66 |
-#define UPDATE_STR_LEN (sizeof(UPDATE_STR)-1) |
|
67 |
-#define RAWQUERY_STR "raw_query" |
|
68 |
-#define RAWQUERY_STR_LEN (sizeof(RAWQUERY_STR)-1) |
|
69 |
-#define RAWQUERYRES_STR "raw_query_response" |
|
70 |
-#define RAWQUERYRES_STR_LEN (sizeof(RAWQUERYRES_STR)-1) |
|
71 |
-#define END_CHR '.' |
|
72 |
- |
|
73 |
-#define INT_TYPE "int" |
|
74 |
-#define INT_TYPE_LEN (sizeof(INT_TYPE)-1) |
|
75 |
-#define DOUBLE_TYPE "double" |
|
76 |
-#define DOUBLE_TYPE_LEN (sizeof(DOUBLE_TYPE)-1) |
|
77 |
-#define STRING_TYPE "string" |
|
78 |
-#define STRING_TYPE_LEN (sizeof(STRING_TYPE)-1) |
|
79 |
-#define DATE_TYPE "date" |
|
80 |
-#define DATE_TYPE_LEN (sizeof(DATE_TYPE)-1) |
|
81 |
-#define BLOB_TYPE "blob" |
|
82 |
-#define BLOB_TYPE_LEN (sizeof(BLOB_TYPE)-1) |
|
83 |
-#define BITMAP_TYPE "bitmap" |
|
84 |
-#define BITMAP_TYPE_LEN (sizeof(BITMAP_TYPE)-1) |
|
85 |
- |
|
86 |
-#define NULL_VAL "null" |
|
87 |
-#define NULL_VAL_LEN (sizeof(NULL_VAL)-1) |
|
88 |
- |
|
89 |
- |
|
90 |
-#define trim_spaces(str) \ |
|
91 |
- do { \ |
|
92 |
- for(;(str).s[0]==' ';(str).s++,((str).len)--);\ |
|
93 |
- for(;(str).s[(str).len-1]==' ';(str).s[--((str).len)]='\0');\ |
|
94 |
- }while(0) |
|
95 |
- |
|
96 |
-#define double_log( _str_ ) \ |
|
97 |
- do { \ |
|
98 |
- fprintf( rpl, "ERROR: %s\n",_str_); \ |
|
99 |
- LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \ |
|
100 |
- }while(0) |
|
101 |
- |
|
102 |
-#define semidouble_log( _str_ ) \ |
|
103 |
- do { \ |
|
104 |
- fprintf( rpl, "ERROR: Internal Server Error\n"); \ |
|
105 |
- LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \ |
|
106 |
- }while(0) |
|
107 |
- |
|
108 |
-#define get_int(_p_,_end_,_res_,_n_,_err_s_,_err_) \ |
|
109 |
- do { \ |
|
110 |
- _res_ = 0;\ |
|
111 |
- for( _n_=0 ; (_p_)<(_end_) && isdigit((int)(unsigned char)*(_p_)) ; \ |
|
112 |
- (_p_)++,(_n_)++)\ |
|
113 |
- (_res_)=(_res_)*10+(*(_p_)-'0');\ |
|
114 |
- if ((_n_)==0) {\ |
|
115 |
- double_log( _err_s_ );\ |
|
116 |
- goto _err_;\ |
|
117 |
- }\ |
|
118 |
- }while(0); |
|
119 |
- |
|
120 |
- |
|
121 |
- |
|
122 |
- |
|
123 |
-static char buf[MAX_SIZE_LINE]; |
|
124 |
-static char tbl_buf[MAX_SIZE_LINE]; /* current 'table name' buffer */ |
|
125 |
-static FILE* rpl; |
|
126 |
-static db_con_t* fifo_db_con=0; |
|
127 |
-static db_func_t fifo_dbf; |
|
128 |
- |
|
129 |
- |
|
130 |
- |
|
131 |
- |
|
132 |
-static inline int sgn_str2float(str* _s, float* _r, db_type_t* _type ) |
|
133 |
-{ |
|
134 |
- int i, dot = 0; |
|
135 |
- int ngv = 0; |
|
136 |
- float order = 0.1; |
|
137 |
- |
|
138 |
- *_r = 0; |
|
139 |
- *_type = DB_INT; |
|
140 |
- i = 0; |
|
141 |
- if (_s->len==0) return -3; |
|
142 |
- if ( (_s->s[0]=='-' && (ngv=1)==1) || (_s->s[0]=='+') ) |
|
143 |
- i++; |
|
144 |
- for( ; i < _s->len; i++) { |
|
145 |
- if (_s->s[i] == '.') { |
|
146 |
- if (dot) return -1; |
|
147 |
- dot = 1; |
|
148 |
- *_type = DB_DOUBLE; |
|
149 |
- continue; |
|
150 |
- } |
|
151 |
- if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) { |
|
152 |
- if (dot) { |
|
153 |
- *_r += (_s->s[i] - '0') * order; |
|
154 |
- order /= 10; |
|
155 |
- } else { |
|
156 |
- *_r *= 10; |
|
157 |
- *_r += _s->s[i] - '0'; |
|
158 |
- } |
|
159 |
- } else { |
|
160 |
- return -2; |
|
161 |
- } |
|
162 |
- } |
|
163 |
- if (ngv) *_r = -(*_r); |
|
164 |
- return 0; |
|
165 |
-} |
|
166 |
- |
|
167 |
- |
|
168 |
- |
|
169 |
-static inline int parse_db_value( str *s, db_val_t *val, str **ret_s) |
|
170 |
-{ |
|
171 |
- db_type_t type; |
|
172 |
- db_type_t nr_type; |
|
173 |
- int cast; |
|
174 |
- struct tm td; |
|
175 |
- char *p; |
|
176 |
- char *end; |
|
177 |
- int n; |
|
178 |
- float nr; |
|
179 |
- |
|
180 |
- cast = 0; |
|
181 |
- *ret_s = 0; |
|
182 |
- p = 0; |
|
183 |
- type = DB_STR; |
|
184 |
- |
|
185 |
- /* some safety checks */ |
|
186 |
- if (s->len==0 || s->s==0) { |
|
187 |
- semidouble_log("BUG -> parse_db_value gets a len/s=0 string"); |
|
188 |
- goto error; |
|
189 |
- } |
|
190 |
- |
|
191 |
- /* is there some data cast operator? */ |
|
192 |
- if (s->s[0]=='[') { |
|
193 |
- /* get the end of the cast operator */ |
|
194 |
- for(p=s->s,end=s->s+s->len ; p<end && *p!=']' ; p++); |
|
195 |
- if (p>=end-1) { |
|
196 |
- double_log("Bad cast operator format (expected attr=[type]val)"); |
|
197 |
- goto error; |
|
198 |
- } |
|
199 |
- n = p - s->s - 1; |
|
200 |
- p = s->s + 1; |
|
201 |
- DBG("---><%.*s>\n",n,p); |
|
202 |
- /*identify the cast type*/ |
|
203 |
- if (n==INT_TYPE_LEN && !strncasecmp(p,INT_TYPE,n)) { |
|
204 |
- type = DB_INT; |
|
205 |
- } else if (n==DOUBLE_TYPE_LEN && !strncasecmp(p,DOUBLE_TYPE,n)) { |
|
206 |
- type = DB_DOUBLE; |
|
207 |
- } else if (n==STRING_TYPE_LEN && !strncasecmp(p,STRING_TYPE,n)) { |
|
208 |
- type = DB_STR; |
|
209 |
- } else if (n==BLOB_TYPE_LEN && !strncasecmp(p,BLOB_TYPE,n)) { |
|
210 |
- type = DB_BLOB; |
|
211 |
- } else if (n==DATE_TYPE_LEN && !strncasecmp(p,DATE_TYPE,n)) { |
|
212 |
- type = DB_DATETIME; |
|
213 |
- } else if (n==BITMAP_TYPE_LEN && !strncasecmp(p,BITMAP_TYPE,n)) { |
|
214 |
- type = DB_BITMAP; |
|
215 |
- } else { |
|
216 |
- double_log("Unknown cast type"); |
|
217 |
- goto error; |
|
218 |
- } |
|
219 |
- cast = 1; |
|
220 |
- s->s += n+2; |
|
221 |
- s->len -= n+2; |
|
222 |
- } |
|
223 |
- |
|
224 |
- /* string has at least one character */ |
|
225 |
- DBG("DEBUG:parse_db_value: value id <%.*s>\n",s->len,s->s); |
|
226 |
- if ( s->s[0]=='\"' && s->s[s->len-1]=='\"' && s->len!=1) { |
|
227 |
- /* can be DB_STR, DB_STRING, DB_BLOB */ |
|
228 |
- /* get rid of the quoting */ |
|
229 |
- s->s++; |
|
230 |
- s->len -= 2; |
|
231 |
- /* if casted, check if is valid */ |
|
232 |
- if (cast) { |
|
233 |
- if (type!=DB_STR && type!=DB_BLOB) { |
|
234 |
- double_log("Invalid cast for quoted value"); |
|
235 |
- goto error; |
|
236 |
- } |
|
237 |
- } else { |
|
238 |
- type = DB_STR; |
|
239 |
- } |
|
240 |
- /* fill in the val struct */ |
|
241 |
- memset( val, 0, sizeof(db_val_t)); |
|
242 |
- val->type = type; |
|
243 |
- if (type==DB_STR) { |
|
244 |
- val->val.str_val = *s; |
|
245 |
- *ret_s = &val->val.str_val; |
|
246 |
- } else if (type==DB_BLOB) { |
|
247 |
- val->val.blob_val = *s; |
|
248 |
- *ret_s = &val->val.blob_val; |
|
249 |
- } else { |
|
250 |
- semidouble_log("BUG -> type is not STR or BLOB"); |
|
251 |
- goto error; |
|
252 |
- } |
|
253 |
- } else if ( s->s[0]=='<' && s->s[s->len-1]=='>' && s->len!=1) { |
|
254 |
- /* can be only date+time type DB_DATETIME*/ |
|
255 |
- /* if casted, check if is valid */ |
|
256 |
- if (cast && type!=DB_DATETIME) { |
|
257 |
- double_log("Invalid cast for quoted value"); |
|
258 |
- goto error; |
|
259 |
- } |
|
260 |
- /* get rid of the quoting */ |
|
261 |
- s->s++; |
|
262 |
- s->len -= 2; |
|
263 |
- /* start parsing */ |
|
264 |
- p = s->s; |
|
265 |
- end = s->s + s->len; |
|
266 |
- td.tm_wday = 0; |
|
267 |
- td.tm_yday = 0; |
|
268 |
- /* get year */ |
|
269 |
- get_int( p, end, td.tm_year, n, "Missing year in date format",error); |
|
270 |
- td.tm_year -= 1900; /* correction */ |
|
271 |
- if (*(p++)!='-') goto date_error; |
|
272 |
- /* get month */ |
|
273 |
- get_int( p, end, td.tm_mon, n, "Missing month in date format",error); |
|
274 |
- td.tm_mon --; /* correction */ |
|
275 |
- if (*(p++)!='-') goto date_error; |
|
276 |
- /* get day */ |
|
277 |
- get_int( p, end, td.tm_mday, n, "Missing day in date format",error); |
|
278 |
- if (*(p++)!=' ') goto date_error; |
|
279 |
- /* get hour */ |
|
280 |
- get_int( p, end, td.tm_hour, n, "Missing hour in date format",error); |
|
281 |
- if (*(p++)!=':') goto date_error; |
|
282 |
- /* get minutes */ |
|
283 |
- get_int( p, end, td.tm_min, n, "Missing minutes in date format",error); |
|
284 |
- if (*(p++)!=':') goto date_error; |
|
285 |
- /* get seconds */ |
|
286 |
- get_int( p, end, td.tm_sec, n,"Missing seconds in date format",error); |
|
287 |
- if (p!=end) goto date_error; |
|
288 |
- td.tm_isdst = -1 ; /*daylight*/ |
|
289 |
- /* fill the val struct */ |
|
290 |
- val->type = DB_DATETIME; |
|
291 |
- val->val.time_val = mktime( &td ); |
|
292 |
- /*DBG("DBG: <%.*s> is %s\n",s->len,s->s,ctime(&val->val.time_val));*/ |
|
293 |
- } else if ( (*(p=s->s)=='+') || (*p=='-') || |
|
294 |
- isdigit((int)(unsigned char)*p) ) { |
|
295 |
- /* can be a DB_INT / DB_DOUBLE / DB_BITMAP value */ |
|
296 |
- if (sgn_str2float( s, &nr, &nr_type)!=0) { |
|
297 |
- double_log("Bad int/float value format (expected [+/-]nr[.nr])"); |
|
298 |
- goto error; |
|
299 |
- } |
|
300 |
- /* if casted, check if valid */ |
|
301 |
- if (cast) { |
|
302 |
- switch (type) { |
|
303 |
- case DB_BITMAP: |
|
304 |
- if ( nr_type!=DB_INT || nr<0 ) { |
|
305 |
- double_log("Invalid value for BITMAP type"); |
|
306 |
- goto error; |
|
307 |
- } |
|
308 |
- break; |
|
309 |
- case DB_INT: |
|
310 |
- case DB_DOUBLE: |
|
311 |
- if (type==DB_INT && nr_type==DB_DOUBLE ) { |
|
312 |
- double_log("Invalid cast to INT for a DOUBLE value"); |
|
313 |
- goto error; |
|
314 |
- } |
|
315 |
- break; |
|
316 |
- default: |
|
317 |
- double_log("Invalid cast for numerical value"); |
|
318 |
- goto error; |
|
319 |
- } |
|
320 |
- } else { |
|
321 |
- type = nr_type; |
|
322 |
- } |
|
323 |
- /* fill the val struct */ |
|
324 |
- val->type = type; |
|
325 |
- switch (type) { |
|
326 |
- case DB_INT: |
|
327 |
- val->val.int_val = (int)nr; break; |
|
328 |
- case DB_DOUBLE: |
|
329 |
- val->val.double_val = nr; break; |
|
330 |
- case DB_BITMAP: |
|
331 |
- val->val.bitmap_val = (int)nr; break; |
|
332 |
- default: |
|
333 |
- semidouble_log("BUG -> unknown type when filling num. val"); |
|
334 |
- goto error; |
|
335 |
- } |
|
336 |
- } else if (s->len==NULL_VAL_LEN && !strncasecmp(s->s,NULL_VAL,s->len) ) { |
|
337 |
- /* it's a NULL val */ |
|
338 |
- if (!cast) { |
|
339 |
- double_log("NULL values requires type casting"); |
|
340 |
- goto error; |
|
341 |
- } |
|
342 |
- val->type = type; |
|
343 |
- val->nul = 1; |
|
344 |
- } else { |
|
345 |
- double_log("Unable to recognize value type"); |
|
346 |
- goto error; |
|
347 |
- } |
|
348 |
- |
|
349 |
- return 0; |
|
350 |
-date_error: |
|
351 |
- double_log("Bad <date time> format (expected <YYYY-MM-DD hh:mm:ss>)\n"); |
|
352 |
-error: |
|
353 |
- return -1; |
|
354 |
-} |
|
355 |
- |
|
356 |
- |
|
357 |
- |
|
358 |
-/* returns : -1 error |
|
359 |
- * 0 success */ |
|
360 |
-static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
|
361 |
- db_val_t *vals, int *nr, int max_nr) |
|
362 |
-{ |
|
363 |
- str line; |
|
364 |
- str key,op,val; |
|
365 |
- unsigned char *c; |
|
366 |
- str *p_val; |
|
367 |
- int sp_found; |
|
368 |
- |
|
369 |
- *nr = 0; |
|
370 |
- |
|
371 |
- while(1) { |
|
372 |
- /* read a new line */ |
|
373 |
- line.s = buf; |
|
374 |
- if (read_line( line.s, MAX_SIZE_LINE, fifo, &line.len)!=1) { |
|
375 |
- double_log("Command end when reading AVPs - missing . at after " |
|
376 |
- "AVP list?"); |
|
377 |
- goto error; |
|
378 |
- } |
|
379 |
- trim_spaces(line); |
|
380 |
- /* is this the separter/end char? */ |
|
381 |
- if (line.len==1 && *line.s==END_CHR) |
|
382 |
- return 0; |
|
383 |
- /* we have a new avp */ |
|
384 |
- if (*nr<max_nr) { |
|
385 |
- /* parse the line key|op|val */ |
|
386 |
- c = (unsigned char*)line.s; |
|
387 |
- /* parse the key name */ |
|
388 |
- for( key.s=(char*)c ; *c && (isalnum((int)*c)||*c=='_') ; c++ ); |
|
389 |
- if (!*c) goto parse_error; |
|
390 |
- key.len = (char*)c-key.s; |
|
391 |
- if (key.len==0) goto parse_error; |
|
392 |
- /* possible spaces? */ |
|
393 |
- for( sp_found=0 ; *c && isspace((int)*c) ; c++,sp_found=1 ); |
|
394 |
- if (!*c) goto parse_error; |
|
395 |
- /* parse the operator */ |
|
396 |
- op.s = (char*)c; |
|
397 |
- switch (*c) { |
|
398 |
- case '<': |
|
399 |
- case '>': |
|
400 |
- if (*(c+1)=='=') c++; |
|
401 |
- case '=': |
|
402 |
- c++; |
|
403 |
- if (!*c) goto parse_error; |
|
404 |
- break; |
|
405 |
- default: |
|
406 |
- /* at least one space must be before unknown ops */ |
|
407 |
- if(!sp_found) goto parse_error; |
|
408 |
- /* eat everything to first space */ |
|
409 |
- for( ; *c && !isspace((int)*c) ; c++ ); |
|
410 |
- if (!*c || (char*)c==op.s) goto parse_error; /* 0 length */ |
|
411 |
- /* include into operator str. one space before and after*/ |
|
412 |
- op.s--; |
|
413 |
- c++; |
|
414 |
- } |
|
415 |
- op.len = (char*)c - op.s; |
|
416 |
- /* possible spaces? */ |
|
417 |
- for( ; *c && isspace((int)*c) ; c++ ); |
|
418 |
- if (!*c) goto parse_error; |
|
419 |
- /* get value */ |
|
420 |
- val.s = (char*)c; |
|
421 |
- val.len = line.len - ((char*)c-line.s); |
|
422 |
- if (val.len==0) goto parse_error; |
|
423 |
- if (parse_db_value( &val, &vals[*nr], &p_val)!=0) |
|
424 |
- goto error; |
|
425 |
- /* duplicate the avp -> make all null terminated */ |
|
426 |
- c = pkg_malloc(key.len+op.len+2+(p_val?p_val->len+1:0)); |
|
427 |
- if (c==0) { |
|
428 |
- semidouble_log("no more pkg memory"); |
|
429 |
- goto error; |
|
430 |
- } |
|
431 |
- /*copy the key */ |
|
432 |
- keys[*nr] = (char*)c; |
|
433 |
- memcpy( c, key.s, key.len); |
|
434 |
- c[key.len] = 0; |
|
435 |
- c += key.len + 1; |
|
436 |
- /*copy the op */ |
|
437 |
- ops[*nr] = (char*)c; |
|
438 |
- memcpy( c, op.s, op.len); |
|
439 |
- c[op.len] = 0; |
|
440 |
- c += op.len + 1; |
|
441 |
- /*copy the val */ |
|
442 |
- if (p_val) { |
|
443 |
- memcpy( c, p_val->s, p_val->len); |
|
444 |
- c[p_val->len] = 0; |
|
445 |
- p_val->s = (char*)c; |
|
446 |
- } |
|
447 |
- /* done */ |
|
448 |
- (*nr)++; |
|
449 |
- } else { |
|
450 |
- LOG(L_WARN,"WARNING:get_avps: too many avps (max=%d), ignoring " |
|
451 |
- "\"%.*s\"\n",max_nr,line.len,line.s); |
|
452 |
- } |
|
453 |
- } |
|
454 |
-parse_error: |
|
455 |
- LOG(L_ERR,"ERROR:get_avps: parse error in \"%.*s\" at char [%d][%c] " |
|
456 |
- "offset %d\n",line.len,line.s,*c,*c, (unsigned)((char*)c-line.s)); |
|
457 |
- double_log("Broken AVP(attr|op|val) in DB command"); |
|
458 |
-error: |
|
459 |
- for(;*nr;(*nr)--) |
|
460 |
- pkg_free( (void*)keys[(*nr)-1] ); |
|
461 |
- return -1; |
|
462 |
-} |
|
463 |
- |
|
464 |
- |
|
465 |
- |
|
466 |
-/* returns : -1 error |
|
467 |
- * 0 success */ |
|
468 |
-static inline int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr) |
|
469 |
-{ |
|
470 |
- str line; |
|
471 |
- char *key; |
|
472 |
- |
|
473 |
- *nr = 0; |
|
474 |
- |
|
475 |
- while(1) { |
|
476 |
- /* read a new line */ |
|
477 |
- line.s = buf; |
|
478 |
- if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || !line.len) { |
|
479 |
- double_log("Bad key list in SELECT DB command " |
|
480 |
- "(missing '.' at the end?)"); |
|
481 |
- goto error; |
|
482 |
- } |
|
483 |
- trim_spaces(line); |
|
484 |
- /* is this the separter/end char? */ |
|
485 |
- if (line.len==1 && *line.s==END_CHR) |
|
486 |
- return 0; |
|
487 |
- /* we have a new key */ |
|
488 |
- if (*nr<max_nr) { |
|
489 |
- /* duplicate the key -> null terminated */ |
|
490 |
- key = (char*)pkg_malloc(line.len+1); |
|
491 |
- if (key==0) { |
|
492 |
- semidouble_log("no more pkg memory"); |
|
493 |
- goto error; |
|
494 |
- } |
|
495 |
- memcpy( key, line.s, line.len); |
|
496 |
- key[line.len] = 0; |
|
497 |
- keys[*nr] = key; |
|
498 |
- (*nr)++; |
|
499 |
- } else { |
|
500 |
- LOG(L_WARN,"WARNING:get_keys: too many keys (max=%d), ignoring " |
|
501 |
- "\"%.*s\"\n",max_nr,line.len,line.s); |
|
502 |
- } |
|
503 |
- } |
|
504 |
- |
|
505 |
-error: |
|
506 |
- for(;*nr;(*nr)--) |
|
507 |
- pkg_free( (void*)keys[(*nr)-1] ); |
|
508 |
- return -1; |
|
509 |
-} |
|
510 |
- |
|
511 |
- |
|
512 |
- |
|
513 |
-static inline void print_res(db_res_t* res, FILE *rpl) |
|
514 |
-{ |
|
515 |
- int i, j; |
|
516 |
- |
|
517 |
- for(i = 0; i < RES_COL_N(res); i++) { |
|
518 |
- fprintf(rpl, "%s ", RES_NAMES(res)[i]); |
|
519 |
- } |
|
520 |
- fprintf(rpl,"\n"); |
|
521 |
- |
|
522 |
- for(i = 0; i < RES_ROW_N(res); i++) { |
|
523 |
- for(j = 0; j < RES_COL_N(res); j++) { |
|
524 |
- if (RES_ROWS(res)[i].values[j].nul) { |
|
525 |
- fprintf(rpl,"NULL "); |
|
526 |
- continue; |
|
527 |
- } |
|
528 |
- switch(RES_ROWS(res)[i].values[j].type) { |
|
529 |
- case DB_INT: |
|
530 |
- fprintf(rpl,"%d ", |
|
531 |
- RES_ROWS(res)[i].values[j].val.int_val); |
|
532 |
- break; |
|
533 |
- case DB_DOUBLE: |
|
534 |
- fprintf(rpl,"%f ", |
|
535 |
- RES_ROWS(res)[i].values[j].val.double_val); |
|
536 |
- break; |
|
537 |
- case DB_DATETIME: |
|
538 |
- fprintf(rpl,"%s ", |
|
539 |
- ctime(&(RES_ROWS(res)[i].values[j].val.time_val))); |
|
540 |
- break; |
|
541 |
- case DB_STRING: |
|
542 |
- fprintf(rpl,"%s ", |
|
543 |
- RES_ROWS(res)[i].values[j].val.string_val); |
|
544 |
- break; |
|
545 |
- case DB_STR: |
|
546 |
- fprintf(rpl,"%.*s ", |
|
547 |
- RES_ROWS(res)[i].values[j].val.str_val.len, |
|
548 |
- RES_ROWS(res)[i].values[j].val.str_val.s); |
|
549 |
- break; |
|
550 |
- case DB_BLOB: |
|
551 |
- fprintf(rpl,"%.*s ", |
|
552 |
- RES_ROWS(res)[i].values[j].val.blob_val.len, |
|
553 |
- RES_ROWS(res)[i].values[j].val.blob_val.s); |
|
554 |
- break; |
|
555 |
- case DB_BITMAP: |
|
556 |
- fprintf(rpl,"%d ", |
|
557 |
- RES_ROWS(res)[i].values[j].val.bitmap_val); |
|
558 |
- break; |
|
559 |
- } |
|
560 |
- } |
|
561 |
- fprintf(rpl,"\n"); |
|
562 |
- } |
|
563 |
-} |
|
564 |
- |
|
565 |
- |
|
566 |
- |
|
567 |
-/* binds the database module, initializes the database and |
|
568 |
- * registers the db fifo cmd |
|
569 |
- * returns 0 on success, -1 on error */ |
|
570 |
-int init_db_fifo(char* fifo_db_url) |
|
571 |
-{ |
|
572 |
- if ( bind_dbmod(fifo_db_url, &fifo_dbf)==0 ) { |
|
573 |
- if (!DB_CAPABILITY(fifo_dbf, DB_CAP_ALL | DB_CAP_RAW_QUERY)) { |
|
574 |
- LOG(L_ERR, "ERROR: init_db_fifo: Database module does " |
|
575 |
- "not implement all function needed by AVP code\n"); |
|
576 |
- return -1; |
|
577 |
- } |
|
578 |
- |
|
579 |
- if ( (fifo_db_con=fifo_dbf.init( fifo_db_url ))==0) { |
|
580 |
- /* connection failed */ |
|
581 |
- LOG(L_ERR,"ERROR: init_db_fifo: unable to connect to database -> " |
|
582 |
- "fifo DB commands disabled!\n"); |
|
583 |
- }else if (register_fifo_cmd(db_fifo_cmd, FIFO_DB, 0)<0) { |
|
584 |
- LOG(L_ERR, "ERROR: init_db_fifo: unable to register '%s'" |
|
585 |
- " FIFO cmd\n", FIFO_DB); |
|
586 |
- } else { |
|
587 |
- return 0; /* success */ |
|
588 |
- } |
|
589 |
- }else{ |
|
590 |
- LOG(L_WARN, "WARNING: init_db_fifo: unable to find any db module - " |
|
591 |
- "fifo DB commands disabled!\n"); |
|
592 |
- } |
|
593 |
- return -1; /* error */ |
|
594 |
-} |
|
595 |
- |
|
596 |
- |
|
597 |
- |
|
598 |
- |
|
599 |
- |
|
600 |
-int db_fifo( FILE *fifo, char *response_file ) |
|
601 |
-{ |
|
602 |
- static db_key_t keys1[MAX_ARRAY]; |
|
603 |
- static db_op_t ops1[MAX_ARRAY]; |
|
604 |
- static db_val_t vals1[MAX_ARRAY]; |
|
605 |
- static db_key_t keys2[MAX_ARRAY]; |
|
606 |
- static db_op_t ops2[MAX_ARRAY]; |
|
607 |
- static db_val_t vals2[MAX_ARRAY]; |
|
608 |
- static db_res_t *select_res; |
|
609 |
- str line; |
|
610 |
- int db_cmd; |
|
611 |
- int nr1, nr2; |
|
612 |
- int ret; |
|
613 |
- int n; |
|
614 |
- |
|
615 |
- ret = -1; /* default is error */ |
|
616 |
- rpl = 0; |
|
617 |
- |
|
618 |
- if (fifo_db_con==0) /* disabled due to database init/binding errors */ |
|
619 |
- goto error; |
|
620 |
- /* first check the response file */ |
|
621 |
- rpl = open_reply_pipe( response_file ); |
|
622 |
- if (rpl==0) |
|
623 |
- goto error; |
|
624 |
- |
|
625 |
- /* first name must be the real name of the DB operation */ |
|
626 |
- line.s = buf; |
|
627 |
- if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || line.len==0) { |
|
628 |
- double_log("DB command name expected"); |
|
629 |
- goto error; |
|
630 |
- } |
|
631 |
- trim_spaces(line); |
|
632 |
- |
|
633 |
- /* check the name of the command */ |
|
634 |
- if (line.len==SELECT_STR_LEN |
|
635 |
- && !strncasecmp( line.s, SELECT_STR, line.len)) { |
|
636 |
- db_cmd = SELECT_CMD; |
|
637 |
- } else if (line.len==DELETE_STR_LEN |
|
638 |
- && !strncasecmp( line.s, DELETE_STR, line.len)) { |
|
639 |
- db_cmd = DELETE_CMD; |
|
640 |
- } else if (line.len==INSERT_STR_LEN |
|
641 |
- && !strncasecmp( line.s, INSERT_STR, line.len)) { |
|
642 |
- db_cmd = INSERT_CMD; |
|
643 |
- } else if (line.len==UPDATE_STR_LEN |
|
644 |
- && !strncasecmp( line.s, UPDATE_STR, line.len)) { |
|
645 |
- db_cmd = UPDATE_CMD; |
|
646 |
- } else if (line.len==RAWQUERY_STR_LEN |
|
647 |
- && !strncasecmp( line.s, RAWQUERY_STR, line.len)) { |
|
648 |
- db_cmd = RAWQUERY_CMD; |
|
649 |
- } else if (line.len==RAWQUERYRES_STR_LEN |
|
650 |
- && !strncasecmp( line.s, RAWQUERYRES_STR, line.len)) { |
|
651 |
- db_cmd = RAWQUERYRES_CMD; |
|
652 |
- } else { |
|
653 |
- double_log("Unknown DB command name"); |
|
654 |
- goto error; |
|
655 |
- } |
|
656 |
- DBG("DEBUG:db_fifo: cmd \"%.*s\" received\n",line.len,line.s); |
|
657 |
- |
|
658 |
- nr1 = 0; |
|
659 |
- nr2 = 0; |
|
660 |
- |
|
661 |
- if (db_cmd==SELECT_CMD) { |
|
662 |
- /* read the columns to be fetched */ |
|
663 |
- if ( get_keys( fifo, keys1, &nr1, MAX_ARRAY)!=0 ) |
|
664 |
- goto error; |
|
665 |
- } else if (db_cmd==UPDATE_CMD) { |
|
666 |
- /* read the col=val pairs to be updated */ |
|
667 |
- if (get_avps( fifo , keys1, ops1, vals1, &nr1, MAX_ARRAY)!=0 ) |
|
668 |
- goto error; |
|
669 |
- /* must be at least one AVP in an update command */ |
|
670 |
- if (nr1==0) { |
|
671 |
- double_log("UPDATE command must have at least one" |
|
672 |
- " field to update"); |
|
673 |
- goto error; |
|
674 |
- } |
|
675 |
- /* all the operators must be '=' */ |
|
676 |
- for(n=0;n<nr1;n++) { |
|
677 |
- if (ops1[n][0]!='=' || ops1[n][1]!='\0') { |
|
678 |
- double_log("Invalid operator in updated fields (expected = )"); |
|
679 |
- goto error1; |
|
680 |
- } |
|
681 |
- }/*end for*/ |
|
682 |
- } else if (db_cmd==RAWQUERY_CMD || db_cmd==RAWQUERYRES_CMD) { |
|
683 |
- /* read the raw db command */ |
|
684 |
- line.s = buf; |
|
685 |
- if (!read_line( line.s, MAX_SIZE_LINE-1,fifo,&line.len) || !line.len) { |
|
686 |
- double_log("Raw db command expected"); |
|
687 |
- goto error; |
|
688 |
- } |
|
689 |
- trim_spaces(line); |
|
690 |
- /* run the command */ |
|
691 |
- if (db_cmd==RAWQUERY_CMD) |
|
692 |
- n = fifo_dbf.raw_query( fifo_db_con, line.s, 0); |
|
693 |
- else |
|
694 |
- n = fifo_dbf.raw_query( fifo_db_con, line.s, &select_res); |
|
695 |
- if (n!=0) { |
|
696 |
- double_log("Internal Server error - DB query failed"); |
|
697 |
- goto error; |
|
698 |
- } |
|
699 |
- /* any results? */ |
|
700 |
- if (db_cmd==RAWQUERYRES_CMD) { |
|
701 |
- /* get all response and write them into reply fifo */ |
|
702 |
- print_res( select_res, rpl); |
|
703 |
- /* free the query response */ |
|
704 |
- fifo_dbf.free_result( fifo_db_con, select_res); |
|
705 |
- } |
|
706 |
- /* done with success */ |
|
707 |
- goto done; |
|
708 |
- } |
|
709 |
- |
|
710 |
- /* read the table name */ |
|
711 |
- line.s = tbl_buf;/*buf;*/ |
|
712 |
- if (!read_line( line.s, MAX_SIZE_LINE-1, fifo, &line.len) || !line.len) { |
|
713 |
- double_log("Table name expected"); |
|
714 |
- goto error1; |
|
715 |
- } |
|
716 |
- trim_spaces(line); |
|
717 |
- |
|
718 |
- /* select the correct table */ |
|
719 |
- line.s[line.len] = 0; /* make it null terminated */ |
|
720 |
- |
|
721 |
- if (fifo_dbf.use_table( fifo_db_con, line.s) < 0) { |
|
722 |
- double_log("use_table function failed"); |
|
723 |
- goto error1; |
|
724 |
- } |
|
725 |
- |
|
726 |
- /*read 'where' avps */ |
|
727 |
- if (get_avps( fifo , keys2, ops2, vals2, &nr2, MAX_ARRAY)!=0 ) |
|
728 |
- goto error1; |
|
729 |
- |
|
730 |
- switch (db_cmd) { |
|
731 |
- case SELECT_CMD: |
|
732 |
- /* push the query */ |
|
733 |
- n = fifo_dbf.query( fifo_db_con, nr2?keys2:0, nr2?ops2:0, |
|
734 |
- nr2?vals2:0, nr1?keys1:0, nr2, nr1, 0, &select_res ); |
|
735 |
- if (n!=0) { |
|
736 |
- double_log("Internal Server error - DB query failed"); |
|
737 |
- goto error2; |
|
738 |
- } |
|
739 |
- /* get all response and write them into reply fifo */ |
|
740 |
- print_res( select_res, rpl); |
|
741 |
- /* free the query response */ |
|
742 |
- fifo_dbf.free_result( fifo_db_con, select_res); |
|
743 |
- break; |
|
744 |
- case UPDATE_CMD: |
|
745 |
- if (nr1==0) { |
|
746 |
- double_log("No values for update (empty first AVP list)"); |
|
747 |
- goto error; |
|
748 |
- } |
|
749 |
- /* all the operators must be '=' in the first avp list */ |
|
750 |
- for(n=0;n<nr1;n++) { |
|
751 |
- if (ops1[n][0]!='=' || ops1[n][1]!='\0') { |
|
752 |
- double_log("Invalid operator in updated fields " |
|
753 |
- "(expected = )"); |
|
754 |
- goto error; |
|
755 |
- } |
|
756 |
- }/*end for*/ |
|
757 |
- /* push the query */ |
|
758 |
- n = fifo_dbf.update( fifo_db_con, nr2?keys2:0, nr2?ops2:0, |
|
759 |
- nr2?vals2:0, keys1, vals1, nr2, nr1 ); |
|
760 |
- if (n!=0) { |
|
761 |
- double_log("Internal Server error - DB query failed"); |
|
762 |
- goto error2; |
|
763 |
- } |
|
764 |
- break; |
|
765 |
- case DELETE_CMD: |
|
766 |
- /* push the query */ |
|
767 |
- n = fifo_dbf.delete( fifo_db_con, nr2?keys2:0, nr2?ops2:0, |
|
768 |
- nr2?vals2:0, nr2); |
|
769 |
- if (n!=0) { |
|
770 |
- double_log("Internal Server error - DB query failed"); |
|
771 |
- goto error2; |
|
772 |
- } |
|
773 |
- break; |
|
774 |
- case INSERT_CMD: |
|
775 |
- if (nr2==0) { |
|
776 |
- double_log("Nothing to insert (empty AVP list)"); |
|
777 |
- goto error; |
|
778 |
- } |
|
779 |
- /* all the operators must be '=' */ |
|
780 |
- for(n=0;n<nr2;n++) { |
|
781 |
- if (ops2[n][0]!='=' || ops2[n][1]!='\0') { |
|
782 |
- double_log("Invalid operator in inserted fields " |
|
783 |
- "(expected = )"); |
|
784 |
- goto error; |
|
785 |
- } |
|
786 |
- }/*end for*/ |
|
787 |
- /* push the query */ |
|
788 |
- n = fifo_dbf.insert( fifo_db_con, nr2?keys2:0, nr2?vals2:0, nr2); |
|
789 |
- if (n!=0) { |
|
790 |
- double_log("Internal Server error - DB query failed"); |
|
791 |
- goto error2; |
|
792 |
- } |
|
793 |
- break; |
|
794 |
- } |
|
795 |
- |
|
796 |
- /* success */ |
|
797 |
-done: |
|
798 |
- ret = 0; |
|
799 |
-error2: |
|
800 |
- for(;nr2;nr2--) |
|
801 |
- pkg_free( (void*)keys2[nr2-1] ); |
|
802 |
-error1: |
|
803 |
- for(;nr1;nr1--) |
|
804 |
- pkg_free( (void*)keys1[nr1-1] ); |
|
805 |
-error: |
|
806 |
- if (rpl) fclose(rpl); |
|
807 |
- return ret; |
|
808 |
-} |
|
809 |
- |
... | ... |
@@ -383,9 +383,9 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
383 | 383 |
/* we have a new avp */ |
384 | 384 |
if (*nr<max_nr) { |
385 | 385 |
/* parse the line key|op|val */ |
386 |
- c = line.s; |
|
386 |
+ c = (unsigned char*)line.s; |
|
387 | 387 |
/* parse the key name */ |
388 |
- for( key.s=c ; *c && (isalnum((int)*c)||*c=='_') ; c++ ); |
|
388 |
+ for( key.s=(char*)c ; *c && (isalnum((int)*c)||*c=='_') ; c++ ); |
|
389 | 389 |
if (!*c) goto parse_error; |
390 | 390 |
key.len = (char*)c-key.s; |
391 | 391 |
if (key.len==0) goto parse_error; |
... | ... |
@@ -393,7 +393,7 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
393 | 393 |
for( sp_found=0 ; *c && isspace((int)*c) ; c++,sp_found=1 ); |
394 | 394 |
if (!*c) goto parse_error; |
395 | 395 |
/* parse the operator */ |
396 |
- op.s = c; |
|
396 |
+ op.s = (char*)c; |
|
397 | 397 |
switch (*c) { |
398 | 398 |
case '<': |
399 | 399 |
case '>': |
... | ... |
@@ -417,24 +417,24 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
417 | 417 |
for( ; *c && isspace((int)*c) ; c++ ); |
418 | 418 |
if (!*c) goto parse_error; |
419 | 419 |
/* get value */ |
420 |
- val.s = c; |
|
420 |
+ val.s = (char*)c; |
|
421 | 421 |
val.len = line.len - ((char*)c-line.s); |
422 | 422 |
if (val.len==0) goto parse_error; |
423 | 423 |
if (parse_db_value( &val, &vals[*nr], &p_val)!=0) |
424 | 424 |
goto error; |
425 | 425 |
/* duplicate the avp -> make all null terminated */ |
426 |
- c = (char*)pkg_malloc(key.len+op.len+2+(p_val?p_val->len+1:0)); |
|
426 |
+ c = pkg_malloc(key.len+op.len+2+(p_val?p_val->len+1:0)); |
|
427 | 427 |
if (c==0) { |
428 | 428 |
semidouble_log("no more pkg memory"); |
429 | 429 |
goto error; |
430 | 430 |
} |
431 | 431 |
/*copy the key */ |
432 |
- keys[*nr] = c; |
|
432 |
+ keys[*nr] = (char*)c; |
|
433 | 433 |
memcpy( c, key.s, key.len); |
434 | 434 |
c[key.len] = 0; |
435 | 435 |
c += key.len + 1; |
436 | 436 |
/*copy the op */ |
437 |
- ops[*nr] = c; |
|
437 |
+ ops[*nr] = (char*)c; |
|
438 | 438 |
memcpy( c, op.s, op.len); |
439 | 439 |
c[op.len] = 0; |
440 | 440 |
c += op.len + 1; |
... | ... |
@@ -442,7 +442,7 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
442 | 442 |
if (p_val) { |
443 | 443 |
memcpy( c, p_val->s, p_val->len); |
444 | 444 |
c[p_val->len] = 0; |
445 |
- p_val->s = c; |
|
445 |
+ p_val->s = (char*)c; |
|
446 | 446 |
} |
447 | 447 |
/* done */ |
448 | 448 |
(*nr)++; |
... | ... |
@@ -108,7 +108,8 @@ |
108 | 108 |
#define get_int(_p_,_end_,_res_,_n_,_err_s_,_err_) \ |
109 | 109 |
do { \ |
110 | 110 |
_res_ = 0;\ |
111 |
- for( _n_=0 ; (_p_)<(_end_) && isdigit(*(_p_)) ; (_p_)++,(_n_)++)\ |
|
111 |
+ for( _n_=0 ; (_p_)<(_end_) && isdigit((int)(unsigned char)*(_p_)) ; \ |
|
112 |
+ (_p_)++,(_n_)++)\ |
|
112 | 113 |
(_res_)=(_res_)*10+(*(_p_)-'0');\ |
113 | 114 |
if ((_n_)==0) {\ |
114 | 115 |
double_log( _err_s_ );\ |
... | ... |
@@ -289,7 +290,8 @@ static inline int parse_db_value( str *s, db_val_t *val, str **ret_s) |
289 | 290 |
val->type = DB_DATETIME; |
290 | 291 |
val->val.time_val = mktime( &td ); |
291 | 292 |
/*DBG("DBG: <%.*s> is %s\n",s->len,s->s,ctime(&val->val.time_val));*/ |
292 |
- } else if ( (*(p=s->s)=='+') || (*p=='-') || isdigit(*p) ) { |
|
293 |
+ } else if ( (*(p=s->s)=='+') || (*p=='-') || |
|
294 |
+ isdigit((int)(unsigned char)*p) ) { |
|
293 | 295 |
/* can be a DB_INT / DB_DOUBLE / DB_BITMAP value */ |
294 | 296 |
if (sgn_str2float( s, &nr, &nr_type)!=0) { |
295 | 297 |
double_log("Bad int/float value format (expected [+/-]nr[.nr])"); |
... | ... |
@@ -360,7 +362,7 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
360 | 362 |
{ |
361 | 363 |
str line; |
362 | 364 |
str key,op,val; |
363 |
- char *c; |
|
365 |
+ unsigned char *c; |
|
364 | 366 |
str *p_val; |
365 | 367 |
int sp_found; |
366 | 368 |
|
... | ... |
@@ -383,12 +385,12 @@ static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, |
383 | 385 |
/* parse the line key|op|val */ |
384 | 386 |
c = line.s; |
385 | 387 |
/* parse the key name */ |
386 |
- for( key.s=c ; *c && (isalnum(*c)||*c=='_') ; c++ ); |
|
388 |
+ for( key.s=c ; *c && (isalnum((int)*c)||*c=='_') ; c++ ); |
|
387 | 389 |