Compare commits
257 Commits
Database_S
...
3a1678e742
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a1678e742 | |||
| c968831209 | |||
|
|
c3fccc3c20 | ||
|
|
97c1fb4803 | ||
|
|
808cdea86a | ||
|
|
c048b6ad6b | ||
| a5b9579b79 | |||
| c2d87c3e25 | |||
|
|
0a6a2093d5 | ||
| c4df4a2f5c | |||
|
|
d040da3277 | ||
|
|
64e92f7a39 | ||
|
|
1d2aecf4fb | ||
|
|
b38a88d5f9 | ||
|
|
e85379dcf5 | ||
|
|
9f9feff2fd | ||
|
|
8362e1885d | ||
|
|
f3eef04a09 | ||
|
|
b55e045cca | ||
|
|
a3e1d34a7a | ||
|
|
a53c5154b0 | ||
|
|
6e5b192fb6 | ||
| efdbed58df | |||
|
|
dc6ad9afac | ||
| 38f330b94b | |||
|
|
9f11b2b7bc | ||
|
|
4a2b64f73d | ||
|
|
12eef1de61 | ||
|
|
bdceababcf | ||
| 07d26cf70c | |||
| 0810983f86 | |||
|
|
9deeb35ad7 | ||
|
|
63ddbaeacf | ||
|
|
71e9fe7cd2 | ||
|
|
726c3481e5 | ||
|
|
30c602a9bf | ||
|
|
5b2ba2eff2 | ||
|
|
04577f3b61 | ||
|
|
8da8bd18a7 | ||
|
|
8ab32a4d2b | ||
|
|
130281b602 | ||
|
|
02272f980f | ||
|
|
e402cdaf5c | ||
|
|
348d054e16 | ||
|
|
011b78472b | ||
|
|
4f3d8e0c7d | ||
|
|
7b01ef788a | ||
|
|
a64823ae5e | ||
|
|
c187bdbe5e | ||
|
|
3c149a32e9 | ||
|
|
2153e83426 | ||
|
|
278dda42a8 | ||
|
|
1556f8bc45 | ||
|
|
b3b3e80509 | ||
|
|
441f65915f | ||
|
|
aa27dd8c1c | ||
|
|
20ec64c21d | ||
|
|
7a6537d529 | ||
|
|
e2d67ab6d7 | ||
|
|
79e10ef2f6 | ||
|
|
da8ba360ca | ||
|
|
fac8762888 | ||
|
|
ddffb9c4f8 | ||
|
|
b16050cfc6 | ||
|
|
a415f90906 | ||
|
|
e8974376c5 | ||
|
|
6f33261101 | ||
|
|
af90bb9efe | ||
|
|
e12b087c94 | ||
|
|
3cb625c921 | ||
|
|
70bb33f823 | ||
|
|
e63d1ea557 | ||
|
|
2b80e8fa97 | ||
|
|
9cab65f941 | ||
|
|
4c8bdb27fd | ||
|
|
b604ffcba2 | ||
|
|
6ef1e97deb | ||
|
|
60bcf26379 | ||
|
|
a4a3dc4536 | ||
|
|
86d61e720f | ||
|
|
002931d6dd | ||
|
|
77d8a0825f | ||
|
|
f6046aec54 | ||
|
|
72f7211d63 | ||
|
|
7fea3dc1ff | ||
|
|
ec309b5afb | ||
|
|
681c561a7d | ||
|
|
22a30533c2 | ||
|
|
de418bcca4 | ||
|
|
7b2b37a870 | ||
|
|
28538bcf41 | ||
|
|
d73fa2a1c5 | ||
|
|
2288bc3fb9 | ||
|
|
05a590b169 | ||
|
|
03f81938ae | ||
|
|
89ee1caf36 | ||
|
|
73f95de4c8 | ||
|
|
5ec049ff61 | ||
|
|
56b0fedbe2 | ||
|
|
902231ff86 | ||
|
|
e5b5c259d7 | ||
|
|
c5b6498f1b | ||
|
|
39a406bfaf | ||
|
|
222176dfca | ||
|
|
2517db3d68 | ||
|
|
c9437f4a5c | ||
|
|
524c429de4 | ||
|
|
0da1eb55a9 | ||
|
|
18b0d4cdaf | ||
|
|
a05156a1a6 | ||
|
|
a19123dd03 | ||
|
|
1c5cc2e6fc | ||
|
|
7625f2d2e3 | ||
|
|
f2e275c8bd | ||
|
|
e156cc9d88 | ||
|
|
cfef91059a | ||
|
|
a4916ba25f | ||
|
|
18374ba93d | ||
|
|
977f79b6a6 | ||
|
|
8c1a1af140 | ||
|
|
36b38f0bd8 | ||
|
|
c9c56ad720 | ||
|
|
ab280ccabe | ||
|
|
b1114545a7 | ||
|
|
00cff028c9 | ||
|
|
76cba215fe | ||
|
|
f491d4dd24 | ||
|
|
e65a6fa1a4 | ||
|
|
726bdd1b2d | ||
|
|
fd2ad3f056 | ||
|
|
a856f5f1b3 | ||
|
|
5ced396e3f | ||
|
|
10d8e7749a | ||
|
|
cd3646dca0 | ||
| 0c1b070a90 | |||
| da9dd6dcd7 | |||
| dd4a4aad95 | |||
|
|
98fd711ea0 | ||
|
|
0008d0f3ba | ||
|
|
fb2e8a6f6c | ||
|
|
2d2c09bdf4 | ||
|
|
1c49054844 | ||
|
|
c871b06cc2 | ||
|
|
1a860c9270 | ||
|
|
88ac9e70b2 | ||
|
|
6885bd2954 | ||
|
|
4a221a9e1d | ||
|
|
11ab322138 | ||
|
|
9cea30235d | ||
|
|
f3afadc3b7 | ||
|
|
89fbc4e4ae | ||
|
|
adf692629a | ||
|
|
f6f421ddd8 | ||
|
|
2ced2f192f | ||
|
|
a80b943dc5 | ||
|
|
214edf22a5 | ||
|
|
5ac3aaab54 | ||
|
|
1ab246fc46 | ||
|
|
9fe177abd3 | ||
| ed7aea5b72 | |||
| 8e1c459a61 | |||
|
|
f6acae9185 | ||
|
|
fd0876a1cb | ||
|
|
ad5443adae | ||
|
|
39a0c8b8ec | ||
|
|
46ce5342a0 | ||
|
|
1013dd3c30 | ||
|
|
41bba8b214 | ||
|
|
4ee519d8c6 | ||
|
|
d9690d270b | ||
|
|
1c86b8091b | ||
|
|
8738fd8300 | ||
|
|
27e3462b6e | ||
|
|
1d0688e995 | ||
|
|
c1018d176e | ||
| 3183b0ed31 | |||
| b33720c61e | |||
|
|
baa661cb14 | ||
|
|
e5ec777d61 | ||
|
|
4dfe32ba33 | ||
|
|
65d58a2274 | ||
|
|
902c835c37 | ||
|
|
79cad24b3f | ||
|
|
a9567a9d18 | ||
|
|
0d207a25a5 | ||
|
|
19f33dbb2c | ||
|
|
0ed5a164e8 | ||
|
|
36dd27b26c | ||
|
|
3df54fa62c | ||
|
|
67cdc580fa | ||
|
|
c082222c80 | ||
|
|
33a95ba46d | ||
|
|
a00ad5a9c0 | ||
|
|
db1d3fb197 | ||
|
|
d5e98c5de4 | ||
|
|
e717dffa54 | ||
|
|
eae009e82d | ||
|
|
d74e0f304a | ||
|
|
2816b644da | ||
|
|
b927e07141 | ||
|
|
f5107a3d21 | ||
| 75df258abf | |||
|
|
1ea73d9234 | ||
|
|
d44ab2f087 | ||
|
|
bd6d483867 | ||
| 7b7b17b657 | |||
|
|
3883c0dad7 | ||
|
|
078282c579 | ||
|
|
e91af7de7c | ||
|
|
fb5527036a | ||
|
|
211c394b2f | ||
|
|
5f52434d67 | ||
|
|
e2494e5117 | ||
|
|
dd5a1c0766 | ||
|
|
a69fecd75d | ||
|
|
7b249fb9cb | ||
|
|
c5973c86c9 | ||
|
|
680b496b90 | ||
|
|
c9ef17e533 | ||
|
|
780238625c | ||
|
|
5794018c5e | ||
|
|
b329492521 | ||
|
|
22b3918a03 | ||
|
|
15d6cac420 | ||
|
|
a469ff9a23 | ||
|
|
55fc875d3a | ||
|
|
1d04027c5f | ||
|
|
e3c500938b | ||
|
|
dbbacd2623 | ||
|
|
7d86d583de | ||
|
|
5c4b302aa7 | ||
|
|
1d8a0faeee | ||
|
|
ca92abbee5 | ||
|
|
8267ecb72d | ||
|
|
86ca1011df | ||
|
|
b1aba0a80d | ||
|
|
a8862709d8 | ||
|
|
36fe39ee66 | ||
|
|
ddc11b62a5 | ||
|
|
7ba516fcd1 | ||
|
|
05a92c3181 | ||
|
|
7d63718e96 | ||
|
|
8af67ef883 | ||
| 6ed636bca0 | |||
| 5f8e1a8608 | |||
|
|
e424402d63 | ||
|
|
9d6dd695e4 | ||
|
|
0410e11b59 | ||
|
|
f4adba98eb | ||
|
|
1dba028deb | ||
|
|
3a26343083 | ||
|
|
1e732a036a | ||
|
|
41165a470d | ||
|
|
8128987be4 | ||
|
|
6ebd3b82b6 | ||
|
|
d18ebfe912 | ||
|
|
b614b3f140 |
@@ -10,7 +10,7 @@
|
||||
<AssemblyName>DigitalData.Modules.Base</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
@@ -46,16 +46,19 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -74,11 +77,25 @@
|
||||
<Import Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BaseClass.vb" />
|
||||
<Compile Include="ECM\ECM.vb" />
|
||||
<Compile Include="IDB\Attributes.vb" />
|
||||
<Compile Include="IDB\Database.vb" />
|
||||
<Compile Include="IDB\FileStore.vb" />
|
||||
<Compile Include="Base\BaseClass.vb" />
|
||||
<Compile Include="Base\BaseUtils.vb" />
|
||||
<Compile Include="Encryption\Compression.vb" />
|
||||
<Compile Include="Encryption\Encryption.vb" />
|
||||
<Compile Include="Encryption\EncryptionLegacy.vb" />
|
||||
<Compile Include="DatabaseEx.vb" />
|
||||
<Compile Include="FilesystemEx.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcher.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcherFilters.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcherProperties.vb" />
|
||||
<Compile Include="IDB\Constants.vb" />
|
||||
<Compile Include="MimeEx.vb" />
|
||||
<Compile Include="WindowsEx.vb" />
|
||||
<Compile Include="ModuleExtensions.vb" />
|
||||
<Compile Include="FileEx.vb" />
|
||||
<Compile Include="NativeMethods.vb" />
|
||||
<Compile Include="ObjectEx.vb" />
|
||||
<Compile Include="GraphicsEx.vb" />
|
||||
<Compile Include="LanguageEx.vb" />
|
||||
<Compile Include="My Project\AssemblyInfo.vb" />
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -95,7 +112,8 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="Performance.vb" />
|
||||
<Compile Include="ScreenEx.vb" />
|
||||
<Compile Include="StringEx.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="My Project\Resources.resx">
|
||||
@@ -126,5 +144,9 @@
|
||||
<Name>Logging</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>powershell.exe -command "& { &'$(SolutionDir)copy-binary.ps1' '$(TargetPath)' '$(TargetFileName)' '$(ConfigurationName)' }"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
7
Base/Base/BaseUtils.vb
Normal file
7
Base/Base/BaseUtils.vb
Normal file
@@ -0,0 +1,7 @@
|
||||
Friend Class BaseUtils
|
||||
Friend Shared Function FormatHash(pChecksum)
|
||||
Return BitConverter.
|
||||
ToString(pChecksum).
|
||||
Replace("-", String.Empty)
|
||||
End Function
|
||||
End Class
|
||||
17
Base/DatabaseEx.vb
Normal file
17
Base/DatabaseEx.vb
Normal file
@@ -0,0 +1,17 @@
|
||||
Public Class DatabaseEx
|
||||
''' <summary>
|
||||
''' TODO: Deprecate
|
||||
''' Checks a Row value for three different `null` values,
|
||||
''' Nothing, Empty String, DBNull
|
||||
'''
|
||||
''' Returns the original value if the value is not null, or `defaultValue`
|
||||
''' </summary>
|
||||
''' <typeparam name="T">The type of the value</typeparam>
|
||||
''' <param name="pRow">The DataRow that contains the value</param>
|
||||
''' <param name="pColumn">The column name</param>
|
||||
''' <param name="pDefaultValue">The default value</param>
|
||||
''' <returns>The original value or the default value</returns>
|
||||
Public Shared Function NotNull(Of T)(ByVal pRow As DataRow, pColumn As String, pDefaultValue As T) As T
|
||||
Return ObjectEx.NotNull(pRow.Item(pColumn), pDefaultValue)
|
||||
End Function
|
||||
End Class
|
||||
@@ -1,7 +0,0 @@
|
||||
Public Class ECM
|
||||
Public Enum Product
|
||||
ProcessManager
|
||||
GlobalIndexer
|
||||
ClipboardWatcher
|
||||
End Enum
|
||||
End Class
|
||||
70
Base/Encryption/Compression.vb
Normal file
70
Base/Encryption/Compression.vb
Normal file
@@ -0,0 +1,70 @@
|
||||
Imports System.IO
|
||||
Imports System.IO.Compression
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class Compression
|
||||
Private ReadOnly _logger As Logger
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
_logger = LogConfig.GetLogger()
|
||||
End Sub
|
||||
|
||||
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()
|
||||
Try
|
||||
' 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
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
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()
|
||||
Try
|
||||
' 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
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
End Class
|
||||
148
Base/Encryption/Encryption.vb
Normal file
148
Base/Encryption/Encryption.vb
Normal file
@@ -0,0 +1,148 @@
|
||||
Imports System.IO
|
||||
Imports System.Security.Cryptography
|
||||
Imports System.Text.Encoding
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
''' <summary>
|
||||
''' https://stackoverflow.com/questions/10168240/encrypting-decrypting-a-string-in-c-sharp
|
||||
''' </summary>
|
||||
Public 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 KEY_SIZE As Integer = 256
|
||||
' This constant determines the number of iterations for the password bytes generation function.
|
||||
Private Const DERIVATION_ITERATIONS As Integer = 1000
|
||||
Private Const BLOCK_SIZE As Integer = 256
|
||||
|
||||
Private _paddingMode As PaddingMode = PaddingMode.Zeros
|
||||
Private _cipherMode As CipherMode = CipherMode.CBC
|
||||
|
||||
Private ReadOnly _password As String
|
||||
Private _logger As Logger
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Password As String)
|
||||
_logger = LogConfig.GetLogger()
|
||||
|
||||
If IsNothing(Password) Then
|
||||
Throw New ArgumentNullException("Password")
|
||||
End If
|
||||
|
||||
_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(PlainText As String) As String
|
||||
Try
|
||||
Dim oBytes As Byte() = UTF8.GetBytes(PlainText)
|
||||
Dim oEncrypted As Byte() = Encrypt(oBytes)
|
||||
Return UTF8.GetString(oEncrypted)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function Encrypt(PlainTextBytes As Byte()) As Byte()
|
||||
Try
|
||||
' 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 oSaltStringBytes = Generate256BitsOfRandomEntropy()
|
||||
Dim oIvStringBytes = Generate256BitsOfRandomEntropy()
|
||||
Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS)
|
||||
Dim oKeyBytes = oPassword.GetBytes(KEY_SIZE / 8)
|
||||
Using oSymmetricKey = New RijndaelManaged()
|
||||
oSymmetricKey.BlockSize = BLOCK_SIZE
|
||||
oSymmetricKey.Mode = _cipherMode
|
||||
oSymmetricKey.Padding = _paddingMode
|
||||
|
||||
Using oEncryptor = oSymmetricKey.CreateEncryptor(oKeyBytes, oIvStringBytes)
|
||||
Using oMemoryStream = New MemoryStream()
|
||||
Using oCryptoStream = New CryptoStream(oMemoryStream, oEncryptor, CryptoStreamMode.Write)
|
||||
oCryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length)
|
||||
oCryptoStream.FlushFinalBlock()
|
||||
' Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
|
||||
Dim oCipherTextBytes = oSaltStringBytes
|
||||
oCipherTextBytes = oCipherTextBytes.Concat(oIvStringBytes).ToArray()
|
||||
oCipherTextBytes = oCipherTextBytes.Concat(oMemoryStream.ToArray()).ToArray()
|
||||
oMemoryStream.Close()
|
||||
oCryptoStream.Close()
|
||||
Return oCipherTextBytes
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
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(CipherTextPlainWithSaltAndIv As String) As String
|
||||
Try
|
||||
Dim oBytes As Byte() = UTF8.GetBytes(CipherTextPlainWithSaltAndIv)
|
||||
Dim oDecrypted As Byte() = Decrypt(oBytes)
|
||||
Return UTF8.GetString(oDecrypted)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function Decrypt(CipherTextBytesWithSaltAndIv As Byte()) As Byte()
|
||||
Try
|
||||
' 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 oSaltStringBytes = CipherTextBytesWithSaltAndIv.Take(KEY_SIZE / 8).ToArray()
|
||||
' Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
|
||||
Dim oIvStringBytes = CipherTextBytesWithSaltAndIv.Skip(KEY_SIZE / 8).Take(KEY_SIZE / 8).ToArray()
|
||||
' Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
|
||||
Dim oCipherTextBytes = CipherTextBytesWithSaltAndIv.Skip((KEY_SIZE / 8) * 2).Take(CipherTextBytesWithSaltAndIv.Length - ((KEY_SIZE / 8) * 2)).ToArray()
|
||||
|
||||
Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS)
|
||||
Dim oKeyBytes = oPassword.GetBytes(KEY_SIZE / 8)
|
||||
Using oSymmetricKey = New RijndaelManaged()
|
||||
oSymmetricKey.BlockSize = BLOCK_SIZE
|
||||
oSymmetricKey.Mode = _cipherMode
|
||||
oSymmetricKey.Padding = _paddingMode
|
||||
Using oDecryptor = oSymmetricKey.CreateDecryptor(oKeyBytes, oIvStringBytes)
|
||||
Using oMemoryStream = New MemoryStream(oCipherTextBytes)
|
||||
Using oCryptoStream = New CryptoStream(oMemoryStream, oDecryptor, CryptoStreamMode.Read)
|
||||
Dim oPlainTextBytes = New Byte(oCipherTextBytes.Length - 1) {}
|
||||
Dim oDecryptedByteCount = oCryptoStream.Read(oPlainTextBytes, 0, oPlainTextBytes.Length)
|
||||
oMemoryStream.Close()
|
||||
oCryptoStream.Close()
|
||||
Return oPlainTextBytes
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Shared Function Generate256BitsOfRandomEntropy() As Byte()
|
||||
Dim oRandomBytes = New Byte(31) {}
|
||||
' 32 Bytes will give us 256 bits.
|
||||
Using oRNGCsp = New RNGCryptoServiceProvider()
|
||||
' Fill the array with cryptographically secure random bytes.
|
||||
oRNGCsp.GetBytes(oRandomBytes)
|
||||
End Using
|
||||
Return oRandomBytes
|
||||
End Function
|
||||
End Class
|
||||
85
Base/Encryption/EncryptionLegacy.vb
Normal file
85
Base/Encryption/EncryptionLegacy.vb
Normal file
@@ -0,0 +1,85 @@
|
||||
Imports System.Security.Cryptography
|
||||
Imports System.Data
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Public Class EncryptionLegacy
|
||||
Private TripleDes As New TripleDESCryptoServiceProvider
|
||||
Private DEFAULT_KEY As String = "!35452didalog="
|
||||
Private SALT_VALUE As String = "!Didalog35452Heuchelheim="
|
||||
|
||||
Sub New()
|
||||
TripleDes.Key = TruncateHash(DEFAULT_KEY, TripleDes.KeySize \ 8)
|
||||
TripleDes.IV = TruncateHash("", TripleDes.BlockSize \ 8)
|
||||
End Sub
|
||||
|
||||
Sub New(key As String)
|
||||
' Initialize the crypto provider.
|
||||
TripleDes.Key = TruncateHash(key, TripleDes.KeySize \ 8)
|
||||
TripleDes.IV = TruncateHash("", TripleDes.BlockSize \ 8)
|
||||
End Sub
|
||||
|
||||
Private Function TruncateHash(ByVal key As String, ByVal length As Integer) As Byte()
|
||||
Dim sha1 As New SHA1CryptoServiceProvider
|
||||
|
||||
' Hash the key.
|
||||
Dim keyBytes() As Byte =
|
||||
System.Text.Encoding.Unicode.GetBytes(key)
|
||||
Dim hash() As Byte = sha1.ComputeHash(keyBytes)
|
||||
|
||||
' Truncate or pad the hash.
|
||||
ReDim Preserve hash(length - 1)
|
||||
Return hash
|
||||
End Function
|
||||
|
||||
<DebuggerStepThrough>
|
||||
Public Function EncryptData(ByVal plaintext As String) As String
|
||||
Try
|
||||
' Convert the plaintext string to a byte array.
|
||||
Dim plaintextBytes() As Byte =
|
||||
System.Text.Encoding.Unicode.GetBytes(SALT_VALUE & plaintext)
|
||||
|
||||
' Create the stream.
|
||||
Dim ms As New System.IO.MemoryStream
|
||||
' Create the encoder to write to the stream.
|
||||
Dim encStream As New CryptoStream(ms,
|
||||
TripleDes.CreateEncryptor(),
|
||||
System.Security.Cryptography.CryptoStreamMode.Write)
|
||||
|
||||
' Use the crypto stream to write the byte array to the stream.
|
||||
encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
|
||||
encStream.FlushFinalBlock()
|
||||
|
||||
' Convert the encrypted stream to a printable string.
|
||||
Return Convert.ToBase64String(ms.ToArray)
|
||||
Catch ex As Exception
|
||||
Return plaintext
|
||||
End Try
|
||||
End Function
|
||||
|
||||
'Entschlüsselt die Zeichenfolge
|
||||
<DebuggerStepThrough>
|
||||
Public Function DecryptData(ByVal EncryptedText As String) As String
|
||||
Try
|
||||
' Convert the encrypted text string to a byte array.
|
||||
Dim oEncryptedBytes() As Byte = Convert.FromBase64String(EncryptedText)
|
||||
|
||||
' Create the stream.
|
||||
Dim oMemoryStream As New System.IO.MemoryStream
|
||||
' Create the decoder to write to the stream.
|
||||
Dim oCryptoStream As New CryptoStream(oMemoryStream,
|
||||
TripleDes.CreateDecryptor(),
|
||||
System.Security.Cryptography.CryptoStreamMode.Write)
|
||||
|
||||
' Use the crypto stream to write the byte array to the stream.
|
||||
oCryptoStream.Write(oEncryptedBytes, 0, oEncryptedBytes.Length)
|
||||
oCryptoStream.FlushFinalBlock()
|
||||
Dim oResult = System.Text.Encoding.Unicode.GetString(oMemoryStream.ToArray)
|
||||
oResult = oResult.Replace(SALT_VALUE, "")
|
||||
' Convert the plaintext stream to a string.
|
||||
Return oResult
|
||||
Catch ex As Exception
|
||||
Return EncryptedText
|
||||
End Try
|
||||
End Function
|
||||
End Class
|
||||
|
||||
78
Base/FileEx.vb
Normal file
78
Base/FileEx.vb
Normal file
@@ -0,0 +1,78 @@
|
||||
Imports System.IO
|
||||
Imports System.Security.Cryptography
|
||||
|
||||
Public Class FileEx
|
||||
''' <summary>
|
||||
''' Reads the file at `FilePath` and computes a SHA256 Hash from its contents
|
||||
''' </summary>
|
||||
''' <param name="pFilePath"></param>
|
||||
''' <returns></returns>
|
||||
Public Shared Function GetChecksumFromFileContents(pFilePath As String) As String
|
||||
Try
|
||||
Using oFileStream = IO.File.OpenRead(pFilePath)
|
||||
Using oStream As New BufferedStream(oFileStream, 1200000)
|
||||
Dim oChecksum() As Byte = SHA256.Create.ComputeHash(oStream)
|
||||
Return BaseUtils.FormatHash(oChecksum)
|
||||
End Using
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Shared Function GetHashFromFileContents(pFilePath As String) As String
|
||||
Return GetChecksumFromFileContents(pFilePath)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Returns a Dictionary path in the form of [Base]\[Year]\[Month]\[Day]
|
||||
''' </summary>
|
||||
''' <param name="pBaseDirectory">The basedirectory</param>
|
||||
''' <param name="pDate">The date to be used</param>
|
||||
''' <returns>The final directory path</returns>
|
||||
Public Shared Function GetDateDirectory(pBaseDirectory As String, pDate As Date) As String
|
||||
Dim oDateDirectory = StringEx.GetDateString(pDate)
|
||||
Dim oFinalDirectory As String = Path.Combine(pBaseDirectory, oDateDirectory)
|
||||
Return oFinalDirectory
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Returns a Dictionary path in the form of [Base]\[Year]\[Month]\[Day] based on the current date
|
||||
''' </summary>
|
||||
''' <param name="pBaseDirectory">The basedirectory</param>
|
||||
''' <returns>The final directory path</returns>
|
||||
Public Shared Function GetDateDirectory(pBaseDirectory As String) As String
|
||||
Return GetDateDirectory(pBaseDirectory, Now)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Creates a Dictionary in the form of [Base]\[Year]\[Month]\[Day]
|
||||
''' </summary>
|
||||
''' <param name="pBaseDirectory">The basedirectory</param>
|
||||
''' <param name="pDate">The date to be used</param>
|
||||
''' <returns>The created path. If the directory cannot be created, Nothing.</returns>
|
||||
Public Shared Function CreateDateDirectory(pBaseDirectory As String, pDate As Date) As String
|
||||
Dim oDateDirectory = StringEx.GetDateString(pDate)
|
||||
Dim oFinalDirectory As String = Path.Combine(pBaseDirectory, oDateDirectory)
|
||||
|
||||
If Directory.Exists(oFinalDirectory) = False Then
|
||||
Try
|
||||
Directory.CreateDirectory(oFinalDirectory)
|
||||
Catch ex As Exception
|
||||
Return Nothing
|
||||
End Try
|
||||
End If
|
||||
|
||||
Return oFinalDirectory
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Creates a Dictionary in the form of [Base]\[Year]\[Month]\[Day] based on the current date
|
||||
''' </summary>
|
||||
''' <param name="pBaseDirectory">The basedirectory</param>
|
||||
''' <returns>The created path. If the directory cannot be created, Nothing.</returns>
|
||||
Public Shared Function CreateDateDirectory(pBaseDirectory As String) As String
|
||||
Return CreateDateDirectory(pBaseDirectory, Now)
|
||||
End Function
|
||||
|
||||
End Class
|
||||
@@ -1,6 +1,5 @@
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Filesystem
|
||||
Imports DigitalData.Modules.Filesystem.FileWatcherFilters
|
||||
Imports DigitalData.Modules.Base.FileWatcherFilters
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
|
||||
@@ -1,29 +1,10 @@
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports System.IO
|
||||
Imports System.Security.Cryptography
|
||||
Imports System.Text
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
''' <module>File</module>
|
||||
''' <version>0.0.0.1</version>
|
||||
''' <date>11.10.2018</date>
|
||||
''' <summary>
|
||||
''' Module that provides variouse File operations
|
||||
''' </summary>
|
||||
''' <dependencies>
|
||||
''' NLog, >= 4.5.8
|
||||
''' </dependencies>
|
||||
''' <params>
|
||||
''' LogConfig, DigitalData.Module.Logging.LogConfig
|
||||
''' A LogConfig object
|
||||
''' </params>
|
||||
''' <props>
|
||||
''' </props>
|
||||
''' <example>
|
||||
''' </example>
|
||||
''' <remarks>
|
||||
''' </remarks>
|
||||
Public Class File
|
||||
Public Class FilesystemEx
|
||||
Private ReadOnly _Logger As Logger
|
||||
Private ReadOnly _LogConfig As LogConfig
|
||||
|
||||
@@ -39,6 +20,10 @@ Public Class File
|
||||
' Source: https://docs.microsoft.com/de-de/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#maximum-path-length-limitation
|
||||
Private Const MAX_FILE_PATH_LENGTH = 250
|
||||
|
||||
' This prevents an infinite loop when no file can be created in a location
|
||||
Private Const MAX_FILE_VERSION = 100
|
||||
Private Const VERSION_SEPARATOR As Char = "~"c
|
||||
|
||||
Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt"
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
@@ -100,6 +85,14 @@ Public Class File
|
||||
Return FormatHash(oChecksum)
|
||||
End Function
|
||||
|
||||
Public Function GetHash(FilePath As String) As String
|
||||
Return GetChecksum(FilePath)
|
||||
End Function
|
||||
|
||||
Public Function GetHashFromString(pStringToCheck As String) As String
|
||||
Return GetChecksumFromString(pStringToCheck)
|
||||
End Function
|
||||
|
||||
Private Function FormatHash(pChecksum)
|
||||
Return BitConverter.
|
||||
ToString(pChecksum).
|
||||
@@ -109,53 +102,65 @@ Public Class File
|
||||
''' <summary>
|
||||
''' Adds file version string to given filename `Destination` if that file already exists.
|
||||
''' </summary>
|
||||
''' <param name="Destination"></param>
|
||||
''' <returns></returns>
|
||||
Public Function GetVersionedFilename(Destination As String) As String
|
||||
''' <param name="pFilePath">Filepath to check</param>
|
||||
''' <returns>Versioned string</returns>
|
||||
Public Function GetVersionedFilename(pFilePath As String) As String
|
||||
Return GetVersionedFilenameWithFilecheck(pFilePath, Function(pPath As String) IO.File.Exists(pPath))
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Adds file version string to given filename `Destination` if that file already exists.
|
||||
''' </summary>
|
||||
''' <param name="pFilePath">Filepath to check</param>
|
||||
''' <param name="pFileExistsAction">Custom action to check for file existence</param>
|
||||
''' <returns>Versioned string</returns>
|
||||
Public Function GetVersionedFilenameWithFilecheck(pFilePath As String, pFileExistsAction As Func(Of String, Boolean)) As String
|
||||
Try
|
||||
Dim oFileName As String = Destination
|
||||
Dim oFileName As String = pFilePath
|
||||
Dim oFinalFileName = oFileName
|
||||
|
||||
Dim oDestinationDir = Path.GetDirectoryName(oFileName)
|
||||
Dim oExtension = Path.GetExtension(oFileName)
|
||||
|
||||
Dim oVersionSeparator As Char = "~"c
|
||||
|
||||
|
||||
Dim oFileNameWithoutExtension = Path.GetFileNameWithoutExtension(oFileName)
|
||||
Dim oSplitResult = GetVersionedString(oFileNameWithoutExtension, oVersionSeparator)
|
||||
Dim oSplitResult = GetVersionedString(oFileNameWithoutExtension)
|
||||
|
||||
oFileNameWithoutExtension = oSplitResult.Item1
|
||||
Dim oFileVersion = oSplitResult.Item2
|
||||
Dim oFileVersion As Integer = oSplitResult.Item2
|
||||
|
||||
' Shorten the filename (only filename, without extension or version)
|
||||
' by cutting the length in half. This should work no matter how long the path and/or filename are.
|
||||
' The initial check operates on the full path to catch all scenarios.
|
||||
If Destination.Length > MAX_FILE_PATH_LENGTH Then
|
||||
If pFilePath.Length > MAX_FILE_PATH_LENGTH Then
|
||||
_Logger.Info("Filename is too long. Filename will be cut to prevent further errors.")
|
||||
_Logger.Info("Original Filename is: {0}", oFileNameWithoutExtension)
|
||||
Dim oNewLength As Integer = Math.Round(oFileNameWithoutExtension.Length / 2)
|
||||
Dim oNewLength As Integer = CInt(Math.Floor(oFileNameWithoutExtension.Length / 2.0))
|
||||
Dim oNewFileNameWithoutExtension = oFileNameWithoutExtension.Substring(0, oNewLength)
|
||||
_Logger.Info("New Filename will be: {0}", oNewFileNameWithoutExtension)
|
||||
|
||||
oFileNameWithoutExtension = oNewFileNameWithoutExtension
|
||||
End If
|
||||
|
||||
' while file exists, increment version
|
||||
' while file exists, increment version.
|
||||
' version cannot go above MAX_FILE_VERSION, to prevent infinite loop
|
||||
Do
|
||||
oFinalFileName = Path.Combine(oDestinationDir, GetFilenameWithVersion(oFileNameWithoutExtension, oVersionSeparator, oFileVersion, oExtension))
|
||||
oFinalFileName = Path.Combine(oDestinationDir, GetFilenameWithVersion(oFileNameWithoutExtension, oFileVersion, oExtension))
|
||||
_Logger.Debug("Intermediate Filename is {0}", oFinalFileName)
|
||||
_Logger.Debug("File version: {0}", oFileVersion)
|
||||
oFileVersion += 1
|
||||
Loop While (IO.File.Exists(oFinalFileName))
|
||||
Loop While pFileExistsAction(oFinalFileName) = True And oFileVersion < MAX_FILE_VERSION
|
||||
|
||||
If oFileVersion >= MAX_FILE_VERSION Then
|
||||
Throw New OverflowException($"Tried '{MAX_FILE_VERSION}' times to version filename before giving up. Sorry.")
|
||||
End If
|
||||
|
||||
_Logger.Debug("Final Filename is {0}", oFinalFileName)
|
||||
|
||||
Return oFinalFileName
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", Destination)
|
||||
_Logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", pFilePath)
|
||||
_Logger.Error(ex)
|
||||
Return Destination
|
||||
Return pFilePath
|
||||
End Try
|
||||
End Function
|
||||
|
||||
@@ -174,8 +179,8 @@ Public Class File
|
||||
''' <param name="pString">The string to versioned</param>
|
||||
''' <param name="pSeparator">The character to split at</param>
|
||||
''' <returns>Tuple of string and version</returns>
|
||||
Public Function GetVersionedString(pString As String, pSeparator As Char) As Tuple(Of String, Integer)
|
||||
Dim oSplitString = pString.Split(pSeparator).ToList()
|
||||
Public Function GetVersionedString(pString As String) As Tuple(Of String, Integer)
|
||||
Dim oSplitString = pString.Split(VERSION_SEPARATOR).ToList()
|
||||
Dim oStringVersion As Integer
|
||||
|
||||
' if string is already versioned, extract string version
|
||||
@@ -195,6 +200,8 @@ Public Class File
|
||||
oStringVersion = 1
|
||||
End If
|
||||
|
||||
_Logger.Debug("Versioned: String [{0}], Version [{1}]", pString, oStringVersion)
|
||||
|
||||
Return New Tuple(Of String, Integer)(pString, oStringVersion)
|
||||
End Function
|
||||
|
||||
@@ -203,11 +210,11 @@ Public Class File
|
||||
Return Path.Combine(oLocalAppData, CompanyName, ProductName)
|
||||
End Function
|
||||
|
||||
Private Function GetFilenameWithVersion(FileNameWithoutExtension As String, VersionSeparator As Char, FileVersion As Integer, Extension As String) As String
|
||||
Private Function GetFilenameWithVersion(FileNameWithoutExtension As String, FileVersion As Integer, Extension As String) As String
|
||||
If FileVersion <= 1 Then
|
||||
Return $"{FileNameWithoutExtension}{Extension}"
|
||||
Else
|
||||
Return $"{FileNameWithoutExtension}{VersionSeparator}{FileVersion}{Extension}"
|
||||
Return $"{FileNameWithoutExtension}{VERSION_SEPARATOR}{FileVersion}{Extension}"
|
||||
End If
|
||||
End Function
|
||||
|
||||
@@ -290,7 +297,7 @@ Public Class File
|
||||
''' <param name="DestDirName"></param>
|
||||
''' <param name="CopySubDirs"></param>
|
||||
Public Sub CopyDirectory(ByVal SourceDirName As String, ByVal DestDirName As String, ByVal CopySubDirs As Boolean)
|
||||
Dim oDirectory As DirectoryInfo = New DirectoryInfo(SourceDirName)
|
||||
Dim oDirectory As New DirectoryInfo(SourceDirName)
|
||||
|
||||
If Not oDirectory.Exists Then
|
||||
Throw New DirectoryNotFoundException("Source directory does not exist or could not be found: " & SourceDirName)
|
||||
@@ -392,6 +399,34 @@ Public Class File
|
||||
Return oIsDirectory
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Checks the size of the supplied file.
|
||||
''' </summary>
|
||||
''' <param name="pFilePath"></param>
|
||||
''' <param name="pMaxFileSizeInMegaBytes"></param>
|
||||
''' <returns></returns>
|
||||
Public Function TestFileSizeIsLessThanMaxFileSize(pFilePath As String, pMaxFileSizeInMegabytes As Integer) As Boolean
|
||||
Dim oFileInfo As New FileInfo(pFilePath)
|
||||
|
||||
_Logger.Info("Checking Filesize of {0}", oFileInfo.Name)
|
||||
_Logger.Debug("Filesize threshold is {0} MB.", pMaxFileSizeInMegabytes)
|
||||
|
||||
If pMaxFileSizeInMegabytes <= 0 Then
|
||||
_Logger.Debug("Filesize is not configured. Skipping check.")
|
||||
Return True
|
||||
End If
|
||||
|
||||
Dim oMaxSize = pMaxFileSizeInMegabytes * 1024 * 1024
|
||||
|
||||
If oMaxSize > 0 And oFileInfo.Length > oMaxSize Then
|
||||
_Logger.Debug("Filesize is bigger than threshold.")
|
||||
Return False
|
||||
Else
|
||||
_Logger.Debug("Filesize is smaller than threshold. All fine.")
|
||||
Return True
|
||||
End If
|
||||
End Function
|
||||
|
||||
Public Function GetDateDirectory(pBaseDirectory As String, pDate As Date) As String
|
||||
Dim oDateDirectory = GetDateString(pDate)
|
||||
Dim oFinalDirectory As String = IO.Path.Combine(pBaseDirectory, oDateDirectory)
|
||||
@@ -457,5 +492,4 @@ Public Class File
|
||||
Public Function GetFilenameWithPrefix(pBaseString As String, pPrefix As String, pExtension As String)
|
||||
Return $"{pPrefix}-{pBaseString}.{pExtension}"
|
||||
End Function
|
||||
|
||||
End Class
|
||||
43
Base/GraphicsEx.vb
Normal file
43
Base/GraphicsEx.vb
Normal file
@@ -0,0 +1,43 @@
|
||||
Imports System.Drawing
|
||||
|
||||
Public Class GraphicsEx
|
||||
|
||||
''' <summary>
|
||||
''' Returns the brightness of a color as a number between 0 and 1
|
||||
''' </summary>
|
||||
''' <param name="pColor">The color to check</param>
|
||||
''' <returns>Low values for dark colors, high values for bright colors.</returns>
|
||||
Public Shared Function GetBrightness(pColor As Color) As Single
|
||||
Return (pColor.R * 0.299F + pColor.G * 0.587F + pColor.B * 0.114F) / 256.0F
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Returns a foreground/text color of either black or white, depending on the brightness of `pOtherColor`
|
||||
''' </summary>
|
||||
''' <param name="pOtherColor">The Background color whose brightness is determined</param>
|
||||
''' <returns>A text color which is either white or black</returns>
|
||||
Public Shared Function GetContrastedColor(pOtherColor As Color) As Color
|
||||
If GetBrightness(pOtherColor) < 0.55 Then
|
||||
Return Color.White
|
||||
Else
|
||||
Return Color.Black
|
||||
End If
|
||||
End Function
|
||||
|
||||
Public Sub DrawRectangle(Bounds As Rectangle)
|
||||
Dim oContext As IntPtr
|
||||
oContext = NativeMethods.GetDC(IntPtr.Zero)
|
||||
|
||||
Try
|
||||
Dim g As Graphics
|
||||
g = Graphics.FromHdc(oContext)
|
||||
Try
|
||||
g.DrawRectangle(Pens.Red, Bounds)
|
||||
Finally
|
||||
g.Dispose()
|
||||
End Try
|
||||
Finally
|
||||
NativeMethods.ReleaseDC(IntPtr.Zero, oContext)
|
||||
End Try
|
||||
End Sub
|
||||
End Class
|
||||
@@ -1,15 +0,0 @@
|
||||
Namespace IDB
|
||||
Public Class Attributes
|
||||
Public Const ATTRIBUTE_DOCTYPE = "Doctype"
|
||||
Public Const ATTRIBUTE_DYNAMIC_FOLDER = "Dynamic Folder"
|
||||
|
||||
Public Const ATTRIBUTE_ORIGIN_FILENAME = "OriginFileName"
|
||||
Public Const ATTRIBUTE_ORIGIN_CHANGED = "OriginChangedDatetime"
|
||||
Public Const ATTRIBUTE_ORIGIN_CREATED = "OriginCreationDatetime"
|
||||
|
||||
Public Const ATTRIBUTE_DISPLAY_FILENAME = "DisplayFileName"
|
||||
Public Const ATTRIBUTE_DISPLAY_FILENAME1 = "DisplayFileName1"
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
43
Base/IDB/Constants.vb
Normal file
43
Base/IDB/Constants.vb
Normal file
@@ -0,0 +1,43 @@
|
||||
Namespace IDB
|
||||
|
||||
Public Class Constants
|
||||
Public Class FileStore
|
||||
Public Const FILE_STORE_INVALID_OBEJCT_ID = 0
|
||||
|
||||
Public Const FILE_CHANGED_QUESTION = "QUESTION VERSION"
|
||||
Public Const FILE_CHANGED_OVERWRITE = "AUTO REPLACE"
|
||||
Public Const FILE_CHANGED_VERSION = "AUTO VERSION"
|
||||
|
||||
Public Const OBJECT_STATE_FILE_ADDED = "File added"
|
||||
Public Const OBJECT_STATE_FILE_VERSIONED = "File versioned"
|
||||
Public Const OBJECT_STATE_FILE_CHANGED = "File changed"
|
||||
Public Const OBJECT_STATE_FILE_OPENED = "File opened"
|
||||
Public Const OBJECT_STATE_FILE_DELETED = "File deleted"
|
||||
Public Const OBJECT_STATE_METADATA_CHANGED = "Metadata changed"
|
||||
Public Const OBJECT_STATE_ATTRIBUTEVALUE_DELETED = "Attributevalue deleted"
|
||||
Public Const OBJECT_STATE_FILE_CHECKED_OUT = "File Checked Out"
|
||||
Public Const OBJECT_STATE_FILE_CHECKED_IN = "File Checked In"
|
||||
End Class
|
||||
|
||||
Public Class Database
|
||||
Public Enum NamedDatabase
|
||||
ECM
|
||||
IDB
|
||||
End Enum
|
||||
End Class
|
||||
|
||||
Public Class Attributes
|
||||
Public Const ATTRIBUTE_DOCTYPE = "Doctype"
|
||||
Public Const ATTRIBUTE_DYNAMIC_FOLDER = "Dynamic Folder"
|
||||
|
||||
Public Const ATTRIBUTE_ORIGIN_FILENAME = "OriginFileName"
|
||||
Public Const ATTRIBUTE_ORIGIN_CHANGED = "OriginChangedDatetime"
|
||||
Public Const ATTRIBUTE_ORIGIN_CREATED = "OriginCreationDatetime"
|
||||
|
||||
Public Const ATTRIBUTE_DISPLAY_FILENAME = "DisplayFileName"
|
||||
Public Const ATTRIBUTE_DISPLAY_FILENAME1 = "DisplayFileName1"
|
||||
|
||||
End Class
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
Namespace IDB
|
||||
Public Class Database
|
||||
Public Enum NamedDatabase
|
||||
ECM
|
||||
IDB
|
||||
End Enum
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
Namespace IDB
|
||||
Public Class FileStore
|
||||
Public Const FILE_STORE_INVALID_OBEJCT_ID = 0
|
||||
|
||||
Public Const FILE_CHANGED_QUESTION = "QUESTION VERSION"
|
||||
Public Const FILE_CHANGED_OVERWRITE = "AUTO REPLACE"
|
||||
Public Const FILE_CHANGED_VERSION = "AUTO VERSION"
|
||||
|
||||
Public Const OBJECT_STATE_FILE_ADDED = "File added"
|
||||
Public Const OBJECT_STATE_FILE_VERSIONED = "File versioned"
|
||||
Public Const OBJECT_STATE_FILE_CHANGED = "File changed"
|
||||
Public Const OBJECT_STATE_FILE_OPENED = "File opened"
|
||||
Public Const OBJECT_STATE_FILE_DELETED = "File deleted"
|
||||
Public Const OBJECT_STATE_METADATA_CHANGED = "Metadata changed"
|
||||
Public Const OBJECT_STATE_ATTRIBUTEVALUE_DELETED = "Attributevalue deleted"
|
||||
Public Const OBJECT_STATE_FILE_CHECKED_OUT = "File Checked Out"
|
||||
Public Const OBJECT_STATE_FILE_CHECKED_IN = "File Checked In"
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
55
Base/LanguageEx.vb
Normal file
55
Base/LanguageEx.vb
Normal file
@@ -0,0 +1,55 @@
|
||||
Imports System.Globalization
|
||||
Imports System.Threading
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
''' <summary>
|
||||
''' Functions relating to i18n, Cultures, Translations
|
||||
''' </summary>
|
||||
Public Class LanguageEx
|
||||
''' <summary>
|
||||
''' Sets the Language of the current thread by setting CurrentCulture and CurrentUICulture
|
||||
''' </summary>
|
||||
''' <param name="pLogger">A Logger instance</param>
|
||||
''' <param name="pUserLanguage">A language code in the form of 'de-DE'</param>
|
||||
''' <param name="pUserDateFormat">A custom date pattern</param>
|
||||
Public Shared Sub SetApplicationLanguage(pLogger As Logger, pUserLanguage As String, Optional pUserDateFormat As String = Nothing)
|
||||
Try
|
||||
pLogger.Debug("Setting application language..")
|
||||
|
||||
Dim Culture As New CultureInfo(pUserLanguage)
|
||||
If String.IsNullOrEmpty(pUserDateFormat) = False Then
|
||||
Culture.DateTimeFormat.ShortDatePattern = pUserDateFormat
|
||||
End If
|
||||
|
||||
pLogger.Debug("Culture object for language [{0}] created", pUserLanguage)
|
||||
|
||||
' The following line provides localization for data formats.
|
||||
Thread.CurrentThread.CurrentCulture = Culture
|
||||
' The following line provides localization for the application's user interface.
|
||||
Thread.CurrentThread.CurrentUICulture = Culture
|
||||
|
||||
' Set this culture as the default culture for all threads in this application.
|
||||
' Note: The following properties are supported in the .NET Framework 4.5+
|
||||
CultureInfo.DefaultThreadCurrentCulture = Culture
|
||||
CultureInfo.DefaultThreadCurrentUICulture = Culture
|
||||
|
||||
pLogger.Debug("Application language set to [{0}]", Culture.Name)
|
||||
Catch ex As Exception
|
||||
pLogger.Warn("Could not set application language!")
|
||||
pLogger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' Logs the culture settings of the current thread
|
||||
''' </summary>
|
||||
''' <param name="pLogger">A Logger instance</param>
|
||||
Public Shared Sub LogApplicationLanguage(pLogger As Logger)
|
||||
pLogger.Debug("=== Application Language ===")
|
||||
pLogger.Debug("Thread.CurrentThread.CurrentCulture: [{0}]", Thread.CurrentThread.CurrentCulture)
|
||||
pLogger.Debug("Thread.CurrentThread.CurrentUICulture: [{0}]", Thread.CurrentThread.CurrentUICulture)
|
||||
pLogger.Debug("CultureInfo.DefaultThreadCurrentCulture: [{0}]", CultureInfo.DefaultThreadCurrentCulture)
|
||||
pLogger.Debug("CultureInfo.DefaultThreadCurrentUICulture: [{0}]", CultureInfo.DefaultThreadCurrentUICulture)
|
||||
|
||||
End Sub
|
||||
End Class
|
||||
685
Base/MimeEx.vb
Normal file
685
Base/MimeEx.vb
Normal file
@@ -0,0 +1,685 @@
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class MimeEx
|
||||
Inherits BaseClass
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig)
|
||||
MyBase.New(pLogConfig)
|
||||
End Sub
|
||||
|
||||
Public Function GetMimeType(ByVal extension As String) As String
|
||||
If extension Is Nothing Then
|
||||
Throw New ArgumentNullException("extension")
|
||||
End If
|
||||
|
||||
If Not extension.StartsWith(".") Then
|
||||
extension = "." & extension
|
||||
End If
|
||||
|
||||
Dim value = Nothing
|
||||
|
||||
If Not _mappings.Value.TryGetValue(extension, value) Then
|
||||
Return "application/octet-stream"
|
||||
End If
|
||||
|
||||
Return value
|
||||
End Function
|
||||
|
||||
Public Function GetExtension(ByVal mimeType As String) As String
|
||||
If mimeType Is Nothing Then
|
||||
Throw New ArgumentNullException("mimeType")
|
||||
End If
|
||||
|
||||
If mimeType.StartsWith(".") Then
|
||||
Throw New ArgumentException("Requested mime type is not valid: " & mimeType)
|
||||
End If
|
||||
|
||||
Dim value = Nothing
|
||||
|
||||
If _mappings.Value.TryGetValue(mimeType, value) Then
|
||||
Return value
|
||||
End If
|
||||
|
||||
Throw New ArgumentException("Requested mime type is not registered: " & mimeType)
|
||||
End Function
|
||||
|
||||
Private ReadOnly _mappings As New Lazy(Of IDictionary(Of String, String))(AddressOf BuildMappings)
|
||||
|
||||
Private Function BuildMappings() As IDictionary(Of String, String)
|
||||
Dim dictionary As New Dictionary(Of String, String)(StringComparer.InvariantCultureIgnoreCase) From {
|
||||
{".323", "text/h323"},
|
||||
{".3g2", "video/3gpp2"},
|
||||
{".3gp", "video/3gpp"},
|
||||
{".3gp2", "video/3gpp2"},
|
||||
{".3gpp", "video/3gpp"},
|
||||
{".7z", "application/x-7z-compressed"},
|
||||
{".aa", "audio/audible"},
|
||||
{".AAC", "audio/aac"},
|
||||
{".aaf", "application/octet-stream"},
|
||||
{".aax", "audio/vnd.audible.aax"},
|
||||
{".ac3", "audio/ac3"},
|
||||
{".aca", "application/octet-stream"},
|
||||
{".accda", "application/msaccess.addin"},
|
||||
{".accdb", "application/msaccess"},
|
||||
{".accdc", "application/msaccess.cab"},
|
||||
{".accde", "application/msaccess"},
|
||||
{".accdr", "application/msaccess.runtime"},
|
||||
{".accdt", "application/msaccess"},
|
||||
{".accdw", "application/msaccess.webapplication"},
|
||||
{".accft", "application/msaccess.ftemplate"},
|
||||
{".acx", "application/internet-property-stream"},
|
||||
{".AddIn", "text/xml"},
|
||||
{".ade", "application/msaccess"},
|
||||
{".adobebridge", "application/x-bridge-url"},
|
||||
{".adp", "application/msaccess"},
|
||||
{".ADT", "audio/vnd.dlna.adts"},
|
||||
{".ADTS", "audio/aac"},
|
||||
{".afm", "application/octet-stream"},
|
||||
{".ai", "application/postscript"},
|
||||
{".aif", "audio/x-aiff"},
|
||||
{".aifc", "audio/aiff"},
|
||||
{".aiff", "audio/aiff"},
|
||||
{".air", "application/vnd.adobe.air-application-installer-package+zip"},
|
||||
{".amc", "application/x-mpeg"},
|
||||
{".application", "application/x-ms-application"},
|
||||
{".art", "image/x-jg"},
|
||||
{".asa", "application/xml"},
|
||||
{".asax", "application/xml"},
|
||||
{".ascx", "application/xml"},
|
||||
{".asd", "application/octet-stream"},
|
||||
{".asf", "video/x-ms-asf"},
|
||||
{".ashx", "application/xml"},
|
||||
{".asi", "application/octet-stream"},
|
||||
{".asm", "text/plain"},
|
||||
{".asmx", "application/xml"},
|
||||
{".aspx", "application/xml"},
|
||||
{".asr", "video/x-ms-asf"},
|
||||
{".asx", "video/x-ms-asf"},
|
||||
{".atom", "application/atom+xml"},
|
||||
{".au", "audio/basic"},
|
||||
{".avi", "video/x-msvideo"},
|
||||
{".axs", "application/olescript"},
|
||||
{".bas", "text/plain"},
|
||||
{".bcpio", "application/x-bcpio"},
|
||||
{".bin", "application/octet-stream"},
|
||||
{".bmp", "image/bmp"},
|
||||
{".c", "text/plain"},
|
||||
{".cab", "application/octet-stream"},
|
||||
{".caf", "audio/x-caf"},
|
||||
{".calx", "application/vnd.ms-office.calx"},
|
||||
{".cat", "application/vnd.ms-pki.seccat"},
|
||||
{".cc", "text/plain"},
|
||||
{".cd", "text/plain"},
|
||||
{".cdda", "audio/aiff"},
|
||||
{".cdf", "application/x-cdf"},
|
||||
{".cer", "application/x-x509-ca-cert"},
|
||||
{".chm", "application/octet-stream"},
|
||||
{".class", "application/x-java-applet"},
|
||||
{".clp", "application/x-msclip"},
|
||||
{".cmx", "image/x-cmx"},
|
||||
{".cnf", "text/plain"},
|
||||
{".cod", "image/cis-cod"},
|
||||
{".config", "application/xml"},
|
||||
{".contact", "text/x-ms-contact"},
|
||||
{".coverage", "application/xml"},
|
||||
{".cpio", "application/x-cpio"},
|
||||
{".cpp", "text/plain"},
|
||||
{".crd", "application/x-mscardfile"},
|
||||
{".crl", "application/pkix-crl"},
|
||||
{".crt", "application/x-x509-ca-cert"},
|
||||
{".cs", "text/plain"},
|
||||
{".csdproj", "text/plain"},
|
||||
{".csh", "application/x-csh"},
|
||||
{".csproj", "text/plain"},
|
||||
{".css", "text/css"},
|
||||
{".csv", "text/csv"},
|
||||
{".cur", "application/octet-stream"},
|
||||
{".cxx", "text/plain"},
|
||||
{".dat", "application/octet-stream"},
|
||||
{".datasource", "application/xml"},
|
||||
{".dbproj", "text/plain"},
|
||||
{".dcr", "application/x-director"},
|
||||
{".def", "text/plain"},
|
||||
{".deploy", "application/octet-stream"},
|
||||
{".der", "application/x-x509-ca-cert"},
|
||||
{".dgml", "application/xml"},
|
||||
{".dib", "image/bmp"},
|
||||
{".dif", "video/x-dv"},
|
||||
{".dir", "application/x-director"},
|
||||
{".disco", "text/xml"},
|
||||
{".divx", "video/divx"},
|
||||
{".dll", "application/x-msdownload"},
|
||||
{".dll.config", "text/xml"},
|
||||
{".dlm", "text/dlm"},
|
||||
{".doc", "application/msword"},
|
||||
{".docm", "application/vnd.ms-word.document.macroEnabled.12"},
|
||||
{".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
|
||||
{".dot", "application/msword"},
|
||||
{".dotm", "application/vnd.ms-word.template.macroEnabled.12"},
|
||||
{".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
|
||||
{".dsp", "application/octet-stream"},
|
||||
{".dsw", "text/plain"},
|
||||
{".dtd", "text/xml"},
|
||||
{".dtsConfig", "text/xml"},
|
||||
{".dv", "video/x-dv"},
|
||||
{".dvi", "application/x-dvi"},
|
||||
{".dwf", "drawing/x-dwf"},
|
||||
{".dwp", "application/octet-stream"},
|
||||
{".dxr", "application/x-director"},
|
||||
{".eml", "message/rfc822"},
|
||||
{".emz", "application/octet-stream"},
|
||||
{".eot", "application/octet-stream"},
|
||||
{".eps", "application/postscript"},
|
||||
{".etl", "application/etl"},
|
||||
{".etx", "text/x-setext"},
|
||||
{".evy", "application/envoy"},
|
||||
{".exe", "application/octet-stream"},
|
||||
{".exe.config", "text/xml"},
|
||||
{".fdf", "application/vnd.fdf"},
|
||||
{".fif", "application/fractals"},
|
||||
{".filters", "application/xml"},
|
||||
{".fla", "application/octet-stream"},
|
||||
{".flr", "x-world/x-vrml"},
|
||||
{".flv", "video/x-flv"},
|
||||
{".fsscript", "application/fsharp-script"},
|
||||
{".fsx", "application/fsharp-script"},
|
||||
{".generictest", "application/xml"},
|
||||
{".gif", "image/gif"},
|
||||
{".group", "text/x-ms-group"},
|
||||
{".gsm", "audio/x-gsm"},
|
||||
{".gtar", "application/x-gtar"},
|
||||
{".gz", "application/x-gzip"},
|
||||
{".h", "text/plain"},
|
||||
{".hdf", "application/x-hdf"},
|
||||
{".hdml", "text/x-hdml"},
|
||||
{".hhc", "application/x-oleobject"},
|
||||
{".hhk", "application/octet-stream"},
|
||||
{".hhp", "application/octet-stream"},
|
||||
{".hlp", "application/winhlp"},
|
||||
{".hpp", "text/plain"},
|
||||
{".hqx", "application/mac-binhex40"},
|
||||
{".hta", "application/hta"},
|
||||
{".htc", "text/x-component"},
|
||||
{".htm", "text/html"},
|
||||
{".html", "text/html"},
|
||||
{".htt", "text/webviewhtml"},
|
||||
{".hxa", "application/xml"},
|
||||
{".hxc", "application/xml"},
|
||||
{".hxd", "application/octet-stream"},
|
||||
{".hxe", "application/xml"},
|
||||
{".hxf", "application/xml"},
|
||||
{".hxh", "application/octet-stream"},
|
||||
{".hxi", "application/octet-stream"},
|
||||
{".hxk", "application/xml"},
|
||||
{".hxq", "application/octet-stream"},
|
||||
{".hxr", "application/octet-stream"},
|
||||
{".hxs", "application/octet-stream"},
|
||||
{".hxt", "text/html"},
|
||||
{".hxv", "application/xml"},
|
||||
{".hxw", "application/octet-stream"},
|
||||
{".hxx", "text/plain"},
|
||||
{".i", "text/plain"},
|
||||
{".ico", "image/x-icon"},
|
||||
{".ics", "application/octet-stream"},
|
||||
{".idl", "text/plain"},
|
||||
{".ief", "image/ief"},
|
||||
{".iii", "application/x-iphone"},
|
||||
{".inc", "text/plain"},
|
||||
{".inf", "application/octet-stream"},
|
||||
{".inl", "text/plain"},
|
||||
{".ins", "application/x-internet-signup"},
|
||||
{".ipa", "application/x-itunes-ipa"},
|
||||
{".ipg", "application/x-itunes-ipg"},
|
||||
{".ipproj", "text/plain"},
|
||||
{".ipsw", "application/x-itunes-ipsw"},
|
||||
{".iqy", "text/x-ms-iqy"},
|
||||
{".isp", "application/x-internet-signup"},
|
||||
{".ite", "application/x-itunes-ite"},
|
||||
{".itlp", "application/x-itunes-itlp"},
|
||||
{".itms", "application/x-itunes-itms"},
|
||||
{".itpc", "application/x-itunes-itpc"},
|
||||
{".IVF", "video/x-ivf"},
|
||||
{".jar", "application/java-archive"},
|
||||
{".java", "application/octet-stream"},
|
||||
{".jck", "application/liquidmotion"},
|
||||
{".jcz", "application/liquidmotion"},
|
||||
{".jfif", "image/pjpeg"},
|
||||
{".jnlp", "application/x-java-jnlp-file"},
|
||||
{".jpb", "application/octet-stream"},
|
||||
{".jpe", "image/jpeg"},
|
||||
{".jpeg", "image/jpeg"},
|
||||
{".jpg", "image/jpeg"},
|
||||
{".js", "application/x-javascript"},
|
||||
{".json", "application/json"},
|
||||
{".jsx", "text/jscript"},
|
||||
{".jsxbin", "text/plain"},
|
||||
{".latex", "application/x-latex"},
|
||||
{".library-ms", "application/windows-library+xml"},
|
||||
{".lit", "application/x-ms-reader"},
|
||||
{".loadtest", "application/xml"},
|
||||
{".lpk", "application/octet-stream"},
|
||||
{".lsf", "video/x-la-asf"},
|
||||
{".lst", "text/plain"},
|
||||
{".lsx", "video/x-la-asf"},
|
||||
{".lzh", "application/octet-stream"},
|
||||
{".m13", "application/x-msmediaview"},
|
||||
{".m14", "application/x-msmediaview"},
|
||||
{".m1v", "video/mpeg"},
|
||||
{".m2t", "video/vnd.dlna.mpeg-tts"},
|
||||
{".m2ts", "video/vnd.dlna.mpeg-tts"},
|
||||
{".m2v", "video/mpeg"},
|
||||
{".m3u", "audio/x-mpegurl"},
|
||||
{".m3u8", "audio/x-mpegurl"},
|
||||
{".m4a", "audio/m4a"},
|
||||
{".m4b", "audio/m4b"},
|
||||
{".m4p", "audio/m4p"},
|
||||
{".m4r", "audio/x-m4r"},
|
||||
{".m4v", "video/x-m4v"},
|
||||
{".mac", "image/x-macpaint"},
|
||||
{".mak", "text/plain"},
|
||||
{".man", "application/x-troff-man"},
|
||||
{".manifest", "application/x-ms-manifest"},
|
||||
{".map", "text/plain"},
|
||||
{".master", "application/xml"},
|
||||
{".mda", "application/msaccess"},
|
||||
{".mdb", "application/x-msaccess"},
|
||||
{".mde", "application/msaccess"},
|
||||
{".mdp", "application/octet-stream"},
|
||||
{".me", "application/x-troff-me"},
|
||||
{".mfp", "application/x-shockwave-flash"},
|
||||
{".mht", "message/rfc822"},
|
||||
{".mhtml", "message/rfc822"},
|
||||
{".mid", "audio/mid"},
|
||||
{".midi", "audio/mid"},
|
||||
{".mix", "application/octet-stream"},
|
||||
{".mk", "text/plain"},
|
||||
{".mmf", "application/x-smaf"},
|
||||
{".mno", "text/xml"},
|
||||
{".mny", "application/x-msmoney"},
|
||||
{".mod", "video/mpeg"},
|
||||
{".mov", "video/quicktime"},
|
||||
{".movie", "video/x-sgi-movie"},
|
||||
{".mp2", "video/mpeg"},
|
||||
{".mp2v", "video/mpeg"},
|
||||
{".mp3", "audio/mpeg"},
|
||||
{".mp4", "video/mp4"},
|
||||
{".mp4v", "video/mp4"},
|
||||
{".mpa", "video/mpeg"},
|
||||
{".mpe", "video/mpeg"},
|
||||
{".mpeg", "video/mpeg"},
|
||||
{".mpf", "application/vnd.ms-mediapackage"},
|
||||
{".mpg", "video/mpeg"},
|
||||
{".mpp", "application/vnd.ms-project"},
|
||||
{".mpv2", "video/mpeg"},
|
||||
{".mqv", "video/quicktime"},
|
||||
{".ms", "application/x-troff-ms"},
|
||||
{".msg", "application/vnd.ms-outlook"},
|
||||
{".msi", "application/octet-stream"},
|
||||
{".mso", "application/octet-stream"},
|
||||
{".mts", "video/vnd.dlna.mpeg-tts"},
|
||||
{".mtx", "application/xml"},
|
||||
{".mvb", "application/x-msmediaview"},
|
||||
{".mvc", "application/x-miva-compiled"},
|
||||
{".mxp", "application/x-mmxp"},
|
||||
{".nc", "application/x-netcdf"},
|
||||
{".nsc", "video/x-ms-asf"},
|
||||
{".nws", "message/rfc822"},
|
||||
{".ocx", "application/octet-stream"},
|
||||
{".oda", "application/oda"},
|
||||
{".odb", "application/vnd.oasis.opendocument.database"},
|
||||
{".odc", "application/vnd.oasis.opendocument.chart"},
|
||||
{".odf", "application/vnd.oasis.opendocument.formula"},
|
||||
{".odg", "application/vnd.oasis.opendocument.graphics"},
|
||||
{".odh", "text/plain"},
|
||||
{".odi", "application/vnd.oasis.opendocument.image"},
|
||||
{".odl", "text/plain"},
|
||||
{".odm", "application/vnd.oasis.opendocument.text-master"},
|
||||
{".odp", "application/vnd.oasis.opendocument.presentation"},
|
||||
{".ods", "application/vnd.oasis.opendocument.spreadsheet"},
|
||||
{".odt", "application/vnd.oasis.opendocument.text"},
|
||||
{".ogv", "video/ogg"},
|
||||
{".one", "application/onenote"},
|
||||
{".onea", "application/onenote"},
|
||||
{".onepkg", "application/onenote"},
|
||||
{".onetmp", "application/onenote"},
|
||||
{".onetoc", "application/onenote"},
|
||||
{".onetoc2", "application/onenote"},
|
||||
{".orderedtest", "application/xml"},
|
||||
{".osdx", "application/opensearchdescription+xml"},
|
||||
{".otg", "application/vnd.oasis.opendocument.graphics-template"},
|
||||
{".oth", "application/vnd.oasis.opendocument.text-web"},
|
||||
{".otp", "application/vnd.oasis.opendocument.presentation-template"},
|
||||
{".ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
|
||||
{".ott", "application/vnd.oasis.opendocument.text-template"},
|
||||
{".oxt", "application/vnd.openofficeorg.extension"},
|
||||
{".p10", "application/pkcs10"},
|
||||
{".p12", "application/x-pkcs12"},
|
||||
{".p7b", "application/x-pkcs7-certificates"},
|
||||
{".p7c", "application/pkcs7-mime"},
|
||||
{".p7m", "application/pkcs7-mime"},
|
||||
{".p7r", "application/x-pkcs7-certreqresp"},
|
||||
{".p7s", "application/pkcs7-signature"},
|
||||
{".pbm", "image/x-portable-bitmap"},
|
||||
{".pcast", "application/x-podcast"},
|
||||
{".pct", "image/pict"},
|
||||
{".pcx", "application/octet-stream"},
|
||||
{".pcz", "application/octet-stream"},
|
||||
{".pdf", "application/pdf"},
|
||||
{".pfb", "application/octet-stream"},
|
||||
{".pfm", "application/octet-stream"},
|
||||
{".pfx", "application/x-pkcs12"},
|
||||
{".pgm", "image/x-portable-graymap"},
|
||||
{".pic", "image/pict"},
|
||||
{".pict", "image/pict"},
|
||||
{".pkgdef", "text/plain"},
|
||||
{".pkgundef", "text/plain"},
|
||||
{".pko", "application/vnd.ms-pki.pko"},
|
||||
{".pls", "audio/scpls"},
|
||||
{".pma", "application/x-perfmon"},
|
||||
{".pmc", "application/x-perfmon"},
|
||||
{".pml", "application/x-perfmon"},
|
||||
{".pmr", "application/x-perfmon"},
|
||||
{".pmw", "application/x-perfmon"},
|
||||
{".png", "image/png"},
|
||||
{".pnm", "image/x-portable-anymap"},
|
||||
{".pnt", "image/x-macpaint"},
|
||||
{".pntg", "image/x-macpaint"},
|
||||
{".pnz", "image/png"},
|
||||
{".pot", "application/vnd.ms-powerpoint"},
|
||||
{".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"},
|
||||
{".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
|
||||
{".ppa", "application/vnd.ms-powerpoint"},
|
||||
{".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"},
|
||||
{".ppm", "image/x-portable-pixmap"},
|
||||
{".pps", "application/vnd.ms-powerpoint"},
|
||||
{".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
|
||||
{".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
|
||||
{".ppt", "application/vnd.ms-powerpoint"},
|
||||
{".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
|
||||
{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
|
||||
{".prf", "application/pics-rules"},
|
||||
{".prm", "application/octet-stream"},
|
||||
{".prx", "application/octet-stream"},
|
||||
{".ps", "application/postscript"},
|
||||
{".psc1", "application/PowerShell"},
|
||||
{".psd", "application/octet-stream"},
|
||||
{".psess", "application/xml"},
|
||||
{".psm", "application/octet-stream"},
|
||||
{".psp", "application/octet-stream"},
|
||||
{".pub", "application/x-mspublisher"},
|
||||
{".pwz", "application/vnd.ms-powerpoint"},
|
||||
{".qht", "text/x-html-insertion"},
|
||||
{".qhtm", "text/x-html-insertion"},
|
||||
{".qt", "video/quicktime"},
|
||||
{".qti", "image/x-quicktime"},
|
||||
{".qtif", "image/x-quicktime"},
|
||||
{".qtl", "application/x-quicktimeplayer"},
|
||||
{".qxd", "application/octet-stream"},
|
||||
{".ra", "audio/x-pn-realaudio"},
|
||||
{".ram", "audio/x-pn-realaudio"},
|
||||
{".rar", "application/octet-stream"},
|
||||
{".ras", "image/x-cmu-raster"},
|
||||
{".rat", "application/rat-file"},
|
||||
{".rc", "text/plain"},
|
||||
{".rc2", "text/plain"},
|
||||
{".rct", "text/plain"},
|
||||
{".rdlc", "application/xml"},
|
||||
{".resx", "application/xml"},
|
||||
{".rf", "image/vnd.rn-realflash"},
|
||||
{".rgb", "image/x-rgb"},
|
||||
{".rgs", "text/plain"},
|
||||
{".rm", "application/vnd.rn-realmedia"},
|
||||
{".rmi", "audio/mid"},
|
||||
{".rmp", "application/vnd.rn-rn_music_package"},
|
||||
{".roff", "application/x-troff"},
|
||||
{".rpm", "audio/x-pn-realaudio-plugin"},
|
||||
{".rqy", "text/x-ms-rqy"},
|
||||
{".rtf", "application/rtf"},
|
||||
{".rtx", "text/richtext"},
|
||||
{".ruleset", "application/xml"},
|
||||
{".s", "text/plain"},
|
||||
{".safariextz", "application/x-safari-safariextz"},
|
||||
{".scd", "application/x-msschedule"},
|
||||
{".sct", "text/scriptlet"},
|
||||
{".sd2", "audio/x-sd2"},
|
||||
{".sdp", "application/sdp"},
|
||||
{".sea", "application/octet-stream"},
|
||||
{".searchConnector-ms", "application/windows-search-connector+xml"},
|
||||
{".setpay", "application/set-payment-initiation"},
|
||||
{".setreg", "application/set-registration-initiation"},
|
||||
{".settings", "application/xml"},
|
||||
{".sgimb", "application/x-sgimb"},
|
||||
{".sgml", "text/sgml"},
|
||||
{".sh", "application/x-sh"},
|
||||
{".shar", "application/x-shar"},
|
||||
{".shtml", "text/html"},
|
||||
{".sit", "application/x-stuffit"},
|
||||
{".sitemap", "application/xml"},
|
||||
{".skin", "application/xml"},
|
||||
{".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"},
|
||||
{".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
|
||||
{".slk", "application/vnd.ms-excel"},
|
||||
{".sln", "text/plain"},
|
||||
{".slupkg-ms", "application/x-ms-license"},
|
||||
{".smd", "audio/x-smd"},
|
||||
{".smi", "application/octet-stream"},
|
||||
{".smx", "audio/x-smd"},
|
||||
{".smz", "audio/x-smd"},
|
||||
{".snd", "audio/basic"},
|
||||
{".snippet", "application/xml"},
|
||||
{".snp", "application/octet-stream"},
|
||||
{".sol", "text/plain"},
|
||||
{".sor", "text/plain"},
|
||||
{".spc", "application/x-pkcs7-certificates"},
|
||||
{".spl", "application/futuresplash"},
|
||||
{".src", "application/x-wais-source"},
|
||||
{".srf", "text/plain"},
|
||||
{".SSISDeploymentManifest", "text/xml"},
|
||||
{".ssm", "application/streamingmedia"},
|
||||
{".sst", "application/vnd.ms-pki.certstore"},
|
||||
{".stl", "application/vnd.ms-pki.stl"},
|
||||
{".sv4cpio", "application/x-sv4cpio"},
|
||||
{".sv4crc", "application/x-sv4crc"},
|
||||
{".svc", "application/xml"},
|
||||
{".svg", "image/svg+xml"},
|
||||
{".swf", "application/x-shockwave-flash"},
|
||||
{".t", "application/x-troff"},
|
||||
{".tar", "application/x-tar"},
|
||||
{".tcl", "application/x-tcl"},
|
||||
{".testrunconfig", "application/xml"},
|
||||
{".testsettings", "application/xml"},
|
||||
{".tex", "application/x-tex"},
|
||||
{".texi", "application/x-texinfo"},
|
||||
{".texinfo", "application/x-texinfo"},
|
||||
{".tgz", "application/x-compressed"},
|
||||
{".thmx", "application/vnd.ms-officetheme"},
|
||||
{".thn", "application/octet-stream"},
|
||||
{".tif", "image/tiff"},
|
||||
{".tiff", "image/tiff"},
|
||||
{".tlh", "text/plain"},
|
||||
{".tli", "text/plain"},
|
||||
{".toc", "application/octet-stream"},
|
||||
{".tr", "application/x-troff"},
|
||||
{".trm", "application/x-msterminal"},
|
||||
{".trx", "application/xml"},
|
||||
{".ts", "video/vnd.dlna.mpeg-tts"},
|
||||
{".tsv", "text/tab-separated-values"},
|
||||
{".ttf", "application/octet-stream"},
|
||||
{".tts", "video/vnd.dlna.mpeg-tts"},
|
||||
{".txt", "text/plain"},
|
||||
{".u32", "application/octet-stream"},
|
||||
{".uls", "text/iuls"},
|
||||
{".user", "text/plain"},
|
||||
{".ustar", "application/x-ustar"},
|
||||
{".vb", "text/plain"},
|
||||
{".vbdproj", "text/plain"},
|
||||
{".vbk", "video/mpeg"},
|
||||
{".vbproj", "text/plain"},
|
||||
{".vbs", "text/vbscript"},
|
||||
{".vcf", "text/x-vcard"},
|
||||
{".vcproj", "application/xml"},
|
||||
{".vcs", "text/plain"},
|
||||
{".vcxproj", "application/xml"},
|
||||
{".vddproj", "text/plain"},
|
||||
{".vdp", "text/plain"},
|
||||
{".vdproj", "text/plain"},
|
||||
{".vdx", "application/vnd.ms-visio.viewer"},
|
||||
{".vml", "text/xml"},
|
||||
{".vscontent", "application/xml"},
|
||||
{".vsct", "text/xml"},
|
||||
{".vsd", "application/vnd.visio"},
|
||||
{".vsi", "application/ms-vsi"},
|
||||
{".vsix", "application/vsix"},
|
||||
{".vsixlangpack", "text/xml"},
|
||||
{".vsixmanifest", "text/xml"},
|
||||
{".vsmdi", "application/xml"},
|
||||
{".vspscc", "text/plain"},
|
||||
{".vss", "application/vnd.visio"},
|
||||
{".vsscc", "text/plain"},
|
||||
{".vssettings", "text/xml"},
|
||||
{".vssscc", "text/plain"},
|
||||
{".vst", "application/vnd.visio"},
|
||||
{".vstemplate", "text/xml"},
|
||||
{".vsto", "application/x-ms-vsto"},
|
||||
{".vsw", "application/vnd.visio"},
|
||||
{".vsx", "application/vnd.visio"},
|
||||
{".vtx", "application/vnd.visio"},
|
||||
{".wav", "audio/wav"},
|
||||
{".wave", "audio/wav"},
|
||||
{".wax", "audio/x-ms-wax"},
|
||||
{".wbk", "application/msword"},
|
||||
{".wbmp", "image/vnd.wap.wbmp"},
|
||||
{".wcm", "application/vnd.ms-works"},
|
||||
{".wdb", "application/vnd.ms-works"},
|
||||
{".wdp", "image/vnd.ms-photo"},
|
||||
{".webarchive", "application/x-safari-webarchive"},
|
||||
{".webm", "video/webm"},
|
||||
{".webp", "image/webp"},
|
||||
{".webtest", "application/xml"},
|
||||
{".wiq", "application/xml"},
|
||||
{".wiz", "application/msword"},
|
||||
{".wks", "application/vnd.ms-works"},
|
||||
{".WLMP", "application/wlmoviemaker"},
|
||||
{".wlpginstall", "application/x-wlpg-detect"},
|
||||
{".wlpginstall3", "application/x-wlpg3-detect"},
|
||||
{".wm", "video/x-ms-wm"},
|
||||
{".wma", "audio/x-ms-wma"},
|
||||
{".wmd", "application/x-ms-wmd"},
|
||||
{".wmf", "application/x-msmetafile"},
|
||||
{".wml", "text/vnd.wap.wml"},
|
||||
{".wmlc", "application/vnd.wap.wmlc"},
|
||||
{".wmls", "text/vnd.wap.wmlscript"},
|
||||
{".wmlsc", "application/vnd.wap.wmlscriptc"},
|
||||
{".wmp", "video/x-ms-wmp"},
|
||||
{".wmv", "video/x-ms-wmv"},
|
||||
{".wmx", "video/x-ms-wmx"},
|
||||
{".wmz", "application/x-ms-wmz"},
|
||||
{".wpl", "application/vnd.ms-wpl"},
|
||||
{".wps", "application/vnd.ms-works"},
|
||||
{".wri", "application/x-mswrite"},
|
||||
{".wrl", "x-world/x-vrml"},
|
||||
{".wrz", "x-world/x-vrml"},
|
||||
{".wsc", "text/scriptlet"},
|
||||
{".wsdl", "text/xml"},
|
||||
{".wvx", "video/x-ms-wvx"},
|
||||
{".x", "application/directx"},
|
||||
{".xaf", "x-world/x-vrml"},
|
||||
{".xaml", "application/xaml+xml"},
|
||||
{".xap", "application/x-silverlight-app"},
|
||||
{".xbap", "application/x-ms-xbap"},
|
||||
{".xbm", "image/x-xbitmap"},
|
||||
{".xdr", "text/plain"},
|
||||
{".xht", "application/xhtml+xml"},
|
||||
{".xhtml", "application/xhtml+xml"},
|
||||
{".xla", "application/vnd.ms-excel"},
|
||||
{".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"},
|
||||
{".xlc", "application/vnd.ms-excel"},
|
||||
{".xld", "application/vnd.ms-excel"},
|
||||
{".xlk", "application/vnd.ms-excel"},
|
||||
{".xll", "application/vnd.ms-excel"},
|
||||
{".xlm", "application/vnd.ms-excel"},
|
||||
{".xls", "application/vnd.ms-excel"},
|
||||
{".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
|
||||
{".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"},
|
||||
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
|
||||
{".xlt", "application/vnd.ms-excel"},
|
||||
{".xltm", "application/vnd.ms-excel.template.macroEnabled.12"},
|
||||
{".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
|
||||
{".xlw", "application/vnd.ms-excel"},
|
||||
{".xml", "text/xml"},
|
||||
{".xmta", "application/xml"},
|
||||
{".xof", "x-world/x-vrml"},
|
||||
{".XOML", "text/plain"},
|
||||
{".xpm", "image/x-xpixmap"},
|
||||
{".xps", "application/vnd.ms-xpsdocument"},
|
||||
{".xrm-ms", "text/xml"},
|
||||
{".xsc", "application/xml"},
|
||||
{".xsd", "text/xml"},
|
||||
{".xsf", "text/xml"},
|
||||
{".xsl", "text/xml"},
|
||||
{".xslt", "text/xml"},
|
||||
{".xsn", "application/octet-stream"},
|
||||
{".xss", "application/xml"},
|
||||
{".xtp", "application/octet-stream"},
|
||||
{".xwd", "image/x-xwindowdump"},
|
||||
{".z", "application/x-compress"},
|
||||
{".zip", "application/x-zip-compressed"},
|
||||
{"application/fsharp-script", ".fsx"},
|
||||
{"application/msaccess", ".adp"},
|
||||
{"application/msword", ".doc"},
|
||||
{"application/octet-stream", ".bin"},
|
||||
{"application/onenote", ".one"},
|
||||
{"application/postscript", ".eps"},
|
||||
{"application/vnd.ms-excel", ".xls"},
|
||||
{"application/vnd.ms-powerpoint", ".ppt"},
|
||||
{"application/vnd.ms-works", ".wks"},
|
||||
{"application/vnd.visio", ".vsd"},
|
||||
{"application/x-director", ".dir"},
|
||||
{"application/x-shockwave-flash", ".swf"},
|
||||
{"application/x-x509-ca-cert", ".cer"},
|
||||
{"application/xhtml+xml", ".xhtml"},
|
||||
{"application/xml", ".xml"},
|
||||
{"audio/aac", ".AAC"},
|
||||
{"audio/aiff", ".aiff"},
|
||||
{"audio/basic", ".snd"},
|
||||
{"audio/mid", ".midi"},
|
||||
{"audio/wav", ".wav"},
|
||||
{"audio/x-mpegurl", ".m3u"},
|
||||
{"audio/x-pn-realaudio", ".ra"},
|
||||
{"audio/x-smd", ".smd"},
|
||||
{"image/bmp", ".bmp"},
|
||||
{"image/jpeg", ".jpg"},
|
||||
{"image/pict", ".pic"},
|
||||
{"image/png", ".png"},
|
||||
{"image/tiff", ".tiff"},
|
||||
{"image/x-macpaint", ".mac"},
|
||||
{"image/x-quicktime", ".qti"},
|
||||
{"message/rfc822", ".eml"},
|
||||
{"text/html", ".html"},
|
||||
{"text/plain", ".txt"},
|
||||
{"text/scriptlet", ".wsc"},
|
||||
{"text/xml", ".xml"},
|
||||
{"video/3gpp", ".3gp"},
|
||||
{"video/3gpp2", ".3gp2"},
|
||||
{"video/mp4", ".mp4"},
|
||||
{"video/mpeg", ".mpg"},
|
||||
{"video/quicktime", ".mov"},
|
||||
{"video/vnd.dlna.mpeg-tts", ".m2t"},
|
||||
{"video/x-dv", ".dv"},
|
||||
{"video/x-la-asf", ".lsf"},
|
||||
{"video/x-ms-asf", ".asf"},
|
||||
{"x-world/x-vrml", ".xof"}
|
||||
}
|
||||
Dim dictionary2 As Dictionary(Of String, String) = dictionary
|
||||
Dim list As List(Of KeyValuePair(Of String, String)) = dictionary2.ToList()
|
||||
|
||||
For Each item As KeyValuePair(Of String, String) In list
|
||||
|
||||
If Not dictionary2.ContainsKey(item.Value) Then
|
||||
dictionary2.Add(item.Value, item.Key)
|
||||
End If
|
||||
Next
|
||||
|
||||
Return dictionary2
|
||||
End Function
|
||||
End Class
|
||||
150
Base/ModuleExtensions.vb
Normal file
150
Base/ModuleExtensions.vb
Normal file
@@ -0,0 +1,150 @@
|
||||
Imports System.Runtime.CompilerServices
|
||||
Imports System.Web
|
||||
|
||||
Public Module ModuleExtensions
|
||||
Const UnixEraStartTicks As Long = 621355968000000000
|
||||
|
||||
' ======================================================
|
||||
' === DATETIME
|
||||
' ======================================================
|
||||
|
||||
<Extension()>
|
||||
Public Function GetUnixTimestamp(pDate As Date) As Long
|
||||
Dim UnixEraTicks = pDate.Ticks - UnixEraStartTicks
|
||||
Return UnixEraTicks \ 10000
|
||||
End Function
|
||||
|
||||
<Extension()>
|
||||
Public Function DateFromUnix(pTimestamp As Long) As Date
|
||||
Return New Date(UnixEraStartTicks + pTimestamp * 10000)
|
||||
End Function
|
||||
|
||||
' ======================================================
|
||||
' === LIST
|
||||
' ======================================================
|
||||
|
||||
<Extension()>
|
||||
Public Function JoinToString(pList As IEnumerable(Of String), pSeparator As Char)
|
||||
Return String.Join(pSeparator, pList)
|
||||
End Function
|
||||
|
||||
' ======================================================
|
||||
' === STRING
|
||||
' ======================================================
|
||||
|
||||
''' <summary>
|
||||
''' Truncates a string to the specified length if it exceeds that length.
|
||||
''' </summary>
|
||||
''' <param name="pString">The string</param>
|
||||
''' <param name="pLength">The maximum string length</param>
|
||||
''' <returns>The truncated string</returns>
|
||||
<Extension()>
|
||||
Public Function Truncate(pString As String, pLength As Integer) As String
|
||||
If String.IsNullOrEmpty(pString) Then Return pString
|
||||
Return pString.Substring(0, Math.Min(pLength, pString.Length))
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Replaces single quotes in text for SQL Commands.
|
||||
''' </summary>
|
||||
''' <param name="pString">The string</param>
|
||||
''' <returns>The escaped string.</returns>
|
||||
<Extension()>
|
||||
Public Function EscapeForSQL(pString As String) As String
|
||||
Return ObjectEx.NotNull(pString, String.Empty).Replace("'", "''")
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Converts a string to boolean. Accepts true and 1 as truthy values
|
||||
''' </summary>
|
||||
''' <param name="pString">The input string</param>
|
||||
''' <returns>True if input is true or 1, otherwise false.</returns>
|
||||
<Extension()>
|
||||
Public Function ToBoolean(pString As String) As Boolean
|
||||
If String.IsNullOrEmpty(pString) Then Return False
|
||||
Return (pString.Trim().ToLower() = "true") OrElse (pString.Trim() = "1")
|
||||
End Function
|
||||
|
||||
' ======================================================
|
||||
' === DICTIONARY
|
||||
' ======================================================
|
||||
|
||||
<Extension()>
|
||||
Public Function ToURLQueryString(pDictionary As IDictionary(Of String, String)) As String
|
||||
Dim oQueryString = HttpUtility.ParseQueryString(String.Empty)
|
||||
|
||||
For Each oItem As KeyValuePair(Of String, String) In pDictionary
|
||||
oQueryString.Add(oItem.Key, oItem.Value)
|
||||
Next
|
||||
|
||||
Return oQueryString.ToString()
|
||||
End Function
|
||||
|
||||
' ======================================================
|
||||
' === DATATABLE
|
||||
' ======================================================
|
||||
|
||||
<Extension()>
|
||||
Public Function ItemEx(Of T)(pRow As DataRow, pFieldName As String, Optional pDefaultValue As T = Nothing) As T
|
||||
Try
|
||||
If TableContainsColumn(pRow.Table, pFieldName) = False Then Return pDefaultValue
|
||||
Return ObjectEx.NotNull(pRow.Item(pFieldName), pDefaultValue)
|
||||
Catch ex As Exception
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
<Extension()>
|
||||
Public Function ItemEx(Of T)(pRow As DataRow, pFieldIndex As Integer, Optional pDefaultValue As T = Nothing) As T
|
||||
Try
|
||||
If TableContainsColumn(pRow.Table, pFieldIndex) = False Then Return pDefaultValue
|
||||
Return ObjectEx.NotNull(pRow.Item(pFieldIndex), pDefaultValue)
|
||||
Catch ex As Exception
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
<Extension()>
|
||||
Public Function FieldOrDefault(Of T)(pRow As DataRow, pFieldName As String, Optional pDefaultValue As T = Nothing) As T
|
||||
Return ItemEx(pRow, pFieldName, pDefaultValue)
|
||||
End Function
|
||||
|
||||
<Extension()>
|
||||
Public Function FieldOrDefault(Of T)(pRow As DataRow, pFieldIndex As Integer, Optional pDefaultValue As T = Nothing) As T
|
||||
Return ItemEx(pRow, pFieldIndex, pDefaultValue)
|
||||
End Function
|
||||
|
||||
<Extension()>
|
||||
Public Function First(pTable As DataTable) As DataRow
|
||||
Try
|
||||
If pTable Is Nothing OrElse pTable.Rows.Count = 0 Then
|
||||
Return Nothing
|
||||
End If
|
||||
Return pTable.Rows.Item(0)
|
||||
Catch ex As Exception
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function TableContainsColumn(pTable As DataTable, pColumnName As String) As Boolean
|
||||
Try
|
||||
If pTable Is Nothing Then Return False
|
||||
If String.IsNullOrEmpty(pColumnName) Then Return False
|
||||
|
||||
Return pTable.Columns.Contains(pColumnName)
|
||||
Catch ex As Exception
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function TableContainsColumn(pTable As DataTable, pColumnIndex As Integer) As Boolean
|
||||
Try
|
||||
If pTable Is Nothing Then Return False
|
||||
If String.IsNullOrEmpty(pColumnIndex) Then Return False
|
||||
|
||||
Return pTable.Columns.Count > pColumnIndex
|
||||
Catch ex As Exception
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
End Module
|
||||
@@ -12,8 +12,8 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("")>
|
||||
<Assembly: AssemblyProduct("Base")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2023")>
|
||||
<Assembly: AssemblyTrademark("1.3.6.0")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' indem Sie "*" wie unten gezeigt eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.0.0.1")>
|
||||
<Assembly: AssemblyFileVersion("1.0.0.1")>
|
||||
<Assembly: AssemblyVersion("1.3.6.0")>
|
||||
<Assembly: AssemblyFileVersion("1.3.6.0")>
|
||||
|
||||
2
Base/My Project/Resources.Designer.vb
generated
2
Base/My Project/Resources.Designer.vb
generated
@@ -22,7 +22,7 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0"), _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
|
||||
2
Base/My Project/Settings.Designer.vb
generated
2
Base/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
237
Base/NativeMethods.vb
Normal file
237
Base/NativeMethods.vb
Normal file
@@ -0,0 +1,237 @@
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Text
|
||||
Imports DigitalData.Modules.Base.ScreenEx
|
||||
|
||||
Public Class NativeMethods
|
||||
Public Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" (ByVal hwnd As Int32) As Integer
|
||||
Public Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal WinTitle As String, ByVal MaxLength As Integer) As Integer
|
||||
<DllImport("Shell32", CharSet:=CharSet.Auto, SetLastError:=True)>
|
||||
Public Shared Function ShellExecuteEx(ByRef lpExecInfo As ShellExecuteInfo) As Boolean
|
||||
End Function
|
||||
<DllImport("user32", EntryPoint:="SetClipboardViewer")>
|
||||
Public Shared Function SetClipboardViewer(ByVal hWnd As IntPtr) As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr
|
||||
End Function
|
||||
<DllImport("User32.dll")>
|
||||
Public Shared Function ReleaseCapture() As Boolean
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetWindowRect(ByVal hWnd As HandleRef, ByRef lpRect As RectangleAPI) As Boolean
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function AttachThreadInput(ByVal idAttach As IntPtr, ByVal idAttachTo As IntPtr, fAttach As Boolean) As Boolean
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetFocus() As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function WindowFromPoint(ByVal p As PointAPI) As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetForegroundWindow() As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function GetClassName(ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal dwProcessId As UInteger) As IntPtr
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UIntPtr, ByVal flAllocationType As UInteger, ByVal flProtect As PageProtection) As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll", SetLastError:=True)>
|
||||
Public Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, <Out> ByRef lpdwProcessId As UInteger) As UInteger
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UIntPtr, ByVal dwFreeType As UInteger) As Boolean
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function CloseHandle(ByVal hObject As IntPtr) As Boolean
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function MapViewOfFile(ByVal hFileMappingObject As IntPtr, ByVal dwDesiredAccess As UInteger, ByVal dwFileOffsetHigh As UInteger, ByVal dwFileOffsetLow As UInteger, ByVal dwNumberOfBytesToMap As UIntPtr) As IntPtr
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function UnmapViewOfFile(ByVal lpBaseAddress As IntPtr) As Boolean
|
||||
End Function
|
||||
<DllImport("kernel32.dll", SetLastError:=True)>
|
||||
Public Shared Function CreateFileMapping(ByVal hFile As IntPtr, ByVal lpFileMappingAttributes As IntPtr, ByVal flProtect As PageProtection, ByVal dwMaximumSizeHigh As Integer, ByVal dwMaximumSizeLow As Integer, ByVal lpName As String) As IntPtr
|
||||
End Function
|
||||
<DllImport("user32.dll")>
|
||||
Public Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
|
||||
End Function
|
||||
<DllImport("kernel32.dll")>
|
||||
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr,
|
||||
<Out> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
|
||||
End Function
|
||||
<DllImport("Kernel32.dll", EntryPoint:="RtlMoveMemory", SetLastError:=False)>
|
||||
Public Shared Sub MoveMemoryFromByte(ByVal dest As IntPtr, ByRef src As Byte, ByVal size As Integer)
|
||||
End Sub
|
||||
<DllImport("Kernel32.dll", EntryPoint:="RtlMoveMemory", SetLastError:=False)>
|
||||
Public Shared Sub MoveMemoryToByte(ByRef dest As Byte, ByVal src As IntPtr, ByVal size As Integer)
|
||||
End Sub
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
|
||||
Public Shared Function RegisterWindowMessage(ByVal lpString As String) As Integer
|
||||
End Function
|
||||
<DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
|
||||
Public Shared Function GetCursorPos(ByRef lpPoint As PointAPI) As <MarshalAs(UnmanagedType.Bool)> Boolean
|
||||
End Function
|
||||
<DllImport("User32.dll", SetLastError:=True)>
|
||||
Friend Shared Function MonitorFromWindow(ByVal hwnd As IntPtr,
|
||||
ByVal dwFlags As Integer) As IntPtr
|
||||
End Function
|
||||
<DllImport("Shcore.dll", SetLastError:=True)>
|
||||
Friend Shared Function GetDpiForMonitor(ByVal hmonitor As IntPtr,
|
||||
ByVal dpiType As Monitor_DPI_Type,
|
||||
ByRef dpiX As UInteger,
|
||||
ByRef dpiY As UInteger) As Integer
|
||||
End Function
|
||||
<DllImport("gdi32.dll")>
|
||||
Friend Shared Function GetDeviceCaps(ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
|
||||
End Function
|
||||
|
||||
Public Declare Function RegisterHotKey Lib "user32" (
|
||||
ByVal Hwnd As IntPtr,
|
||||
ByVal ID As Integer,
|
||||
ByVal Modifiers As Integer,
|
||||
ByVal Key As Integer
|
||||
) As Integer
|
||||
|
||||
Public Declare Function UnregisterHotKey Lib "user32" (
|
||||
ByVal Hwnd As IntPtr,
|
||||
ByVal ID As Integer
|
||||
) As Integer
|
||||
|
||||
Public Declare Auto Function GetWindowText Lib "user32" (
|
||||
ByVal hWnd As IntPtr,
|
||||
ByVal lpString As StringBuilder,
|
||||
ByVal cch As Integer
|
||||
) As Integer
|
||||
|
||||
Public Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal IDString As String) As Short
|
||||
Public Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal Atom As Short) As Short
|
||||
|
||||
Public Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
|
||||
|
||||
Public Const SECTION_QUERY As Short = &H1
|
||||
Public Const SECTION_MAP_WRITE As Short = &H2
|
||||
Public Const SECTION_MAP_READ As Short = &H4
|
||||
Public Const SECTION_MAP_EXECUTE As Short = &H8
|
||||
Public Const SECTION_EXTEND_SIZE As Short = &H10
|
||||
Public Const SECTION_ALL_ACCESS As Integer = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE
|
||||
Public Const FILE_MAP_ALL_ACCESS As Integer = SECTION_ALL_ACCESS
|
||||
|
||||
Public Const PROCESS_VM_OPERATION As Short = &H8
|
||||
Public Const PROCESS_VM_READ As Short = &H10
|
||||
Public Const PROCESS_VM_WRITE As Short = &H20
|
||||
Public Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
|
||||
|
||||
Public Const MEM_COMMIT As Short = &H1000
|
||||
Public Const MEM_RESERVE As Short = &H2000
|
||||
Public Const MEM_DECOMMIT As Short = &H4000
|
||||
Public Const MEM_RELEASE As Integer = &H8000
|
||||
Public Const MEM_FREE As Integer = &H10000
|
||||
Public Const MEM_PRIVATE As Integer = &H20000
|
||||
Public Const MEM_MAPPED As Integer = &H40000
|
||||
Public Const MEM_TOP_DOWN As Integer = &H100000
|
||||
|
||||
Public Const INVALID_HANDLE_VALUE As Integer = -1
|
||||
Public Const SW_SHOW As Short = 5
|
||||
|
||||
Public Const SEE_MASK_INVOKEIDLIST = &HC
|
||||
Public Const SEE_MASK_NOCLOSEPROCESS = &H40
|
||||
Public Const SEE_MASK_FLAG_NO_UI = &H400
|
||||
|
||||
Public Const ULW_COLORKEY As Integer = &H1
|
||||
Public Const ULW_ALPHA As Integer = &H2
|
||||
Public Const ULW_OPAQUE As Integer = &H4
|
||||
|
||||
Public Const AC_SRC_OVER As Byte = &H0
|
||||
Public Const AC_SRC_ALPHA As Byte = &H1
|
||||
|
||||
Public Const HTCAPTION As Integer = &H2
|
||||
|
||||
Public Const WM_NCLBUTTONDOWN As Integer = &HA1
|
||||
Public Const WM_HOTKEY As Integer = &H312
|
||||
Public Const WM_DRAWCLIPBOARD As Integer = &H308
|
||||
|
||||
Public Enum PageProtection As UInteger
|
||||
NoAccess = &H1
|
||||
[Readonly] = &H2
|
||||
ReadWrite = &H4
|
||||
WriteCopy = &H8
|
||||
Execute = &H10
|
||||
ExecuteRead = &H20
|
||||
ExecuteReadWrite = &H40
|
||||
ExecuteWriteCopy = &H80
|
||||
Guard = &H100
|
||||
NoCache = &H200
|
||||
WriteCombine = &H400
|
||||
End Enum
|
||||
|
||||
Public Enum ChildWindowFromPointFlags As UInteger
|
||||
CWP_ALL
|
||||
CWP_SKIPINVISIBLE
|
||||
CWP_SKIPDISABLED
|
||||
CWP_SKIPTRANSPARENT
|
||||
End Enum
|
||||
|
||||
<StructLayout(LayoutKind.Sequential)>
|
||||
Public Structure WINDOWPOS
|
||||
Public hwnd As IntPtr
|
||||
Public hwndInsertAfter As IntPtr
|
||||
Public x As Integer
|
||||
Public y As Integer
|
||||
Public cx As Integer
|
||||
Public cy As Integer
|
||||
Public flags As Integer
|
||||
End Structure
|
||||
|
||||
Public Structure RectangleAPI
|
||||
Public Left As Integer
|
||||
Public Top As Integer
|
||||
Public Right As Integer
|
||||
Public Bottom As Integer
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Return String.Format("Top: {0}, Bottom: {1}, Left: {2}, Right: {3}", Top, Bottom, Left, Right)
|
||||
End Function
|
||||
End Structure
|
||||
|
||||
Public Structure ShellExecuteInfo
|
||||
Public cbSize As Integer
|
||||
Public fMask As Integer
|
||||
Public hwnd As IntPtr
|
||||
<MarshalAs(UnmanagedType.LPTStr)> Public lpVerb As String
|
||||
<MarshalAs(UnmanagedType.LPTStr)> Public lpFile As String
|
||||
<MarshalAs(UnmanagedType.LPTStr)> Public lpParameters As String
|
||||
<MarshalAs(UnmanagedType.LPTStr)> Public lpDirectory As String
|
||||
Dim nShow As Integer
|
||||
Dim hInstApp As IntPtr
|
||||
Dim lpIDList As IntPtr
|
||||
<MarshalAs(UnmanagedType.LPTStr)> Public lpClass As String
|
||||
Public hkeyClass As IntPtr
|
||||
Public dwHotKey As Integer
|
||||
Public hIcon As IntPtr
|
||||
Public hProcess As IntPtr
|
||||
End Structure
|
||||
|
||||
<System.Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)>
|
||||
Public Structure PointAPI
|
||||
Public X As Integer
|
||||
Public Y As Integer
|
||||
|
||||
Public Sub New(ByVal X As Integer, ByVal Y As Integer)
|
||||
Me.X = X
|
||||
Me.Y = Y
|
||||
End Sub
|
||||
End Structure
|
||||
End Class
|
||||
46
Base/ObjectEx.vb
Normal file
46
Base/ObjectEx.vb
Normal file
@@ -0,0 +1,46 @@
|
||||
Public Class ObjectEx
|
||||
''' <summary>
|
||||
''' Checks a value for three different `null` values,
|
||||
''' Nothing, Empty String, DBNull
|
||||
'''
|
||||
''' Returns the original value if the value is not null, or `defaultValue`
|
||||
''' </summary>
|
||||
''' <typeparam name="T">The type of the value</typeparam>
|
||||
''' <param name="value">The value</param>
|
||||
''' <param name="defaultValue">The default Value</param>
|
||||
''' <returns>The original value or the default value</returns>
|
||||
Public Shared Function NotNull(Of T)(ByVal value As T, ByVal defaultValue As T) As T
|
||||
If IsNothing(value) OrElse String.IsNullOrEmpty(value.ToString) OrElse IsDBNull(value) Then
|
||||
Return defaultValue
|
||||
Else
|
||||
Return value
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Converts a String value to the given Enum
|
||||
''' </summary>
|
||||
''' <typeparam name="T">The Enum Type</typeparam>
|
||||
''' <param name="value">The string value to convert</param>
|
||||
Public Shared Function ToEnum(Of T)(value As String) As T
|
||||
Return [Enum].Parse(GetType(T), value)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Converts an Integer value to the given Enum
|
||||
''' </summary>
|
||||
''' <typeparam name="T">The Enum Type</typeparam>
|
||||
''' <param name="value">The integer value to convert</param>
|
||||
Public Shared Function ToEnum(Of T)(value As Integer) As T
|
||||
Return [Enum].ToObject(GetType(T), value)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Converts a Long value to the given Enum
|
||||
''' </summary>
|
||||
''' <typeparam name="T">The Enum Type</typeparam>
|
||||
''' <param name="value">The long value to convert</param>
|
||||
Public Shared Function ToEnum(Of T)(value As Long) As T
|
||||
Return [Enum].ToObject(GetType(T), value)
|
||||
End Function
|
||||
End Class
|
||||
@@ -1,44 +0,0 @@
|
||||
Imports System.IO
|
||||
Imports System.Reflection
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Security.Cryptography
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class Performance
|
||||
Public Sub New(pLogConfig As LogConfig, pAppDataPath As String)
|
||||
Dim savedHash = String.Empty
|
||||
Dim assemblyLocation = Assembly.GetEntryAssembly().Location
|
||||
|
||||
Dim hashPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "hash.txt")
|
||||
If Not File.Exists(hashPath) Then
|
||||
File.Create(hashPath)
|
||||
Else
|
||||
savedHash = File.ReadAllText(hashPath)
|
||||
End If
|
||||
|
||||
Dim hash = String.Concat(SHA1.Create().ComputeHash(File.ReadAllBytes(assemblyLocation)).Select(Function(x) x.ToString("x2")))
|
||||
If hash.Equals(savedHash) Then
|
||||
Return
|
||||
End If
|
||||
|
||||
Dim dotNetRuntimePath = RuntimeEnvironment.GetRuntimeDirectory()
|
||||
Dim ngenPath = Path.Combine(dotNetRuntimePath, "ngen.exe")
|
||||
|
||||
Dim process = New Process With {
|
||||
.StartInfo = New ProcessStartInfo With {
|
||||
.FileName = ngenPath,
|
||||
.Arguments = $"install ""{assemblyLocation}"" /nologo",
|
||||
.CreateNoWindow = True,
|
||||
.UseShellExecute = True,
|
||||
.Verb = "runas"
|
||||
}
|
||||
}
|
||||
Try
|
||||
process.Start()
|
||||
process.WaitForExit()
|
||||
File.WriteAllText(hashPath, hash)
|
||||
Catch
|
||||
' ...
|
||||
End Try
|
||||
End Sub
|
||||
End Class
|
||||
163
Base/ScreenEx.vb
Normal file
163
Base/ScreenEx.vb
Normal file
@@ -0,0 +1,163 @@
|
||||
Imports System
|
||||
Imports System.Drawing
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Windows.Forms
|
||||
Imports DigitalData.Modules.Base.NativeMethods
|
||||
|
||||
Public Class ScreenEx
|
||||
Public Const DEFAULT_WINDOW_HEIGHT = 480
|
||||
Public Const DEFAULT_WINDOW_WIDTH = 640
|
||||
|
||||
Friend Const MONITORINFOF_PRIMARY As Integer = &H1
|
||||
Friend Const MONITOR_DEFAULTTONEAREST As Integer = &H2
|
||||
Friend Const MONITOR_DEFAULTTONULL As Integer = &H0
|
||||
Friend Const MONITOR_DEFAULTTOPRIMARY As Integer = &H1
|
||||
|
||||
Friend Enum Monitor_DPI_Type As Integer
|
||||
MDT_Effective_DPI = 0
|
||||
MDT_Angular_DPI = 1
|
||||
MDT_Raw_DPI = 2
|
||||
MDT_Default = MDT_Effective_DPI
|
||||
End Enum
|
||||
|
||||
Private Enum DeviceCap
|
||||
VERTRES = 10
|
||||
DESKTOPVERTRES = 117
|
||||
End Enum
|
||||
|
||||
Public Shared Function GetLocationWithinScreen(pLocation As Point) As Point?
|
||||
For Each screen As Screen In Screen.AllScreens
|
||||
If screen.Bounds.Contains(pLocation) Then
|
||||
Return New Point(pLocation.X - screen.Bounds.Left, pLocation.Y - screen.Bounds.Top)
|
||||
End If
|
||||
Next
|
||||
|
||||
Return Nothing
|
||||
End Function
|
||||
|
||||
Public Shared Sub RestoreFormPosition(pForm As Form, pPosition As Point)
|
||||
Dim oLocationWithinScreen As Point? = GetLocationWithinScreen(pPosition)
|
||||
|
||||
If oLocationWithinScreen Is Nothing Then
|
||||
Dim oPrimaryScreen = Screen.PrimaryScreen
|
||||
pForm.StartPosition = FormStartPosition.CenterScreen
|
||||
Else
|
||||
pForm.StartPosition = FormStartPosition.Manual
|
||||
pForm.Location = pPosition
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Shared Sub RestoreFormState(pForm As Form, pFormState As FormWindowState)
|
||||
If pFormState = FormWindowState.Maximized Then
|
||||
pForm.WindowState = FormWindowState.Normal
|
||||
pForm.WindowState = FormWindowState.Maximized
|
||||
ElseIf pFormState = FormWindowState.Minimized Then
|
||||
pForm.WindowState = FormWindowState.Normal
|
||||
pForm.WindowState = FormWindowState.Minimized
|
||||
Else
|
||||
pForm.WindowState = FormWindowState.Normal
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Public Shared Sub RestoreFormState(pForm As Form, pFormState As String)
|
||||
Dim oFormState As FormWindowState
|
||||
If Not [Enum].TryParse(pFormState, oFormState) Then
|
||||
oFormState = FormWindowState.Normal
|
||||
End If
|
||||
|
||||
RestoreFormState(pForm, oFormState)
|
||||
End Sub
|
||||
|
||||
Public Shared Sub RestoreFormSize(pForm As Form, pFormSize As Size)
|
||||
Dim oFormSize As Size
|
||||
If pFormSize.Height < 1 Or pFormSize.Width < 1 Or pFormSize.IsEmpty Then
|
||||
oFormSize = New Size(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT)
|
||||
Else
|
||||
oFormSize = pFormSize
|
||||
End If
|
||||
|
||||
pForm.Size = oFormSize
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' Checks if a point is Visible on any screen
|
||||
''' </summary>
|
||||
Public Shared Function IsVisibleOnAnyScreen(Location As Point) As Boolean
|
||||
Try
|
||||
Dim oRect As New Rectangle(Location, New Size(0, 0))
|
||||
|
||||
For Each oScreen In Screen.AllScreens
|
||||
If oScreen.WorkingArea.IntersectsWith(oRect) Then
|
||||
Return True
|
||||
End If
|
||||
Next
|
||||
|
||||
Return False
|
||||
Catch ex As Exception
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Checks if Size is not negative
|
||||
''' </summary>
|
||||
Public Shared Function SizeIsVisible(Size As Size) As Boolean
|
||||
If Size.Width >= 0 And Size.Height >= 0 Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
Return False
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Checks if Location is not negative
|
||||
''' </summary>
|
||||
Public Shared Function LocationIsVisible(Location As Point) As Boolean
|
||||
If Location.X >= 0 And Location.Y >= 0 Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
Return False
|
||||
End Function
|
||||
|
||||
Public Function GetScreenScaling(Form As Form) As Single
|
||||
Dim oHandle As IntPtr = Form.Handle
|
||||
Dim oFactor1, oFactor2 As Single
|
||||
|
||||
oFactor1 = GetFactorFromDeviceCaps(oHandle)
|
||||
oFactor2 = GetDPIFromMonitor(oHandle)
|
||||
|
||||
If oFactor1 > 1 Then
|
||||
Return oFactor1
|
||||
Else
|
||||
Return oFactor2
|
||||
End If
|
||||
End Function
|
||||
|
||||
Private Function GetFactorFromDeviceCaps(Handle As IntPtr) As Single
|
||||
Dim g As Graphics = Graphics.FromHwnd(Handle)
|
||||
Dim desktop As IntPtr = g.GetHdc()
|
||||
Dim LogicalScreenHeight As Integer = GetDeviceCaps(desktop, DeviceCap.VERTRES)
|
||||
Dim PhysicalScreenHeight As Integer = GetDeviceCaps(desktop, DeviceCap.DESKTOPVERTRES)
|
||||
Dim oScreenScalingFactor As Single = CSng(PhysicalScreenHeight) / CSng(LogicalScreenHeight)
|
||||
Return oScreenScalingFactor
|
||||
End Function
|
||||
|
||||
Private Function GetDPIFromMonitor(Handle As IntPtr) As Single
|
||||
'Get handle to monitor that contains this window.
|
||||
Dim monitorHandle As IntPtr = MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST)
|
||||
|
||||
'Get DPI (If the OS is not Windows 8.1 or newer, calling GetDpiForMonitor will cause exception).
|
||||
Dim dpiX As UInteger
|
||||
Dim dpiY As UInteger
|
||||
|
||||
Dim result As Integer = GetDpiForMonitor(monitorHandle, Monitor_DPI_Type.MDT_Default, dpiX, dpiY)
|
||||
|
||||
|
||||
If (result = 0) Then 'If S_OK (= 0)
|
||||
Return dpiX / 96.0F
|
||||
Else
|
||||
Return -1
|
||||
End If
|
||||
End Function
|
||||
End Class
|
||||
141
Base/StringEx.vb
Normal file
141
Base/StringEx.vb
Normal file
File diff suppressed because one or more lines are too long
36
Base/WindowsEx.vb
Normal file
36
Base/WindowsEx.vb
Normal file
@@ -0,0 +1,36 @@
|
||||
Imports System.ComponentModel
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Base.NativeMethods
|
||||
|
||||
Public Class WindowsEx
|
||||
Private ReadOnly _LogConfig As LogConfig
|
||||
Private ReadOnly _Logger As Logger
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
_LogConfig = LogConfig
|
||||
_Logger = LogConfig.GetLogger()
|
||||
End Sub
|
||||
|
||||
Public Function OpenFileProperties(FilePath As String) As Boolean
|
||||
Try
|
||||
Dim oShellExecuteInfo As New ShellExecuteInfo()
|
||||
oShellExecuteInfo.cbSize = Marshal.SizeOf(oShellExecuteInfo)
|
||||
oShellExecuteInfo.lpVerb = "properties"
|
||||
oShellExecuteInfo.lpFile = FilePath
|
||||
oShellExecuteInfo.nShow = SW_SHOW
|
||||
oShellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST
|
||||
|
||||
If Not ShellExecuteEx(oShellExecuteInfo) Then
|
||||
Dim oWin32Error = Marshal.GetLastWin32Error()
|
||||
Dim oException As New Win32Exception(oWin32Error)
|
||||
Throw oException
|
||||
End If
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
End Class
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -10,7 +10,8 @@
|
||||
<AssemblyName>DigitalData.Modules.Config</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -43,9 +44,12 @@
|
||||
<OptionInfer>On</OptionInfer>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DigitalData.Modules.Base">
|
||||
<HintPath>..\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
@@ -81,6 +85,7 @@
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -118,10 +123,6 @@
|
||||
<Project>{8a8f20fc-c46e-41ac-bee7-218366cfff99}</Project>
|
||||
<Name>Encryption</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Filesystem\Filesystem.vbproj">
|
||||
<Project>{991d0231-4623-496d-8bd0-9ca906029cbc}</Project>
|
||||
<Name>Filesystem</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Logging\Logging.vbproj">
|
||||
<Project>{903b2d7d-3b80-4be9-8713-7447b704e1b0}</Project>
|
||||
<Name>Logging</Name>
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
Imports System.Reflection
|
||||
Imports System.Xml.Serialization
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Encryption
|
||||
Imports DigitalData.Modules.Config.ConfigAttributes
|
||||
Imports DigitalData.Modules.Base
|
||||
|
||||
Public Class ConfigManager(Of T)
|
||||
Private Const USER_CONFIG_NAME As String = "UserConfig.xml"
|
||||
Private Const COMPUTER_CONFIG_NAME As String = "ComputerConfig.xml"
|
||||
Private Const APP_CONFIG_NAME As String = "AppConfig.xml"
|
||||
Public Const USER_CONFIG_NAME As String = "UserConfig.xml"
|
||||
Public Const COMPUTER_CONFIG_NAME As String = "ComputerConfig.xml"
|
||||
Public Const APP_CONFIG_NAME As String = "AppConfig.xml"
|
||||
|
||||
Private ReadOnly _LogConfig As LogConfig
|
||||
Private ReadOnly _Logger As Logger
|
||||
Private ReadOnly _File As Filesystem.File
|
||||
Private ReadOnly _File As FilesystemEx
|
||||
|
||||
Private ReadOnly _UserDirectory As String
|
||||
Private ReadOnly _UserConfigPath As String
|
||||
@@ -104,7 +104,7 @@ Public Class ConfigManager(Of T)
|
||||
Public Sub New(LogConfig As LogConfig, UserConfigPath As String, ComputerConfigPath As String, Optional ApplicationStartupPath As String = "", Optional ForceUserConfig As Boolean = False)
|
||||
_LogConfig = LogConfig
|
||||
_Logger = LogConfig.GetLogger()
|
||||
_File = New Filesystem.File(_LogConfig)
|
||||
_File = New FilesystemEx(_LogConfig)
|
||||
|
||||
_Blueprint = Activator.CreateInstance(Of T)
|
||||
_BlueprintType = _Blueprint.GetType
|
||||
@@ -122,9 +122,9 @@ Public Class ConfigManager(Of T)
|
||||
_ComputerConfigPath = Path.Combine(_ComputerDirectory, COMPUTER_CONFIG_NAME)
|
||||
End If
|
||||
|
||||
If ApplicationStartupPath <> String.Empty Then
|
||||
_Logger.Info($"AppConfig is being used: [{ApplicationStartupPath}]")
|
||||
If ApplicationStartupPath <> String.Empty Then
|
||||
_AppConfigPath = Path.Combine(ApplicationStartupPath, APP_CONFIG_NAME)
|
||||
|
||||
End If
|
||||
|
||||
_WriteAllValuesToUserConfig = ForceUserConfig
|
||||
|
||||
@@ -1,17 +1,80 @@
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Base
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class ConfigUtils
|
||||
Private _Logger As Logger
|
||||
Private _File As Filesystem.File
|
||||
Private ReadOnly _Logger As Logger
|
||||
Private ReadOnly _File As FilesystemEx
|
||||
|
||||
Private Const MIGRATE_DIRECTORY As String = "Migrate"
|
||||
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
_Logger = LogConfig.GetLogger()
|
||||
_File = New Filesystem.File(LogConfig)
|
||||
_File = New FilesystemEx(LogConfig)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' Migrate a config file when the ProductName has changed
|
||||
''' </summary>
|
||||
''' <param name="pUserBasePath">The user config base path, should be Application.UserAppDataPath</param>
|
||||
''' <param name="pProductName">The current or new product name</param>
|
||||
''' <param name="pOldProductName">The old product name</param>
|
||||
''' <returns></returns>
|
||||
Public Function MigrateUserAppDataConfig(pUserBasePath As String, pProductName As String, pOldProductName As String)
|
||||
Return MigrateAppDataConfig(pUserBasePath, ConfigManager(Of ConfigSample).USER_CONFIG_NAME, pProductName, pOldProductName)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Migrate a config file when the ProductName has changed
|
||||
''' </summary>
|
||||
''' <param name="pCommonBasePath">The config base path, should be Application.CommonAppDataPath</param>
|
||||
''' <param name="pProductName">The current or new product name</param>
|
||||
''' <param name="pOldProductName">The old product name</param>
|
||||
''' <returns></returns>
|
||||
Public Function MigrateCommonAppDataConfig(pCommonBasePath As String, pProductName As String, pOldProductName As String)
|
||||
Return MigrateAppDataConfig(pCommonBasePath, ConfigManager(Of ConfigSample).COMPUTER_CONFIG_NAME, pProductName, pOldProductName)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Migrate a config file when the ProductName has changed
|
||||
''' </summary>
|
||||
''' <param name="pBasePath">The config base path, can be Application.UserAppDataPath or Application.CommonAppDataPath</param>
|
||||
''' <param name="pProductName">The current or new product name</param>
|
||||
''' <param name="pOldProductName">The old product name</param>
|
||||
''' <returns></returns>
|
||||
Private Function MigrateAppDataConfig(pBasePath As String, pConfigName As String, pProductName As String, pOldProductName As String)
|
||||
Dim oNewDirPath = pBasePath
|
||||
Dim oOldDirPath = oNewDirPath.Replace(pProductName, pOldProductName)
|
||||
Dim oNewFilePath = Path.Combine(oNewDirPath, pConfigName)
|
||||
Dim oOldFilePath = Path.Combine(oOldDirPath, pConfigName)
|
||||
|
||||
' If there is already a new config, exit.
|
||||
If File.Exists(oNewFilePath) Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
' If there is no old config, exit.
|
||||
If Not File.Exists(oOldFilePath) Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
Try
|
||||
If Not Directory.Exists(oNewDirPath) Then
|
||||
Directory.CreateDirectory(oNewDirPath)
|
||||
End If
|
||||
|
||||
_Logger.Info("Migrating Config from [{0}] to [{1}]", pOldProductName, pProductName)
|
||||
File.Move(oOldFilePath, oNewFilePath)
|
||||
Return True
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Error while Migrating Config")
|
||||
_Logger.Error(ex)
|
||||
Return False
|
||||
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function TestMigrationNeeded(TargetDirectory As String) As Boolean
|
||||
If IO.Directory.Exists(TargetDirectory) Then
|
||||
Return False
|
||||
@@ -21,99 +84,97 @@ Public Class ConfigUtils
|
||||
End Function
|
||||
|
||||
Public Sub MigrateConfig(SourceDirectory As String, TargetDirectory As String, Optional FilePattern As String = "*.*")
|
||||
If IO.Directory.Exists(TargetDirectory) Then
|
||||
_Logger.Warn("Config Migration aborted because new config directory [{0}] already exists!", TargetDirectory)
|
||||
Exit Sub
|
||||
End If
|
||||
'If IO.Directory.Exists(TargetDirectory) Then
|
||||
' _Logger.Warn("Config Migration aborted because new config directory [{0}] already exists!", TargetDirectory)
|
||||
' Exit Sub
|
||||
'End If
|
||||
|
||||
_Logger.Debug("Creating TargetDirectory [{0}]", TargetDirectory)
|
||||
' Create target directory
|
||||
Try
|
||||
IO.Directory.CreateDirectory(TargetDirectory)
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Config Migration aborted because new config directory [{0}] could not be created!", TargetDirectory)
|
||||
_Logger.Error(ex)
|
||||
Exit Sub
|
||||
End Try
|
||||
'_Logger.Debug("Creating TargetDirectory [{0}]", TargetDirectory)
|
||||
'' Create target directory
|
||||
'Try
|
||||
' IO.Directory.CreateDirectory(TargetDirectory)
|
||||
'Catch ex As Exception
|
||||
' _Logger.Warn("Config Migration aborted because new config directory [{0}] could not be created!", TargetDirectory)
|
||||
' _Logger.Error(ex)
|
||||
' Exit Sub
|
||||
'End Try
|
||||
|
||||
' Create Migration directory
|
||||
Dim oMigrationDirectory = IO.Path.Combine(SourceDirectory, MIGRATE_DIRECTORY)
|
||||
_Logger.Debug("Creating MigrationDirectory [{0}]", oMigrationDirectory)
|
||||
Try
|
||||
IO.Directory.CreateDirectory(oMigrationDirectory)
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Config Migration aborted because migration directory [{0}] could not be created!", oMigrationDirectory)
|
||||
_Logger.Error(ex)
|
||||
Exit Sub
|
||||
End Try
|
||||
'' Create Migration directory
|
||||
'Dim oMigrationDirectory = IO.Path.Combine(SourceDirectory, MIGRATE_DIRECTORY)
|
||||
'_Logger.Debug("Creating MigrationDirectory [{0}]", oMigrationDirectory)
|
||||
'Try
|
||||
' IO.Directory.CreateDirectory(oMigrationDirectory)
|
||||
'Catch ex As Exception
|
||||
' _Logger.Warn("Config Migration aborted because migration directory [{0}] could not be created!", oMigrationDirectory)
|
||||
' _Logger.Error(ex)
|
||||
' Exit Sub
|
||||
'End Try
|
||||
|
||||
' Copy individual files from top level directory
|
||||
For Each oPath In IO.Directory.EnumerateFiles(SourceDirectory, FilePattern)
|
||||
Dim oFileInfo = New IO.FileInfo(oPath)
|
||||
'' Copy individual files from top level directory
|
||||
'For Each oPath In IO.Directory.EnumerateFiles(SourceDirectory, FilePattern)
|
||||
' Dim oFileInfo = New IO.FileInfo(oPath)
|
||||
|
||||
_Logger.NewBlock($"File {oFileInfo.Name}")
|
||||
_Logger.Debug("Processing file [{0}]", oFileInfo.Name)
|
||||
' _Logger.Debug("Processing file [{0}]", oFileInfo.Name)
|
||||
|
||||
_Logger.Debug("Copying [{0}] to TargetDirectory..", oFileInfo.Name)
|
||||
' Copy to target directory
|
||||
Try
|
||||
IO.File.Copy(oPath, IO.Path.Combine(TargetDirectory, oFileInfo.Name))
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Could not move old config file {0} to new config location {1}", oFileInfo.Name, TargetDirectory)
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
' _Logger.Debug("Copying [{0}] to TargetDirectory..", oFileInfo.Name)
|
||||
' ' Copy to target directory
|
||||
' Try
|
||||
' IO.File.Copy(oPath, IO.Path.Combine(TargetDirectory, oFileInfo.Name))
|
||||
' Catch ex As Exception
|
||||
' _Logger.Warn("Could not move old config file {0} to new config location {1}", oFileInfo.Name, TargetDirectory)
|
||||
' _Logger.Error(ex)
|
||||
' End Try
|
||||
|
||||
_Logger.Debug("Moving [{0}] to MigrationDirectory..", oFileInfo.Name)
|
||||
' Move to migration directory
|
||||
Try
|
||||
IO.File.Move(oPath, IO.Path.Combine(oMigrationDirectory, oFileInfo.Name))
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Could not move old config file {0} to migration directory {1}", oFileInfo.Name, oMigrationDirectory)
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
Next
|
||||
' _Logger.Debug("Moving [{0}] to MigrationDirectory..", oFileInfo.Name)
|
||||
' ' Move to migration directory
|
||||
' Try
|
||||
' IO.File.Move(oPath, IO.Path.Combine(oMigrationDirectory, oFileInfo.Name))
|
||||
' Catch ex As Exception
|
||||
' _Logger.Warn("Could not move old config file {0} to migration directory {1}", oFileInfo.Name, oMigrationDirectory)
|
||||
' _Logger.Error(ex)
|
||||
' End Try
|
||||
'Next
|
||||
|
||||
For Each oDirectoryPath In IO.Directory.EnumerateDirectories(SourceDirectory, "*", IO.SearchOption.TopDirectoryOnly)
|
||||
Dim oDirInfo As New IO.DirectoryInfo(oDirectoryPath)
|
||||
'For Each oDirectoryPath In IO.Directory.EnumerateDirectories(SourceDirectory, "*", IO.SearchOption.TopDirectoryOnly)
|
||||
' Dim oDirInfo As New IO.DirectoryInfo(oDirectoryPath)
|
||||
|
||||
_Logger.NewBlock($"Directory {oDirInfo.Name}")
|
||||
_Logger.Debug("Processing directory [{0}]", oDirInfo.Name)
|
||||
' _Logger.Debug("Processing directory [{0}]", oDirInfo.Name)
|
||||
|
||||
' Don't copy TargetDirectory if subpath of SourceDirectory or if MigrationDirectory
|
||||
If oDirInfo.FullName = TargetDirectory Or oDirInfo.FullName = oMigrationDirectory Then
|
||||
_Logger.Debug("Directory [{0}] should not be copied. Skipping.", oDirInfo.Name)
|
||||
Continue For
|
||||
End If
|
||||
' ' Don't copy TargetDirectory if subpath of SourceDirectory or if MigrationDirectory
|
||||
' If oDirInfo.FullName = TargetDirectory Or oDirInfo.FullName = oMigrationDirectory Then
|
||||
' _Logger.Debug("Directory [{0}] should not be copied. Skipping.", oDirInfo.Name)
|
||||
' Continue For
|
||||
' End If
|
||||
|
||||
' Copy directory to TargetDirectory
|
||||
Dim oNewDirectoryPath = IO.Path.Combine(TargetDirectory, oDirInfo.Name)
|
||||
_Logger.Debug("Copying [{0}] to TargetDirectory..", oDirInfo.Name)
|
||||
Try
|
||||
_File.CopyDirectory(oDirInfo.FullName, oNewDirectoryPath, True)
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Could not move directory [{0}] to new path [{1}]", oDirInfo.FullName, oNewDirectoryPath)
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
' ' Copy directory to TargetDirectory
|
||||
' Dim oNewDirectoryPath = IO.Path.Combine(TargetDirectory, oDirInfo.Name)
|
||||
' _Logger.Debug("Copying [{0}] to TargetDirectory..", oDirInfo.Name)
|
||||
' Try
|
||||
' _File.CopyDirectory(oDirInfo.FullName, oNewDirectoryPath, True)
|
||||
' Catch ex As Exception
|
||||
' _Logger.Warn("Could not move directory [{0}] to new path [{1}]", oDirInfo.FullName, oNewDirectoryPath)
|
||||
' _Logger.Error(ex)
|
||||
' End Try
|
||||
|
||||
_Logger.Debug("Copying [{0}] to MigrationDirectory..", oDirInfo.Name)
|
||||
' Copy directory to MigrationDirectory
|
||||
Dim oMigrationDirectoryPath = IO.Path.Combine(oMigrationDirectory, oDirInfo.Name)
|
||||
Try
|
||||
_File.CopyDirectory(oDirInfo.FullName, oMigrationDirectoryPath, True)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
_Logger.Warn("Could not move directory [{0}] to migration directory [{1}]", oDirInfo.FullName, oMigrationDirectoryPath)
|
||||
End Try
|
||||
' _Logger.Debug("Copying [{0}] to MigrationDirectory..", oDirInfo.Name)
|
||||
' ' Copy directory to MigrationDirectory
|
||||
' Dim oMigrationDirectoryPath = IO.Path.Combine(oMigrationDirectory, oDirInfo.Name)
|
||||
' Try
|
||||
' _File.CopyDirectory(oDirInfo.FullName, oMigrationDirectoryPath, True)
|
||||
' Catch ex As Exception
|
||||
' _Logger.Error(ex)
|
||||
' _Logger.Warn("Could not move directory [{0}] to migration directory [{1}]", oDirInfo.FullName, oMigrationDirectoryPath)
|
||||
' End Try
|
||||
|
||||
_Logger.Debug("Deleting [{0}]..", oDirInfo.Name)
|
||||
' Delete directory
|
||||
Try
|
||||
IO.Directory.Delete(oDirInfo.FullName, True)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
_Logger.Warn("Could not delete directory [{0}]", oDirInfo.FullName)
|
||||
End Try
|
||||
Next
|
||||
' _Logger.Debug("Deleting [{0}]..", oDirInfo.Name)
|
||||
' ' Delete directory
|
||||
' Try
|
||||
' IO.Directory.Delete(oDirInfo.FullName, True)
|
||||
' Catch ex As Exception
|
||||
' _Logger.Error(ex)
|
||||
' _Logger.Warn("Could not delete directory [{0}]", oDirInfo.FullName)
|
||||
' End Try
|
||||
'Next
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
@@ -12,7 +12,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("")>
|
||||
<Assembly: AssemblyProduct("Modules.Config")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2023")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.1.4.1")>
|
||||
<Assembly: AssemblyFileVersion("1.1.4.1")>
|
||||
<Assembly: AssemblyVersion("1.2.2.0")>
|
||||
<Assembly: AssemblyFileVersion("1.2.2.0")>
|
||||
|
||||
2
Config/My Project/Resources.Designer.vb
generated
2
Config/My Project/Resources.Designer.vb
generated
@@ -22,7 +22,7 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
|
||||
2
Config/My Project/Settings.Designer.vb
generated
2
Config/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<MySubMain>false</MySubMain>
|
||||
<MySubMain>true</MySubMain>
|
||||
<MainForm>Form1</MainForm>
|
||||
<SingleInstance>false</SingleInstance>
|
||||
<ShutdownMode>0</ShutdownMode>
|
||||
<EnableVisualStyles>true</EnableVisualStyles>
|
||||
<AuthenticationMode>0</AuthenticationMode>
|
||||
<ApplicationType>1</ApplicationType>
|
||||
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
|
||||
</MyApplicationData>
|
||||
</MyApplicationData>
|
||||
@@ -1,16 +1,22 @@
|
||||
Imports System.ComponentModel
|
||||
Imports System.Data.Common
|
||||
Imports System.Data.SqlClient
|
||||
Imports DigitalData.Modules.Encryption
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Base
|
||||
Imports System.Threading
|
||||
|
||||
Public Class MSSQLServer
|
||||
Implements IDatabase
|
||||
|
||||
Public Property DBInitialized As Boolean = False Implements IDatabase.DBInitialized
|
||||
Public Property CurrentConnectionString As String = "" Implements IDatabase.CurrentConnectionString
|
||||
Public ReadOnly Property MaskedConnectionString As String
|
||||
Get
|
||||
If CurrentConnectionString = "" Then
|
||||
Return ""
|
||||
Else
|
||||
Return MaskConnectionString(CurrentConnectionString)
|
||||
End If
|
||||
End Get
|
||||
End Property
|
||||
|
||||
Private ReadOnly QueryTimeout As Integer
|
||||
Private ReadOnly Logger As Logger
|
||||
@@ -103,33 +109,34 @@ Public Class MSSQLServer
|
||||
End Try
|
||||
End Function
|
||||
|
||||
<DebuggerStepThrough()>
|
||||
Private Function MaybeGetTransaction(Connection As SqlConnection, Mode As TransactionMode, Transaction As SqlTransaction) As SqlTransaction
|
||||
If Connection Is Nothing Then
|
||||
Throw New ArgumentNullException("Connection")
|
||||
Private Function MaybeGetTransaction(pConnection As SqlConnection, pTransactionMode As TransactionMode, pTransaction As SqlTransaction) As SqlTransaction
|
||||
If pConnection Is Nothing Then
|
||||
Throw New ArgumentNullException("Connection", "Could not get transaction because connection is null!")
|
||||
End If
|
||||
|
||||
If Mode = TransactionMode.NoTransaction Then
|
||||
Logger.Debug("Transaction Mode: [{0}]", pTransactionMode.ToString)
|
||||
|
||||
If pTransactionMode = TransactionMode.NoTransaction Then
|
||||
Return Nothing
|
||||
ElseIf Mode = TransactionMode.ExternalTransaction Then
|
||||
Return Transaction
|
||||
ElseIf pTransactionMode = TransactionMode.ExternalTransaction Then
|
||||
Return pTransaction
|
||||
Else
|
||||
Return Connection.BeginTransaction()
|
||||
Return pConnection.BeginTransaction()
|
||||
End If
|
||||
End Function
|
||||
|
||||
<DebuggerStepThrough()>
|
||||
Private Function MaybeCommitTransaction(Transaction As SqlTransaction, TransactionMode As TransactionMode) As Boolean
|
||||
Select Case TransactionMode
|
||||
Private Function MaybeCommitTransaction(pTransaction As SqlTransaction, pTransactionMode As TransactionMode) As Boolean
|
||||
Select Case pTransactionMode
|
||||
Case TransactionMode.NoTransaction
|
||||
Return True
|
||||
Case TransactionMode.ExternalTransaction
|
||||
Return True
|
||||
Case TransactionMode.WithTransaction
|
||||
Try
|
||||
Transaction.Commit()
|
||||
pTransaction.Commit()
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Logger.Warn("Error while committing transaction!")
|
||||
Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
@@ -206,10 +213,13 @@ Public Class MSSQLServer
|
||||
Dim oDecryptedConnectionString = DecryptConnectionString(pConnectionString)
|
||||
Dim oConnection As New SqlConnection(oDecryptedConnectionString)
|
||||
OpenSQLConnection(oConnection)
|
||||
oConnection.Close()
|
||||
oConnection?.Close()
|
||||
Return True
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error("Error while testing connection!")
|
||||
Logger.Error(ex)
|
||||
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
@@ -217,14 +227,21 @@ Public Class MSSQLServer
|
||||
''' <summary>
|
||||
''' This Function intentionally has no try..catch block to have any errors caught outside
|
||||
''' </summary>
|
||||
''' <param name="Connection"></param>
|
||||
''' <param name="pConnection"></param>
|
||||
''' <returns></returns>
|
||||
Private Function OpenSQLConnection(Connection As SqlConnection) As SqlConnection
|
||||
If Connection.State = ConnectionState.Closed Then
|
||||
Connection.Open()
|
||||
End If
|
||||
Private Function OpenSQLConnection(pConnection As SqlConnection) As SqlConnection
|
||||
Try
|
||||
If pConnection.State = ConnectionState.Closed Then
|
||||
pConnection.Open()
|
||||
End If
|
||||
|
||||
Return Connection
|
||||
Return pConnection
|
||||
Catch ex As Exception
|
||||
Logger.Error("Error while opening Connection!")
|
||||
Logger.Error(ex)
|
||||
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
<DebuggerStepThrough()>
|
||||
@@ -242,6 +259,7 @@ Public Class MSSQLServer
|
||||
|
||||
Return oConnection
|
||||
Catch ex As Exception
|
||||
Logger.Error("Connection could not be created or opened!")
|
||||
Logger.Error(ex)
|
||||
|
||||
Return Nothing
|
||||
@@ -253,14 +271,16 @@ Public Class MSSQLServer
|
||||
Try
|
||||
If pConnectionString Is Nothing OrElse pConnectionString.Length = 0 Then
|
||||
Logger.Warn("Connection String is empty!")
|
||||
Throw New ArgumentNullException("pConnectionString")
|
||||
Throw New ArgumentNullException("pConnectionString", "Could not mask connection string because connectiong string is empty!")
|
||||
End If
|
||||
|
||||
Dim oBuilder As New SqlConnectionStringBuilder() With {.ConnectionString = pConnectionString}
|
||||
Dim oConnectionString = pConnectionString.Replace(oBuilder.Password, "XXXXX")
|
||||
Return oConnectionString
|
||||
Catch ex As Exception
|
||||
Logger.Error("ConnectionString is invalid and could not be masked!")
|
||||
Logger.Error(ex)
|
||||
|
||||
Return "Invalid ConnectionString"
|
||||
End Try
|
||||
End Function
|
||||
@@ -288,15 +308,11 @@ Public Class MSSQLServer
|
||||
End Function
|
||||
|
||||
Public Function GetDatatable(pSqlCommand As String, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As DataTable
|
||||
Using oSqlConnection = GetSQLConnection()
|
||||
Return GetDatatableWithConnectionObject(pSqlCommand, oSqlConnection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return GetDatatableWithConnectionObject(pSqlCommand, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Function GetDatatable(pSqlCommandObject As SqlCommand, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As DataTable
|
||||
Using oSqlConnection = GetSQLConnection()
|
||||
Return GetDatatableWithConnectionObject(pSqlCommandObject, oSqlConnection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return GetDatatableWithConnectionObject(pSqlCommandObject, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Async Function GetDatatableAsync(pSqlCommand As String, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Task(Of DataTable)
|
||||
@@ -319,6 +335,20 @@ Public Class MSSQLServer
|
||||
End Using
|
||||
End Function
|
||||
|
||||
Public Async Function GetDatatableWithConnectionObjectAsync(pSqlCommand As String, pSqlConnection As SqlConnection,
|
||||
Optional pTransactionMode As TransactionMode = TransactionMode.WithTransaction,
|
||||
Optional pTransaction As SqlTransaction = Nothing,
|
||||
Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Task(Of DataTable)
|
||||
Return Await Task.Run(Function() GetDatatableWithConnectionObject(pSqlCommand, pSqlConnection, pTransactionMode, pTransaction, pTimeout))
|
||||
End Function
|
||||
|
||||
Public Async Function GetDatatableWithConnectionObjectAsync(pSqlCommandObject As SqlCommand, pSqlConnection As SqlConnection,
|
||||
Optional pTransactionMode As TransactionMode = TransactionMode.WithTransaction,
|
||||
Optional pTransaction As SqlTransaction = Nothing,
|
||||
Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Task(Of DataTable)
|
||||
Return Await Task.Run(Function() GetDatatableWithConnectionObject(pSqlCommandObject, pSqlConnection, pTransactionMode, pTransaction, pTimeout))
|
||||
End Function
|
||||
|
||||
Public Function GetDatatableWithConnectionObject(pSqlCommand As String, pSqlConnection As SqlConnection,
|
||||
Optional pTransactionMode As TransactionMode = TransactionMode.WithTransaction,
|
||||
Optional pTransaction As SqlTransaction = Nothing,
|
||||
@@ -340,13 +370,13 @@ Public Class MSSQLServer
|
||||
pSqlCommandObject.CommandTimeout = pTimeout
|
||||
|
||||
Using oAdapter As New SqlDataAdapter(pSqlCommandObject)
|
||||
Logger.Debug("GetDatatableWithConnectionObject: Running Query [{0}]", pSqlCommandObject.CommandText)
|
||||
Logger.Debug("GetDatatableWithConnectionObject: Running Query [{0}] and Parameters [{1}]", pSqlCommandObject.CommandText, GetParameterListAsString(pSqlCommandObject))
|
||||
oAdapter.Fill(oTable)
|
||||
End Using
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error("GetDatatableWithConnectionObject: Error in GetDatatableWithConnection while executing command: [{0}]", pSqlCommandObject.CommandText)
|
||||
Logger.Error(ex)
|
||||
Logger.Warn("GetDatatableWithConnectionObject: Error in GetDatatableWithConnection while executing command: [{0}]", pSqlCommandObject)
|
||||
Throw ex
|
||||
Finally
|
||||
MaybeCommitTransaction(oTransaction, pTransactionMode)
|
||||
@@ -381,15 +411,11 @@ Public Class MSSQLServer
|
||||
|
||||
|
||||
Public Function ExecuteNonQuery(pSQLCommand As String, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Boolean
|
||||
Using oConnection = GetSQLConnection()
|
||||
Return ExecuteNonQueryWithConnectionObject(pSQLCommand, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return ExecuteNonQueryWithConnectionObject(pSQLCommand, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Function ExecuteNonQuery(pSQLCommandObject As SqlCommand, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Boolean
|
||||
Using oConnection = GetSQLConnection()
|
||||
Return ExecuteNonQueryWithConnectionObject(pSQLCommandObject, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return ExecuteNonQueryWithConnectionObject(pSQLCommandObject, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Async Function ExecuteNonQueryAsync(pSQLCommand As String, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Task(Of Boolean)
|
||||
@@ -427,7 +453,7 @@ Public Class MSSQLServer
|
||||
Dim oTransaction As SqlTransaction = MaybeGetTransaction(pSqlConnection, pTransactionMode, pTransaction)
|
||||
|
||||
Try
|
||||
Logger.Debug("ExecuteNonQueryWithConnectionObject: Running Command [{0}]", pSqlCommandObject.CommandText)
|
||||
Logger.Debug("ExecuteNonQueryWithConnectionObject: Running Command [{0}] and Parameters [{1}]", pSqlCommandObject.CommandText, GetParameterListAsString(pSqlCommandObject))
|
||||
|
||||
pSqlCommandObject.Connection = pSqlConnection
|
||||
pSqlCommandObject.Transaction = oTransaction
|
||||
@@ -436,8 +462,9 @@ Public Class MSSQLServer
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Logger.Error("ExecuteNonQueryWithConnectionObject: Error in ExecuteNonQueryWithConnectionObject while executing command: [{0}]", pSqlCommandObject.CommandText)
|
||||
Logger.Error(ex)
|
||||
Logger.Warn("ExecuteNonQueryWithConnectionObject: Error in ExecuteNonQueryWithConnectionObject while executing command: [{0}]-[{1}]", SqlCommand, SqlConnection.ConnectionString)
|
||||
|
||||
Return False
|
||||
Finally
|
||||
MaybeCommitTransaction(oTransaction, pTransactionMode)
|
||||
@@ -469,15 +496,11 @@ Public Class MSSQLServer
|
||||
End Function
|
||||
|
||||
Public Function GetScalarValue(pSQLCommand As String, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Object
|
||||
Using oConnection = GetSQLConnection()
|
||||
Return GetScalarValueWithConnectionObject(pSQLCommand, oConnection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return GetScalarValueWithConnectionObject(pSQLCommand, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Function GetScalarValue(pSQLCommandObject As SqlCommand, pTransaction As SqlTransaction, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Object
|
||||
Using oConnection = GetSQLConnection()
|
||||
Return GetScalarValueWithConnectionObject(pSQLCommandObject, oConnection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Using
|
||||
Return GetScalarValueWithConnectionObject(pSQLCommandObject, pTransaction.Connection, TransactionMode.ExternalTransaction, pTransaction, pTimeout)
|
||||
End Function
|
||||
|
||||
Public Async Function GetScalarValueAsync(pSQLCommand As String, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As Task(Of Object)
|
||||
@@ -517,6 +540,9 @@ Public Class MSSQLServer
|
||||
Dim oResult As Object = Nothing
|
||||
|
||||
Try
|
||||
|
||||
Logger.Debug("GetScalarValueWithConnectionObject: Running Query [{0}] with Parameters [{1}]", pSqlCommandObject.CommandText, GetParameterListAsString(pSqlCommandObject))
|
||||
|
||||
pSqlCommandObject.Connection = pSqlConnection
|
||||
pSqlCommandObject.CommandTimeout = pTimeout
|
||||
pSqlCommandObject.Transaction = oTransaction
|
||||
@@ -524,7 +550,7 @@ Public Class MSSQLServer
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Logger.Warn("GetDatatableWithConnectionObject: Error in GetDatatableWithConnection while executing command: [{0}]", pSqlCommandObject)
|
||||
Logger.Error("GetDatatableWithConnectionObject: Error in GetDatatableWithConnection while executing command: [{0}]", pSqlCommandObject.CommandText)
|
||||
|
||||
Finally
|
||||
MaybeCommitTransaction(oTransaction, pTransactionMode)
|
||||
@@ -559,7 +585,7 @@ Public Class MSSQLServer
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Logger.Warn($"GetScalarValue failed SQLCommand [{pSqlCommand}]")
|
||||
Logger.Error($"GetScalarValue failed SQLCommand [{pSqlCommand}]")
|
||||
|
||||
Return Nothing
|
||||
End Try
|
||||
@@ -591,7 +617,7 @@ Public Class MSSQLServer
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Logger.Warn($"NewExecuteNonQueryAsync failed SQLCommand [{SqlCommand}]")
|
||||
Logger.Error($"NewExecuteNonQueryAsync failed SQLCommand [{SqlCommand}]")
|
||||
|
||||
End Try
|
||||
End Sub
|
||||
@@ -601,4 +627,13 @@ Public Class MSSQLServer
|
||||
Dim res = command.EndExecuteNonQuery(result)
|
||||
Logger.Info("Finished executing Async database operation: {0}", command.CommandText)
|
||||
End Sub
|
||||
|
||||
Private Function GetParameterListAsString(pSQLCommand As SqlCommand) As String
|
||||
Dim oList = pSQLCommand.Parameters.
|
||||
Cast(Of SqlParameter).
|
||||
Select(Function(p) $"({p.ParameterName}={p.Value})").
|
||||
ToList()
|
||||
|
||||
Return String.Join(",", oList)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
@@ -127,7 +127,7 @@ Public Class Oracle
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function GetDatatable(pSQLCommand As String, pTimeout As Integer) As DataTable Implements IDatabase.GetDatatable
|
||||
Public Function GetDatatable(pSQLCommand As String, Optional pTimeout As Integer = Constants.DEFAULT_TIMEOUT) As DataTable Implements IDatabase.GetDatatable
|
||||
Try
|
||||
Using oConnection = GetConnection(CurrentConnectionString)
|
||||
Dim oSQLCommand As OracleCommand
|
||||
@@ -151,8 +151,8 @@ Public Class Oracle
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function GetDatatable(pSQLCommand As String) As DataTable Implements IDatabase.GetDatatable
|
||||
Return GetDatatable(pSQLCommand, _Timeout)
|
||||
Public Function GetDatatable(SqlCommand As SqlClient.SqlCommand, Optional Timeout As Integer = 120) As DataTable Implements IDatabase.GetDatatable
|
||||
Throw New NotImplementedException()
|
||||
End Function
|
||||
|
||||
Public Function ExecuteNonQuery(pSQLCommand As String, pTimeout As Integer) As Boolean Implements IDatabase.ExecuteNonQuery
|
||||
@@ -250,4 +250,6 @@ Public Class Oracle
|
||||
Return "Invalid ConnectionString"
|
||||
End Try
|
||||
End Function
|
||||
|
||||
|
||||
End Class
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
|
||||
</configSections>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="EntityFramework.Firebird.FbConnectionFactory, EntityFramework.Firebird" />
|
||||
<defaultConnectionFactory type="EntityFramework.Firebird.FbConnectionFactory, EntityFramework.Firebird"/>
|
||||
<providers>
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
|
||||
<provider invariantName="FirebirdSql.Data.FirebirdClient" type="EntityFramework.Firebird.FbProviderServices, EntityFramework.Firebird" />
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
|
||||
<provider invariantName="FirebirdSql.Data.FirebirdClient" type="EntityFramework.Firebird.FbProviderServices, EntityFramework.Firebird"/>
|
||||
</providers>
|
||||
</entityFramework>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-7.5.0.0" newVersion="7.5.0.0" />
|
||||
<assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-7.5.0.0" newVersion="7.5.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
<AssemblyName>DigitalData.Modules.Database</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -59,8 +60,8 @@
|
||||
<HintPath>..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Oracle.ManagedDataAccess">
|
||||
<HintPath>P:\Visual Studio Projekte\Bibliotheken\Oracle.ManagedDataAccess.dll</HintPath>
|
||||
@@ -99,7 +100,6 @@
|
||||
<Compile Include="Dispatcher.vb" />
|
||||
<Compile Include="Exceptions.vb" />
|
||||
<Compile Include="Adapters\Firebird.vb" />
|
||||
<Compile Include="Helpers.vb" />
|
||||
<Compile Include="IDatabase.vb" />
|
||||
<Compile Include="Adapters\ODBC.vb" />
|
||||
<Compile Include="Adapters\Oracle.vb" />
|
||||
@@ -108,6 +108,7 @@
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -120,7 +121,6 @@
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="Queries.vb" />
|
||||
<Compile Include="TableCache.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="My Project\Resources.resx">
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
Public Class Helpers
|
||||
|
||||
Public Shared Function MaybeEscapeSQLCommand(pSQLCommand As String) As String
|
||||
|
||||
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
End Class
|
||||
@@ -12,8 +12,8 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("Digital Data")>
|
||||
<Assembly: AssemblyProduct("Modules.Database")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyTrademark("2.2.7.5")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
||||
<Assembly: AssemblyTrademark("2.3.4.0")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2.2.7.5")>
|
||||
<Assembly: AssemblyFileVersion("2.2.7.5")>
|
||||
<Assembly: AssemblyVersion("2.3.4.0")>
|
||||
<Assembly: AssemblyFileVersion("2.3.4.0")>
|
||||
|
||||
2
Database/My Project/Resources.Designer.vb
generated
2
Database/My Project/Resources.Designer.vb
generated
@@ -22,7 +22,7 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
|
||||
2
Database/My Project/Settings.Designer.vb
generated
2
Database/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Public Class TableCache
|
||||
Private Items As New Dictionary(Of String, DataTable)
|
||||
|
||||
Public Function [Get](SQLCommand As String)
|
||||
Dim oKey As String = SQLCommand.ToUpper
|
||||
If Items.ContainsKey(oKey) Then
|
||||
Return Items.Item(oKey)
|
||||
Else
|
||||
|
||||
End If
|
||||
End Function
|
||||
|
||||
Private Function SaveTable()
|
||||
|
||||
End Function
|
||||
|
||||
End Class
|
||||
@@ -3,6 +3,6 @@
|
||||
<package id="EntityFramework" version="6.4.4" targetFramework="net461" />
|
||||
<package id="EntityFramework.Firebird" version="6.4.0" targetFramework="net461" />
|
||||
<package id="FirebirdSql.Data.FirebirdClient" version="7.5.0" targetFramework="net461" />
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
<package id="System.Data.Odbc" version="6.0.1" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -1,9 +1,9 @@
|
||||
Imports System.IO
|
||||
Imports System.ServiceModel
|
||||
Imports DigitalData.Modules.Base
|
||||
Imports DigitalData.Modules.EDMI.API.Constants
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.EDMI.API.Rights
|
||||
Imports DigitalData.Modules.Language.Utils
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class Client
|
||||
@@ -550,10 +550,10 @@ Public Class Client
|
||||
.Id = oRow.Item("AttributeId"),
|
||||
.Title = oRow.Item("AttributeTitle"),
|
||||
.Type = oRow.Item("AttributeType"),
|
||||
.ValueBigInt = NotNull(oRow.Item("ValueBigInt"), Nothing),
|
||||
.ValueDate = NotNull(oRow.Item("ValueDate"), Nothing),
|
||||
.ValueDecimal = NotNull(oRow.Item("ValueDecimal"), Nothing),
|
||||
.ValueText = NotNull(oRow.Item("ValueText"), Nothing)
|
||||
.ValueBigInt = oRow.ItemEx(Of Object)("ValueBigInt", Nothing),
|
||||
.ValueDate = oRow.ItemEx(Of Object)("ValueDate", Nothing),
|
||||
.ValueDecimal = oRow.ItemEx(Of Object)("ValueDecimal", Nothing),
|
||||
.ValueText = oRow.ItemEx(Of Object)("ValueText", Nothing)
|
||||
}
|
||||
|
||||
oAttributes.Add(oAttribute)
|
||||
@@ -932,11 +932,11 @@ Public Class Client
|
||||
|
||||
|
||||
Private Function GetUserLanguage(pOverrideLanguage As String) As String
|
||||
Return NotNull(pOverrideLanguage, Threading.Thread.CurrentThread.CurrentUICulture.Name)
|
||||
Return ObjectEx.NotNull(pOverrideLanguage, Threading.Thread.CurrentThread.CurrentUICulture.Name)
|
||||
End Function
|
||||
|
||||
Private Function GetUserName(pOverrideName) As String
|
||||
Return NotNull(pOverrideName, Environment.UserName)
|
||||
Return ObjectEx.NotNull(pOverrideName, Environment.UserName)
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ Imports DigitalData.Modules.EDMI.API
|
||||
Imports DigitalData.Modules.EDMI.API.Constants
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Language.Utils
|
||||
|
||||
Public Class DatabaseWithFallback
|
||||
Private ReadOnly _Logger As Logger
|
||||
@@ -191,25 +190,30 @@ Public Class DatabaseWithFallback
|
||||
|
||||
' If there is no client, we assume there is no service (configured)
|
||||
If _Client Is Nothing Then
|
||||
_Logger.Debug("Client is empty, falling back to direct database access.")
|
||||
Return GetDatatableFromDatabase(pFallbackSQL, pFallbackType, pConnectionId)
|
||||
End If
|
||||
|
||||
' If ForceFallback flag is set, we go to database immediately
|
||||
If pForceFallback Or _ClientConfig.ForceDirectDatabaseAccess Then
|
||||
_Logger.Debug("ForceFallback is True, falling back to direct database access.")
|
||||
Return GetDatatableFromDatabase(pFallbackSQL, pFallbackType, pConnectionId)
|
||||
End If
|
||||
|
||||
' If the table is not cached, we try going through the service
|
||||
If Not IsTableCached(pDataTableName) Then
|
||||
_Logger.Debug("Datatable is not chached, fetching data from service.")
|
||||
Return GetDatatableFromService(pFallbackSQL, pFallbackType, pConnectionId)
|
||||
End If
|
||||
|
||||
' If there is a proper ConnectionId, we try going through the service
|
||||
If pConnectionId > 0 Then
|
||||
_Logger.Debug("ConnectionId is set, fetching data from service.")
|
||||
Return GetDatatableFromService(pFallbackSQL, pFallbackType, pConnectionId)
|
||||
End If
|
||||
|
||||
Try
|
||||
_Logger.Debug("Datatable is chached, fetching data from cache.")
|
||||
oTableResult = _Client.GetDatatableByName(pDataTableName, pFilterExpression, pSortByColumn)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
@@ -332,26 +336,25 @@ Public Class DatabaseWithFallback
|
||||
End Function
|
||||
|
||||
|
||||
Private Function GetDatatableFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As DataTable
|
||||
Private Function GetDatatableFromDatabase(pSQLCommand As String, pDatabaseType As Constants.DatabaseType, pConnectionId As Integer) As DataTable
|
||||
Try
|
||||
Dim oResult As ExecuteNonQueryResponse = Nothing
|
||||
|
||||
Select Case DatabaseType
|
||||
Case Constants.DatabaseType.ECM
|
||||
Return _DatabaseECM.GetDatatable(pSQLCommand)
|
||||
_Logger.Debug("Fetching data from database [{0}] with Connection Id [{0}]", pDatabaseType.ToString, pConnectionId)
|
||||
|
||||
Select Case pDatabaseType
|
||||
Case Constants.DatabaseType.IDB
|
||||
Return _DatabaseIDB.GetDatatable(pSQLCommand)
|
||||
|
||||
Case Else
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
If oConnectionString = String.Empty Then
|
||||
Return _DatabaseECM.GetDatatable(pSQLCommand)
|
||||
Else
|
||||
If pConnectionId > 0 Then
|
||||
_Logger.Debug("Retrieving Connection String from Connection Id [{0}]", pConnectionId)
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
Return _DatabaseECM.GetDatatableWithConnection(pSQLCommand, oConnectionString)
|
||||
Else
|
||||
Return _DatabaseECM.GetDatatable(pSQLCommand)
|
||||
End If
|
||||
|
||||
End Select
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return Nothing
|
||||
@@ -397,20 +400,19 @@ Public Class DatabaseWithFallback
|
||||
Private Function GetScalarValueFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Object
|
||||
Try
|
||||
Select Case DatabaseType
|
||||
Case Constants.DatabaseType.ECM
|
||||
Return _DatabaseECM.GetScalarValue(pSQLCommand)
|
||||
|
||||
Case Constants.DatabaseType.IDB
|
||||
Return _DatabaseIDB.GetScalarValue(pSQLCommand)
|
||||
|
||||
Case Else
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
If oConnectionString = String.Empty Then
|
||||
Return _DatabaseECM.GetScalarValue(pSQLCommand)
|
||||
Else
|
||||
If pConnectionId > 0 Then
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
Return _DatabaseECM.GetScalarValueWithConnection(pSQLCommand, oConnectionString)
|
||||
Else
|
||||
Return _DatabaseECM.GetScalarValue(pSQLCommand)
|
||||
End If
|
||||
|
||||
End Select
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return Nothing
|
||||
@@ -455,21 +457,19 @@ Public Class DatabaseWithFallback
|
||||
Private Function ExecuteNonQueryFromDatabase(pSQLCommand As String, DatabaseType As Constants.DatabaseType, pConnectionId As Integer) As Boolean
|
||||
Try
|
||||
Select Case DatabaseType
|
||||
Case Constants.DatabaseType.ECM
|
||||
Return _DatabaseECM.ExecuteNonQuery(pSQLCommand)
|
||||
|
||||
Case Constants.DatabaseType.IDB
|
||||
Return _DatabaseIDB.ExecuteNonQuery(pSQLCommand)
|
||||
|
||||
Case Else
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
If oConnectionString = String.Empty Then
|
||||
Return _DatabaseECM.ExecuteNonQuery(pSQLCommand)
|
||||
Else
|
||||
If pConnectionId > 0 Then
|
||||
Dim oConnectionString = _DatabaseECM.Get_ConnectionStringforID(pConnectionId)
|
||||
Return _DatabaseECM.ExecuteNonQueryWithConnection(pSQLCommand, oConnectionString)
|
||||
Else
|
||||
Return _DatabaseECM.ExecuteNonQuery(pSQLCommand)
|
||||
End If
|
||||
|
||||
End Select
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return False
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
<AssemblyName>DigitalData.Modules.EDMI.API</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -44,8 +45,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
@@ -101,6 +102,7 @@
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
@@ -306,14 +308,6 @@
|
||||
<Project>{eaf0ea75-5fa7-485d-89c7-b2d843b03a96}</Project>
|
||||
<Name>Database</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Filesystem\Filesystem.vbproj">
|
||||
<Project>{991d0231-4623-496d-8bd0-9ca906029cbc}</Project>
|
||||
<Name>Filesystem</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Language\Language.vbproj">
|
||||
<Project>{d3c8cfed-d6f6-43a8-9bdf-454145d0352f}</Project>
|
||||
<Name>Language</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Logging\Logging.vbproj">
|
||||
<Project>{903b2d7d-3b80-4be9-8713-7447b704e1b0}</Project>
|
||||
<Name>Logging</Name>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Base
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
|
||||
Public Class Helpers
|
||||
Private ReadOnly LogConfig As LogConfig
|
||||
Private ReadOnly Logger As Logger
|
||||
Private ReadOnly FileEx As Filesystem.File
|
||||
Private ReadOnly FileEx As FilesystemEx
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig)
|
||||
LogConfig = pLogConfig
|
||||
Logger = pLogConfig.GetLogger()
|
||||
FileEx = New Filesystem.File(pLogConfig)
|
||||
FileEx = New FilesystemEx(pLogConfig)
|
||||
End Sub
|
||||
|
||||
Public Function GetFileProperties(pFilePath As String, pDateImportedAt As Date) As FileProperties
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Base
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Namespace Modules
|
||||
@@ -6,14 +7,14 @@ Namespace Modules
|
||||
Friend ReadOnly LogConfig As LogConfig
|
||||
Friend ReadOnly Logger As Logger
|
||||
Friend ReadOnly Channel As IEDMIServiceChannel
|
||||
Friend ReadOnly FileEx As Filesystem.File
|
||||
Friend ReadOnly FileEx As FilesystemEx
|
||||
Friend ReadOnly Helpers As Helpers
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig, pChannel As IEDMIServiceChannel)
|
||||
LogConfig = pLogConfig
|
||||
Logger = pLogConfig.GetLogger()
|
||||
Channel = pChannel
|
||||
FileEx = New Filesystem.File(pLogConfig)
|
||||
FileEx = New FilesystemEx(pLogConfig)
|
||||
Helpers = New Helpers(pLogConfig)
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Filesystem
|
||||
|
||||
Namespace Modules.IDB
|
||||
Public Class NewFile
|
||||
|
||||
@@ -12,8 +12,8 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("Digital Data")>
|
||||
<Assembly: AssemblyProduct("EDMIAPI")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyTrademark("1.5.4.0")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2023")>
|
||||
<Assembly: AssemblyTrademark("1.6.1.1")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.5.4.0")>
|
||||
<Assembly: AssemblyFileVersion("1.5.4.0")>
|
||||
<Assembly: AssemblyVersion("1.6.1.1")>
|
||||
<Assembly: AssemblyFileVersion("1.6.1.1")>
|
||||
|
||||
4
EDMIAPI/My Project/Resources.Designer.vb
generated
4
EDMIAPI/My Project/Resources.Designer.vb
generated
@@ -22,7 +22,7 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
@@ -39,7 +39,7 @@ Namespace My.Resources
|
||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||
Get
|
||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("DigitalData.Modules.EDMIAPI.Resources", GetType(Resources).Assembly)
|
||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("DigitalData.Modules.EDMI.API.Resources", GetType(Resources).Assembly)
|
||||
resourceMan = temp
|
||||
End If
|
||||
Return resourceMan
|
||||
|
||||
6
EDMIAPI/My Project/Settings.Designer.vb
generated
6
EDMIAPI/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
@@ -62,8 +62,8 @@ Namespace My
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
|
||||
Friend Module MySettingsProperty
|
||||
|
||||
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")>
|
||||
|
||||
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
|
||||
Friend ReadOnly Property Settings() As Global.DigitalData.Modules.EDMI.API.My.MySettings
|
||||
Get
|
||||
Return Global.DigitalData.Modules.EDMI.API.My.MySettings.Default
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- Dieser Abschnitt definiert die Protokollierungskonfiguration für My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog" />
|
||||
<add name="FileLog"/>
|
||||
<!-- Auskommentierung des nachfolgenden Abschnitts aufheben, um in das Anwendungsereignisprotokoll zu schreiben -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information" />
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter" />
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Auskommentierung des nachfolgenden Abschnitts aufheben und APPLICATION_NAME durch den Namen der Anwendung ersetzen, um in das Anwendungsereignisprotokoll zu schreiben -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
@@ -25,7 +25,7 @@
|
||||
<netTcpBinding>
|
||||
<binding name="NetTcpBinding_IEDMIService" transferMode="Streamed">
|
||||
<security>
|
||||
<transport sslProtocols="None" />
|
||||
<transport sslProtocols="None"/>
|
||||
</security>
|
||||
</binding>
|
||||
</netTcpBinding>
|
||||
@@ -33,7 +33,7 @@
|
||||
<client>
|
||||
<endpoint address="net.tcp://localhost:9000/DigitalData/Services/Main" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService" contract="EDMIServiceReference.IEDMIService" name="NetTcpBinding_IEDMIService">
|
||||
<identity>
|
||||
<userPrincipalName value="Administrator@dd-san01.dd-gan.local.digitaldata.works" />
|
||||
<userPrincipalName value="Administrator@dd-san01.dd-gan.local.digitaldata.works"/>
|
||||
</identity>
|
||||
</endpoint>
|
||||
</client>
|
||||
@@ -41,9 +41,9 @@
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-7.5.0.0" newVersion="7.5.0.0" />
|
||||
<assemblyIdentity name="FirebirdSql.Data.FirebirdClient" publicKeyToken="3750abcc3150b00c" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-7.5.0.0" newVersion="7.5.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -10,8 +10,9 @@
|
||||
<AssemblyName>DigitalData.Modules.Encryption</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -45,8 +46,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
|
||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyCompany("")>
|
||||
<Assembly: AssemblyProduct("Encryption")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2021")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
<Assembly: AssemblyTrademark("1.2.0.0")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' indem Sie "*" wie unten gezeigt eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.1.0.0")>
|
||||
<Assembly: AssemblyFileVersion("1.1.0.0")>
|
||||
<Assembly: AssemblyVersion("1.2.0.0")>
|
||||
<Assembly: AssemblyFileVersion("1.2.0.0")>
|
||||
|
||||
2
Encryption/My Project/Resources.Designer.vb
generated
2
Encryption/My Project/Resources.Designer.vb
generated
@@ -22,7 +22,7 @@ Namespace My.Resources
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0"), _
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
|
||||
2
Encryption/My Project/Settings.Designer.vb
generated
2
Encryption/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -1,18 +0,0 @@
|
||||
Imports System.Runtime.Serialization
|
||||
|
||||
<Serializable>
|
||||
Public Class DocumentObject
|
||||
|
||||
<DataMember(Name:="FileName")>
|
||||
Public ReadOnly FileName As String
|
||||
<DataMember(Name:="ContainerId")>
|
||||
Public ReadOnly ContainerId As String
|
||||
<DataMember(Name:="DocumentId")>
|
||||
Public ReadOnly DocumentId As Int64
|
||||
|
||||
Public Sub New(ContainerId As String, DocumentId As Int64, FileName As String)
|
||||
Me.ContainerId = ContainerId
|
||||
Me.DocumentId = DocumentId
|
||||
Me.FileName = FileName
|
||||
End Sub
|
||||
End Class
|
||||
@@ -1,193 +0,0 @@
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Encryption
|
||||
Imports ProtoBuf
|
||||
|
||||
''' <module>FileContainer</module>
|
||||
''' <version>0.0.0.2</version>
|
||||
''' <date>21.11.2018</date>
|
||||
''' <summary>
|
||||
''' File Container for securely saving files
|
||||
''' </summary>
|
||||
''' <dependencies>
|
||||
''' NLog, >= 4.5.8
|
||||
''' </dependencies>
|
||||
''' <params>
|
||||
''' LogConfig, DigitalData.Module.Logging.LogConfig
|
||||
''' A LogConfig object
|
||||
''' Password, String
|
||||
''' The Password to Encrypt
|
||||
''' Path, String
|
||||
''' The Path to save/load the container
|
||||
''' </params>
|
||||
''' <example>
|
||||
''' 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")
|
||||
''' </example>
|
||||
Public Class FileContainer
|
||||
Private _crypto As Encryption.Encryption
|
||||
Private _compression As Compression
|
||||
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 ReadOnly Property ContainerId 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)
|
||||
_logger = LogConfig.GetLogger()
|
||||
_crypto = New Encryption.Encryption(LogConfig, Password)
|
||||
_compression = New Compression(LogConfig)
|
||||
_inner = New FileContainerInner()
|
||||
End Sub
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Password As String, Path As String)
|
||||
MyClass.New(LogConfig, Password)
|
||||
_path = Path
|
||||
End Sub
|
||||
|
||||
Public Sub SetFile(Contents As Byte(), FileName As String)
|
||||
_inner.Contents = Contents
|
||||
_inner.UpdatedAt = Date.Now
|
||||
_inner.FileName = FileName
|
||||
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
|
||||
@@ -1,23 +0,0 @@
|
||||
Imports ProtoBuf
|
||||
|
||||
<Serializable>
|
||||
<ProtoContract>
|
||||
Public Class FileContainerInner
|
||||
<ProtoMember(1)>
|
||||
Public FileId As String
|
||||
<ProtoMember(2)>
|
||||
Public Contents As Byte()
|
||||
<ProtoMember(3)>
|
||||
Public CreatedAt As DateTime
|
||||
<ProtoMember(4)>
|
||||
Public UpdatedAt As DateTime
|
||||
<ProtoMember(5)>
|
||||
Public FileName As String
|
||||
|
||||
Public Sub New()
|
||||
FileId = Guid.NewGuid().ToString
|
||||
CreatedAt = Date.Now
|
||||
UpdatedAt = Date.Now
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
@@ -1,132 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{991D0231-4623-496D-8BD0-9CA906029CBC}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>DigitalData.Modules.Filesystem</RootNamespace>
|
||||
<AssemblyName>DigitalData.Modules.Filesystem</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Windows</MyType>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DocumentationFile>DigitalData.Modules.Filesystem.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DocumentationFile>DigitalData.Modules.Filesystem.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionExplicit>On</OptionExplicit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionCompare>Binary</OptionCompare>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionStrict>Off</OptionStrict>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionInfer>On</OptionInfer>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="protobuf-net, Version=2.4.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\protobuf-net.2.4.0\lib\net40\protobuf-net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Import Include="Microsoft.VisualBasic" />
|
||||
<Import Include="System" />
|
||||
<Import Include="System.Collections" />
|
||||
<Import Include="System.Collections.Generic" />
|
||||
<Import Include="System.Data" />
|
||||
<Import Include="System.Diagnostics" />
|
||||
<Import Include="System.Linq" />
|
||||
<Import Include="System.Xml.Linq" />
|
||||
<Import Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FileContainer\DocumentObject.vb" />
|
||||
<Compile Include="FileContainer\FileContainer.vb" />
|
||||
<Compile Include="File.vb" />
|
||||
<Compile Include="FileContainer\FileContainerInner.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcher.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcherFilters.vb" />
|
||||
<Compile Include="FileWatcher\FileWatcherProperties.vb" />
|
||||
<Compile Include="My Project\AssemblyInfo.vb" />
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Settings.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="My Project\Resources.resx">
|
||||
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="My Project\Application.myapp">
|
||||
<Generator>MyApplicationCodeGenerator</Generator>
|
||||
<LastGenOutput>Application.Designer.vb</LastGenOutput>
|
||||
</None>
|
||||
<None Include="My Project\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<CustomToolNamespace>My</CustomToolNamespace>
|
||||
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Encryption\Encryption.vbproj">
|
||||
<Project>{8a8f20fc-c46e-41ac-bee7-218366cfff99}</Project>
|
||||
<Name>Encryption</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Logging\Logging.vbproj">
|
||||
<Project>{903b2d7d-3b80-4be9-8713-7447b704e1b0}</Project>
|
||||
<Name>Logging</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||
</Project>
|
||||
13
Filesystem/My Project/Application.Designer.vb
generated
13
Filesystem/My Project/Application.Designer.vb
generated
@@ -1,13 +0,0 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' Dieser Code wurde von einem Tool generiert.
|
||||
' Laufzeitversion:4.0.30319.42000
|
||||
'
|
||||
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
' der Code erneut generiert wird.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
Imports System
|
||||
Imports System.Reflection
|
||||
Imports System.Runtime.InteropServices
|
||||
|
||||
' Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
' die einer Assembly zugeordnet sind.
|
||||
|
||||
' Werte der Assemblyattribute überprüfen
|
||||
|
||||
<Assembly: AssemblyTitle("Modules.Filesystem")>
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("Digital Data")>
|
||||
<Assembly: AssemblyProduct("Modules.Filesystem")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyTrademark("1.3.1.1")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
'Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird.
|
||||
<Assembly: Guid("2787495c-e65f-4730-be0c-af87bede4b11")>
|
||||
|
||||
' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
'
|
||||
' Hauptversion
|
||||
' Nebenversion
|
||||
' Buildnummer
|
||||
' Revision
|
||||
'
|
||||
' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.3.1.1")>
|
||||
<Assembly: AssemblyFileVersion("1.3.1.1")>
|
||||
63
Filesystem/My Project/Resources.Designer.vb
generated
63
Filesystem/My Project/Resources.Designer.vb
generated
@@ -1,63 +0,0 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' Dieser Code wurde von einem Tool generiert.
|
||||
' Laufzeitversion:4.0.30319.42000
|
||||
'
|
||||
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
' der Code erneut generiert wird.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
Imports System
|
||||
|
||||
Namespace My.Resources
|
||||
|
||||
'Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||
'-Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||
'Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||
'mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||
'''<summary>
|
||||
''' Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
Friend Module Resources
|
||||
|
||||
Private resourceMan As Global.System.Resources.ResourceManager
|
||||
|
||||
Private resourceCulture As Global.System.Globalization.CultureInfo
|
||||
|
||||
'''<summary>
|
||||
''' Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||
Get
|
||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("DigitalData.Modules.Filesystem.Resources", GetType(Resources).Assembly)
|
||||
resourceMan = temp
|
||||
End If
|
||||
Return resourceMan
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||
''' Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
||||
Get
|
||||
Return resourceCulture
|
||||
End Get
|
||||
Set
|
||||
resourceCulture = value
|
||||
End Set
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
73
Filesystem/My Project/Settings.Designer.vb
generated
73
Filesystem/My Project/Settings.Designer.vb
generated
@@ -1,73 +0,0 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' Dieser Code wurde von einem Tool generiert.
|
||||
' Laufzeitversion:4.0.30319.42000
|
||||
'
|
||||
' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||
' der Code erneut generiert wird.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
|
||||
|
||||
#Region "Automatische My.Settings-Speicherfunktion"
|
||||
#If _MyType = "WindowsForms" Then
|
||||
Private Shared addedHandler As Boolean
|
||||
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
#End If
|
||||
#End Region
|
||||
|
||||
Public Shared ReadOnly Property [Default]() As MySettings
|
||||
Get
|
||||
|
||||
#If _MyType = "WindowsForms" Then
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
#End If
|
||||
Return defaultInstance
|
||||
End Get
|
||||
End Property
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
Namespace My
|
||||
|
||||
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
|
||||
Friend Module MySettingsProperty
|
||||
|
||||
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
|
||||
Friend ReadOnly Property Settings() As Global.DigitalData.Modules.Filesystem.My.MySettings
|
||||
Get
|
||||
Return Global.DigitalData.Modules.Filesystem.My.MySettings.Default
|
||||
End Get
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="protobuf-net" version="2.4.0" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -37,23 +37,22 @@ Public Class ActiveDirectoryInterface
|
||||
_logger.Info("Using RootPath {0}", _rootPath)
|
||||
End Sub
|
||||
|
||||
Public Function SyncUsersForGroup(GroupName As String, Firebird As Firebird, MSSQL As MSSQLServer) As List(Of ADUser)
|
||||
Public Function SyncUsersForGroup(GroupName As String, MSSQL As MSSQLServer) As List(Of ADUser)
|
||||
Try
|
||||
Return SyncUsersForGroup(GroupName, New List(Of AttributeMapping), Firebird, MSSQL)
|
||||
Return SyncUsersForGroup(GroupName, New List(Of AttributeMapping), MSSQL)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function SyncUsersForGroup(GroupName As String, AttributeMappings As List(Of AttributeMapping), Firebird As Firebird, MSSQL As MSSQLServer, Optional Filter As String = DEFAULT_USER_FILTER) As List(Of ADUser)
|
||||
Public Function SyncUsersForGroup(GroupName As String, AttributeMappings As List(Of AttributeMapping), MSSQL As MSSQLServer, Optional Filter As String = DEFAULT_USER_FILTER) As List(Of ADUser)
|
||||
Dim oUsers As New List(Of ADUser)
|
||||
Dim oSyncedUsers As New List(Of ADUser)
|
||||
Dim oGroupId As Int64 = Nothing
|
||||
|
||||
Dim oFirebirdSync As New SyncUsers.SyncUsersFirebird(_logConfig, Firebird)
|
||||
Dim oSQLSync As New SyncUsers.SyncUsersMSSQL(_logConfig, MSSQL)
|
||||
Dim oSyncedUsersFirebird, oSyncedUsersMSSQL As List(Of ADUser)
|
||||
Dim oSyncedUsersMSSQL As List(Of ADUser)
|
||||
|
||||
Try
|
||||
_logger.Debug("Fetching users from ActiveDirectory")
|
||||
@@ -64,16 +63,6 @@ Public Class ActiveDirectoryInterface
|
||||
Return Nothing
|
||||
End Try
|
||||
|
||||
' Do the actual sync into firebird
|
||||
If Firebird IsNot Nothing Then
|
||||
oSyncedUsersFirebird = oFirebirdSync.SyncUsers(GroupName, oUsers, AttributeMappings)
|
||||
If oSyncedUsersFirebird.Count > 0 Then
|
||||
_logger.Debug("Synced {0} users to Firebird", oSyncedUsersFirebird.Count)
|
||||
End If
|
||||
Else
|
||||
_logger.Debug("SyncUsersForGroup: _firebird is nothing. ")
|
||||
End If
|
||||
|
||||
' Do the actual sync into MSSQL
|
||||
If MSSQL IsNot Nothing Then
|
||||
oSyncedUsersMSSQL = oSQLSync.SyncUsers(GroupName, oUsers, AttributeMappings)
|
||||
@@ -193,6 +182,8 @@ Public Class ActiveDirectoryInterface
|
||||
.FirebirdSyskey = oMap.FirebirdSyskey,
|
||||
.MSSQLColumn = oMap.MSSQLColumn
|
||||
})
|
||||
Else
|
||||
_logger.Debug("Attribute [{0}] is empty.", oMap.AttributeName)
|
||||
End If
|
||||
Next
|
||||
Else
|
||||
|
||||
@@ -8,6 +8,7 @@ Public Class ADUser
|
||||
Public Property GivenName As String
|
||||
Public Property Middlename As String
|
||||
Public Property Email As String
|
||||
Public Property Language As String
|
||||
|
||||
Public CustomAttributes As List(Of CustomAttribute)
|
||||
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Interfaces
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Namespace SyncUsers
|
||||
Public Class SyncUsersFirebird
|
||||
Implements ISyncUsers
|
||||
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _firebird As Database.Firebird
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Database.Firebird)
|
||||
_logConfig = LogConfig
|
||||
_logger = LogConfig.GetLogger()
|
||||
_firebird = Firebird
|
||||
End Sub
|
||||
|
||||
Public Function SyncUsers(GroupName As String, Users As List(Of ADUser), PropertyMapping As List(Of AttributeMapping)) As List(Of ADUser) Implements ISyncUsers.SyncUsers
|
||||
Dim oGroupId As Integer
|
||||
Dim oSyncedUsers As New List(Of ADUser)
|
||||
|
||||
Try
|
||||
_logger.Debug("Getting group Id for group [{0}]", GroupName)
|
||||
oGroupId = GetGroupId(GroupName)
|
||||
|
||||
If oGroupId = 0 Then
|
||||
_logger.Debug("Group [{0}] does not exist in database or is not enabled for sync.", GroupName)
|
||||
Return oSyncedUsers
|
||||
End If
|
||||
|
||||
_logger.Debug("Using group Id [{0}]", oGroupId)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Return oSyncedUsers
|
||||
End Try
|
||||
|
||||
For Each oUser In Users
|
||||
Dim oUserId As Int64
|
||||
Dim oUserExists As Boolean = False
|
||||
|
||||
' Check if user already exists
|
||||
Try
|
||||
_logger.Debug("Checking if user [{0}] exists", oUser)
|
||||
oUserId = GetUserId(oUser.samAccountName)
|
||||
oUserExists = Not IsNothing(oUserId)
|
||||
_logger.Debug("User [{0}] exists in database: ", oUser, oUserExists)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Could not get UserId for user. Skipping")
|
||||
Continue For
|
||||
End Try
|
||||
|
||||
' I user does not exist, create a new user
|
||||
Try
|
||||
If Not oUserExists Then
|
||||
_logger.Debug("Creating new user for [{0}]", oUser)
|
||||
oUserId = CreateUser(oUser)
|
||||
_logger.Debug("User created with Id [{0}]", oUserId)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Could not create user. Skipping")
|
||||
Continue For
|
||||
End Try
|
||||
|
||||
' Add the user to group
|
||||
Try
|
||||
AddUserToGroup(oUserId, oGroupId)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Could not add user to group. Skipping")
|
||||
Continue For
|
||||
End Try
|
||||
|
||||
oSyncedUsers.Add(oUser)
|
||||
Next
|
||||
|
||||
Return oSyncedUsers
|
||||
End Function
|
||||
|
||||
Private Function AddUserToGroup(UserId As Integer, GroupId As Integer) As Boolean Implements ISyncUsers.AddUserToGroup
|
||||
Try
|
||||
Dim oSQL = $"SELECT FNICM_RADM_NEW_USER2GROUP({UserId}, {GroupId}, 'AD-Sync') from RDB$DATABASE"
|
||||
Dim oRecordId = _firebird.GetScalarValue(oSQL)
|
||||
|
||||
If IsDBNull(oRecordId) Then
|
||||
_logger.Warn("UserId {0} - GroupId {1} relation already exists.", UserId, GroupId)
|
||||
Return False
|
||||
End If
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
Private Function GetGroupId(GroupName As String) As Integer Implements ISyncUsers.GetGroupId
|
||||
Try
|
||||
Dim oSQL As String = $"SELECT FNICM_GET_RECORD4SYSKEY('{GroupName}','002-NAME') from RDB$DATABASE"
|
||||
Dim oGroupId = _firebird.GetScalarValue(oSQL)
|
||||
|
||||
If IsDBNull(oGroupId) OrElse oGroupId = 0 Then
|
||||
_logger.Debug("Group {0} not found in database", GroupName)
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
Return oGroupId
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
Private Function GetUserId(UserName As String) As Integer Implements ISyncUsers.GetUserId
|
||||
Try
|
||||
Dim oSQL As String = $"SELECT FNICM_GET_RECORD4SYSKEY('{UserName}','001-USRNAME') from RDB$DATABASE"
|
||||
Dim oResult = _firebird.GetScalarValue(oSQL)
|
||||
|
||||
If IsDBNull(oResult) Then
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
Return oResult
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
Private Function CreateUser(User As ADUser) As Integer Implements ISyncUsers.CreateUser
|
||||
Try
|
||||
Dim oSQL = $"SELECT FNICM_RADM_NEW_USER('{User?.GivenName}', '{User?.Surname}', '{User?.samAccountName}', 'AD-Sync') from RDB$DATABASE"
|
||||
Dim oUserId As Integer = _firebird.GetScalarValue(oSQL)
|
||||
|
||||
Return oUserId
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Sub AddCustomAttributesToUser(User As ADUser, UserId As Integer) Implements ISyncUsers.AddCustomAttributesToUser
|
||||
Throw New NotImplementedException()
|
||||
End Sub
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -1,6 +1,6 @@
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Language
|
||||
Imports DigitalData.Modules.Base
|
||||
|
||||
Namespace SyncUsers
|
||||
Public Class SyncUsersMSSQL
|
||||
@@ -42,7 +42,7 @@ Namespace SyncUsers
|
||||
End Try
|
||||
|
||||
For Each oUser In Users
|
||||
Dim oUserId As Int64
|
||||
Dim oUserId As Long
|
||||
Dim oUserExists As Boolean
|
||||
|
||||
' Check if user already exists
|
||||
@@ -68,7 +68,7 @@ Namespace SyncUsers
|
||||
_logger.Debug("Creating new user for [{0}]", oUser)
|
||||
oUserId = CreateUser(oUser)
|
||||
_logger.Debug("User created with Id [{0}]", oUserId)
|
||||
_logger.Info("Added new User [{0}]", oUser.samAccountName)
|
||||
_logger.Info("Added new User [{0}]", oUser)
|
||||
|
||||
oCreatedUsers.Add(oUser)
|
||||
Else
|
||||
@@ -76,7 +76,7 @@ Namespace SyncUsers
|
||||
oUserId = UpdateUser(oUser)
|
||||
If oUserId <> 0 Then
|
||||
_logger.Debug("User created with Id [{0}]", oUserId)
|
||||
_logger.Info("Updated User [{0}]", oUser.samAccountName)
|
||||
_logger.Info("Updated User [{0}]", oUser)
|
||||
|
||||
oUpdatedUsers.Add(oUser)
|
||||
End If
|
||||
@@ -84,7 +84,7 @@ Namespace SyncUsers
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Could Not create/update user [{0}]. Skipping.", oUser.samAccountName)
|
||||
_logger.Warn("Could Not create/update user [{0}]. Skipping.", oUser)
|
||||
Continue For
|
||||
End Try
|
||||
|
||||
@@ -99,7 +99,7 @@ Namespace SyncUsers
|
||||
' Add the user to group
|
||||
Try
|
||||
If AddUserToGroup(oUserId, oGroupId) Then
|
||||
_logger.Info("User [{0}] added to group [{1}]", oUser.samAccountName, GroupName)
|
||||
_logger.Info("User [{0}] added to group [{1}]", oUser, GroupName)
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
@@ -175,7 +175,8 @@ Namespace SyncUsers
|
||||
Dim oSQL As String = $"SELECT GUID FROM TBDD_USER WHERE UPPER(USERNAME) = UPPER('{UserName}')"
|
||||
Dim oUserId = _mssql.GetScalarValue(oSQL)
|
||||
|
||||
If IsDBNull(oUserId) OrElse oUserId = 0 Then
|
||||
If IsDBNull(oUserId) OrElse IsNothing(oUserId) OrElse oUserId = 0 Then
|
||||
_logger.Debug("User [{0}] does not exist", UserName)
|
||||
Return 0
|
||||
End If
|
||||
|
||||
@@ -194,9 +195,15 @@ Namespace SyncUsers
|
||||
End If
|
||||
|
||||
Dim oUserId As Integer = GetUserId(User.samAccountName)
|
||||
_logger.Debug("UserId of User [{0}] is [{1}]", User, oUserId)
|
||||
|
||||
If oUserId = 0 Then
|
||||
Dim oSQL As String = $"INSERT INTO TBDD_USER (PRENAME, NAME, USERNAME, EMAIL, ADDED_WHO) VALUES ('{User?.GivenName}', '{User?.Surname?.Replace("'", "''")}', UPPER('{User?.samAccountName?.Replace("'", "''")}'), '{User?.Email?.Replace("'", "''")}', '{ADDED_WHO}')"
|
||||
Dim oPrename = User.GivenName.EscapeForSQL()
|
||||
Dim oSurname = User.Surname.EscapeForSQL()
|
||||
Dim oUsername = User.samAccountName.EscapeForSQL()
|
||||
Dim oEmail = User.Email.EscapeForSQL()
|
||||
|
||||
Dim oSQL As String = $"INSERT INTO TBDD_USER (PRENAME, NAME, USERNAME, EMAIL, ADDED_WHO) VALUES ('{oPrename}', '{oSurname}', UPPER('{oUsername}'), '{oEmail}', '{ADDED_WHO}')"
|
||||
Dim oResult = _mssql.ExecuteNonQuery(oSQL)
|
||||
|
||||
If oResult = True Then
|
||||
@@ -230,11 +237,11 @@ Namespace SyncUsers
|
||||
Dim oUserId As Integer = GetUserId(User.samAccountName)
|
||||
If Not IsNothing(oUserId) Then
|
||||
If oUserId > 0 Then
|
||||
Dim oGivenName As String = EscapeQuotes(User.GivenName)
|
||||
Dim oSurname As String = EscapeQuotes(User.Surname)
|
||||
Dim oEmail As String = EscapeQuotes(User.Email)
|
||||
Dim oPrename = User.GivenName.EscapeForSQL()
|
||||
Dim oSurname = User.Surname.EscapeForSQL()
|
||||
Dim oEmail = User.Email.EscapeForSQL()
|
||||
|
||||
Dim oSQL As String = $"UPDATE TBDD_USER SET PRENAME = '{oGivenName}', NAME = '{oSurname}', EMAIL = '{oEmail}', CHANGED_WHO = '{ADDED_WHO}' WHERE GUID = {oUserId}"
|
||||
Dim oSQL As String = $"UPDATE TBDD_USER SET PRENAME = '{oPrename}', NAME = '{oSurname}', EMAIL = '{oEmail}', CHANGED_WHO = '{ADDED_WHO}' WHERE GUID = {oUserId}"
|
||||
Dim oResult = _mssql.ExecuteNonQuery(oSQL)
|
||||
|
||||
If oResult = True Then
|
||||
@@ -256,11 +263,6 @@ Namespace SyncUsers
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function EscapeQuotes(pString As String)
|
||||
Dim oString = Utils.NotNull(pString, String.Empty)
|
||||
Return oString.Replace("'", "''")
|
||||
End Function
|
||||
|
||||
Public Sub AddCustomAttributesToUser(User As ADUser, UserId As Integer) Implements ISyncUsers.AddCustomAttributesToUser
|
||||
Dim oCustomAttributes = User.CustomAttributes
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ Public Class GraphQLInterface
|
||||
Public Property Proxy As WebProxy
|
||||
Public Property Credentials As NetworkCredential
|
||||
|
||||
Public Event LogRequested As EventHandler(Of String)
|
||||
|
||||
Public ReadOnly Property Certificate As X509Certificate2
|
||||
Get
|
||||
Return _certificate
|
||||
End Get
|
||||
End Property
|
||||
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, BaseUrl As String, Email As String, Password As String, CertificateFingerprint As String)
|
||||
Try
|
||||
_logConfig = LogConfig
|
||||
@@ -46,6 +55,10 @@ Public Class GraphQLInterface
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
If oCertificate IsNot Nothing Then
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
|
||||
@@ -103,10 +116,18 @@ Public Class GraphQLInterface
|
||||
|
||||
Public Function Login() As HttpWebResponse
|
||||
Try
|
||||
RaiseEvent LogRequested(Me, $"Login started with user: [{_userEmail}]")
|
||||
|
||||
Dim oLoginData As New LoginData() With {.email = _userEmail, .token = _userPassword}
|
||||
Dim oBytes As Byte() = ToBytes(JsonConvert.SerializeObject(oLoginData))
|
||||
Dim oRequest As HttpWebRequest = GetRequest("/login", oBytes)
|
||||
|
||||
RaiseEvent LogRequested(Me, $"Sending HTTP request to GraphQL")
|
||||
RaiseEvent LogRequested(Me, $"Request Host: [{oRequest.Host}]")
|
||||
RaiseEvent LogRequested(Me, $"Request Address: [{oRequest.Address}]")
|
||||
RaiseEvent LogRequested(Me, $"Request Method: [{oRequest.Method}]")
|
||||
RaiseEvent LogRequested(Me, $"Request ContentType: [{oRequest.ContentType}]")
|
||||
|
||||
Using oStream = oRequest.GetRequestStream()
|
||||
oStream.Write(oBytes, 0, oBytes.Length)
|
||||
End Using
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.7.15\lib\net45\NLog.dll</HintPath>
|
||||
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
@@ -86,7 +86,6 @@
|
||||
<Compile Include="ActiveDirectoryInterface\ActiveDirectoryUser.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\AttributeMap.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\ISyncUsers.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\SyncUsers.Firebird.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\SyncUsers.MSSQL.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\UserEqualityComparer.vb" />
|
||||
<Compile Include="ActiveDirectoryInterface\UserPrincipalEx.vb" />
|
||||
@@ -111,6 +110,8 @@
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="ZUGFeRDInterface\PDFConverter.vb" />
|
||||
<Compile Include="ZUGFeRDInterface\Validator.vb" />
|
||||
<Compile Include="ZUGFeRDInterface\Version1.0\CrossIndustryDocumentType.vb" />
|
||||
<Compile Include="ZUGFeRDInterface.vb" />
|
||||
<Compile Include="ZUGFeRDInterface\FileGroups.vb" />
|
||||
@@ -154,14 +155,14 @@
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Base\Base.vbproj">
|
||||
<Project>{6ea0c51f-c2b1-4462-8198-3de0b32b74f8}</Project>
|
||||
<Name>Base</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Database\Database.vbproj">
|
||||
<Project>{eaf0ea75-5fa7-485d-89c7-b2d843b03a96}</Project>
|
||||
<Name>Database</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Language\Language.vbproj">
|
||||
<Project>{d3c8cfed-d6f6-43a8-9bdf-454145d0352f}</Project>
|
||||
<Name>Language</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Logging\Logging.vbproj">
|
||||
<Project>{903b2d7d-3b80-4be9-8713-7447b704e1b0}</Project>
|
||||
<Name>Logging</Name>
|
||||
|
||||
@@ -12,8 +12,8 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("Digital Data")>
|
||||
<Assembly: AssemblyProduct("Modules.Interfaces")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2022")>
|
||||
<Assembly: AssemblyTrademark("1.7.4.0")>
|
||||
<Assembly: AssemblyCopyright("Copyright © 2024")>
|
||||
<Assembly: AssemblyTrademark("1.12.1.0")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.7.4.0")>
|
||||
<Assembly: AssemblyFileVersion("1.7.4.0")>
|
||||
<Assembly: AssemblyVersion("1.12.1.0")>
|
||||
<Assembly: AssemblyFileVersion("1.12.1.0")>
|
||||
|
||||
2
Interfaces/My Project/Settings.Designer.vb
generated
2
Interfaces/My Project/Settings.Designer.vb
generated
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
@@ -1,56 +1,150 @@
|
||||
Imports System.IO
|
||||
Imports System.Collections.Generic
|
||||
Imports System.IO
|
||||
Imports System.Reflection.Emit
|
||||
Imports System.Xml
|
||||
Imports System.Xml.Serialization
|
||||
Imports System.Xml.XPath
|
||||
Imports System.Xml.Xsl
|
||||
Imports DigitalData.Modules.Interfaces.Exceptions
|
||||
Imports DigitalData.Modules.Interfaces.ZUGFeRD
|
||||
Imports DigitalData.Modules.Interfaces.ZUGFeRDInterface
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
Public Class ZUGFeRDInterface
|
||||
Private _logConfig As LogConfig
|
||||
Private _logger As Logger
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _Options As ZugferdOptions
|
||||
Private ReadOnly _Validator As Validator
|
||||
|
||||
' These constants define the specification markers for the different
|
||||
' zugferd document schema versions. These markers need to be used to
|
||||
' define the property map in the database (column SPECIFICATION).
|
||||
Public Const ZUGFERD_SPEC_DEFAULT = "DEFAULT"
|
||||
Public Const ZUGFERD_SPEC_10 = "ZUGFERD_10"
|
||||
Public Const ZUGFERD_SPEC_2x = "ZUGFERD_2x"
|
||||
|
||||
Private ReadOnly ValidFilenames As New List(Of String) From {
|
||||
PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_FR.ToUpper
|
||||
}
|
||||
|
||||
Private AllowedFilenames As New List(Of String)
|
||||
|
||||
Public Enum ErrorType
|
||||
NoValidFile
|
||||
NoZugferd
|
||||
NoValidZugferd
|
||||
MissingProperties
|
||||
UnsupportedFormat
|
||||
FileTooBig
|
||||
UnknownError
|
||||
End Enum
|
||||
|
||||
Public ReadOnly Property FileGroup As FileGroups
|
||||
Public ReadOnly Property PropertyValues As PropertyValues
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, GDPictureKey As String)
|
||||
_logConfig = LogConfig
|
||||
Public Class ZugferdOptions
|
||||
Public Property AllowFacturX_Filename As Boolean = True
|
||||
Public Property AllowXRechnung_Filename As Boolean = True
|
||||
Public Property AllowZugferd_1_0_Schema As Boolean = True
|
||||
Public Property AllowZugferd_2_x_Schema As Boolean = True
|
||||
End Class
|
||||
|
||||
Public Class ZugferdResult
|
||||
Public Property DataFileName As String
|
||||
Public Property XElementObject As XElement
|
||||
Public Property SchemaObject As Object
|
||||
Public Property Specification As String
|
||||
Public Property ValidationErrors As New List(Of ZugferdValidationError)
|
||||
End Class
|
||||
|
||||
Public Class ZugferdValidationError
|
||||
Public ElementName As String
|
||||
Public ElementValue As String
|
||||
Public ErrorMessage As String
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' Create a new instance of ZUGFeRDInterface
|
||||
''' </summary>
|
||||
''' <param name="pLogConfig">A LogConfig object</param>
|
||||
''' <param name="pGDPictureKey">A valid GDPicture License</param>
|
||||
''' <param name="pOptions">Optional parameters to control various settings</param>
|
||||
Public Sub New(pLogConfig As LogConfig, pGDPictureKey As String, Optional pOptions As ZugferdOptions = Nothing)
|
||||
_logConfig = pLogConfig
|
||||
_logger = _logConfig.GetLogger()
|
||||
_Validator = New Validator(_logConfig)
|
||||
|
||||
If pOptions Is Nothing Then
|
||||
_Options = New ZugferdOptions()
|
||||
Else
|
||||
_Options = pOptions
|
||||
End If
|
||||
|
||||
ApplyFilenameOptions(_Options)
|
||||
|
||||
FileGroup = New FileGroups(_logConfig)
|
||||
PropertyValues = New PropertyValues(_logConfig)
|
||||
|
||||
Try
|
||||
Dim oLicenseManager As New LicenseManager
|
||||
oLicenseManager.RegisterKEY(GDPictureKey)
|
||||
oLicenseManager.RegisterKEY(pGDPictureKey)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("GDPicture License could not be registered!")
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub ApplyFilenameOptions(pOptions As ZugferdOptions)
|
||||
Dim oAllowedFilenames As List(Of String) = ValidFilenames
|
||||
|
||||
If pOptions.AllowFacturX_Filename = False Then
|
||||
oAllowedFilenames = oAllowedFilenames.
|
||||
Except(New List(Of String) From {PDFEmbeds.FACTUR_X_XML_FILENAME_FR}).ToList()
|
||||
End If
|
||||
|
||||
If pOptions.AllowXRechnung_Filename = False Then
|
||||
oAllowedFilenames = oAllowedFilenames.
|
||||
Except(New List(Of String) From {PDFEmbeds.FACTUR_X_XML_FILENAME_DE}).ToList()
|
||||
End If
|
||||
|
||||
AllowedFilenames = oAllowedFilenames
|
||||
End Sub
|
||||
|
||||
Public Function FilterPropertyMap(pPropertyMap As Dictionary(Of String, XmlItemProperty), pSpecification As String) As Dictionary(Of String, XmlItemProperty)
|
||||
_logger.Debug("Filtering Property map for Specification [{0}]", pSpecification)
|
||||
|
||||
If pSpecification = ZUGFERD_SPEC_10 Then
|
||||
_logger.Debug("Special Case [{0}], including [{1}]", ZUGFERD_SPEC_10, ZUGFERD_SPEC_DEFAULT)
|
||||
Return pPropertyMap.
|
||||
Where(Function(kv) kv.Value.Specification = pSpecification Or kv.Value.Specification = ZUGFERD_SPEC_DEFAULT).
|
||||
ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value)
|
||||
Else
|
||||
_logger.Debug("Using Specification [{0}]", pSpecification)
|
||||
Return pPropertyMap.
|
||||
Where(Function(kv) kv.Value.Specification = pSpecification).
|
||||
ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value)
|
||||
End If
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="Path"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Object
|
||||
Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path)
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As ZugferdResult
|
||||
Dim oResult = ValidateZUGFeRDFileWithGDPicture(Path)
|
||||
oResult = ValidateZUGFeRDDocument(oResult)
|
||||
|
||||
If IsNothing(oXmlDocument) Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
|
||||
If oResult.ValidationErrors.Any() Then
|
||||
Throw New ValidationException() With {
|
||||
.ValidationErrors = oResult.ValidationErrors
|
||||
}
|
||||
End If
|
||||
|
||||
Return SerializeZUGFeRDDocument(oXmlDocument)
|
||||
Return SerializeZUGFeRDDocument(oResult)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
@@ -58,29 +152,36 @@ Public Class ZUGFeRDInterface
|
||||
''' </summary>
|
||||
''' <param name="Stream"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Object
|
||||
Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream)
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As ZugferdResult
|
||||
Dim oResult = ValidateZUGFeRDFileWithGDPicture(Stream)
|
||||
oResult = ValidateZUGFeRDDocument(oResult)
|
||||
|
||||
If IsNothing(oXmlDocument) Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
|
||||
If oResult.ValidationErrors.Any() Then
|
||||
_logger.Info("Validation found [{0}] errors", oResult.ValidationErrors.Count)
|
||||
oResult.ValidationErrors.ForEach(
|
||||
Sub(e) _logger.Info("Field [{0}] with value [{1}] has error: [{2}]", e.ElementName, e.ElementValue, e.ErrorMessage)
|
||||
)
|
||||
|
||||
Throw New ValidationException() With {
|
||||
.ValidationErrors = oResult.ValidationErrors
|
||||
}
|
||||
End If
|
||||
|
||||
Return SerializeZUGFeRDDocument(oXmlDocument)
|
||||
Return SerializeZUGFeRDDocument(oResult)
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="Stream"></param>
|
||||
''' <param name="pStream"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(Stream As Stream) As XPathDocument
|
||||
''' <returns>The embedded xml data as an XPath document</returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As ZugferdResult
|
||||
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
|
||||
Dim oAllowedExtensions = New List(Of String) From {"xml"}
|
||||
|
||||
Try
|
||||
Dim oFiles = oEmbedExtractor.Extract(Stream, oAllowedExtensions)
|
||||
' Extract XML attachments only!
|
||||
Dim oFiles = oEmbedExtractor.Extract(pStream, New List(Of String) From {"xml"})
|
||||
|
||||
' Attachments are in this case the files that are embedded into a pdf file,
|
||||
' like for example the zugferd-invoice.xml file
|
||||
@@ -92,17 +193,24 @@ Public Class ZUGFeRDInterface
|
||||
Throw ex
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Error while validating ZUGFeRD file with GDPicture")
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(Path As String) As XPathDocument
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="pPath"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns>The embedded xml data as an XPath document</returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As ZugferdResult
|
||||
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
|
||||
Dim oAllowedExtensions = New List(Of String) From {"xml"}
|
||||
|
||||
Try
|
||||
Dim oFiles = oEmbedExtractor.Extract(Path, oAllowedExtensions)
|
||||
' Extract XML attachments only!
|
||||
Dim oFiles = oEmbedExtractor.Extract(pPath, New List(Of String) From {"xml"})
|
||||
|
||||
' Attachments are in this case the files that are embedded into a pdf file,
|
||||
' like for example the zugferd-invoice.xml file
|
||||
@@ -114,43 +222,48 @@ Public Class ZUGFeRDInterface
|
||||
Throw ex
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Error while validating ZUGFeRD file with GDPicture")
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function HandleEmbeddedFiles(Results As List(Of PDFEmbeds.EmbeddedFile)) As XPathDocument
|
||||
Dim oXmlDocument As XPathDocument
|
||||
|
||||
If Results Is Nothing Then
|
||||
Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As ZugferdResult
|
||||
If pResults Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die Attachments nicht gelesen werden konnten.")
|
||||
End If
|
||||
|
||||
If Results.Count = 0 Then
|
||||
If pResults.Count = 0 Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil sie keine Attachments enthält.")
|
||||
End If
|
||||
|
||||
Dim oValidFilenames As New List(Of String) From {
|
||||
PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_FR.ToUpper
|
||||
}
|
||||
|
||||
' Find the first file which filename matches the valid filenames for embedded invoice files
|
||||
Dim oFoundResult As PDFEmbeds.EmbeddedFile = Results.
|
||||
Where(Function(result) oValidFilenames.Contains(result.FileName.ToUpper)).
|
||||
Dim oValidResult As PDFEmbeds.EmbeddedFile = pResults.
|
||||
Where(Function(f) ValidFilenames.Contains(f.FileName.ToUpper)).
|
||||
FirstOrDefault()
|
||||
|
||||
If oFoundResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die zugferd-invoice.xml nicht gefunden wurde.")
|
||||
If oValidResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil keine entsprechende XML-Datei gefunden wurde.")
|
||||
End If
|
||||
|
||||
' Search the embedded files for the ones which are allowed as per the configuration.
|
||||
' The config might say, allow ZUGFeRD but not Factur-X.
|
||||
Dim oAllowedResult As PDFEmbeds.EmbeddedFile = pResults.
|
||||
Where(Function(f) AllowedFilenames.Contains(f.FileName.ToUpper)).
|
||||
FirstOrDefault()
|
||||
|
||||
If oAllowedResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Datei ist eine ZUGFeRD Datei, aber das Format wird nicht unterstützt.", oAllowedResult.FileName)
|
||||
End If
|
||||
|
||||
Try
|
||||
Using oStream As New MemoryStream(oFoundResult.FileContents)
|
||||
oXmlDocument = New XPathDocument(oStream)
|
||||
Using oStream As New MemoryStream(oAllowedResult.FileContents)
|
||||
Return New ZugferdResult With {
|
||||
.DataFileName = oAllowedResult.FileName,
|
||||
.XElementObject = XElement.Load(oStream)
|
||||
}
|
||||
End Using
|
||||
|
||||
Return oXmlDocument
|
||||
Catch ex As ZUGFeRDExecption
|
||||
' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code.
|
||||
' It also produces misleading error messages when checking if an attachment is a zugferd file.
|
||||
@@ -162,46 +275,87 @@ Public Class ZUGFeRDInterface
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As Object
|
||||
Private Class AllowedType
|
||||
Public SchemaType As Type
|
||||
Public Specification As String
|
||||
End Class
|
||||
|
||||
Public Function ValidateZUGFeRDDocument(pResult As ZugferdResult) As ZugferdResult
|
||||
Return _Validator.ValidateZUGFeRDDocument(pResult)
|
||||
End Function
|
||||
|
||||
Public Function SerializeZUGFeRDDocument(pResult As ZugferdResult) As ZugferdResult
|
||||
Try
|
||||
Dim oNavigator As XPathNavigator = Document.CreateNavigator()
|
||||
Dim oReader As XmlReader
|
||||
Dim oResult = Nothing
|
||||
|
||||
Dim oTypes As New List(Of Type) From {
|
||||
GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType),
|
||||
GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType),
|
||||
GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType),
|
||||
GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType)
|
||||
}
|
||||
Dim oObject As Object = Nothing
|
||||
Dim oSpecification As String = Nothing
|
||||
|
||||
For Each oType In oTypes
|
||||
_logger.Debug("Trying Type [{0}]", oType.FullName)
|
||||
Dim oSerializer As New XmlSerializer(oType)
|
||||
Dim oAllowedTypes As New List(Of AllowedType)
|
||||
|
||||
If _Options.AllowZugferd_1_0_Schema Then
|
||||
oAllowedTypes.Add(New AllowedType With {
|
||||
.SchemaType = GetType(Version1_0.CrossIndustryDocumentType),
|
||||
.Specification = ZUGFERD_SPEC_10
|
||||
})
|
||||
End If
|
||||
|
||||
If _Options.AllowZugferd_2_x_Schema Then
|
||||
oAllowedTypes.AddRange(New List(Of AllowedType) From {
|
||||
New AllowedType With {
|
||||
.SchemaType = GetType(Version2_0.CrossIndustryInvoiceType),
|
||||
.Specification = ZUGFERD_SPEC_2x
|
||||
},
|
||||
New AllowedType With {
|
||||
.SchemaType = GetType(Version2_1_1.CrossIndustryInvoiceType),
|
||||
.Specification = ZUGFERD_SPEC_2x
|
||||
},
|
||||
New AllowedType With {
|
||||
.SchemaType = GetType(Version2_2_FacturX.CrossIndustryInvoiceType),
|
||||
.Specification = ZUGFERD_SPEC_2x
|
||||
}
|
||||
})
|
||||
End If
|
||||
|
||||
For Each oType In oAllowedTypes
|
||||
Dim oTypeName As String = oType.SchemaType.FullName
|
||||
Dim oSerializer As New XmlSerializer(oType.SchemaType)
|
||||
_logger.Debug("Trying Type [{0}]", oTypeName)
|
||||
|
||||
Try
|
||||
oReader = oNavigator.ReadSubtree()
|
||||
oResult = oSerializer.Deserialize(oReader)
|
||||
_logger.Debug("Serializing with type [{0}] succeeded", oType.FullName)
|
||||
oReader = pResult.XElementObject.CreateReader()
|
||||
oObject = oSerializer.Deserialize(oReader)
|
||||
oSpecification = oType.Specification
|
||||
|
||||
_logger.Debug("Serializing with type [{0}] succeeded", oTypeName)
|
||||
Exit For
|
||||
Catch ex As Exception
|
||||
_logger.Debug("Serializing with type [{0}] failed", oType.FullName)
|
||||
_logger.Debug("Serializing with type [{0}] failed", oTypeName)
|
||||
_logger.Debug(ex.Message)
|
||||
_logger.Error(ex.InnerException?.Message)
|
||||
If IsNothing(ex.InnerException) = False Then
|
||||
_logger.Debug(ex.InnerException.Message)
|
||||
End If
|
||||
End Try
|
||||
Next
|
||||
|
||||
If oResult Is Nothing Then
|
||||
Throw New ApplicationException("No Types matched the given document. Document could not be serialized.")
|
||||
If oObject Is Nothing Then
|
||||
'Throw New ApplicationException("No Types matched the given document. Document could not be serialized.")
|
||||
Throw New ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Unsupported Format")
|
||||
End If
|
||||
|
||||
Return oResult
|
||||
pResult.Specification = oSpecification
|
||||
pResult.SchemaObject = oObject
|
||||
|
||||
Return pResult
|
||||
|
||||
Catch ex As ZUGFeRDExecption
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, "Datei ist eine ungültige ZUGFeRD Datei.")
|
||||
Dim oMessage = "Datei ist eine ungültige ZUGFeRD Datei oder das Format wird nicht unterstüzt, oder das Format ist deaktiviert."
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, oMessage)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
|
||||
End Class
|
||||
|
||||
@@ -1,13 +1,38 @@
|
||||
Public Class Exceptions
|
||||
Imports DigitalData.Modules.Interfaces.ZUGFeRDInterface
|
||||
|
||||
Public Class Exceptions
|
||||
Public Class ZUGFeRDExecption
|
||||
Inherits ApplicationException
|
||||
|
||||
Public ReadOnly Property ErrorType() As ZUGFeRDInterface.ErrorType
|
||||
|
||||
''' <summary>
|
||||
''' Contains the name of the extracted xml file if already extracted.
|
||||
''' </summary>
|
||||
''' <returns>A filename like zugferd-invoice.xml</returns>
|
||||
Public ReadOnly Property XmlFile As String = String.Empty
|
||||
|
||||
Public Sub New(ErrorType As ZUGFeRDInterface.ErrorType, Message As String)
|
||||
MyBase.New(Message)
|
||||
|
||||
_ErrorType = ErrorType
|
||||
End Sub
|
||||
|
||||
Public Sub New(ErrorType As ZUGFeRDInterface.ErrorType, Message As String, pXmlFileName As String)
|
||||
MyBase.New(Message)
|
||||
|
||||
_ErrorType = ErrorType
|
||||
_XmlFile = pXmlFileName
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
Public Class ValidationException
|
||||
Inherits ApplicationException
|
||||
|
||||
Public ValidationErrors As List(Of ZugferdValidationError)
|
||||
|
||||
Public Sub New()
|
||||
MyBase.New("ZUGFeRD document found but validation failed!")
|
||||
End Sub
|
||||
End Class
|
||||
End Class
|
||||
|
||||
@@ -3,7 +3,7 @@ Imports System.Text.RegularExpressions
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class FileGroups
|
||||
Private _logger As Logger
|
||||
Private ReadOnly _logger As Logger
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
_logger = LogConfig.GetLogger()
|
||||
@@ -25,7 +25,7 @@ Public Class FileGroups
|
||||
Dim oMessageId = GetMessageIdFromFileName(oFile.Name)
|
||||
|
||||
If oMessageId Is Nothing Then
|
||||
_logger.Warn("File {0} did not have the required filename-format!", oMessageId)
|
||||
_logger.Warn("File {0} did not have the required filename-format!", oFile.Name)
|
||||
Continue For
|
||||
End If
|
||||
|
||||
@@ -69,7 +69,9 @@ Public Class FileGroups
|
||||
Private Function GetMessageIdFromFileName(Filename As String) As String
|
||||
' Regex to find MessageId
|
||||
' See also: https://stackoverflow.com/questions/3968500/regex-to-validate-a-message-id-as-per-rfc2822
|
||||
Dim oRegex = "(((([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(""(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*""))@(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\]))))~.+"
|
||||
'Dim oRegex = "(((([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(""(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*""))@(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\]))))~.+"
|
||||
|
||||
Dim oRegex = "([A-Z0-9]+)~ATTM\d+\..*"
|
||||
Dim oMatch = Regex.Match(Filename, oRegex, RegexOptions.IgnoreCase)
|
||||
|
||||
If oMatch.Success Then
|
||||
|
||||
68
Interfaces/ZUGFeRDInterface/PDFConverter.vb
Normal file
68
Interfaces/ZUGFeRDInterface/PDFConverter.vb
Normal file
@@ -0,0 +1,68 @@
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Interfaces.Exceptions
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
Public Class PDFConverter
|
||||
Private ReadOnly _LogConfig As LogConfig
|
||||
Private ReadOnly _Logger As Logger
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig)
|
||||
_LogConfig = pLogConfig
|
||||
_Logger = pLogConfig.GetLogger()
|
||||
End Sub
|
||||
|
||||
Public Function ConvertPDFADocumentToPDFDocument(pFilePath As String, pNewFilePath As String) As Boolean
|
||||
Try
|
||||
Using oGdPicturePDF As New GdPicturePDF()
|
||||
Using oGdPicturePDFDestination As New GdPicturePDF()
|
||||
|
||||
' Load the source file into memory
|
||||
If oGdPicturePDF.LoadFromFile(pFilePath, True) <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("File could not be loaded!")
|
||||
End If
|
||||
|
||||
' Create a new pdf file
|
||||
If oGdPicturePDFDestination.NewPDF() <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("New Pdf could not be created!")
|
||||
End If
|
||||
|
||||
' Copy all pages from the source into the new pdf
|
||||
If oGdPicturePDFDestination.ClonePages(oGdPicturePDF, "*") <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("Document could not be copied into new pdf!")
|
||||
End If
|
||||
|
||||
' Close the source document
|
||||
If oGdPicturePDF.CloseDocument() <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("Source document could not be closed!")
|
||||
End If
|
||||
|
||||
' Set the file path
|
||||
Dim oFinalFilePath = pFilePath
|
||||
If Not String.IsNullOrWhiteSpace(pNewFilePath) Then
|
||||
oFinalFilePath = pNewFilePath
|
||||
End If
|
||||
|
||||
' Save the file to disk
|
||||
If oGdPicturePDFDestination.SaveToFile(oFinalFilePath) <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("New document could not be saved to disk!")
|
||||
End If
|
||||
|
||||
If oGdPicturePDFDestination.CloseDocument() <> GdPictureStatus.OK Then
|
||||
Throw New ApplicationException("Destination document could not be closed!")
|
||||
End If
|
||||
|
||||
End Using
|
||||
End Using
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
End Class
|
||||
@@ -1,5 +1,7 @@
|
||||
Imports System.Collections.Generic
|
||||
Imports System.IO
|
||||
Imports System.Reflection
|
||||
Imports System.Runtime.Remoting.Messaging
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
@@ -28,7 +30,7 @@ Public Class PDFEmbeds
|
||||
Public Function Extract(FilePath As String, AllowedExtensions As List(Of String)) As List(Of EmbeddedFile)
|
||||
Dim oFile As New List(Of EmbeddedFile)
|
||||
Dim oFileInfo As FileInfo
|
||||
Dim oExtensions = AllowedExtensions.ConvertAll(New Converter(Of String, String)(Function(ext) ext.ToUpper))
|
||||
Dim oExtensions = AllowedExtensions.Select(Function(ext) ext.ToUpper).ToList()
|
||||
|
||||
Logger.Debug("Extracting embedded files from [{0}]", FilePath)
|
||||
|
||||
@@ -69,7 +71,7 @@ Public Class PDFEmbeds
|
||||
''' <param name="AllowedExtensions">List of allowed extensions to be extracted</param>
|
||||
Public Function Extract(Stream As Stream, AllowedExtensions As List(Of String)) As List(Of EmbeddedFile)
|
||||
Dim oResults As New List(Of EmbeddedFile)
|
||||
Dim oExtensions = AllowedExtensions.ConvertAll(New Converter(Of String, String)(Function(ext) ext.ToUpper))
|
||||
Dim oExtensions = AllowedExtensions.Select(Function(ext) ext.ToUpper).ToList()
|
||||
|
||||
Logger.Debug("Extracting embedded files from stream")
|
||||
|
||||
@@ -91,6 +93,64 @@ Public Class PDFEmbeds
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function RemoveEmbeddedFiles(pFilePath As String) As Boolean
|
||||
Dim oFile As New List(Of EmbeddedFile)
|
||||
Dim oFileInfo As FileInfo
|
||||
|
||||
Logger.Debug("Removing embedded files from [{0}]", pFilePath)
|
||||
|
||||
Try
|
||||
oFileInfo = New FileInfo(pFilePath)
|
||||
|
||||
Logger.Debug("Filename: {0}", oFileInfo.Name)
|
||||
Logger.Debug("Filesize: {0} bytes", oFileInfo.Length)
|
||||
Logger.Debug("Exists: {0}", oFileInfo.Exists)
|
||||
Catch ex As Exception
|
||||
Logger.Warn("File information for [{0}] could not be read!", pFilePath)
|
||||
Logger.Error(ex)
|
||||
End Try
|
||||
|
||||
Try
|
||||
Using oGDPicturePDF As New GdPicturePDF()
|
||||
If oGDPicturePDF.LoadFromFile(pFilePath, False) <> GdPictureStatus.OK Then
|
||||
Dim oMessage = String.Format("The file [{0}] can't be loaded. Status: [{1}]", pFilePath, oGDPicturePDF.GetStat().ToString())
|
||||
Throw New ApplicationException(oMessage)
|
||||
End If
|
||||
|
||||
If DoRemove(oGDPicturePDF) = False Then
|
||||
Dim oMessage = String.Format("Attachments for file [{0}] can't be removed. Status: [{1}]", pFilePath, oGDPicturePDF.GetStat().ToString())
|
||||
Throw New ApplicationException(oMessage)
|
||||
End If
|
||||
End Using
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Logger.Warn("Unexpected Error while Extracting attachments from File [{0}]", pFilePath)
|
||||
Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function DoRemove(GDPicturePDF As GdPicturePDF) As Boolean
|
||||
Dim oStatus As GdPictureStatus
|
||||
|
||||
Dim oEmbeddedFileCount As Integer = GDPicturePDF.GetEmbeddedFileCount()
|
||||
|
||||
If oStatus <> GdPictureStatus.OK Then
|
||||
Logger.Warn("Embedded files could not be removed. Status: [{0}]", oStatus.ToString)
|
||||
Return False
|
||||
End If
|
||||
|
||||
If oEmbeddedFileCount = 0 Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
While GDPicturePDF.GetEmbeddedFileCount() > 0
|
||||
GDPicturePDF.DeleteEmbeddedFile(0)
|
||||
End While
|
||||
|
||||
End Function
|
||||
|
||||
Private Function DoExtract(GDPicturePDF As GdPicturePDF, pExtensions As List(Of String)) As List(Of EmbeddedFile)
|
||||
Dim oResults As New List(Of EmbeddedFile)
|
||||
Dim oEmbeddedFileCount As Integer = GDPicturePDF.GetEmbeddedFileCount()
|
||||
@@ -105,7 +165,17 @@ Public Class PDFEmbeds
|
||||
If GDPicturePDF.GetStat() = GdPictureStatus.OK Then
|
||||
Logger.Debug("Extracting embedded file [{0}]", oFileName)
|
||||
|
||||
Dim oExtension = New FileInfo(oFileName).Extension.ToUpper.Substring(1)
|
||||
Dim oFileInfo = New FileInfo(oFileName)
|
||||
Dim oExtension As String = oFileInfo.Extension
|
||||
|
||||
If String.IsNullOrWhiteSpace(oExtension) Then
|
||||
Logger.Error("The embedded file [{0}] does not have any extension. Skipping.", oFileName)
|
||||
Continue For
|
||||
Else
|
||||
' Jetzt wissen wir, das es eine Extension gibt!
|
||||
oExtension = oFileInfo.Extension.ToUpper.Substring(1)
|
||||
End If
|
||||
|
||||
If pExtensions.Contains(oExtension) Then
|
||||
Dim oFileSize As Integer = GDPicturePDF.GetEmbeddedFileSize(oIndex)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Public Class PropertyValues
|
||||
Public TableName As String
|
||||
Public TableColumn As String
|
||||
|
||||
Public ISRequired As Boolean
|
||||
Public IsRequired As Boolean
|
||||
Public GroupCounter As Integer = -1
|
||||
|
||||
Public Description As String
|
||||
@@ -99,9 +99,7 @@ Public Class PropertyValues
|
||||
Dim oIsRequired As Boolean = oColumn.Key.IsRequired
|
||||
Dim oPropertyDescription As String = oColumn.Key.Description
|
||||
Dim oRowCounter = oRowIndex + oGlobalGroupCounter + 1
|
||||
If IsNothing(oRowCounter) Then
|
||||
|
||||
End If
|
||||
' Returns nothing if oColumn.Value contains an empty list
|
||||
Dim oPropertyValue = oColumn.Value.ElementAtOrDefault(oRowIndex)
|
||||
|
||||
@@ -127,7 +125,7 @@ Public Class PropertyValues
|
||||
.GroupCounter = oRowCounter,
|
||||
.TableName = oTableName,
|
||||
.TableColumn = oTableColumn,
|
||||
.ISRequired = oIsRequired
|
||||
.IsRequired = oIsRequired
|
||||
})
|
||||
Next
|
||||
Next
|
||||
@@ -139,6 +137,7 @@ Public Class PropertyValues
|
||||
For Each oItem As KeyValuePair(Of String, XmlItemProperty) In oDefaultProperties
|
||||
Dim oPropertyValueList As List(Of Object)
|
||||
Dim oTableColumn As String = oItem.Value.TableColumn
|
||||
Dim oPropertyDescription As String = oItem.Value.Description
|
||||
Dim oPropertyValue As Object = Nothing
|
||||
Dim oTableName = oItem.Value.TableName
|
||||
Dim oIsRequired = oItem.Value.IsRequired
|
||||
@@ -146,7 +145,7 @@ Public Class PropertyValues
|
||||
Try
|
||||
oPropertyValueList = GetPropValue(Document, oItem.Key)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("{2} # Unknown error occurred while fetching specification [{0}] in group [{1}]:", oTableColumn, oItem.Value.GroupScope, MessageId)
|
||||
_logger.Warn("{2} # Unknown error occurred while fetching specification [{0}] in group [{1}]:", oPropertyDescription, oItem.Value.GroupScope, MessageId)
|
||||
_logger.Error(ex)
|
||||
oPropertyValueList = New List(Of Object)
|
||||
End Try
|
||||
@@ -164,24 +163,24 @@ Public Class PropertyValues
|
||||
|
||||
' This should hopefully show config errors
|
||||
If TypeOf oPropertyValue Is List(Of Object) Then
|
||||
_logger.Warn("Item with TableColumn [{0}] may be configured incorrectly", oTableColumn)
|
||||
_logger.Warn("Item with specification [{0}] may be configured incorrectly", oPropertyDescription)
|
||||
oPropertyValue = Nothing
|
||||
End If
|
||||
End Select
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Unknown error occurred while processing specification [{0}]:", oTableColumn)
|
||||
_logger.Warn("Unknown error occurred while processing specification [{0}]:", oPropertyDescription)
|
||||
_logger.Error(ex)
|
||||
oPropertyValue = Nothing
|
||||
End Try
|
||||
|
||||
If IsNothing(oPropertyValue) OrElse String.IsNullOrEmpty(oPropertyValue) Then
|
||||
If oItem.Value.IsRequired Then
|
||||
_logger.Warn("{0} # Specification [{1}] is empty, but marked as required! Skipping.", MessageId, oTableColumn)
|
||||
oResult.MissingProperties.Add(oTableColumn)
|
||||
_logger.Warn("{0} # Specification [{1}] is empty, but marked as required! Skipping.", MessageId, oPropertyDescription)
|
||||
oResult.MissingProperties.Add(oPropertyDescription)
|
||||
Continue For
|
||||
Else
|
||||
_logger.Debug("{0} # oPropertyValue for specification [{1}] is empty or not found. Skipping.", MessageId, oTableColumn)
|
||||
_logger.Debug("{0} # oPropertyValue for specification [{1}] is empty or not found. Skipping.", MessageId, oPropertyDescription)
|
||||
|
||||
Continue For
|
||||
End If
|
||||
@@ -193,7 +192,7 @@ Public Class PropertyValues
|
||||
.Value = oPropertyValue,
|
||||
.TableName = oTableName,
|
||||
.TableColumn = oTableColumn,
|
||||
.ISRequired = oIsRequired
|
||||
.IsRequired = oIsRequired
|
||||
})
|
||||
Next
|
||||
|
||||
@@ -240,6 +239,12 @@ Public Class PropertyValues
|
||||
|
||||
Obj = oInfo.GetValue(Obj, Nothing)
|
||||
|
||||
' TODO: This code should check for array properties by itself
|
||||
' and should not rely on the user to
|
||||
'If oInfo.PropertyType.IsArray Then
|
||||
' Obj = Obj(0)
|
||||
'End If
|
||||
|
||||
If oHasIndex Then
|
||||
Obj = Obj(0)
|
||||
End If
|
||||
@@ -265,6 +270,8 @@ Public Class PropertyValues
|
||||
|
||||
Return oResults
|
||||
End If
|
||||
|
||||
|
||||
Next
|
||||
|
||||
Return New List(Of Object) From {Obj}
|
||||
|
||||
98
Interfaces/ZUGFeRDInterface/Validator.vb
Normal file
98
Interfaces/ZUGFeRDInterface/Validator.vb
Normal file
@@ -0,0 +1,98 @@
|
||||
Imports DigitalData.Modules.Interfaces.ZUGFeRDInterface
|
||||
Imports DigitalData.Modules.Logging
|
||||
|
||||
Public Class Validator
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _logger As Logger
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig)
|
||||
_logConfig = pLogConfig
|
||||
_logger = pLogConfig.GetLogger()
|
||||
End Sub
|
||||
|
||||
Public Function ValidateZUGFeRDDocument(pResult As ZugferdResult) As ZugferdResult
|
||||
ValidateDecimalNodes(pResult)
|
||||
ValidateCurrencyNodes(pResult)
|
||||
|
||||
Return pResult
|
||||
End Function
|
||||
|
||||
Private Sub ValidateDecimalNodes(ByRef pResult As ZugferdResult)
|
||||
Try
|
||||
Dim oDecimalNodes = pResult.XElementObject.Descendants().
|
||||
Where(Function(n) n.Name.ToString.EndsWith("Amount") Or n.Name.ToString.EndsWith("Percent"))
|
||||
|
||||
For Each oNode As XElement In oDecimalNodes
|
||||
Dim oParsedValue As Decimal = 0.0
|
||||
If Decimal.TryParse(oNode.Value, oParsedValue) = False Then
|
||||
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
|
||||
.ElementName = oNode.Name.LocalName,
|
||||
.ElementValue = oNode.Value,
|
||||
.ErrorMessage = "Value could not be parsed as Decimal"
|
||||
})
|
||||
End If
|
||||
Next
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub ValidateCurrencyNodes(ByRef pResult As ZugferdResult)
|
||||
' CurrencyCode Nodes
|
||||
Try
|
||||
Dim oCurrencyCodeNodes = pResult.XElementObject.Descendants().
|
||||
Where(Function(n) n.Name.ToString.EndsWith("CurrencyCode"))
|
||||
|
||||
For Each oNode As XElement In oCurrencyCodeNodes
|
||||
Dim oValid = ValidateCurrencyCode(oNode.Value)
|
||||
If oValid = False Then
|
||||
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
|
||||
.ElementName = oNode.Name.LocalName,
|
||||
.ElementValue = oNode.Value,
|
||||
.ErrorMessage = "Invalid CurrencyCode. Only 3-Character codes are allowed."
|
||||
})
|
||||
End If
|
||||
Next
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
|
||||
' currencyID
|
||||
Try
|
||||
Dim oCurrencyIDNodes = pResult.XElementObject.Descendants().
|
||||
Where(Function(n) n.Attributes.Any(Function(a) a.Name.LocalName = "currencyID"))
|
||||
|
||||
For Each oNode As XElement In oCurrencyIDNodes
|
||||
Dim oCurrencyID As String = oNode.Attribute("currencyID")?.Value
|
||||
|
||||
' CurrencyID is optional per spec
|
||||
If String.IsNullOrWhiteSpace(oCurrencyID) Then
|
||||
Continue For
|
||||
End If
|
||||
|
||||
Dim oValid = ValidateCurrencyCode(oCurrencyID)
|
||||
If oValid = False Then
|
||||
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
|
||||
.ElementName = oNode.Name.LocalName,
|
||||
.ElementValue = oCurrencyID,
|
||||
.ErrorMessage = "Invalid currencyID. Only 3-Character codes or empty values are allowed."
|
||||
})
|
||||
End If
|
||||
Next
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Function ValidateCurrencyCode(pValue As String) As Boolean
|
||||
Dim oValueRegex As New Text.RegularExpressions.Regex("[A-Z]{3}")
|
||||
|
||||
If oValueRegex.IsMatch(pValue) = False Then
|
||||
Return False
|
||||
End If
|
||||
|
||||
Return True
|
||||
End Function
|
||||
End Class
|
||||
@@ -330,6 +330,17 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
|
||||
Private directDebitMandateIDField As IDType
|
||||
|
||||
Private descriptionField As TextType
|
||||
|
||||
Public Property Description As TextType
|
||||
Get
|
||||
Return descriptionField
|
||||
End Get
|
||||
Set
|
||||
Me.descriptionField = Value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
'''<remarks/>
|
||||
Public Property DueDateDateTime() As DateTimeType
|
||||
Get
|
||||
@@ -363,7 +374,7 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlElementAttribute("DateTimeString")>
|
||||
Public Property Item() As DateTimeTypeDateTimeString
|
||||
Public Property DateTimeString() As DateTimeTypeDateTimeString
|
||||
Get
|
||||
Return Me.itemField
|
||||
End Get
|
||||
@@ -481,6 +492,28 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
System.SerializableAttribute(),
|
||||
System.Diagnostics.DebuggerStepThroughAttribute(),
|
||||
System.ComponentModel.DesignerCategoryAttribute("code"),
|
||||
System.Xml.Serialization.XmlTypeAttribute([Namespace]:="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:10" &
|
||||
"")>
|
||||
Partial Public Class CreditorFinancialInstitutionType
|
||||
|
||||
Private bICIDField As IDType
|
||||
|
||||
'''<remarks/>
|
||||
Public Property BICID() As IDType
|
||||
Get
|
||||
Return Me.bICIDField
|
||||
End Get
|
||||
Set
|
||||
Me.bICIDField = Value
|
||||
End Set
|
||||
End Property
|
||||
End Class
|
||||
|
||||
'''<remarks/>
|
||||
<System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0"),
|
||||
System.SerializableAttribute(),
|
||||
System.Diagnostics.DebuggerStepThroughAttribute(),
|
||||
System.ComponentModel.DesignerCategoryAttribute("code"),
|
||||
System.Xml.Serialization.XmlTypeAttribute([Namespace]:="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:10" &
|
||||
"0")>
|
||||
Partial Public Class DebtorFinancialAccountType
|
||||
@@ -581,10 +614,14 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
|
||||
Private typeCodeField As PaymentMeansCodeType
|
||||
|
||||
Private informationField As TextType
|
||||
|
||||
Private payerPartyDebtorFinancialAccountField As DebtorFinancialAccountType
|
||||
|
||||
Private payeePartyCreditorFinancialAccountField As CreditorFinancialAccountType
|
||||
|
||||
Private payeeSpecifiedCreditorFinancialInstitutionField As CreditorFinancialInstitutionType
|
||||
|
||||
'''<remarks/>
|
||||
Public Property TypeCode() As PaymentMeansCodeType
|
||||
Get
|
||||
@@ -595,6 +632,16 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
End Set
|
||||
End Property
|
||||
|
||||
'''<remarks/>
|
||||
Public Property Information() As TextType
|
||||
Get
|
||||
Return Me.informationField
|
||||
End Get
|
||||
Set
|
||||
Me.informationField = Value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
'''<remarks/>
|
||||
Public Property PayerPartyDebtorFinancialAccount() As DebtorFinancialAccountType
|
||||
Get
|
||||
@@ -614,6 +661,16 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
Me.payeePartyCreditorFinancialAccountField = Value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
'''<remarks/>
|
||||
Public Property PayeeSpecifiedCreditorFinancialInstitution() As CreditorFinancialInstitutionType
|
||||
Get
|
||||
Return Me.payeeSpecifiedCreditorFinancialInstitutionField
|
||||
End Get
|
||||
Set
|
||||
Me.payeeSpecifiedCreditorFinancialInstitutionField = Value
|
||||
End Set
|
||||
End Property
|
||||
End Class
|
||||
|
||||
'''<remarks/>
|
||||
@@ -1207,7 +1264,7 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
|
||||
Private specifiedTradeAllowanceChargeField() As TradeAllowanceChargeType
|
||||
|
||||
Private specifiedTradePaymentTermsField As TradePaymentTermsType
|
||||
Private specifiedTradePaymentTermsField() As TradePaymentTermsType
|
||||
|
||||
Private specifiedTradeSettlementHeaderMonetarySummationField As TradeSettlementHeaderMonetarySummationType
|
||||
|
||||
@@ -1299,7 +1356,8 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
End Property
|
||||
|
||||
'''<remarks/>
|
||||
Public Property SpecifiedTradePaymentTerms() As TradePaymentTermsType
|
||||
<System.Xml.Serialization.XmlElementAttribute("SpecifiedTradePaymentTerms")>
|
||||
Public Property SpecifiedTradePaymentTerms() As TradePaymentTermsType()
|
||||
Get
|
||||
Return Me.specifiedTradePaymentTermsField
|
||||
End Get
|
||||
@@ -4100,171 +4158,171 @@ Namespace ZUGFeRD.Version2_1_1
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("80")>
|
||||
Item80
|
||||
Item80 = 80
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("81")>
|
||||
Item81
|
||||
Item81 = 81
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("82")>
|
||||
Item82
|
||||
Item82 = 82
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("83")>
|
||||
Item83
|
||||
Item83 = 83
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("84")>
|
||||
Item84
|
||||
Item84 = 84
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("130")>
|
||||
Item130
|
||||
Item130 = 130
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("202")>
|
||||
Item202
|
||||
Item202 = 202
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("203")>
|
||||
Item203
|
||||
Item203 = 203
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("204")>
|
||||
Item204
|
||||
Item204 = 204
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("211")>
|
||||
Item211
|
||||
Item211 = 211
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("261")>
|
||||
Item261
|
||||
Item261 = 261
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("262")>
|
||||
Item262
|
||||
Item262 = 262
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("295")>
|
||||
Item295
|
||||
Item295 = 295
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("296")>
|
||||
Item296
|
||||
Item296 = 296
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("308")>
|
||||
Item308
|
||||
Item308 = 308
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("325")>
|
||||
Item325
|
||||
Item325 = 325
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("326")>
|
||||
Item326
|
||||
Item326 = 326
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("380")>
|
||||
Item380
|
||||
Item380 = 380
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("381")>
|
||||
Item381
|
||||
Item381 = 381
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("383")>
|
||||
Item383
|
||||
Item383 = 383
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("384")>
|
||||
Item384
|
||||
Item384 = 384
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("385")>
|
||||
Item385
|
||||
Item385 = 385
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("386")>
|
||||
Item386
|
||||
Item386 = 386
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("387")>
|
||||
Item387
|
||||
Item387 = 387
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("388")>
|
||||
Item388
|
||||
Item388 = 388
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("389")>
|
||||
Item389
|
||||
Item389 = 389
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("390")>
|
||||
Item390
|
||||
Item390 = 390
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("393")>
|
||||
Item393
|
||||
Item393 = 393
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("394")>
|
||||
Item394
|
||||
Item394 = 394
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("395")>
|
||||
Item395
|
||||
Item395 = 395
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("396")>
|
||||
Item396
|
||||
Item396 = 396
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("420")>
|
||||
Item420
|
||||
Item420 = 420
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("456")>
|
||||
Item456
|
||||
Item456 = 456
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("457")>
|
||||
Item457
|
||||
Item457 = 457
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("458")>
|
||||
Item458
|
||||
Item458 = 458
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("527")>
|
||||
Item527
|
||||
Item527 = 527
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("575")>
|
||||
Item575
|
||||
Item575 = 575
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("623")>
|
||||
Item623
|
||||
Item623 = 623
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("633")>
|
||||
Item633
|
||||
Item633 = 633
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("751")>
|
||||
Item751
|
||||
Item751 = 751
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("780")>
|
||||
Item780
|
||||
Item780 = 780
|
||||
|
||||
'''<remarks/>
|
||||
<System.Xml.Serialization.XmlEnumAttribute("935")>
|
||||
Item935
|
||||
Item935 = 935
|
||||
End Enum
|
||||
|
||||
'''<remarks/>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
Public Class XmlItemProperty
|
||||
Public IsRequired As Boolean
|
||||
Public IsGrouped As Boolean
|
||||
|
||||
Public TableName As String
|
||||
Public TableColumn As String
|
||||
Public Description As String
|
||||
Public IsRequired As Boolean
|
||||
Public IsGrouped As Boolean
|
||||
Public GroupScope As String
|
||||
|
||||
''' <summary>
|
||||
''' Document version, eg. ZUGFeRD Schema version
|
||||
''' </summary>
|
||||
Public Specification As String
|
||||
End Class
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
|
||||
<package id="NLog" version="4.7.15" targetFramework="net461" />
|
||||
<package id="NLog" version="5.0.5" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -8,8 +8,8 @@ Public Class ADSyncJob
|
||||
Inherits JobBase
|
||||
Implements IJob(Of ADSyncArgs)
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, MSSQL As MSSQLServer)
|
||||
MyBase.New(LogConfig, Firebird, MSSQL)
|
||||
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer)
|
||||
MyBase.New(LogConfig, MSSQL)
|
||||
End Sub
|
||||
|
||||
Public Sub Start(Arguments As ADSyncArgs) Implements IJob(Of ADSyncArgs).Start
|
||||
@@ -31,7 +31,7 @@ Public Class ADSyncJob
|
||||
|
||||
For Each oGroup In oGroups
|
||||
_Logger.Debug("Syncing Group [{0}]", oGroup)
|
||||
Dim oSyncedUsers = oSync.SyncUsersForGroup(oGroup, oAttributeMappings, _Firebird, _MSSQL, Arguments.UserFilter)
|
||||
Dim oSyncedUsers = oSync.SyncUsersForGroup(oGroup, oAttributeMappings, _MSSQL, Arguments.UserFilter)
|
||||
|
||||
If oSyncedUsers Is Nothing Then
|
||||
_Logger.Warn("Group [{0}] could not be synced!", oGroup)
|
||||
@@ -1,223 +0,0 @@
|
||||
Option Explicit On
|
||||
|
||||
Imports System.IO
|
||||
Imports DigitalData.Modules.Interfaces
|
||||
Imports DigitalData.Modules.Jobs
|
||||
Imports DigitalData.Modules.Config
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports Newtonsoft.Json.Linq
|
||||
Imports System.Collections.Generic
|
||||
Imports System.Linq
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports System.Data
|
||||
|
||||
Public Class GraphQLJob
|
||||
Inherits JobBase
|
||||
Implements IJob(Of GraphQLArgs)
|
||||
|
||||
Private _GraphQL As GraphQLInterface = Nothing
|
||||
|
||||
Private Const PLACEHOLDER_STATIC = "STATIC:"
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer)
|
||||
MyBase.New(LogConfig, Nothing, MSSQL)
|
||||
End Sub
|
||||
|
||||
Public Sub Start(Args As GraphQLArgs) Implements IJob(Of GraphQLArgs).Start
|
||||
Try
|
||||
Dim oConfigPath As String = Args.QueryConfigPath
|
||||
Dim oConfigManager As New ConfigManager(Of GraphQLConfig)(_LogConfig, oConfigPath)
|
||||
|
||||
With oConfigManager.Config
|
||||
_GraphQL = New GraphQLInterface(_LogConfig, .BaseUrl, .Email, .Password, .CertificateFingerprint)
|
||||
End With
|
||||
|
||||
' Login to get cookie
|
||||
_Logger.Debug("Logging in")
|
||||
Dim oLoginResponse = _GraphQL.Login()
|
||||
|
||||
' save cookie for future requests
|
||||
_GraphQL.SaveCookies(oLoginResponse.Cookies.Item(0))
|
||||
|
||||
_Logger.Debug("Loading Queries")
|
||||
|
||||
' Load query data from TBCUST_JOBRUNNER_QUERY
|
||||
Dim oQueryTable As DataTable = _MSSQL.GetDatatable("SELECT * FROM TBCUST_JOBRUNNER_QUERY ORDER BY OPERATION_NAME, CLEAR_BEFORE_FILL ASC")
|
||||
Dim oQueryList As New List(Of GraphQL.Query)
|
||||
|
||||
' Save query data to business objects
|
||||
For Each oRow As DataRow In oQueryTable.Rows
|
||||
Dim oQuery As New GraphQL.Query With {
|
||||
.Id = oRow.Item("GUID"),
|
||||
.Name = oRow.Item("TITLE"),
|
||||
.ClearBeforeFill = oRow.Item("CLEAR_BEFORE_FILL"),
|
||||
.ConnectionId = oRow.Item("CON_ID"), ' TODO: Connection String?
|
||||
.DestinationTable = oRow.Item("DESTINATION_TABLE"),
|
||||
.OperationName = oRow.Item("OPERATION_NAME"),
|
||||
.MappingBasePath = oRow.Item("MAPPING_BASE_PATH"),
|
||||
.QueryString = oRow.Item("QUERY_STRING"),
|
||||
.QueryConstraint = oRow.Item("QUERY_CONSTRAINT")
|
||||
}
|
||||
oQueryList.Add(oQuery)
|
||||
Next
|
||||
|
||||
_Logger.Debug("Getting the data from GraphQL")
|
||||
|
||||
For Each oQuery As GraphQL.Query In oQueryList
|
||||
Try
|
||||
_Logger.NewBlock($"Query [{oQuery.Name}]")
|
||||
|
||||
Dim oConnectionId As Integer = oQuery.ConnectionId
|
||||
Dim oConnectionString = _MSSQL.Get_ConnectionStringforID(oConnectionId)
|
||||
|
||||
Dim oDatabase As New MSSQLServer(_LogConfig, oConnectionString)
|
||||
|
||||
' Reset all records to status = 0
|
||||
_Logger.Info("Resetting data with constraint [{1}]", oQuery.Name, oQuery.QueryConstraint)
|
||||
|
||||
Dim oResetSQL = $"UPDATE {oQuery.DestinationTable} SET STATUS = 0"
|
||||
If oQuery.QueryConstraint <> String.Empty Then
|
||||
oResetSQL &= $" WHERE {oQuery.QueryConstraint}"
|
||||
End If
|
||||
_MSSQL.ExecuteNonQuery(oResetSQL)
|
||||
|
||||
_Logger.Info("Getting data..", oQuery.Name)
|
||||
|
||||
' get the data from GraphQL
|
||||
Dim oDataResponse = _GraphQL.GetData(oQuery.QueryString, oQuery.OperationName)
|
||||
Dim oResult As String
|
||||
|
||||
' write data to string
|
||||
Using oStream = oDataResponse.GetResponseStream()
|
||||
Using oReader As New StreamReader(oStream)
|
||||
oResult = oReader.ReadToEnd()
|
||||
End Using
|
||||
End Using
|
||||
|
||||
' Fill the query object with field mapping data from TBCUST_JOBRUNNER_QUERY_MAPPING
|
||||
Dim oSQL As String = "SELECT t2.* FROM TBCUST_JOBRUNNER_QUERY_MAPPING t
|
||||
JOIN TBCUST_JOBRUNNER_MAPPING t2 ON t.MAPPING_ID = t2.GUID
|
||||
WHERE t.QUERY_ID = {0}"
|
||||
Dim oMappingTable As DataTable = _MSSQL.GetDatatable(String.Format(oSQL, oQuery.Id))
|
||||
|
||||
For Each oMapping As DataRow In oMappingTable.Rows
|
||||
oQuery.MappingFields.Add(New GraphQL.FieldMapping With {
|
||||
.DestinationColumn = oMapping.Item("DestinationColumn"),
|
||||
.SourcePath = oMapping.Item("SourcePath")
|
||||
})
|
||||
Next
|
||||
|
||||
' Handle the response from GraphQL and insert Data
|
||||
Dim oQueryHandleResult = HandleResponse(oResult, oQuery, oDatabase)
|
||||
|
||||
If IsNothing(oQueryHandleResult) Then
|
||||
Continue For
|
||||
End If
|
||||
|
||||
' Finally delete all old records
|
||||
Dim oDeleteSQL = $"DELETE FROM {oQuery.DestinationTable} WHERE STATUS = 0"
|
||||
If oQuery.QueryConstraint <> String.Empty Then
|
||||
oDeleteSQL &= $" AND {oQuery.QueryConstraint}"
|
||||
End If
|
||||
|
||||
_Logger.Info("Success, deleting old records..", oQuery.Name)
|
||||
_MSSQL.ExecuteNonQuery(oDeleteSQL)
|
||||
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("Error while getting Data for Name/OperationName [{0}]/[{1}]", oQuery.Name, oQuery.OperationName)
|
||||
_Logger.Error(ex)
|
||||
|
||||
_Logger.Info("Failure, deleting new records..", oQuery.Name)
|
||||
|
||||
' If a crash happens, delete all records which were inserted in this run,
|
||||
' thus going back to the previous state
|
||||
Dim oDeleteSQL = $"DELETE FROM {oQuery.DestinationTable} WHERE STATUS = 1"
|
||||
If oQuery.QueryConstraint <> String.Empty Then
|
||||
oDeleteSQL &= $" AND {oQuery.QueryConstraint}"
|
||||
End If
|
||||
_MSSQL.ExecuteNonQuery(oDeleteSQL)
|
||||
Finally
|
||||
_Logger.EndBlock()
|
||||
End Try
|
||||
Next
|
||||
|
||||
' logout
|
||||
_Logger.Debug("Logging out")
|
||||
Dim oLogoutResponse = _GraphQL.Logout()
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Function HandleResponse(JsonString As String, QueryData As GraphQL.Query, DB As Database.MSSQLServer) As GraphQL.Query
|
||||
Dim oObj As JObject = JObject.Parse(JsonString)
|
||||
Dim oResultList As JToken
|
||||
|
||||
If _GraphQL.ReadJSONPathFragmented(oObj, QueryData.MappingBasePath) = False Then
|
||||
_Logger.Warn("There is an error in the MappingBasePath [{1}] configuration of query [{0}]", QueryData.Name, QueryData.MappingBasePath)
|
||||
End If
|
||||
|
||||
Try
|
||||
oResultList = oObj.SelectToken(QueryData.MappingBasePath, errorWhenNoMatch:=True)
|
||||
Catch ex As Exception
|
||||
_Logger.Warn("HandleResponse: Could not find BasePath: [{0}] for query [{1}]", QueryData.MappingBasePath, QueryData.Name)
|
||||
_Logger.Error(ex)
|
||||
Return Nothing
|
||||
End Try
|
||||
|
||||
If oResultList Is Nothing Then
|
||||
_Logger.Warn("HandleResponse: Could not find BasePath: [{0}] for query [{1}]", QueryData.MappingBasePath, QueryData.Name)
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
_Logger.Info("HandleResponse: Processing Queue [{0}] with [{1}] Items", QueryData.Name, oResultList.Count)
|
||||
|
||||
For Each oResultItem As JToken In oResultList
|
||||
Try
|
||||
Dim oValues As New List(Of String)
|
||||
Dim oKeys As New List(Of String)
|
||||
|
||||
For Each oMapping In QueryData.MappingFields
|
||||
Dim oValue As String = String.Empty
|
||||
|
||||
If oMapping.SourcePath.StartsWith(PLACEHOLDER_STATIC) Then
|
||||
oValue = oMapping.SourcePath.Replace(PLACEHOLDER_STATIC, String.Empty)
|
||||
Else
|
||||
Dim oToken = oResultItem.SelectToken(oMapping.SourcePath)
|
||||
|
||||
If oToken Is Nothing Then
|
||||
_Logger.Warn("HandleResponse: Could not find value at SourcePath: {0}", oMapping.SourcePath)
|
||||
oValue = String.Empty
|
||||
Else
|
||||
oValue = oToken.ToString
|
||||
End If
|
||||
End If
|
||||
|
||||
oValues.Add(oValue)
|
||||
oKeys.Add(oMapping.DestinationColumn)
|
||||
Next
|
||||
|
||||
Dim oColumnValues = oValues.
|
||||
Select(Function(Value) Regex.Replace(Value, "'", "''")).
|
||||
Select(Function(Value) $"'{Value}'").
|
||||
ToList()
|
||||
Dim oValueString = String.Join(",", oColumnValues)
|
||||
|
||||
Dim oColumns = String.Join(",", oKeys.ToArray)
|
||||
Dim oSQL As String = $"INSERT INTO {QueryData.DestinationTable} ({oColumns}) VALUES ({oValueString})"
|
||||
|
||||
DB.ExecuteNonQuery(oSQL)
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
End Try
|
||||
Next
|
||||
|
||||
Return QueryData
|
||||
End Function
|
||||
|
||||
Public Function ShouldStart(Arguments As GraphQLArgs) As Boolean Implements IJob(Of GraphQLArgs).ShouldStart
|
||||
Return Arguments.Enabled
|
||||
End Function
|
||||
End Class
|
||||
@@ -1,5 +0,0 @@
|
||||
Public Class EmailData
|
||||
Public Attachment As String = ""
|
||||
Public Subject As String
|
||||
Public From As String
|
||||
End Class
|
||||
@@ -1,203 +0,0 @@
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports System.Data
|
||||
Imports System.IO
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Public Class EmailFunctions
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _mssql As MSSQLServer
|
||||
Private ReadOnly _firebird As Firebird
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer, Firebird As Firebird)
|
||||
_logConfig = LogConfig
|
||||
_logger = _logConfig.GetLogger()
|
||||
_mssql = MSSQL
|
||||
_firebird = Firebird
|
||||
End Sub
|
||||
|
||||
Public Sub AddToEmailQueueFB(MessageId As String, BodyText As String, EmailData As EmailData, NamePortal As String)
|
||||
If EmailData Is Nothing Then
|
||||
_logger.Warn("EmailData is empty. Email will not be sent!")
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
Try
|
||||
Dim oJobId = RandomValue(1, 10000)
|
||||
Dim oReference = MessageId
|
||||
Dim oEmailTo = ""
|
||||
Dim oSubject = EmailStrings.EMAIL_SUBJECT_REJECTED.Replace(EmailStrings.constNAME_ZUGFERD_PORTAL, NamePortal)
|
||||
Dim oAccountId = 1
|
||||
Dim oCreatedWho = "ZUGFeRD Service"
|
||||
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT.Replace(EmailStrings.constNAME_ZUGFERD_PORTAL, NamePortal), BodyText)
|
||||
|
||||
Dim oEmailAddress = EmailData.From
|
||||
Dim oAttachment = EmailData.Attachment
|
||||
|
||||
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
|
||||
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
|
||||
oEmailTo = String.Empty
|
||||
Else
|
||||
oEmailTo = oEmailAddress
|
||||
End If
|
||||
|
||||
_logger.Debug("Generated Email:")
|
||||
_logger.Debug("To: {0}", oEmailTo)
|
||||
_logger.Debug("Subject: {0}", oSubject)
|
||||
_logger.Debug("Body {0}", oFinalBodyText)
|
||||
Dim osql = $"select * from TBEDM_EMAIL_QUEUE where REFERENCE1 = '{oReference} and EMAIL_TO = ''{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
|
||||
|
||||
Dim oDTResult As DataTable = _firebird.GetDatatable(osql)
|
||||
|
||||
If oDTResult.Rows.Count = 0 Then
|
||||
Dim oSQLInsert = $"INSERT INTO TBEDM_EMAIL_QUEUE "
|
||||
oSQLInsert &= "(JOB_ID, REFERENCE1, EMAIL_ACCOUNT_ID, EMAIL_TO, EMAIL_SUBJ, EMAIL_BODY, CREATEDWHO, EMAIL_ATTMT1) VALUES "
|
||||
oSQLInsert &= $"({oJobId}, '{oReference}', {oAccountId}, '{oEmailTo}', '{oSubject}', '{oFinalBodyText.Replace("'", "''")}', '{oCreatedWho}', '{oAttachment}')"
|
||||
_firebird.ExecuteNonQuery(oSQLInsert)
|
||||
_logger.Debug("Email Queue updated for MessageId {0}.", MessageId, oEmailTo)
|
||||
Else
|
||||
_logger.Debug("Email has already been sent!!")
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
Public Sub AddToEmailQueueMSSQL(MessageId As String, BodyText As String, pEmailData As EmailData, SourceProcedure As String, pEmailAccountId As Integer, NamePortal As String)
|
||||
If pEmailData Is Nothing Then
|
||||
_logger.Warn("EmailData is empty. Email will not be sent!")
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
Try
|
||||
Dim oJobId = RandomValue(1, 10000)
|
||||
Dim oReference = MessageId
|
||||
Dim oEmailTo = ""
|
||||
Dim oSubject = EmailStrings.EMAIL_SUBJECT_REJECTED.Replace(EmailStrings.constNAME_ZUGFERD_PORTAL, NamePortal)
|
||||
Dim oCreatedWho = "ZUGFeRD Service"
|
||||
|
||||
Dim oMaskedBodyText = BodyText.Replace("'", "''")
|
||||
Dim oSubjectBodyText = String.Format(EmailStrings.EMAIL_SUBJECT_TEXT.Replace(EmailStrings.constNAME_ZUGFERD_PORTAL, NamePortal), pEmailData.Subject).Replace("'", "''")
|
||||
Dim oCompleteBodyText = oMaskedBodyText & oSubjectBodyText
|
||||
|
||||
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT.Replace(EmailStrings.constNAME_ZUGFERD_PORTAL, NamePortal), oCompleteBodyText)
|
||||
|
||||
Dim oEmailAddress = pEmailData.From
|
||||
Dim oAttachment = pEmailData.Attachment
|
||||
If oAttachment <> String.Empty Then
|
||||
_logger.Debug($"Attachment_String [{oAttachment}]!")
|
||||
If IO.File.Exists(oAttachment) = False Then
|
||||
_logger.Info($"Attachment.File [{oAttachment}] is not existing!!!")
|
||||
End If
|
||||
End If
|
||||
|
||||
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
|
||||
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
|
||||
oEmailTo = String.Empty
|
||||
Else
|
||||
oEmailTo = oEmailAddress
|
||||
End If
|
||||
|
||||
_logger.Debug("Generated Email:")
|
||||
_logger.Debug("To: {0}", oEmailTo)
|
||||
_logger.Debug("Subject: {0}", oSubject)
|
||||
_logger.Debug("Body {0}", oFinalBodyText)
|
||||
Dim osql = $"Select MAX(GUID) FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
|
||||
Dim oHistoryID = _mssql.GetScalarValue(osql)
|
||||
|
||||
'osql = $"select * from TBEMLP_EMAIL_OUT where REFERENCE_ID = {oHistoryID} and EMAIL_ADRESS = '{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
|
||||
|
||||
'Dim oDTResult As DataTable = _mssql.GetDatatable(osql)
|
||||
|
||||
If IsNumeric(oHistoryID) Then
|
||||
Dim oInsert = $"INSERT INTO [dbo].[TBEMLP_EMAIL_OUT] (
|
||||
[REMINDER_TYPE_ID]
|
||||
,[SENDING_PROFILE]
|
||||
,[REFERENCE_ID]
|
||||
,[REFERENCE_STRING]
|
||||
,[WF_ID]
|
||||
,[EMAIL_ADRESS]
|
||||
,[EMAIL_SUBJ]
|
||||
,[EMAIL_BODY]
|
||||
,[COMMENT]
|
||||
,[ADDED_WHO]
|
||||
,EMAIL_ATTMT1)
|
||||
VALUES
|
||||
(77
|
||||
,{pEmailAccountId}
|
||||
,{oHistoryID}
|
||||
,'{MessageId}'
|
||||
,77
|
||||
,'{oEmailTo}'
|
||||
,'{oSubject}'
|
||||
,'{oFinalBodyText}'
|
||||
,'{SourceProcedure}'
|
||||
,'{oCreatedWho}'
|
||||
,'{oAttachment}')"
|
||||
_mssql.ExecuteNonQuery(oInsert)
|
||||
Else
|
||||
'If oDTResult.Rows.Count = 0 Then
|
||||
' _logger.Debug("Email has already been sent!!")
|
||||
'Else
|
||||
_logger.Warn("Could not get oHistoryID in AddToEmailQueueMSSQL!!")
|
||||
' End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Public Function GetEmailDataForMessageId(MessageId As String) As EmailData
|
||||
Dim oSQL = $"SELECT EMAIL_FROM, EMAIL_SUBJECT, EMAIL_ATTMT1 FROM TBEDM_EMAIL_PROFILER_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
|
||||
Try
|
||||
Dim oDatatable = _firebird.GetDatatable(oSQL)
|
||||
Dim oRow As DataRow
|
||||
|
||||
If oDatatable.Rows.Count = 0 Then
|
||||
_logger.Warn("Got no results for MessageId {0}", MessageId)
|
||||
Return Nothing
|
||||
ElseIf oDatatable.Rows.Count > 1 Then
|
||||
_logger.Warn("Got too many results for MessageId {0}. Using last row.", MessageId)
|
||||
End If
|
||||
|
||||
_logger.Debug("Got Email Data for FileId {0}", MessageId)
|
||||
oRow = oDatatable.Rows.Item(oDatatable.Rows.Count - 1)
|
||||
|
||||
Return New EmailData() With {
|
||||
.From = oRow.Item("EMAIL_FROM"),
|
||||
.Attachment = oRow.Item("EMAIL_ATTMT1"),
|
||||
.Subject = oRow.Item("EMAIL_SUBJECT")
|
||||
}
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Could not fetch Email Data for FileId {0}", MessageId)
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function GetOriginalEmailPath(OriginalEmailDirectory As String, MessageId As String) As String
|
||||
Dim oAttachmentDirectory = OriginalEmailDirectory
|
||||
Dim oAttachmentFile = MessageId & ".eml"
|
||||
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
|
||||
|
||||
If File.Exists(oAttachmentPath) Then
|
||||
Return oAttachmentPath
|
||||
Else
|
||||
_logger.Warn("Email File {0} does not exist. Empty String will be returned.", oAttachmentPath)
|
||||
Return String.Empty
|
||||
End If
|
||||
End Function
|
||||
|
||||
Public Function GetEmailPathWithSubjectAsName(RejectedEmailDirectory As String, UncleanedSubject As String) As String
|
||||
Dim oCleanSubject = String.Join("", UncleanedSubject.Split(Path.GetInvalidPathChars()))
|
||||
Dim oAttachmentDirectory = RejectedEmailDirectory
|
||||
Dim oAttachmentFile = oCleanSubject & ".eml"
|
||||
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
|
||||
|
||||
Return oAttachmentPath
|
||||
End Function
|
||||
|
||||
Private Function RandomValue(lowerBound As Integer, upperBound As Integer) As Integer
|
||||
Dim oRandomValue = CInt(Math.Floor((upperBound - lowerBound + 1) * Rnd())) + lowerBound
|
||||
Return oRandomValue
|
||||
End Function
|
||||
End Class
|
||||
@@ -1,825 +0,0 @@
|
||||
Imports System.Collections.Generic
|
||||
Imports System.Data
|
||||
Imports System.IO
|
||||
Imports System.Linq
|
||||
Imports System.Security.Cryptography
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Interfaces
|
||||
Imports DigitalData.Modules.Interfaces.Exceptions
|
||||
Imports DigitalData.Modules.Jobs.Exceptions
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports FirebirdSql.Data.FirebirdClient
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Public Class ImportZUGFeRDFiles
|
||||
Implements IJob
|
||||
|
||||
Public Const ZUGFERD_IN = "ZUGFeRD in"
|
||||
Public Const ZUGFERD_ERROR = "ZUGFeRD Error"
|
||||
Public Const ZUGFERD_SUCCESS = "ZUGFeRD Success"
|
||||
Public Const ZUGFERD_EML = "ZUGFeRD Eml"
|
||||
Public Const ZUGFERD_REJECTED_EML = "ZUGFeRD Eml Rejected"
|
||||
Public Const ZUGFERD_ATTACHMENTS = "ZUGFeRD Attachments"
|
||||
Public Const ZUGFERD_NO_ZUGFERD = "Non-ZUGFeRD Files"
|
||||
|
||||
Public HISTORY_ID As Integer
|
||||
|
||||
Private Const DIRECTORY_DONT_MOVE = "DIRECTORY_DONT_MOVE"
|
||||
|
||||
|
||||
' List of allowed extensions for PDF/A Attachments
|
||||
' This list should not contain xml so the zugferd xml file will be filtered out
|
||||
Private ReadOnly AllowedExtensions As List(Of String) = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"}
|
||||
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _zugferd As ZUGFeRDInterface
|
||||
Private ReadOnly _firebird As Firebird
|
||||
Private ReadOnly _filesystem As Filesystem.File
|
||||
Private ReadOnly _EmailOutAccountId As Integer
|
||||
Private ReadOnly _mssql As MSSQLServer
|
||||
Private ReadOnly _email As EmailFunctions
|
||||
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, pEmailOutAccount As Integer, pPortalName As String, Optional MSSQL As MSSQLServer = Nothing)
|
||||
_logConfig = LogConfig
|
||||
_logger = LogConfig.GetLogger()
|
||||
_firebird = Firebird
|
||||
_filesystem = New Filesystem.File(_logConfig)
|
||||
_mssql = MSSQL
|
||||
_EmailOutAccountId = pEmailOutAccount
|
||||
_email = New EmailFunctions(LogConfig, _mssql, _firebird)
|
||||
|
||||
_logger.Debug("Registering GDPicture License")
|
||||
If _mssql IsNot Nothing Then
|
||||
Dim oSQL = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'"
|
||||
Dim oLicenseKey As String = _mssql.GetScalarValue(oSQL)
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig, oLicenseKey)
|
||||
Else
|
||||
_logger.Warn("GDPicture License could not be registered! MSSQL is not enabled!")
|
||||
Throw New ArgumentNullException("MSSQL")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
Private Function MoveAndRenameEmailToRejected(Args As WorkerArgs, MessageId As String) As EmailData
|
||||
Dim oEmailData = _email.GetEmailDataForMessageId(MessageId)
|
||||
Dim oSource = _email.GetOriginalEmailPath(Args.OriginalEmailDirectory, MessageId)
|
||||
Dim oDateSubDirectoryName As String = Now.ToString("yyyy-MM-dd")
|
||||
Dim oDestination As String
|
||||
|
||||
Dim oRejectedDirectory As String = Path.Combine(Args.RejectedEmailDirectory, oDateSubDirectoryName)
|
||||
|
||||
' Create the destination directory if it does not exist
|
||||
If Not Directory.Exists(oRejectedDirectory) Then
|
||||
Try
|
||||
Directory.CreateDirectory(oRejectedDirectory)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End If
|
||||
|
||||
' If oEmailData is Nothing, TBEDM_EMAIL_PROFILER_HISTORY for MessageId was not found.
|
||||
' This only should happen when testing and db-tables are deleted frequently
|
||||
If oEmailData Is Nothing Then
|
||||
oDestination = _email.GetEmailPathWithSubjectAsName(oRejectedDirectory, MessageId)
|
||||
Else
|
||||
oDestination = _email.GetEmailPathWithSubjectAsName(oRejectedDirectory, oEmailData.Subject)
|
||||
End If
|
||||
|
||||
_logger.Debug("Destination for eml file is {0}", oDestination)
|
||||
|
||||
Dim oFinalFileName = _filesystem.GetVersionedFilename(oDestination)
|
||||
|
||||
_logger.Debug("Versioned filename for eml file is {0}", oFinalFileName)
|
||||
|
||||
If oEmailData Is Nothing Then
|
||||
_logger.Warn("Could not get Email Data from firebird-database. File {0} will not be moved!", oSource)
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
Try
|
||||
_logger.Info("Moving email from {0} to {1}", oSource, oFinalFileName)
|
||||
IO.File.Move(oSource, oFinalFileName)
|
||||
oEmailData.Attachment = oFinalFileName
|
||||
Catch ex As Exception
|
||||
_logger.Warn("File {0} could not be moved! Original Filename will be used!", oSource)
|
||||
_logger.Error(ex)
|
||||
oEmailData.Attachment = oSource
|
||||
End Try
|
||||
|
||||
Return oEmailData
|
||||
End Function
|
||||
|
||||
Private Sub AddRejectedState(oMessageID As String, oTitle As String, oTitle1 As String, oComment As String, Transaction As SqlTransaction)
|
||||
Try
|
||||
'PRCUST_ADD_HISTORY_STATE: @MessageID VARCHAR(250), @TITLE1 VARCHAR(250), @TITLE2 VARCHAR(250)
|
||||
Dim oSQL = $"EXEC PRCUST_ADD_HISTORY_STATE '{oMessageID}','{oTitle}','{oTitle1}','{oComment.Replace("'", "''")}'"
|
||||
_mssql.ExecuteNonQuery(oSQL, Transaction)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Public Sub Start(Arguments As Object) Implements IJob.Start
|
||||
Dim oArgs As WorkerArgs = Arguments
|
||||
Dim oPropertyExtractor = New PropertyValues(_logConfig)
|
||||
Dim oAttachmentExtractor = New PDFEmbeds(_logConfig)
|
||||
|
||||
_logger.Debug("Starting Job {0}", [GetType].Name)
|
||||
|
||||
Try
|
||||
For Each oPath As String In oArgs.WatchDirectories
|
||||
Dim oDirInfo As New DirectoryInfo(oPath)
|
||||
|
||||
_logger.Debug($"Start processing directory {oDirInfo.FullName}")
|
||||
|
||||
If oDirInfo.Exists Then
|
||||
' Filter out *.lock files
|
||||
Dim oFiles As List(Of FileInfo) = oDirInfo.
|
||||
GetFiles().
|
||||
Where(Function(f) Not f.Name.EndsWith(".lock")).
|
||||
ToList()
|
||||
Dim oFileCount = oFiles.Count
|
||||
Dim oCurrentFileCount = 0
|
||||
|
||||
If oFileCount = 0 Then
|
||||
_logger.Debug("No files to process.")
|
||||
Continue For
|
||||
Else
|
||||
_logger.Info("Found {0} files", oFileCount)
|
||||
End If
|
||||
|
||||
' Group files by messageId
|
||||
Dim oGrouped As Dictionary(Of String, List(Of FileInfo)) = _zugferd.FileGroup.GroupFiles(oFiles)
|
||||
|
||||
_logger.Info("Found {0} file groups", oGrouped.Count)
|
||||
|
||||
' Process each file group together
|
||||
For Each oFileGroup In oGrouped
|
||||
' Start a new transaction for each file group.
|
||||
' This way we can rollback database changes for the whole filegroup in case something goes wrong.
|
||||
Dim oFBConnection As FbConnection = _firebird.GetConnection()
|
||||
Dim oFBTransaction As FbTransaction = oFBConnection.BeginTransaction()
|
||||
|
||||
Dim oSQLConnection As SqlConnection = _mssql.GetConnection()
|
||||
Dim oSQLTransaction As SqlTransaction = oSQLConnection?.BeginTransaction()
|
||||
|
||||
If oSQLConnection Is Nothing Then
|
||||
_logger.Warn("SQL Connection was not set. No INSERTs for MSSQL Server will be performed!")
|
||||
oArgs.InsertIntoSQLServer = False
|
||||
End If
|
||||
|
||||
' Count the amount of ZUGFeRD files
|
||||
Dim oZUGFeRDCount As Integer = 0
|
||||
|
||||
' Set the default Move Directory
|
||||
Dim oMoveDirectory As String = oArgs.ErrorDirectory
|
||||
|
||||
' Flag to save if the whole process was a success.
|
||||
' Will be set only at the end of the function if no error occurred.
|
||||
Dim oIsSuccess As Boolean = False
|
||||
|
||||
' Flag to save if the occurred error (if any) was expected
|
||||
' Used to determine if transactions should be committed or not
|
||||
Dim oExpectedError As Boolean = True
|
||||
|
||||
' Create file lists
|
||||
Dim oFileGroupFiles As List(Of FileInfo) = oFileGroup.Value
|
||||
Dim oEmailAttachmentFiles As New List(Of FileInfo)
|
||||
Dim oEmbeddedAttachmentFiles As New List(Of PDFEmbeds.EmbeddedFile)
|
||||
|
||||
Dim oMessageId As String = oFileGroup.Key
|
||||
Dim oMissingProperties As New List(Of String)
|
||||
Dim oMD5CheckSum As String = String.Empty
|
||||
|
||||
_logger.NewBlock($"Message Id {oMessageId}")
|
||||
_logger.Info("Start processing file group {0}", oMessageId)
|
||||
|
||||
Try
|
||||
For Each oFile In oFileGroupFiles
|
||||
' 09.12.2021: oDocument is now an Object, because have different classes corresponding to the
|
||||
' different versions of ZUGFeRD and the type is unknown at compile-time.
|
||||
Dim oDocument As Object
|
||||
|
||||
' Start a global group counter for each file
|
||||
Dim oGlobalGroupCounter = 0
|
||||
' Clear missing properties for the new file
|
||||
oMissingProperties = New List(Of String)
|
||||
oCurrentFileCount += 1
|
||||
|
||||
' Only pdf files are allowed from here on
|
||||
If Not oFile.Name.ToUpper.EndsWith(".PDF") Then
|
||||
_logger.Debug("Skipping non-pdf file {0}", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
|
||||
' Checking filesize for attachment files
|
||||
If Check_FileSize(oFile, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
|
||||
Continue For
|
||||
End If
|
||||
|
||||
_logger.Info("Start processing file {0}", oFile.Name)
|
||||
|
||||
' Checking filesize for pdf files
|
||||
If Check_FileSize(oFile, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
|
||||
Try
|
||||
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFile.FullName)
|
||||
Catch ex As ZUGFeRDExecption
|
||||
Select Case ex.ErrorType
|
||||
Case ZUGFeRDInterface.ErrorType.NoZugferd
|
||||
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
Continue For
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.NoValidZugferd
|
||||
_logger.Warn("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name)
|
||||
Throw New InvalidFerdException()
|
||||
|
||||
Case Else
|
||||
_logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", oFile.Name)
|
||||
Throw ex
|
||||
End Select
|
||||
End Try
|
||||
|
||||
' Extract all attachments with the extensions specified in `AllowedExtensions`.
|
||||
' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
|
||||
' Right now the zugferd-invoice.xml is filtered out because `AllowedExtensions` does not contain `xml`.
|
||||
Dim oAttachments = oAttachmentExtractor.Extract(oFile.FullName, AllowedExtensions)
|
||||
If oAttachments Is Nothing Then
|
||||
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
|
||||
Else
|
||||
oEmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
End If
|
||||
|
||||
' Check the Checksum and rejection status
|
||||
oMD5CheckSum = GenerateAndCheck_MD5Sum(oFile.FullName, oArgs.IgnoreRejectionStatus)
|
||||
|
||||
' Check if there are more than one ZUGFeRD files
|
||||
If oZUGFeRDCount = 1 Then
|
||||
Throw New TooMuchFerdsException()
|
||||
End If
|
||||
|
||||
' Since extraction went well, increase the amount of ZUGFeRD files
|
||||
oZUGFeRDCount += 1
|
||||
|
||||
' Check the document against the configured property map and return:
|
||||
' - a List of valid properties
|
||||
' - a List of missing properties
|
||||
Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument, oArgs.PropertyMap, oMessageId)
|
||||
|
||||
_logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count)
|
||||
|
||||
If oCheckResult.MissingProperties.Count > 0 Then
|
||||
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
|
||||
oMissingProperties = oCheckResult.MissingProperties
|
||||
Throw New MissingValueException(oFile)
|
||||
End If
|
||||
|
||||
_logger.Debug("No missing properties found. Continuing.")
|
||||
|
||||
Dim oDelSQL = $"DELETE FROM TBEDMI_ITEM_VALUE where REFERENCE_GUID = '{oMessageId}'"
|
||||
Dim oStep As String
|
||||
|
||||
oStep = "Firebird TBEDMI_ITEM_VALUE Delete messageID Items"
|
||||
Try
|
||||
_firebird.ExecuteNonQueryWithConnection(oDelSQL, oFBConnection, Firebird.TransactionMode.ExternalTransaction, oFBTransaction)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Step [{0}] with SQL [{1}] was not successful.", oStep, oDelSQL)
|
||||
End Try
|
||||
|
||||
If oArgs.InsertIntoSQLServer = True Then
|
||||
oStep = "MSSQL TBEDMI_ITEM_VALUE Delete messageID Items"
|
||||
Try
|
||||
_mssql.ExecuteNonQueryWithConnectionObject(oDelSQL, oSQLConnection, MSSQLServer.TransactionMode.ExternalTransaction, oSQLTransaction)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Step [{0}] with SQL [{1}] was not successful.", oStep, oDelSQL)
|
||||
End Try
|
||||
End If
|
||||
|
||||
For Each oProperty In oCheckResult.ValidProperties
|
||||
Dim oGroupCounterValue = oProperty.GroupCounter
|
||||
|
||||
' If GroupCounter is -1, it means this is a default property that can only occur once.
|
||||
' Set the actual inserted value to 0
|
||||
If oGroupCounterValue = -1 Then
|
||||
oGroupCounterValue = 0
|
||||
End If
|
||||
|
||||
Dim oCommand = $"INSERT INTO {oProperty.TableName} (REFERENCE_GUID, ITEM_DESCRIPTION, ITEM_VALUE, GROUP_COUNTER,SPEC_NAME,IS_REQUIRED) VALUES
|
||||
('{oMessageId}', '{oProperty.Description}', '{oProperty.Value.Replace("'", "''")}', {oGroupCounterValue},'{oProperty.TableColumn}','{oProperty.ISRequired}')"
|
||||
_logger.Debug("Mapping Property [{0}] with value [{1}], Will be inserted into table [{2}]", oProperty.TableColumn, oProperty.Value.Replace("'", "''"), oProperty.TableName)
|
||||
' Insert into SQL Server
|
||||
If oArgs.InsertIntoSQLServer = True Then
|
||||
Dim oResult = _mssql.ExecuteNonQueryWithConnectionObject(oCommand, oSQLConnection, MSSQLServer.TransactionMode.ExternalTransaction, oSQLTransaction)
|
||||
If oResult = False Then
|
||||
_logger.Warn($"SQL Command [{oCommand}] was not successful. Check the log.")
|
||||
End If
|
||||
End If
|
||||
' Insert into Firebird
|
||||
_firebird.ExecuteNonQueryWithConnection(oCommand, oFBConnection, Firebird.TransactionMode.ExternalTransaction, oFBTransaction)
|
||||
Next
|
||||
Next
|
||||
|
||||
'Check if there are no ZUGFeRD files
|
||||
If oZUGFeRDCount = 0 Then
|
||||
' If NonZugferdDirectory is not set, a NoFerdsException will be thrown and a rejection will be generated
|
||||
' This is the default/initial behaviour.
|
||||
If oArgs.NonZugferdDirectory Is Nothing OrElse oArgs.NonZugferdDirectory = String.Empty Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
' Also, if the directory is set but does not exist, still a rejection will be generated.
|
||||
If Not IO.Directory.Exists(oArgs.NonZugferdDirectory) Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
' Only if the directory is set and does exist, it will be used and any file groups which
|
||||
' do NOT CONTAIN ANY ZUGFERD DOCUMENTS, are moved to that directory.
|
||||
Throw New NoFerdsAlternateException()
|
||||
|
||||
End If
|
||||
|
||||
'If no errors occurred...
|
||||
'Log the History
|
||||
If oMD5CheckSum <> String.Empty Then
|
||||
Create_HistoryEntry(oMessageId, oMD5CheckSum, "SUCCESS", oFBTransaction)
|
||||
|
||||
'Dim oInsertCommand = $"INSERT INTO TBEDM_ZUGFERD_HISTORY_IN (MESSAGE_ID, MD5HASH) VALUES ('{oMessageId}', '{oMD5CheckSum}')"
|
||||
'_firebird.ExecuteNonQueryWithConnection(oInsertCommand, oFBConnection, Firebird.TransactionMode.ExternalTransaction, oFBTransaction)
|
||||
'' History ID is only need in case of an error
|
||||
'oFBTransaction.Commit()
|
||||
'Try
|
||||
' Dim oSQL = $"SELECT MAX(GUID) FROM TBEDM_ZUGFERD_HISTORY_IN WHERE MESSAGE_ID = '{oMessageId}'"
|
||||
' HISTORY_ID = _firebird.GetScalarValue(oSQL)
|
||||
'Catch ex As Exception
|
||||
' HISTORY_ID = 0
|
||||
'End Try
|
||||
Else
|
||||
Create_HistoryEntry(oMessageId, String.Empty, "SUCCESS (with empty MD5Hash)", oFBTransaction)
|
||||
End If
|
||||
|
||||
oIsSuccess = True
|
||||
oMoveDirectory = oArgs.SuccessDirectory
|
||||
|
||||
Catch ex As MD5HashException
|
||||
_logger.Error(ex)
|
||||
|
||||
Dim oMessage = "REJECTED - Already processed (MD5Hash)"
|
||||
Update_HistoryEntry(oMessageId, oMD5CheckSum, oMessage, oFBTransaction)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_MD5_ERROR
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "", oSQLTransaction)
|
||||
|
||||
Catch ex As InvalidFerdException
|
||||
_logger.Error(ex)
|
||||
|
||||
' When InvalidFerdException is thrown, we don't have a MD5Hash yet.
|
||||
' That 's why we set it to String.Empty here.
|
||||
Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but incorrect format", oFBTransaction)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "", oSQLTransaction)
|
||||
|
||||
Catch ex As TooMuchFerdsException
|
||||
_logger.Error(ex)
|
||||
|
||||
Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - More than one ZUGFeRD-document in email", oFBTransaction)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "", oSQLTransaction)
|
||||
|
||||
Catch ex As NoFerdsException
|
||||
_logger.Error(ex)
|
||||
|
||||
Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - no ZUGFeRD-Document in email", oFBTransaction)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_NO_FERDS
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "", oSQLTransaction)
|
||||
|
||||
Catch ex As NoFerdsAlternateException
|
||||
' TODO: Maybe dont even log this 'error', since it's not really an error and it might happen *A LOT*
|
||||
_logger.Error(ex)
|
||||
oMoveDirectory = oArgs.NonZugferdDirectory
|
||||
|
||||
Catch ex As MissingValueException
|
||||
_logger.Error(ex)
|
||||
|
||||
Dim oMessage As String = ""
|
||||
For Each prop In oMissingProperties
|
||||
oMessage &= $"- {prop}"
|
||||
Next
|
||||
|
||||
Create_HistoryEntry(oMessageId, oMD5CheckSum, $"REJECTED - Missing Required Properties: [{oMessage}]", oFBTransaction)
|
||||
|
||||
Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage, oSQLTransaction)
|
||||
|
||||
Catch ex As FileSizeLimitReachedException
|
||||
_logger.Error(ex)
|
||||
|
||||
Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - File size limit reached", oFBTransaction)
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
|
||||
Dim oKey = FileSizeLimitReachedException.KEY_FILENAME
|
||||
Dim oFileExceedingThreshold As String = IIf(ex.Data.Contains(oKey), ex.Data.Item(oKey), "")
|
||||
Dim oFileWithoutMessageId = oFileExceedingThreshold.
|
||||
Replace(oMessageId, "").
|
||||
Replace("~", "")
|
||||
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_FILE_SIZE_REACHED, oArgs.MaxAttachmentSizeInMegaBytes, oFileWithoutMessageId)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "FileSizeLimitReachedException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "FileSizeLimitReachedException", "Erlaubte Dateigröße überschritten", "", oSQLTransaction)
|
||||
|
||||
Catch ex As OutOfMemoryException
|
||||
_logger.Warn("OutOfMemory Error occurred: {0}", ex.Message)
|
||||
_logger.Error(ex)
|
||||
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = oArgs.ExceptionEmailAddress,
|
||||
.Subject = $"OutOfMemoryException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "OutOfMemoryException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
|
||||
' Rollback Firebird
|
||||
oFBTransaction.Rollback()
|
||||
|
||||
' Rollback MSSQL
|
||||
oSQLTransaction.Rollback()
|
||||
|
||||
oMoveDirectory = DIRECTORY_DONT_MOVE
|
||||
|
||||
oExpectedError = False
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Unknown Error occurred: {0}", ex.Message)
|
||||
_logger.Error(ex)
|
||||
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = oArgs.ExceptionEmailAddress,
|
||||
.Subject = $"UnhandledException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnhandledException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
|
||||
' Rollback Firebird
|
||||
oFBTransaction.Rollback()
|
||||
|
||||
' Rollback MSSQL
|
||||
oSQLTransaction.Rollback()
|
||||
|
||||
oMoveDirectory = DIRECTORY_DONT_MOVE
|
||||
|
||||
oExpectedError = False
|
||||
|
||||
Finally
|
||||
Try
|
||||
' If an application error occurred, dont move files so they will be processed again later
|
||||
If oMoveDirectory = DIRECTORY_DONT_MOVE Then
|
||||
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
|
||||
Else
|
||||
' Move all files of the current group
|
||||
MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
|
||||
End If
|
||||
_logger.Info("Finished processing file group {0}", oMessageId)
|
||||
Catch ex As Exception
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = oArgs.ExceptionEmailAddress,
|
||||
.Subject = $"FileMoveException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "FileMoveException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
|
||||
_logger.Warn("Could not move files!")
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
Finally
|
||||
_logger.EndBlock()
|
||||
End Try
|
||||
|
||||
Try
|
||||
' If everything went OK or an expected error occurred,
|
||||
' finally commit all changes To the Database
|
||||
' ==================================================================
|
||||
If oIsSuccess Or oExpectedError Then
|
||||
' Commit SQL Transaction
|
||||
oSQLTransaction.Commit()
|
||||
|
||||
' Commit Firebird Transaction
|
||||
oFBTransaction.Commit()
|
||||
End If
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Database Transactions were not committed successfully.")
|
||||
End Try
|
||||
|
||||
Try
|
||||
oFBConnection.Close()
|
||||
oSQLConnection.Close()
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Database Connections were not closed successfully.")
|
||||
End Try
|
||||
End Try
|
||||
Next
|
||||
End If
|
||||
Next
|
||||
|
||||
_logger.Debug("Finishing Job {0}", Me.GetType.Name)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Info("Job Failed! See error log for details")
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub MoveFiles(
|
||||
Args As WorkerArgs,
|
||||
MessageId As String,
|
||||
Files As List(Of FileInfo),
|
||||
AttachmentFiles As List(Of FileInfo),
|
||||
EmbeddedAttachments As List(Of PDFEmbeds.EmbeddedFile),
|
||||
MoveDirectory As String,
|
||||
IsSuccess As Boolean)
|
||||
|
||||
Dim oFinalMoveDirectory As String = MoveDirectory
|
||||
Dim oDateSubDirectoryName As String = Now.ToString("yyyy\\MM\\dd")
|
||||
Dim oAttachmentDirectory As String = Path.Combine(oFinalMoveDirectory, Args.AttachmentsSubDirectory, oDateSubDirectoryName)
|
||||
|
||||
' Files will be moved to a subfolder for the current day if they are rejected
|
||||
If Not IsSuccess Then
|
||||
oFinalMoveDirectory = Path.Combine(oFinalMoveDirectory, oDateSubDirectoryName)
|
||||
End If
|
||||
|
||||
' Create directories if they don't exist
|
||||
If Not Directory.Exists(oFinalMoveDirectory) Then
|
||||
Try
|
||||
Directory.CreateDirectory(oFinalMoveDirectory)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End If
|
||||
|
||||
If Not Directory.Exists(oAttachmentDirectory) And AttachmentFiles.Count > 0 Then
|
||||
Try
|
||||
Directory.CreateDirectory(oAttachmentDirectory)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End If
|
||||
|
||||
' Filter out Attachments from `Files`
|
||||
Dim oInvoiceFiles As List(Of FileInfo) = Files.Except(AttachmentFiles).ToList()
|
||||
|
||||
' Move PDF/A Files
|
||||
For Each oFile In oInvoiceFiles
|
||||
Try
|
||||
Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name))
|
||||
|
||||
_filesystem.MoveTo(oFile.FullName, oFilePath, oFinalMoveDirectory)
|
||||
|
||||
_logger.Info("File moved to {0}", oFilePath)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Could not move file {0}", oFile.FullName)
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
Next
|
||||
|
||||
' Move non-PDF/A Email Attachments/Files
|
||||
For Each oFile In AttachmentFiles
|
||||
Try
|
||||
Dim oFilePath = _filesystem.GetVersionedFilename(Path.Combine(oAttachmentDirectory, oFile.Name))
|
||||
|
||||
_filesystem.MoveTo(oFile.FullName, oFilePath, oAttachmentDirectory)
|
||||
_logger.Info("Attachment moved to {0}", oFilePath)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Could not move attachment {0}", oFile.FullName)
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
Next
|
||||
|
||||
' Write Embedded Files to disk
|
||||
For Each oResult In EmbeddedAttachments
|
||||
Try
|
||||
Dim oFileName As String = $"{MessageId}~{oResult.FileName}"
|
||||
Dim oFilePath As String = Path.Combine(oAttachmentDirectory, oFileName)
|
||||
|
||||
If Not File.Exists(oAttachmentDirectory) Then
|
||||
Directory.CreateDirectory(oAttachmentDirectory)
|
||||
End If
|
||||
|
||||
Using oWriter As New FileStream(oFilePath, FileMode.Create)
|
||||
oWriter.Write(oResult.FileContents, 0, oResult.FileContents.Length)
|
||||
_logger.Info("Embedded Attachment moved to {0}", oFilePath)
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Could not save embedded attachment {0}", oResult.FileName)
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
Next
|
||||
|
||||
_logger.Info("Finished moving files")
|
||||
End Sub
|
||||
|
||||
|
||||
Private Function CreateBodyForMissingProperties(OriginalFilename As String, MissingProperties As List(Of String)) As String
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_MISSINGPROPERTIES_1, OriginalFilename)
|
||||
|
||||
If MissingProperties.Count > 0 Then
|
||||
oBody &= $"{vbNewLine}{vbNewLine}"
|
||||
oBody &= EmailStrings.EMAIL_MISSINGPROPERTIES_2
|
||||
oBody &= $"{vbNewLine}{vbNewLine}"
|
||||
|
||||
For Each prop In MissingProperties
|
||||
oBody &= $"- {prop}"
|
||||
Next
|
||||
End If
|
||||
|
||||
Return oBody
|
||||
End Function
|
||||
|
||||
Private Function CreateBodyForUnhandledException(MessageId As String, Exception As Exception) As String
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_UNHANDLED_EXCEPTION, MessageId, Exception.Message, Exception.StackTrace)
|
||||
|
||||
Return oBody
|
||||
End Function
|
||||
|
||||
Private Function CreateMD5(ByVal Filename As String) As String
|
||||
Try
|
||||
Dim oMD5 As New MD5CryptoServiceProvider
|
||||
Dim oHash As Byte()
|
||||
Dim oHashString As String
|
||||
Dim oResult As String = ""
|
||||
|
||||
Using oFileStream As New FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
|
||||
oHash = oMD5.ComputeHash(oFileStream)
|
||||
oHashString = BitConverter.ToString(oHash)
|
||||
End Using
|
||||
|
||||
oResult = oHashString.Replace("-", "")
|
||||
Return oResult
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
Return ""
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function Create_HistoryEntry(MessageId As String, MD5Checksum As String, Message As String, Transaction As FbTransaction) As Boolean
|
||||
Try
|
||||
Dim oConnection = _firebird.GetConnection()
|
||||
Dim oSQL = $"INSERT INTO TBEDM_ZUGFERD_HISTORY_IN (COMMENT, MD5HASH, MESSAGE_ID) VALUES ('{Message}', '{MD5Checksum}', '{MessageId}')"
|
||||
|
||||
' 09.07.2021: This can't be in the transaction since the history
|
||||
' Entry needs to be accessed by MoveAndRenameEmailToRejected shortly after
|
||||
_firebird.ExecuteNonQueryWithConnection(oSQL, oConnection, Firebird.TransactionMode.WithTransaction)
|
||||
|
||||
' Close the connection
|
||||
oConnection.Close()
|
||||
If Message.Contains("REJECTED") Then
|
||||
oSQL = $"UPDATE TBEMLP_HISTORY SET STATUS = 'REJECTED', COMMENT = '{Message}', CUST_REJECTED = 1,CUST_REJECTED_WHEN = GETDATE() WHERE EMAIL_MSGID = '{MessageId}'"
|
||||
_mssql.ExecuteNonQuery(oSQL)
|
||||
End If
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
_logger.Warn("History Entry count not be created for message id [{0}] and md5 [{1}]", MessageId, MD5Checksum)
|
||||
_logger.Error(ex)
|
||||
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function Update_HistoryEntry(MessageId As String, MD5Checksum As String, Message As String, Transaction As FbTransaction) As Boolean
|
||||
Try
|
||||
Dim oConnection = _firebird.GetConnection()
|
||||
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = '{Message}' WHERE MD5HASH = '{MD5Checksum}' AND MESSAGE_ID = '{MessageId}'"
|
||||
|
||||
_firebird.ExecuteNonQueryWithConnection(oSQL, oConnection, Firebird.TransactionMode.WithTransaction)
|
||||
|
||||
' Close the connection
|
||||
oConnection.Close()
|
||||
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
_logger.Warn("History Entry count not be updated for message id [{0}] and md5 [{1}]", MessageId, MD5Checksum)
|
||||
_logger.Error(ex)
|
||||
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Generates the MD5 Checksum of a file and checks it against the histroy table TBEDM_ZUGFERD_HISTORY_IN
|
||||
''' </summary>
|
||||
''' <param name="pFilePath">The path of the file to be checked</param>
|
||||
''' <param name="pIgnoreRejectionStatus">Should the check take into account the rejection status of the file?</param>
|
||||
''' <returns>The MD5 Checksum of the file, or an empty string, if the Checksum could not be created</returns>
|
||||
''' <exception cref="MD5HashException">Throws, when the file should be rejected, ie. if it already exists in the table</exception>
|
||||
Private Function GenerateAndCheck_MD5Sum(pFilePath As String, pIgnoreRejectionStatus As Boolean) As String
|
||||
Dim oMD5CheckSum = CreateMD5(pFilePath)
|
||||
|
||||
' Exit if MD5 could not be created
|
||||
If oMD5CheckSum = String.Empty Then
|
||||
_logger.Warn("MD5 Checksum is nothing for file [{0}]!", pFilePath)
|
||||
Return oMD5CheckSum
|
||||
End If
|
||||
|
||||
' Check if Checksum exists in History Table
|
||||
Dim oCheckCommand = $"SELECT * FROM TBEDM_ZUGFERD_HISTORY_IN WHERE GUID = (SELECT MAX(GUID) FROM TBEDM_ZUGFERD_HISTORY_IN WHERE UPPER(MD5HASH) = UPPER('{oMD5CheckSum}'))"
|
||||
Dim oTable As DataTable = _firebird.GetDatatable(oCheckCommand, Firebird.TransactionMode.NoTransaction)
|
||||
|
||||
' If History entries could not be fetched, just return the MD5 Checksum
|
||||
If IsNothing(oTable) Then
|
||||
_logger.Warn("Be careful: oExistsDT is nothing for file [{0}]!", pFilePath)
|
||||
Return oMD5CheckSum
|
||||
End If
|
||||
|
||||
' If Checksum does not exist in History entries, just return the MD5 Checksum
|
||||
If oTable.Rows.Count = 0 Then
|
||||
_logger.Debug("File [{0}] was not found in History!", pFilePath)
|
||||
Return oMD5CheckSum
|
||||
End If
|
||||
|
||||
' ====================================================
|
||||
' Checksum exists in History entries, reject!
|
||||
' ====================================================
|
||||
|
||||
Dim oRejected As Boolean
|
||||
Dim oHistoryId As Integer
|
||||
|
||||
' Try to read Rejected Status and History Id
|
||||
Try
|
||||
Dim oRow As DataRow = oTable.Rows.Item(0)
|
||||
oRejected = DirectCast(oRow.Item("REJECTED"), Boolean)
|
||||
oHistoryId = oRow.Item("GUID")
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Error while converting REJECTED: " & ex.Message)
|
||||
oRejected = False
|
||||
|
||||
End Try
|
||||
_logger.Info("File has already been processed...")
|
||||
' If the file was already rejected, it is allowed to be processed again,
|
||||
' even if the Checksum exists in the history entries (default case)
|
||||
' Which means, if it was not rejected before, it will be rejected in any case!
|
||||
'
|
||||
' This logic can be overwritten by the IgnoreRejectionStatus parameter.
|
||||
' If it is set to true, the file will be rejected if the file exists in the history entries,
|
||||
' regardless of the rejected parameter.
|
||||
If oRejected = True And pIgnoreRejectionStatus = True Then
|
||||
_logger.Info("ZuGFeRDFile already has been processed, but formerly obviously was rejected!")
|
||||
Else
|
||||
Throw New MD5HashException($"There is already an identical invoice! - HistoryID [{oHistoryId}]")
|
||||
End If
|
||||
|
||||
Return oMD5CheckSum
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' Checks the size of the supplied file.
|
||||
''' </summary>
|
||||
''' <param name="pFileInfo"></param>
|
||||
''' <param name="pMaxFileSizeInMegaBytes"></param>
|
||||
''' <returns></returns>
|
||||
Private Function Check_FileSize(pFileInfo As FileInfo, pMaxFileSizeInMegaBytes As Integer) As Boolean
|
||||
_logger.Info("Checking Filesize of {0}", pFileInfo.Name)
|
||||
_logger.Debug("Filesize threshold is {0} MB.", pMaxFileSizeInMegaBytes)
|
||||
|
||||
If pMaxFileSizeInMegaBytes <= 0 Then
|
||||
_logger.Debug("Filesize is not configured. Skipping check.")
|
||||
Return True
|
||||
End If
|
||||
|
||||
Dim oMaxSize = pMaxFileSizeInMegaBytes * 1024 * 1024
|
||||
|
||||
If oMaxSize > 0 And pFileInfo.Length > oMaxSize Then
|
||||
_logger.Debug("Filesize is bigger than threshold. Rejecting.")
|
||||
Return False
|
||||
Else
|
||||
_logger.Debug("Filesize is smaller than threshold. All fine.")
|
||||
Return True
|
||||
End If
|
||||
End Function
|
||||
End Class
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user