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: 107793 $")
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, query->str, buffer, bufsize);
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, query->str, buffer, bufsize);
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, query->str, buffer, bufsize);
00262
00263
00264 stringp = buffer;
00265 while (*stringp <= ' ')
00266 stringp++;
00267 sscanf(stringp, "%d", &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
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 static int store_curl(const char *url, const char *unused, va_list ap)
00292 {
00293 struct ast_str *query;
00294 char buf1[200], buf2[200];
00295 const char *newparam, *newval;
00296 char *stringp;
00297 int i, rowcount = -1;
00298 const int EncodeSpecialChars = 1, bufsize = 100;
00299 char *buffer;
00300
00301 if (!ast_custom_function_find("CURL")) {
00302 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00303 return -1;
00304 }
00305
00306 if (!(query = ast_str_create(1000)))
00307 return -1;
00308
00309 if (!(buffer = ast_malloc(bufsize))) {
00310 ast_free(query);
00311 return -1;
00312 }
00313
00314 ast_str_set(&query, 0, "${CURL(%s/store,", url);
00315
00316 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00317 newval = va_arg(ap, const char *);
00318 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00319 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00320 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00321 }
00322 va_end(ap);
00323
00324 ast_str_append(&query, 0, ")}");
00325 pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
00326
00327 stringp = buffer;
00328 while (*stringp <= ' ')
00329 stringp++;
00330 sscanf(stringp, "%d", &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
00355
00356 static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
00357 {
00358 struct ast_str *query;
00359 char buf1[200], buf2[200];
00360 const char *newparam, *newval;
00361 char *stringp;
00362 int i, rowcount = -1;
00363 const int EncodeSpecialChars = 1, bufsize = 100;
00364 char *buffer;
00365
00366 if (!ast_custom_function_find("CURL")) {
00367 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00368 return -1;
00369 }
00370
00371 if (!(query = ast_str_create(1000)))
00372 return -1;
00373
00374 if (!(buffer = ast_malloc(bufsize))) {
00375 ast_free(query);
00376 return -1;
00377 }
00378
00379 ast_uri_encode(keyfield, buf1, sizeof(buf1), EncodeSpecialChars);
00380 ast_uri_encode(lookup, buf2, sizeof(buf2), EncodeSpecialChars);
00381 ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);
00382
00383 for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00384 newval = va_arg(ap, const char *);
00385 ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00386 ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00387 ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00388 }
00389 va_end(ap);
00390
00391 ast_str_append(&query, 0, ")}");
00392 pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
00393
00394
00395 stringp = buffer;
00396 while (*stringp <= ' ')
00397 stringp++;
00398 sscanf(stringp, "%d", &rowcount);
00399
00400 ast_free(buffer);
00401 ast_free(query);
00402
00403 if (rowcount >= 0)
00404 return (int)rowcount;
00405
00406 return -1;
00407 }
00408
00409
00410 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)
00411 {
00412 struct ast_str *query;
00413 char buf1[200];
00414 char *stringp, *line, *pair, *key;
00415 const int EncodeSpecialChars = 1, bufsize = 256000;
00416 int last_cat_metric = -1, cat_metric = -1;
00417 struct ast_category *cat=NULL;
00418 char *buffer, *cur_cat = "";
00419 char *category = "", *var_name = "", *var_val = "";
00420 struct ast_flags loader_flags = { 0 };
00421
00422 if (!ast_custom_function_find("CURL")) {
00423 ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00424 return NULL;
00425 }
00426
00427 if (!(query = ast_str_create(1000)))
00428 return NULL;
00429
00430 if (!(buffer = ast_malloc(bufsize))) {
00431 ast_free(query);
00432 return NULL;
00433 }
00434
00435 ast_uri_encode(file, buf1, sizeof(buf1), EncodeSpecialChars);
00436 ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
00437
00438
00439 pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize);
00440
00441
00442 stringp = buffer;
00443 cat = ast_config_get_current_category(cfg);
00444
00445 while ((line = strsep(&stringp, "\r\n"))) {
00446 if (ast_strlen_zero(line))
00447 continue;
00448
00449 while ((pair = strsep(&line, "&"))) {
00450 key = strsep(&pair, "=");
00451 ast_uri_decode(key);
00452 if (pair)
00453 ast_uri_decode(pair);
00454
00455 if (!strcasecmp(key, "category"))
00456 category = S_OR(pair, "");
00457 else if (!strcasecmp(key, "var_name"))
00458 var_name = S_OR(pair, "");
00459 else if (!strcasecmp(key, "var_val"))
00460 var_val = S_OR(pair, "");
00461 else if (!strcasecmp(key, "cat_metric"))
00462 cat_metric = pair ? atoi(pair) : 0;
00463 }
00464
00465 if (!strcmp(var_name, "#include")) {
00466 if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
00467 return NULL;
00468 }
00469
00470 if (strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
00471 if (!(cat = ast_category_new(category, "", 99999)))
00472 break;
00473 cur_cat = category;
00474 last_cat_metric = cat_metric;
00475 ast_category_append(cfg, cat);
00476 }
00477 ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
00478 }
00479
00480 ast_free(buffer);
00481 ast_free(query);
00482 return cfg;
00483 }
00484
00485 static struct ast_config_engine curl_engine = {
00486 .name = "curl",
00487 .load_func = config_curl,
00488 .realtime_func = realtime_curl,
00489 .realtime_multi_func = realtime_multi_curl,
00490 .store_func = store_curl,
00491 .destroy_func = destroy_curl,
00492 .update_func = update_curl
00493 };
00494
00495 static int unload_module (void)
00496 {
00497 ast_config_engine_deregister(&curl_engine);
00498 ast_verb(1, "res_config_curl unloaded.\n");
00499 return 0;
00500 }
00501
00502 static int load_module (void)
00503 {
00504 ast_config_engine_register(&curl_engine);
00505 ast_verb(1, "res_config_curl loaded.\n");
00506 return 0;
00507 }
00508
00509 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Curl configuration");