00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 280556 $")
00036
00037 #include <curl/curl.h>
00038
00039 #include "asterisk/file.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/config.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/lock.h"
00045 #include "asterisk/utils.h"
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 static struct ast_variable *realtime_curl(const char *url, const char *unused, va_list ap)
00057 {
00058 struct ast_str *query;
00059 char buf1[200], buf2[200];
00060 const char *newparam, *newval;
00061 char *stringp, *pair, *key;
00062 int i;
00063 struct ast_variable *var=NULL, *prev=NULL;
00064 const int EncodeSpecialChars = 1, bufsize = 64000;
00065 char *buffer;
00066
00067 if (!ast_custom_function_find("CURL")) {
00068 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00069 return NULL;
00070 }
00071
00072 if (!(query = ast_str_create(1000)))
00073 return NULL;
00074
00075 if (!(buffer = ast_malloc(bufsize))) {
00076 ast_free(query);
00077 return NULL;
00078 }
00079
00080 ast_str_set(&query, 0, "${CURL(%s/single,", url);
00081
00082 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00083 newval = va_arg(ap, const char *);
00084 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00085 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00086 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00087 }
00088 va_end(ap);
00089
00090 ast_str_append(&query, 0, ")}");
00091 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00092
00093
00094 if ((stringp = strchr(buffer, '\r')) || (stringp = strchr(buffer, '\n')))
00095 *stringp = '\0';
00096
00097 stringp = buffer;
00098 while ((pair = strsep(&stringp, "&"))) {
00099 key = strsep(&pair, "=");
00100 ast_uri_decode(key);
00101 if (pair)
00102 ast_uri_decode(pair);
00103
00104 if (!ast_strlen_zero(key)) {
00105 if (prev) {
00106 prev->next = ast_variable_new(key, S_OR(pair, ""), "");
00107 if (prev->next)
00108 prev = prev->next;
00109 } else
00110 prev = var = ast_variable_new(key, S_OR(pair, ""), "");
00111 }
00112 }
00113
00114 ast_free(buffer);
00115 ast_free(query);
00116 return var;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 static struct ast_config *realtime_multi_curl(const char *url, const char *unused, va_list ap)
00129 {
00130 struct ast_str *query;
00131 char buf1[200], buf2[200];
00132 const char *newparam, *newval;
00133 char *stringp, *line, *pair, *key, *initfield = NULL;
00134 int i;
00135 const int EncodeSpecialChars = 1, bufsize = 256000;
00136 struct ast_variable *var=NULL;
00137 struct ast_config *cfg=NULL;
00138 struct ast_category *cat=NULL;
00139 char *buffer;
00140
00141 if (!ast_custom_function_find("CURL")) {
00142 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00143 return NULL;
00144 }
00145
00146 if (!(query = ast_str_create(1000)))
00147 return NULL;
00148
00149 if (!(buffer = ast_malloc(bufsize))) {
00150 ast_free(query);
00151 return NULL;
00152 }
00153
00154 ast_str_set(&query, 0, "${CURL(%s/multi,", url);
00155
00156 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00157 newval = va_arg(ap, const char *);
00158 if (i == 0) {
00159 char *op;
00160 initfield = ast_strdupa(newparam);
00161 if ((op = strchr(initfield, ' ')))
00162 *op = '\0';
00163 }
00164 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00165 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00166 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00167 }
00168 va_end(ap);
00169
00170 ast_str_append(&query, 0, ")}");
00171
00172
00173 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00174
00175 if (!(cfg = ast_config_new()))
00176 goto exit_multi;
00177
00178
00179 stringp = buffer;
00180 while ((line = strsep(&stringp, "\r\n"))) {
00181 if (ast_strlen_zero(line))
00182 continue;
00183
00184 if (!(cat = ast_category_new("", "", 99999)))
00185 continue;
00186
00187 while ((pair = strsep(&line, "&"))) {
00188 key = strsep(&pair, "=");
00189 ast_uri_decode(key);
00190 if (pair)
00191 ast_uri_decode(pair);
00192
00193 if (!strcasecmp(key, initfield) && pair)
00194 ast_category_rename(cat, pair);
00195
00196 if (!ast_strlen_zero(key)) {
00197 var = ast_variable_new(key, S_OR(pair, ""), "");
00198 ast_variable_append(cat, var);
00199 }
00200 }
00201 ast_category_append(cfg, cat);
00202 }
00203
00204 exit_multi:
00205 ast_free(buffer);
00206 ast_free(query);
00207 return cfg;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 static int update_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
00226 {
00227 struct ast_str *query;
00228 char buf1[200], buf2[200];
00229 const char *newparam, *newval;
00230 char *stringp;
00231 int i, rowcount = -1;
00232 const int EncodeSpecialChars = 1, bufsize = 100;
00233 char *buffer;
00234
00235 if (!ast_custom_function_find("CURL")) {
00236 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00237 return -1;
00238 }
00239
00240 if (!(query = ast_str_create(1000)))
00241 return -1;
00242
00243 if (!(buffer = ast_malloc(bufsize))) {
00244 ast_free(query);
00245 return -1;
00246 }
00247
00248 ast_uri_encode(keyfield, buf1, sizeof(buf1), EncodeSpecialChars);
00249 ast_uri_encode(lookup, buf2, sizeof(buf2), EncodeSpecialChars);
00250 ast_str_set(&query, 0, "${CURL(%s/update?%s=%s,", url, buf1, buf2);
00251
00252 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00253 newval = va_arg(ap, const char *);
00254 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00255 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00256 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00257 }
00258 va_end(ap);
00259
00260 ast_str_append(&query, 0, ")}");
00261 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00262
00263
00264 stringp = buffer;
00265 while (*stringp <= ' ')
00266 stringp++;
00267 sscanf(stringp, "%30d", &rowcount);
00268
00269 ast_free(buffer);
00270 ast_free(query);
00271
00272 if (rowcount >= 0)
00273 return (int)rowcount;
00274
00275 return -1;
00276 }
00277
00278 static int update2_curl(const char *url, const char *unused, va_list ap)
00279 {
00280 struct ast_str *query;
00281 char buf1[200], buf2[200];
00282 const char *newparam, *newval;
00283 char *stringp;
00284 int rowcount = -1, lookup = 1, first = 1;
00285 const int EncodeSpecialChars = 1, bufsize = 100;
00286 char *buffer;
00287
00288 if (!ast_custom_function_find("CURL")) {
00289 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00290 return -1;
00291 }
00292
00293 if (!(query = ast_str_create(1000)))
00294 return -1;
00295
00296 if (!(buffer = ast_malloc(bufsize))) {
00297 ast_free(query);
00298 return -1;
00299 }
00300
00301 ast_str_set(&query, 0, "${CURL(%s/update?", url);
00302
00303 for (;;) {
00304 if ((newparam = va_arg(ap, const char *)) == SENTINEL) {
00305 if (lookup) {
00306 lookup = 0;
00307 ast_str_append(&query, 0, ",");
00308
00309 first = 1;
00310 continue;
00311 } else {
00312 break;
00313 }
00314 }
00315 newval = va_arg(ap, const char *);
00316 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00317 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00318 ast_str_append(&query, 0, "%s%s=%s", first ? "" : "&", buf1, buf2);
00319 }
00320 va_end(ap);
00321
00322 ast_str_append(&query, 0, ")}");
00323
00324 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00325
00326
00327 stringp = buffer;
00328 while (*stringp <= ' ')
00329 stringp++;
00330 sscanf(stringp, "%30d", &rowcount);
00331
00332 ast_free(buffer);
00333 ast_free(query);
00334
00335 if (rowcount >= 0)
00336 return (int)rowcount;
00337
00338 return -1;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 static int store_curl(const char *url, const char *unused, va_list ap)
00355 {
00356 struct ast_str *query;
00357 char buf1[200], buf2[200];
00358 const char *newparam, *newval;
00359 char *stringp;
00360 int i, rowcount = -1;
00361 const int EncodeSpecialChars = 1, bufsize = 100;
00362 char *buffer;
00363
00364 if (!ast_custom_function_find("CURL")) {
00365 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00366 return -1;
00367 }
00368
00369 if (!(query = ast_str_create(1000)))
00370 return -1;
00371
00372 if (!(buffer = ast_malloc(bufsize))) {
00373 ast_free(query);
00374 return -1;
00375 }
00376
00377 ast_str_set(&query, 0, "${CURL(%s/store,", url);
00378
00379 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00380 newval = va_arg(ap, const char *);
00381 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00382 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00383 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00384 }
00385 va_end(ap);
00386
00387 ast_str_append(&query, 0, ")}");
00388 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00389
00390 stringp = buffer;
00391 while (*stringp <= ' ')
00392 stringp++;
00393 sscanf(stringp, "%30d", &rowcount);
00394
00395 ast_free(buffer);
00396 ast_free(query);
00397
00398 if (rowcount >= 0)
00399 return (int)rowcount;
00400
00401 return -1;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
00420 {
00421 struct ast_str *query;
00422 char buf1[200], buf2[200];
00423 const char *newparam, *newval;
00424 char *stringp;
00425 int i, rowcount = -1;
00426 const int EncodeSpecialChars = 1, bufsize = 100;
00427 char *buffer;
00428
00429 if (!ast_custom_function_find("CURL")) {
00430 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00431 return -1;
00432 }
00433
00434 if (!(query = ast_str_create(1000)))
00435 return -1;
00436
00437 if (!(buffer = ast_malloc(bufsize))) {
00438 ast_free(query);
00439 return -1;
00440 }
00441
00442 ast_uri_encode(keyfield, buf1, sizeof(buf1), EncodeSpecialChars);
00443 ast_uri_encode(lookup, buf2, sizeof(buf2), EncodeSpecialChars);
00444 ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);
00445
00446 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00447 newval = va_arg(ap, const char *);
00448 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00449 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00450 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00451 }
00452 va_end(ap);
00453
00454 ast_str_append(&query, 0, ")}");
00455 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00456
00457
00458 stringp = buffer;
00459 while (*stringp <= ' ')
00460 stringp++;
00461 sscanf(stringp, "%30d", &rowcount);
00462
00463 ast_free(buffer);
00464 ast_free(query);
00465
00466 if (rowcount >= 0)
00467 return (int)rowcount;
00468
00469 return -1;
00470 }
00471
00472 static int require_curl(const char *url, const char *unused, va_list ap)
00473 {
00474 struct ast_str *query;
00475 char *elm, field[256], buffer[128];
00476 int type, size;
00477 const int EncodeSpecialChars = 1;
00478
00479 if (!ast_custom_function_find("CURL")) {
00480 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00481 return -1;
00482 }
00483
00484 if (!(query = ast_str_create(100))) {
00485 return -1;
00486 }
00487
00488 ast_str_set(&query, 0, "${CURL(%s/require,", url);
00489
00490 while ((elm = va_arg(ap, char *))) {
00491 type = va_arg(ap, require_type);
00492 size = va_arg(ap, int);
00493 ast_uri_encode(elm, field, sizeof(field), EncodeSpecialChars);
00494 ast_str_append(&query, 0, "%s=%s%%3A%d", field,
00495 type == RQ_CHAR ? "char" :
00496 type == RQ_INTEGER1 ? "integer1" :
00497 type == RQ_UINTEGER1 ? "uinteger1" :
00498 type == RQ_INTEGER2 ? "integer2" :
00499 type == RQ_UINTEGER2 ? "uinteger2" :
00500 type == RQ_INTEGER3 ? "integer3" :
00501 type == RQ_UINTEGER3 ? "uinteger3" :
00502 type == RQ_INTEGER4 ? "integer4" :
00503 type == RQ_UINTEGER4 ? "uinteger4" :
00504 type == RQ_INTEGER8 ? "integer8" :
00505 type == RQ_UINTEGER8 ? "uinteger8" :
00506 type == RQ_DATE ? "date" :
00507 type == RQ_DATETIME ? "datetime" :
00508 type == RQ_FLOAT ? "float" :
00509 "unknown", size);
00510 }
00511 va_end(ap);
00512
00513 ast_str_append(&query, 0, ")}");
00514 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, sizeof(buffer) - 1);
00515 return atoi(buffer);
00516 }
00517
00518 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)
00519 {
00520 struct ast_str *query;
00521 char buf1[200];
00522 char *stringp, *line, *pair, *key;
00523 const int EncodeSpecialChars = 1, bufsize = 256000;
00524 int last_cat_metric = -1, cat_metric = -1;
00525 struct ast_category *cat=NULL;
00526 char *buffer, *cur_cat = "";
00527 char *category = "", *var_name = "", *var_val = "";
00528 struct ast_flags loader_flags = { 0 };
00529
00530 if (!ast_custom_function_find("CURL")) {
00531 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00532 return NULL;
00533 }
00534
00535 if (!(query = ast_str_create(1000)))
00536 return NULL;
00537
00538 if (!(buffer = ast_malloc(bufsize))) {
00539 ast_free(query);
00540 return NULL;
00541 }
00542
00543 ast_uri_encode(file, buf1, sizeof(buf1), EncodeSpecialChars);
00544 ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
00545
00546
00547 pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize - 1);
00548
00549
00550 stringp = buffer;
00551 cat = ast_config_get_current_category(cfg);
00552
00553 while ((line = strsep(&stringp, "\r\n"))) {
00554 if (ast_strlen_zero(line))
00555 continue;
00556
00557 while ((pair = strsep(&line, "&"))) {
00558 key = strsep(&pair, "=");
00559 ast_uri_decode(key);
00560 if (pair)
00561 ast_uri_decode(pair);
00562
00563 if (!strcasecmp(key, "category"))
00564 category = S_OR(pair, "");
00565 else if (!strcasecmp(key, "var_name"))
00566 var_name = S_OR(pair, "");
00567 else if (!strcasecmp(key, "var_val"))
00568 var_val = S_OR(pair, "");
00569 else if (!strcasecmp(key, "cat_metric"))
00570 cat_metric = pair ? atoi(pair) : 0;
00571 }
00572
00573 if (!strcmp(var_name, "#include")) {
00574 if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
00575 return NULL;
00576 }
00577
00578 if (strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
00579 if (!(cat = ast_category_new(category, "", 99999)))
00580 break;
00581 cur_cat = category;
00582 last_cat_metric = cat_metric;
00583 ast_category_append(cfg, cat);
00584 }
00585 ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
00586 }
00587
00588 ast_free(buffer);
00589 ast_free(query);
00590 return cfg;
00591 }
00592
00593 static struct ast_config_engine curl_engine = {
00594 .name = "curl",
00595 .load_func = config_curl,
00596 .realtime_func = realtime_curl,
00597 .realtime_multi_func = realtime_multi_curl,
00598 .store_func = store_curl,
00599 .destroy_func = destroy_curl,
00600 .update_func = update_curl,
00601 .update2_func = update2_curl,
00602 .require_func = require_curl,
00603 };
00604
00605 static int unload_module(void)
00606 {
00607 ast_config_engine_deregister(&curl_engine);
00608 ast_verb(1, "res_config_curl unloaded.\n");
00609 return 0;
00610 }
00611
00612 static int load_module(void)
00613 {
00614 if (!ast_module_check("res_curl.so")) {
00615 if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00616 ast_log(LOG_ERROR, "Cannot load res_curl, so res_config_curl cannot be loaded\n");
00617 return AST_MODULE_LOAD_DECLINE;
00618 }
00619 }
00620
00621 ast_config_engine_register(&curl_engine);
00622 ast_verb(1, "res_config_curl loaded.\n");
00623 return 0;
00624 }
00625
00626 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Curl configuration");