Mon Jun 27 16:50:53 2011

Asterisk developer's documentation


func_curl.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C)  2004 - 2006, Tilghman Lesher
00005  *
00006  * Tilghman Lesher <curl-20050919@the-tilghman.com>
00007  * and Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)
00008  *
00009  * app_curl.c is distributed with no restrictions on usage or
00010  * redistribution.
00011  *
00012  * See http://www.asterisk.org for more information about
00013  * the Asterisk project. Please do not directly contact
00014  * any of the maintainers of this project for assistance;
00015  * the project provides a web site, mailing lists and IRC
00016  * channels for your use.
00017  *
00018  */
00019 
00020 /*! \file
00021  * 
00022  * \brief Curl - Load a URL
00023  *
00024  * \author Tilghman Lesher <curl-20050919@the-tilghman.com>
00025  *
00026  * \note Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option) 
00027  *
00028  * \extref Depends on the CURL library  - http://curl.haxx.se/
00029  * 
00030  * \ingroup functions
00031  */
00032  
00033 /*** MODULEINFO
00034    <depend>curl</depend>
00035  ***/
00036 
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 294989 $")
00040 
00041 #include <curl/curl.h>
00042 
00043 #include "asterisk/lock.h"
00044 #include "asterisk/file.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/cli.h"
00048 #include "asterisk/module.h"
00049 #include "asterisk/app.h"
00050 #include "asterisk/utils.h"
00051 #include "asterisk/threadstorage.h"
00052 
00053 #define CURLVERSION_ATLEAST(a,b,c) \
00054    ((LIBCURL_VERSION_MAJOR > (a)) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR > (b))) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR == (b)) && (LIBCURL_VERSION_PATCH >= (c))))
00055 
00056 #define CURLOPT_SPECIAL_HASHCOMPAT -500
00057 
00058 static void curlds_free(void *data);
00059 
00060 static struct ast_datastore_info curl_info = {
00061    .type = "CURL",
00062    .destroy = curlds_free,
00063 };
00064 
00065 struct curl_settings {
00066    AST_LIST_ENTRY(curl_settings) list;
00067    CURLoption key;
00068    void *value;
00069 };
00070 
00071 AST_LIST_HEAD_STATIC(global_curl_info, curl_settings);
00072 
00073 static void curlds_free(void *data)
00074 {
00075    AST_LIST_HEAD(global_curl_info, curl_settings) *list = data;
00076    struct curl_settings *setting;
00077    if (!list) {
00078       return;
00079    }
00080    while ((setting = AST_LIST_REMOVE_HEAD(list, list))) {
00081       free(setting);
00082    }
00083    AST_LIST_HEAD_DESTROY(list);
00084 }
00085 
00086 enum optiontype {
00087    OT_BOOLEAN,
00088    OT_INTEGER,
00089    OT_INTEGER_MS,
00090    OT_STRING,
00091    OT_ENUM,
00092 };
00093 
00094 static int parse_curlopt_key(const char *name, CURLoption *key, enum optiontype *ot)
00095 {
00096    if (!strcasecmp(name, "header")) {
00097       *key = CURLOPT_HEADER;
00098       *ot = OT_BOOLEAN;
00099    } else if (!strcasecmp(name, "proxy")) {
00100       *key = CURLOPT_PROXY;
00101       *ot = OT_STRING;
00102    } else if (!strcasecmp(name, "proxyport")) {
00103       *key = CURLOPT_PROXYPORT;
00104       *ot = OT_INTEGER;
00105    } else if (!strcasecmp(name, "proxytype")) {
00106       *key = CURLOPT_PROXYTYPE;
00107       *ot = OT_ENUM;
00108    } else if (!strcasecmp(name, "dnstimeout")) {
00109       *key = CURLOPT_DNS_CACHE_TIMEOUT;
00110       *ot = OT_INTEGER;
00111    } else if (!strcasecmp(name, "userpwd")) {
00112       *key = CURLOPT_USERPWD;
00113       *ot = OT_STRING;
00114    } else if (!strcasecmp(name, "proxyuserpwd")) {
00115       *key = CURLOPT_PROXYUSERPWD;
00116       *ot = OT_STRING;
00117    } else if (!strcasecmp(name, "maxredirs")) {
00118       *key = CURLOPT_MAXREDIRS;
00119       *ot = OT_INTEGER;
00120    } else if (!strcasecmp(name, "referer")) {
00121       *key = CURLOPT_REFERER;
00122       *ot = OT_STRING;
00123    } else if (!strcasecmp(name, "useragent")) {
00124       *key = CURLOPT_USERAGENT;
00125       *ot = OT_STRING;
00126    } else if (!strcasecmp(name, "cookie")) {
00127       *key = CURLOPT_COOKIE;
00128       *ot = OT_STRING;
00129    } else if (!strcasecmp(name, "ftptimeout")) {
00130       *key = CURLOPT_FTP_RESPONSE_TIMEOUT;
00131       *ot = OT_INTEGER;
00132    } else if (!strcasecmp(name, "httptimeout")) {
00133 #if CURLVERSION_ATLEAST(7,16,2)
00134       *key = CURLOPT_TIMEOUT_MS;
00135       *ot = OT_INTEGER_MS;
00136 #else
00137       *key = CURLOPT_TIMEOUT;
00138       *ot = OT_INTEGER;
00139 #endif
00140    } else if (!strcasecmp(name, "conntimeout")) {
00141 #if CURLVERSION_ATLEAST(7,16,2)
00142       *key = CURLOPT_CONNECTTIMEOUT_MS;
00143       *ot = OT_INTEGER_MS;
00144 #else
00145       *key = CURLOPT_CONNECTTIMEOUT;
00146       *ot = OT_INTEGER;
00147 #endif
00148    } else if (!strcasecmp(name, "ftptext")) {
00149       *key = CURLOPT_TRANSFERTEXT;
00150       *ot = OT_BOOLEAN;
00151    } else if (!strcasecmp(name, "ssl_verifypeer")) {
00152       *key = CURLOPT_SSL_VERIFYPEER;
00153       *ot = OT_BOOLEAN;
00154    } else if (!strcasecmp(name, "hashcompat")) {
00155       *key = CURLOPT_SPECIAL_HASHCOMPAT;
00156       *ot = OT_BOOLEAN;
00157    } else {
00158       return -1;
00159    }
00160    return 0;
00161 }
00162 
00163 static int acf_curlopt_write(struct ast_channel *chan, const char *cmd, char *name, const char *value)
00164 {
00165    struct ast_datastore *store;
00166    struct global_curl_info *list;
00167    struct curl_settings *cur, *new = NULL;
00168    CURLoption key;
00169    enum optiontype ot;
00170 
00171    if (chan) {
00172       if (!(store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
00173          /* Create a new datastore */
00174          if (!(store = ast_datastore_alloc(&curl_info, NULL))) {
00175             ast_log(LOG_ERROR, "Unable to allocate new datastore.  Cannot set any CURL options\n");
00176             return -1;
00177          }
00178 
00179          if (!(list = ast_calloc(1, sizeof(*list)))) {
00180             ast_log(LOG_ERROR, "Unable to allocate list head.  Cannot set any CURL options\n");
00181             ast_datastore_free(store);
00182          }
00183 
00184          store->data = list;
00185          AST_LIST_HEAD_INIT(list);
00186          ast_channel_datastore_add(chan, store);
00187       } else {
00188          list = store->data;
00189       }
00190    } else {
00191       /* Populate the global structure */
00192       list = &global_curl_info;
00193    }
00194 
00195    if (!parse_curlopt_key(name, &key, &ot)) {
00196       if (ot == OT_BOOLEAN) {
00197          if ((new = ast_calloc(1, sizeof(*new)))) {
00198             new->value = (void *)((long) ast_true(value));
00199          }
00200       } else if (ot == OT_INTEGER) {
00201          long tmp = atol(value);
00202          if ((new = ast_calloc(1, sizeof(*new)))) {
00203             new->value = (void *)tmp;
00204          }
00205       } else if (ot == OT_INTEGER_MS) {
00206          long tmp = atof(value) * 1000.0;
00207          if ((new = ast_calloc(1, sizeof(*new)))) {
00208             new->value = (void *)tmp;
00209          }
00210       } else if (ot == OT_STRING) {
00211          if ((new = ast_calloc(1, sizeof(*new) + strlen(value) + 1))) {
00212             new->value = (char *)new + sizeof(*new);
00213             strcpy(new->value, value);
00214          }
00215       } else if (ot == OT_ENUM) {
00216          if (key == CURLOPT_PROXYTYPE) {
00217             long ptype =
00218 #if CURLVERSION_ATLEAST(7,10,0)
00219                CURLPROXY_HTTP;
00220 #else
00221                CURLPROXY_SOCKS5;
00222 #endif
00223             if (0) {
00224 #if CURLVERSION_ATLEAST(7,15,2)
00225             } else if (!strcasecmp(value, "socks4")) {
00226                ptype = CURLPROXY_SOCKS4;
00227 #endif
00228 #if CURLVERSION_ATLEAST(7,18,0)
00229             } else if (!strcasecmp(value, "socks4a")) {
00230                ptype = CURLPROXY_SOCKS4A;
00231 #endif
00232 #if CURLVERSION_ATLEAST(7,18,0)
00233             } else if (!strcasecmp(value, "socks5")) {
00234                ptype = CURLPROXY_SOCKS5;
00235 #endif
00236 #if CURLVERSION_ATLEAST(7,18,0)
00237             } else if (!strncasecmp(value, "socks5", 6)) {
00238                ptype = CURLPROXY_SOCKS5_HOSTNAME;
00239 #endif
00240             }
00241 
00242             if ((new = ast_calloc(1, sizeof(*new)))) {
00243                new->value = (void *)ptype;
00244             }
00245          } else {
00246             /* Highly unlikely */
00247             goto yuck;
00248          }
00249       }
00250 
00251       /* Memory allocation error */
00252       if (!new) {
00253          return -1;
00254       }
00255 
00256       new->key = key;
00257    } else {
00258 yuck:
00259       ast_log(LOG_ERROR, "Unrecognized option: %s\n", name);
00260       return -1;
00261    }
00262 
00263    /* Remove any existing entry */
00264    AST_LIST_LOCK(list);
00265    AST_LIST_TRAVERSE_SAFE_BEGIN(list, cur, list) {
00266       if (cur->key == new->key) {
00267          AST_LIST_REMOVE_CURRENT(list);
00268          free(cur);
00269          break;
00270       }
00271    }
00272    AST_LIST_TRAVERSE_SAFE_END
00273 
00274    /* Insert new entry */
00275    ast_debug(1, "Inserting entry %p with key %d and value %p\n", new, new->key, new->value);
00276    AST_LIST_INSERT_TAIL(list, new, list);
00277    AST_LIST_UNLOCK(list);
00278 
00279    return 0;
00280 }
00281 
00282 static int acf_curlopt_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, ssize_t len)
00283 {
00284    struct ast_datastore *store;
00285    struct global_curl_info *list[2] = { &global_curl_info, NULL };
00286    struct curl_settings *cur = NULL;
00287    CURLoption key;
00288    enum optiontype ot;
00289    int i;
00290 
00291    if (parse_curlopt_key(data, &key, &ot)) {
00292       ast_log(LOG_ERROR, "Unrecognized option: '%s'\n", data);
00293       return -1;
00294    }
00295 
00296    if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
00297       list[0] = store->data;
00298       list[1] = &global_curl_info;
00299    }
00300 
00301    for (i = 0; i < 2; i++) {
00302       if (!list[i]) {
00303          break;
00304       }
00305       AST_LIST_LOCK(list[i]);
00306       AST_LIST_TRAVERSE(list[i], cur, list) {
00307          if (cur->key == key) {
00308             if (ot == OT_BOOLEAN || ot == OT_INTEGER) {
00309                if (buf) {
00310                   snprintf(buf, len, "%ld", (long) cur->value);
00311                } else {
00312                   ast_str_set(bufstr, len, "%ld", (long) cur->value);
00313                }
00314             } else if (ot == OT_INTEGER_MS) {
00315                if ((long) cur->value % 1000 == 0) {
00316                   if (buf) {
00317                      snprintf(buf, len, "%ld", (long)cur->value / 1000);
00318                   } else {
00319                      ast_str_set(bufstr, len, "%ld", (long) cur->value / 1000);
00320                   }
00321                } else {
00322                   if (buf) {
00323                      snprintf(buf, len, "%.3f", (double) ((long) cur->value) / 1000.0);
00324                   } else {
00325                      ast_str_set(bufstr, len, "%.3f", (double) ((long) cur->value) / 1000.0);
00326                   }
00327                }
00328             } else if (ot == OT_STRING) {
00329                ast_debug(1, "Found entry %p, with key %d and value %p\n", cur, cur->key, cur->value);
00330                if (buf) {
00331                   ast_copy_string(buf, cur->value, len);
00332                } else {
00333                   ast_str_set(bufstr, 0, "%s", (char *) cur->value);
00334                }
00335             } else if (key == CURLOPT_PROXYTYPE) {
00336                if (0) {
00337 #if CURLVERSION_ATLEAST(7,15,2)
00338                } else if ((long)cur->value == CURLPROXY_SOCKS4) {
00339                   if (buf) {
00340                      ast_copy_string(buf, "socks4", len);
00341                   } else {
00342                      ast_str_set(bufstr, 0, "socks4");
00343                   }
00344 #endif
00345 #if CURLVERSION_ATLEAST(7,18,0)
00346                } else if ((long)cur->value == CURLPROXY_SOCKS4A) {
00347                   if (buf) {
00348                      ast_copy_string(buf, "socks4a", len);
00349                   } else {
00350                      ast_str_set(bufstr, 0, "socks4a");
00351                   }
00352 #endif
00353                } else if ((long)cur->value == CURLPROXY_SOCKS5) {
00354                   if (buf) {
00355                      ast_copy_string(buf, "socks5", len);
00356                   } else {
00357                      ast_str_set(bufstr, 0, "socks5");
00358                   }
00359 #if CURLVERSION_ATLEAST(7,18,0)
00360                } else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) {
00361                   if (buf) {
00362                      ast_copy_string(buf, "socks5hostname", len);
00363                   } else {
00364                      ast_str_set(bufstr, 0, "socks5hostname");
00365                   }
00366 #endif
00367 #if CURLVERSION_ATLEAST(7,10,0)
00368                } else if ((long)cur->value == CURLPROXY_HTTP) {
00369                   if (buf) {
00370                      ast_copy_string(buf, "http", len);
00371                   } else {
00372                      ast_str_set(bufstr, 0, "http");
00373                   }
00374 #endif
00375                } else {
00376                   if (buf) {
00377                      ast_copy_string(buf, "unknown", len);
00378                   } else {
00379                      ast_str_set(bufstr, 0, "unknown");
00380                   }
00381                }
00382             }
00383             break;
00384          }
00385       }
00386       AST_LIST_UNLOCK(list[i]);
00387       if (cur) {
00388          break;
00389       }
00390    }
00391 
00392    return cur ? 0 : -1;
00393 }
00394 
00395 static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00396 {
00397    return acf_curlopt_helper(chan, cmd, data, buf, NULL, len);
00398 }
00399 
00400 static int acf_curlopt_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
00401 {
00402    return acf_curlopt_helper(chan, cmd, data, NULL, buf, len);
00403 }
00404 
00405 static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
00406 {
00407    register int realsize = size * nmemb;
00408    struct ast_str **pstr = (struct ast_str **)data;
00409 
00410    ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, ast_str_size(*pstr), ast_str_strlen(*pstr));
00411 
00412    ast_str_append_substr(pstr, 0, ptr, realsize);
00413 
00414    ast_debug(3, "Now, len=%zu, used=%zu\n", ast_str_size(*pstr), ast_str_strlen(*pstr));
00415 
00416    return realsize;
00417 }
00418 
00419 static const char * const global_useragent = "asterisk-libcurl-agent/1.0";
00420 
00421 static int curl_instance_init(void *data)
00422 {
00423    CURL **curl = data;
00424 
00425    if (!(*curl = curl_easy_init()))
00426       return -1;
00427 
00428    curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1);
00429    curl_easy_setopt(*curl, CURLOPT_TIMEOUT, 180);
00430    curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
00431    curl_easy_setopt(*curl, CURLOPT_USERAGENT, global_useragent);
00432 
00433    return 0;
00434 }
00435 
00436 static void curl_instance_cleanup(void *data)
00437 {
00438    CURL **curl = data;
00439 
00440    curl_easy_cleanup(*curl);
00441 
00442    ast_free(data);
00443 }
00444 
00445 AST_THREADSTORAGE_CUSTOM(curl_instance, curl_instance_init, curl_instance_cleanup);
00446 
00447 static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info, char *buf, struct ast_str **input_str, ssize_t len)
00448 {
00449    struct ast_str *str = ast_str_create(16);
00450    int ret = -1;
00451    AST_DECLARE_APP_ARGS(args,
00452       AST_APP_ARG(url);
00453       AST_APP_ARG(postdata);
00454    );
00455    CURL **curl;
00456    struct curl_settings *cur;
00457    struct ast_datastore *store = NULL;
00458    int hashcompat = 0;
00459    AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL;
00460 
00461    if (buf) {
00462       *buf = '\0';
00463    }
00464 
00465    if (ast_strlen_zero(info)) {
00466       ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
00467       ast_free(str);
00468       return -1;
00469    }
00470 
00471    AST_STANDARD_APP_ARGS(args, info);
00472 
00473    if (chan) {
00474       ast_autoservice_start(chan);
00475    }
00476 
00477    if (!(curl = ast_threadstorage_get(&curl_instance, sizeof(*curl)))) {
00478       ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
00479       return -1;
00480    }
00481 
00482    AST_LIST_LOCK(&global_curl_info);
00483    AST_LIST_TRAVERSE(&global_curl_info, cur, list) {
00484       if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
00485          hashcompat = (cur->value != NULL) ? 1 : 0;
00486       } else {
00487          curl_easy_setopt(*curl, cur->key, cur->value);
00488       }
00489    }
00490 
00491    if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
00492       list = store->data;
00493       AST_LIST_LOCK(list);
00494       AST_LIST_TRAVERSE(list, cur, list) {
00495          if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
00496             hashcompat = (cur->value != NULL) ? 1 : 0;
00497          } else {
00498             curl_easy_setopt(*curl, cur->key, cur->value);
00499          }
00500       }
00501    }
00502 
00503    curl_easy_setopt(*curl, CURLOPT_URL, args.url);
00504    curl_easy_setopt(*curl, CURLOPT_FILE, (void *) &str);
00505 
00506    if (args.postdata) {
00507       curl_easy_setopt(*curl, CURLOPT_POST, 1);
00508       curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, args.postdata);
00509    }
00510 
00511    curl_easy_perform(*curl);
00512 
00513    if (store) {
00514       AST_LIST_UNLOCK(list);
00515    }
00516    AST_LIST_UNLOCK(&global_curl_info);
00517 
00518    if (args.postdata) {
00519       curl_easy_setopt(*curl, CURLOPT_POST, 0);
00520    }
00521 
00522    if (ast_str_strlen(str)) {
00523       ast_str_trim_blanks(str);
00524 
00525       ast_debug(3, "str='%s'\n", ast_str_buffer(str));
00526       if (hashcompat) {
00527          char *remainder = ast_str_buffer(str);
00528          char *piece;
00529          struct ast_str *fields = ast_str_create(ast_str_strlen(str) / 2);
00530          struct ast_str *values = ast_str_create(ast_str_strlen(str) / 2);
00531          int rowcount = 0;
00532          while (fields && values && (piece = strsep(&remainder, "&"))) {
00533             char *name = strsep(&piece, "=");
00534             if (!piece) {
00535                piece = "";
00536             }
00537             ast_uri_decode(piece);
00538             ast_uri_decode(name);
00539             ast_str_append(&fields, 0, "%s%s", rowcount ? "," : "", name);
00540             ast_str_append(&values, 0, "%s%s", rowcount ? "," : "", piece);
00541             rowcount++;
00542          }
00543          pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
00544          if (buf) {
00545             ast_copy_string(buf, ast_str_buffer(values), len);
00546          } else {
00547             ast_str_set(input_str, len, "%s", ast_str_buffer(values));
00548          }
00549          ast_free(fields);
00550          ast_free(values);
00551       } else {
00552          if (buf) {
00553             ast_copy_string(buf, ast_str_buffer(str), len);
00554          } else {
00555             ast_str_set(input_str, len, "%s", ast_str_buffer(str));
00556          }
00557       }
00558       ret = 0;
00559    }
00560    ast_free(str);
00561 
00562    if (chan)
00563       ast_autoservice_stop(chan);
00564 
00565    return ret;
00566 }
00567 
00568 static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
00569 {
00570    return acf_curl_helper(chan, cmd, info, buf, NULL, len);
00571 }
00572 
00573 static int acf_curl2_exec(struct ast_channel *chan, const char *cmd, char *info, struct ast_str **buf, ssize_t len)
00574 {
00575    return acf_curl_helper(chan, cmd, info, NULL, buf, len);
00576 }
00577 
00578 static struct ast_custom_function acf_curl = {
00579    .name = "CURL",
00580    .synopsis = "Retrieves the contents of a URL",
00581    .syntax = "CURL(url[,post-data])",
00582    .desc =
00583    "  url       - URL to retrieve\n"
00584    "  post-data - Optional data to send as a POST (GET is default action)\n",
00585    .read = acf_curl_exec,
00586    .read2 = acf_curl2_exec,
00587 };
00588 
00589 static struct ast_custom_function acf_curlopt = {
00590    .name = "CURLOPT",
00591    .synopsis = "Set options for use with the CURL() function",
00592    .syntax = "CURLOPT(<option>)",
00593    .desc =
00594 "  cookie         - Send cookie with request [none]\n"
00595 "  conntimeout    - Number of seconds to wait for connection\n"
00596 "  dnstimeout     - Number of seconds to wait for DNS response\n"
00597 "  ftptext        - For FTP, force a text transfer (boolean)\n"
00598 "  ftptimeout     - For FTP, the server response timeout\n"
00599 "  header         - Retrieve header information (boolean)\n"
00600 "  httptimeout    - Number of seconds to wait for HTTP response\n"
00601 "  maxredirs      - Maximum number of redirects to follow\n"
00602 "  proxy          - Hostname or IP to use as a proxy\n"
00603 "  proxytype      - http, socks4, or socks5\n"
00604 "  proxyport      - port number of the proxy\n"
00605 "  proxyuserpwd   - A <user>:<pass> to use for authentication\n"
00606 "  referer        - Referer URL to use for the request\n"
00607 "  useragent      - UserAgent string to use\n"
00608 "  userpwd        - A <user>:<pass> to use for authentication\n"
00609 "  ssl_verifypeer - Whether to verify the peer certificate (boolean)\n"
00610 "  hashcompat     - Result data will be compatible for use with HASH()\n"
00611 "",
00612    .read = acf_curlopt_read,
00613    .read2 = acf_curlopt_read2,
00614    .write = acf_curlopt_write,
00615 };
00616 
00617 static int unload_module(void)
00618 {
00619    int res;
00620 
00621    res = ast_custom_function_unregister(&acf_curl);
00622    res |= ast_custom_function_unregister(&acf_curlopt);
00623 
00624    return res;
00625 }
00626 
00627 static int load_module(void)
00628 {
00629    int res;
00630 
00631    if (!ast_module_check("res_curl.so")) {
00632       if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00633          ast_log(LOG_ERROR, "Cannot load res_curl, so func_curl cannot be loaded\n");
00634          return AST_MODULE_LOAD_DECLINE;
00635       }
00636    }
00637 
00638    res = ast_custom_function_register(&acf_curl);
00639    res |= ast_custom_function_register(&acf_curlopt);
00640 
00641    return res;
00642 }
00643 
00644 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Load external URL",
00645       .load = load_module,
00646       .unload = unload_module,
00647       .load_pri = AST_MODPRI_REALTIME_DEPEND2,
00648    );
00649 

Generated on Mon Jun 27 16:50:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7