mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-27 06:31:54 +00:00 
			
		
		
		
	This patch fixes gcc warnings that occur due to the type qualifier 'const' being ignored on a return type of int. ASTERISK-24246 #close Reported by: Shaun Ruffell patches: 0001-main-uri-Quiet-warning-about-ignored-attribute-on-re.patch uploaded by Shaun Ruffell (License 5417) ........ Merged revisions 421675 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@421676 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			324 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			324 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Asterisk -- An open source telephony toolkit.
 | |
|  *
 | |
|  * Copyright (C) 2014, Digium, Inc.
 | |
|  *
 | |
|  * Kevin Harwell <kharwell@digium.com>
 | |
|  *
 | |
|  * 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.
 | |
|  *
 | |
|  * This program is free software, distributed under the terms of
 | |
|  * the GNU General Public License Version 2. See the LICENSE file
 | |
|  * at the top of the source tree.
 | |
|  */
 | |
| 
 | |
| #include "asterisk.h"
 | |
| 
 | |
| #include "asterisk/astobj2.h"
 | |
| #include "asterisk/strings.h"
 | |
| #include "asterisk/uri.h"
 | |
| 
 | |
| #ifdef HAVE_URIPARSER
 | |
| #include <uriparser/Uri.h>
 | |
| #endif
 | |
| 
 | |
| /*! \brief Stores parsed uri information */
 | |
| struct ast_uri {
 | |
| 	/*! scheme (e.g. http, https, ws, wss, etc...) */
 | |
| 	char *scheme;
 | |
| 	/*! username:password */
 | |
| 	char *user_info;
 | |
| 	/*! host name or address */
 | |
| 	char *host;
 | |
| 	/*! associated port */
 | |
| 	char *port;
 | |
| 	/*! path info following host[:port] */
 | |
| 	char *path;
 | |
| 	/*! query information */
 | |
| 	char *query;
 | |
| 	/*! storage for uri string */
 | |
| 	char uri[0];
 | |
| };
 | |
| 
 | |
| /*!
 | |
|  * \brief Construct a uri object with the given values.
 | |
|  *
 | |
|  * \note The size parameters [should] include room for the string terminator
 | |
|  *       (strlen(<param>) + 1). For instance, if a scheme of 'http' is given
 | |
|  *       then the 'scheme_size' should be equal to 5.
 | |
|  */
 | |
| static struct ast_uri *ast_uri_create_(
 | |
| 	const char *scheme, unsigned int scheme_size,
 | |
| 	const char *user_info, unsigned int user_info_size,
 | |
| 	const char *host, unsigned int host_size,
 | |
| 	const char *port, unsigned int port_size,
 | |
| 	const char *path, unsigned int path_size,
 | |
| 	const char *query, unsigned int query_size)
 | |
