浏览代码

handle_form example: Upload to temporary directory and do some filename checks

For Windows, determine the temporary directory from the GetTempPath API.

According to RFC7578, path information should be ignored and you should not
overwrite existing files.
bel2125 4 年之前
父节点
当前提交
e489ff4f05
共有 1 个文件被更改,包括 49 次插入2 次删除
  1. 49 2
      examples/embedded_c/embedded_c.c

+ 49 - 2
examples/embedded_c/embedded_c.c

@@ -286,17 +286,64 @@ field_found(const char *key,
             size_t pathlen,
             size_t pathlen,
             void *user_data)
             void *user_data)
 {
 {
+#ifdef _WIN32
+	char temppath[MAX_PATH + 2];
+	DWORD temppathlen;
+#endif
+
 	struct mg_connection *conn = (struct mg_connection *)user_data;
 	struct mg_connection *conn = (struct mg_connection *)user_data;
 
 
 	mg_printf(conn, "\r\n\r\n%s:\r\n", key);
 	mg_printf(conn, "\r\n\r\n%s:\r\n", key);
 
 
 	if (filename && *filename) {
 	if (filename && *filename) {
+
+		/* According to
+		 * https://datatracker.ietf.org/doc/html/rfc7578#section-4.2: Do not use
+		 * path information present in the filename. Drop all "/" (and "\" for
+		 * Windows).
+		 */
+		char *sep = strrchr(filename, '/');
+		if (sep) {
+			memmove(filename, sep + 1, strlen(sep));
+		}
+
 #ifdef _WIN32
 #ifdef _WIN32
-		_snprintf(path, pathlen, "D:\\tmp\\%s", filename);
+		sep = strrchr(filename, '\\');
+		if (sep) {
+			memmove(filename, sep + 1, strlen(sep));
+		}
+
+		/* For Windows: Find the directory for temporary files */
+		temppathlen = GetTempPathA(sizeof(temppath), temppath);
+		if (temppathlen > 0) {
+			_snprintf(path, pathlen, "%s\\%s", temppath, filename);
+		} else {
+			_snprintf(path, pathlen, "C:\\tmp\\%s", filename);
+		}
 #else
 #else
 		snprintf(path, pathlen, "/tmp/%s", filename);
 		snprintf(path, pathlen, "/tmp/%s", filename);
 #endif
 #endif
-		return MG_FORM_FIELD_STORAGE_STORE;
+
+		/* According to https://datatracker.ietf.org/doc/html/rfc7578#section-7:
+		 * Do not overwrite existing files.
+		 */
+		{
+			FILE *ftest = fopen(path, "r");
+			if (!ftest) {
+				return MG_FORM_FIELD_STORAGE_STORE;
+			}
+			fclose(ftest);
+			/* This is just simple demo code. More sophisticated code could add
+			 * numbers to the file name to make filenames unique. However, most
+			 * likely file upload will not end up in the temporary path, but in
+			 * a user directory - multiple directories for multiple users that
+			 * are logged into the web service. In this case, users might want
+			 * to overwrite their own code. You need to adapt this example to
+			 * your needs.
+			 */
+		}
+
+		return MG_FORM_FIELD_STORAGE_SKIP;
 	}
 	}
 	return MG_FORM_FIELD_STORAGE_GET;
 	return MG_FORM_FIELD_STORAGE_GET;
 }
 }