Improvements for #2221 - validate file extensions client-side before initiating upload, valid file extension server-side before writing part to disk, optimize cleanup logic, add error handling to JavaScript XMLHttpRequest, ensure FileInput gets initialized after upload
This commit is contained in:
parent
43c34fcd64
commit
ea5655ae42
@ -310,6 +310,17 @@
|
|||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var upload = await interop.GetFiles(_fileinputid);
|
var upload = await interop.GetFiles(_fileinputid);
|
||||||
if (upload.Length > 0)
|
if (upload.Length > 0)
|
||||||
|
{
|
||||||
|
string restricted = "";
|
||||||
|
foreach (var file in upload)
|
||||||
|
{
|
||||||
|
var extension = (file.LastIndexOf(".") != -1) ? file.Substring(file.LastIndexOf(".") + 1) : "";
|
||||||
|
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
|
||||||
|
{
|
||||||
|
restricted += (restricted == "" ? "" : ",") + extension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (restricted == "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -360,6 +371,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_message = string.Format(Localizer["Message.File.Restricted"], restricted);
|
||||||
|
_messagetype = MessageType.Warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.File.NotSelected"];
|
_message = Localizer["Message.File.NotSelected"];
|
||||||
_messagetype = MessageType.Warning;
|
_messagetype = MessageType.Warning;
|
||||||
|
@ -141,4 +141,7 @@
|
|||||||
<data name="Success.File.Upload" xml:space="preserve">
|
<data name="Success.File.Upload" xml:space="preserve">
|
||||||
<value>File Upload Succeeded</value>
|
<value>File Upload Succeeded</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.File.Restricted" xml:space="preserve">
|
||||||
|
<value>Files With Extension Of {0} Are Restricted From Upload. Please Contact Your Administrator For More Information.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -276,9 +276,17 @@ namespace Oqtane.Controllers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formfile.FileName.IsPathOrFileValid())
|
// ensure filename is valid
|
||||||
|
string token = ".part_";
|
||||||
|
if (!formfile.FileName.IsPathOrFileValid() || !formfile.FileName.Contains(token))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for allowable file extensions (ignore token)
|
||||||
|
var extension = Path.GetExtension(formfile.FileName.Substring(0, formfile.FileName.IndexOf(token))).Replace(".", "");
|
||||||
|
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
|
||||||
{
|
{
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,9 +339,9 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
string merged = "";
|
string merged = "";
|
||||||
|
|
||||||
// parse the filename which is in the format of filename.ext.part_x_y
|
// parse the filename which is in the format of filename.ext.part_001_999
|
||||||
string token = ".part_";
|
string token = ".part_";
|
||||||
string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y"
|
string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "001_999"
|
||||||
int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1));
|
int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1));
|
||||||
|
|
||||||
filename = Path.GetFileNameWithoutExtension(filename); // base filename
|
filename = Path.GetFileNameWithoutExtension(filename); // base filename
|
||||||
@ -370,13 +378,6 @@ namespace Oqtane.Controllers
|
|||||||
System.IO.File.Delete(filepart);
|
System.IO.File.Delete(filepart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for allowable file extensions
|
|
||||||
if (!Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(filename)?.ToLower().Replace(".", "")))
|
|
||||||
{
|
|
||||||
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// remove file if it already exists
|
// remove file if it already exists
|
||||||
if (System.IO.File.Exists(Path.Combine(folder, filename)))
|
if (System.IO.File.Exists(Path.Combine(folder, filename)))
|
||||||
{
|
{
|
||||||
@ -386,7 +387,6 @@ namespace Oqtane.Controllers
|
|||||||
// rename file now that the entire process is completed
|
// rename file now that the entire process is completed
|
||||||
System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename));
|
System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename));
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename));
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename));
|
||||||
}
|
|
||||||
|
|
||||||
merged = filename;
|
merged = filename;
|
||||||
}
|
}
|
||||||
@ -394,8 +394,7 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
// clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed )
|
// clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed )
|
||||||
var cleanupFiles = Directory.EnumerateFiles(folder, "*" + token + "*")
|
var cleanupFiles = Directory.EnumerateFiles(folder, "*" + token + "*")
|
||||||
.Where(f => Path.GetExtension(f).StartsWith(token));
|
.Where(f => Path.GetExtension(f).StartsWith(token) && !Path.GetFileName(f).StartsWith(filename));
|
||||||
|
|
||||||
foreach (var file in cleanupFiles)
|
foreach (var file in cleanupFiles)
|
||||||
{
|
{
|
||||||
var createdDate = System.IO.File.GetCreationTime(file).ToUniversalTime();
|
var createdDate = System.IO.File.GetCreationTime(file).ToUniversalTime();
|
||||||
|
@ -344,10 +344,17 @@ Oqtane.Interop = {
|
|||||||
progressinfo.innerHTML = file.name + ' 100%';
|
progressinfo.innerHTML = file.name + ' 100%';
|
||||||
progressbar.value = 1;
|
progressbar.value = 1;
|
||||||
};
|
};
|
||||||
|
request.upload.onerror = function () {
|
||||||
|
progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
|
||||||
|
progressbar.value = 0;
|
||||||
|
};
|
||||||
request.send(data);
|
request.send(data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (i === files.length - 1) {
|
||||||
fileinput.value = '';
|
fileinput.value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
refreshBrowser: function (reload, wait) {
|
refreshBrowser: function (reload, wait) {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user