Asterisk - The Open Source Telephony Project  GIT-master-b7027de
res_config_curl.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Tilghman Lesher <res_config_curl_v1@the-tilghman.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief curl plugin for portable configuration engine
22  *
23  * \author Tilghman Lesher <res_config_curl_v1@the-tilghman.com>
24  *
25  * Depends on the CURL library - http://curl.haxx.se/
26  *
27  */
28 
29 /*** MODULEINFO
30  <depend>func_curl</depend>
31  <depend>res_curl</depend>
32  <depend>curl</depend>
33  <support_level>core</support_level>
34  ***/
35 
36 #include "asterisk.h"
37 
38 #include <curl/curl.h>
39 
40 #include "asterisk/file.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/config.h"
44 #include "asterisk/module.h"
45 #include "asterisk/lock.h"
46 #include "asterisk/utils.h"
47 #include "asterisk/threadstorage.h"
48 
51 
52 /*!
53  * \brief Execute a curl query and return ast_variable list
54  * \param url The base URL from which to retrieve data
55  * \param unused Not currently used
56  * \param fields list containing one or more field/operator/value set.
57  *
58  * \retval var on success
59  * \retval NULL on failure
60 */
61 static struct ast_variable *realtime_curl(const char *url, const char *unused, const struct ast_variable *fields)
62 {
63  struct ast_str *query, *buffer;
64  char buf1[256], buf2[256];
65  const struct ast_variable *field;
66  char *stringp, *pair, *key;
67  unsigned int start = 1;
68  struct ast_variable *var = NULL, *prev = NULL;
69 
70  if (!ast_custom_function_find("CURL")) {
71  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
72  return NULL;
73  }
74 
75  if (!(query = ast_str_thread_get(&query_buf, 16))) {
76  return NULL;
77  }
78 
79  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
80  return NULL;
81  }
82 
83  ast_str_set(&query, 0, "${CURL(%s/single,", url);
84 
85  for (field = fields; field; field = field->next) {
86  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
87  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
88  ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
89  start = 0;
90  }
91 
92  ast_str_append(&query, 0, ")}");
94 
95  /* Remove any trailing newline characters */
96  if ((stringp = strchr(ast_str_buffer(buffer), '\r')) || (stringp = strchr(ast_str_buffer(buffer), '\n'))) {
97  *stringp = '\0';
98  }
99 
100  stringp = ast_str_buffer(buffer);
101  while ((pair = strsep(&stringp, "&"))) {
102  key = strsep(&pair, "=");
104  if (pair) {
106  }
107 
108  if (!ast_strlen_zero(key)) {
109  if (prev) {
110  prev->next = ast_variable_new(key, S_OR(pair, ""), "");
111  if (prev->next) {
112  prev = prev->next;
113  }
114  } else {
115  prev = var = ast_variable_new(key, S_OR(pair, ""), "");
116  }
117  }
118  }
119 
120  return var;
121 }
122 
123 /*!
124  * \brief Excute an Select query and return ast_config list
125  * \param url
126  * \param unused
127  * \param fields list containing one or more field/operator/value set.
128  *
129  * \retval struct ast_config pointer on success
130  * \retval NULL on failure
131 */
132 static struct ast_config *realtime_multi_curl(const char *url, const char *unused, const struct ast_variable *fields)
133 {
134  struct ast_str *query, *buffer;
135  char buf1[256], buf2[256];
136  const struct ast_variable *field;
137  char *stringp, *line, *pair, *key, *initfield = NULL;
138  int start = 1;
139  struct ast_variable *var = NULL;
140  struct ast_config *cfg = NULL;
141  struct ast_category *cat = NULL;
142 
143  if (!ast_custom_function_find("CURL")) {
144  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
145  return NULL;
146  }
147 
148  if (!(query = ast_str_thread_get(&query_buf, 16))) {
149  return NULL;
150  }
151 
152  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
153  return NULL;
154  }
155 
156  ast_str_set(&query, 0, "${CURL(%s/multi,", url);
157 
158  for (field = fields; field; field = field->next) {
159  if (start) {
160  char *op;
161  initfield = ast_strdup(field->name);
162  if ((op = strchr(initfield, ' ')))
163  *op = '\0';
164  }
165  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
166  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
167  ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
168  start = 0;
169  }
170 
171  ast_str_append(&query, 0, ")}");
172 
173  /* Do the CURL query */
174  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
175 
176  if (!(cfg = ast_config_new())) {
177  ast_free(initfield);
178  return NULL;
179  }
180 
181  /* Line oriented output */
182  stringp = ast_str_buffer(buffer);
183  while ((line = strsep(&stringp, "\r\n"))) {
184  if (ast_strlen_zero(line)) {
185  continue;
186  }
187 
189  if (!cat) {
190  continue;
191  }
192 
193  while ((pair = strsep(&line, "&"))) {
194  key = strsep(&pair, "=");
196  if (pair) {
198  }
199 
200  if (!strcasecmp(key, initfield) && pair) {
201  ast_category_rename(cat, pair);
202  }
203 
204  if (!ast_strlen_zero(key)) {
205  var = ast_variable_new(key, S_OR(pair, ""), "");
206  ast_variable_append(cat, var);
207  }
208  }
209  ast_category_append(cfg, cat);
210  }
211 
212  ast_free(initfield);
213 
214  return cfg;
215 }
216 
217 /*!
218  * \brief Execute an UPDATE query
219  * \param url
220  * \param unused
221  * \param keyfield where clause field
222  * \param lookup value of field for where clause
223  * \param fields list containing one or more field/value set(s).
224  *
225  * Update a database table, prepare the sql statement using keyfield and lookup
226  * control the number of records to change. All values to be changed are stored in ap list.
227  * Sub-in the values to the prepared statement and execute it.
228  *
229  * \retval number of rows affected
230  * \retval -1 on failure
231 */
232 static int update_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, const struct ast_variable *fields)
233 {
234  struct ast_str *query, *buffer;
235  char buf1[256], buf2[256];
236  const struct ast_variable *field;
237  char *stringp;
238  int start = 1, rowcount = -1;
239 
240  if (!ast_custom_function_find("CURL")) {
241  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
242  return -1;
243  }
244 
245  if (!(query = ast_str_thread_get(&query_buf, 16))) {
246  return -1;
247  }
248 
249  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
250  return -1;
251  }
252 
253  ast_uri_encode(keyfield, buf1, sizeof(buf1), ast_uri_http);
254  ast_uri_encode(lookup, buf2, sizeof(buf2), ast_uri_http);
255  ast_str_set(&query, 0, "${CURL(%s/update?%s=%s,", url, buf1, buf2);
256 
257  for (field = fields; field; field = field->next) {
258  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
259  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
260  ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
261  start = 0;
262  }
263 
264  ast_str_append(&query, 0, ")}");
265  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
266 
267  /* Line oriented output */
268  stringp = ast_str_buffer(buffer);
269  while (*stringp <= ' ') {
270  stringp++;
271  }
272  sscanf(stringp, "%30d", &rowcount);
273 
274  if (rowcount >= 0) {
275  return (int)rowcount;
276  }
277 
278  return -1;
279 }
280 
281 static int update2_curl(const char *url, const char *unused, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
282 {
283  struct ast_str *query, *buffer;
284  char buf1[200], buf2[200];
285  const struct ast_variable *field;
286  char *stringp;
287  unsigned int start = 1;
288  int rowcount = -1;
289 
290  if (!ast_custom_function_find("CURL")) {
291  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
292  return -1;
293  }
294 
295  if (!(query = ast_str_thread_get(&query_buf, 1000)))
296  return -1;
297 
298  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
299  return -1;
300  }
301 
302  ast_str_set(&query, 0, "${CURL(%s/update?", url);
303 
304  for (field = lookup_fields; field; field = field->next) {
305  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
306  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
307  ast_str_append(&query, 0, "%s%s=%s", !start ? "" : "&", buf1, buf2);
308  start = 0;
309  }
310  ast_str_append(&query, 0, ",");
311  start = 1;
312 
313  for (field = update_fields; field; field = field->next) {
314  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
315  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
316  ast_str_append(&query, 0, "%s%s=%s", !start ? "" : "&", buf1, buf2);
317  start = 0;
318  }
319 
320  ast_str_append(&query, 0, ")}");
321  /* Proxies work, by setting CURLOPT options in the [globals] section of
322  * extensions.conf. Unfortunately, this means preloading pbx_config.so
323  * so that they have an opportunity to be set prior to startup realtime
324  * queries. */
325  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
326 
327  /* Line oriented output */
328  stringp = ast_str_buffer(buffer);
329  while (*stringp <= ' ') {
330  stringp++;
331  }
332  sscanf(stringp, "%30d", &rowcount);
333 
334  if (rowcount >= 0) {
335  return (int)rowcount;
336  }
337 
338  return -1;
339 }
340 
341 /*!
342  * \brief Execute an INSERT query
343  * \param url
344  * \param unused
345  * \param fields list containing one or more field/value set(s)
346  *
347  * Insert a new record into database table, prepare the sql statement.
348  * All values to be changed are stored in ap list.
349  * Sub-in the values to the prepared statement and execute it.
350  *
351  * \retval number of rows affected
352  * \retval -1 on failure
353 */
354 static int store_curl(const char *url, const char *unused, const struct ast_variable *fields)
355 {
356  struct ast_str *query, *buffer;
357  char buf1[256], buf2[256];
358  const struct ast_variable *field;
359  char *stringp;
360  int start = 1, rowcount = -1;
361 
362  if (!ast_custom_function_find("CURL")) {
363  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
364  return -1;
365  }
366 
367  if (!(query = ast_str_thread_get(&query_buf, 1000))) {
368  return -1;
369  }
370 
371  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
372  return -1;
373  }
374 
375  ast_str_set(&query, 0, "${CURL(%s/store,", url);
376 
377  for (field = fields; field; field = field->next) {
378  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
379  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
380  ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
381  start = 0;
382  }
383 
384  ast_str_append(&query, 0, ")}");
385  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
386 
387  stringp = ast_str_buffer(buffer);
388  while (*stringp <= ' ') {
389  stringp++;
390  }
391  sscanf(stringp, "%30d", &rowcount);
392 
393  if (rowcount >= 0) {
394  return rowcount;
395  }
396 
397  return -1;
398 }
399 
400 /*!
401  * \brief Execute an DELETE query
402  * \param url
403  * \param unused
404  * \param keyfield where clause field
405  * \param lookup value of field for where clause
406  * \param fields list containing one or more field/value set(s)
407  *
408  * Delete a row from a database table, prepare the sql statement using keyfield and lookup
409  * control the number of records to change. Additional params to match rows are stored in ap list.
410  * Sub-in the values to the prepared statement and execute it.
411  *
412  * \retval number of rows affected
413  * \retval -1 on failure
414 */
415 static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, const struct ast_variable *fields)
416 {
417  struct ast_str *query, *buffer;
418  char buf1[200], buf2[200];
419  const struct ast_variable *field;
420  char *stringp;
421  int start = 1, rowcount = -1;
422 
423  if (!ast_custom_function_find("CURL")) {
424  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
425  return -1;
426  }
427 
428  if (!(query = ast_str_thread_get(&query_buf, 1000))) {
429  return -1;
430  }
431 
432  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
433  return -1;
434  }
435 
436  ast_uri_encode(keyfield, buf1, sizeof(buf1), ast_uri_http);
437  ast_uri_encode(lookup, buf2, sizeof(buf2), ast_uri_http);
438  ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);
439 
440  for (field = fields; field; field = field->next) {
441  ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http);
442  ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http);
443  ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2);
444  start = 0;
445  }
446 
447  ast_str_append(&query, 0, ")}");
448  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
449 
450  /* Line oriented output */
451  stringp = ast_str_buffer(buffer);
452  while (*stringp <= ' ') {
453  stringp++;
454  }
455  sscanf(stringp, "%30d", &rowcount);
456 
457  if (rowcount >= 0) {
458  return (int)rowcount;
459  }
460 
461  return -1;
462 }
463 
464 static int require_curl(const char *url, const char *unused, va_list ap)
465 {
466  struct ast_str *query, *buffer;
467  char *elm, field[256];
468  int type, size, i = 0;
469 
470  if (!ast_custom_function_find("CURL")) {
471  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
472  return -1;
473  }
474 
475  if (!(query = ast_str_thread_get(&query_buf, 100))) {
476  return -1;
477  }
478 
479  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
480  return -1;
481  }
482 
483  ast_str_set(&query, 0, "${CURL(%s/require,", url);
484 
485  while ((elm = va_arg(ap, char *))) {
486  type = va_arg(ap, require_type);
487  size = va_arg(ap, int);
488  ast_uri_encode(elm, field, sizeof(field), ast_uri_http);
489  ast_str_append(&query, 0, "%s%s=%s%%3A%d",
490  i > 0 ? "&" : "",
491  field,
492  type == RQ_CHAR ? "char" :
493  type == RQ_INTEGER1 ? "integer1" :
494  type == RQ_UINTEGER1 ? "uinteger1" :
495  type == RQ_INTEGER2 ? "integer2" :
496  type == RQ_UINTEGER2 ? "uinteger2" :
497  type == RQ_INTEGER3 ? "integer3" :
498  type == RQ_UINTEGER3 ? "uinteger3" :
499  type == RQ_INTEGER4 ? "integer4" :
500  type == RQ_UINTEGER4 ? "uinteger4" :
501  type == RQ_INTEGER8 ? "integer8" :
502  type == RQ_UINTEGER8 ? "uinteger8" :
503  type == RQ_DATE ? "date" :
504  type == RQ_DATETIME ? "datetime" :
505  type == RQ_FLOAT ? "float" :
506  "unknown", size);
507  i++;
508  }
509 
510  ast_str_append(&query, 0, ")}");
511  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
512  return atoi(ast_str_buffer(buffer));
513 }
514 
515 static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
516 {
517  struct ast_str *query, *buffer;
518  char buf1[200];
519  char *stringp, *line, *pair, *key;
520  int last_cat_metric = -1, cat_metric = -1;
521  struct ast_category *cat = NULL;
522  char *cur_cat = "";
523  char *category = "", *var_name = "", *var_val = "";
524  struct ast_flags loader_flags = { 0 };
525 
526  if (!ast_custom_function_find("CURL")) {
527  ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
528  return NULL;
529  }
530 
531  if (!(query = ast_str_thread_get(&query_buf, 100))) {
532  return NULL;
533  }
534 
535  if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
536  return NULL;
537  }
538 
539  ast_uri_encode(file, buf1, sizeof(buf1), ast_uri_http);
540  ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
541 
542  /* Do the CURL query */
543  ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
544 
545  /* Line oriented output */
546  stringp = ast_str_buffer(buffer);
548 
549  while ((line = strsep(&stringp, "\r\n"))) {
550  if (ast_strlen_zero(line)) {
551  continue;
552  }
553 
554  while ((pair = strsep(&line, "&"))) {
555  key = strsep(&pair, "=");
557  if (pair) {
559  }
560 
561  if (!strcasecmp(key, "category")) {
562  category = S_OR(pair, "");
563  } else if (!strcasecmp(key, "var_name")) {
564  var_name = S_OR(pair, "");
565  } else if (!strcasecmp(key, "var_val")) {
566  var_val = S_OR(pair, "");
567  } else if (!strcasecmp(key, "cat_metric")) {
568  cat_metric = pair ? atoi(pair) : 0;
569  }
570  }
571 
572  if (!strcmp(var_name, "#include")) {
573  if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
574  return NULL;
575  }
576 
577  if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
578  cat = ast_category_new_dynamic(category);
579  if (!cat) {
580  break;
581  }
582  cur_cat = category;
583  last_cat_metric = cat_metric;
584  ast_category_append(cfg, cat);
585  }
586  ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
587  }
588 
589  return cfg;
590 }
591 
593  .name = "curl",
594  .load_func = config_curl,
595  .realtime_func = realtime_curl,
596  .realtime_multi_func = realtime_multi_curl,
597  .store_func = store_curl,
598  .destroy_func = destroy_curl,
599  .update_func = update_curl,
600  .update2_func = update2_curl,
601  .require_func = require_curl,
602 };
603 
604 static int reload_module(void)
605 {
606  struct ast_flags flags = { CONFIG_FLAG_NOREALTIME };
607  struct ast_config *cfg;
608  struct ast_variable *var;
609 
610  if (!(cfg = ast_config_load("res_curl.conf", flags))) {
611  return 0;
612  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
613  ast_log(LOG_WARNING, "res_curl.conf could not be parsed!\n");
614  return 0;
615  }
616 
617  if (!(var = ast_variable_browse(cfg, "globals")) && !(var = ast_variable_browse(cfg, "global")) && !(var = ast_variable_browse(cfg, "general"))) {
618  ast_log(LOG_WARNING, "[globals] not found in res_curl.conf\n");
619  ast_config_destroy(cfg);
620  return 0;
621  }
622 
623  for (; var; var = var->next) {
624  if (strncmp(var->name, "CURLOPT(", 8)) {
625  char name[256];
626  snprintf(name, sizeof(name), "CURLOPT(%s)", var->name);
627  pbx_builtin_setvar_helper(NULL, name, var->value);
628  } else {
630  }
631  }
632  ast_config_destroy(cfg);
633  return 0;
634 }
635 
636 static int unload_module(void)
637 {
638  ast_config_engine_deregister(&curl_engine);
639 
640  return 0;
641 }
642 
643 static int load_module(void)
644 {
645  reload_module();
646 
647  ast_config_engine_register(&curl_engine);
648 
649  return 0;
650 }
651 
652 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime Curl configuration",
653  .support_level = AST_MODULE_SUPPORT_CORE,
654  .load = load_module,
655  .unload = unload_module,
657  .load_pri = AST_MODPRI_REALTIME_DRIVER,
658  .requires = "extconfig,res_curl,func_curl",
659 );
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: main/utils.c:616
struct ast_variable * next
static int reload_module(void)
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:84
require_type
Types used in ast_realtime_require_field.
static const char type[]
Definition: chan_ooh323.c:109
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an DELETE query.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static struct ast_config * config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
#define CONFIG_STATUS_FILEINVALID
static struct ast_config * realtime_multi_curl(const char *url, const char *unused, const struct ast_variable *fields)
Excute an Select query and return ast_config list.
Structure for variables, used for configurations and for channel variables.
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: main/utils.c:577
#define var
Definition: ast_expr2f.c:614
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: main/config.c:3006
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
Definition: extconf.c:2783
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: main/config.c:2990
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
static struct ast_threadstorage buf2
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
#define NULL
Definition: resample.c:96
Definitions to aid in the use of thread local storage.
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: main/config.c:3112
Configuration engine structure, used to define realtime drivers.
Utility functions.
static struct ast_variable * realtime_curl(const char *url, const char *unused, const struct ast_variable *fields)
Execute a curl query and return ast_variable list.
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
Configuration File Parser.
void ast_category_rename(struct ast_category *cat, const char *name)
Definition: main/config.c:1362
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
static struct ast_config_engine curl_engine
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static struct ast_threadstorage result_buf
#define ast_variable_new(name, value, filename)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
Core PBX routines and definitions.
static int require_curl(const char *url, const char *unused, va_list ap)
static int update2_curl(const char *url, const char *unused, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
struct ast_custom_function * ast_custom_function_find(const char *name)
Definition: ael_main.c:173
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static struct ast_threadstorage buf1
#define ast_strlen_zero(a)
Definition: muted.c:73
static int store_curl(const char *url, const char *unused, const struct ast_variable *fields)
Execute an INSERT query.
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
static int reload(void)
Definition: cdr_mysql.c:741
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
Structure used to handle boolean flags.
Definition: utils.h:199
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
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_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835
char * strsep(char **str, const char *delims)
static int update_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, const struct ast_variable *fields)
Execute an UPDATE query.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static int unload_module(void)
const struct ast_flags ast_uri_http
Definition: main/utils.c:573
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
static char url[512]
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static int load_module(void)
static struct ast_threadstorage query_buf