Asterisk - The Open Source Telephony Project GIT-master-2de1a68
func_db.c
Go to the documentation of this file.
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 <see-also>
99 <ref type="function">DB_KEYCOUNT</ref>
100 </see-also>
101 </function>
102 <function name="DB_KEYCOUNT" language="en_US">
103 <synopsis>
104 Obtain the number of keys at a prefix within the Asterisk database.
105 </synopsis>
106 <syntax>
107 <parameter name="prefix" />
108 </syntax>
109 <description>
110 <para>This function will return the number of keys that exist
111 at the prefix specified within the Asterisk database. If no argument is
112 provided, then the number of all key families will be returned.</para>
113 </description>
114 <see-also>
115 <ref type="function">DB_KEYS</ref>
116 </see-also>
117 </function>
118 <function name="DB_DELETE" language="en_US">
119 <synopsis>
120 Return a value from the database and delete it.
121 </synopsis>
122 <syntax argsep="/">
123 <parameter name="family" required="true" />
124 <parameter name="key" required="true" />
125 </syntax>
126 <description>
127 <para>This function will retrieve a value from the Asterisk database
128 and then remove that key from the database. <variable>DB_RESULT</variable>
129 will be set to the key's value if it exists.</para>
130 <note>
131 <para>If <literal>live_dangerously</literal> in <literal>asterisk.conf</literal>
132 is set to <literal>no</literal>, this function can only be read from the
133 dialplan, and not directly from external protocols. It can, however, be
134 executed as a write operation (<literal>DB_DELETE(family, key)=ignored</literal>)</para>
135 </note>
136 </description>
137 <see-also>
138 <ref type="application">DBdel</ref>
139 <ref type="function">DB</ref>
140 <ref type="application">DBdeltree</ref>
141 </see-also>
142 </function>
143 ***/
144
145static int function_db_read(struct ast_channel *chan, const char *cmd,
146 char *parse, char *buf, size_t len)
147{
149 AST_APP_ARG(family);
150 AST_APP_ARG(key);
151 );
152
153 buf[0] = '\0';
154
155 if (ast_strlen_zero(parse)) {
156 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
157 return -1;
158 }
159
160 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
161
162 if (args.argc < 2) {
163 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
164 return -1;
165 }
166
167 if (ast_db_get(args.family, args.key, buf, len - 1)) {
168 ast_debug(1, "DB: %s/%s not found in database.\n", args.family, args.key);
169 } else {
170 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
171 }
172
173 return 0;
174}
175
176static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse,
177 const char *value)
178{
180 AST_APP_ARG(family);
181 AST_APP_ARG(key);
182 );
183
184 if (ast_strlen_zero(parse)) {
185 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=<value>\n");
186 return -1;
187 }
188
189 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
190
191 if (args.argc < 2) {
192 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=value\n");
193 return -1;
194 }
195 /*
196 * When keynames are dynamically created using variables, if the variable is empty, this put bad data into the DB.
197 * In particular, a few cases: an empty key name, a key starting or ending with a /, and a key containing // two slashes.
198 * If this happens, allow it to go in, but warn the user of the issue and possible data corruption. */
199 if (ast_strlen_zero(args.key) || args.key[0] == '/' || args.key[strlen(args.key) - 1] == '/' || strstr(args.key, "//")) {
200 ast_log(LOG_WARNING, "DB: key '%s' seems malformed\n", args.key);
201 }
202 if (ast_db_put(args.family, args.key, value)) {
203 ast_log(LOG_WARNING, "DB: Error writing value to database.\n");
204 }
205
206 return 0;
207}
208
210 .name = "DB",
211 .read = function_db_read,
212 .write = function_db_write,
213};
214
215static int function_db_exists(struct ast_channel *chan, const char *cmd,
216 char *parse, char *buf, size_t len)
217{
219 AST_APP_ARG(family);
220 AST_APP_ARG(key);
221 );
222
223 buf[0] = '\0';
224
225 if (ast_strlen_zero(parse)) {
226 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
227 return -1;
228 }
229
230 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
231
232 if (args.argc < 2) {
233 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
234 return -1;
235 }
236
237 if (ast_db_get(args.family, args.key, buf, len - 1)) {
238 strcpy(buf, "0");
239 } else {
240 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
241 strcpy(buf, "1");
242 }
243
244 return 0;
245}
246
248 .name = "DB_EXISTS",
249 .read = function_db_exists,
250 .read_max = 2,
251};
252
253static int function_db_keys(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **result, ssize_t maxlen)
254{
255 size_t parselen = strlen(parse);
256 struct ast_db_entry *dbe, *orig_dbe;
257 struct ast_str *escape_buf = NULL;
258 const char *last = "";
259
260 /* Remove leading and trailing slashes */
261 while (parse[0] == '/') {
262 parse++;
263 parselen--;
264 }
265 while (parse[parselen - 1] == '/') {
266 parse[--parselen] = '\0';
267 }
268
270
271 /* Nothing within the database at that prefix? */
272 if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) {
273 return 0;
274 }
275
276 for (; dbe; dbe = dbe->next) {
277 /* Find the current component */
278 char *curkey = &dbe->key[parselen + 1], *slash;
279 if (*curkey == '/') {
280 curkey++;
281 }
282 /* Remove everything after the current component */
283 if ((slash = strchr(curkey, '/'))) {
284 *slash = '\0';
285 }
286
287 /* Skip duplicates */
288 if (!strcasecmp(last, curkey)) {
289 continue;
290 }
291 last = curkey;
292
293 if (orig_dbe != dbe) {
294 ast_str_append(result, maxlen, ",");
295 }
296 ast_str_append_escapecommas(result, maxlen, curkey, strlen(curkey));
297 }
298 ast_db_freetree(orig_dbe);
299 ast_free(escape_buf);
300 return 0;
301}
302
304 .name = "DB_KEYS",
305 .read2 = function_db_keys,
306};
307
308static int function_db_keycount(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
309{
310 size_t parselen = strlen(parse);
311 struct ast_db_entry *dbe, *orig_dbe;
312 const char *last = "";
313 int keycount = 0;
314
315 /* Remove leading and trailing slashes */
316 while (parse[0] == '/') {
317 parse++;
318 parselen--;
319 }
320 while (parse[parselen - 1] == '/') {
321 parse[--parselen] = '\0';
322 }
323
324 /* Nothing within the database at that prefix? */
325 if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) {
326 snprintf(buf, len, "%d", keycount);
327 return 0;
328 }
329
330 for (; dbe; dbe = dbe->next) {
331 /* Find the current component */
332 char *curkey = &dbe->key[parselen + 1], *slash;
333 if (*curkey == '/') {
334 curkey++;
335 }
336 /* Remove everything after the current component */
337 if ((slash = strchr(curkey, '/'))) {
338 *slash = '\0';
339 }
340
341 /* Skip duplicates */
342 if (!strcasecmp(last, curkey)) {
343 continue;
344 }
345 last = curkey;
346
347 keycount++;
348 }
349 ast_db_freetree(orig_dbe);
350 snprintf(buf, len, "%d", keycount);
351 return 0;
352}
353
355 .name = "DB_KEYCOUNT",
356 .read = function_db_keycount,
357};
358
359static int function_db_delete(struct ast_channel *chan, const char *cmd,
360 char *parse, char *buf, size_t len)
361{
363 AST_APP_ARG(family);
364 AST_APP_ARG(key);
365 );
366
367 buf[0] = '\0';
368
369 if (ast_strlen_zero(parse)) {
370 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
371 return -1;
372 }
373
374 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
375
376 if (args.argc < 2) {
377 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
378 return -1;
379 }
380
381 if (ast_db_get(args.family, args.key, buf, len - 1)) {
382 ast_debug(1, "DB_DELETE: %s/%s not found in database.\n", args.family, args.key);
383 } else {
384 if (ast_db_del(args.family, args.key)) {
385 ast_debug(1, "DB_DELETE: %s/%s could not be deleted from the database\n", args.family, args.key);
386 }
387 }
388
389 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
390
391 return 0;
392}
393
394/*!
395 * \brief Wrapper to execute DB_DELETE from a write operation. Allows execution
396 * even if live_dangerously is disabled.
397 */
398static int function_db_delete_write(struct ast_channel *chan, const char *cmd, char *parse,
399 const char *value)
400{
401 /* Throwaway to hold the result from the read */
402 char buf[128];
403 return function_db_delete(chan, cmd, parse, buf, sizeof(buf));
404}
405
407 .name = "DB_DELETE",
408 .read = function_db_delete,
410};
411
412static int unload_module(void)
413{
414 int res = 0;
415
421
422 return res;
423}
424
425static int load_module(void)
426{
427 int res = 0;
428
434
435 return res;
436}
437
438AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Database (astdb) related dialplan functions");
struct sla_ringing_trunk * last
Definition: app_sla.c:332
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: main/db.c:427
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:610
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:84
General Asterisk PBX channel definitions.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_custom_function db_function
Definition: func_db.c:209
static int function_db_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:145
static int function_db_delete_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Wrapper to execute DB_DELETE from a write operation. Allows execution even if live_dangerously is dis...
Definition: func_db.c:398
static int function_db_exists(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:215
static int function_db_keycount(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:308
static struct ast_custom_function db_keys_function
Definition: func_db.c:303
static struct ast_custom_function db_delete_function
Definition: func_db.c:406
static int function_db_keys(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **result, ssize_t maxlen)
Definition: func_db.c:253
static struct ast_custom_function db_exists_function
Definition: func_db.c:247
static struct ast_custom_function db_keycount_function
Definition: func_db.c:354
static int load_module(void)
Definition: func_db.c:425
static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_db.c:176
static int unload_module(void)
Definition: func_db.c:412
static int function_db_delete(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:359
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Core PBX routines and definitions.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1567
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
@ AST_CFE_READ
Definition: pbx.h:1550
@ AST_CFE_BOTH
Definition: pbx.h:1552
#define NULL
Definition: resample.c:96
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_str_append_escapecommas(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas.
Definition: strings.h:1076
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
Support for dynamic strings.
Definition: strings.h:623
int value
Definition: syslog.c:37
const char * args
Utility functions.