Sat Apr 26 2014 22:02:51

Asterisk developer's documentation


func_curl.c File Reference

Curl - Load a URL. More...

#include "asterisk.h"
#include <curl/curl.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
Include dependency graph for func_curl.c:

Go to the source code of this file.

Data Structures

struct  curl_settings
struct  global_curl_info

Defines

#define CURLOPT_SPECIAL_HASHCOMPAT   -500
#define CURLVERSION_ATLEAST(a, b, c)   ((LIBCURL_VERSION_MAJOR > (a)) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR > (b))) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR == (b)) && (LIBCURL_VERSION_PATCH >= (c))))

Enumerations

enum  hashcompat { HASHCOMPAT_NO = 0, HASHCOMPAT_YES, HASHCOMPAT_LEGACY }
enum  optiontype {
  OT_BOOLEAN, OT_INTEGER, OT_INTEGER_MS, OT_STRING,
  OT_ENUM
}

Functions

static void __init_curl_instance (void)
static void __init_thread_escapebuf (void)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_curl2_exec (struct ast_channel *chan, const char *cmd, char *info, struct ast_str **buf, ssize_t len)
static int acf_curl_exec (struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
static int acf_curl_helper (struct ast_channel *chan, const char *cmd, char *info, char *buf, struct ast_str **input_str, ssize_t len)
static int acf_curlopt_helper (struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, ssize_t len)
static int acf_curlopt_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int acf_curlopt_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
static int acf_curlopt_write (struct ast_channel *chan, const char *cmd, char *name, const char *value)
static void curl_instance_cleanup (void *data)
static int curl_instance_init (void *data)
static void curlds_free (void *data)
static int load_module (void)
static int parse_curlopt_key (const char *name, CURLoption *key, enum optiontype *ot)
static int unload_module (void)
static size_t WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Load external URL" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_REALTIME_DEPEND2, }
static struct ast_custom_function acf_curl
static struct ast_custom_function acf_curlopt
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_datastore_info curl_info
static struct ast_threadstorage curl_instance = { .once = PTHREAD_ONCE_INIT , .key_init = __init_curl_instance , .custom_init = curl_instance_init , }
struct global_curl_info global_curl_info
static const char *const global_useragent = "asterisk-libcurl-agent/1.0"
static struct ast_threadstorage thread_escapebuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_escapebuf , .custom_init = NULL , }

Detailed Description

Curl - Load a URL.

Author:
Tilghman Lesher <curl-20050919@the-tilghman.com>
Note:
Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)
ExtRef:
Depends on the CURL library - http://curl.haxx.se/

Definition in file func_curl.c.


Define Documentation

#define CURLVERSION_ATLEAST (   a,
  b,
 
)    ((LIBCURL_VERSION_MAJOR > (a)) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR > (b))) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR == (b)) && (LIBCURL_VERSION_PATCH >= (c))))

Definition at line 170 of file func_curl.c.


Enumeration Type Documentation

enum hashcompat
Enumerator:
HASHCOMPAT_NO 
HASHCOMPAT_YES 
HASHCOMPAT_LEGACY 

Definition at line 211 of file func_curl.c.

enum optiontype
Enumerator:
OT_BOOLEAN 
OT_INTEGER 
OT_INTEGER_MS 
OT_STRING 
OT_ENUM 

Definition at line 203 of file func_curl.c.


Function Documentation

static void __init_curl_instance ( void  ) [static]

Definition at line 567 of file func_curl.c.

