| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  |  * Copyright (C)  2004 - 2006, Tilghman Lesher | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  |  * Tilghman Lesher <curl-20050919@the-tilghman.com> | 
					
						
							| 
									
										
										
										
											2005-01-05 06:38:39 +00:00
										 |  |  |  * and Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option) | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * app_curl.c is distributed with no restrictions on usage or | 
					
						
							|  |  |  |  * redistribution. | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2006-02-23 22:27:49 +00:00
										 |  |  |  * \brief Curl - Load a URL | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \author Tilghman Lesher <curl-20050919@the-tilghman.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)  | 
					
						
							| 
									
										
										
										
											2007-02-24 19:27:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \extref Depends on the CURL library  - http://curl.haxx.se/
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2006-02-23 22:27:49 +00:00
										 |  |  |  * \ingroup functions | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  |   | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>curl</depend> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 22:39:32 +00:00
										 |  |  | #include <curl/curl.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-30 19:38:54 +00:00
										 |  |  | #include "asterisk/app.h"
 | 
					
						
							| 
									
										
										
										
											2006-01-11 22:41:34 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | #include "asterisk/threadstorage.h"
 | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #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)))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | #define CURLOPT_SPECIAL_HASHCOMPAT -500
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | static void curlds_free(void *data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_datastore_info curl_info = { | 
					
						
							|  |  |  | 	.type = "CURL", | 
					
						
							|  |  |  | 	.destroy = curlds_free, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct curl_settings { | 
					
						
							|  |  |  | 	AST_LIST_ENTRY(curl_settings) list; | 
					
						
							|  |  |  | 	CURLoption key; | 
					
						
							|  |  |  | 	void *value; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AST_LIST_HEAD_STATIC(global_curl_info, curl_settings); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void curlds_free(void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	AST_LIST_HEAD(global_curl_info, curl_settings) *list = data; | 
					
						
							| 
									
										
										
										
											2008-10-08 12:15:06 +00:00
										 |  |  | 	struct curl_settings *setting; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	if (!list) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-10-08 12:15:06 +00:00
										 |  |  | 	while ((setting = AST_LIST_REMOVE_HEAD(list, list))) { | 
					
						
							|  |  |  | 		free(setting); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	AST_LIST_HEAD_DESTROY(list); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum optiontype { | 
					
						
							|  |  |  | 	OT_BOOLEAN, | 
					
						
							|  |  |  | 	OT_INTEGER, | 
					
						
							|  |  |  | 	OT_INTEGER_MS, | 
					
						
							|  |  |  | 	OT_STRING, | 
					
						
							|  |  |  | 	OT_ENUM, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int parse_curlopt_key(const char *name, CURLoption *key, enum optiontype *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!strcasecmp(name, "header")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_HEADER; | 
					
						
							|  |  |  | 		*ot = OT_BOOLEAN; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "proxy")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_PROXY; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "proxyport")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_PROXYPORT; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "proxytype")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_PROXYTYPE; | 
					
						
							|  |  |  | 		*ot = OT_ENUM; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "dnstimeout")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_DNS_CACHE_TIMEOUT; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "userpwd")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_USERPWD; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "proxyuserpwd")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_PROXYUSERPWD; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "maxredirs")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_MAXREDIRS; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "referer")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_REFERER; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "useragent")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_USERAGENT; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "cookie")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_COOKIE; | 
					
						
							|  |  |  | 		*ot = OT_STRING; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "ftptimeout")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_FTP_RESPONSE_TIMEOUT; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "httptimeout")) { | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,16,2)
 | 
					
						
							|  |  |  | 		*key = CURLOPT_TIMEOUT_MS; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER_MS; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		*key = CURLOPT_TIMEOUT; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "conntimeout")) { | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,16,2)
 | 
					
						
							|  |  |  | 		*key = CURLOPT_CONNECTTIMEOUT_MS; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER_MS; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		*key = CURLOPT_CONNECTTIMEOUT; | 
					
						
							|  |  |  | 		*ot = OT_INTEGER; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} else if (!strcasecmp(name, "ftptext")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_TRANSFERTEXT; | 
					
						
							|  |  |  | 		*ot = OT_BOOLEAN; | 
					
						
							| 
									
										
										
										
											2009-08-14 17:36:40 +00:00
										 |  |  | 	} else if (!strcasecmp(name, "ssl_verifypeer")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_SSL_VERIFYPEER; | 
					
						
							|  |  |  | 		*ot = OT_BOOLEAN; | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 	} else if (!strcasecmp(name, "hashcompat")) { | 
					
						
							|  |  |  | 		*key = CURLOPT_SPECIAL_HASHCOMPAT; | 
					
						
							|  |  |  | 		*ot = OT_BOOLEAN; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int acf_curlopt_write(struct ast_channel *chan, const char *cmd, char *name, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_datastore *store; | 
					
						
							| 
									
										
										
										
											2008-09-06 15:40:15 +00:00
										 |  |  | 	struct global_curl_info *list; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	struct curl_settings *cur, *new = NULL; | 
					
						
							|  |  |  | 	CURLoption key; | 
					
						
							|  |  |  | 	enum optiontype ot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (chan) { | 
					
						
							|  |  |  | 		if (!(store = ast_channel_datastore_find(chan, &curl_info, NULL))) { | 
					
						
							|  |  |  | 			/* Create a new datastore */ | 
					
						
							|  |  |  | 			if (!(store = ast_datastore_alloc(&curl_info, NULL))) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Unable to allocate new datastore.  Cannot set any CURL options\n"); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!(list = ast_calloc(1, sizeof(*list)))) { | 
					
						
							|  |  |  | 				ast_log(LOG_ERROR, "Unable to allocate list head.  Cannot set any CURL options\n"); | 
					
						
							|  |  |  | 				ast_datastore_free(store); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			store->data = list; | 
					
						
							|  |  |  | 			AST_LIST_HEAD_INIT(list); | 
					
						
							|  |  |  | 			ast_channel_datastore_add(chan, store); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			list = store->data; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* Populate the global structure */ | 
					
						
							| 
									
										
										
										
											2008-09-06 15:40:15 +00:00
										 |  |  | 		list = &global_curl_info; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!parse_curlopt_key(name, &key, &ot)) { | 
					
						
							|  |  |  | 		if (ot == OT_BOOLEAN) { | 
					
						
							|  |  |  | 			if ((new = ast_calloc(1, sizeof(*new)))) { | 
					
						
							| 
									
										
										
										
											2008-09-05 22:03:26 +00:00
										 |  |  | 				new->value = (void *)((long) ast_true(value)); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else if (ot == OT_INTEGER) { | 
					
						
							|  |  |  | 			long tmp = atol(value); | 
					
						
							|  |  |  | 			if ((new = ast_calloc(1, sizeof(*new)))) { | 
					
						
							|  |  |  | 				new->value = (void *)tmp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if (ot == OT_INTEGER_MS) { | 
					
						
							|  |  |  | 			long tmp = atof(value) * 1000.0; | 
					
						
							|  |  |  | 			if ((new = ast_calloc(1, sizeof(*new)))) { | 
					
						
							|  |  |  | 				new->value = (void *)tmp; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if (ot == OT_STRING) { | 
					
						
							|  |  |  | 			if ((new = ast_calloc(1, sizeof(*new) + strlen(value) + 1))) { | 
					
						
							|  |  |  | 				new->value = (char *)new + sizeof(*new); | 
					
						
							|  |  |  | 				strcpy(new->value, value); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if (ot == OT_ENUM) { | 
					
						
							|  |  |  | 			if (key == CURLOPT_PROXYTYPE) { | 
					
						
							|  |  |  | 				long ptype = | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,10,0)
 | 
					
						
							|  |  |  | 					CURLPROXY_HTTP; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 					CURLPROXY_SOCKS5; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				if (0) { | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,15,2)
 | 
					
						
							|  |  |  | 				} else if (!strcasecmp(value, "socks4")) { | 
					
						
							|  |  |  | 					ptype = CURLPROXY_SOCKS4; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,18,0)
 | 
					
						
							|  |  |  | 				} else if (!strcasecmp(value, "socks4a")) { | 
					
						
							|  |  |  | 					ptype = CURLPROXY_SOCKS4A; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,18,0)
 | 
					
						
							|  |  |  | 				} else if (!strcasecmp(value, "socks5")) { | 
					
						
							|  |  |  | 					ptype = CURLPROXY_SOCKS5; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,18,0)
 | 
					
						
							|  |  |  | 				} else if (!strncasecmp(value, "socks5", 6)) { | 
					
						
							|  |  |  | 					ptype = CURLPROXY_SOCKS5_HOSTNAME; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if ((new = ast_calloc(1, sizeof(*new)))) { | 
					
						
							|  |  |  | 					new->value = (void *)ptype; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				/* Highly unlikely */ | 
					
						
							|  |  |  | 				goto yuck; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Memory allocation error */ | 
					
						
							|  |  |  | 		if (!new) { | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		new->key = key; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | yuck: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unrecognized option: %s\n", name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Remove any existing entry */ | 
					
						
							|  |  |  | 	AST_LIST_LOCK(list); | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE_SAFE_BEGIN(list, cur, list) { | 
					
						
							|  |  |  | 		if (cur->key == new->key) { | 
					
						
							|  |  |  | 			AST_LIST_REMOVE_CURRENT(list); | 
					
						
							|  |  |  | 			free(cur); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE_SAFE_END | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Insert new entry */ | 
					
						
							|  |  |  | 	ast_debug(1, "Inserting entry %p with key %d and value %p\n", new, new->key, new->value); | 
					
						
							|  |  |  | 	AST_LIST_INSERT_TAIL(list, new, list); | 
					
						
							|  |  |  | 	AST_LIST_UNLOCK(list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | static int acf_curlopt_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, ssize_t len) | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_datastore *store; | 
					
						
							| 
									
										
										
										
											2008-09-06 15:40:15 +00:00
										 |  |  | 	struct global_curl_info *list[2] = { &global_curl_info, NULL }; | 
					
						
							| 
									
										
										
										
											2008-09-07 00:04:05 +00:00
										 |  |  | 	struct curl_settings *cur = NULL; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	CURLoption key; | 
					
						
							|  |  |  | 	enum optiontype ot; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (parse_curlopt_key(data, &key, &ot)) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unrecognized option: '%s'\n", data); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) { | 
					
						
							|  |  |  | 		list[0] = store->data; | 
					
						
							| 
									
										
										
										
											2008-09-06 15:40:15 +00:00
										 |  |  | 		list[1] = &global_curl_info; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < 2; i++) { | 
					
						
							|  |  |  | 		if (!list[i]) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		AST_LIST_LOCK(list[i]); | 
					
						
							|  |  |  | 		AST_LIST_TRAVERSE(list[i], cur, list) { | 
					
						
							|  |  |  | 			if (cur->key == key) { | 
					
						
							|  |  |  | 				if (ot == OT_BOOLEAN || ot == OT_INTEGER) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 					if (buf) { | 
					
						
							|  |  |  | 						snprintf(buf, len, "%ld", (long) cur->value); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						ast_str_set(bufstr, len, "%ld", (long) cur->value); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 				} else if (ot == OT_INTEGER_MS) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 					if ((long) cur->value % 1000 == 0) { | 
					
						
							|  |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							snprintf(buf, len, "%ld", (long)cur->value / 1000); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, len, "%ld", (long) cur->value / 1000); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							snprintf(buf, len, "%.3f", (double) ((long) cur->value) / 1000.0); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, len, "%.3f", (double) ((long) cur->value) / 1000.0); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} else if (ot == OT_STRING) { | 
					
						
							|  |  |  | 					ast_debug(1, "Found entry %p, with key %d and value %p\n", cur, cur->key, cur->value); | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 					if (buf) { | 
					
						
							|  |  |  | 						ast_copy_string(buf, cur->value, len); | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						ast_str_set(bufstr, 0, "%s", (char *) cur->value); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 				} else if (key == CURLOPT_PROXYTYPE) { | 
					
						
							|  |  |  | 					if (0) { | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,15,2)
 | 
					
						
							|  |  |  | 					} else if ((long)cur->value == CURLPROXY_SOCKS4) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "socks4", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "socks4"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,18,0)
 | 
					
						
							|  |  |  | 					} else if ((long)cur->value == CURLPROXY_SOCKS4A) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "socks4a", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "socks4a"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 					} else if ((long)cur->value == CURLPROXY_SOCKS5) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "socks5", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "socks5"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #if CURLVERSION_ATLEAST(7,18,0)
 | 
					
						
							|  |  |  | 					} else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "socks5hostname", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "socks5hostname"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if CURLVERSION_ATLEAST(7,10,0)
 | 
					
						
							|  |  |  | 					} else if ((long)cur->value == CURLPROXY_HTTP) { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "http", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "http"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 						if (buf) { | 
					
						
							|  |  |  | 							ast_copy_string(buf, "unknown", len); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							ast_str_set(bufstr, 0, "unknown"); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		AST_LIST_UNLOCK(list[i]); | 
					
						
							|  |  |  | 		if (cur) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cur ? 0 : -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return acf_curlopt_helper(chan, cmd, data, buf, NULL, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int acf_curlopt_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return acf_curlopt_helper(chan, cmd, data, NULL, buf, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register int realsize = size * nmemb; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	struct ast_str **pstr = (struct ast_str **)data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, ast_str_size(*pstr), ast_str_strlen(*pstr)); | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_str_append_substr(pstr, 0, ptr, realsize); | 
					
						
							| 
									
										
										
										
											2007-07-18 14:59:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	ast_debug(3, "Now, len=%zu, used=%zu\n", ast_str_size(*pstr), ast_str_strlen(*pstr)); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 	return realsize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-12 13:59:35 +00:00
										 |  |  | static const char * const global_useragent = "asterisk-libcurl-agent/1.0"; | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-16 21:24:08 +00:00
										 |  |  | static int curl_instance_init(void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CURL **curl = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(*curl = curl_easy_init())) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1); | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_TIMEOUT, 180); | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_USERAGENT, global_useragent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | static void curl_instance_cleanup(void *data) | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | 	CURL **curl = data; | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | 	curl_easy_cleanup(*curl); | 
					
						
							| 
									
										
										
										
											2008-07-30 19:55:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_free(data); | 
					
						
							| 
									
										
										
										
											2006-12-16 04:25:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AST_THREADSTORAGE_CUSTOM(curl_instance, curl_instance_init, curl_instance_cleanup); | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info, char *buf, struct ast_str **input_str, ssize_t len) | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-25 16:00:54 +00:00
										 |  |  | 	struct ast_str *str = ast_str_create(16); | 
					
						
							| 
									
										
										
										
											2008-10-06 21:09:05 +00:00
										 |  |  | 	int ret = -1; | 
					
						
							| 
									
										
										
										
											2005-11-30 19:38:54 +00:00
										 |  |  | 	AST_DECLARE_APP_ARGS(args, | 
					
						
							|  |  |  | 		AST_APP_ARG(url); | 
					
						
							|  |  |  | 		AST_APP_ARG(postdata); | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	CURL **curl; | 
					
						
							|  |  |  | 	struct curl_settings *cur; | 
					
						
							|  |  |  | 	struct ast_datastore *store = NULL; | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 	int hashcompat = 0; | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL; | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 	if (buf) { | 
					
						
							|  |  |  | 		*buf = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 	if (ast_strlen_zero(info)) { | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "CURL requires an argument (URL)\n"); | 
					
						
							| 
									
										
										
										
											2008-06-25 16:00:54 +00:00
										 |  |  | 		ast_free(str); | 
					
						
							| 
									
										
										
										
											2006-02-12 04:28:58 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-01-05 06:38:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 	AST_STANDARD_APP_ARGS(args, info); | 
					
						
							| 
									
										
										
										
											2006-09-03 19:07:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	if (chan) { | 
					
						
							| 
									
										
										
										
											2007-10-26 14:00:48 +00:00
										 |  |  | 		ast_autoservice_start(chan); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-19 19:36:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	if (!(curl = ast_threadstorage_get(&curl_instance, sizeof(*curl)))) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Cannot allocate curl structure\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AST_LIST_LOCK(&global_curl_info); | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE(&global_curl_info, cur, list) { | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 		if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) { | 
					
						
							|  |  |  | 			hashcompat = (cur->value != NULL) ? 1 : 0; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			curl_easy_setopt(*curl, cur->key, cur->value); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	if (chan && (store = ast_channel_datastore_find(chan, &curl_info, NULL))) { | 
					
						
							|  |  |  | 		list = store->data; | 
					
						
							|  |  |  | 		AST_LIST_LOCK(list); | 
					
						
							|  |  |  | 		AST_LIST_TRAVERSE(list, cur, list) { | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 			if (cur->key == CURLOPT_SPECIAL_HASHCOMPAT) { | 
					
						
							|  |  |  | 				hashcompat = (cur->value != NULL) ? 1 : 0; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				curl_easy_setopt(*curl, cur->key, cur->value); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-05-26 16:15:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_URL, args.url); | 
					
						
							|  |  |  | 	curl_easy_setopt(*curl, CURLOPT_FILE, (void *) &str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (args.postdata) { | 
					
						
							|  |  |  | 		curl_easy_setopt(*curl, CURLOPT_POST, 1); | 
					
						
							|  |  |  | 		curl_easy_setopt(*curl, CURLOPT_POSTFIELDS, args.postdata); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	curl_easy_perform(*curl); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (store) { | 
					
						
							|  |  |  | 		AST_LIST_UNLOCK(list); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_LIST_UNLOCK(&global_curl_info); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (args.postdata) { | 
					
						
							|  |  |  | 		curl_easy_setopt(*curl, CURLOPT_POST, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 	if (ast_str_strlen(str)) { | 
					
						
							|  |  |  | 		ast_str_trim_blanks(str); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 		ast_debug(3, "str='%s'\n", ast_str_buffer(str)); | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 		if (hashcompat) { | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 			char *remainder = ast_str_buffer(str); | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 			char *piece; | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 			struct ast_str *fields = ast_str_create(ast_str_strlen(str) / 2); | 
					
						
							|  |  |  | 			struct ast_str *values = ast_str_create(ast_str_strlen(str) / 2); | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 			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++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-12-13 08:36:35 +00:00
										 |  |  | 			pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields)); | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 			if (buf) { | 
					
						
							|  |  |  | 				ast_copy_string(buf, ast_str_buffer(values), len); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ast_str_set(input_str, len, "%s", ast_str_buffer(values)); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 			ast_free(fields); | 
					
						
							|  |  |  | 			ast_free(values); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 			if (buf) { | 
					
						
							|  |  |  | 				ast_copy_string(buf, ast_str_buffer(str), len); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ast_str_set(input_str, len, "%s", ast_str_buffer(str)); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-09-24 06:43:05 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-10-06 21:09:05 +00:00
										 |  |  | 		ret = 0; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-06-25 16:00:54 +00:00
										 |  |  | 	ast_free(str); | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-26 14:00:48 +00:00
										 |  |  | 	if (chan) | 
					
						
							|  |  |  | 		ast_autoservice_stop(chan); | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-06 21:09:05 +00:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return acf_curl_helper(chan, cmd, info, buf, NULL, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int acf_curl2_exec(struct ast_channel *chan, const char *cmd, char *info, struct ast_str **buf, ssize_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return acf_curl_helper(chan, cmd, info, NULL, buf, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 17:34:30 +00:00
										 |  |  | static struct ast_custom_function acf_curl = { | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 	.name = "CURL", | 
					
						
							|  |  |  | 	.synopsis = "Retrieves the contents of a URL", | 
					
						
							| 
									
										
										
										
											2007-07-31 01:10:47 +00:00
										 |  |  | 	.syntax = "CURL(url[,post-data])", | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 	.desc = | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	"  url       - URL to retrieve\n" | 
					
						
							|  |  |  | 	"  post-data - Optional data to send as a POST (GET is default action)\n", | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | 	.read = acf_curl_exec, | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 	.read2 = acf_curl2_exec, | 
					
						
							| 
									
										
										
										
											2005-09-25 19:36:48 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 17:34:30 +00:00
										 |  |  | static struct ast_custom_function acf_curlopt = { | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	.name = "CURLOPT", | 
					
						
							|  |  |  | 	.synopsis = "Set options for use with the CURL() function", | 
					
						
							|  |  |  | 	.syntax = "CURLOPT(<option>)", | 
					
						
							|  |  |  | 	.desc = | 
					
						
							| 
									
										
										
										
											2009-08-14 17:36:40 +00:00
										 |  |  | "  cookie         - Send cookie with request [none]\n" | 
					
						
							|  |  |  | "  conntimeout    - Number of seconds to wait for connection\n" | 
					
						
							|  |  |  | "  dnstimeout     - Number of seconds to wait for DNS response\n" | 
					
						
							|  |  |  | "  ftptext        - For FTP, force a text transfer (boolean)\n" | 
					
						
							|  |  |  | "  ftptimeout     - For FTP, the server response timeout\n" | 
					
						
							|  |  |  | "  header         - Retrieve header information (boolean)\n" | 
					
						
							|  |  |  | "  httptimeout    - Number of seconds to wait for HTTP response\n" | 
					
						
							|  |  |  | "  maxredirs      - Maximum number of redirects to follow\n" | 
					
						
							|  |  |  | "  proxy          - Hostname or IP to use as a proxy\n" | 
					
						
							|  |  |  | "  proxytype      - http, socks4, or socks5\n" | 
					
						
							|  |  |  | "  proxyport      - port number of the proxy\n" | 
					
						
							|  |  |  | "  proxyuserpwd   - A <user>:<pass> to use for authentication\n" | 
					
						
							|  |  |  | "  referer        - Referer URL to use for the request\n" | 
					
						
							|  |  |  | "  useragent      - UserAgent string to use\n" | 
					
						
							|  |  |  | "  userpwd        - A <user>:<pass> 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" | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | "", | 
					
						
							|  |  |  | 	.read = acf_curlopt_read, | 
					
						
							| 
									
										
										
										
											2009-04-29 18:53:01 +00:00
										 |  |  | 	.read2 = acf_curlopt_read2, | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	.write = acf_curlopt_write, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = ast_custom_function_unregister(&acf_curl); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	res |= ast_custom_function_unregister(&acf_curlopt); | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-25 16:00:54 +00:00
										 |  |  | 	if (!ast_module_check("res_curl.so")) { | 
					
						
							|  |  |  | 		if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Cannot load res_curl, so func_curl cannot be loaded\n"); | 
					
						
							|  |  |  | 			return AST_MODULE_LOAD_DECLINE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-03 19:07:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	res = ast_custom_function_register(&acf_curl); | 
					
						
							| 
									
										
										
										
											2008-09-05 19:12:03 +00:00
										 |  |  | 	res |= ast_custom_function_register(&acf_curlopt); | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:55:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Load external URL"); | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | 
 |