Fri Jun 19 12:09:45 2009

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: 146838 $")
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 static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
00054 {
00055    register int realsize = size * nmemb;
00056    struct ast_str **str = (struct ast_str **)data;
00057 
00058    if (ast_str_make_space(str, (*str)->used + realsize + 1) == 0) {
00059       memcpy(&(*str)->str[(*str)->used], ptr, realsize);
00060       (*str)->used += realsize;
00061    }
00062 
00063    return realsize;
00064 }
00065 
00066 static const char *global_useragent = "asterisk-libcurl-agent/1.0";
00067 
00068 static int curl_instance_init(void *data)
00069 {
00070    CURL **curl = data;
00071 
00072    if (!(*curl = curl_easy_init()))
00073       return -1;
00074 
00075    curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1);
00076    curl_easy_setopt(*curl, CURLOPT_TIMEOUT, 180);
00077    curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
00078    curl_easy_setopt(*curl, CURLOPT_USERAGENT, global_useragent);
00079 
00080    return 0;
00081 }
00082 
00083 static void curl_instance_cleanup(void *data)
00084 {
00085    CURL **curl = data;
00086 
00087    curl_easy_cleanup(*curl);
00088 
00089    ast_free(data);
00090 }
00091 
00092 AST_THREADSTORAGE_CUSTOM(curl_instance, curl_instance_init, curl_instance_cleanup);
00093 
00094 static int curl_internal(struct ast_str **chunk, char *url, char *post)
00095 {
00096    CURL **curl;
00097 
00098    if (!(curl = ast_threadstorage_get(&curl_instance, sizeof(*curl))))
00099       return -1;
00100 
00101    curl_easy_setopt(*curl, CURLOPT_URL, url);
00102    curl_easy_setopt(*curl, CURLOPT_WRITEDATA, (void *) chunk);
00103 
00104    if (post) {
00105       curl_easy_setopt(*curl, CURLOPT_POST, 1);
00106       curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, post);
00107    }
00108 
00109    curl_easy_perform(*curl);
00110 
00111    if (post)
00112       curl_easy_setopt(*curl, CURLOPT_POST, 0);
00113 
00114    return 0;
00115 }
00116 
00117 static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
00118 {
00119    struct ast_str *str = ast_str_create(16);
00120    int ret = -1;
00121    AST_DECLARE_APP_ARGS(args,
00122       AST_APP_ARG(url);
00123       AST_APP_ARG(postdata);
00124    );
00125 
00126    *buf = '\0';
00127    
00128    if (ast_strlen_zero(info)) {
00129       ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
00130       ast_free(str);
00131       return -1;
00132    }
00133 
00134    AST_STANDARD_APP_ARGS(args, info);  
00135 
00136    if (chan)
00137       ast_autoservice_start(chan);
00138 
00139    if (!curl_internal(&str, args.url, args.postdata)) {
00140       if (str->used) {
00141          str->str[str->used] = '\0';
00142          if (str->str[str->used - 1] == '\n') {
00143             str->str[str->used - 1] = '\0';
00144          }
00145 
00146          ast_copy_string(buf, str->str, len);
00147       }
00148       ret = 0;
00149    } else {
00150       ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
00151    }
00152    ast_free(str);
00153 
00154    if (chan)
00155       ast_autoservice_stop(chan);
00156    
00157    return ret;
00158 }
00159 
00160 struct ast_custom_function acf_curl = {
00161    .name = "CURL",
00162    .synopsis = "Retrieves the contents of a URL",
00163    .syntax = "CURL(url[,post-data])",
00164    .desc =
00165    "  url       - URL to retrieve\n"
00166    "  post-data - Optional data to send as a POST (GET is default action)\n",
00167    .read = acf_curl_exec,
00168 };
00169 
00170 static int unload_module(void)
00171 {
00172    int res;
00173 
00174    res = ast_custom_function_unregister(&acf_curl);
00175 
00176    return res;
00177 }
00178 
00179 static int load_module(void)
00180 {
00181    int res;
00182 
00183    if (!ast_module_check("res_curl.so")) {
00184       if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00185          ast_log(LOG_ERROR, "Cannot load res_curl, so func_curl cannot be loaded\n");
00186          return AST_MODULE_LOAD_DECLINE;
00187       }
00188    }
00189 
00190    res = ast_custom_function_register(&acf_curl);
00191 
00192    return res;
00193 }
00194 
00195 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Load external URL");
00196 

Generated on Fri Jun 19 12:09:45 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7