Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 <since>
48 <version>1.2.0</version>
49 </since>
50 <synopsis>
51 Read from or write to the Asterisk database.
52 </synopsis>
53 <syntax argsep="/">
54 <parameter name="family" required="true" />
55 <parameter name="key" required="true" />
56 </syntax>
57 <description>
58 <para>This function will read from or write a value to the Asterisk database. On a
59 read, this function returns the corresponding value from the database, or blank
60 if it does not exist. Reading a database value will also set the variable
61 DB_RESULT. If you wish to find out if an entry exists, use the DB_EXISTS
62 function.</para>
63 </description>
64 <see-also>
65 <ref type="application">DBdel</ref>
66 <ref type="function">DB_DELETE</ref>
67 <ref type="application">DBdeltree</ref>
68 <ref type="function">DB_EXISTS</ref>
69 </see-also>
70 </function>
71 <function name="DB_EXISTS" language="en_US">
72 <since>
73 <version>1.2.0</version>
74 </since>
75 <synopsis>
76 Check to see if a key exists in the Asterisk database.
77 </synopsis>
78 <syntax argsep="/">
79 <parameter name="family" required="true" />
80 <parameter name="key" required="true" />
81 </syntax>
82 <description>
83 <para>This function will check to see if a key exists in the Asterisk
84 database. If it exists, the function will return <literal>1</literal>. If not,
85 it will return <literal>0</literal>. Checking for existence of a database key will
86 also set the variable DB_RESULT to the key's value if it exists.</para>
87 </description>
88 <see-also>
89 <ref type="function">DB</ref>
90 </see-also>
91 </function>
92 <function name="DB_KEYS" language="en_US">
93 <since>
94 <version>10.0.0</version>
95 </since>
96 <synopsis>
97 Obtain a list of keys within the Asterisk database.
98 </synopsis>
99 <syntax>
100 <parameter name="prefix" />
101 </syntax>
102 <description>
103 <para>This function will return a comma-separated list of keys existing
104 at the prefix specified within the Asterisk database. If no argument is
105 provided, then a list of key families will be returned.</para>
106 </description>
107 <see-also>
108 <ref type="function">DB_KEYCOUNT</ref>
109 </see-also>
110 </function>
111 <function name="DB_KEYCOUNT" language="en_US">
112 <since>
113 <version>16.26.0</version>
114 <version>18.12.0</version>
115 <version>19.4.0</version>
116 </since>
117 <synopsis>
118 Obtain the number of keys at a prefix within the Asterisk database.
119 </synopsis>
120 <syntax>
121 <parameter name="prefix" />
122 </syntax>
123 <description>
124 <para>This function will return the number of keys that exist
125 at the prefix specified within the Asterisk database. If no argument is
126 provided, then the number of all key families will be returned.</para>
127 </description>
128 <see-also>
129 <ref type="function">DB_KEYS</ref>
130 </see-also>
131 </function>
132 <function name="DB_DELETE" language="en_US">
133 <since>
134 <version>1.4.0</version>
135 </since>
136 <synopsis>
137 Return a value from the database and delete it.
138 </synopsis>
139 <syntax argsep="/">
140 <parameter name="family" required="true" />
141 <parameter name="key" required="true" />
142 </syntax>
143 <description>
144 <para>This function will retrieve a value from the Asterisk database
145 and then remove that key from the database. <variable>DB_RESULT</variable>
146 will be set to the key's value if it exists.</para>
147 <note>
148 <para>If <literal>live_dangerously</literal> in <literal>asterisk.conf</literal>
149 is set to <literal>no</literal>, this function can only be read from the
150 dialplan, and not directly from external protocols. It can, however, be
151 executed as a write operation (<literal>DB_DELETE(family, key)=ignored</literal>)</para>
152 </note>
153 </description>
154 <see-also>
155 <ref type="application">DBdel</ref>
156 <ref type="function">DB</ref>
157 <ref type="application">DBdeltree</ref>
158 </see-also>
159 </function>
160 ***/
161
162static int function_db_read(struct ast_channel *chan, const char *cmd,
163 char *parse, char *buf, size_t len)
164{
166 AST_APP_ARG(family);
167 AST_APP_ARG(key);
168 );
169
170 buf[0] = '\0';
171
172 if (ast_strlen_zero(parse)) {
173 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
174 return -1;
175 }
176
177 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
178
179 if (args.argc < 2) {
180 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)\n");
181 return -1;
182 }
183
184 if (ast_db_get(args.family, args.key, buf, len - 1)) {
185 ast_debug(1, "DB: %s/%s not found in database.\n", args.family, args.key);
186 } else {
187 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
188 }
189
190 return 0;
191}
192
193static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse,
194 const char *value)
195{
197 AST_APP_ARG(family);
198 AST_APP_ARG(key);
199 );
200
201 if (ast_strlen_zero(parse)) {
202 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=<value>\n");
203 return -1;
204 }
205
206 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
207
208 if (args.argc < 2) {
209 ast_log(LOG_WARNING, "DB requires an argument, DB(<family>/<key>)=value\n");
210 return -1;
211 }
212 /*
213 * When keynames are dynamically created using variables, if the variable is empty, this put bad data into the DB.
214 * In particular, a few cases: an empty key name, a key starting or ending with a /, and a key containing // two slashes.
215 * If this happens, allow it to go in, but warn the user of the issue and possible data corruption. */
216 if (ast_strlen_zero(args.key) || args.key[0] == '/' || args.key[strlen(args.key) - 1] == '/' || strstr(args.key, "//")) {
217 ast_log(LOG_WARNING, "DB: key '%s' seems malformed\n", args.key);
218 }
219 if (ast_db_put(args.family, args.key, value)) {
220 ast_log(LOG_WARNING, "DB: Error writing value to database.\n");
221 }
222
223 return 0;
224}
225
227 .name = "DB",
228 .read = function_db_read,
229 .write = function_db_write,
230};
231
232static int function_db_exists(struct ast_channel *chan, const char *cmd,
233 char *parse, char *buf, size_t len)
234{
236 AST_APP_ARG(family);
237 AST_APP_ARG(key);
238 );
239
240 buf[0] = '\0';
241
242 if (ast_strlen_zero(parse)) {
243 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
244 return -1;
245 }
246
247 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
248
249 if (args.argc < 2) {
250 ast_log(LOG_WARNING, "DB_EXISTS requires an argument, DB(<family>/<key>)\n");
251 return -1;
252 }
253
254 if (ast_db_get(args.family, args.key, buf, len - 1)) {
255 strcpy(buf, "0");
256 } else {
257 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
258 strcpy(buf, "1");
259 }
260
261 return 0;
262}
263
265 .name = "DB_EXISTS",
266 .read = function_db_exists,
267 .read_max = 2,
268};
269
270static int function_db_keys(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **result, ssize_t maxlen)
271{
272 size_t parselen = strlen(parse);
273 struct ast_db_entry *dbe, *orig_dbe;
274 struct ast_str *escape_buf = NULL;
275 const char *last = "";
276
277 /* Remove leading and trailing slashes */
278 while (parse[0] == '/') {
279 parse++;
280 parselen--;
281 }
282 while (parse[parselen - 1] == '/') {
283 parse[--parselen] = '\0';
284 }
285
287
288 /* Nothing within the database at that prefix? */
289 if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) {
290 return 0;
291 }
292
293 for (; dbe; dbe = dbe->next) {
294 /* Find the current component */
295 char *curkey = &dbe->key[parselen + 1], *slash;
296 if (*curkey == '/') {
297 curkey++;
298 }
299 /* Remove everything after the current component */
300 if ((slash = strchr(curkey, '/'))) {
301 *slash = '\0';
302 }
303
304 /* Skip duplicates */
305 if (!strcasecmp(last, curkey)) {
306 continue;
307 }
308 last = curkey;
309
310 if (orig_dbe != dbe) {
311 ast_str_append(result, maxlen, ",");
312 }
313 ast_str_append_escapecommas(result, maxlen, curkey, strlen(curkey));
314 }
315 ast_db_freetree(orig_dbe);
316 ast_free(escape_buf);
317 return 0;
318}
319
321 .name = "DB_KEYS",
322 .read2 = function_db_keys,
323};
324
325static int function_db_keycount(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
326{
327 size_t parselen = strlen(parse);
328 struct ast_db_entry *dbe, *orig_dbe;
329 const char *last = "";
330 int keycount = 0;
331
332 /* Remove leading and trailing slashes */
333 while (parse[0] == '/') {
334 parse++;
335 parselen--;
336 }
337 while (parse[parselen - 1] == '/') {
338 parse[--parselen] = '\0';
339 }
340
341 /* Nothing within the database at that prefix? */
342 if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) {
343 snprintf(buf, len, "%d", keycount);
344 return 0;
345 }
346
347 for (; dbe; dbe = dbe->next) {
348 /* Find the current component */
349 char *curkey = &dbe->key[parselen + 1], *slash;
350 if (*curkey == '/') {
351 curkey++;
352 }
353 /* Remove everything after the current component */
354 if ((slash = strchr(curkey, '/'))) {
355 *slash = '\0';
356 }
357
358 /* Skip duplicates */
359 if (!strcasecmp(last, curkey)) {
360 continue;
361 }
362 last = curkey;
363
364 keycount++;
365 }
366 ast_db_freetree(orig_dbe);
367 snprintf(buf, len, "%d", keycount);
368 return 0;
369}
370
372 .name = "DB_KEYCOUNT",
373 .read = function_db_keycount,
374};
375
376static int function_db_delete(struct ast_channel *chan, const char *cmd,
377 char *parse, char *buf, size_t len)
378{
380 AST_APP_ARG(family);
381 AST_APP_ARG(key);
382 );
383
384 buf[0] = '\0';
385
386 if (ast_strlen_zero(parse)) {
387 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
388 return -1;
389 }
390
391 AST_NONSTANDARD_APP_ARGS(args, parse, '/');
392
393 if (args.argc < 2) {
394 ast_log(LOG_WARNING, "DB_DELETE requires an argument, DB_DELETE(<family>/<key>)\n");
395 return -1;
396 }
397
398 if (ast_db_get(args.family, args.key, buf, len - 1)) {
399 ast_debug(1, "DB_DELETE: %s/%s not found in database.\n", args.family, args.key);
400 } else {
401 if (ast_db_del(args.family, args.key)) {
402 ast_debug(1, "DB_DELETE: %s/%s could not be deleted from the database\n", args.family, args.key);
403 }
404 }
405
406 pbx_builtin_setvar_helper(chan, "DB_RESULT", buf);
407
408 return 0;
409}
410
411/*!
412 * \brief Wrapper to execute DB_DELETE from a write operation. Allows execution
413 * even if live_dangerously is disabled.
414 */
415static int function_db_delete_write(struct ast_channel *chan, const char *cmd, char *parse,
416 const char *value)
417{
418 /* Throwaway to hold the result from the read */
419 char buf[128];
420 return function_db_delete(chan, cmd, parse, buf, sizeof(buf));
421}
422
424 .name = "DB_DELETE",
425 .read = function_db_delete,
427};
428
429static int unload_module(void)
430{
431 int res = 0;
432
438
439 return res;
440}
441
442static int load_module(void)
443{
444 int res = 0;
445
451
452 return res;
453}
454
455AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Database (astdb) related dialplan functions");
struct sla_ringing_trunk * last
Definition: app_sla.c:338
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: db.c:335
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: db.c:421
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:472
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: db.c:635
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: db.c:695
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:226
static int function_db_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:162
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:415
static int function_db_exists(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:232
static int function_db_keycount(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:325
static struct ast_custom_function db_keys_function
Definition: func_db.c:320
static struct ast_custom_function db_delete_function
Definition: func_db.c:423
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:270
static struct ast_custom_function db_exists_function
Definition: func_db.c:264
static struct ast_custom_function db_keycount_function
Definition: func_db.c:371
static int load_module(void)
Definition: func_db.c:442
static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_db.c:193
static int unload_module(void)
Definition: func_db.c:429
static int function_db_delete(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:376
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:581
#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:1568
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
@ AST_CFE_READ
Definition: pbx.h:1551
@ AST_CFE_BOTH
Definition: pbx.h:1553
#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.