|
|
|
|
// (C) Copyright 2019 C-xC-c <boku@plum.moe>
|
|
|
|
|
// This file is part of BantFlags.
|
|
|
|
|
// BantFlags is licensed under the GNU AGPL Version 3.0 or later.
|
|
|
|
|
// see the LICENSE file or <https://www.gnu.org/licenses/>
|
|
|
|
|
using ImageMagick;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace BantFlags.Data
|
|
|
|
|
{
|
|
|
|
|
public class Staging
|
|
|
|
|
{
|
|
|
|
|
public List<Flag> Flags { get; set; }
|
|
|
|
|
public string Password { get; }
|
|
|
|
|
|
|
|
|
|
public HashSet<string> Names { get; set; }
|
|
|
|
|
|
|
|
|
|
public Staging(string password)
|
|
|
|
|
{
|
|
|
|
|
Flags = new List<Flag>();
|
|
|
|
|
Password = password;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
{
|
|
|
|
|
Flags = new List<Flag>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum Method
|
|
|
|
|
{
|
|
|
|
|
Add = 0,
|
|
|
|
|
|
|
|
|
|
Delete = 1,
|
|
|
|
|
|
|
|
|
|
Rename = 2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Flag
|
|
|
|
|
{
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
|
|
|
|
public string OldName { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool IsChecked { get; set; }
|
|
|
|
|
|
|
|
|
|
public Method FlagMethod { get; set; }
|
|
|
|
|
|
|
|
|
|
// This is bad but we need it so Flags can be generated by the input tag helper
|
|
|
|
|
public Flag()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Flag(string name, Method method)
|
|
|
|
|
{
|
|
|
|
|
Name = name;
|
|
|
|
|
FlagMethod = method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Flag(string name, string oldName, Method method)
|
|
|
|
|
{
|
|
|
|
|
Name = name;
|
|
|
|
|
OldName = oldName;
|
|
|
|
|
FlagMethod = method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Flag CreateFromDelete(string name) => new Flag(name, Method.Delete); // We don't need any validation for deleted flags.
|
|
|
|
|
|
|
|
|
|
public static (Flag, string) CreateFromRename(string oldName, string newName, HashSet<string> names)
|
|
|
|
|
{
|
|
|
|
|
(bool valid, string error) = ValidateFileName(newName, names);
|
|
|
|
|
|
|
|
|
|
if (!valid)
|
|
|
|
|
{
|
|
|
|
|
return (default, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (new Flag(newName, oldName, Method.Rename), default);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<(Flag, string)> CreateFromFile(IFormFile upload, HashSet<string> names)
|
|
|
|
|
{
|
|
|
|
|
byte[] PNGHeader = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
|
|
|
|
|
|
|
|
|
|
if (upload.ContentType.ToLower() != "image/png")
|
|
|
|
|
return (default, "Image must be a png.");
|
|
|
|
|
|
|
|
|
|
if (upload.Length > 15 * 1024)
|
|
|
|
|
return (default, "File too big. Max size is 15kb.");
|
|
|
|
|
|
|
|
|
|
var name = Path.GetFileNameWithoutExtension(upload.FileName);
|
|
|
|
|
|
|
|
|
|
(bool valid, string error) = ValidateFileName(name, names);
|
|
|
|
|
|
|
|
|
|
if (!valid)
|
|
|
|
|
return (default, error);
|
|
|
|
|
|
|
|
|
|
using (var memoryStream = new MemoryStream())
|
|
|
|
|
{
|
|
|
|
|
await upload.CopyToAsync(memoryStream);
|
|
|
|
|
memoryStream.Position = 0;
|
|
|
|
|
|
|
|
|
|
using (var image = new MagickImage(memoryStream))
|
|
|
|
|
{
|
|
|
|
|
if (image.Width != 16 || image.Height != 11)
|
|
|
|
|
return (default, "Invalid image dimensions. Flags should be 16px by 11px.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var reader = new BinaryReader(memoryStream))
|
|
|
|
|
{
|
|
|
|
|
reader.BaseStream.Position = 0;
|
|
|
|
|
|
|
|
|
|
if (!reader.ReadBytes(PNGHeader.Length).SequenceEqual(PNGHeader))
|
|
|
|
|
return (default, "Invalid png header.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (new Flag(name, Method.Add), default);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Filters file names created by users.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">The file name to validate.</param>
|
|
|
|
|
/// <param name="names">The list of current file names.</param>
|
|
|
|
|
private static (bool, string) ValidateFileName(string name, HashSet<string> names)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
|
|
|
return (false, "Flag name can't be empty.");
|
|
|
|
|
|
|
|
|
|
if (name.Length > 100)
|
|
|
|
|
return (false, "Flag name too long.");
|
|
|
|
|
|
|
|
|
|
if (name == "empty, or there were errors. Re - set your flags.")
|
|
|
|
|
return (false, "Invalid flag name.");
|
|
|
|
|
|
|
|
|
|
if (name.Contains("||") || name.Contains(","))
|
|
|
|
|
return (false, "Flag name contains invalid characters. You can't use \"||\" or \",\".");
|
|
|
|
|
|
|
|
|
|
if (names.Contains(name))
|
|
|
|
|
return (false, "A flag with that name already exists.");
|
|
|
|
|
|
|
|
|
|
return (true, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|