@ -53,6 +53,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
# define CURLVERSION_ATLEAST(a,b,c) \
# 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 ) ) ) )
( ( LIBCURL_VERSION_MAJOR > ( a ) ) | | ( ( LIBCURL_VERSION_MAJOR = = ( a ) ) & & ( LIBCURL_VERSION_MINOR > ( b ) ) ) | | ( ( LIBCURL_VERSION_MAJOR = = ( a ) ) & & ( LIBCURL_VERSION_MINOR = = ( b ) ) & & ( LIBCURL_VERSION_PATCH > = ( c ) ) ) )
# define CURLOPT_SPECIAL_HASHCOMPAT -500
static void curlds_free ( void * data ) ;
static void curlds_free ( void * data ) ;
static struct ast_datastore_info curl_info = {
static struct ast_datastore_info curl_info = {
@ -146,6 +148,9 @@ static int parse_curlopt_key(const char *name, CURLoption *key, enum optiontype
} else if ( ! strcasecmp ( name , " ftptext " ) ) {
} else if ( ! strcasecmp ( name , " ftptext " ) ) {
* key = CURLOPT_TRANSFERTEXT ;
* key = CURLOPT_TRANSFERTEXT ;
* ot = OT_BOOLEAN ;
* ot = OT_BOOLEAN ;
} else if ( ! strcasecmp ( name , " hashcompat " ) ) {
* key = CURLOPT_SPECIAL_HASHCOMPAT ;
* ot = OT_BOOLEAN ;
} else {
} else {
return - 1 ;
return - 1 ;
}
}
@ -351,7 +356,7 @@ static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *da
ast_debug ( 3 , " Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu \n " , data , * pstr , realsize , ( * pstr ) - > len , ( * pstr ) - > used ) ;
ast_debug ( 3 , " Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu \n " , data , * pstr , realsize , ( * pstr ) - > len , ( * pstr ) - > used ) ;
if ( ast_str_make_space ( pstr , ( ( ( * pstr ) - > used + realsize + 1 ) / 512 + 1 ) * 512 + 47 0) = = 0 ) {
if ( ast_str_make_space ( pstr , ( ( ( * pstr ) - > used + realsize + 1 ) / 512 + 1 ) * 512 + 23 0) = = 0 ) {
memcpy ( & ( ( * pstr ) - > str [ ( * pstr ) - > used ] ) , ptr , realsize ) ;
memcpy ( & ( ( * pstr ) - > str [ ( * pstr ) - > used ] ) , ptr , realsize ) ;
( * pstr ) - > used + = realsize ;
( * pstr ) - > used + = realsize ;
}
}
@ -399,6 +404,7 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
CURL * * curl ;
CURL * * curl ;
struct curl_settings * cur ;
struct curl_settings * cur ;
struct ast_datastore * store = NULL ;
struct ast_datastore * store = NULL ;
int hashcompat = 0 ;
AST_LIST_HEAD ( global_curl_info , curl_settings ) * list = NULL ;
AST_LIST_HEAD ( global_curl_info , curl_settings ) * list = NULL ;
* buf = ' \0 ' ;
* buf = ' \0 ' ;
@ -422,16 +428,24 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
AST_LIST_LOCK ( & global_curl_info ) ;
AST_LIST_LOCK ( & global_curl_info ) ;
AST_LIST_TRAVERSE ( & global_curl_info , cur , list ) {
AST_LIST_TRAVERSE ( & global_curl_info , cur , list ) {
if ( cur - > key = = CURLOPT_SPECIAL_HASHCOMPAT ) {
hashcompat = ( cur - > value ! = NULL ) ? 1 : 0 ;
} else {
curl_easy_setopt ( * curl , cur - > key , cur - > value ) ;
curl_easy_setopt ( * curl , cur - > key , cur - > value ) ;
}
}
}
if ( chan & & ( store = ast_channel_datastore_find ( chan , & curl_info , NULL ) ) ) {
if ( chan & & ( store = ast_channel_datastore_find ( chan , & curl_info , NULL ) ) ) {
list = store - > data ;
list = store - > data ;
AST_LIST_LOCK ( list ) ;
AST_LIST_LOCK ( list ) ;
AST_LIST_TRAVERSE ( list , cur , list ) {
AST_LIST_TRAVERSE ( list , cur , list ) {
if ( cur - > key = = CURLOPT_SPECIAL_HASHCOMPAT ) {
hashcompat = ( cur - > value ! = NULL ) ? 1 : 0 ;
} else {
curl_easy_setopt ( * curl , cur - > key , cur - > value ) ;
curl_easy_setopt ( * curl , cur - > key , cur - > value ) ;
}
}
}
}
}
curl_easy_setopt ( * curl , CURLOPT_URL , args . url ) ;
curl_easy_setopt ( * curl , CURLOPT_URL , args . url ) ;
curl_easy_setopt ( * curl , CURLOPT_FILE , ( void * ) & str ) ;
curl_easy_setopt ( * curl , CURLOPT_FILE , ( void * ) & str ) ;
@ -458,8 +472,29 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info,
str - > str [ str - > used - 1 ] = ' \0 ' ;
str - > str [ str - > used - 1 ] = ' \0 ' ;
}
}
ast_log ( LOG_NOTICE , " str='%s' \n " , str - > str ) ;
if ( hashcompat ) {
char * remainder = str - > str ;
char * piece ;
struct ast_str * fields = ast_str_create ( str - > used / 2 ) ;
struct ast_str * values = ast_str_create ( str - > used / 2 ) ;
int rowcount = 0 ;
while ( ( piece = strsep ( & remainder , " & " ) ) ) {
char * name = strsep ( & piece , " = " ) ;
ast_uri_decode ( piece ) ;
ast_uri_decode ( name ) ;
ast_str_append ( & fields , 0 , " %s%s " , rowcount ? " , " : " " , name ) ;
ast_str_append ( & values , 0 , " %s%s " , rowcount ? " , " : " " , piece ) ;
rowcount + + ;
}
pbx_builtin_setvar_helper ( chan , " ~ODBCFIELDS~ " , fields - > str ) ;
ast_copy_string ( buf , values - > str , len ) ;
ast_free ( fields ) ;
ast_free ( values ) ;
} else {
ast_copy_string ( buf , str - > str , len ) ;
ast_copy_string ( buf , str - > str , len ) ;
}
}
}
ast_free ( str ) ;
ast_free ( str ) ;
if ( chan )
if ( chan )
@ -498,6 +533,7 @@ struct ast_custom_function acf_curlopt = {
" referer - Referer URL to use for the request \n "
" referer - Referer URL to use for the request \n "
" useragent - UserAgent string to use \n "
" useragent - UserAgent string to use \n "
" userpwd - A <user>:<pass> to use for authentication \n "
" userpwd - A <user>:<pass> to use for authentication \n "
" hashcompat - Result data will be compatible for use with HASH() \n "
" " ,
" " ,
. read = acf_curlopt_read ,
. read = acf_curlopt_read ,
. write = acf_curlopt_write ,
. write = acf_curlopt_write ,