{
static void __init_thread_escapebuf ( void  ) [static]

Definition at line 568 of file func_curl.c.

{
static void __reg_module ( void  ) [static]

Definition at line 796 of file func_curl.c.

static void __unreg_module ( void  ) [static]

Definition at line 796 of file func_curl.c.

static int acf_curl2_exec ( struct ast_channel chan,
const char *  cmd,
char *  info,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 720 of file func_curl.c.

References acf_curl_helper().

{
   return acf_curl_helper(chan, cmd, info, NULL, buf, len);
}
static int acf_curl_exec ( struct ast_channel chan,
const char *  cmd,
char *  info,
char *  buf,
size_t  len 
) [static]

Definition at line 715 of file func_curl.c.

References acf_curl_helper().

{
   return acf_curl_helper(chan, cmd, info, buf, NULL, len);
}
static int acf_curl_helper ( struct ast_channel chan,
const char *  cmd,
char *  info,
char *  buf,
struct ast_str **  input_str,
ssize_t  len 
) [static]

Definition at line 570 of file func_curl.c.

References args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_set_escapecommas(), ast_str_strlen(), ast_str_thread_get(), ast_str_trim_blanks(), ast_strlen_zero(), ast_threadstorage_get(), ast_uri_decode(), ast_uri_http, ast_uri_http_legacy, curl_instance, CURLOPT_SPECIAL_HASHCOMPAT, ast_datastore::data, HASHCOMPAT_LEGACY, curl_settings::key, curl_settings::list, LOG_ERROR, LOG_WARNING, name, pbx_builtin_setvar_helper(), S_OR, str, thread_escapebuf, url, and curl_settings::value.

Referenced by acf_curl2_exec(), and acf_curl_exec().

{
   struct ast_str *escapebuf = ast_str_thread_get(&thread_escapebuf, 16);
   struct ast_str *str = ast_str_create(16);
   int ret = -1;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(url);
      AST_APP_ARG(postdata);
   );
   CURL **curl;
   struct curl_settings *cur;
   struct ast_datastore *store = NULL;
   int hashcompat = 0;
   AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL;
   char curl_errbuf[CURL_ERROR_SIZE + 1]; /* add one to be safe */

   if (buf) {
      *buf = '\0';
   }

   if (!str) {
      return -1;
   }

   if (!escapebuf) {
      ast_free(str);
      return -1;
   }

   if (ast_strlen_zero(info)) {
      ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
      ast_free(str);
      return -1;
   }

   AST_STANDARD_APP_ARGS(args, info);

   if (chan) {
      ast_autoservice_start(chan);
   }

   if (!(curl = ast_threadstorage_get(&curl_instance, sizeof(*curl)))) {
      ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
      ast_free(str);
      return -1;
   }

   AST_LIST_LOCK(&global_curl_info);
   AST_LIST_TRAVERSE(&global_curl_info, cur, list) {
      if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
         hashcompat = (long) cur->value;
      } else {
         curl_easy_setopt(*curl, cur->key, cur->value);
      }
   }

   if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
      list = store->data;
      AST_LIST_LOCK(list);
      AST_LIST_TRAVERSE(list, cur, list) {
         if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
            hashcompat = (long) cur->value;
         } else {
            curl_easy_setopt(*curl, cur->key, cur->value);
         }
      }
   }

   curl_easy_setopt(*curl, CURLOPT_URL, args.url);
   curl_easy_setopt(*curl, CURLOPT_FILE, (void *) &str);

   if (args.postdata) {
      curl_easy_setopt(*curl, CURLOPT_POST, 1);
      curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, args.postdata);
   }

   /* Temporarily assign a buffer for curl to write errors to. */
   curl_errbuf[0] = curl_errbuf[CURL_ERROR_SIZE] = '\0';
   curl_easy_setopt(*curl, CURLOPT_ERRORBUFFER, curl_errbuf);

   if (curl_easy_perform(*curl) != 0) {
      ast_log(LOG_WARNING, "%s ('%s')\n", curl_errbuf, args.url);
   }

   /* Reset buffer to NULL so curl doesn't try to write to it when the
    * buffer is deallocated. Documentation is vague about allowing NULL
    * here, but the source allows it. See: "typecheck: allow NULL to unset
    * CURLOPT_ERRORBUFFER" (62bcf005f4678a93158358265ba905bace33b834). */
   curl_easy_setopt(*curl, CURLOPT_ERRORBUFFER, (char*)NULL);

   if (store) {
      AST_LIST_UNLOCK(list);
   }
   AST_LIST_UNLOCK(&global_curl_info);

   if (args.postdata) {
      curl_easy_setopt(*curl, CURLOPT_POST, 0);
   }

   if (ast_str_strlen(str)) {
      ast_str_trim_blanks(str);

      ast_debug(3, "str='%s'\n", ast_str_buffer(str));
      if (hashcompat) {
         char *remainder = ast_str_buffer(str);
         char *piece;
         struct ast_str *fields = ast_str_create(ast_str_strlen(str) / 2);
         struct ast_str *values = ast_str_create(ast_str_strlen(str) / 2);
         int rowcount = 0;
         while (fields && values && (piece = strsep(&remainder, "&"))) {
            char *name = strsep(&piece, "=");
            struct ast_flags mode = (hashcompat == HASHCOMPAT_LEGACY ? ast_uri_http_legacy : ast_uri_http);
            if (piece) {
               ast_uri_decode(piece, mode);
            }
            ast_uri_decode(name, mode);
            ast_str_append(&fields, 0, "%s%s", rowcount ? "," : "", ast_str_set_escapecommas(&escapebuf, 0, name, INT_MAX));
            ast_str_append(&values, 0, "%s%s", rowcount ? "," : "", ast_str_set_escapecommas(&escapebuf, 0, S_OR(piece, ""), INT_MAX));
            rowcount++;
         }
         pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
         if (buf) {
            ast_copy_string(buf, ast_str_buffer(values), len);
         } else {
            ast_str_set(input_str, len, "%s", ast_str_buffer(values));
         }
         ast_free(fields);
         ast_free(values);
      } else {
         if (buf) {
            ast_copy_string(buf, ast_str_buffer(str), len);
         } else {
            ast_str_set(input_str, len, "%s", ast_str_buffer(str));
         }
      }
      ret = 0;
   }
   ast_free(str);

   if (chan)
      ast_autoservice_stop(chan);

   return ret;
}
static int acf_curlopt_helper ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
struct ast_str **  bufstr,
ssize_t  len 
) [static]

