jj: throw exception instead of swallowing

This commit is contained in:
Jonathan Jenne 2018-11-09 15:54:51 +01:00
parent 5748d37227
commit 734becb971
10 changed files with 15 additions and 389 deletions

View File

@ -57,7 +57,7 @@ Public Class FrmMain
Private Sub Init()
_firebird = New Firebird(_logConfig, My.Settings.fbDatasource, My.Settings.fbDatabaseLocation, My.Settings.fbUser, My.Settings.fbPassword)
If _firebird.ConnectionFailed Then
MsgBox("Database connection failed. Please check the log.", vbCritical)
Exit Sub

View File

@ -1,54 +0,0 @@
Imports System.IO
Imports System.IO.Compression
Friend Class Compression
Public Async Function CompressAsync(data As Byte()) As Task(Of Byte())
Return Await Task.Run(Function() As Byte()
Return Compress(data)
End Function)
End Function
Public Function Compress(data As Byte()) As Byte()
' ByteArray in Stream umwandeln
Using originalStream As New MemoryStream(data)
' Ziel Stream erstellen
Using compressedStream As New MemoryStream()
' Gzip-Stream erstellen, der alle Daten komprimiert und zu compressedStream durchleitet
'
' > MemoryStream > GzipStream > MemoryStream
' originalStream --> compressionStream --> compressedFileStream
'
Using compressionStream As New GZipStream(compressedStream, CompressionMode.Compress)
originalStream.CopyTo(compressionStream)
compressionStream.Close()
Return compressedStream.ToArray()
End Using
End Using
End Using
End Function
Public Async Function DecompressAsync(data As Byte()) As Task(Of Byte())
Return Await Task.Run(Function() As Byte()
Return Decompress(data)
End Function)
End Function
Public Function Decompress(data As Byte()) As Byte()
' ByteArray in Stream umwandeln
Using compressedStream As New MemoryStream(data)
' Ziel Stream erstellen
Using decompressedStream As New MemoryStream()
' Gzip-Stream erstellen, der alle Daten komprimiert und zu compressedStream durchleitet
'
' > MemoryStream > GzipStream > MemoryStream
' compressedStream --> decompressionStream --> decompressedStream
'
Using decompressionStream As New GZipStream(compressedStream, CompressionMode.Decompress)
decompressionStream.CopyTo(decompressedStream)
Return decompressedStream.ToArray()
End Using
End Using
End Using
End Function
End Class

View File

