IT BUILDS!!!
- Removed LocalizationServices and other sus things. - Rewrote AssemblyLoader [In Progress] SafeStorageService [In Progress] LuaScriptLoader
This commit is contained in:
@@ -1,8 +1,32 @@
|
||||
using Barotrauma.LuaCs.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.LuaCs.Configuration;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
public interface ILuaConfigService : ILuaService
|
||||
{
|
||||
|
||||
// get values
|
||||
bool TryGetConfigBool(string packageName, string configName, out bool value);
|
||||
bool TryGetConfigInt(string packageName, string configName, out int value);
|
||||
bool TryGetConfigFloat(string packageName, string configName, out float value);
|
||||
bool TryGetConfigNumber(string packageName, string configName, out double value);
|
||||
bool TryGetConfigString(string packageName, string configName, out string value);
|
||||
bool TryGetConfigVector2(string packageName, string configName, out Vector2 value);
|
||||
bool TryGetConfigVector3(string packageName, string configName, out Vector3 value);
|
||||
bool TryGetConfigColor(string packageName, string configName, out Color value);
|
||||
bool TryGetConfigList(string packageName, string configName, out IReadOnlyList<string> value);
|
||||
// set values
|
||||
void SetConfigBool(string packageName, string configName, bool value);
|
||||
void SetConfigInt(string packageName, string configName, int value);
|
||||
void SetConfigFloat(string packageName, string configName, float value);
|
||||
void SetConfigNumber(string packageName, string configName, double value);
|
||||
void SetConfigString(string packageName, string configName, string value);
|
||||
void SetConfigVector2(string packageName, string configName, Vector2 value);
|
||||
void SetConfigVector3(string packageName, string configName, Vector3 value);
|
||||
void SetConfigColor(string packageName, string configName, Color value);
|
||||
void SetConfigList(string packageName, string configName, string value);
|
||||
// profiles
|
||||
bool TryApplyProfileSettings(string packageName, string profileName);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public interface ILuaDataService : ILuaService
|
||||
/// <summary>
|
||||
/// Returns stored table data for the given object or creates a new table if one doesn't exist.
|
||||
/// </summary>
|
||||
/// <remarks>Note: tables are stored using weak references and will be automatically deleted when the object is
|
||||
/// garbage collected.</remarks>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="tableName"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using MoonSharp.Interpreter.Loaders;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
public interface ILuaScriptLoader : IService, IScriptLoader
|
||||
{
|
||||
void ClearCaches();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
public interface ISafeStorageService : IStorageService
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks the given file path to see if it can be read. This includes any permissions, whitelists and OS checks.
|
||||
/// </summary>
|
||||
/// <param name="path">The absolute path to the file.</param>
|
||||
/// <param name="readOnly">Whether to only check for read permissions only, or full RWM if false.</param>
|
||||
/// <param name="checkWhitelistOnly">Whether to only check if the file is safe to access, without checking accessibility at the OS level.</param>
|
||||
/// <returns>Whether the file is accessible.</returns>
|
||||
bool IsFileAccessible(string path, bool readOnly, bool checkWhitelistOnly = true);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given path to the specified whitelists.
|
||||
/// </summary>
|
||||
/// <param name="path">Either the fully-qualified or local reference path to the given file.</param>
|
||||
/// <param name="readOnly"></param>
|
||||
void AddFileToWhitelist(string path, bool readOnly = true);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the given path from all whitelists (Read|Write).
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
void RemoveFileFromAllWhitelists(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the whitelist filtering for read-only file permissions for the instance.
|
||||
/// </summary>
|
||||
/// <param name="filePaths">List of absolute file paths allowed.</param>
|
||||
FluentResults.Result SetReadOnlyWhitelist(ImmutableArray<string> filePaths);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the whitelist filtering for read & write file permissions for the instance.
|
||||
/// </summary>
|
||||
/// <param name="filePaths">List of absolute file paths allowed.</param>
|
||||
FluentResults.Result SetReadWriteWhitelist(ImmutableArray<string> filePaths);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all paths from all white lists.
|
||||
/// </summary>
|
||||
void ClearAllWhitelists();
|
||||
|
||||
/// <summary>
|
||||
/// Whether the service instance is in file read-only mode.
|
||||
/// </summary>
|
||||
bool IsReadOnlyMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the service into file read-only mode. Cannot be undone.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool EnableReadOnlyMode();
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using MoonSharp.Interpreter;
|
||||
using MoonSharp.Interpreter.Loaders;
|
||||
using System.Linq;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Safe
|
||||
{
|
||||
public class LuaScriptLoader : ScriptLoaderBase, ILuaScriptLoader
|
||||
{
|
||||
public LuaScriptLoader(IStorageService storageService, Lazy<ILoggerService> loggerService, ILuaScriptServicesConfig luaScriptServicesConfig)
|
||||
{
|
||||
this._storageService = storageService;
|
||||
this._loggerService = loggerService;
|
||||
this._luaScriptServicesConfig = luaScriptServicesConfig;
|
||||
_storageService.UseCaching = _luaScriptServicesConfig.UseCaching;
|
||||
if (_luaScriptServicesConfig.SafeLuaIOEnabled)
|
||||
{
|
||||
//_storageService.EnableWhitelistOnly();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly Lazy<ILoggerService> _loggerService;
|
||||
private readonly ILuaScriptServicesConfig _luaScriptServicesConfig;
|
||||
|
||||
public override object LoadFile(string file, Table globalContext)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
|
||||
if (!CanReadFromPath(file))
|
||||
{
|
||||
LogErrors<string>($"File access to \"{file}\" is not allowed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_storageService.TryLoadText(file) is not { IsSuccess: true, Value: not null } script)
|
||||
{
|
||||
LogErrors<string>($"Failed to load file \"{file}\".");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (script.Value.IsNullOrWhiteSpace())
|
||||
{
|
||||
LogErrors<string>($"The file \"{file}\" was empty.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return script.Value;
|
||||
}
|
||||
|
||||
public void ClearCaches()
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
_storageService?.PurgeCache();
|
||||
}
|
||||
|
||||
public override bool ScriptFileExists(string file)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
|
||||
if (!CanReadFromPath(file))
|
||||
{
|
||||
LogErrors<string>($"File access to \"{file}\" is not allowed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = _storageService.FileExists(file);
|
||||
|
||||
if (result is { IsFailed: true })
|
||||
{
|
||||
LogErrors<string>($"Unable to find and load file \"{file}\".");
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.IsSuccess;
|
||||
}
|
||||
|
||||
private bool CanReadFromPath(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private bool CanWriteToPath(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void LogErrors<T>(string message, FluentResults.Result<T> result = null)
|
||||
{
|
||||
_loggerService.Value.LogError($"{nameof(LuaScriptLoader)}: {message}");
|
||||
|
||||
if (result is null || result.Errors.Count <= 0)
|
||||
return;
|
||||
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
_loggerService.Value.LogError($"{nameof(LuaScriptLoader)}: Error: {error.Message}.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
IsDisposed = true;
|
||||
|
||||
_storageService?.Dispose();
|
||||
_loggerService?.Value.Dispose();
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.LuaCs.Data;
|
||||
using FarseerPhysics.Common;
|
||||
using FluentResults;
|
||||
|
||||
namespace Barotrauma.LuaCs.Services.Safe;
|
||||
|
||||
public class SafeStorageService : StorageService, ISafeStorageService
|
||||
{
|
||||
private ConcurrentDictionary<string, byte> _fileListRead = new (), _fileListReadWrite = new();
|
||||
|
||||
public SafeStorageService(IStorageServiceConfig configData) : base(configData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private string GetFullPath(string path) => System.IO.Path.GetFullPath(path).CleanUpPathCrossPlatform();
|
||||
|
||||
public bool IsFileAccessible(string path, bool readOnly, bool checkWhitelistOnly = true)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
|
||||
try
|
||||
{
|
||||
path = GetFullPath(path);
|
||||
if (!readOnly && IsReadOnlyMode)
|
||||
return false;
|
||||
if (readOnly)
|
||||
{
|
||||
if (!_fileListRead.ContainsKey(path))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_fileListReadWrite.ContainsKey(path))
|
||||
return false;
|
||||
}
|
||||
if (checkWhitelistOnly)
|
||||
return true;
|
||||
|
||||
using var fs = System.IO.File.Open(
|
||||
path, FileMode.Open, readOnly ? FileAccess.Read : FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFileToWhitelist(string path, bool readOnly = true)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
try
|
||||
{
|
||||
path = GetFullPath(path);
|
||||
_fileListRead.AddOrUpdate(path, s => 0, (s, b) => 0);
|
||||
if (!readOnly && !IsReadOnlyMode)
|
||||
_fileListRead.AddOrUpdate(path, s => 0, (s, b) => 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveFileFromAllWhitelists(string path)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
try
|
||||
{
|
||||
path = GetFullPath(path);
|
||||
_fileListRead.TryRemove(path, out _);
|
||||
_fileListReadWrite.TryRemove(path, out _);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public FluentResults.Result SetReadOnlyWhitelist(ImmutableArray<string> filePaths)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
if (filePaths.IsDefaultOrEmpty)
|
||||
return FluentResults.Result.Fail($"{nameof(SetReadOnlyWhitelist)}: FilePaths cannot be empty.");
|
||||
var res = new FluentResults.Result();
|
||||
foreach (var path in filePaths)
|
||||
{
|
||||
// TODO: Cleanup path and add it.
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public FluentResults.Result SetReadWriteWhitelist(ImmutableArray<string> filePaths)
|
||||
{
|
||||
((IService)this).CheckDisposed();
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void ClearAllWhitelists()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
private int _isReadOnlyMode = 0;
|
||||
public bool IsReadOnlyMode => ModUtils.Threading.GetBool(ref _isReadOnlyMode);
|
||||
|
||||
public bool EnableReadOnlyMode()
|
||||
{
|
||||
ModUtils.Threading.SetBool(ref _isReadOnlyMode, true);
|
||||
return ModUtils.Threading.GetBool(ref _isReadOnlyMode);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user