channel: Clear channel flag in error branch.
[asterisk/asterisk.git] / funcs / func_db.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005-2006, Russell Bryant <russelb@clemson.edu> 
5  *
6  * func_db.c adapted from the old app_db.c, copyright by the following people 
7  * Copyright (C) 2005, Mark Spencer <markster@digium.com>
8  * Copyright (C) 2003, 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 Functions for interaction with the Asterisk database
24  *
25  * \author Russell Bryant <russelb@clemson.edu>
26  *
27  * \ingroup functions
28  */
29
30 /*** MODULEINFO
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 #include <regex.h>
37
38 #include "asterisk/module.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/app.h"
43 #include "asterisk/astdb.h"
44
45 /*** DOCUMENTATION
46         <function name="DB" language="en_US">
47                 <synopsis>
48                         Read from or write to the Asterisk database.
49                 </synopsis>
50                 <syntax argsep="/">
51                         <parameter name="family" required="true" />
52                         <parameter name="key" required="true" />
53                 </syntax>
54                 <description>
55                         <para>This function will read from or write a value to the Asterisk database.  On a
56                         read, this function returns the corresponding value from the database, or blank
57                         if it does not exist.  Reading a database value will also set the variable
58                         DB_RESULT.  If you wish to find out if an entry exists, use the DB_EXISTS
59                         function.</para>
60                 </description>
61                 <see-also>
62                         <ref type="application">DBdel</ref>
63                         <ref type="function">DB_DELETE</ref>
64                         <ref type="application">DBdeltree</ref>
65                         <ref type="function">DB_EXISTS</ref>
66                 </see-also>
67         </function>
68         <function name="DB_EXISTS" language="en_US">
69                 <synopsis>
70                         Check to see if a key exists in the Asterisk database.
71                 </synopsis>
72                 <syntax argsep="/">
73                         <parameter name="family" required="true" />
74                         <parameter name="key" required="true" />
75                 </syntax>
76                 <description>
77                         <para>This function will check to see if a key exists in the Asterisk
78                         database. If it exists, the function will return <literal>1</literal>. If not,
79                         it will return <literal>0</literal>.  Checking for existence of a database key will
80                         also set the variable DB_RESULT to the key's value if it exists.</para>
81                 </description>
82                 <see-also>
83                         <ref type="function">DB</ref>
84                 </see-also>
85         </function>
86         <function name="DB_KEYS" language="en_US">
87                 <synopsis>
88                         Obtain a list of keys within the Asterisk database.
89                 </synopsis>
90                 <syntax>
91                         <parameter name="prefix" />
92                 </syntax>
93                 <description>
94                         <para>This function will return a comma-separated list of keys existing
95                         at the prefix specified within the Asterisk database.  If no argument is
96                         provided, then a list of key families will be returned.</para>
97                 </description>
98         </function>
99         <function name="DB_DELETE" language="en_US">
100                 <synopsis>
101                         Return a value from the database and delete it.
102                 </synopsis>
103                 <syntax argsep="/">
104                         <parameter name="family" required="true" />
105                         <parameter name="key" required="true" />
106                 </syntax>
107                 <description>
108                         <para>This function will retrieve a value from the Asterisk database
109                         and then remove that key from the database. <variable>DB_RESULT</variable>
110                         will be set to the key's value if it exists.</para>
111                         <note>
112                                 <para>If <literal>live_dangerously</literal> in <literal>asterisk.conf</literal>
113                                 is set to <literal>no</literal>, this function can only be read from the
114                                 dialplan, and not directly from external protocols. It can, however, be
115                                 executed as a write operation (<literal>DB_DELETE(family, key)=ignored</literal>)</para>
116                         </note>
117                 </description>
118                 <see-also>
119                         <ref type="application">DBdel</ref>
120                         <ref type="function">DB</ref>
121                         <ref type="application">DBdeltree</ref>
122                 </see-also>
123         </function>
124  ***/
125
126 static int function_db_read(struct ast_channel *chan, const char *cmd,
127                             char *parse, char *buf, size_t len)
128 {
129         AST_DECLARE_APP_ARGS(args,
130                 AST_APP_ARG(family);
131                 AST_APP_ARG(key);
132         );
133
134         buf[0] = '\0';
135
136         if (ast_strlen_zero(parse)) {
137                 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
138                 return -1;
139         }
140
141         AST_NONSTANDARD_APP_ARGS(args, parse, '/');
142
143         if (args.argc < 2) {
144                 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
145                 return -1;
146         }
147
148         if (ast_db_get(args.family, args.key, buf, len - 1)) {
149                 ast_debug(1, "DB: %s/%s not found in database.\n", args.family, args.key);
150         } else {
151                 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
152         }
153
154         return 0;
155 }
156
157 static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse,
158                              const char *value)
159 {
160         AST_DECLARE_APP_ARGS(args,
161                 AST_APP_ARG(family);
162                 AST_APP_ARG(key);
163         );
164
165         if (ast_strlen_zero(parse)) {
166                 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=<value>\n");
167                 return -1;
168         }
169
170         AST_NONSTANDARD_APP_ARGS(args, parse, '/');
171
172         if (args.argc < 2) {
173                 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=value\n");
174                 return -1;
175         }
176
177         if (ast_db_put(args.family, args.key, value)) {
178                 ast_log(LOG_WARNING, "DB: Error writing value to database.\n");
179         }
180
181         return 0;
182 }
183
184 static struct ast_custom_function db_function = {
185         .name = "DB",
186         .read = function_db_read,
187         .write = function_db_write,
188 };
189
190 static int function_db_exists(struct ast_channel *chan, const char *cmd,
191                               char *parse, char *buf, size_t len)
192 {
193         AST_DECLARE_APP_ARGS(args,
194                 AST_APP_ARG(family);
195                 AST_APP_ARG(key);
196         );
197
198         buf[0] = '\0';
199
200         if (ast_strlen_zero(parse)) {
201                 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
202                 return -1;
203         }
204
205         AST_NONSTANDARD_APP_ARGS(args, parse, '/');
206
207         if (args.argc < 2) {
208                 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
209                 return -1;
210         }
211
212         if (ast_db_get(args.family, args.key, buf, len - 1)) {
213                 strcpy(buf, "0");
214         } else {
215                 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
216                 strcpy(buf, "1");
217         }
218
219         return 0;
220 }
221
222 static struct ast_custom_function db_exists_function = {
223         .name = "DB_EXISTS",
224         .read = function_db_exists,
225         .read_max = 2,
226 };
227
228 static int function_db_keys(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **result, ssize_t maxlen)
229 {
230         size_t parselen = strlen(parse);
231         struct ast_db_entry *dbe, *orig_dbe;
232         struct ast_str *escape_buf = NULL;
233         const char *last = "";
234
235         /* Remove leading and trailing slashes */
236         while (parse[0] == '/') {
237                 parse++;
238                 parselen--;
239         }
240         while (parse[parselen - 1] == '/') {
241                 parse[--parselen] = '\0';
242         }
243
244         ast_str_reset(*result);
245
246         /* Nothing within the database at that prefix? */
247         if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) {
248                 return 0;
249         }
250
251         for (; dbe; dbe = dbe->next) {
252                 /* Find the current component */
253                 char *curkey = &dbe->key[parselen + 1], *slash;
254                 if (*curkey == '/') {
255                         curkey++;
256                 }
257                 /* Remove everything after the current component */
258                 if ((slash = strchr(curkey, '/'))) {
259                         *slash = '\0';
260                 }
261
262                 /* Skip duplicates */
263                 if (!strcasecmp(last, curkey)) {
264                         continue;
265                 }
266                 last = curkey;
267
268                 if (orig_dbe != dbe) {
269                         ast_str_append(result, maxlen, ",");
270                 }
271                 ast_str_append_escapecommas(result, maxlen, curkey, strlen(curkey));
272         }
273         ast_db_freetree(orig_dbe);
274         ast_free(escape_buf);
275         return 0;
276 }
277
278 static struct ast_custom_function db_keys_function = {
279         .name = "DB_KEYS",
280         .read2 = function_db_keys,
281 };
282
283 static int function_db_delete(struct ast_channel *chan, const char *cmd,
284                               char *parse, char *buf, size_t len)
285 {
286         AST_DECLARE_APP_ARGS(args,
287                 AST_APP_ARG(family);
288                 AST_APP_ARG(key);
289         );
290
291         buf[0] = '\0';
292
293         if (ast_strlen_zero(parse)) {
294                 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
295                 return -1;
296         }
297
298         AST_NONSTANDARD_APP_ARGS(args, parse, '/');
299
300         if (args.argc < 2) {
301                 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
302                 return -1;
303         }
304
305         if (ast_db_get(args.family, args.key, buf, len - 1)) {
306                 ast_debug(1, "DB_DELETE: %s/%s not found in database.\n", args.family, args.key);
307         } else {
308                 if (ast_db_del(args.family, args.key)) {
309                         ast_debug(1, "DB_DELETE: %s/%s could not be deleted from the database\n", args.family, args.key);
310                 }
311         }
312
313         pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
314
315         return 0;
316 }
317
318 /*!
319  * \brief Wrapper to execute DB_DELETE from a write operation. Allows execution
320  * even if live_dangerously is disabled.
321  */
322 static int function_db_delete_write(struct ast_channel *chan, const char *cmd, char *parse,
323         const char *value)
324 {
325         /* Throwaway to hold the result from the read */
326         char buf[128];
327         return function_db_delete(chan, cmd, parse, buf, sizeof(buf));
328 }
329
330 static struct ast_custom_function db_delete_function = {
331         .name = "DB_DELETE",
332         .read = function_db_delete,
333         .write = function_db_delete_write,
334 };
335
336 static int unload_module(void)
337 {
338         int res = 0;
339
340         res |= ast_custom_function_unregister(&db_function);
341         res |= ast_custom_function_unregister(&db_exists_function);
342         res |= ast_custom_function_unregister(&db_delete_function);
343         res |= ast_custom_function_unregister(&db_keys_function);
344
345         return res;
346 }
347
348 static int load_module(void)
349 {
350         int res = 0;
351
352         res |= ast_custom_function_register_escalating(&db_function, AST_CFE_BOTH);
353         res |= ast_custom_function_register(&db_exists_function);
354         res |= ast_custom_function_register_escalating(&db_delete_function, AST_CFE_READ);
355         res |= ast_custom_function_register(&db_keys_function);
356
357         return res;
358 }
359
360 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Database (astdb) related dialplan functions");