@ -1,105 +0,0 @@
Imports System.IO
Imports System.Security.Cryptography
''' <summary>
''' https://stackoverflow.com/questions/10168240/encrypting-decrypting-a-string-in-c-sharp
''' </summary>
Friend Class Encryption
' This constant is used to determine the keysize of the encryption algorithm in bits.
' We divide this by 8 within the code below to get the equivalent number of bytes.
Private Const Keysize As Integer = 256
' This constant determines the number of iterations for the password bytes generation function.
Private Const DerivationIterations As Integer = 1000
Private ReadOnly password As String
Public Sub New(password As String)
If IsNothing(password) Then
Throw New ArgumentNullException("password")
End If
Me.password = password
End Sub
Public Async Function EncryptAsync(plainTextBytes As Byte()) As Task(Of Byte())
Return Await Task.Run(Function() As Byte()
Return Encrypt(plainTextBytes)
End Function)
End Function
Public Function Encrypt(plainTextBytes As Byte()) As Byte()
' Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
' so that the same Salt and IV values can be used when decrypting.
Dim saltStringBytes = Generate256BitsOfRandomEntropy()
Dim ivStringBytes = Generate256BitsOfRandomEntropy()
Using password = New Rfc2898DeriveBytes(Me.password, saltStringBytes, DerivationIterations)
Dim keyBytes = password.GetBytes(Keysize / 8)
Using symmetricKey = New RijndaelManaged()
symmetricKey.BlockSize = 256
symmetricKey.Mode = CipherMode.CBC
symmetricKey.Padding = PaddingMode.PKCS7
Using encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)
Using memoryStream = New MemoryStream()
Using cryptoStream = New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
' Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
Dim cipherTextBytes = saltStringBytes
cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray()
cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray()
memoryStream.Close()
cryptoStream.Close()
Return cipherTextBytes
End Using
End Using
End Using
End Using
End Using
End Function
Public Async Function DecryptAsync(cipherTextBytesWithSaltAndIv As Byte()) As Task(Of Byte())
Return Await Task.Run(Function() As Byte()
Return Decrypt(cipherTextBytesWithSaltAndIv)
End Function)
End Function
Public Function Decrypt(cipherTextBytesWithSaltAndIv As Byte()) As Byte()
' Get the complete stream of bytes that represent:
' [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
' Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
Dim saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray()
' Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
Dim ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray()
' Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
Dim cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray()
Using password = New Rfc2898DeriveBytes(Me.password, saltStringBytes, DerivationIterations)
Dim keyBytes = password.GetBytes(Keysize / 8)
Using symmetricKey = New RijndaelManaged()
symmetricKey.BlockSize = 256
symmetricKey.Mode = CipherMode.CBC
symmetricKey.Padding = PaddingMode.PKCS7
Using decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)
Using memoryStream = New MemoryStream(cipherTextBytes)
Using cryptoStream = New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
Dim plainTextBytes = New Byte(cipherTextBytes.Length - 1) {}
Dim decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
memoryStream.Close()
cryptoStream.Close()
Return plainTextBytes
End Using
End Using
End Using
End Using
End Using
End Function
Private Shared Function Generate256BitsOfRandomEntropy() As Byte()
Dim randomBytes = New Byte(31) {}
' 32 Bytes will give us 256 bits.
Using rngCsp = New RNGCryptoServiceProvider()
' Fill the array with cryptographically secure random bytes.
rngCsp.GetBytes(randomBytes)
End Using
Return randomBytes
End Function
End Class

View File

@ -30,20 +30,16 @@ Public Class File
End Sub
''' <summary>
''' Removes files in a directory filtered by filename, extension and last write date.
''' Removes files in a directory filtered by filename, extension and last write date
''' </summary>
''' <param name="Path">The directory in which files will be deleted</param>
''' <param name="FileKeepTime">Only delete files which are older than x days. Must be between 0 and 1000 days.</param>
''' <param name="FileBaseName">A filename filter which will be checked</param>
''' <param name="FileExtension">A file extension which will be checked</param>
''' <param name="ContinueOnError">Should the function continue with deleting when a file could not be deleted?</param>
''' <exception cref="ArgumentException">When Path is not a directory</exception>
''' <exception cref="DirectoryNotFoundException">When Path was not found</exception>
''' <exception cref="ArgumentOutOfRangeException">When FileKeepTime is below 0 or above 1000</exception>
''' <returns>True if all files were deleted or if no files were deleted, otherwise false</returns>
Public Function RemoveFiles(Path As String, FileKeepTime As Integer, FileBaseName As String, Optional FileExtension As String = "log", Optional ContinueOnError As Boolean = True) As Boolean
If Not TestPathIsDirectory(Path) Then
Throw New ArgumentException($"Path {Path} is not a directory!")
End If
@ -97,4 +93,5 @@ Public Class File
Dim oIsDirectory As Boolean = (System.IO.File.GetAttributes(Path) And FileAttributes.Directory) = FileAttributes.Directory
Return oIsDirectory
End Function
End Class

View File

