|  | @@ -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;
 | 
											
												
													
														|  |  }
 |  |  }
 |