Definition at line 410 of file func_curl.c.

References ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_str_set(), CURLOPT_SPECIAL_HASHCOMPAT, ast_datastore::data, global_curl_info, HASHCOMPAT_LEGACY, HASHCOMPAT_NO, HASHCOMPAT_YES, curl_settings::key, curl_settings::list, LOG_ERROR, OT_BOOLEAN, OT_INTEGER, OT_INTEGER_MS, OT_STRING, parse_curlopt_key(), and curl_settings::value.

Referenced by acf_curlopt_read(), and acf_curlopt_read2().

{
   struct ast_datastore *store;
   struct global_curl_info *list[2] = { &global_curl_info, NULL };
   struct curl_settings *cur = NULL;
   CURLoption key;
   enum optiontype ot;
   int i;

   if (parse_curlopt_key(data, &key, &ot)) {
      ast_log(LOG_ERROR, "Unrecognized option: '%s'\n", data);
      return -1;
   }

   if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
      list[0] = store->data;
      list[1] = &global_curl_info;
   }

   for (i = 0; i < 2; i++) {
      if (!list[i]) {
         break;
      }
      AST_LIST_LOCK(list[i]);
      AST_LIST_TRAVERSE(list[i], cur, list) {
         if (cur->key == key) {
            if (ot == OT_BOOLEAN || ot == OT_INTEGER) {
               if (buf) {
                  snprintf(buf, len, "%ld", (long) cur->value);
               } else {
                  ast_str_set(bufstr, len, "%ld", (long) cur->value);
               }
            } else if (ot == OT_INTEGER_MS) {
               if ((long) cur->value % 1000 == 0) {
                  if (buf) {
                     snprintf(buf, len, "%ld", (long)cur->value / 1000);
                  } else {
                     ast_str_set(bufstr, len, "%ld", (long) cur->value / 1000);
                  }
               } else {
                  if (buf) {
                     snprintf(buf, len, "%.3f", (double) ((long) cur->value) / 1000.0);
                  } else {
                     ast_str_set(bufstr, len, "%.3f", (double) ((long) cur->value) / 1000.0);
                  }
               }
            } else if (ot == OT_STRING) {
               ast_debug(1, "Found entry %p, with key %d and value %p\n", cur, cur->key, cur->value);
               if (buf) {
                  ast_copy_string(buf, cur->value, len);
               } else {
                  ast_str_set(bufstr, 0, "%s", (char *) cur->value);
               }
            } else if (key == CURLOPT_PROXYTYPE) {
               const char *strval = "unknown";
               if (0) {
#if CURLVERSION_ATLEAST(7,15,2)
               } else if ((long)cur->value == CURLPROXY_SOCKS4) {
                  strval = "socks4";
#endif
#if CURLVERSION_ATLEAST(7,18,0)
               } else if ((long)cur->value == CURLPROXY_SOCKS4A) {
                  strval = "socks4a";
#endif
               } else if ((long)cur->value == CURLPROXY_SOCKS5) {
                  strval = "socks5";
#if CURLVERSION_ATLEAST(7,18,0)
               } else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) {
                  strval = "socks5hostname";
#endif
#if CURLVERSION_ATLEAST(7,10,0)
               } else if ((long)cur->value == CURLPROXY_HTTP) {
                  strval = "http";
#endif
               }
               if (buf) {
                  ast_copy_string(buf, strval, len);
               } else {
                  ast_str_set(bufstr, 0, "%s", strval);
               }
            } else if (key == CURLOPT_SPECIAL_HASHCOMPAT) {
               const char *strval = "unknown";
               if ((long) cur->value == HASHCOMPAT_LEGACY) {
                  strval = "legacy";
               } else if ((long) cur->value == HASHCOMPAT_YES) {
                  strval = "yes";
               } else if ((long) cur->value == HASHCOMPAT_NO) {
                  strval = "no";
               }
               if (buf) {
                  ast_copy_string(buf, strval, len);
               } else {
                  ast_str_set(bufstr, 0, "%s", strval);
               }
            }
            break;
         }
      }
      AST_LIST_UNLOCK(list[i]);
      if (cur) {
         break;
      }
   }

   return cur ? 0 : -1;
}
static int acf_curlopt_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 517 of file func_curl.c.

