1 /*
2  * db_berkeley module, portions of this code were templated using
3  * the dbtext and postgres modules.
4 
5  * Copyright (C) 2007 Cisco Systems
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
9  * Kamailio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * Kamailio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24 
25 /*! \file
26  * Berkeley DB :
27  *
28  * \ingroup database
29  */
30 
31 
32 #include "../../lib/srdb1/db_val.h"
33 #include "../../lib/srdb1/db_ut.h"
34 #include "db_berkeley.h"
35 #include "km_bdb_res.h"
36 #include "km_bdb_val.h"
37 #include <string.h>
38 
39 /**
40  * A copy of db_ut::db_time2str EXCEPT does not wrap the date in single-quotes
41  *
42  * Convert a time_t value to string (w.o single-quote)
43  * \param _v source value
44  * \param _s target string
45  * \param _l available length and target length
46  * \return -1 on error, 0 on success
47  * \todo This functions add quotes to the time value. This
48  * should be done in the val2str function, as some databases
49  * like db_berkeley don't need or like this at all.
50  */
km_bdb_time2str(time_t _v,char * _s,int * _l)51 int km_bdb_time2str(time_t _v, char *_s, int *_l)
52 {
53 	struct tm *t;
54 	int l;
55 
56 	if((!_s) || (!_l) || (*_l < 2)) {
57 		LM_ERR("Invalid parameter value\n");
58 		return -1;
59 	}
60 
61 	//	*_s++ = '\'';
62 
63 	/* Convert time_t structure to format accepted by the database */
64 	t = localtime(&_v);
65 	l = strftime(_s, *_l - 1, "%Y-%m-%d %H:%M:%S", t);
66 
67 	if(l == 0) {
68 		LM_ERR("Error during time conversion\n");
69 		/* the value of _s is now unspecified */
70 		_s = NULL;
71 		_l = 0;
72 		return -1;
73 	}
74 	*_l = l;
75 
76 	//	*(_s + l) = '\'';
77 	//	*_l = l + 2;
78 	return 0;
79 }
80 
81 /**
82  * Does not copy strings
83  */
bdb_str2val(db_type_t _t,db_val_t * _v,char * _s,int _l)84 int bdb_str2val(db_type_t _t, db_val_t *_v, char *_s, int _l)
85 {
86 
87 	static str dummy_string = {"", 0};
88 
89 	if(!_s) {
90 		memset(_v, 0, sizeof(db_val_t));
91 		/* Initialize the string pointers to a dummy empty
92 		 * string so that we do not crash when the NULL flag
93 		 * is set but the module does not check it properly
94 		 */
95 		VAL_STRING(_v) = dummy_string.s;
96 		VAL_STR(_v) = dummy_string;
97 		VAL_BLOB(_v) = dummy_string;
98 		VAL_TYPE(_v) = _t;
99 		VAL_NULL(_v) = 1;
100 		return 0;
101 	}
102 	VAL_NULL(_v) = 0;
103 
104 	switch(_t) {
105 		case DB1_INT:
106 			if(db_str2int(_s, &VAL_INT(_v)) < 0) {
107 				LM_ERR("Error while converting INT value from string\n");
108 				return -2;
109 			} else {
110 				VAL_TYPE(_v) = DB1_INT;
111 				return 0;
112 			}
113 			break;
114 
115 		case DB1_BIGINT:
116 			LM_ERR("BIGINT not supported");
117 			return -1;
118 
119 		case DB1_BITMAP:
120 			if(db_str2int(_s, &VAL_INT(_v)) < 0) {
121 				LM_ERR("Error while converting BITMAP value from string\n");
122 				return -3;
123 			} else {
124 				VAL_TYPE(_v) = DB1_BITMAP;
125 				return 0;
126 			}
127 			break;
128 
129 		case DB1_DOUBLE:
130 			if(db_str2double(_s, &VAL_DOUBLE(_v)) < 0) {
131 				LM_ERR("Error while converting DOUBLE value from string\n");
132 				return -4;
133 			} else {
134 				VAL_TYPE(_v) = DB1_DOUBLE;
135 				return 0;
136 			}
137 			break;
138 
139 		case DB1_STRING:
140 			VAL_STRING(_v) = _s;
141 			VAL_TYPE(_v) = DB1_STRING;
142 			VAL_FREE(_v) = 1;
143 
144 			if(strlen(_s) == 4 && !strncasecmp(_s, "NULL", 4))
145 				VAL_NULL(_v) = 1;
146 
147 			return 0;
148 
149 		case DB1_STR:
150 			VAL_STR(_v).s = (char *)_s;
151 			VAL_STR(_v).len = _l;
152 			VAL_TYPE(_v) = DB1_STR;
153 			VAL_FREE(_v) = 1;
154 
155 			if(strlen(_s) == 4 && !strncasecmp(_s, "NULL", 4))
156 				VAL_NULL(_v) = 1;
157 
158 			return 0;
159 
160 		case DB1_DATETIME:
161 			if(db_str2time(_s, &VAL_TIME(_v)) < 0) {
162 				LM_ERR("Error converting datetime\n");
163 				return -5;
164 			} else {
165 				VAL_TYPE(_v) = DB1_DATETIME;
166 				return 0;
167 			}
168 			break;
169 
170 		case DB1_BLOB:
171 			VAL_BLOB(_v).s = _s;
172 			VAL_TYPE(_v) = DB1_BLOB;
173 			LM_DBG("got blob len %d\n", _l);
174 			return 0;
175 		default:
176 			break;
177 	}
178 
179 	return -6;
180 }
181 
182 
183 /*
184  * Used when converting result from a query
185  */
km_bdb_val2str(db_val_t * _v,char * _s,int * _len)186 int km_bdb_val2str(db_val_t *_v, char *_s, int *_len)
187 {
188 	int l;
189 
190 	if(VAL_NULL(_v)) {
191 		*_len = snprintf(_s, *_len, "NULL");
192 		return 0;
193 	}
194 
195 	switch(VAL_TYPE(_v)) {
196 		case DB1_INT:
197 			if(db_int2str(VAL_INT(_v), _s, _len) < 0) {
198 				LM_ERR("Error while converting int to string\n");
199 				return -2;
200 			} else {
201 				LM_DBG("Converted int to string\n");
202 				return 0;
203 			}
204 			break;
205 
206 		case DB1_BITMAP:
207 			if(db_int2str(VAL_INT(_v), _s, _len) < 0) {
208 				LM_ERR("Error while converting bitmap to string\n");
209 				return -3;
210 			} else {
211 				LM_DBG("Converted bitmap to string\n");
212 				return 0;
213 			}
214 			break;
215 
216 		case DB1_DOUBLE:
217 			if(db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) {
218 				LM_ERR("Error while converting double  to string\n");
219 				return -3;
220 			} else {
221 				LM_DBG("Converted double to string\n");
222 				return 0;
223 			}
224 			break;
225 
226 		case DB1_STRING:
227 			l = strlen(VAL_STRING(_v));
228 			if(*_len < l) {
229 				LM_ERR("Destination buffer too short for string\n");
230 				return -4;
231 			} else {
232 				LM_DBG("Converted string to string\n");
233 				strncpy(_s, VAL_STRING(_v), l);
234 				_s[l] = 0;
235 				*_len = l;
236 				return 0;
237 			}
238 			break;
239 
240 		case DB1_STR:
241 			l = VAL_STR(_v).len;
242 			if(*_len < l) {
243 				LM_ERR("Destination buffer too short for str\n");
244 				return -5;
245 			} else {
246 				LM_DBG("Converted str to string\n");
247 				strncpy(_s, VAL_STR(_v).s, VAL_STR(_v).len);
248 				*_len = VAL_STR(_v).len;
249 				return 0;
250 			}
251 			break;
252 
253 		case DB1_DATETIME:
254 			if(km_bdb_time2str(VAL_TIME(_v), _s, _len) < 0) {
255 				LM_ERR("Error while converting time_t to string\n");
256 				return -6;
257 			} else {
258 				LM_DBG("Converted time_t to string\n");
259 				return 0;
260 			}
261 			break;
262 
263 		case DB1_BLOB:
264 			l = VAL_BLOB(_v).len;
265 			if(*_len < l) {
266 				LM_ERR("Destination buffer too short for blob\n");
267 				return -7;
268 			} else {
269 				LM_DBG("Converting BLOB [%s]\n", _s);
270 				_s = VAL_BLOB(_v).s;
271 				*_len = 0;
272 				return -8;
273 			}
274 			break;
275 
276 		default:
277 			LM_ERR("Unknown data type\n");
278 			return -8;
279 	}
280 }
281