@ -1,196 +0,0 @@
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Public Class FileContainer
Private _files As List(Of FileEntry)
Private _crypto As Encryption
Private _compression As Compression
Private _formatter As BinaryFormatter
<Serializable>
Public Class FileEntry
Public FileId As String
Public Contents As Byte()
End Class
''' <summary>
''' Gibt eine Auflistung der Dateien in Container zurück.
''' </summary>
''' <returns>Eine Liste von Objekten der Klasse FileContainer.FileEntry</returns>
Public ReadOnly Property Files As List(Of FileEntry)
Get
Return _files
End Get
End Property
''' <summary>
''' Erstellt eine Representation eines Datei Containers, der mit dem angegebenen Passwort geschützt ist.
''' Ist für das speichern von neuen Containern und für das laden vorhandener Container nötig.
''' </summary>
''' <param name="password">Das Passwort, mit dem der Container ver- und entschlüsselt wird</param>
''' <example>
''' Dim password = "meinpasswort"
''' Dim container = new FileContainer(password)
''' </example>
Public Sub New(password As String)
_crypto = New Encryption(password)
_compression = New Compression()
_formatter = New BinaryFormatter()
_files = New List(Of FileEntry)
End Sub
''' <summary>
''' Speichert einen Datei Container am angegebenen Pfad.
''' Davor werden die Dateien in Files komprimiert und dann verschlüsselt.
''' </summary>
''' <param name="path">Der Pfad mit Dateiname, unter dem der Container abgelegt wird.</param>
''' <see cref="Files"/>
''' <example>
''' container.AddFile("datei1.txt")
''' container.AddFile("datei2.pdf")
''' container.Save("container.enc")
''' </example>
Public Sub Save(path As String)
' 1. Serialize
Dim bFiles As Byte() = Serialize(_files)
' 2. Compress
Dim bFilesCompressed As Byte() = _compression.Compress(bFiles)
' 3. Encrypt
Dim bFilesEncrypted As Byte() = _crypto.Encrypt(bFilesCompressed)
BytesToFile(bFilesEncrypted, path)
End Sub
''' <summary>
''' Speichert einen Datei Container am angegebenen Pfad.
''' Davor werden die Dateien in Files komprimiert und dann verschlüsselt.
''' </summary>
''' <param name="path">Der Pfad mit Dateiname, unter dem der Container abgelegt wird.</param>
''' <example>
''' Public Async Sub foobar()
''' ...
''' container.AddFile("datei1.txt")
''' container.AddFile("datei2.pdf")
''' await container.SaveAsync("container.enc")
''' ...
''' End Sub
''' </example>
Public Async Function SaveAsync(path As String) As Task
' 1. Serialize
Dim bFiles As Byte() = Serialize(_files)
' 2. Compress
Dim bFilesCompressed As Byte() = Await _compression.CompressAsync(bFiles)
'Dim bFilesCompressed = bFiles
' 3. Encrypt
Dim bFilesEncrypted As Byte() = Await _crypto.EncryptAsync(bFilesCompressed)
BytesToFileAsync(bFilesEncrypted, path)
End Function
''' <summary>
''' Lädt einen Datei Container aus dem angegebenen Pfad.
''' Anschließend werden die enthaltenen Dateien entschlüsselt, dekomprimiert und in Files abgelegt.
''' </summary>
''' <param name="path">Der Pfad mit Dateiname, von dem der Container geladen wird.</param>
''' <see cref="Files"/>
''' <example>
''' container.Load("container.enc")
''' Dim files As List(Of FileContainer.FileEntry) = container.Files
''' </example>
Public Sub Load(path As String)
Dim bFilesEncrypted As Byte() = FileToBytes(path)
' 1. Decrypt
Dim bFiles As Byte() = _crypto.Decrypt(bFilesEncrypted)
' 2. Decompress
Dim bFilesDecompressed As Byte() = _compression.Decompress(bFiles)
' 3. Deserialize
_files = Deserialize(bFilesDecompressed)
End Sub
''' <summary>
''' Lädt einen Datei Container aus dem angegebenen Pfad.
''' Anschließend werden die enthaltenen Dateien entschlüsselt, dekomprimiert und in Files abgelegt.
''' </summary>
''' <param name="path">Der Pfad mit Dateiname, von dem der Container geladen wird.</param>
''' <example>
''' Public Async Sub foobar()
''' ...
''' await container.LoadAsync("container.enc")
''' Dim files As List(Of FileContainer.FileEntry) = container.Files
''' ...
''' End Sub
''' </example>
Public Async Function LoadAsync(path As String) As Task
Dim bFilesEncrypted As Byte() = Await FileToBytesAsync(path)
' 1. Decrypt
Dim bFiles As Byte() = Await _crypto.DecryptAsync(bFilesEncrypted)
' 2. Decompress
Dim bFilesDecompressed As Byte() = Await _compression.DecompressAsync(bFiles)
'Dim bFilesDecompressed = bFiles
' 3. Deserialize
_files = Deserialize(bFilesDecompressed)
End Function
''' <summary>
''' Fügt einem Datei Container eine neue Datei hinzu
''' </summary>
''' <param name="filePath">Der Pfad zur Datei, die im Container gespeichert werden soll</param>
''' <exception cref="FileNotFoundException" />
Public Sub AddFile(filePath As String)
Dim fi As New FileInfo(filePath)
Dim fe As New FileEntry()
If fi.Exists = False Then
Throw New FileNotFoundException($"{filePath} is not a valid path.")
End If
fe.Contents = IO.File.ReadAllBytes(filePath)
fe.FileId = Guid.NewGuid().ToString()
_files.Add(fe)
End Sub
Public Function GetFile(fileId As String) As FileEntry
Return _files.Where(Function(f) f.FileId = fileId).FirstOrDefault()
End Function
Private Function Serialize(list As List(Of FileEntry)) As Byte()
Using ms As New MemoryStream
_formatter.Serialize(ms, list)
Return ms.ToArray()
End Using
End Function
Private Function Deserialize(data As Byte()) As List(Of FileEntry)
Using ms As New MemoryStream(data)
Dim list = TryCast(_formatter.Deserialize(ms), List(Of FileEntry))
Return list
End Using
End Function
Private Sub BytesToFile(data As Byte(), filePath As String)
IO.File.WriteAllBytes(filePath, data)
End Sub
Private Function FileToBytes(filePath As String) As Byte()
Return IO.File.ReadAllBytes(filePath)
End Function
Private Async Function FileToBytesAsync(filePath As String) As Task(Of Byte())
Using file = New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, True)
Dim buff As Byte() = New Byte(file.Length - 1) {}
Await file.ReadAsync(buff, 0, file.Length)
file.Close()
Return buff
End Using
End Function
Private Async Sub BytesToFileAsync(data As Byte(), filePath As String)
Using sourceStream As New FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None, bufferSize:=4096, useAsync:=True)
Await sourceStream.WriteAsync(data, 0, data.Length)
End Using
End Sub
End Class

