[DONT MERGE] give a spec to input files

vnext
Paul Schneider 7 years ago
parent 26a1caf088
commit 8d09f50f22
12 changed files with 67 additions and 44 deletions

@ -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.IO;
using System.Linq;
using Yavsc.Helpers;
using Yavsc.Abstract.FileSystem;
namespace Yavsc.ViewModels.UserFiles
{
@ -9,14 +9,14 @@ namespace Yavsc.ViewModels.UserFiles
{
public string UserName { get; private set; }
public string SubPath { get; private set; }
public DefaultFileInfo [] Files {
public RemoteFileInfo [] Files {
get; private set;
}
public string [] SubDirectories { 
get; private set;
}
private DirectoryInfo dInfo;
public UserDirectoryInfo(string username, string path)
public UserDirectoryInfo(string userReposPath, string username, string path)
{
if (string.IsNullOrWhiteSpace(username))
throw new NotSupportedException("No user name, no user dir.");
@ -24,15 +24,15 @@ namespace Yavsc.ViewModels.UserFiles
var finalPath = username;
if (!string.IsNullOrWhiteSpace(path))
finalPath += Path.DirectorySeparatorChar + path;
if (!finalPath.IsValidPath())
if (!finalPath.IsValidYavscPath())
throw new InvalidOperationException(
$"File name contains invalid chars, using path {finalPath}");
dInfo = new DirectoryInfo(
Startup.UserFilesDirName+Path.DirectorySeparatorChar+finalPath);
userReposPath+FileSystemConstants.RemoteDirectorySeparator+finalPath);
if (!dInfo.Exists) dInfo.Create();
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();
SubDirectories = dInfo.GetDirectories().Select
( d=> d.Name ).ToArray();

@ -2,7 +2,7 @@ using System;
namespace Yavsc.ViewModels
{
public class DefaultFileInfo
public class RemoteFileInfo
{
public string Name { get; set; }

@ -10,6 +10,7 @@ using Yavsc.Models;
namespace Yavsc.ApiControllers
{
using System.Threading.Tasks;
using Yavsc.Abstract.FileSystem;
using Yavsc.Exceptions;
public class FSQuotaException : Exception {
@ -38,16 +39,17 @@ namespace Yavsc.ApiControllers
public IActionResult GetDir(string subdir="")
{
if (subdir !=null)
if (!FileSystemHelpers.IsValidPath(subdir))
if (!subdir.IsValidYavscPath())
return new BadRequestResult();
var files = User.GetUserFiles(subdir);
return Ok(files);
}
[HttpPost]
public IEnumerable<IActionResult> Post(string subdir="")
public IEnumerable<IActionResult> Post(string subdir="", string names = null)
{
string root = null;
string [] destinationFileNames = names?.Split('/');
InvalidPathException pathex = null;
try {
@ -61,10 +63,12 @@ namespace Yavsc.ApiControllers
var user = dbContext.Users.Single(
u => u.Id == User.GetUserId()
);
int i=0;
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());
yield return Ok(item);
};

@ -30,7 +30,7 @@ namespace Yavsc
AvatarsPath = "/avatars",
DefaultAvatar = "/images/Users/icon_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 Scope[] SiteScopes = { 

@ -11,7 +11,6 @@ using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using Microsoft.AspNet.Http;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Services;
using Yavsc.ViewModels.Account;

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
@ -13,10 +12,8 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.Primitives;
using OAuth.AspNet.AuthServer;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Auth;
using Yavsc.ViewModels.Account;
namespace Yavsc.Controllers
{

@ -7,8 +7,10 @@ using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Security.Claims;
using System.Text;
using System.Web;
using Microsoft.AspNet.Http;
using Yavsc.Abstract.FileSystem;
using Yavsc.Exceptions;
using Yavsc.Models;
using Yavsc.Models.FileSystem;
@ -20,33 +22,30 @@ namespace Yavsc.Helpers
public static class FileSystemHelpers
{
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;
}
public static bool IsValidDirectoryName(this string name)
{
return !name.Any(c => !Constants.ValidChars.Contains(c));
}
// Ensure this path is canonical,
// No "dirto/./this", neither "dirt/to/that/"
// 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;
foreach (var name in path.Split(Path.DirectorySeparatorChar))
if (fileName==null) return null;
StringBuilder sb = new StringBuilder();
foreach (var c in fileName)
{
if (!IsValidDirectoryName(name) || name.Equals("..") || name.Equals("."))
return false;
if (FileSystemConstants.ValidFileNameChars.Contains(c))
sb.Append(c);
else sb.Append('_');
}
if (path.EndsWith($"{Path.DirectorySeparatorChar}")) return false;
return true;
return sb.ToString();
}
public static string InitPostToFileSystem(
this ClaimsPrincipal user,
@ -56,7 +55,7 @@ namespace Yavsc.Helpers
var diRoot = new DirectoryInfo(root);
if (!diRoot.Exists) diRoot.Create();
if (!string.IsNullOrWhiteSpace(subpath)) {
if (!subpath.IsValidPath())
if (!subpath.IsValidYavscPath())
{
throw new InvalidPathException();
}
@ -66,6 +65,7 @@ namespace Yavsc.Helpers
if (!di.Exists) di.Create();
return root;
}
public static void DeleteUserFile(this ApplicationUser user, string fileName)
{
var root = Path.Combine(Startup.UserFilesDirName, user.UserName);
@ -74,14 +74,14 @@ namespace Yavsc.Helpers
fi.Delete();
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;
var item = new FileRecievedInfo();
// form-data; name="file"; filename="capt0008.jpg"
ContentDisposition contentDisposition = new ContentDisposition(f.ContentDisposition);
item.FileName = contentDisposition.FileName;
item.FileName = FilterFileName (destFileName ?? contentDisposition.FileName);
item.MimeType = contentDisposition.DispositionType;
var fi = new FileInfo(Path.Combine(root, item.FileName));
if (fi.Exists) item.Overriden = true;
@ -111,7 +111,7 @@ namespace Yavsc.Helpers
user.DiskUsage = usage;
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 + "/" +
HttpUtility.UrlEncode(info.Name) );

@ -1,7 +1,6 @@
using System;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Migrations;
using Yavsc.Models;

@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.Entity.Migrations;
namespace Yavsc.Migrations

@ -12,7 +12,7 @@ namespace Yavsc.ViewComponents
IViewComponentResult result = null;
await Task.Run(() =>
{
result = View(new UserDirectoryInfo(User.Identity.Name, dirname));
result = View(new UserDirectoryInfo(Startup.UserFilesDirName, User.Identity.Name, dirname));
});
return result;
}

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Yavsc.Models.Auth
namespace Yavsc.Models.Auth
{
public class Me : IApplicationUser {
public Me(ApplicationUser user)

Loading…