Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:47 2009

## Asterisk developer's documentation

# app_curl.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C)  2004 - 2005, 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  * \brief Curl - App to load a URL
    00022  *
    00023  * \ingroup applications
    00024  */
    00025
    00026 #include <stdio.h>
    00027 #include <stdlib.h>
    00028 #include <string.h>
    00029 #include <curl/curl.h>
    00030
    00031 #include "asterisk.h"
    00032
    00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 46662 $")
    00034
    00035 #include "asterisk/lock.h"
    00036 #include "asterisk/file.h"
    00037 #include "asterisk/logger.h"
    00038 #include "asterisk/channel.h"
    00039 #include "asterisk/pbx.h"
    00040 #include "asterisk/cli.h"
    00041 #include "asterisk/options.h"
    00042 #include "asterisk/module.h"
    00043
    00044 static char *tdesc = "Load external URL";
    00045
    00046 static char *app = "Curl";
    00047
    00048 static char *synopsis = "Load an external URL";
    00049
    00050 static char *descrip =
    00051 "  Curl(URL[|postdata]): This application will request the specified URL.\n"
    00052 "It is mainly used for signalling external applications of an event.\n"
    00053 "Parameters:\n"
    00054 "  URL      - This is the external URL to request.\n"
    00055 "  postdata - This information will be treated as POST data.\n"
    00056 "This application will set the following variable:\n"
    00057 "  CURL - This variable will contain the resulting page.\n"
    00058 "This application has been deprecated in favor of the CURL function.\n";
    00059
    00060 STANDARD_LOCAL_USER;
    00061
    00062 LOCAL_USER_DECL;
    00063
    00064 struct MemoryStruct {
    00065    char *memory;
    00066    size_t size;
    00067 };
    00068
    00069 static void *myrealloc(void *ptr, size_t size)
    00070 {
    00071    /* There might be a realloc() out there that doesn't like reallocing
    00072       NULL pointers, so we take care of it here */
    00073    if (ptr)
    00074       return realloc(ptr, size);
    00075    else
    00076       return malloc(size);
    00077 }
    00078
    00079 static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
    00080 {
    00081    register int realsize = size * nmemb;
    00082    struct MemoryStruct *mem = (struct MemoryStruct *)data;
    00083
    00084    mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
    00085    if (mem->memory) {
    00086       memcpy(&(mem->memory[mem->size]), ptr, realsize);
    00087       mem->size += realsize;
    00088       mem->memory[mem->size] = 0;
    00089    }
    00090    return realsize;
    00091 }
    00092
    00093 static int curl_internal(struct MemoryStruct *chunk, char *url, char *post)
    00094 {
    00095    CURL *curl;
    00096
    00097    curl = curl_easy_init();
    00098
    00099    if (!curl) {
    00100       return -1;
    00101    }
    00102
    00103    curl_easy_setopt(curl, CURLOPT_URL, url);
    00104    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    00105    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
    00106    curl_easy_setopt(curl, CURLOPT_USERAGENT, "asterisk-libcurl-agent/1.0");
    00107
    00108    if (post) {
    00109       curl_easy_setopt(curl, CURLOPT_POST, 1);
    00110       curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
    00111    }
    00112
    00113    curl_easy_perform(curl);
    00114    curl_easy_cleanup(curl);
    00115    return 0;
    00116 }
    00117
    00118 static int curl_exec(struct ast_channel *chan, void *data)
    00119 {
    00120    int res = 0;
    00121    struct localuser *u;
    00122    char *info, *post_data=NULL, *url;
    00123    struct MemoryStruct chunk = { NULL, 0 };
    00124    static int dep_warning = 0;
    00125
    00126    if (!dep_warning) {
    00127       ast_log(LOG_WARNING, "The application Curl is deprecated.  Please use the CURL() function instead.\n");
    00128       dep_warning = 1;
    00129    }
    00130
    00131    if (ast_strlen_zero(data)) {
    00132       ast_log(LOG_WARNING, "Curl requires an argument (URL)\n");
    00133       return -1;
    00134    }
    00135
    00136    LOCAL_USER_ADD(u);
    00137
    00138    if ((info = ast_strdupa(data))) {
    00139       url = strsep(&info, "|");
    00140       post_data = info;
    00141    } else {
    00142       ast_log(LOG_ERROR, "Out of memory\n");
    00143       LOCAL_USER_REMOVE(u);
    00144       return -1;
    00145    }
    00146
    00147    if (! curl_internal(&chunk, url, post_data)) {
    00148       if (chunk.memory) {
    00149          chunk.memory[chunk.size] = '\0';
    00150          if (chunk.memory[chunk.size - 1] == 10)
    00151             chunk.memory[chunk.size - 1] = '\0';
    00152
    00153          pbx_builtin_setvar_helper(chan, "CURL", chunk.memory);
    00154
    00155          free(chunk.memory);
    00156       }
    00157    } else {
    00158       ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
    00159       res = -1;
    00160    }
    00161
    00162    LOCAL_USER_REMOVE(u);
    00163    return res;
    00164 }
    00165
    00166 static char *acf_curl_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
    00167 {
    00168    struct localuser *u;
    00169    char *info, *post_data=NULL, *url;
    00170    struct MemoryStruct chunk = { NULL, 0 };
    00171
    00172    *buf = '\0';
    00173
    00174    if (ast_strlen_zero(data)) {
    00175       ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
    00176       return buf;
    00177    }
    00178
    00179    LOCAL_USER_ACF_ADD(u);
    00180
    00181    info = ast_strdupa(data);
    00182    if (!info) {
    00183       ast_log(LOG_ERROR, "Out of memory\n");
    00184       LOCAL_USER_REMOVE(u);
    00185       return buf;
    00186    }
    00187
    00188    url = strsep(&info, "|");
    00189    post_data = info;
    00190
    00191    if (! curl_internal(&chunk, url, post_data)) {
    00192       if (chunk.memory) {
    00193          chunk.memory[chunk.size] = '\0';
    00194          if (chunk.memory[chunk.size - 1] == 10)
    00195             chunk.memory[chunk.size - 1] = '\0';
    00196
    00197          ast_copy_string(buf, chunk.memory, len);
    00198          free(chunk.memory);
    00199       }
    00200    } else {
    00201       ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
    00202    }
    00203
    00204    LOCAL_USER_REMOVE(u);
    00205    return buf;
    00206 }
    00207
    00208 struct ast_custom_function acf_curl = {
    00209    .name = "CURL",
    00210    .synopsis = "Retrieves the contents of a URL",
    00211    .syntax = "CURL(url[|post-data])",
    00212    .desc =
    00213    "  url       - URL to retrieve\n"
    00214    "  post-data - Optional data to send as a POST (GET is default action)\n",
    00215    .read = acf_curl_exec,
    00216 };
    00217
    00218 int unload_module(void)
    00219 {
    00220    int res;
    00221
    00222    res = ast_custom_function_unregister(&acf_curl);
    00223    res |= ast_unregister_application(app);
    00224
    00225    STANDARD_HANGUP_LOCALUSERS;
    00226    curl_global_cleanup();
    00227
    00228    return res;
    00229 }
    00230
    00231 int load_module(void)
    00232 {
    00233    int res;
    00234
    00235    curl_global_init(CURL_GLOBAL_ALL);
    00236    res = ast_custom_function_register(&acf_curl);
    00237    res |= ast_register_application(app, curl_exec, synopsis, descrip);
    00238
    00239    return res;
    00240 }
    00241
    00242 char *description(void)
    00243 {
    00244    return tdesc;
    00245 }
    00246
    00247 int usecount(void)
    00248 {
    00249    int res;
    00250    STANDARD_USECOUNT(res);
    00251    return res;
    00252 }
    00253
    00254 char *key()
    00255 {
    00256    return ASTERISK_GPL_KEY;
    00257 }