View File

@ -72,10 +72,7 @@
<Import Include="System.Threading.Tasks" />
</ItemGroup>
<ItemGroup>
<Compile Include="Compression.vb" />
<Compile Include="Encryption.vb" />
<Compile Include="File.vb" />
<Compile Include="FileContainer.vb" />
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>

View File

@ -24,15 +24,14 @@ Partial Class LookupControl
Private Sub InitializeComponent()
Me.SuspendLayout()
'
'LookupControl
'Grid
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.AutoSize = True
Me.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink
Me.BackColor = System.Drawing.Color.Transparent
Me.Name = "LookupControl"
Me.Size = New System.Drawing.Size(0, 0)
Me.Name = "Grid"
Me.Size = New System.Drawing.Size(270, 35)
Me.ResumeLayout(False)
End Sub

View File

@ -157,7 +157,7 @@ Public Class Firebird
Return True
Catch ex As Exception
_logger.Error(ex, $"Error in ExecuteNonQuery while executing command: '{SqlCommand}'")
Return False
Throw ex
End Try
End Function
@ -200,7 +200,7 @@ Public Class Firebird
Return oResult
Catch ex As Exception
_logger.Error(ex, $"Error in ReturnScalar while executing command: '{SqlQuery}'")
Return Nothing
Throw ex
End Try
End Function

