Pārlūkot izejas kodu

Add configuration parameter to activate resource handling by index.cgi/lua scripts

Serving sub-resources from index.cgi is a new feature that may confusion.
See #519, in particular: see 4. from https://github.com/civetweb/civetweb/issues/519#issuecomment-329590388

Not this feature is inactive by default and must be explicitly activated
bel2125 7 gadi atpakaļ
vecāks
revīzija
03c825176c
3 mainītis faili ar 78 papildinājumiem un 44 dzēšanām
  1. 1 0
      RELEASE_NOTES.md
  2. 23 0
      docs/UserManual.md
  3. 54 44
      src/civetweb.c

+ 1 - 0
RELEASE_NOTES.md

@@ -37,6 +37,7 @@ Changes
 - Allow to compile civetweb.c wih a C++ compiler
 - Lua: Remove internal length limits of encode/decode functions
 - Allow sub-resources of index script files
+- Add config parameter allow\_index\_script\_resource the aforementioned feature
 - Remove deprecated "uri" member of the request from the interface
 - Improve documentation
 - Make auth domain check optional (configuration)

+ 23 - 0
docs/UserManual.md

@@ -602,6 +602,29 @@ This option can be used to enable or disable the use of the Linux `sendfile` sys
 ### case\_sensitive `no`
 This option can be uset to enable case URLs for Windows servers. It is only available for Windows systems. Windows file systems are not case sensitive, but they still store the file name including case. If this option is set to `yes`, the comparison for URIs and Windows file names will be case sensitive.
 
+### allow\_index\_script\_resource `no`
+Index scripts (like `index.cgi` or `index.lua`) may have script handled resources.
+
+It this feature is activated, that /some/path/file.ext might be handled by:
+  1. /some/path/file.ext (with PATH\_INFO='/', if ext = cgi)
+  2. /some/path/index.lua with mg.request\_info.path\_info='/file.ext'
+  3. /some/path/index.cgi with PATH\_INFO='/file.ext'
+  4. /some/path/index.php with PATH\_INFO='/file.ext'
+  5. /some/index.lua with mg.request\_info.path\_info=='/path/file.ext'
+  6. /some/index.cgi with PATH\_INFO='/path/file.ext'
+  7. /some/index.php with PATH\_INFO='/path/file.ext'
+  8. /index.lua with mg.request\_info.path\_info=='/some/path/file.ext'
+  9. /index.cgi with PATH\_INFO='/some/path/file.ext'
+  10. /index.php with PATH\_INFO='/some/path/file.ext'
+
+Note: This example is valid, if the default configuration values for `index_files`, `cgi_pattern` and `lua_script_pattern` are used, and the server is built with CGI and Lua support enabled.
+
+If this feature is not activated, only the first file (/some/path/file.cgi) will be accepted.
+
+Note: This parameter affects only index scripts. A path like /here/script.cgi/handle/this.ext will call /here/script.cgi with PATH\_INFO='/handle/this.ext', no matter if this option is set to `yes` or `no`. 
+
+This feature can be used to completely hide the script extension from the URL.
+
 ### additional\_header
 Send additional HTTP response header line for every request.
 The full header line including key and value must be specified, excluding the carriage return line feed.

+ 54 - 44
src/civetweb.c

@@ -2124,6 +2124,7 @@ enum {
 #endif
 	ADDITIONAL_HEADER,
 	MAX_REQUEST_SIZE,
+	ALLOW_INDEX_SCRIPT_SUB_RES,
 
 	NUM_OPTIONS
 };