References acf_curlopt_helper().

{
   return acf_curlopt_helper(chan, cmd, data, buf, NULL, len);
}
static int acf_curlopt_read2 ( struct ast_channel chan,
const char *  cmd,
char *  data,
struct ast_str **  buf,
ssize_t  len 
) [static]

Definition at line 522 of file func_curl.c.

References acf_curlopt_helper().

{
   return acf_curlopt_helper(chan, cmd, data, NULL, buf, len);
}
static int acf_curlopt_write ( struct ast_channel chan,
const char *  cmd,
char *  name,
const char *  value 
) [static]

Definition at line 286 of file func_curl.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc(), ast_datastore_free(), ast_debug, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_true(), CURLOPT_SPECIAL_HASHCOMPAT, ast_datastore::data, free, global_curl_info, HASHCOMPAT_LEGACY, HASHCOMPAT_NO, HASHCOMPAT_YES, curl_settings::key, curl_settings::list, LOG_ERROR, OT_BOOLEAN, OT_ENUM, OT_INTEGER, OT_INTEGER_MS, OT_STRING, and parse_curlopt_key().

{
   struct ast_datastore *store;
   struct global_curl_info *list;
   struct curl_settings *cur, *new = NULL;
   CURLoption key;
   enum optiontype ot;

   if (chan) {
      if (!(store = ast_channel_datastore_find(chan, &curl_info, NULL))) {
         /* Create a new datastore */
         if (!(store = ast_datastore_alloc(&curl_info, NULL))) {
            ast_log(LOG_ERROR, "Unable to allocate new datastore.  Cannot set any CURL options\n");
            return -1;
         }

         if (!(list = ast_calloc(1, sizeof(*list)))) {
            ast_log(LOG_ERROR, "Unable to allocate list head.  Cannot set any CURL options\n");
            ast_datastore_free(store);
            return -1;
         }

         store->data = list;
         AST_LIST_HEAD_INIT(list);
         ast_channel_datastore_add(chan, store);
      } else {
         list = store->data;
      }
   } else {
      /* Populate the global structure */
      list = &global_curl_info;
   }

   if (!parse_curlopt_key(name, &key, &ot)) {
      if (ot == OT_BOOLEAN) {
         if ((new = ast_calloc(1, sizeof(*new)))) {
            new->value = (void *)((long) ast_true(value));
         }
      } else if (ot == OT_INTEGER) {
         long tmp = atol(value);
         if ((new = ast_calloc(1, sizeof(*new)))) {
            new->value = (void *)tmp;
         }
      } else if (ot == OT_INTEGER_MS) {
         long tmp = atof(value) * 1000.0;
         if ((new = ast_calloc(1, sizeof(*new)))) {
            new->value = (void *)tmp;
         }
      } else if (ot == OT_STRING) {
         if ((new = ast_calloc(1, sizeof(*new) + strlen(value) + 1))) {
            new->value = (char *)new + sizeof(*new);
            strcpy(new->value, value);
         }
      } else if (ot == OT_ENUM) {
         if (key == CURLOPT_PROXYTYPE) {
            long ptype =
#if CURLVERSION_ATLEAST(7,10,0)
               CURLPROXY_HTTP;
#else
               CURLPROXY_SOCKS5;
#endif
            if (0) {
#if CURLVERSION_ATLEAST(7,15,2)
            } else if (!strcasecmp(value, "socks4")) {
               ptype = CURLPROXY_SOCKS4;
#endif
#if CURLVERSION_ATLEAST(7,18,0)
            } else if (!strcasecmp(value, "socks4a")) {
               ptype = CURLPROXY_SOCKS4A;
#endif
#if CURLVERSION_ATLEAST(7,18,0)
            } else if (!strcasecmp(value, "socks5")) {
               ptype = CURLPROXY_SOCKS5;
#endif
#if CURLVERSION_ATLEAST(7,18,0)
            } else if (!strncasecmp(value, "socks5", 6)) {
               ptype = CURLPROXY_SOCKS5_HOSTNAME;
#endif
            }

            if ((new = ast_calloc(1, sizeof(*new)))) {
               new->value = (void *)ptype;
            }
         } else if (key == CURLOPT_SPECIAL_HASHCOMPAT) {
            if ((new = ast_calloc(1, sizeof(*new)))) {
               new->value = (void *) (long) (!strcasecmp(value, "legacy") ? HASHCOMPAT_LEGACY : ast_true(value) ? HASHCOMPAT_YES : HASHCOMPAT_NO);
            }
         } else {
            /* Highly unlikely */
            goto yuck;
         }
      }

      /* Memory allocation error */
      if (!new) {
         return -1;
      }

      new->key = key;
   } else {
yuck:
      ast_log(LOG_ERROR, "Unrecognized option: %s\n", name);
      return -1;
   }

   /* Remove any existing entry */
   AST_LIST_LOCK(list);
   AST_LIST_TRAVERSE_SAFE_BEGIN(list, cur, list) {
      if (cur->key == new->key) {
         AST_LIST_REMOVE_CURRENT(list);
         free(cur);
         break;
      }
   }
   AST_LIST_TRAVERSE_SAFE_END

   /* Insert new entry */
   ast_debug(1, "Inserting entry %p with key %d and value %p\n", new, new->key, new->value);
   AST_LIST_INSERT_TAIL(list, new, list);
   AST_LIST_UNLOCK(list);

   return 0;
}
static void curl_instance_cleanup ( void *  data) [static]

