Modules/Windows/FileDrop.vb
2025-10-01 15:17:45 +02:00

364 lines
12 KiB
VB.net

Imports System.Text
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
'Imports DigitalData.Modules.Language.Utils
Imports Microsoft.Office.Interop
Imports System.Windows.Forms
Partial Public Class FileDrop
Inherits BaseClass
Public Enum FileFormat
OutlookAttachment
OutlookMail
ThunderbirdAttachment
ThunderbirdMail
MailWithoutAttachments
LocalFile
Unknown
End Enum
Public Enum FileSource
DragDrop
FolderWatch
Attachment
End Enum
Public ReadOnly Property TempFileSubDirectory
Get
Return _TempFileSubDirectory
End Get
End Property
Private _TempFileSubDirectory As String = "FileDrop"
Public Sub New(pLogConfig As LogConfig)
MyBase.New(pLogConfig)
End Sub
Public Sub New(pLogConfig As LogConfig, pTempFileSubDirectory As String)
MyClass.New(pLogConfig)
_TempFileSubDirectory = pTempFileSubDirectory
End Sub
Public Function GetFileFormats(pEvent As DragEventArgs) As List(Of String)
Dim oFormats As New List(Of String)
For Each oFormat As String In pEvent.Data.GetFormats(False)
oFormats.Add(oFormat)
Next
Return oFormats
End Function
Public Function GetFileFormat(pEvent As DragEventArgs) As FileFormat
Logger.Debug("Determining FileFormat")
If IsThunderbird(pEvent) Then
Logger.Debug("File is a Thunderbird File")
If IsThunderbirdAttachment(pEvent) Then
Return FileFormat.ThunderbirdAttachment
ElseIf IsThunderbirdMail(pEvent) Then
Return FileFormat.ThunderbirdMail
Else
Return FileFormat.Unknown
End If
End If
If IsOutlook(pEvent) Then
Logger.Debug("File is an Outlook File")
If IsOutlookAttachment(pEvent) Then
Return FileFormat.OutlookAttachment
ElseIf IsOutlookMail(pEvent) Then
Return FileFormat.OutlookMail
Else
Return FileFormat.Unknown
End If
End If
If IsNormalFile(pEvent) Then
Logger.Debug("File is a normal File")
Return FileFormat.LocalFile
Else
Return FileFormat.Unknown
End If
End Function
Public Function GetFiles(pEvent As DragEventArgs) As List(Of DroppedFile)
Try
Dim oFormats As List(Of String) = GetFileFormats(pEvent)
Dim oFormatString = String.Join(", ", oFormats)
Logger.Debug("Available Formats: [{0}]", oFormatString)
Dim oFormat = GetFileFormat(pEvent)
Logger.Debug("Format: [{0}]", oFormat.ToString)
Dim oFiles As New List(Of DroppedFile)
Select Case oFormat
Case FileFormat.OutlookAttachment, FileFormat.OutlookMail
Dim oFilePaths = GetOutlookFilePath(pEvent)
For Each oPath In oFilePaths
oFiles.Add(New DroppedFile(oPath) With {
.FileFormat = oFormat
})
Next
Case Else
Dim oDroppedFiles As String() = GetFormat(pEvent, "FileDrop")
Dim oTempPath As String = GetTempPathWithSubdirectory()
If oDroppedFiles IsNot Nothing Then
For Each oPath In oDroppedFiles
oFiles.Add(New DroppedFile(oPath) With {
.FileFormat = oFormat
})
Next
End If
End Select
Logger.Debug("Handled [{0}] dropped files.", oFiles.Count)
Return oFiles
Catch ex As Exception
Logger.Warn("Error while handling dropped files.")
Logger.Error(ex)
Return Nothing
End Try
End Function
Private Function GetOutlookFilePath(pEvent As DragEventArgs) As List(Of String)
Dim oTempPath As String = GetTempPathWithSubdirectory()
Dim oFileName As String = GetOutlookFileName(pEvent)
Dim oFilePath As String = IO.Path.Combine(oTempPath, oFileName)
Dim oContentsList As List(Of Byte()) = GetOutlookFileContents_FromInterop(pEvent)
If oContentsList Is Nothing Then
Return Nothing
End If
Dim oPathList As New List(Of String)
For Each oContents In oContentsList
Using oFileStream As IO.FileStream = New IO.FileStream(oFilePath, IO.FileMode.Create)
oFileStream.Write(oContents, 0, oContents.Length)
oFileStream.Close()
End Using
oPathList.Add(oFilePath)
Next
Return oPathList
End Function
Private Function GetOutlookFileName(pEvent As DragEventArgs) As String
Dim oFileDescriptorSize = 512
Dim oIndex As Integer = 76
Dim oBuilder As New StringBuilder()
Using oStream As IO.MemoryStream = GetFormat(pEvent, "FileGroupDescriptor")
Dim oFileGroupDescriptor As Byte() = New Byte(oFileDescriptorSize) {}
oStream.Read(oFileGroupDescriptor, 0, oFileDescriptorSize)
While oFileGroupDescriptor(oIndex) <> 0
Dim oChar = Convert.ToChar(oFileGroupDescriptor(oIndex))
oBuilder.Append(oChar)
oIndex += 1
End While
End Using
Dim oFileName As String = oBuilder.ToString
Logger.Debug("Outlook filename is [{0}]", oFileName)
Return oFileName
End Function
Private Function GetOutlookFileContents_FromDragEvent(pEvent As DragEventArgs) As List(Of Byte())
Logger.Debug("Getting file contents")
Using oStream As IO.MemoryStream = pEvent.Data.GetData("FileContents", True)
If oStream Is Nothing Then
Return Nothing
End If
Dim oContentLength = Convert.ToInt32(oStream.Length)
Dim oContents As Byte() = New Byte(oContentLength) {}
oStream.Position = 0
oStream.Read(oContents, 0, Convert.ToInt32(oContentLength))
Return New List(Of Byte()) From {oContents}
End Using
End Function
Private Function GetOutlookFileContents_FromInterop(pEvent As DragEventArgs) As List(Of Byte())
Logger.Debug("Getting file contents")
Logger.Debug("Creating Outlook Application")
Dim oApp As Outlook.Application
Try
oApp = New Outlook.Application()
Catch ex As Exception
Logger.Error(ex)
Return Nothing
End Try
Dim oResults As New List(Of Byte())
Dim oMailItem As Outlook.MailItem
For oIndex As Integer = 1 To oApp.ActiveExplorer.Selection.Count
Try
Logger.Debug("Fetching mail [{0}]")
oMailItem = oApp.ActiveExplorer.Selection.Item(oIndex)
Dim oSubject As String = StringEx.ConvertTextToSlug(oMailItem.Subject)
If oSubject = "" Then
oSubject = "NO_SUBJECT"
End If
Logger.Info("Subject Slug: [{0}]", oSubject)
Dim oFileName As String = $"{oSubject}.msg"
Dim oTempPath As String = GetTempPathWithSubdirectory()
Dim oFilePath As String = IO.Path.Combine(oTempPath, oFileName)
oMailItem.SaveAs(oFilePath)
Using oFileStream As New IO.FileStream(oFilePath, IO.FileMode.Open)
Dim oContents As Byte() = New Byte(oFileStream.Length) {}
oFileStream.Read(oContents, 0, oFileStream.Length)
oResults.Add(oContents)
End Using
Try
IO.File.Delete(oFilePath)
Catch ex As Exception
Logger.Warn("Temp file [{0}] could not be deleted!", oFilePath)
Logger.Error(ex)
End Try
Return oResults
Catch ex As Exception
Logger.Error(ex)
End Try
Next
Return Nothing
End Function
Public Function GetFormat(pEvent As DragEventArgs, pFormat As String, pAutoConvert As Boolean) As Object
If CheckFor(pEvent, pFormat) Then
Dim oValue = pEvent.Data.GetData(pFormat, pAutoConvert)
Return oValue
Else
Return Nothing
End If
End Function
Public Function GetFormat(pEvent As DragEventArgs, pFormat As String) As Object
Return GetFormat(pEvent, pFormat, False)
End Function
Public Function CheckFor(pEvent As DragEventArgs, pFormat As String, pAutoConvert As Boolean) As Boolean
Dim oFormats = pEvent.Data.GetFormats(pAutoConvert).ToList()
Dim oFormatExists = oFormats.Any(Function(format) format = pFormat)
Logger.Debug("Format [{0}] exists: [{1}]", pFormat, oFormatExists)
Return oFormatExists
End Function
Public Function CheckFor(pEvent As DragEventArgs, pFormat As String) As Boolean
Return CheckFor(pEvent, pFormat, False)
End Function
Public Function IsNormalFile(e As DragEventArgs) As Boolean
Return CheckFor(e, DataFormats.FileDrop, False)
End Function
Public Function IsOutlook(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Outlook")
Return CheckFor(e, "FileGroupDescriptor") AndAlso CheckFor(e, "FileContents")
End Function
Public Function IsThunderbird(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Thunderbird")
Return CheckFor(e, "text/x-moz-url") AndAlso CheckFor(e, "FileDrop")
End Function
Public Sub RemoveTempDirectory()
Dim oTempPath As String = IO.Path.Combine(IO.Path.GetTempPath(), _TempFileSubDirectory)
If IO.Directory.Exists(oTempPath) Then
Try
IO.Directory.Delete(oTempPath, recursive:=True)
Catch ex As Exception
Logger.Warn("Could not delete Temp Subdirectory [{0}].", oTempPath)
Logger.Error(ex)
End Try
End If
End Sub
Private Function GetTempPathWithSubdirectory() As String
Dim oTempPath As String = IO.Path.Combine(IO.Path.GetTempPath(), _TempFileSubDirectory)
If IO.Directory.Exists(oTempPath) = False Then
Try
IO.Directory.CreateDirectory(oTempPath)
Catch ex As Exception
Logger.Warn("Could not create Temp Subdirectory [{0}]. Returning default Temp Path.", oTempPath)
Logger.Error(ex)
Return IO.Path.GetTempPath()
End Try
End If
Return oTempPath
End Function
#Region "Thunderbird"
Private Function IsOutlookMail(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Outlook Mail")
Return Not IsOutlookAttachment(e) AndAlso CheckFor(e, "RenPrivateSourceFolder")
End Function
Private Function IsOutlookAttachment(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Outlook Attachment")
Return IsOutlook(e) AndAlso CheckFor(e, "RenPrivateItem")
End Function
#End Region
#Region "Outlook"
Private Function IsThunderbirdMail(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Thunderbird Mail")
Return Not IsThunderbirdAttachment(e)
End Function
Private Function IsThunderbirdAttachment(e As DragEventArgs) As Boolean
Logger.Debug("Checking for Thunderbird Attachment")
Return IsThunderbird(e) AndAlso
CheckFor(e, "text/x-moz-url-data") AndAlso
CheckFor(e, "text/x-moz-url-desc")
End Function
#End Region
End Class