| {
 | |
| #define SET_VALUE(param, field, size) \
 | |
| 	do { if (param) { \
 | |
| 	     ast_copy_string(p, param, size); \
 | |
| 	     field = p; \
 | |
| 	     p += size;	} } while (0)
 | |
| 
 | |
| 	char *p;
 | |
| 	struct ast_uri *res = ao2_alloc(
 | |
| 		sizeof(*res) + scheme_size + user_info_size + host_size +
 | |
| 		port_size + path_size + query_size, NULL);
 | |
| 
 | |
| 	if (!res) {
 | |
| 		ast_log(LOG_ERROR, "Unable to create URI object\n");
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	p = res->uri;
 | |
| 	SET_VALUE(scheme, res->scheme, scheme_size);
 | |
| 	SET_VALUE(user_info, res->user_info, user_info_size);
 | |
| 	SET_VALUE(host, res->host, host_size);
 | |
| 	SET_VALUE(port, res->port, port_size);
 | |
| 	SET_VALUE(path, res->path, path_size);
 | |
| 	SET_VALUE(query, res->query, query_size);
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| struct ast_uri *ast_uri_create(const char *scheme, const char *user_info,
 | |
| 			       const char *host, const char *port,
 | |
| 			       const char *path, const char *query)
 | |
| {
 | |
| 	return ast_uri_create_(
 | |
| 		scheme, scheme ? strlen(scheme) + 1 : 0,
 | |
| 		user_info, user_info ? strlen(user_info) + 1 : 0,
 | |
| 		host, host ? strlen(host) + 1 : 0,
 | |
| 		port, port ? strlen(port) + 1 : 0,
 | |
| 		path, path ? strlen(path) + 1 : 0,
 | |
| 		query, query ? strlen(query) + 1 : 0);
 | |
| }
 | |
| 
 | |
| struct ast_uri *ast_uri_copy_replace(const struct ast_uri *uri, const char *scheme,
 | |
| 				     const char *user_info, const char *host,
 | |
| 				     const char *port, const char *path,
 | |
| 				     const char *query)
 | |
| {
 | |
| 	return ast_uri_create(
 | |
| 		scheme ? scheme : uri->scheme,
 | |
| 		user_info ? user_info : uri->user_info,
 | |
| 		host ? host : uri->host,
 | |
| 		port ? port : uri->port,
 | |
| 		path ? path : uri->path,
 | |
| 		query ? query : uri->query);
 | |
| }
 | |
| 
 | |
| const char *ast_uri_scheme(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->scheme;
 | |
| }
 | |
| 
 | |
| const char *ast_uri_user_info(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->user_info;
 | |
| }
 | |
| 
 | |
| const char *ast_uri_host(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->host;
 | |
| }
 | |
| 
 | |
| const char *ast_uri_port(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->port;
 | |
| }
 | |
| 
 | |
| const char *ast_uri_path(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->path;
 | |
| }
 | |
| 
 | |
| const char *ast_uri_query(const struct ast_uri *uri)
 | |
| {
 | |
| 	return uri->query;
 | |
| }
 | |
| 
 | |
| int ast_uri_is_secure(const struct ast_uri *uri)
 | |
| {
 | |
| 	return ast_strlen_zero(uri->scheme) ? 0 :
 | |
| 		*(uri->scheme + strlen(uri->scheme) - 1) == 's';
 | |
| }
 | |
| 
 | |
| #ifdef HAVE_URIPARSER
 | |
| struct ast_uri *ast_uri_parse(const char *uri)
 | |
| {
 | |
| 	UriParserStateA state;
 | |
| 	UriUriA uria;
 | |
| 	struct ast_uri *res;
 | |
| 	unsigned int scheme_size, user_info_size, host_size;
 | |
| 	unsigned int port_size, path_size, query_size;
 | |
| 	const char *path_start, *path_end;
 | |
| 
 | |
| 	state.uri = &uria;
 | |
| 	if (uriParseUriA(&state, uri) != URI_SUCCESS) {
 | |
| 		ast_log(LOG_ERROR, "Unable to parse URI %s\n", uri);
 | |
| 		uriFreeUriMembersA(&uria);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	scheme_size = uria.scheme.first ?
 | |
| 		uria.scheme.afterLast - uria.scheme.first + 1 : 0;
 | |
| 	user_info_size = uria.userInfo.first ?
 | |
| 		uria.userInfo.afterLast - uria.userInfo.first + 1 : 0;
 | |
| 	host_size = uria.hostText.first ?
 | |
| 		uria.hostText.afterLast - uria.hostText.first + 1 : 0;
 | |
| 	port_size = uria.portText.first ?
 | |
| 		uria.portText.afterLast - uria.portText.first + 1 : 0;
 | |
| 
 | |
| 	path_start = uria.pathHead && uria.pathHead->text.first ?
 | |
| 		uria.pathHead->text.first : NULL;
 | |
| 	path_end = path_start ? uria.pathTail->text.afterLast : NULL;
 | |
| 	path_size = path_end ? path_end - path_start + 1 : 0;
 | |
| 
 | |
| 	query_size = uria.query.first ?
 | |
| 		uria.query.afterLast - uria.query.first + 1 : 0;
 | |
| 
 | |
| 	res = ast_uri_create_(uria.scheme.first, scheme_size,
 | |
| 			      uria.userInfo.first, user_info_size,
 | |
| 			      uria.hostText.first, host_size,
 | |
| 			      uria.portText.first, port_size,
 | |
| 			      path_start, path_size,
 | |
| 			      uria.query.first, query_size);
 | |
| 	uriFreeUriMembersA(&uria);
 | |
| 	return res;
 | |
| }
 | |
| #else
 | |
| struct ast_uri *ast_uri_parse(const char *uri)
 | |
| {
 | |
| #define SET_VALUES(value) \
 | |
| 	value = uri; \
 | |
| 	size_##value = p - uri + 1; \
 | |
| 	uri = p + 1;
 | |
| 
 | |
| 	const char *p, *scheme = NULL, *user_info = NULL, *host = NULL;
 | |
| 	const char *port = NULL, *path = NULL, *query = NULL;
 | |
| 	unsigned int size_scheme = 0, size_user_info = 0, size_host = 0;
 | |
| 	unsigned int size_port = 0, size_path = 0, size_query = 0;
 | |
| 
 | |
| 	if ((p = strstr(uri, "://"))) {
 | |
| 		scheme = uri;
 | |
| 		size_scheme = p - uri + 1;
 | |
| 		uri = p + 3;
 | |
| 	}
 | |
| 
 | |
| 	if ((p = strchr(uri, '@'))) {
 | |
| 		SET_VALUES(user_info);
 | |
| 	}
 | |
| 
 | |
| 	if ((p = strchr(uri, ':'))) {
 | |
| 		SET_VALUES(host);
 | |
| 	}
 | |
| 
 | |
| 	if ((p = strchr(uri, '/'))) {
 | |
| 		if (!host) {
 | |
| 			SET_VALUES(host);
 | |
| 		} else {
 | |
| 			SET_VALUES(port);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if ((p = strchr(uri, '?'))) {
 | |
| 		query = p + 1;
 | |
| 		size_query = strlen(query) + 1;
 | |
| 	} else {
 | |
| 		p = uri + strlen(uri);
 | |
| 	}
 | |
| 
 | |
| 	if (!host) {
 | |
| 		SET_VALUES(host);
 | |
| 	} else if (*(uri - 1) == ':') {
 | |
| 		SET_VALUES(port);
 | |
| 	} else if (*(uri - 1) == '/') {
 | |
| 		SET_VALUES(path);
 | |
| 	}
 | |
| 
 | |
| 	return ast_uri_create_(scheme, size_scheme,
 | |
| 			       user_info, size_user_info,
 | |
| 			       host, size_host,
 | |
| 			       port, size_port,
 | |
| 			       path, size_path,
 | |
| 			       query, size_query);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static struct ast_uri *uri_parse_and_default(const char *uri, const char *scheme,
 | |
| 					     const char *port, const char *secure_port)
 | |
| {
 | |
| 	struct ast_uri *res;
 | |
| 	int len = strlen(scheme);
 | |
| 
 | |
| 	if (!strncmp(uri, scheme, len)) {
 | |
| 		res = ast_uri_parse(uri);
 | |
| 	} else {
 | |
| 		/* make room for <scheme>:// */
 | |
| 		char *with_scheme = ast_malloc(len + strlen(uri) + 4);
 | |
| 		if (!with_scheme) {
 | |
| 			ast_log(LOG_ERROR, "Unable to allocate uri '%s' with "
 | |
| 				"scheme '%s'", uri, scheme);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 
 | |
| 		/* safe - 'with_scheme' created with size equal to len of
 | |
| 		   scheme plus length of uri plus space for extra characters
 | |
| 		   '://' and terminator */
 | |
| 		sprintf(with_scheme, "%s://%s", scheme, uri);
 | |
| 		res = ast_uri_parse(with_scheme);
 | |
| 		ast_free(with_scheme);
 | |
| 	}
 | |
| 
 | |
| 	if (res && ast_strlen_zero(ast_uri_port(res))) {
 | |
| 		/* default the port if not given */
 | |
| 		struct ast_uri *tmp = ast_uri_copy_replace(
 | |
| 			res, NULL, NULL, NULL,
 | |
| 			ast_uri_is_secure(res) ? secure_port : port,
 | |
| 			NULL, NULL);
 | |
| 		ao2_ref(res, -1);
 | |
| 		res = tmp;
 | |
| 	}
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| struct ast_uri *ast_uri_parse_http(const char *uri)
 | |
| {
 | |
| 	return uri_parse_and_default(uri, "http", "80", "443");
 | |
| }
 | |
| 
 | |
| struct ast_uri *ast_uri_parse_websocket(const char *uri)
 | |
| {
 | |
| 	return uri_parse_and_default(uri, "ws", "80", "443");
 | |
| }
 | |
| 
 | |
| char *ast_uri_make_host_with_port(const struct ast_uri *uri)
 | |
| {
 | |
| 	int host_size = ast_uri_host(uri) ?
 | |
| 		strlen(ast_uri_host(uri)) : 0;
 | |
| 	/* if there is a port +1 for the colon */
 | |
| 	int port_size = ast_uri_port(uri) ?
 | |
| 		strlen(ast_uri_port(uri)) + 1 : 0;
 | |
| 	char *res = ast_malloc(host_size + port_size + 1);
 | |
| 
 | |
| 	if (!res) {
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	memcpy(res, ast_uri_host(uri), host_size);
 | |
| 
 | |
| 	if (ast_uri_port(uri)) {
 | |
| 		res[host_size] = ':';
 | |
| 		memcpy(res + host_size + 1,
 | |
| 		       ast_uri_port(uri), port_size - 1);
 | |
| 	}
 | |
| 
 | |
| 	res[host_size + port_size] = '\0';
 | |
| 	return res;
 | |
| }
 |