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 = 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