Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
5  *
6  * func_db.c adapted from the old app_db.c, copyright by the following people
7  * Copyright (C) 2005, Mark Spencer <[email protected]>
8  * Copyright (C) 2003, Jefferson Noxon <[email protected]>
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 <[email protected]>
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 {
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 {
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 
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 {
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 
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 
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 {
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 
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 
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");
const char * name
Definition: pbx.h:119
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:598
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:1028
static struct ast_custom_function db_delete_function
Definition: func_db.c:330
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:1091
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1517
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int function_db_exists(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:190
static int function_db_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_db.c:157
struct ast_db_entry * next
Definition: astdb.h:32
General Asterisk PBX channel definitions.
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
static int function_db_delete(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:283
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:322
Core PBX routines and definitions.
static int unload_module(void)
Definition: func_db.c:336
static struct ast_custom_function db_keys_function
Definition: func_db.c:278
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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:531
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:228
Definition: astdb.h:31
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_free(a)
Definition: astmm.h:182
static int load_module(void)
Definition: func_db.c:348
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:412
static struct ast_custom_function db_exists_function
Definition: func_db.c:222
static struct ast_threadstorage escape_buf
Definition: cdr_mysql.c:71
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...
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:653
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
static PGresult * result
Definition: cel_pgsql.c:88
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static int function_db_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_db.c:126
Asterisk module definitions.
Persistant data storage (akin to *doze registry)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
static struct ast_custom_function db_function
Definition: func_db.c:184
char * key
Definition: astdb.h:33
#define AST_APP_ARG(name)
Define an application argument.