Browse Source

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 years ago
parent
commit
e489ff4f05
1 changed files with 49 additions and 2 deletions
  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;
 }