Advertisement
Guest User

Untitled

a guest
May 10th, 2017
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 30.64 KB | None | 0 0
  1. Imports System.Collections.Generic
  2. Imports System.Net
  3. Imports System.IO
  4. Imports System.Text.RegularExpressions
  5.  
  6.  
  7. Namespace Utilities
  8.  
  9. #Region "FTP client class"
  10.     ''' <summary>
  11.     ''' A wrapper class for .NET 2.0 FTP
  12.     ''' </summary>
  13.     ''' <remarks>
  14.     ''' This class does not hold open an FTP connection but
  15.     ''' instead is stateless: for each FTP request it
  16.     ''' connects, performs the request and disconnects.
  17.     ''' </remarks>
  18.     Public Class FTPclient
  19.  
  20. #Region "CONSTRUCTORS"
  21.         ''' <summary>
  22.         ''' Blank constructor
  23.         ''' </summary>
  24.         ''' <remarks>Hostname, username and password must be set manually</remarks>
  25.         Sub New()
  26.         End Sub
  27.  
  28.         ''' <summary>
  29.         ''' Constructor just taking the hostname
  30.         ''' </summary>
  31.         ''' <param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param>
  32.         ''' <remarks></remarks>
  33.         Sub New(ByVal Hostname As String)
  34.             _hostname = Hostname
  35.         End Sub
  36.  
  37.         ''' <summary>
  38.         ''' Constructor taking hostname, username and password
  39.         ''' </summary>
  40.         ''' <param name="Hostname">in either ftp://ftp.host.com or ftp.host.com form</param>
  41.         ''' <param name="Username">Leave blank to use 'anonymous' but set password to your email</param>
  42.         ''' <param name="Password"></param>
  43.         ''' <remarks></remarks>
  44.         Sub New(ByVal Hostname As String, ByVal Username As String, ByVal Password As String)
  45.             _hostname = Hostname
  46.             _username = Username
  47.             _password = Password
  48.         End Sub
  49. #End Region
  50.  
  51. #Region "Directory functions"
  52.         ''' <summary>
  53.         ''' Return a simple directory listing
  54.         ''' </summary>
  55.         ''' <param name="directory">Directory to list, e.g. /pub</param>
  56.         ''' <returns>A list of filenames and directories as a List(of String)</returns>
  57.         ''' <remarks>For a detailed directory listing, use ListDirectoryDetail</remarks>
  58.         Public Function ListDirectory(Optional ByVal directory As String = "") As List(Of String)
  59.             'return a simple list of filenames in directory
  60.             Dim ftp As Net.FtpWebRequest = GetRequest(GetDirectory(directory))
  61.             'Set request to do simple list
  62.             ftp.Method = Net.WebRequestMethods.Ftp.ListDirectory
  63.  
  64.             Dim str As String = GetStringResponse(ftp)
  65.             'replace CRLF to CR, remove last instance
  66.             str = str.Replace(vbCrLf, vbCr).TrimEnd(Chr(13))
  67.             'split the string into a list
  68.             Dim result As New List(Of String)
  69.             result.AddRange(str.Split(Chr(13)))
  70.             Return result
  71.         End Function
  72.  
  73.         ''' <summary>
  74.         ''' Return a detailed directory listing
  75.         ''' </summary>
  76.         ''' <param name="directory">Directory to list, e.g. /pub/etc</param>
  77.         ''' <returns>An FTPDirectory object</returns>
  78.         Public Function ListDirectoryDetail(Optional ByVal directory As String = "") As FTPdirectory
  79.             Dim ftp As Net.FtpWebRequest = GetRequest(GetDirectory(directory))
  80.             'Set request to do simple list
  81.             ftp.Method = Net.WebRequestMethods.Ftp.ListDirectoryDetails
  82.  
  83.             Dim str As String = GetStringResponse(ftp)
  84.             'replace CRLF to CR, remove last instance
  85.             str = str.Replace(vbCrLf, vbCr).TrimEnd(Chr(13))
  86.             'split the string into a list
  87.             Return New FTPdirectory(str, _lastDirectory)
  88.         End Function
  89.  
  90. #End Region
  91.  
  92. #Region "Upload: File transfer TO ftp server"
  93.         ''' <summary>
  94.         ''' Copy a local file to the FTP server
  95.         ''' </summary>
  96.         ''' <param name="localFilename">Full path of the local file</param>
  97.         ''' <param name="targetFilename">Target filename, if required</param>
  98.         ''' <returns></returns>
  99.         ''' <remarks>If the target filename is blank, the source filename is used
  100.         ''' (assumes current directory). Otherwise use a filename to specify a name
  101.         ''' or a full path and filename if required.</remarks>
  102.         Public Function Upload(ByVal localFilename As String, Optional ByVal targetFilename As String = "") As Boolean
  103.             '1. check source
  104.             If Not File.Exists(localFilename) Then
  105.                 Throw New ApplicationException("File " & localFilename & " not found")
  106.             End If
  107.             'copy to FI
  108.             Dim fi As New FileInfo(localFilename)
  109.             Return Upload(fi, targetFilename)
  110.         End Function
  111.  
  112.         ''' <summary>
  113.         ''' Upload a local file to the FTP server
  114.         ''' </summary>
  115.         ''' <param name="fi">Source file</param>
  116.         ''' <param name="targetFilename">Target filename (optional)</param>
  117.         ''' <returns></returns>
  118.         Public Function Upload(ByVal fi As FileInfo, Optional ByVal targetFilename As String = "") As Boolean
  119.             'copy the file specified to target file: target file can be full path or just filename (uses current dir)
  120.  
  121.             '1. check target
  122.             Dim target As String
  123.             If targetFilename.Trim = "" Then
  124.                 'Blank target: use source filename & current dir
  125.                 target = Me.CurrentDirectory & fi.Name
  126.             ElseIf targetFilename.Contains("/") Then
  127.                 'If contains / treat as a full path
  128.                 target = AdjustDir(targetFilename)
  129.             Else
  130.                 'otherwise treat as filename only, use current directory
  131.                 target = CurrentDirectory & targetFilename
  132.             End If
  133.  
  134.             Dim URI As String = Hostname & target
  135.             'perform copy
  136.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  137.  
  138.             'Set request to upload a file in binary
  139.             ftp.Method = Net.WebRequestMethods.Ftp.UploadFile
  140.             ftp.UseBinary = True
  141.  
  142.             'Notify FTP of the expected size
  143.             ftp.ContentLength = fi.Length
  144.  
  145.             'create byte array to store: ensure at least 1 byte!
  146.             Const BufferSize As Integer = 2048
  147.             Dim content(BufferSize - 1) As Byte, dataRead As Integer
  148.  
  149.             'open file for reading
  150.             Using fs As FileStream = fi.OpenRead()
  151.                 Try
  152.                     'open request to send
  153.                     Using rs As Stream = ftp.GetRequestStream
  154.                         Do
  155.                             dataRead = fs.Read(content, 0, BufferSize)
  156.                             rs.Write(content, 0, dataRead)
  157.                         Loop Until dataRead < BufferSize
  158.                         rs.Close()
  159.                     End Using
  160.                 Catch ex As Exception
  161.  
  162.                 Finally
  163.                     'ensure file closed
  164.                     fs.Close()
  165.                 End Try
  166.  
  167.             End Using
  168.  
  169.             ftp = Nothing
  170.             Return True
  171.  
  172.         End Function
  173. #End Region
  174.  
  175. #Region "Download: File transfer FROM ftp server"
  176.         ''' <summary>
  177.         ''' Copy a file from FTP server to local
  178.         ''' </summary>
  179.         ''' <param name="sourceFilename">Target filename, if required</param>
  180.         ''' <param name="localFilename">Full path of the local file</param>
  181.         ''' <returns></returns>
  182.         ''' <remarks>Target can be blank (use same filename), or just a filename
  183.         ''' (assumes current directory) or a full path and filename</remarks>
  184.         Public Function Download(ByVal sourceFilename As String, ByVal localFilename As String, Optional ByVal PermitOverwrite As Boolean = False) As Boolean
  185.             '2. determine target file
  186.             Dim fi As New FileInfo(localFilename)
  187.             Return Me.Download(sourceFilename, fi, PermitOverwrite)
  188.         End Function
  189.  
  190.         'Version taking an FtpFileInfo
  191.         Public Function Download(ByVal file As FTPfileInfo, ByVal localFilename As String, Optional ByVal PermitOverwrite As Boolean = False) As Boolean
  192.             Return Me.Download(file.FullName, localFilename, PermitOverwrite)
  193.         End Function
  194.  
  195.         'Another version taking FtpFileInfo and FileInfo
  196.         Public Function Download(ByVal file As FTPfileInfo, ByVal localFI As FileInfo, Optional ByVal PermitOverwrite As Boolean = False) As Boolean
  197.             Return Me.Download(file.FullName, localFI, PermitOverwrite)
  198.         End Function
  199.  
  200.         'Version taking string/FileInfo
  201.         Public Function Download(ByVal sourceFilename As String, ByVal targetFI As FileInfo, Optional ByVal PermitOverwrite As Boolean = False) As Boolean
  202.             '1. check target
  203.             If targetFI.Exists And Not (PermitOverwrite) Then Throw New ApplicationException("Target file already exists")
  204.  
  205.             '2. check source
  206.             Dim target As String
  207.             If sourceFilename.Trim = "" Then
  208.                 Throw New ApplicationException("File not specified")
  209.             ElseIf sourceFilename.Contains("/") Then
  210.                 'treat as a full path
  211.                 target = AdjustDir(sourceFilename)
  212.             Else
  213.                 'treat as filename only, use current directory
  214.                 target = CurrentDirectory & sourceFilename
  215.             End If
  216.  
  217.             Dim URI As String = Hostname & target
  218.  
  219.             '3. perform copy
  220.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  221.  
  222.             'Set request to download a file in binary mode
  223.             ftp.Method = Net.WebRequestMethods.Ftp.DownloadFile
  224.             ftp.UseBinary = True
  225.  
  226.             'open request and get response stream
  227.             Using response As FtpWebResponse = CType(ftp.GetResponse, FtpWebResponse)
  228.                 Using responseStream As Stream = response.GetResponseStream
  229.                     'loop to read & write to file
  230.                     Using fs As FileStream = targetFI.OpenWrite
  231.                         Try
  232.                             Dim buffer(2047) As Byte
  233.                             Dim read As Integer = 0
  234.                             Do
  235.                                 read = responseStream.Read(buffer, 0, buffer.Length)
  236.                                 fs.Write(buffer, 0, read)
  237.                             Loop Until read = 0
  238.                             responseStream.Close()
  239.                             fs.Flush()
  240.                             fs.Close()
  241.                         Catch ex As Exception
  242.                             'catch error and delete file only partially downloaded
  243.                             fs.Close()
  244.                             'delete target file as it's incomplete
  245.                             targetFI.Delete()
  246.                             Throw
  247.                         End Try
  248.                     End Using
  249.                     responseStream.Close()
  250.                 End Using
  251.                 response.Close()
  252.             End Using
  253.  
  254.             Return True
  255.         End Function
  256. #End Region
  257.  
  258. #Region "Other functions: Delete rename etc."
  259.         ''' <summary>
  260.         ''' Delete remote file
  261.         ''' </summary>
  262.         ''' <param name="filename">filename or full path</param>
  263.         ''' <returns></returns>
  264.         ''' <remarks></remarks>
  265.         Public Function FtpDelete(ByVal filename As String) As Boolean
  266.             'Determine if file or full path
  267.             Dim URI As String = Me.Hostname & GetFullPath(filename)
  268.  
  269.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  270.             'Set request to delete
  271.             ftp.Method = Net.WebRequestMethods.Ftp.DeleteFile
  272.             Try
  273.                 'get response but ignore it
  274.                 Dim str As String = GetStringResponse(ftp)
  275.             Catch ex As Exception
  276.                 Return False
  277.             End Try
  278.             Return True
  279.         End Function
  280.  
  281.         ''' <summary>
  282.         ''' Determine if file exists on remote FTP site
  283.         ''' </summary>
  284.         ''' <param name="filename">Filename (for current dir) or full path</param>
  285.         ''' <returns></returns>
  286.         ''' <remarks>Note this only works for files</remarks>
  287.         Public Function FtpFileExists(ByVal filename As String) As Boolean
  288.             'Try to obtain filesize: if we get error msg containing "550"
  289.             'the file does not exist
  290.             Try
  291.                 Dim size As Long = GetFileSize(filename)
  292.                 Return True
  293.  
  294.             Catch ex As Exception
  295.                 'only handle expected not-found exception
  296.                 If TypeOf ex Is System.Net.WebException Then
  297.                     'file does not exist/no rights error = 550
  298.                     If ex.Message.Contains("550") Then
  299.                         'clear
  300.                         Return False
  301.                     Else
  302.                         Throw
  303.                     End If
  304.                 Else
  305.                     Throw
  306.                 End If
  307.             End Try
  308.         End Function
  309.  
  310.         ''' <summary>
  311.         ''' Determine size of remote file
  312.         ''' </summary>
  313.         ''' <param name="filename"></param>
  314.         ''' <returns></returns>
  315.         ''' <remarks>Throws an exception if file does not exist</remarks>
  316.         Public Function GetFileSize(ByVal filename As String) As Long
  317.             Dim path As String
  318.             If filename.Contains("/") Then
  319.                 path = AdjustDir(filename)
  320.             Else
  321.                 path = Me.CurrentDirectory & filename
  322.             End If
  323.             Dim URI As String = Me.Hostname & path
  324.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  325.             'Try to get info on file/dir?
  326.             ftp.Method = Net.WebRequestMethods.Ftp.GetFileSize
  327.             Dim tmp As String = Me.GetStringResponse(ftp)
  328.             Return GetSize(ftp)
  329.         End Function
  330.  
  331.         Public Function FtpRename(ByVal sourceFilename As String, ByVal newName As String) As Boolean
  332.             'Does file exist?
  333.             Dim source As String = GetFullPath(sourceFilename)
  334.             If Not FtpFileExists(source) Then
  335.                 Throw New FileNotFoundException("File " & source & " not found")
  336.             End If
  337.  
  338.             'build target name, ensure it does not exist
  339.             Dim target As String = GetFullPath(newName)
  340.             If target = source Then
  341.                 Throw New ApplicationException("Source and target are the same")
  342.             ElseIf FtpFileExists(target) Then
  343.                 Throw New ApplicationException("Target file " & target & " already exists")
  344.             End If
  345.  
  346.             'perform rename
  347.             Dim URI As String = Me.Hostname & source
  348.  
  349.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  350.             'Set request to delete
  351.             ftp.Method = Net.WebRequestMethods.Ftp.Rename
  352.             ftp.RenameTo = target
  353.             Try
  354.                 'get response but ignore it
  355.                 Dim str As String = GetStringResponse(ftp)
  356.             Catch ex As Exception
  357.                 Return False
  358.             End Try
  359.             Return True
  360.         End Function
  361.  
  362.         Public Function FtpCreateDirectory(ByVal dirpath As String) As Boolean
  363.             'perform create
  364.             Dim URI As String = Me.Hostname & AdjustDir(dirpath)
  365.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  366.             'Set request to MkDir
  367.             ftp.Method = Net.WebRequestMethods.Ftp.MakeDirectory
  368.             Try
  369.                 'get response but ignore it
  370.                 Dim str As String = GetStringResponse(ftp)
  371.             Catch ex As Exception
  372.                 Return False
  373.             End Try
  374.             Return True
  375.         End Function
  376.  
  377.         Public Function FtpDeleteDirectory(ByVal dirpath As String) As Boolean
  378.             'perform remove
  379.             Dim URI As String = Me.Hostname & AdjustDir(dirpath)
  380.             Dim ftp As Net.FtpWebRequest = GetRequest(URI)
  381.             'Set request to RmDir
  382.             ftp.Method = Net.WebRequestMethods.Ftp.RemoveDirectory
  383.             Try
  384.                 'get response but ignore it
  385.                 Dim str As String = GetStringResponse(ftp)
  386.             Catch ex As Exception
  387.                 Return False
  388.             End Try
  389.             Return True
  390.         End Function
  391. #End Region
  392.  
  393. #Region "private supporting fns"
  394.         'Get the basic FtpWebRequest object with the
  395.         'common settings and security
  396.         Public Function GetRequest(ByVal URI As String) As FtpWebRequest
  397.             'create request
  398.             Dim result As FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)
  399.             'Set the login details
  400.             result.Credentials = GetCredentials()
  401.             'Do not keep alive (stateless mode)
  402.             result.KeepAlive = False
  403.             Return result
  404.         End Function
  405.  
  406.  
  407.         ''' <summary>
  408.         ''' Get the credentials from username/password
  409.         ''' </summary>
  410.         Private Function GetCredentials() As Net.ICredentials
  411.             Return New Net.NetworkCredential(Username, Password)
  412.         End Function
  413.  
  414.         ''' <summary>
  415.         ''' returns a full path using CurrentDirectory for a relative file reference
  416.         ''' </summary>
  417.         Private Function GetFullPath(ByVal file As String) As String
  418.             If file.Contains("/") Then
  419.                 Return AdjustDir(file)
  420.             Else
  421.                 Return Me.CurrentDirectory & file
  422.             End If
  423.         End Function
  424.  
  425.         ''' <summary>
  426.         ''' Amend an FTP path so that it always starts with /
  427.         ''' </summary>
  428.         ''' <param name="path">Path to adjust</param>
  429.         ''' <returns></returns>
  430.         ''' <remarks></remarks>
  431.         Private Function AdjustDir(ByVal path As String) As String
  432.             Return CStr(IIf(path.StartsWith("/"), "", "/")) & path
  433.         End Function
  434.  
  435.         Private Function GetDirectory(Optional ByVal directory As String = "") As String
  436.             Dim URI As String
  437.             If directory = "" Then
  438.                 'build from current
  439.                 URI = Hostname & Me.CurrentDirectory
  440.                 _lastDirectory = Me.CurrentDirectory
  441.             Else
  442.                 If Not directory.StartsWith("/") Then Throw New ApplicationException("Directory should start with /")
  443.                 URI = Me.Hostname & directory
  444.                 _lastDirectory = directory
  445.             End If
  446.             Return URI
  447.         End Function
  448.  
  449.         'stores last retrieved/set directory
  450.         Private _lastDirectory As String = ""
  451.  
  452.         ''' <summary>
  453.         ''' Obtains a response stream as a string
  454.         ''' </summary>
  455.         ''' <param name="ftp">current FTP request</param>
  456.         ''' <returns>String containing response</returns>
  457.         ''' <remarks>FTP servers typically return strings with CR and
  458.         ''' not CRLF. Use respons.Replace(vbCR, vbCRLF) to convert
  459.         ''' to an MSDOS string</remarks>
  460.         Private Function GetStringResponse(ByVal ftp As FtpWebRequest) As String
  461.             'Get the result, streaming to a string
  462.             Dim result As String = ""
  463.             Using response As FtpWebResponse = CType(ftp.GetResponse, FtpWebResponse)
  464.                 Dim size As Long = response.ContentLength
  465.                 Using datastream As Stream = response.GetResponseStream
  466.                     Using sr As New StreamReader(datastream)
  467.                         result = sr.ReadToEnd()
  468.                         sr.Close()
  469.                     End Using
  470.                     datastream.Close()
  471.                 End Using
  472.                 response.Close()
  473.             End Using
  474.             Return result
  475.         End Function
  476.  
  477.         ''' <summary>
  478.         ''' Gets the size of an FTP request
  479.         ''' </summary>
  480.         ''' <param name="ftp"></param>
  481.         ''' <returns></returns>
  482.         ''' <remarks></remarks>
  483.         Private Function GetSize(ByVal ftp As FtpWebRequest) As Long
  484.             Dim size As Long
  485.             Using response As FtpWebResponse = CType(ftp.GetResponse, FtpWebResponse)
  486.                 size = response.ContentLength
  487.                 response.Close()
  488.             End Using
  489.             Return size
  490.         End Function
  491. #End Region
  492.  
  493. #Region "Properties"
  494.         Private _hostname As String
  495.         ''' <summary>
  496.         ''' Hostname
  497.         ''' </summary>
  498.         ''' <value></value>
  499.         ''' <remarks>Hostname can be in either the full URL format
  500.         ''' ftp://ftp.myhost.com or just ftp.myhost.com
  501.         ''' </remarks>
  502.         Public Property Hostname() As String
  503.             Get
  504.                 If _hostname.StartsWith("ftp://") Then
  505.                     Return _hostname
  506.                 Else
  507.                     Return "ftp://" & _hostname
  508.                 End If
  509.             End Get
  510.             Set(ByVal value As String)
  511.                 _hostname = value
  512.             End Set
  513.         End Property
  514.         Private _username As String
  515.         ''' <summary>
  516.         ''' Username property
  517.         ''' </summary>
  518.         ''' <value></value>
  519.         ''' <remarks>Can be left blank, in which case 'anonymous' is returned</remarks>
  520.         Public Property Username() As String
  521.             Get
  522.                 Return CStr(IIf(_username = "", "anonymous", _username))
  523.             End Get
  524.             Set(ByVal value As String)
  525.                 _username = value
  526.             End Set
  527.         End Property
  528.         Private _password As String
  529.         Public Property Password() As String
  530.             Get
  531.                 Return _password
  532.             End Get
  533.             Set(ByVal value As String)
  534.                 _password = value
  535.             End Set
  536.         End Property
  537.  
  538.         ''' <summary>
  539.         ''' The CurrentDirectory value
  540.         ''' </summary>
  541.         ''' <remarks>Defaults to the root '/'</remarks>
  542.         Private _currentDirectory As String = "/"
  543.         Public Property CurrentDirectory() As String
  544.             Get
  545.                 'return directory, ensure it ends with /
  546.                 Return _currentDirectory & CStr(IIf(_currentDirectory.EndsWith("/"), "", "/"))
  547.             End Get
  548.             Set(ByVal value As String)
  549.                 If Not value.StartsWith("/") Then Throw New ApplicationException("Directory should start with /")
  550.                 _currentDirectory = value
  551.             End Set
  552.         End Property
  553.  
  554.  
  555. #End Region
  556.  
  557.     End Class
  558. #End Region
  559.  
  560. #Region "FTP file info class"
  561.     ''' <summary>
  562.     ''' Represents a file or directory entry from an FTP listing
  563.     ''' </summary>
  564.     ''' <remarks>
  565.     ''' This class is used to parse the results from a detailed
  566.     ''' directory list from FTP. It supports most formats of
  567.     ''' </remarks>
  568.     Public Class FTPfileInfo
  569.         'Stores extended info about FTP file
  570.  
  571. #Region "Properties"
  572.         Public ReadOnly Property FullName() As String
  573.             Get
  574.                 Return Path & Filename
  575.             End Get
  576.         End Property
  577.         Public ReadOnly Property Filename() As String
  578.             Get
  579.                 Return _filename
  580.             End Get
  581.         End Property
  582.         Public ReadOnly Property Path() As String
  583.             Get
  584.                 Return _path
  585.             End Get
  586.         End Property
  587.         Public ReadOnly Property FileType() As DirectoryEntryTypes
  588.             Get
  589.                 Return _fileType
  590.             End Get
  591.         End Property
  592.         Public ReadOnly Property Size() As Long
  593.             Get
  594.                 Return _size
  595.             End Get
  596.         End Property
  597.         Public ReadOnly Property FileDateTime() As Date
  598.             Get
  599.                 Return _fileDateTime
  600.             End Get
  601.         End Property
  602.         Public ReadOnly Property Permission() As String
  603.             Get
  604.                 Return _permission
  605.             End Get
  606.         End Property
  607.         Public ReadOnly Property Extension() As String
  608.             Get
  609.                 Dim i As Integer = Me.Filename.LastIndexOf(".")
  610.                 If i >= 0 And i < (Me.Filename.Length - 1) Then
  611.                     Return Me.Filename.Substring(i + 1)
  612.                 Else
  613.                     Return ""
  614.                 End If
  615.             End Get
  616.         End Property
  617.         Public ReadOnly Property NameOnly() As String
  618.             Get
  619.                 Dim i As Integer = Me.Filename.LastIndexOf(".")
  620.                 If i > 0 Then
  621.                     Return Me.Filename.Substring(0, i)
  622.                 Else
  623.                     Return Me.Filename
  624.                 End If
  625.             End Get
  626.         End Property
  627.         Private _filename As String
  628.         Private _path As String
  629.         Private _fileType As DirectoryEntryTypes
  630.         Private _size As Long
  631.         Private _fileDateTime As Date
  632.         Private _permission As String
  633.  
  634. #End Region
  635.  
  636.         ''' <summary>
  637.         ''' Identifies entry as either File or Directory
  638.         ''' </summary>
  639.         Public Enum DirectoryEntryTypes
  640.             File
  641.             Directory
  642.         End Enum
  643.  
  644.         ''' <summary>
  645.         ''' Constructor taking a directory listing line and path
  646.         ''' </summary>
  647.         ''' <param name="line">The line returned from the detailed directory list</param>
  648.         ''' <param name="path">Path of the directory</param>
  649.         ''' <remarks></remarks>
  650.         Sub New(ByVal line As String, ByVal path As String)
  651.             'parse line
  652.             Dim m As Match = GetMatchingRegex(line)
  653.             If m Is Nothing Then
  654.                 'failed
  655.                 Throw New ApplicationException("Unable to parse line: " & line)
  656.             Else
  657.                 _filename = m.Groups("name").Value
  658.                 _path = path
  659.                 _size = CLng(m.Groups("size").Value)
  660.                 _permission = m.Groups("permission").Value
  661.                 Dim _dir As String = m.Groups("dir").Value
  662.                 If (_dir <> "" And _dir <> "-") Then
  663.                     _fileType = DirectoryEntryTypes.Directory
  664.                 Else
  665.                     _fileType = DirectoryEntryTypes.File
  666.                 End If
  667.  
  668.                 Try
  669.                     _fileDateTime = Date.Parse(m.Groups("timestamp").Value)
  670.                 Catch ex As Exception
  671.                     _fileDateTime = Nothing
  672.                 End Try
  673.  
  674.             End If
  675.         End Sub
  676.  
  677.         Private Function GetMatchingRegex(ByVal line As String) As Match
  678.             Dim rx As Regex, m As Match
  679.             For i As Integer = 0 To _ParseFormats.Length - 1
  680.                 rx = New Regex(_ParseFormats(i))
  681.                 m = rx.Match(line)
  682.                 If m.Success Then Return m
  683.             Next
  684.             Return Nothing
  685.         End Function
  686.  
  687. #Region "Regular expressions for parsing LIST results"
  688.         ''' <summary>
  689.         ''' List of REGEX formats for different FTP server listing formats
  690.         ''' </summary>
  691.         ''' <remarks>
  692.         ''' The first three are various UNIX/LINUX formats, fourth is for MS FTP
  693.         ''' in detailed mode and the last for MS FTP in 'DOS' mode.
  694.         ''' I wish VB.NET had support for Const arrays like C# but there you go
  695.         ''' </remarks>
  696.         Private Shared _ParseFormats As String() = { _
  697.             "(?<dir>[\-d])(?<permission>([\-r][\-w][\-xs]){3})\s+\d+\s+\w+\s+\w+\s+(?<size>\d+)\s+(?<timestamp>\w+\s+\d+\s+\d{4})\s+(?<name>.+)", _
  698.             "(?<dir>[\-d])(?<permission>([\-r][\-w][\-xs]){3})\s+\d+\s+\d+\s+(?<size>\d+)\s+(?<timestamp>\w+\s+\d+\s+\d{4})\s+(?<name>.+)", _
  699.             "(?<dir>[\-d])(?<permission>([\-r][\-w][\-xs]){3})\s+\d+\s+\d+\s+(?<size>\d+)\s+(?<timestamp>\w+\s+\d+\s+\d{1,2}:\d{2})\s+(?<name>.+)", _
  700.             "(?<dir>[\-d])(?<permission>([\-r][\-w][\-xs]){3})\s+\d+\s+\w+\s+\w+\s+(?<size>\d+)\s+(?<timestamp>\w+\s+\d+\s+\d{1,2}:\d{2})\s+(?<name>.+)", _
  701.             "(?<dir>[\-d])(?<permission>([\-r][\-w][\-xs]){3})(\s+)(?<size>(\d+))(\s+)(?<ctbit>(\w+\s\w+))(\s+)(?<size2>(\d+))\s+(?<timestamp>\w+\s+\d+\s+\d{2}:\d{2})\s+(?<name>.+)", _
  702.             "(?<timestamp>\d{2}\-\d{2}\-\d{2}\s+\d{2}:\d{2}[Aa|Pp][mM])\s+(?<dir>\<\w+\>){0,1}(?<size>\d+){0,1}\s+(?<name>.+)"}
  703. #End Region
  704.     End Class
  705. #End Region
  706.  
  707. #Region "FTP Directory class"
  708.     ''' <summary>
  709.     ''' Stores a list of files and directories from an FTP result
  710.     ''' </summary>
  711.     ''' <remarks></remarks>
  712.     Public Class FTPdirectory
  713.         Inherits List(Of FTPfileInfo)
  714.  
  715.         Sub New()
  716.             'creates a blank directory listing
  717.         End Sub
  718.  
  719.         ''' <summary>
  720.         ''' Constructor: create list from a (detailed) directory string
  721.         ''' </summary>
  722.         ''' <param name="dir">directory listing string</param>
  723.         ''' <param name="path"></param>
  724.         ''' <remarks></remarks>
  725.         Sub New(ByVal dir As String, ByVal path As String)
  726.             For Each line As String In dir.Replace(vbLf, "").Split(CChar(vbCr))
  727.                 'parse
  728.                 If line <> "" Then Me.Add(New FTPfileInfo(line, path))
  729.             Next
  730.         End Sub
  731.  
  732.         ''' <summary>
  733.         ''' Filter out only files from directory listing
  734.         ''' </summary>
  735.         ''' <param name="ext">optional file extension filter</param>
  736.         ''' <returns>FTPdirectory listing</returns>
  737.         Public Function GetFiles(Optional ByVal ext As String = "") As FTPdirectory
  738.             Return Me.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.File, ext)
  739.         End Function
  740.  
  741.         ''' <summary>
  742.         ''' Returns a list of only subdirectories
  743.         ''' </summary>
  744.         ''' <returns>FTPDirectory list</returns>
  745.         ''' <remarks></remarks>
  746.         Public Function GetDirectories() As FTPdirectory
  747.             Return Me.GetFileOrDir(FTPfileInfo.DirectoryEntryTypes.Directory)
  748.         End Function
  749.  
  750.         'internal: share use function for GetDirectories/Files
  751.         Private Function GetFileOrDir(ByVal type As FTPfileInfo.DirectoryEntryTypes, Optional ByVal ext As String = "") As FTPdirectory
  752.             Dim result As New FTPdirectory()
  753.             For Each fi As FTPfileInfo In Me
  754.                 If fi.FileType = type Then
  755.                     If ext = "" Then
  756.                         result.Add(fi)
  757.                     ElseIf ext = fi.Extension Then
  758.                         result.Add(fi)
  759.                     End If
  760.                 End If
  761.             Next
  762.             Return result
  763.  
  764.         End Function
  765.  
  766.         Public Function FileExists(ByVal filename As String) As Boolean
  767.             For Each ftpfile As FTPfileInfo In Me
  768.                 If ftpfile.Filename = filename Then
  769.                     Return True
  770.                 End If
  771.             Next
  772.             Return False
  773.         End Function
  774.  
  775.         Private Const slash As Char = "/"
  776.  
  777.         Public Shared Function GetParentDirectory(ByVal dir As String) As String
  778.             Dim tmp As String = dir.TrimEnd(slash)
  779.             Dim i As Integer = tmp.LastIndexOf(slash)
  780.             If i > 0 Then
  781.                 Return tmp.Substring(0, i - 1)
  782.             Else
  783.                 Throw New ApplicationException("No parent for root")
  784.             End If
  785.         End Function
  786.     End Class
  787. #End Region
  788.  
  789. End Namespace
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement