mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Add a hashcompat mode called "legacy", which translates a literal plus sign to a space.
(closes issue #18046) Reported by: wdoekes Patches: 20100930__issue18046.diff.txt uploaded by tilghman (license 14) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@300840 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -50,6 +50,122 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/utils.h" | ||||
| #include "asterisk/threadstorage.h" | ||||
|  | ||||
| /*** DOCUMENTATION | ||||
| 	<function name="CURL" language="en_US"> | ||||
| 		<synopsis> | ||||
| 			Retrieve content from a remote web or ftp server | ||||
| 		</synopsis> | ||||
| 		<syntax> | ||||
| 			<parameter name="url" required="true" /> | ||||
| 			<parameter name="post-data"> | ||||
| 				<para>If specified, an <literal>HTTP POST</literal> will be | ||||
| 				performed with the content of | ||||
| 				<replaceable>post-data</replaceable>, instead of an | ||||
| 				<literal>HTTP GET</literal> (default).</para> | ||||
| 			</parameter> | ||||
| 		</syntax> | ||||
| 		<description /> | ||||
| 		<see-also> | ||||
| 			<ref type="function">CURLOPT</ref> | ||||
| 		</see-also> | ||||
| 	</function> | ||||
| 	<function name="CURLOPT" language="en_US"> | ||||
| 		<synopsis> | ||||
| 			Sets various options for future invocations of <literal>CURL</literal>. | ||||
| 		</synopsis> | ||||
| 		<syntax> | ||||
| 			<parameter name="key" required="yes"> | ||||
| 				<enumlist> | ||||
| 					<enum name="cookie"> | ||||
| 						<para>A cookie to send with the request.  Multiple | ||||
| 						cookies are supported.</para> | ||||
| 					</enum> | ||||
| 					<enum name="conntimeout"> | ||||
| 						<para>Number of seconds to wait for a connection to succeed</para> | ||||
| 					</enum> | ||||
| 					<enum name="dnstimeout"> | ||||
| 						<para>Number of seconds to wait for DNS to be resolved</para> | ||||
| 					</enum> | ||||
| 					<enum name="ftptext"> | ||||
| 						<para>For FTP URIs, force a text transfer (boolean)</para> | ||||
| 					</enum> | ||||
| 					<enum name="ftptimeout"> | ||||
| 						<para>For FTP URIs, number of seconds to wait for a | ||||
| 						server response</para> | ||||
| 					</enum> | ||||
| 					<enum name="header"> | ||||
| 						<para>Include header information in the result | ||||
| 						(boolean)</para> | ||||
| 					</enum> | ||||
| 					<enum name="httptimeout"> | ||||
| 						<para>For HTTP(S) URIs, number of seconds to wait for a | ||||
| 						server response</para> | ||||
| 					</enum> | ||||
| 					<enum name="maxredirs"> | ||||
| 						<para>Maximum number of redirects to follow</para> | ||||
| 					</enum> | ||||
| 					<enum name="proxy"> | ||||
| 						<para>Hostname or IP address to use as a proxy server</para> | ||||
| 					</enum> | ||||
| 					<enum name="proxytype"> | ||||
| 						<para>Type of <literal>proxy</literal></para> | ||||
| 						<enumlist> | ||||
| 							<enum name="http" /> | ||||
| 							<enum name="socks4" /> | ||||
| 							<enum name="socks5" /> | ||||
| 						</enumlist> | ||||
| 					</enum> | ||||
| 					<enum name="proxyport"> | ||||
| 						<para>Port number of the <literal>proxy</literal></para> | ||||
| 					</enum> | ||||
| 					<enum name="proxyuserpwd"> | ||||
| 						<para>A <replaceable>username</replaceable><literal>:</literal><replaceable>password</replaceable> | ||||
| 						combination to use for authenticating requests through a | ||||
| 						<literal>proxy</literal></para> | ||||
| 					</enum> | ||||
| 					<enum name="referer"> | ||||
| 						<para>Referer URL to use for the request</para> | ||||
| 					</enum> | ||||
| 					<enum name="useragent"> | ||||
| 						<para>UserAgent string to use for the request</para> | ||||
| 					</enum> | ||||
| 					<enum name="userpwd"> | ||||
| 						<para>A <replaceable>username</replaceable><literal>:</literal><replaceable>password</replaceable> | ||||
| 						to use for authentication when the server response to | ||||
| 						an initial request indicates a 401 status code.</para> | ||||
| 					</enum> | ||||
| 					<enum name="ssl_verifypeer"> | ||||
| 						<para>Whether to verify the server certificate against | ||||
| 						a list of known root certificate authorities (boolean).</para> | ||||
| 					</enum> | ||||
| 					<enum name="hashcompat"> | ||||
| 						<para>Assuming the responses will be in <literal>key1=value1&key2=value2</literal> | ||||
| 						format, reformat the response such that it can be used | ||||
| 						by the <literal>HASH</literal> function.</para> | ||||
| 						<enumlist> | ||||
| 							<enum name="yes" /> | ||||
| 							<enum name="no" /> | ||||
| 							<enum name="legacy"> | ||||
| 								<para>Also translate <literal>+<literal> to the | ||||
| 								space character, in violation of current RFC | ||||
| 								standards.</para> | ||||
| 							</enum> | ||||
| 						</enumlist> | ||||
| 					</enum> | ||||
| 				</enumlist> | ||||
| 			</parameter> | ||||
| 		</syntax> | ||||
| 		<description> | ||||
| 			<para>Options may be set globally or per channel.  Per-channel | ||||
| 			settings will override global settings.</para> | ||||
| 		</description> | ||||
| 		<see-also> | ||||
| 			<ref type="function">CURL</ref> | ||||
| 			<ref type="function">HASH</ref> | ||||
| 		</see-also> | ||||
| 	</function> | ||||
|  ***/ | ||||
|  | ||||
| #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 <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" | ||||
| "                 - if value is \"legacy\", will translate '+' to ' '\n" | ||||
| "", | ||||
| 	.read = acf_curlopt_read, | ||||
| 	.read2 = acf_curlopt_read2, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user