diff --git a/funcs/func_curl.c b/funcs/func_curl.c
index d6c440257e..bc04780c35 100644
--- a/funcs/func_curl.c
+++ b/funcs/func_curl.c
@@ -50,6 +50,122 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
+/*** DOCUMENTATION
+
+
+ Retrieve content from a remote web or ftp server
+
+
+
+
+ If specified, an HTTP POST will be
+ performed with the content of
+ post-data, instead of an
+ HTTP GET (default).
+
+
+
+
+ [CURLOPT]
+
+
+
+
+ Sets various options for future invocations of CURL.
+
+
+
+
+
+ A cookie to send with the request. Multiple
+ cookies are supported.
+
+
+ Number of seconds to wait for a connection to succeed
+
+
+ Number of seconds to wait for DNS to be resolved
+
+
+ For FTP URIs, force a text transfer (boolean)
+
+
+ For FTP URIs, number of seconds to wait for a
+ server response
+
+
+ Include header information in the result
+ (boolean)
+
+
+ For HTTP(S) URIs, number of seconds to wait for a
+ server response
+
+
+ Maximum number of redirects to follow
+
+
+ Hostname or IP address to use as a proxy server
+
+
+ Type of proxy
+
+
+
+
+
+
+
+ Port number of the proxy
+
+
+ A username:password
+ combination to use for authenticating requests through a
+ proxy
+
+
+ Referer URL to use for the request
+
+
+ UserAgent string to use for the request
+
+
+ A username:password
+ to use for authentication when the server response to
+ an initial request indicates a 401 status code.
+
+
+ Whether to verify the server certificate against
+ a list of known root certificate authorities (boolean).
+
+
+ Assuming the responses will be in key1=value1&key2=value2
+ format, reformat the response such that it can be used
+ by the HASH function.
+
+
+
+
+ Also translate + to the
+ space character, in violation of current RFC
+ standards.
+
+
+
+
+
+
+
+ Options may be set globally or per channel. Per-channel
+ settings will override global settings.
+
+
+ [CURL]
+ [HASH]
+
+
+ ***/
+
#define CURLVERSION_ATLEAST(a,b,c) \
((LIBCURL_VERSION_MAJOR > (a)) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR > (b))) || ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR == (b)) && (LIBCURL_VERSION_PATCH >= (c))))
@@ -91,6 +207,12 @@ enum optiontype {
OT_ENUM,
};
+enum hashcompat {
+ HASHCOMPAT_NO = 0,
+ HASHCOMPAT_YES,
+ HASHCOMPAT_LEGACY,
+};
+
static int parse_curlopt_key(const char *name, CURLoption *key, enum optiontype *ot)
{
if (!strcasecmp(name, "header")) {
@@ -153,7 +275,7 @@ static int parse_curlopt_key(const char *name, CURLoption *key, enum optiontype
*ot = OT_BOOLEAN;
} else if (!strcasecmp(name, "hashcompat")) {
*key = CURLOPT_SPECIAL_HASHCOMPAT;
- *ot = OT_BOOLEAN;
+ *ot = OT_ENUM;
} else {
return -1;
}
@@ -242,6 +364,10 @@ static int acf_curlopt_write(struct ast_channel *chan, const char *cmd, char *na
if ((new = ast_calloc(1, sizeof(*new)))) {
new->value = (void *)ptype;
}
+ } else if (key == CURLOPT_SPECIAL_HASHCOMPAT) {
+ if ((new = ast_calloc(1, sizeof(*new)))) {
+ new->value = (void *) (long) (!strcasecmp(value, "legacy") ? HASHCOMPAT_LEGACY : ast_true(value) ? HASHCOMPAT_YES : HASHCOMPAT_NO);
+ }
} else {
/* Highly unlikely */
goto yuck;
@@ -333,51 +459,45 @@ static int acf_curlopt_helper(struct ast_channel *chan, const char *cmd, char *d
ast_str_set(bufstr, 0, "%s", (char *) cur->value);
}
} else if (key == CURLOPT_PROXYTYPE) {
+ const char *strval = "unknown";
if (0) {
#if CURLVERSION_ATLEAST(7,15,2)
} else if ((long)cur->value == CURLPROXY_SOCKS4) {
- if (buf) {
- ast_copy_string(buf, "socks4", len);
- } else {
- ast_str_set(bufstr, 0, "socks4");
- }
+ strval = "socks4";
#endif
#if CURLVERSION_ATLEAST(7,18,0)
} else if ((long)cur->value == CURLPROXY_SOCKS4A) {
- if (buf) {
- ast_copy_string(buf, "socks4a", len);
- } else {
- ast_str_set(bufstr, 0, "socks4a");
- }
+ strval = "socks4a";
#endif
} else if ((long)cur->value == CURLPROXY_SOCKS5) {
- if (buf) {
- ast_copy_string(buf, "socks5", len);
- } else {
- ast_str_set(bufstr, 0, "socks5");
- }
+ strval = "socks5";
#if CURLVERSION_ATLEAST(7,18,0)
} else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) {
- if (buf) {
- ast_copy_string(buf, "socks5hostname", len);
- } else {
- ast_str_set(bufstr, 0, "socks5hostname");
- }
+ strval = "socks5hostname";
#endif
#if CURLVERSION_ATLEAST(7,10,0)
} else if ((long)cur->value == CURLPROXY_HTTP) {
- if (buf) {
- ast_copy_string(buf, "http", len);
- } else {
- ast_str_set(bufstr, 0, "http");
- }
+ strval = "http";
#endif
+ }
+ if (buf) {
+ ast_copy_string(buf, strval, len);
} else {
- if (buf) {
- ast_copy_string(buf, "unknown", len);
- } else {
- ast_str_set(bufstr, 0, "unknown");
- }
+ ast_str_set(bufstr, 0, "%s", strval);
+ }
+ } else if (key == CURLOPT_SPECIAL_HASHCOMPAT) {
+ const char *strval = "unknown";
+ if ((long) cur->value == HASHCOMPAT_LEGACY) {
+ strval = "legacy";
+ } else if ((long) cur->value == HASHCOMPAT_YES) {
+ strval = "yes";
+ } else if ((long) cur->value == HASHCOMPAT_NO) {
+ strval = "no";
+ }
+ if (buf) {
+ ast_copy_string(buf, strval, len);
+ } else {
+ ast_str_set(bufstr, 0, "%s", strval);
}
}
break;
@@ -482,7 +602,7 @@ static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info
AST_LIST_LOCK(&global_curl_info);
AST_LIST_TRAVERSE(&global_curl_info, cur, list) {
if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
- hashcompat = (cur->value != NULL) ? 1 : 0;
+ hashcompat = (long) cur->value;
} else {
curl_easy_setopt(*curl, cur->key, cur->value);
}
@@ -493,7 +613,7 @@ static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info
AST_LIST_LOCK(list);
AST_LIST_TRAVERSE(list, cur, list) {
if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) {
- hashcompat = (cur->value != NULL) ? 1 : 0;
+ hashcompat = (long) cur->value;
} else {
curl_easy_setopt(*curl, cur->key, cur->value);
}
@@ -608,6 +728,7 @@ static struct ast_custom_function acf_curlopt = {
" userpwd - A : to use for authentication\n"
" ssl_verifypeer - Whether to verify the peer certificate (boolean)\n"
" hashcompat - Result data will be compatible for use with HASH()\n"
+" - if value is \"legacy\", will translate '+' to ' '\n"
"",
.read = acf_curlopt_read,
.read2 = acf_curlopt_read2,