|  | @@ -5725,11 +5725,70 @@ extention_matches_script(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* For given directory path, substitute it to valid index file.
 | 
	
		
			
				|  |  | + * Return 1 if index file has been found, 0 if not found.
 | 
	
		
			
				|  |  | + * If the file is found, it's stats is returned in stp. */
 | 
	
		
			
				|  |  | +static int
 | 
	
		
			
				|  |  | +substitute_index_file(struct mg_connection *conn,
 | 
	
		
			
				|  |  | +                      char *path,
 | 
	
		
			
				|  |  | +                      size_t path_len,
 | 
	
		
			
				|  |  | +                      struct mg_file_stat *filestat)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +#if !defined(NO_FILES)
 | 
	
		
			
				|  |  | +	const char *list = conn->ctx->config[INDEX_FILES];
 | 
	
		
			
				|  |  | +	struct vec filename_vec;
 | 
	
		
			
				|  |  | +	size_t n = strlen(path);
 | 
	
		
			
				|  |  | +	int found = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* The 'path' given to us points to the directory. Remove all trailing
 | 
	
		
			
				|  |  | +	 * directory separator characters from the end of the path, and
 | 
	
		
			
				|  |  | +	 * then append single directory separator character. */
 | 
	
		
			
				|  |  | +	while (n > 0 && path[n - 1] == '/') {
 | 
	
		
			
				|  |  | +		n--;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	path[n] = '/';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Traverse index files list. For each entry, append it to the given
 | 
	
		
			
				|  |  | +	 * path and see if the file exists. If it exists, break the loop */
 | 
	
		
			
				|  |  | +	while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
 | 
	
		
			
				|  |  | +		/* Ignore too long entries that may overflow path buffer */
 | 
	
		
			
				|  |  | +		if (filename_vec.len > path_len - (n + 2)) {
 | 
	
		
			
				|  |  | +			continue;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* Prepare full path to the index file */
 | 
	
		
			
				|  |  | +		mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* Does it exist? */
 | 
	
		
			
				|  |  | +		if (mg_stat(conn, path, filestat)) {
 | 
	
		
			
				|  |  | +			/* Yes it does, break the loop */
 | 
	
		
			
				|  |  | +			found = 1;
 | 
	
		
			
				|  |  | +			break;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* If no index file exists, restore directory path */
 | 
	
		
			
				|  |  | +	if (!found) {
 | 
	
		
			
				|  |  | +		path[n] = '\0';
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return found;
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +	(void)conn;
 | 
	
		
			
				|  |  | +	(void)path;
 | 
	
		
			
				|  |  | +	(void)path_len;
 | 
	
		
			
				|  |  | +	(void)filep;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 | 
	
		
			
				|  |  |                char *filename,                /* out: filename */
 | 
	
		
			
				|  |  |                size_t filename_buf_len,       /* in: size of filename buffer */
 | 
	
		
			
				|  |  | -              struct mg_file_stat *filestat, /* out: file structure */
 | 
	
		
			
				|  |  | +              struct mg_file_stat *filestat, /* out: file status structure */
 | 
	
		
			
				|  |  |                int *is_found,                 /* out: file found (directly) */
 | 
	
		
			
				|  |  |                int *is_script_resource,       /* out: handled by a script? */
 | 
	
		
			
				|  |  |                int *is_websocket_request,     /* out: websocket connetion? */
 | 
	
	
		
			
				|  | @@ -5813,7 +5872,6 @@ interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 | 
	
		
			
				|  |  |  	/* Local file path and name, corresponding to requested URI
 | 
	
		
			
				|  |  |  	 * is now stored in "filename" variable. */
 | 
	
		
			
				|  |  |  	if (mg_stat(conn, filename, filestat)) {
 | 
	
		
			
				|  |  | -#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 | 
	
		
			
				|  |  |  		/* File exists. Check if it is a script type. */
 | 
	
		
			
				|  |  |  		if (extention_matches_script(conn, filename)) {
 | 
	
		
			
				|  |  |  			/* The request addresses a CGI script or a Lua script. The URI
 | 
	
	
		
			
				|  | @@ -5828,8 +5886,29 @@ interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 | 
	
		
			
				|  |  |  			 * generated response. */
 | 
	
		
			
				|  |  |  			*is_script_resource = (!*is_put_or_delete_request);
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -#endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		*is_found = 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		/* If the request target is a directory,
 | 
	
		
			
				|  |  | +		 * there could be a substitute file
 | 
	
		
			
				|  |  | +		 * (index.html, index.cgi, ...). */
 | 
	
		
			
				|  |  | +		if (filestat->is_directory) {
 | 
	
		
			
				|  |  | +			if (substitute_index_file(
 | 
	
		
			
				|  |  | +			        conn, filename, filename_buf_len, filestat)) {
 | 
	
		
			
				|  |  | +				/* Substitute file found. It could ba a script file */
 | 
	
		
			
				|  |  | +				if (extention_matches_script(conn, filename)) {
 | 
	
		
			
				|  |  | +					/* Substitute file is a script file */
 | 
	
		
			
				|  |  | +					*is_script_resource = 1;
 | 
	
		
			
				|  |  | +				} else {
 | 
	
		
			
				|  |  | +					/* Substitute file is a regular file */
 | 
	
		
			
				|  |  | +					*is_script_resource = 0;
 | 
	
		
			
				|  |  | +					*is_found = (mg_stat(conn, filename, filestat) ? 1 : 0);
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			/* If there is no substitute file, the server could return
 | 
	
		
			
				|  |  | +			 * a directory listing in a later step */
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -8196,62 +8275,6 @@ read_request(FILE *fp,
 | 
	
		
			
				|  |  |  	return request_len;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#if !defined(NO_FILES)
 | 
	
		
			
				|  |  | -/* For given directory path, substitute it to valid index file.
 | 
	
		
			
				|  |  | - * Return 1 if index file has been found, 0 if not found.
 | 
	
		
			
				|  |  | - * If the file is found, it's stats is returned in stp. */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -substitute_index_file(struct mg_connection *conn,
 | 
	
		
			
				|  |  | -                      char *path,
 | 
	
		
			
				|  |  | -                      size_t path_len,
 | 
	
		
			
				|  |  | -                      struct mg_file *filep)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	if (conn && conn->ctx) {
 | 
	
		
			
				|  |  | -		const char *list = conn->ctx->config[INDEX_FILES];
 | 
	
		
			
				|  |  | -		struct mg_file file = STRUCT_FILE_INITIALIZER;
 | 
	
		
			
				|  |  | -		struct vec filename_vec;
 | 
	
		
			
				|  |  | -		size_t n = strlen(path);
 | 
	
		
			
				|  |  | -		int found = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		/* The 'path' given to us points to the directory. Remove all trailing
 | 
	
		
			
				|  |  | -		 * directory separator characters from the end of the path, and
 | 
	
		
			
				|  |  | -		 * then append single directory separator character. */
 | 
	
		
			
				|  |  | -		while (n > 0 && path[n - 1] == '/') {
 | 
	
		
			
				|  |  | -			n--;
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		path[n] = '/';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		/* Traverse index files list. For each entry, append it to the given
 | 
	
		
			
				|  |  | -		 * path and see if the file exists. If it exists, break the loop */
 | 
	
		
			
				|  |  | -		while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
 | 
	
		
			
				|  |  | -			/* Ignore too long entries that may overflow path buffer */
 | 
	
		
			
				|  |  | -			if (filename_vec.len > path_len - (n + 2)) {
 | 
	
		
			
				|  |  | -				continue;
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			/* Prepare full path to the index file */
 | 
	
		
			
				|  |  | -			mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -			/* Does it exist? */
 | 
	
		
			
				|  |  | -			if (mg_stat(conn, path, &file.stat)) {
 | 
	
		
			
				|  |  | -				/* Yes it does, break the loop */
 | 
	
		
			
				|  |  | -				*filep = file;
 | 
	
		
			
				|  |  | -				found = 1;
 | 
	
		
			
				|  |  | -				break;
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		/* If no index file exists, restore directory path */
 | 
	
		
			
				|  |  | -		if (!found) {
 | 
	
		
			
				|  |  | -			path[n] = '\0';
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		return found;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if !defined(NO_CACHING)
 | 
	
		
			
				|  |  |  /* Return True if we should reply 304 Not Modified. */
 | 
	
	
		
			
				|  | @@ -11040,27 +11063,6 @@ handle_request(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  		              &is_script_resource,
 | 
	
		
			
				|  |  |  		              &is_websocket_request,
 | 
	
		
			
				|  |  |  		              &is_put_or_delete_request);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -		/* 5.2.3. If the request target is a directory,
 | 
	
		
			
				|  |  | -		 * there could be a substitute file
 | 
	
		
			
				|  |  | -		 * (index.html, index.cgi, ...). */
 | 
	
		
			
				|  |  | -#if !defined(NO_FILES)
 | 
	
		
			
				|  |  | -		if (file.stat.is_directory) {
 | 
	
		
			
				|  |  | -			if (substitute_index_file(conn, path, sizeof(path), &file)) {
 | 
	
		
			
				|  |  | -				/* 5.2.4. Substitute file found. It could ba a script file */
 | 
	
		
			
				|  |  | -				if (extention_matches_script(conn, path)) {
 | 
	
		
			
				|  |  | -					/* 5.2.5. Substitute file is a script file */
 | 
	
		
			
				|  |  | -					is_script_resource = 1;
 | 
	
		
			
				|  |  | -				} else {
 | 
	
		
			
				|  |  | -					/* 5.2.6. Substitute file is a regular file */
 | 
	
		
			
				|  |  | -					is_script_resource = 0;
 | 
	
		
			
				|  |  | -					is_found = (mg_stat(conn, path, &(file.stat)) ? 1 : 0);
 | 
	
		
			
				|  |  | -				}
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -			/* If there is no substitute file, the server could return
 | 
	
		
			
				|  |  | -			 * a directory listing in a later step */
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* 6. authorization check */
 |