Asterisk - The Open Source Telephony Project GIT-master-f36a736
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"
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*/
61static 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 Execute 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*/
132static 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 */
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) {
202 }
203
204 if (!ast_strlen_zero(key)) {
205 var = ast_variable_new(key, S_OR(pair, ""), "");
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*/
232static 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, ")}");
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
281static 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. */
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*/
354static 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, ")}");
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*/
415static 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, ")}");
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
464static 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, ")}");
512 return atoi(ast_str_buffer(buffer));
513}
514
515static 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
540 ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
541
542 /* Do the CURL 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
604static int reload_module(void)
605{
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");
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);
628 } else {
629 pbx_builtin_setvar_helper(NULL, var->name, var->value);
630 }
631 }
633 return 0;
634}
635
636static int unload_module(void)
637{
639
640 return 0;
641}
642
643static int load_module(void)
644{
646
648
649 return 0;
650}
651
652AST_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",
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
Generic File Format Support. Should be included by clients of the file handling routines....
static const char name[]
Definition: format_mp3.c:68
static struct ast_threadstorage buf2
static struct ast_threadstorage buf1
char * strsep(char **str, const char *delims)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
void ast_category_rename(struct ast_category *cat, const char *name)
Definition: main/config.c:1460
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
#define ast_variable_new(name, value, filename)
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: main/config.c:3188
struct ast_category * ast_config_get_current_category(const struct ast_config *cfg)
Retrieve the current category name being built.
Definition: extconf.c:2781
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
require_type
Types used in ast_realtime_require_field.
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:3294
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: main/config.c:3172
@ CONFIG_FLAG_NOREALTIME
#define LOG_ERROR
#define LOG_WARNING
Asterisk locking-related definitions:
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_REALTIME_DRIVER
Definition: module.h:337
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Core PBX routines and definitions.
struct ast_custom_function * ast_custom_function_find(const char *name)
Definition: ael_main.c:173
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
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.
static struct ast_threadstorage result_buf
static struct ast_config_engine curl_engine
static int require_curl(const char *url, const char *unused, va_list ap)
static struct ast_config * realtime_multi_curl(const char *url, const char *unused, const struct ast_variable *fields)
Execute an Select query and return ast_config list.
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)
static int reload_module(void)
static int update2_curl(const char *url, const char *unused, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
static struct ast_threadstorage query_buf
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.
static int load_module(void)
static int unload_module(void)
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.
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.
static int store_curl(const char *url, const char *unused, const struct ast_variable *fields)
Execute an INSERT query.
static char url[512]
static int reload(void)
#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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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:1113
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:909
Configuration engine structure, used to define realtime drivers.
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
Utility functions.
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: utils.c:723
const struct ast_flags ast_uri_http
Definition: utils.c:719
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: utils.c:762