[DONT MERGE] give a spec to input files
This commit is contained in:
parent
5e233b5020
commit
742796c592
12 changed files with 67 additions and 44 deletions
30
Yavsc.Abstract/FileSystem/FileSystemHelpers.cs
Normal file
30
Yavsc.Abstract/FileSystem/FileSystemHelpers.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Yavsc.Abstract.FileSystem
|
||||||
|
{
|
||||||
|
public static class FileSystemHelpers
|
||||||
|
{
|
||||||
|
public static bool IsValidYavscPath(this string path)
|
||||||
|
{
|
||||||
|
if (path == null) return true;
|
||||||
|
foreach (var name in path.Split('/'))
|
||||||
|
{
|
||||||
|
if (!IsValidDirectoryName(name) || name.Equals("..") || name.Equals("."))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (path[path.Length]==FileSystemConstants.RemoteDirectorySeparator) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public static bool IsValidDirectoryName(this string name)
|
||||||
|
{
|
||||||
|
return !name.Any(c => !FileSystemConstants.ValidFileNameChars.Contains(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FileSystemConstants
|
||||||
|
{
|
||||||
|
public const char RemoteDirectorySeparator = '/';
|
||||||
|
public static char[] ValidFileNameChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_~. ".ToCharArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Yavsc.Helpers;
|
using Yavsc.Abstract.FileSystem;
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.UserFiles
|
namespace Yavsc.ViewModels.UserFiles
|
||||||
{
|
{
|
||||||
|
|
@ -9,14 +9,14 @@ namespace Yavsc.ViewModels.UserFiles
|
||||||
{
|
{
|
||||||
public string UserName { get; private set; }
|
public string UserName { get; private set; }
|
||||||
public string SubPath { get; private set; }
|
public string SubPath { get; private set; }
|
||||||
public DefaultFileInfo [] Files {
|
public RemoteFileInfo [] Files {
|
||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
public string [] SubDirectories {
|
public string [] SubDirectories {
|
||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
private DirectoryInfo dInfo;
|
private DirectoryInfo dInfo;
|
||||||
public UserDirectoryInfo(string username, string path)
|
public UserDirectoryInfo(string userReposPath, string username, string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(username))
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
throw new NotSupportedException("No user name, no user dir.");
|
throw new NotSupportedException("No user name, no user dir.");
|
||||||
|
|
@ -24,15 +24,15 @@ namespace Yavsc.ViewModels.UserFiles
|
||||||
var finalPath = username;
|
var finalPath = username;
|
||||||
if (!string.IsNullOrWhiteSpace(path))
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
finalPath += Path.DirectorySeparatorChar + path;
|
finalPath += Path.DirectorySeparatorChar + path;
|
||||||
if (!finalPath.IsValidPath())
|
if (!finalPath.IsValidYavscPath())
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
$"File name contains invalid chars, using path {finalPath}");
|
$"File name contains invalid chars, using path {finalPath}");
|
||||||
|
|
||||||
dInfo = new DirectoryInfo(
|
dInfo = new DirectoryInfo(
|
||||||
Startup.UserFilesDirName+Path.DirectorySeparatorChar+finalPath);
|
userReposPath+FileSystemConstants.RemoteDirectorySeparator+finalPath);
|
||||||
if (!dInfo.Exists) dInfo.Create();
|
if (!dInfo.Exists) dInfo.Create();
|
||||||
Files = dInfo.GetFiles().Select
|
Files = dInfo.GetFiles().Select
|
||||||
( entry => new DefaultFileInfo { Name = entry.Name, Size = entry.Length,
|
( entry => new RemoteFileInfo { Name = entry.Name, Size = entry.Length,
|
||||||
CreationTime = entry.CreationTime, LastModified = entry.LastWriteTime }).ToArray();
|
CreationTime = entry.CreationTime, LastModified = entry.LastWriteTime }).ToArray();
|
||||||
SubDirectories = dInfo.GetDirectories().Select
|
SubDirectories = dInfo.GetDirectories().Select
|
||||||
( d=> d.Name ).ToArray();
|
( d=> d.Name ).ToArray();
|
||||||
|
|
@ -2,7 +2,7 @@ using System;
|
||||||
|
|
||||||
namespace Yavsc.ViewModels
|
namespace Yavsc.ViewModels
|
||||||
{
|
{
|
||||||
public class DefaultFileInfo
|
public class RemoteFileInfo
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
|
@ -10,6 +10,7 @@ using Yavsc.Models;
|
||||||
namespace Yavsc.ApiControllers
|
namespace Yavsc.ApiControllers
|
||||||
{
|
{
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Yavsc.Abstract.FileSystem;
|
||||||
using Yavsc.Exceptions;
|
using Yavsc.Exceptions;
|
||||||
public class FSQuotaException : Exception {
|
public class FSQuotaException : Exception {
|
||||||
|
|
||||||
|
|
@ -38,16 +39,17 @@ namespace Yavsc.ApiControllers
|
||||||
public IActionResult GetDir(string subdir="")
|
public IActionResult GetDir(string subdir="")
|
||||||
{
|
{
|
||||||
if (subdir !=null)
|
if (subdir !=null)
|
||||||
if (!FileSystemHelpers.IsValidPath(subdir))
|
if (!subdir.IsValidYavscPath())
|
||||||
return new BadRequestResult();
|
return new BadRequestResult();
|
||||||
var files = User.GetUserFiles(subdir);
|
var files = User.GetUserFiles(subdir);
|
||||||
return Ok(files);
|
return Ok(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IEnumerable<IActionResult> Post(string subdir="")
|
public IEnumerable<IActionResult> Post(string subdir="", string names = null)
|
||||||
{
|
{
|
||||||
string root = null;
|
string root = null;
|
||||||
|
string [] destinationFileNames = names?.Split('/');
|
||||||
|
|
||||||
InvalidPathException pathex = null;
|
InvalidPathException pathex = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -61,10 +63,12 @@ namespace Yavsc.ApiControllers
|
||||||
var user = dbContext.Users.Single(
|
var user = dbContext.Users.Single(
|
||||||
u => u.Id == User.GetUserId()
|
u => u.Id == User.GetUserId()
|
||||||
);
|
);
|
||||||
|
int i=0;
|
||||||
foreach (var f in Request.Form.Files)
|
foreach (var f in Request.Form.Files)
|
||||||
{
|
{
|
||||||
var item = user.ReceiveUserFile(root, f);
|
var destFileName = destinationFileNames?.Length >i ? destinationFileNames[i] : null;
|
||||||
|
|
||||||
|
var item = user.ReceiveUserFile(root, f, destFileName);
|
||||||
dbContext.SaveChanges(User.GetUserId());
|
dbContext.SaveChanges(User.GetUserId());
|
||||||
yield return Ok(item);
|
yield return Ok(item);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Yavsc
|
||||||
AvatarsPath = "/avatars",
|
AvatarsPath = "/avatars",
|
||||||
DefaultAvatar = "/images/Users/icon_user.png",
|
DefaultAvatar = "/images/Users/icon_user.png",
|
||||||
AnonAvatar = "/images/Users/icon_anon_user.png";
|
AnonAvatar = "/images/Users/icon_anon_user.png";
|
||||||
public static char[] ValidChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_~. ".ToCharArray();
|
|
||||||
public static readonly long DefaultFSQ = 1024*1024*500;
|
public static readonly long DefaultFSQ = 1024*1024*500;
|
||||||
|
|
||||||
public static readonly Scope[] SiteScopes = {
|
public static readonly Scope[] SiteScopes = {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.OptionsModel;
|
using Microsoft.Extensions.OptionsModel;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Yavsc.Helpers;
|
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Services;
|
using Yavsc.Services;
|
||||||
using Yavsc.ViewModels.Account;
|
using Yavsc.ViewModels.Account;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -13,10 +12,8 @@ using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.OptionsModel;
|
using Microsoft.Extensions.OptionsModel;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using OAuth.AspNet.AuthServer;
|
using OAuth.AspNet.AuthServer;
|
||||||
using Yavsc.Helpers;
|
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Models.Auth;
|
using Yavsc.Models.Auth;
|
||||||
using Yavsc.ViewModels.Account;
|
|
||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Yavsc.Abstract.FileSystem;
|
||||||
using Yavsc.Exceptions;
|
using Yavsc.Exceptions;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Models.FileSystem;
|
using Yavsc.Models.FileSystem;
|
||||||
|
|
@ -20,33 +22,30 @@ namespace Yavsc.Helpers
|
||||||
public static class FileSystemHelpers
|
public static class FileSystemHelpers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static UserDirectoryInfo GetUserFiles(this ClaimsPrincipal user, string subdir)
|
public static UserDirectoryInfo GetUserFiles(this ClaimsPrincipal user, string subdir)
|
||||||
{
|
{
|
||||||
|
|
||||||
UserDirectoryInfo di = new UserDirectoryInfo(user.Identity.Name, subdir);
|
UserDirectoryInfo di = new UserDirectoryInfo(Startup.UserFilesDirName, user.Identity.Name, subdir);
|
||||||
|
|
||||||
return di;
|
return di;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static bool IsValidDirectoryName(this string name)
|
|
||||||
{
|
|
||||||
return !name.Any(c => !Constants.ValidChars.Contains(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure this path is canonical,
|
// Ensure this path is canonical,
|
||||||
// No "dirto/./this", neither "dirt/to/that/"
|
// No "dirto/./this", neither "dirt/to/that/"
|
||||||
// no .. and each char must be listed as valid in constants
|
// no .. and each char must be listed as valid in constants
|
||||||
public static bool IsValidPath(this string path)
|
|
||||||
|
public static string FilterFileName(string fileName)
|
||||||
{
|
{
|
||||||
if (path == null) return true;
|
if (fileName==null) return null;
|
||||||
foreach (var name in path.Split(Path.DirectorySeparatorChar))
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (var c in fileName)
|
||||||
{
|
{
|
||||||
if (!IsValidDirectoryName(name) || name.Equals("..") || name.Equals("."))
|
if (FileSystemConstants.ValidFileNameChars.Contains(c))
|
||||||
return false;
|
sb.Append(c);
|
||||||
|
else sb.Append('_');
|
||||||
}
|
}
|
||||||
if (path.EndsWith($"{Path.DirectorySeparatorChar}")) return false;
|
return sb.ToString();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
public static string InitPostToFileSystem(
|
public static string InitPostToFileSystem(
|
||||||
this ClaimsPrincipal user,
|
this ClaimsPrincipal user,
|
||||||
|
|
@ -56,7 +55,7 @@ namespace Yavsc.Helpers
|
||||||
var diRoot = new DirectoryInfo(root);
|
var diRoot = new DirectoryInfo(root);
|
||||||
if (!diRoot.Exists) diRoot.Create();
|
if (!diRoot.Exists) diRoot.Create();
|
||||||
if (!string.IsNullOrWhiteSpace(subpath)) {
|
if (!string.IsNullOrWhiteSpace(subpath)) {
|
||||||
if (!subpath.IsValidPath())
|
if (!subpath.IsValidYavscPath())
|
||||||
{
|
{
|
||||||
throw new InvalidPathException();
|
throw new InvalidPathException();
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +65,7 @@ namespace Yavsc.Helpers
|
||||||
if (!di.Exists) di.Create();
|
if (!di.Exists) di.Create();
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DeleteUserFile(this ApplicationUser user, string fileName)
|
public static void DeleteUserFile(this ApplicationUser user, string fileName)
|
||||||
{
|
{
|
||||||
var root = Path.Combine(Startup.UserFilesDirName, user.UserName);
|
var root = Path.Combine(Startup.UserFilesDirName, user.UserName);
|
||||||
|
|
@ -74,14 +74,14 @@ namespace Yavsc.Helpers
|
||||||
fi.Delete();
|
fi.Delete();
|
||||||
user.DiskUsage -= fi.Length;
|
user.DiskUsage -= fi.Length;
|
||||||
}
|
}
|
||||||
public static FileRecievedInfo ReceiveUserFile(this ApplicationUser user, string root, IFormFile f)
|
public static FileRecievedInfo ReceiveUserFile(this ApplicationUser user, string root, IFormFile f, string destFileName = null)
|
||||||
{
|
{
|
||||||
long usage = user.DiskUsage;
|
long usage = user.DiskUsage;
|
||||||
|
|
||||||
var item = new FileRecievedInfo();
|
var item = new FileRecievedInfo();
|
||||||
// form-data; name="file"; filename="capt0008.jpg"
|
// form-data; name="file"; filename="capt0008.jpg"
|
||||||
ContentDisposition contentDisposition = new ContentDisposition(f.ContentDisposition);
|
ContentDisposition contentDisposition = new ContentDisposition(f.ContentDisposition);
|
||||||
item.FileName = contentDisposition.FileName;
|
item.FileName = FilterFileName (destFileName ?? contentDisposition.FileName);
|
||||||
item.MimeType = contentDisposition.DispositionType;
|
item.MimeType = contentDisposition.DispositionType;
|
||||||
var fi = new FileInfo(Path.Combine(root, item.FileName));
|
var fi = new FileInfo(Path.Combine(root, item.FileName));
|
||||||
if (fi.Exists) item.Overriden = true;
|
if (fi.Exists) item.Overriden = true;
|
||||||
|
|
@ -111,7 +111,7 @@ namespace Yavsc.Helpers
|
||||||
user.DiskUsage = usage;
|
user.DiskUsage = usage;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
public static HtmlString FileLink(this DefaultFileInfo info, string username, string subpath)
|
public static HtmlString FileLink(this RemoteFileInfo info, string username, string subpath)
|
||||||
{
|
{
|
||||||
return new HtmlString( Startup.UserFilesOptions.RequestPath+"/"+ username + "/" + subpath + "/" +
|
return new HtmlString( Startup.UserFilesOptions.RequestPath+"/"+ username + "/" + subpath + "/" +
|
||||||
HttpUtility.UrlEncode(info.Name) );
|
HttpUtility.UrlEncode(info.Name) );
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Data.Entity;
|
using Microsoft.Data.Entity;
|
||||||
using Microsoft.Data.Entity.Infrastructure;
|
using Microsoft.Data.Entity.Infrastructure;
|
||||||
using Microsoft.Data.Entity.Metadata;
|
|
||||||
using Microsoft.Data.Entity.Migrations;
|
using Microsoft.Data.Entity.Migrations;
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.Data.Entity.Migrations;
|
using Microsoft.Data.Entity.Migrations;
|
||||||
|
|
||||||
namespace Yavsc.Migrations
|
namespace Yavsc.Migrations
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace Yavsc.ViewComponents
|
||||||
IViewComponentResult result = null;
|
IViewComponentResult result = null;
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
result = View(new UserDirectoryInfo(User.Identity.Name, dirname));
|
result = View(new UserDirectoryInfo(Startup.UserFilesDirName, User.Identity.Name, dirname));
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
using System;
|
namespace Yavsc.Models.Auth
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Yavsc.Models.Auth
|
|
||||||
{
|
{
|
||||||
public class Me : IApplicationUser {
|
public class Me : IApplicationUser {
|
||||||
public Me(ApplicationUser user)
|
public Me(ApplicationUser user)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue