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