Definition at line 558 of file func_curl.c.

References ast_free.

{
   CURL **curl = data;

   curl_easy_cleanup(*curl);

   ast_free(data);
}
static int curl_instance_init ( void *  data) [static]

Definition at line 543 of file func_curl.c.

References global_useragent, and WriteMemoryCallback().

{
   CURL **curl = data;

   if (!(*curl = curl_easy_init()))
      return -1;

   curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt(*curl, CURLOPT_TIMEOUT, 180);
   curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
   curl_easy_setopt(*curl, CURLOPT_USERAGENT, global_useragent);

   return 0;
}
static void curlds_free ( void *  data) [static]

Definition at line 190 of file func_curl.c.

References AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, and free.

{
   AST_LIST_HEAD(global_curl_info, curl_settings) *list = data;
   struct curl_settings *setting;
   if (!list) {
      return;
   }
   while ((setting = AST_LIST_REMOVE_HEAD(list, list))) {
      free(setting);
   }
   AST_LIST_HEAD_DESTROY(list);
}
static int load_module ( void  ) [static]

Definition at line 775 of file func_curl.c.

References acf_curl, acf_curlopt, ast_custom_function_register, ast_load_resource(), ast_log(), ast_module_check(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and LOG_ERROR.

{
   int res;

   if (!ast_module_check("res_curl.so")) {
      if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
         ast_log(LOG_ERROR, "Cannot load res_curl, so func_curl cannot be loaded\n");
         return AST_MODULE_LOAD_DECLINE;
      }
   }

   res = ast_custom_function_register(&acf_curl);
   res |= ast_custom_function_register(&acf_curlopt);

   return res;
}
static int parse_curlopt_key ( const char *  name,
CURLoption *  key,
enum optiontype ot 
) [static]

Definition at line 217 of file func_curl.c.

References CURLOPT_SPECIAL_HASHCOMPAT, OT_BOOLEAN, OT_ENUM, OT_INTEGER, OT_INTEGER_MS, and OT_STRING.

Referenced by acf_curlopt_helper(), and acf_curlopt_write().

