Imports System.IO Imports DigitalData.Modules.Logging Imports ProtoBuf ''' FileContainer ''' 0.0.0.2 ''' 21.11.2018 ''' ''' File Container for securely saving files ''' ''' ''' NLog, >= 4.5.8 ''' ''' ''' LogConfig, DigitalData.Module.Logging.LogConfig ''' A LogConfig object ''' Password, String ''' The Password to Encrypt ''' Path, String ''' The Path to save/load the container ''' ''' ''' dim oContainer = Container.Create(logConfig, "pass", "E:\some.container") ''' dim oContainer = Container.Load(logConfig, "pass", "E:\some.container") ''' ''' dim oContainer = new Container(logConfig, "pass", "E:\some.container") ''' oContainer.Save() ''' ''' dim oContainer = new Container(logConfig, "pass", "E:\some.container") ''' oContainer.Contents = oSomeData ''' oContainer.Save() ''' ''' dim oContainer = new Container(logConfig, "pass", "E:\some.container") ''' oContainer.Load() ''' dim oContents = oContainer.Contents ''' ''' dim oContainer = new Container(logConfig, "pass", "E:\some.container") ''' oContainer.Load() ''' oContainer.Contents = oSomeOtherData ''' oContainer.Save() ''' oContainer.SaveAs("E:\some2.container") ''' Public Class FileContainer Private _crypto As Encryption Private _compression As Compression Private _containerId As Guid Private _inner As FileContainerInner Private _logger As Logger Private _logConfig As LogConfig Private _path As String Public Property Contents As Byte() Get Return _inner.Contents End Get Set(value As Byte()) _inner.Contents = value End Set End Property Public Property Extension As String Get Return _inner.Extension End Get Set(value As String) _inner.Extension = value End Set End Property Public ReadOnly Property FileId As String Get Return _inner.FileId End Get End Property Public ReadOnly Property CreatedAt As String Get Return _inner.CreatedAt End Get End Property Public ReadOnly Property UpdatedAt As String Get Return _inner.UpdatedAt End Get End Property Public Shared Function Create(LogConfig As LogConfig, Password As String) As FileContainer Dim oContainer = New FileContainer(LogConfig, Password) Return oContainer End Function Public Shared Function Load(LogConfig As LogConfig, Password As String, Path As String) As FileContainer Dim oContainer = New FileContainer(LogConfig, Password, Path) oContainer.Load() Return oContainer End Function Public Sub New(LogConfig As LogConfig, Password As String, Path As String) _logger = LogConfig.GetLogger() _crypto = New Encryption(LogConfig, Password) _compression = New Compression(LogConfig) _inner = New FileContainerInner() _path = Path End Sub Public Sub New(LogConfig As LogConfig, Password As String) _logger = LogConfig.GetLogger() _crypto = New Encryption(LogConfig, Password) _compression = New Compression(LogConfig) _inner = New FileContainerInner() End Sub Public Sub SetFile(Contents As Byte(), Extension As String) _inner.Contents = Contents _inner.Extension = Extension End Sub Public Function GetFile() As FileContainerInner Return _inner End Function Public Sub Save() If IsNothing(_path) Then Throw New ArgumentException("Path not set") End If SaveAs(_path) End Sub Public Sub SaveAs(Path As String) Try WriteBytesToFile(TransformToBytes(_inner), Path) Catch ex As Exception _logger.Error(ex) Throw ex End Try End Sub Public Sub Load() If IsNothing(_path) Then Throw New ArgumentException("Path not set") End If LoadFrom(_path) End Sub Public Sub LoadFrom(Path As String) Try _inner = TransformToObject(ReadBytesFromFile(_path)) Catch ex As Exception _logger.Error(ex) Throw ex End Try End Sub Private Function TransformToBytes([Object] As FileContainerInner) As Byte() Dim oBytes = Serialize([Object]) Dim oCompressed = _compression.Compress(oBytes) Dim oEncrypted = _crypto.Encrypt(oCompressed) Return oEncrypted End Function Private Function TransformToObject(Bytes As Byte()) As FileContainerInner Dim oDecrypted = _crypto.Decrypt(Bytes) Dim oDecompressed = _compression.Decompress(oDecrypted) Dim oObject = Deserialize(oDecompressed) Return oObject End Function Private Function Serialize(InnerData As FileContainerInner) As Byte() Dim oBinaryData As Byte() Using oStream As New MemoryStream Serializer.Serialize(oStream, InnerData) oBinaryData = oStream.ToArray() End Using Return oBinaryData End Function Private Function Deserialize(InnerData As Byte()) As FileContainerInner Dim oObject As FileContainerInner Using oStream As New MemoryStream(InnerData) oObject = Serializer.Deserialize(Of FileContainerInner)(oStream) End Using Return oObject End Function Private Sub WriteBytesToFile(Data As Byte(), FilePath As String) Using oSourceStream As New FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None) oSourceStream.Write(Data, 0, Data.Length) oSourceStream.Flush() End Using End Sub Private Function ReadBytesFromFile(FilePath As String) As Byte() Using oFileStream = New FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096) Dim oBuffer As Byte() = New Byte(oFileStream.Length - 1) {} oFileStream.Read(oBuffer, 0, oFileStream.Length) oFileStream.Close() Return oBuffer End Using End Function End Class