1 /*
2 * $Id$
3 *
4 * Copyright (C) 2001-2003 FhG Fokus
5 *
6 * This file is part of Kamailio, a free SIP server.
7 *
8 * Kamailio 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 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 /*
23 * History:
24 * --------
25 * 2004-06-06 updated to the new DB api (andrei)
26 */
27
28 #include "../../core/mem/shm_mem.h"
29 #include "../../lib/srdb1/db.h"
30 #include "../../core/dprint.h"
31 #include "../../core/str.h"
32 #include "cpl_db.h"
33
34 #define TABLE_VERSION 1
35
36 static db1_con_t* db_hdl=0;
37 static db_func_t cpl_dbf;
38
39 str cpl_username_col = str_init("username");
40 str cpl_domain_col = str_init("domain");
41 str cpl_xml_col = str_init("cpl_xml");
42 str cpl_bin_col = str_init("cpl_bin");
43
44
cpl_db_bind(const str * db_url,const str * db_table)45 int cpl_db_bind(const str* db_url, const str *db_table)
46 {
47 if (db_bind_mod(db_url, &cpl_dbf )) {
48 LM_CRIT("cannot bind to database module! "
49 "Did you forget to load a database module ?\n");
50 return -1;
51 }
52
53 /* CPL module uses all database functions */
54 if (!DB_CAPABILITY(cpl_dbf, DB_CAP_ALL)) {
55 LM_CRIT("Database modules does not "
56 "provide all functions needed by cpl-c module\n");
57 return -1;
58 }
59
60 if ( cpl_db_init( db_url, db_table) )
61 return -1;
62
63 if(db_check_table_version(&cpl_dbf, db_hdl, db_table, TABLE_VERSION) < 0) {
64 str tmp = *db_table;
65 DB_TABLE_VERSION_ERROR(tmp);
66 cpl_db_close();
67 return -1;
68 }
69
70 cpl_db_close();
71 return 0;
72 }
73
74
75
cpl_db_init(const str * db_url,const str * db_table)76 int cpl_db_init(const str* db_url, const str* db_table)
77 {
78 if (cpl_dbf.init==0){
79 LM_CRIT("BUG - unbound database module\n");
80 return -1;
81 }
82
83 db_hdl=cpl_dbf.init(db_url);
84
85 if (db_hdl==0){
86 LM_CRIT("cannot initialize database connection\n");
87 return -1;
88 }
89
90 if (cpl_dbf.use_table(db_hdl, db_table)<0) {
91 LM_CRIT("cannot select table \"%.*s\"\n",db_table->len, db_table->s);
92 cpl_db_close();
93 return -1;
94 }
95
96 return 0;
97 }
98
99
cpl_db_close(void)100 void cpl_db_close(void)
101 {
102 if (db_hdl && cpl_dbf.close){
103 cpl_dbf.close(db_hdl);
104 db_hdl=0;
105 }
106 }
107
108
109 /* gets from database the cpl script in binary format; the returned script is
110 * allocated in shared memory
111 * Returns: 1 - success
112 * -1 - error
113 */
get_user_script(str * username,str * domain,str * script,str * key)114 int get_user_script(str *username, str *domain, str *script, str* key)
115 {
116 db_key_t keys_cmp[2];
117 db_key_t keys_ret[1];
118 db_val_t vals[2];
119 db1_res_t *res = NULL;
120 int n;
121
122 keys_cmp[0] = &cpl_username_col;
123 keys_cmp[1] = &cpl_domain_col;
124 keys_ret[0] = key;
125
126 LM_DBG("fetching script for user <%.*s>\n",
127 username->len,username->s);
128 vals[0].type = DB1_STR;
129 vals[0].nul = 0;
130 vals[0].val.str_val = *username;
131 n = 1;
132 if (domain) {
133 vals[1].type = DB1_STR;
134 vals[1].nul = 0;
135 vals[1].val.str_val = *domain;
136 n++;
137 }
138
139 if (cpl_dbf.query(db_hdl, keys_cmp, 0, vals, keys_ret, n, 1, NULL, &res)
140 < 0){
141 LM_ERR("db_query failed\n");
142 goto error;
143 }
144
145 if (res->n==0) {
146 LM_DBG("user <%.*s> not found in db -> probably "
147 "he has no script\n",username->len, username->s);
148 script->s = 0;
149 script->len = 0;
150 } else {
151 if (res->rows[0].values[0].nul) {
152 LM_DBG("user <%.*s> has a NULL script\n",
153 username->len, username->s);
154 script->s = 0;
155 script->len = 0;
156 } else {
157 LM_DBG("we got the script len=%d\n",
158 res->rows[0].values[0].val.blob_val.len);
159 script->len = res->rows[0].values[0].val.blob_val.len;
160 script->s = shm_malloc( script->len );
161 if (!script->s) {
162 LM_ERR("no free sh_mem\n");
163 goto error;
164 }
165 memcpy( script->s, res->rows[0].values[0].val.blob_val.s,
166 script->len);
167 }
168 }
169
170 cpl_dbf.free_result( db_hdl, res);
171 return 1;
172 error:
173 if (res)
174 cpl_dbf.free_result( db_hdl, res);
175 script->s = 0;
176 script->len = 0;
177 return -1;
178 }
179
180
181
182 /* inserts into database a cpl script in XML format(xml) along with its binary
183 * format (bin)
184 * Returns: 1 - success
185 * -1 - error
186 */
write_to_db(str * username,str * domain,str * xml,str * bin)187 int write_to_db(str *username, str *domain, str *xml, str *bin)
188 {
189 db_key_t keys[4];
190 db_val_t vals[4];
191 db1_res_t *res = NULL;
192 int n;
193
194 /* lets see if the user is already in database */
195 keys[2] = &cpl_username_col;
196 vals[2].type = DB1_STR;
197 vals[2].nul = 0;
198 vals[2].val.str_val = *username;
199 n = 1;
200 if (domain) {
201 keys[3] = &cpl_domain_col;
202 vals[3].type = DB1_STR;
203 vals[3].nul = 0;
204 vals[3].val.str_val = *domain;
205 n++;
206 }
207 if (cpl_dbf.query(db_hdl, keys+2, 0, vals+2, keys+2, n, 1, NULL, &res)<0) {
208 LM_ERR("db_query failed\n");
209 goto error;
210 }
211 if (res->n>1) {
212 LM_ERR("Inconsistent CPL database:"
213 " %d records for user %.*s\n",res->n,username->len,username->s);
214 goto error;
215 }
216
217 /* cpl text */
218 keys[0] = &cpl_xml_col;
219 vals[0].type = DB1_BLOB;
220 vals[0].nul = 0;
221 vals[0].val.blob_val.s = xml->s;
222 vals[0].val.blob_val.len = xml->len;
223 n++;
224 /* cpl bin */
225 keys[1] = &cpl_bin_col;
226 vals[1].type = DB1_BLOB;
227 vals[1].nul = 0;
228 vals[1].val.blob_val.s = bin->s;
229 vals[1].val.blob_val.len = bin->len;
230 n++;
231 /* insert or update ? */
232 if (res->n==0) {
233 LM_DBG("no user %.*s in CPL database->insert\n",
234 username->len,username->s);
235 if (cpl_dbf.insert(db_hdl, keys, vals, n) < 0) {
236 LM_ERR("insert failed !\n");
237 goto error;
238 }
239 } else {
240 LM_DBG("user %.*s already in CPL database ->"
241 " update\n",username->len,username->s);
242 if (cpl_dbf.update(db_hdl, keys+2, 0, vals+2, keys, vals, n-2, 2) < 0) {
243 LM_ERR("update failed !\n");
244 goto error;
245 }
246 }
247
248 return 1;
249 error:
250 return -1;
251 }
252
253
254
255 /* delete from database the entity record for a given user - if a user has no
256 * script, he will be removed completely from db; users without script are not
257 * allowed into db ;-)
258 * Returns: 1 - success
259 * -1 - error
260 */
rmv_from_db(str * username,str * domain)261 int rmv_from_db(str *username, str *domain)
262 {
263 db_key_t keys[2];
264 db_val_t vals[2];
265 int n;
266
267 /* username */
268 keys[0] = &cpl_username_col;
269 vals[0].type = DB1_STR;
270 vals[0].nul = 0;
271 vals[0].val.str_val = *username;
272 n = 1;
273 if (domain) {
274 keys[1] = &cpl_domain_col;
275 vals[1].type = DB1_STR;
276 vals[1].nul = 0;
277 vals[1].val.str_val = *domain;
278 n++;
279 }
280
281 if (cpl_dbf.delete(db_hdl, keys, NULL, vals, n) < 0) {
282 LM_ERR("failed to delete script for "
283 "user \"%.*s\"\n",username->len,username->s);
284 return -1;
285 }
286
287 return 1;
288 }
289
290