{
   if (!strcasecmp(name, "header")) {
      *key = CURLOPT_HEADER;
      *ot = OT_BOOLEAN;
   } else if (!strcasecmp(name, "proxy")) {
      *key = CURLOPT_PROXY;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "proxyport")) {
      *key = CURLOPT_PROXYPORT;
      *ot = OT_INTEGER;
   } else if (!strcasecmp(name, "proxytype")) {
      *key = CURLOPT_PROXYTYPE;
      *ot = OT_ENUM;
   } else if (!strcasecmp(name, "dnstimeout")) {
      *key = CURLOPT_DNS_CACHE_TIMEOUT;
      *ot = OT_INTEGER;
   } else if (!strcasecmp(name, "userpwd")) {
      *key = CURLOPT_USERPWD;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "proxyuserpwd")) {
      *key = CURLOPT_PROXYUSERPWD;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "maxredirs")) {
      *key = CURLOPT_MAXREDIRS;
      *ot = OT_INTEGER;
   } else if (!strcasecmp(name, "referer")) {
      *key = CURLOPT_REFERER;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "useragent")) {
      *key = CURLOPT_USERAGENT;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "cookie")) {
      *key = CURLOPT_COOKIE;
      *ot = OT_STRING;
   } else if (!strcasecmp(name, "ftptimeout")) {
      *key = CURLOPT_FTP_RESPONSE_TIMEOUT;
      *ot = OT_INTEGER;
   } else if (!strcasecmp(name, "httptimeout")) {
#if CURLVERSION_ATLEAST(7,16,2)
      *key = CURLOPT_TIMEOUT_MS;
      *ot = OT_INTEGER_MS;
#else
      *key = CURLOPT_TIMEOUT;
      *ot = OT_INTEGER;
#endif
   } else if (!strcasecmp(name, "conntimeout")) {
#if CURLVERSION_ATLEAST(7,16,2)
      *key = CURLOPT_CONNECTTIMEOUT_MS;
      *ot = OT_INTEGER_MS;
#else
      *key = CURLOPT_CONNECTTIMEOUT;
      *ot = OT_INTEGER;
#endif
   } else if (!strcasecmp(name, "ftptext")) {
      *key = CURLOPT_TRANSFERTEXT;
      *ot = OT_BOOLEAN;
   } else if (!strcasecmp(name, "ssl_verifypeer")) {
      *key = CURLOPT_SSL_VERIFYPEER;
      *ot = OT_BOOLEAN;
   } else if (!strcasecmp(name, "hashcompat")) {
      *key = CURLOPT_SPECIAL_HASHCOMPAT;
      *ot = OT_ENUM;
   } else {
      return -1;
   }
   return 0;
}
static int unload_module ( void  ) [static]

Definition at line 765 of file func_curl.c.

References acf_curl, acf_curlopt, and ast_custom_function_unregister().

static size_t WriteMemoryCallback ( void *  ptr,
size_t  size,
size_t  nmemb,
void *  data 
) [static]

Definition at line 527 of file func_curl.c.

References ast_debug, ast_str_append_substr(), ast_str_size(), and ast_str_strlen().

Referenced by curl_instance_init().

{
   register int realsize = size * nmemb;
   struct ast_str **pstr = (struct ast_str **)data;

   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));

   ast_str_append_substr(pstr, 0, ptr, realsize);

   ast_debug(3, "Now, len=%zu, used=%zu\n", ast_str_size(*pstr), ast_str_strlen(*pstr));

   return realsize;
}

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Load external URL" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_REALTIME_DEPEND2, } [static]

Definition at line 796 of file func_curl.c.

struct ast_custom_function acf_curl [static]

Definition at line 725 of file func_curl.c.

Referenced by load_module(), and unload_module().

Definition at line 736 of file func_curl.c.

Referenced by load_module(), and unload_module().

Definition at line 796 of file func_curl.c.

struct ast_datastore_info curl_info [static]
Initial value:
 {
   .type = "CURL",
   .destroy = curlds_free,
}

Definition at line 177 of file func_curl.c.

struct ast_threadstorage curl_instance = { .once = PTHREAD_ONCE_INIT , .key_init = __init_curl_instance , .custom_init = curl_instance_init , } [static]

Definition at line 567 of file func_curl.c.

Referenced by acf_curl_helper().

const char* const global_useragent = "asterisk-libcurl-agent/1.0" [static]

Definition at line 541 of file func_curl.c.

Referenced by curl_instance_init().

struct ast_threadstorage thread_escapebuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_thread_escapebuf , .custom_init = NULL , } [static]

Definition at line 568 of file func_curl.c.

Referenced by acf_curl_helper().