@@ -2147,8 +2148,8 @@ static struct mg_option config_options[] = {
     {"index_files",
      CONFIG_TYPE_STRING_LIST,
 #ifdef USE_LUA
-     "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index."
-     "cgi,"
+     "index.xhtml,index.html,index.htm,"
+     "index.lp,index.lsp,index.lua,index.cgi,"
      "index.shtml,index.php"},
 #else
      "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
@@ -2223,6 +2224,7 @@ static struct mg_option config_options[] = {
 #endif
     {"additional_header", CONFIG_TYPE_STRING_MULTILINE, NULL},
     {"max_request_size", CONFIG_TYPE_NUMBER, "16384"},
+    {"allow_index_script_resource", CONFIG_TYPE_BOOLEAN, "no"},
 
     {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
 
@@ -3460,8 +3462,8 @@ mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
 			int def_port = ri->is_ssl ? 443 : 80;
 			int auth_domain_check_enabled =
 			    conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK]
-			    && (!strcmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],
-			                "yes"));
+			    && (!mg_strcasecmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],
+			                       "yes"));
 			const char *server_domain =
 			    conn->ctx->config[AUTHENTICATION_DOMAIN];
 
@@ -6713,6 +6715,7 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
 	char *tmp_str;
 	size_t tmp_str_len, sep_pos;
+	int allow_substitute_script_subresources;
 #endif
 #else
 	(void)filename_buf_len; /* unused if NO_FILES is defined */
@@ -6879,6 +6882,10 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
 	}
 	memcpy(tmp_str, filename, tmp_str_len + 1);
 
+	/* Check config, if index scripts may have sub-resources */
+	allow_substitute_script_subresources =
+	    !mg_strcasecmp(conn->ctx->config[ALLOW_INDEX_SCRIPT_SUB_RES], "yes");
+
 	sep_pos = tmp_str_len;
 	while (sep_pos > 0) {
 		sep_pos--;
@@ -6902,52 +6909,55 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
 				*is_found = 1;
 				break;
 			}
-			if (substitute_index_file(
-			        conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
 
-				/* some intermediate directory has an index file */
-				if (extention_matches_script(conn, tmp_str)) {
+			if (allow_substitute_script_subresources) {
+				if (substitute_index_file(
+				        conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
 
-					char *tmp_str2;
+					/* some intermediate directory has an index file */
+					if (extention_matches_script(conn, tmp_str)) {
 
-					DEBUG_TRACE("Substitute script %s serving path %s",
-					            tmp_str,
-					            filename);
+						char *tmp_str2;
 
-					/* this index file is a script */
-					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);
+						DEBUG_TRACE("Substitute script %s serving path %s",
+						            tmp_str,
+						            filename);
 
-					if (truncated) {
-						mg_free(tmp_str);
-						goto interpret_cleanup;
-					}
-					sep_pos = strlen(tmp_str);
-					filename[sep_pos] = 0;
-					conn->path_info = filename + sep_pos + 1;
-					*is_script_resource = 1;
-					*is_found = 1;
-					break;
+						/* this index file is a script */
+						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);
+							goto interpret_cleanup;
+						}
+						sep_pos = strlen(tmp_str);
+						filename[sep_pos] = 0;
+						conn->path_info = filename + sep_pos + 1;
+						*is_script_resource = 1;
+						*is_found = 1;
+						break;
 
-				} else {
+					} else {
 
-					DEBUG_TRACE("Substitute file %s serving path %s",
-					            tmp_str,
-					            filename);
+						DEBUG_TRACE("Substitute file %s serving path %s",
+						            tmp_str,
+						            filename);
 
-					/* non-script files will not have sub-resources */
-					filename[sep_pos] = 0;
-					conn->path_info = 0;
-					*is_script_resource = 0;
-					*is_found = 0;
-					break;
+						/* non-script files will not have sub-resources */
+						filename[sep_pos] = 0;
+						conn->path_info = 0;
+						*is_script_resource = 0;
+						*is_found = 0;
+						break;
+					}
 				}
 			}
 
@@ -15126,7 +15136,7 @@ get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
 	char *portend;
 
 	auth_domain_check_enabled =
-	    !strcmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes");
+	    !mg_strcasecmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes");
 
 	if (!auth_domain_check_enabled) {
 		return 0;
@@ -15733,7 +15743,7 @@ init_connection(struct mg_connection *conn)
 {
 	/* Is keep alive allowed by the server */
 	int keep_alive_enabled =
-	    !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
+	    !mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
 
 	if (!keep_alive_enabled) {
 		conn->must_close = 1;