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 #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: 7221 $")
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
00072
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_global_init(CURL_GLOBAL_ALL);
00098 curl = curl_easy_init();
00099
00100 if (!curl) {
00101 return -1;
00102 }
00103
00104 curl_easy_setopt(curl, CURLOPT_URL, url);
00105 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
00106 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
00107 curl_easy_setopt(curl, CURLOPT_USERAGENT, "asterisk-libcurl-agent/1.0");
00108
00109 if (post) {
00110 curl_easy_setopt(curl, CURLOPT_POST, 1);
00111 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
00112 }
00113
00114 curl_easy_perform(curl);
00115 curl_easy_cleanup(curl);
00116 return 0;
00117 }
00118
00119 static int curl_exec(struct ast_channel *chan, void *data)
00120 {
00121 int res = 0;
00122 struct localuser *u;
00123 char *info, *post_data=NULL, *url;
00124 struct MemoryStruct chunk = { NULL, 0 };
00125 static int dep_warning = 0;
00126
00127 if (!dep_warning) {
00128 ast_log(LOG_WARNING, "The application Curl is deprecated. Please use the CURL() function instead.\n");
00129 dep_warning = 1;
00130 }
00131
00132 if (ast_strlen_zero(data)) {
00133 ast_log(LOG_WARNING, "Curl requires an argument (URL)\n");
00134 return -1;
00135 }
00136
00137 LOCAL_USER_ADD(u);
00138
00139 if ((info = ast_strdupa(data))) {
00140 url = strsep(&info, "|");
00141 post_data = info;
00142 } else {
00143 ast_log(LOG_ERROR, "Out of memory\n");
00144 LOCAL_USER_REMOVE(u);
00145 return -1;
00146 }
00147
00148 if (! curl_internal(&chunk, url, post_data)) {
00149 if (chunk.memory) {
00150 chunk.memory[chunk.size] = '\0';
00151 if (chunk.memory[chunk.size - 1] == 10)
00152 chunk.memory[chunk.size - 1] = '\0';
00153
00154 pbx_builtin_setvar_helper(chan, "CURL", chunk.memory);
00155
00156 free(chunk.memory);
00157 }
00158 } else {
00159 ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
00160 res = -1;
00161 }
00162
00163 LOCAL_USER_REMOVE(u);
00164 return res;
00165 }
00166
00167 static char *acf_curl_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
00168 {
00169 struct localuser *u;
00170 char *info, *post_data=NULL, *url;
00171 struct MemoryStruct chunk = { NULL, 0 };
00172
00173 *buf = '\0';
00174
00175 if (ast_strlen_zero(data)) {
00176 ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
00177 return buf;
00178 }
00179
00180 LOCAL_USER_ACF_ADD(u);
00181
00182 info = ast_strdupa(data);
00183 if (!info) {
00184 ast_log(LOG_ERROR, "Out of memory\n");
00185 LOCAL_USER_REMOVE(u);
00186 return buf;
00187 }
00188
00189 url = strsep(&info, "|");
00190 post_data = info;
00191
00192 if (! curl_internal(&chunk, url, post_data)) {
00193 if (chunk.memory) {
00194 chunk.memory[chunk.size] = '\0';
00195 if (chunk.memory[chunk.size - 1] == 10)
00196 chunk.memory[chunk.size - 1] = '\0';
00197
00198 ast_copy_string(buf, chunk.memory, len);
00199 free(chunk.memory);
00200 }
00201 } else {
00202 ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
00203 }
00204
00205 LOCAL_USER_REMOVE(u);
00206 return buf;
00207 }
00208
00209 struct ast_custom_function acf_curl = {
00210 .name = "CURL",
00211 .synopsis = "Retrieves the contents of a URL",
00212 .syntax = "CURL(url[|post-data])",
00213 .desc =
00214 " url - URL to retrieve\n"
00215 " post-data - Optional data to send as a POST (GET is default action)\n",
00216 .read = acf_curl_exec,
00217 };
00218
00219 int unload_module(void)
00220 {
00221 int res;
00222
00223 res = ast_custom_function_unregister(&acf_curl);
00224 res |= ast_unregister_application(app);
00225
00226 STANDARD_HANGUP_LOCALUSERS;
00227
00228 return res;
00229 }
00230
00231 int load_module(void)
00232 {
00233 int res;
00234
00235 res = ast_custom_function_register(&acf_curl);
00236 res |= ast_register_application(app, curl_exec, synopsis, descrip);
00237
00238 return res;
00239 }
00240
00241 char *description(void)
00242 {
00243 return tdesc;
00244 }
00245
00246 int usecount(void)
00247 {
00248 int res;
00249 STANDARD_USECOUNT(res);
00250 return res;
00251 }
00252
00253 char *key()
00254 {
00255 return ASTERISK_GPL_KEY;
00256 }