Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Jobs.Exceptions
Imports DigitalData.Modules.Logging
Imports System.Data
Imports System.IO
Imports System.Security.Cryptography
Public Class HashFunctions
Inherits BaseClass
Private ReadOnly Database As MSSQLServer
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer)
MyBase.New(pLogConfig)
Database = pDatabase
End Sub
'''
''' Generates the MD5 Checksum of a file and checks it against the histroy table TBEDM_ZUGFERD_HISTORY_IN
'''
''' The path of the file to be checked
''' Should the check take into account the rejection status of the file?
''' The MD5 Checksum of the file, or an empty string, if the Checksum could not be created
''' Throws, when the file should be rejected, ie. if it already exists in the table
Public Function GenerateAndCheck_MD5Sum(pFile As FileInfo, pMessageId As String, pIgnoreRejectionStatus As Boolean) As String
Dim oMD5CheckSum = CreateMD5(pFile.FullName)
' Exit if MD5 could not be created
If oMD5CheckSum = String.Empty Then
Logger.Warn("MD5 Checksum is nothing for file [{0}]!", pFile.FullName)
Return oMD5CheckSum
End If
' Check if Checksum exists in History Table
Dim oCheckCommand = $"SELECT * FROM TBEMLP_HISTORY WHERE GUID = (SELECT MAX(GUID) FROM TBEMLP_HISTORY WHERE UPPER(MD5HASH) = UPPER('{oMD5CheckSum}'))"
Dim oTable As DataTable = Database.GetDatatable(oCheckCommand, MSSQLServer.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}]!", pFile.FullName)
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!", pFile.FullName)
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 = oRow.ItemEx("CUST_REJECTED", False)
oHistoryId = oRow.Item("GUID")
Catch ex As Exception
Logger.Warn("Error while converting REJECTED: " & ex.Message)
oRejected = False
End Try
Dim oOriginalName As Object = GetOriginalFilename(pFile.Name)
Logger.Info("File with MessageId [{0}] and Filename [{1}] has already been processed.", pMessageId, oOriginalName)
' 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 Rejection Status will be ignored!")
ElseIf oRejected = False Then
Logger.Info("ZuGFeRDFile already has been processed. Will be rejected.")
Throw New MD5HashException($"There is already an identical invoice! - HistoryID [{oHistoryId}] - Case 1", oOriginalName)
Else
Logger.Info("ZuGFeRDFile already has been processed. Will be rejected.")
Throw New MD5HashException($"There is already an identical invoice! - HistoryID [{oHistoryId}] - Case 2", oOriginalName)
End If
Return oMD5CheckSum
End Function
Public Function GetOriginalFilename(pFilename As String) As String
' Try to get the original filename from Attachment table
' If this fails, falls back to the new filename (~Attm.ext)
Dim oSQL = $"SELECT EMAIL_ATTMT FROM TBEMLP_HISTORY_ATTACHMENT WHERE EMAIL_ATTMT_INDEX = '{pFilename}'"
Dim oEmailAttachment = Database.GetScalarValue(oSQL, MSSQLServer.TransactionMode.NoTransaction)
Dim oOriginalName = ObjectEx.NotNull(oEmailAttachment, pFilename)
Return oOriginalName
End Function
Private Function CreateMD5(pFilename 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(pFilename, 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
End Class