소스 검색

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,
             void *user_data)
 {
+#ifdef _WIN32
+	char temppath[MAX_PATH + 2];
+	DWORD temppathlen;
+#endif
+
 	struct mg_connection *conn = (struct mg_connection *)user_data;
 
 	mg_printf(conn, "\r\n\r\n%s:\r\n", key);
 
 	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
-		_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
 		snprintf(path, pathlen, "/tmp/%s", filename);
 #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;
 }