|  | @@ -5798,7 +5798,8 @@ interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 | 
											
												
													
														|  |  	char const *accept_encoding;
 |  |  	char const *accept_encoding;
 | 
											
												
													
														|  |  	int truncated;
 |  |  	int truncated;
 | 
											
												
													
														|  |  #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 |  |  #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 | 
											
												
													
														|  | -	char *p;
 |  | 
 | 
											
												
													
														|  | 
 |  | +	char *tmp_str;
 | 
											
												
													
														|  | 
 |  | +	size_t tmp_str_len, sep_pos;
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  |  #else
 |  |  #else
 | 
											
												
													
														|  |  	(void)filename_buf_len; /* unused if NO_FILES is defined */
 |  |  	(void)filename_buf_len; /* unused if NO_FILES is defined */
 | 
											
										
											
												
													
														|  | @@ -5951,42 +5952,80 @@ interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 | 
											
												
													
														|  |  #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 |  |  #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 | 
											
												
													
														|  |  	/* Step 9: Script resources may handle sub-resources */
 |  |  	/* Step 9: Script resources may handle sub-resources */
 | 
											
												
													
														|  |  	/* Support PATH_INFO for CGI scripts. */
 |  |  	/* Support PATH_INFO for CGI scripts. */
 | 
											
												
													
														|  | -	for (p = filename + strlen(filename); p > filename + 1; p--) {
 |  | 
 | 
											
												
													
														|  | -		if (*p == '/') {
 |  | 
 | 
											
												
													
														|  | -			*p = '\0';
 |  | 
 | 
											
												
													
														|  | -			if (extention_matches_script(conn, filename)
 |  | 
 | 
											
												
													
														|  | -			    && mg_stat(conn, filename, filestat)) {
 |  | 
 | 
											
												
													
														|  | -				/* Shift PATH_INFO block one character right, e.g.
 |  | 
 | 
											
												
													
														|  | -				 * "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
 |  | 
 | 
											
												
													
														|  | -				 * conn->path_info is pointing to the local variable "path"
 |  | 
 | 
											
												
													
														|  | -				 * declared in handle_request(), so PATH_INFO is not valid
 |  | 
 | 
											
												
													
														|  | -				 * after handle_request returns. */
 |  | 
 | 
											
												
													
														|  | -				conn->path_info = p + 1;
 |  | 
 | 
											
												
													
														|  | -				memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
 |  | 
 | 
											
												
													
														|  | -				                                           * trailing \0 */
 |  | 
 | 
											
												
													
														|  | -				p[1] = '/';
 |  | 
 | 
											
												
													
														|  | 
 |  | +	tmp_str_len = strlen(filename);
 | 
											
												
													
														|  | 
 |  | +	tmp_str = mg_malloc(tmp_str_len + PATH_MAX + 1);
 | 
											
												
													
														|  | 
 |  | +	if (!tmp_str) {
 | 
											
												
													
														|  | 
 |  | +		/* Out of memory */
 | 
											
												
													
														|  | 
 |  | +		goto interpret_cleanup;
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +	memcpy(tmp_str, filename, tmp_str_len + 1);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	sep_pos = tmp_str_len;
 | 
											
												
													
														|  | 
 |  | +	while (sep_pos > 0) {
 | 
											
												
													
														|  | 
 |  | +		sep_pos--;
 | 
											
												
													
														|  | 
 |  | +		if (tmp_str[sep_pos] == '/') {
 | 
											
												
													
														|  | 
 |  | +			int is_script = 0, does_exist = 0;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			tmp_str[sep_pos] = 0;
 | 
											
												
													
														|  | 
 |  | +			if (tmp_str[0]) {
 | 
											
												
													
														|  | 
 |  | +				is_script = extention_matches_script(conn, tmp_str);
 | 
											
												
													
														|  | 
 |  | +				does_exist = mg_stat(conn, tmp_str, filestat);
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			if (does_exist && is_script) {
 | 
											
												
													
														|  | 
 |  | +				filename[sep_pos] = 0;
 | 
											
												
													
														|  | 
 |  | +				memmove(filename + sep_pos + 2,
 | 
											
												
													
														|  | 
 |  | +				        filename + sep_pos + 1,
 | 
											
												
													
														|  | 
 |  | +				        strlen(filename + sep_pos + 1) + 1);
 | 
											
												
													
														|  | 
 |  | +				conn->path_info = filename + sep_pos + 1;
 | 
											
												
													
														|  | 
 |  | +				filename[sep_pos + 1] = '/';
 | 
											
												
													
														|  |  				*is_script_resource = 1;
 |  |  				*is_script_resource = 1;
 | 
											
												
													
														|  |  				*is_found = 1;
 |  |  				*is_found = 1;
 | 
											
												
													
														|  |  				break;
 |  |  				break;
 | 
											
												
													
														|  | -			} else if (substitute_index_file(
 |  | 
 | 
											
												
													
														|  | -			               conn, filename, filename_buf_len, filestat)) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +			if (substitute_index_file(
 | 
											
												
													
														|  | 
 |  | +			        conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
 | 
											
												
													
														|  |  				/* some intermediate directory has an index file */
 |  |  				/* some intermediate directory has an index file */
 | 
											
												
													
														|  | -				if (extention_matches_script(conn, filename)) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +				if (extention_matches_script(conn, tmp_str)) {
 | 
											
												
													
														|  |  					/* this index file is a script */
 |  |  					/* this index file is a script */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +					char *tmp_str2 = mg_strdup(filename + sep_pos + 1);
 | 
											
												
													
														|  | 
 |  | +					mg_snprintf(conn,
 | 
											
												
													
														|  | 
 |  | +					            &truncated,
 | 
											
												
													
														|  | 
 |  | +					            filename,
 | 
											
												
													
														|  | 
 |  | +					            filename_buf_len,
 | 
											
												
													
														|  | 
 |  | +					            "%s//%s",
 | 
											
												
													
														|  | 
 |  | +					            tmp_str,
 | 
											
												
													
														|  | 
 |  | +					            tmp_str2);
 | 
											
												
													
														|  | 
 |  | +					mg_free(tmp_str2);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +					if (truncated) {
 | 
											
												
													
														|  | 
 |  | +						mg_free(tmp_str);
 | 
											
												
													
														|  | 
 |  | +						tmp_str = NULL;
 | 
											
												
													
														|  | 
 |  | +						goto interpret_cleanup;
 | 
											
												
													
														|  | 
 |  | +					}
 | 
											
												
													
														|  | 
 |  | +					sep_pos = strlen(tmp_str);
 | 
											
												
													
														|  | 
 |  | +					filename[sep_pos] = 0;
 | 
											
												
													
														|  | 
 |  | +					conn->path_info = filename + sep_pos + 1;
 | 
											
												
													
														|  |  					*is_script_resource = 1;
 |  |  					*is_script_resource = 1;
 | 
											
												
													
														|  |  					*is_found = 1;
 |  |  					*is_found = 1;
 | 
											
												
													
														|  |  					break;
 |  |  					break;
 | 
											
												
													
														|  |  				} else {
 |  |  				} else {
 | 
											
												
													
														|  |  					/* non-script files will not have sub-resources */
 |  |  					/* non-script files will not have sub-resources */
 | 
											
												
													
														|  | 
 |  | +					filename[sep_pos] = 0;
 | 
											
												
													
														|  | 
 |  | +					conn->path_info;
 | 
											
												
													
														|  |  					*is_script_resource = 0;
 |  |  					*is_script_resource = 0;
 | 
											
												
													
														|  |  					*is_found = 0;
 |  |  					*is_found = 0;
 | 
											
												
													
														|  |  					break;
 |  |  					break;
 | 
											
												
													
														|  |  				}
 |  |  				}
 | 
											
												
													
														|  | -			} else {
 |  | 
 | 
											
												
													
														|  | -				*p = '/';
 |  | 
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			tmp_str[sep_pos] = '/';
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	mg_free(tmp_str);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
 |  |  #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
 | 
											
												
													
														|  |  #endif /* !defined(NO_FILES) */
 |  |  #endif /* !defined(NO_FILES) */
 | 
											
												
													
														|  |  	return;
 |  |  	return;
 |