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
00034
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