View File

@ -7,11 +7,11 @@ Imports DigitalData.Modules.Logging
''' Test creating the log path in various configurations
''' </summary>
<TestClass()> Public Class ConstructorUnitTest
Private Shared ReadOnly _currentDirectoryLogPath = Path.Combine(Directory.GetCurrentDirectory(), "Log")
Private Shared ReadOnly _appdataDirectoryLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Digital Data", "Modules.Logging")
Private Shared ReadOnly _customDirectoryLogPath = Path.Combine(Directory.GetCurrentDirectory(), "CustomLogFolder")
Private Shared ReadOnly _restrictedDirectoryLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "ShouldNotBeCreated")
Private Shared ReadOnly _nonsenseDirectoryLogPath = "X:\FOO\BAR\BAZ\QUUX"
Private Shared _currentDirectoryLogPath = Path.Combine(Directory.GetCurrentDirectory(), "Log")
Private Shared _appdataDirectoryLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Digital Data", "Modules.Logging")
Private Shared _customDirectoryLogPath = Path.Combine(Directory.GetCurrentDirectory(), "CustomLogFolder")
Private Shared _restrictedDirectoryLogPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "ShouldNotBeCreated")
Private Shared _nonsenseDirectoryLogPath = "X:\FOO\BAR\BAZ\QUUX"
<TestMethod()> Public Sub TestConstructorCurrentDirectory()
Dim oLogConfig As New LogConfig(LogConfig.PathType.CurrentDirectory)

View File

@ -45,7 +45,6 @@ Partial Class Form1
Me.Label6 = New System.Windows.Forms.Label()
Me.Button4 = New System.Windows.Forms.Button()
Me.LookupControl1 = New DigitalData.Controls.LookupGrid.LookupControl()
Me.Button6 = New System.Windows.Forms.Button()
CType(Me.GridControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.GridView1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
@ -236,29 +235,19 @@ Partial Class Form1
Me.LookupControl1.AutoSize = True
Me.LookupControl1.BackColor = System.Drawing.Color.Transparent
Me.LookupControl1.DataSource = Nothing
Me.LookupControl1.Location = New System.Drawing.Point(684, 195)
Me.LookupControl1.Location = New System.Drawing.Point(695, 214)
Me.LookupControl1.MultiSelect = True
Me.LookupControl1.Name = "LookupControl1"
Me.LookupControl1.SelectedValues = CType(resources.GetObject("LookupControl1.SelectedValues"), System.Collections.Generic.List(Of String))
Me.LookupControl1.Size = New System.Drawing.Size(270, 87)
Me.LookupControl1.Size = New System.Drawing.Size(270, 23)
Me.LookupControl1.TabIndex = 23
'
'Button6
'
Me.Button6.Location = New System.Drawing.Point(637, 240)
Me.Button6.Name = "Button6"
Me.Button6.Size = New System.Drawing.Size(75, 23)
Me.Button6.TabIndex = 24
Me.Button6.Text = "Button6"
Me.Button6.UseVisualStyleBackColor = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(1050, 487)
Me.Controls.Add(Me.LookupControl1)
Me.Controls.Add(Me.Button6)
Me.Controls.Add(Me.Button4)
Me.Controls.Add(Me.Label6)
Me.Controls.Add(Me.TextBox1)
@ -311,5 +300,4 @@ Partial Class Form1
Friend WithEvents Label6 As Label
Friend WithEvents Button4 As Button
Friend WithEvents LookupControl1 As DigitalData.Controls.LookupGrid.LookupControl
Friend WithEvents Button6 As Button
End Class