659f9686e702fa23e676e544d0dd72e0d96b5c85
[asterisk/asterisk.git] / apps / app_db.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  * Copyright (C) 2003, Jefferson Noxon
6  *
7  * Mark Spencer <markster@digium.com>
8  * Jefferson Noxon <jeff@debian.org>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20
21 /*! \file
22  *
23  * \brief Database access functions
24  *
25  * \ingroup applications
26  */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include "asterisk/options.h"
39 #include "asterisk/file.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/module.h"
44 #include "asterisk/astdb.h"
45 #include "asterisk/lock.h"
46 #include "asterisk/options.h"
47
48 static char *tdesc = "Database access functions for Asterisk extension logic";
49
50 static char *g_descrip =
51         "  DBget(varname=family/key[|options]): Retrieves a value from the Asterisk\n"
52         "database and stores it in the given variable.\n"
53         "  The option string may contain the following character:\n"
54         "       'j' -- jump to +101 priority if the requested family/key isn't found.\n"
55         "  This application sets the following channel variable upon completion:\n"
56         "     DBGETSTATUS       The status of the attempt as a text string, one of\n"
57         "             FOUND | NOTFOUND \n";
58
59 static char *p_descrip =
60         "  DBput(family/key=value): Stores the given value in the Asterisk\n"
61         "database.\n";
62
63 static char *d_descrip =
64         "  DBdel(family/key): Deletes a key from the Asterisk database.\n";
65
66 static char *dt_descrip =
67         "  DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
68         "database.\n";
69
70 static char *g_app = "DBget";
71 static char *p_app = "DBput";
72 static char *d_app = "DBdel";
73 static char *dt_app = "DBdeltree";
74
75 static char *g_synopsis = "Retrieve a value from the database";
76 static char *p_synopsis = "Store a value in the database";
77 static char *d_synopsis = "Delete a key from the database";
78 static char *dt_synopsis = "Delete a family or keytree from the database";
79
80 STANDARD_LOCAL_USER;
81
82 LOCAL_USER_DECL;
83
84 static int deltree_exec(struct ast_channel *chan, void *data)
85 {
86         char *argv, *family, *keytree;
87         struct localuser *u;
88
89         LOCAL_USER_ADD(u);
90
91         argv = ast_strdupa(data);
92         if (!argv) {
93                 ast_log(LOG_ERROR, "Memory allocation failed\n");
94                 LOCAL_USER_REMOVE(u);
95                 return 0;
96         }
97
98         if (strchr(argv, '/')) {
99                 family = strsep(&argv, "/");
100                 keytree = strsep(&argv, "\0");
101                         if (!family || !keytree) {
102                                 ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
103                                 LOCAL_USER_REMOVE(u);
104                                 return 0;
105                         }
106                 if (ast_strlen_zero(keytree))
107                         keytree = 0;
108         } else {
109                 family = argv;
110                 keytree = 0;
111         }
112
113         if (option_verbose > 2) {
114                 if (keytree)
115                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
116                 else
117                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
118         }
119
120         if (ast_db_deltree(family, keytree)) {
121                 if (option_verbose > 2)
122                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
123         }
124
125         LOCAL_USER_REMOVE(u);
126
127         return 0;
128 }
129
130 static int del_exec(struct ast_channel *chan, void *data)
131 {
132         char *argv, *family, *key;
133         struct localuser *u;
134
135         LOCAL_USER_ADD(u);
136
137         argv = ast_strdupa(data);
138         if (!argv) {
139                 ast_log (LOG_ERROR, "Memory allocation failed\n");
140                 LOCAL_USER_REMOVE(u);
141                 return 0;
142         }
143
144         if (strchr(argv, '/')) {
145                 family = strsep(&argv, "/");
146                 key = strsep(&argv, "\0");
147                 if (!family || !key) {
148                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
149                         LOCAL_USER_REMOVE(u);
150                         return 0;
151                 }
152                 if (option_verbose > 2)
153                         ast_verbose(VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
154                 if (ast_db_del(family, key)) {
155                         if (option_verbose > 2)
156                                 ast_verbose(VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
157                 }
158         } else {
159                 ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
160         }
161
162         LOCAL_USER_REMOVE(u);
163         
164         return 0;
165 }
166
167 static int put_exec(struct ast_channel *chan, void *data)
168 {
169         char *argv, *value, *family, *key;
170         static int dep_warning = 0;
171         struct localuser *u;
172
173         LOCAL_USER_ADD(u);
174
175         if (!dep_warning) {
176                 ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
177                 dep_warning = 1;
178         }
179         
180         argv = ast_strdupa(data);
181         if (!argv) {
182                 ast_log(LOG_ERROR, "Memory allocation failed\n");
183                 LOCAL_USER_REMOVE(u);
184                 return 0;
185         }
186
187         if (strchr(argv, '/') && strchr(argv, '=')) {
188                 family = strsep(&argv, "/");
189                 key = strsep(&argv, "=");
190                 value = strsep(&argv, "\0");
191                 if (!value || !family || !key) {
192                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
193                         LOCAL_USER_REMOVE(u);
194                         return 0;
195                 }
196                 if (option_verbose > 2)
197                         ast_verbose(VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
198                 if (ast_db_put(family, key, value)) {
199                         if (option_verbose > 2)
200                                 ast_verbose(VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
201                 }
202
203         } else  {
204                 ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
205         }
206
207         LOCAL_USER_REMOVE(u);
208
209         return 0;
210 }
211
212 static int get_exec(struct ast_channel *chan, void *data)
213 {
214         char *argv, *varname, *family, *key, *options = NULL;
215         char dbresult[256];
216         static int dep_warning = 0;
217         int priority_jump = 0;
218         struct localuser *u;
219
220         LOCAL_USER_ADD(u);
221
222         if (!dep_warning) {
223                 ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
224                 dep_warning = 1;
225         }
226         
227         argv = ast_strdupa(data);
228         if (!argv) {
229                 ast_log(LOG_ERROR, "Memory allocation failed\n");
230                 LOCAL_USER_REMOVE(u);
231                 return 0;
232         }
233
234         if (strchr(argv, '=') && strchr(argv, '/')) {
235                 varname = strsep(&argv, "=");
236                 family = strsep(&argv, "/");
237                 if (strchr((void *)&argv, '|')) {
238                         key = strsep(&argv, "|");
239                         options = strsep(&argv, "\0");
240                 } else
241                         key = strsep(&argv, "\0");
242                         
243                 if (!varname || !family || !key) {
244                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
245                         LOCAL_USER_REMOVE(u);
246                         return 0;
247                 }
248
249                 if (options) {
250                         if (strchr(options, 'j'))
251                                 priority_jump = 1;
252                 }
253                         
254                 if (option_verbose > 2)
255                         ast_verbose(VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
256                 if (!ast_db_get(family, key, dbresult, sizeof (dbresult) - 1)) {
257                         pbx_builtin_setvar_helper(chan, varname, dbresult);
258                         if (option_verbose > 2)
259                                 ast_verbose(VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
260                         pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "FOUND");
261                 } else {
262                         if (option_verbose > 2)
263                         ast_verbose(VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
264                         if (priority_jump || option_priority_jumping) {
265                                 /* Send the call to n+101 priority, where n is the current priority */
266                                 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
267                         }
268                         pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "NOTFOUND");
269                 }
270         } else {
271                 ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
272         }
273
274         LOCAL_USER_REMOVE(u);
275
276         return 0;
277 }
278
279 int unload_module(void)
280 {
281         int retval;
282
283         retval = ast_unregister_application(dt_app);
284         retval |= ast_unregister_application(d_app);
285         retval |= ast_unregister_application(p_app);
286         retval |= ast_unregister_application(g_app);
287
288         STANDARD_HANGUP_LOCALUSERS;
289
290         return retval;
291 }
292
293 int load_module(void)
294 {
295         int retval;
296
297         retval = ast_register_application(g_app, get_exec, g_synopsis, g_descrip);
298         retval |= ast_register_application(p_app, put_exec, p_synopsis, p_descrip);
299         retval |= ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
300         retval |= ast_register_application(dt_app, deltree_exec, dt_synopsis, dt_descrip);
301         
302         return retval;
303 }
304
305 char *description(void)
306 {
307         return tdesc;
308 }
309
310 int usecount(void)
311 {
312         int res;
313         STANDARD_USECOUNT(res);
314         return res;
315 }
316
317 char *key()
318 {
319         return ASTERISK_GPL_KEY;
320 }