|  | @@ -9838,12 +9838,22 @@ struct mg_connection *mg_connect_client(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +struct {
 | 
	
		
			
				|  |  | +	const char *proto;
 | 
	
		
			
				|  |  | +	size_t proto_len;
 | 
	
		
			
				|  |  | +	int default_port;
 | 
	
		
			
				|  |  | +} static abs_uri_protocols[] = {{"http://", 7, 80},
 | 
	
		
			
				|  |  | +                                {"https://", 8, 443},
 | 
	
		
			
				|  |  | +                                {"ws://", 5, 80},
 | 
	
		
			
				|  |  | +                                {"wss://", 6, 443},
 | 
	
		
			
				|  |  | +                                {NULL, 0, 0}};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int is_valid_uri(const char *uri)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	size_t proto_len;
 | 
	
		
			
				|  |  | -	char *hostend, *portbegin;
 | 
	
		
			
				|  |  | +	int i;
 | 
	
		
			
				|  |  | +	char *hostend, *portbegin, *portend;
 | 
	
		
			
				|  |  |  	unsigned long port;
 | 
	
		
			
				|  |  | -	char *pend;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* According to the HTTP standard
 | 
	
		
			
				|  |  |  	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
 | 
	
	
		
			
				|  | @@ -9863,34 +9873,30 @@ static int is_valid_uri(const char *uri)
 | 
	
		
			
				|  |  |  	 * addressing the current server. So civetweb can also be used
 | 
	
		
			
				|  |  |  	 * as a proxy server. */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if (mg_strncasecmp(uri, "http://", 7) == 0) {
 | 
	
		
			
				|  |  | -		proto_len = 7;
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "https://", 8) == 0) {
 | 
	
		
			
				|  |  | -		proto_len = 8;
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "ws://", 5) == 0) {
 | 
	
		
			
				|  |  | -		proto_len = 5;
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "wss://", 6) == 0) {
 | 
	
		
			
				|  |  | -		proto_len = 6;
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		/* unknown protocol */
 | 
	
		
			
				|  |  | -		return 0;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
 | 
	
		
			
				|  |  | +		if (mg_strncasecmp(uri,
 | 
	
		
			
				|  |  | +		                   abs_uri_protocols[i].proto,
 | 
	
		
			
				|  |  | +		                   abs_uri_protocols[i].proto_len) == 0) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	hostend = strchr(uri + proto_len, '/');
 | 
	
		
			
				|  |  | -	if (!hostend) {
 | 
	
		
			
				|  |  | -		return 0;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	portbegin = strchr(uri + proto_len, ':');
 | 
	
		
			
				|  |  | -	if (!portbegin) {
 | 
	
		
			
				|  |  | -		return 1;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +			hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
 | 
	
		
			
				|  |  | +			if (!hostend) {
 | 
	
		
			
				|  |  | +				return 0;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
 | 
	
		
			
				|  |  | +			if (!portbegin) {
 | 
	
		
			
				|  |  | +				return 1;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	port = strtoul(portbegin + 1, &pend, 10);
 | 
	
		
			
				|  |  | -	if ((pend != hostend) || !is_valid_port(port)) {
 | 
	
		
			
				|  |  | -		return 0;
 | 
	
		
			
				|  |  | +			port = strtoul(portbegin + 1, &portend, 10);
 | 
	
		
			
				|  |  | +			if ((portend != hostend) || !port || !is_valid_port(port)) {
 | 
	
		
			
				|  |  | +				return 0;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			return 1;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	return port && is_valid_port(port);
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -9899,8 +9905,9 @@ static int is_absolute_uri_at_current_server(const char *uri,
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	const char *domain;
 | 
	
		
			
				|  |  |  	size_t domain_len;
 | 
	
		
			
				|  |  | -	unsigned long port;
 | 
	
		
			
				|  |  | -	char *pend;
 | 
	
		
			
				|  |  | +	unsigned long port = 0;
 | 
	
		
			
				|  |  | +	int i;
 | 
	
		
			
				|  |  | +	char *hostend, *portbegin, *portend;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* DNS is case insensitive, so use case insensitive string compare here */
 | 
	
		
			
				|  |  |  	domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
 | 
	
	
		
			
				|  | @@ -9912,76 +9919,29 @@ static int is_absolute_uri_at_current_server(const char *uri,
 | 
	
		
			
				|  |  |  		return 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if (mg_strncasecmp(uri, "http://", 7) == 0) {
 | 
	
		
			
				|  |  | -		if (mg_strncasecmp(uri + 7, domain, domain_len) == 0) {
 | 
	
		
			
				|  |  | -			if (uri[7 + domain_len] == '/') {
 | 
	
		
			
				|  |  | -				port = 80;
 | 
	
		
			
				|  |  | -			} else if (uri[7 + domain_len] == ':') {
 | 
	
		
			
				|  |  | -				port = strtoul(uri + 7 + domain_len + 1, &pend, 10);
 | 
	
		
			
				|  |  | -				if (!pend || *pend != '/') {
 | 
	
		
			
				|  |  | -					return 0;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | +	for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
 | 
	
		
			
				|  |  | +		if (mg_strncasecmp(uri,
 | 
	
		
			
				|  |  | +		                   abs_uri_protocols[i].proto,
 | 
	
		
			
				|  |  | +		                   abs_uri_protocols[i].proto_len) == 0) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
 | 
	
		
			
				|  |  | +			if (!hostend) {
 | 
	
		
			
				|  |  |  				return 0;
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			/* not the correct domain */
 | 
	
		
			
				|  |  | -			return 0;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "https://", 8) == 0) {
 | 
	
		
			
				|  |  | -		if (mg_strncasecmp(uri + 8, domain, domain_len) == 0) {
 | 
	
		
			
				|  |  | -			if (uri[8 + domain_len] == '/') {
 | 
	
		
			
				|  |  | -				port = 443;
 | 
	
		
			
				|  |  | -			} else if (uri[8 + domain_len] == ':') {
 | 
	
		
			
				|  |  | -				port = strtoul(uri + 8 + domain_len + 1, &pend, 10);
 | 
	
		
			
				|  |  | -				if (!pend || *pend != '/') {
 | 
	
		
			
				|  |  | -					return 0;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | +			portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
 | 
	
		
			
				|  |  | +			if (!portbegin) {
 | 
	
		
			
				|  |  | +				port = abs_uri_protocols[i].default_port;
 | 
	
		
			
				|  |  |  			} else {
 | 
	
		
			
				|  |  | -				return 0;
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			/* not the correct domain */
 | 
	
		
			
				|  |  | -			return 0;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "ws://", 5) == 0) {
 | 
	
		
			
				|  |  | -		if (mg_strncasecmp(uri + 5, domain, domain_len) == 0) {
 | 
	
		
			
				|  |  | -			if (uri[5 + domain_len] == '/') {
 | 
	
		
			
				|  |  | -				port = 80;
 | 
	
		
			
				|  |  | -			} else if (uri[5 + domain_len] == ':') {
 | 
	
		
			
				|  |  | -				port = strtoul(uri + 5 + domain_len + 1, &pend, 10);
 | 
	
		
			
				|  |  | -				if (!pend || *pend != '/') {
 | 
	
		
			
				|  |  | +				port = strtoul(portbegin + 1, &portend, 10);
 | 
	
		
			
				|  |  | +				if ((portend != hostend) || !port || !is_valid_port(port)) {
 | 
	
		
			
				|  |  |  					return 0;
 | 
	
		
			
				|  |  |  				}
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | -				return 0;
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			/* not the correct domain */
 | 
	
		
			
				|  |  | -			return 0;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	} else if (mg_strncasecmp(uri, "wss://", 6) == 0) {
 | 
	
		
			
				|  |  | -		if (mg_strncasecmp(uri + 6, domain, domain_len) == 0) {
 | 
	
		
			
				|  |  | -			if (uri[6 + domain_len] == '/') {
 | 
	
		
			
				|  |  | -				port = 443;
 | 
	
		
			
				|  |  | -			} else if (uri[6 + domain_len] == ':') {
 | 
	
		
			
				|  |  | -				port = strtoul(uri + 6 + domain_len + 1, &pend, 10);
 | 
	
		
			
				|  |  | -				if (!pend || *pend != '/') {
 | 
	
		
			
				|  |  | -					return 0;
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			} else {
 | 
	
		
			
				|  |  | -				return 0;
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		} else {
 | 
	
		
			
				|  |  | -			/* not the correct domain */
 | 
	
		
			
				|  |  | -			return 0;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		/* unknown protocol */
 | 
	
		
			
				|  |  | -		return 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if (!is_valid_port(port)) {
 | 
	
		
			
				|  |  | +	if (!port) {
 | 
	
		
			
				|  |  | +		/* port remains 0 if the protocol is not found */
 | 
	
		
			
				|  |  |  		return 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 |