Browse Source

Replace string manipulation algorithm in interpret_uri

bel 8 năm trước cách đây
mục cha
commit
a457e918d0
1 tập tin đã thay đổi với 59 bổ sung20 xóa
  1. 59 20
      src/civetweb.c

+ 59 - 20
src/civetweb.c

@@ -5798,7 +5798,8 @@ interpret_uri(struct mg_connection *conn,    /* in: request (must be valid) */
 	char const *accept_encoding;
 	int truncated;
 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
-	char *p;
+	char *tmp_str;
+	size_t tmp_str_len, sep_pos;
 #endif
 #else
 	(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)
 	/* Step 9: Script resources may handle sub-resources */
 	/* 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_found = 1;
 				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 */
-				if (extention_matches_script(conn, filename)) {
+				if (extention_matches_script(conn, tmp_str)) {
 					/* 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_found = 1;
 					break;
 				} else {
 					/* non-script files will not have sub-resources */
+					filename[sep_pos] = 0;
+					conn->path_info;
 					*is_script_resource = 0;
 					*is_found = 0;
 					break;
 				}
-			} else {
-				*p = '/';
 			}
+
+			tmp_str[sep_pos] = '/';
 		}
 	}
+
+	mg_free(tmp_str);
+
 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
 #endif /* !defined(NO_FILES) */
 	return;