Know a good article or link that we're missing? Submit it!
*/
*/

View \VBFTP.BAS

FTP Client in VBasic with source

Submitted By: WEBMASTER
Rating: Not rated (Rate It)


OPTION Explicit

Global intXferStop AS INTEGER

'ini file management
DECLARE FUNCTION GetPrivateProfileString Lib "Kernel" (BYVAL lpApplicationName AS STRING, BYVAL lpKeyName AS STRING, BYVAL lpDefault AS STRING, BYVAL lpReturnedString AS STRING, BYVAL nSize AS INTEGER, BYVAL lpFileName AS STRING) AS INTEGER
DECLARE FUNCTION WritePrivateProfileString Lib "Kernel" (BYVAL lpApplicationName AS STRING, BYVAL lpKeyName AS STRING, BYVAL lpString AS STRING, BYVAL lplFileName AS STRING) AS INTEGER
Global intMachineCnt AS INTEGER

FUNCTION ftpcommand (CtlData AS STRING) AS INTEGER
    ON ERROR RESUME NEXT
   
    IF GetField(CtlData, 1, " ") = "PASS" THEN
        frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & "<local>PASS " & STRING$(LEN(CtlData) - 5, "*")
    ELSE
        frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & "<local>" & CtlData
    END IF
    frmClient.txtStatus.SelStart = LEN(frmClient.txtStatus.Text)

    'append a carriage return and linefeed to the data
    CtlData = CtlData & CHR$(13) & CHR$(10)
    'set the transmit buffer length to the length of the string
    frmClient.Socket1.SendLen = LEN(CtlData)
    'send the data
    frmClient.Socket1.SendData = CtlData

    'check for errors
    IF ERR <> 0 THEN
        ftpcommand = False
    ELSE
        ftpcommand = True
    END IF

END FUNCTION

FUNCTION FTPConnect (HostName AS STRING)
    DIM CtlData AS STRING, Reply AS INTEGER

    FTPConnect = False
    IF HostName = "" THEN EXIT FUNCTION

    'internet address family
    frmClient.Socket1.AddressFamily = AF_INET
    'internet protocol
    frmClient.Socket1.Protocol = IPPROTO_IP
    'streaming socket (most reliable way to send data)
    frmClient.Socket1.TYPE = SOCK_STREAM
    'connect to ftp port on remote host (port 21)
    frmClient.Socket1.RemotePort = IPPORT_FTP
    'set remote host name
    frmClient.Socket1.HostName = HostName
    'transfer data in ascii
    frmClient.Socket1.BINARY = False
    'use 1024 byte packets to pass data
    frmClient.Socket1.BufferSize = 1024
    'turn on socket block (synchronous transmission)
    'will not return control to caller until process is complete
    frmClient.Socket1.Blocking = True

    ON ERROR RESUME NEXT
    'call the socket connect
    frmClient.Socket1.Action = SOCKET_CONNECT
    IF ERR THEN
        MsgBox ERROR$
        EXIT FUNCTION
    END IF

    'get the results from the connect
    Reply = FTPResult(CtlData)
   
    'if connect resulted in 220 then fine,
    'otherwise close the socket
    IF Reply = 220 THEN
        FTPConnect = True
    ELSE
        frmClient.Socket1.Action = SOCKET_CLOSE
    END IF

END FUNCTION

SUB FTPGetDirectory ()
    DIM CtlData AS STRING
    DIM Buffer AS STRING
    DIM intRC AS INTEGER
    DIM intLpCnt AS INTEGER
    DIM intDirCnt AS INTEGER
    DIM strLine AS STRING
    DIM strPerm AS STRING
    DIM strFName AS STRING
    DIM strFSize AS STRING
   
    'clear the list and caption
    frmClient.lstRemFiles.CLEAR
    frmClient.lblRemPath.Caption = ""

    'send the command PWD (Present Working Directory) to remote
    IF NOT ftpcommand("PWD") THEN EXIT SUB
    'code 257 - got directory
    IF LEFT$(STR$(FTPResult(CtlData)), 3) <> " 25" THEN EXIT SUB

    'parse directory out of returned string
    CtlData = MID$(CtlData, 2, INSTR(CtlData, " ") - 3)
    frmClient.lblRemPath.Caption = CtlData
   
    'If ftpcommand("SYST") Then intRC = FTPResult(CtlData)

    'get the file list
    IF NOT FTPListen(0) THEN EXIT SUB 'listen in ascii
    IF NOT ftpcommand("LIST") THEN EXIT SUB
    'code 150 - starting transfer
    IF LEFT$(Str(FTPResult(CtlData)), 2) <> " 1" THEN
        frmClient.Socket2.Action = SOCKET_CLOSE
        EXIT SUB
    END IF
    'start accepting listing in second socket
    frmClient.Socket2.Action = SOCKET_ACCEPT
    ON ERROR RESUME NEXT
   
    IF ERR THEN
        MsgBox ERROR$
        frmClient.Socket2.Action = SOCKET_CLOSE
        EXIT SUB
    END IF
    Buffer = ""
    DO
        'size of packet to recieve
        frmClient.Socket2.RecvLen = 4092
'        frmClient.Socket2.RecvLen = 512
        'receive the data packet
        Buffer = Buffer & frmClient.Socket2.RecvData
        IF ERR THEN
            MsgBox ERROR$
            EXIT DO
        END IF
        IF frmClient.Socket2.RecvLen = 0 THEN EXIT DO
        'permit other system operations
        DoEvents
    LOOP
    'close the secondary socket
    frmClient.Socket2.Action = SOCKET_CLOSE
    'wait for close verification
    intRC = FTPResult(CtlData)

    intDirCnt = CountOf(Buffer, CHR$(13))
    FOR intLpCnt = 1 TO intDirCnt
        strLine = StringCompress(GetField(Buffer, intLpCnt, CHR$(13) & CHR$(10)), " ")
        strPerm = GetField(strLine, 1, " ")
        IF LEN(strPerm) = 10 AND (MID$(strPerm, 2, 1) = "-" OR MID$(strPerm, 2, 1) = "r") THEN
        'buffer is a unix type ls -l output
'drwx------   4 owner      group         512 Aug 11 11:25 DiretoryName
'-rwxr-xr-x   1 owner      group         501 Jun 26 09:09 FileName
            strFName = GetField(strLine, 9, " ")
            strFSize = GetField(strLine, 5, " ")
            IF strFName <> "." THEN 'ignore present directory
                IF UCase(LEFT$(strPerm, 1)) = "D" THEN
                    'put brackets around directories
                    frmClient.lstRemFiles.AddItem "<" & strFName & ">"
                ELSE
                    frmClient.lstRemFiles.AddItem strFName
                    frmClient.lstRemFiles.ItemData(frmClient.lstRemFiles.NewIndex) = strFSize
                END IF
            END IF
        ELSE
        'buffer is something else
            IF NOT (strPerm = "total" AND GetField(strLine, 3, " ") = "") THEN
                strFName = GetField(strLine, 1, " ")
                'take the heading off of it
                intRC = INSTR(strFName, ".")
                IF intRC <> 0 THEN
                    strFName = MID$(strFName, intRC + 1, LEN(strFName))
                END IF
                strFSize = GetField(strLine, 6, " ")
                frmClient.lstRemFiles.AddItem strFName
                frmClient.lstRemFiles.ItemData(frmClient.lstRemFiles.NewIndex) = strFSize
            END IF
        END IF
        IF intLpCnt MOD 5 = 0 THEN
            frmClient.lstRemFiles.TopIndex = intLpCnt - 5
            frmClient.lstRemFiles.Refresh
        END IF
    NEXT intLpCnt
    frmClient.lstRemFiles.TopIndex = 0
END SUB

FUNCTION FTPGetFile (RemoteFile AS STRING, LocalFile AS STRING)
    DIM CtlData AS STRING, Buffer AS STRING
    DIM Result AS INTEGER
    DIM intMode AS INTEGER
    DIM lngFSize AS LONG
    DIM lngXSize AS LONG
    DIM intLpCnt AS INTEGER
    DIM strFHold AS STRING

    FTPGetFile = False

    IF REMoteFile = "" Or LocalFile = "" Then Exit Function
    'do not permit exit or refresh at this time
    'frmClient.MousePointer = MOUSE_HOURGLASS
    frmClient.cmdLocRef.Enabled = False
    frmClient.cmdRemRef.Enabled = False
    frmClient.FileMenu.Enabled = False
    frmClient.mnuSession.Enabled = False
    intXferStop = False
    frmClient.lblXferText.Caption = "Retrieving file '" & REMoteFile & "' ( ? bytes)"
    frmClient.pnlXferGauge.FloodPercent = 0
    frmClient.pnlXferStat.Visible = True
    'start listening for the remote machine connection
    IF frmClient.rdoAscii.Value THEN
        intMode = 0
    ELSE
        intMode = 1
    END IF
    IF NOT FTPListen(intMode) THEN
        frmClient.cmdLocRef.Enabled = True
        frmClient.cmdRemRef.Enabled = True
        frmClient.FileMenu.Enabled = True
        frmClient.mnuSession.Enabled = True
        frmClient.pnlXferStat.Visible = False
        frmClient.MousePointer = MOUSE_DEFAULT
        MsgBox "Could not get remote system to respond."
        EXIT FUNCTION
    END IF
    'tell the remote host which file we want to retrieve
    IF NOT ftpcommand("RETR " & REMoteFile) Then
        frmClient.cmdLocRef.Enabled = True
        frmClient.cmdRemRef.Enabled = True
        frmClient.FileMenu.Enabled = True
        frmClient.mnuSession.Enabled = True
        frmClient.pnlXferStat.Visible = False
        frmClient.MousePointer = MOUSE_DEFAULT
        frmClient.Socket2.Action = SOCKET_CLOSE
        MsgBox "Could not open file on remote system. - No transfer"
        EXIT FUNCTION
    END IF
    'code 150 - starting transfer
    IF LEFT$(Str(FTPResult(CtlData)), 2) <> " 1" THEN
        frmClient.cmdLocRef.Enabled = True
        frmClient.cmdRemRef.Enabled = True
        frmClient.FileMenu.Enabled = True
        frmClient.mnuSession.Enabled = True
        frmClient.pnlXferStat.Visible = False
        frmClient.MousePointer = MOUSE_DEFAULT
        frmClient.Socket2.Action = SOCKET_CLOSE
        MsgBox "Could not initiate transfer from remote system."
        EXIT FUNCTION
    END IF
   
    frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & "<Comment>Opening retrieval socket."
    frmClient.txtStatus.SelStart = LEN(frmClient.txtStatus.Text)
    'give remote time to initiate transfer
    SLEEP (1)
    'start accepting file in second socket
    frmClient.Socket2.Action = SOCKET_ACCEPT
    DoEvents
    IF NOT frmClient.Socket2.Connected THEN
        frmClient.cmdLocRef.Enabled = True
        frmClient.cmdRemRef.Enabled = True
        frmClient.FileMenu.Enabled = True
        frmClient.mnuSession.Enabled = True
        frmClient.pnlXferStat.Visible = False
        frmClient.MousePointer = MOUSE_DEFAULT
        frmClient.Socket2.Action = SOCKET_ABORT
        frmClient.pnlXferStat.Visible = False
        MsgBox "Remote system is not accepting file requests."
        EXIT FUNCTION
    END IF
    ON ERROR RESUME NEXT
    frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & "<Comment>Retrieving file length."
    frmClient.txtStatus.SelStart = LEN(frmClient.txtStatus.Text)
    'look up file size
    strFHold = GetField(RemoteFile, (CountOf(RemoteFile, "/") + 1), "/")
    strFHold = GetField(strFHold, (CountOf(strFHold, "\") + 1), "\")
    lngFSize = 1
    FOR intLpCnt = 0 TO frmClient.lstRemFiles.ListCount - 1
        IF strFHold = frmClient.lstRemFiles.LIST(intLpCnt) THEN
            lngFSize = frmClient.lstRemFiles.ItemData(intLpCnt)
            EXIT FOR
        END IF
    NEXT intLpCnt
    lngXSize = 0
    frmClient.lblXferText.Caption = "Retrieving file '" & REMoteFile & "' (" & lngFSize & " bytes)"
    frmClient.pnlXferGauge.FloodPercent = lngXSize
    frmClient.pnlXferStat.Visible = True
   
    'open file for writing
    OPEN LocalFile FOR BINARY AS #1
    IF ERR THEN
        MsgBox ERROR$
        frmClient.Socket2.Shutdown = 0
        frmClient.Socket2.Action = SOCKET_CLOSE
        frmClient.pnlXferStat.Visible = False
        EXIT FUNCTION
    END IF

    FTPGetFile = True
   
    'loop through loading file
    DO
        'size of packet to recieve
        frmClient.Socket2.RecvLen = 4096
        'receive the data packet
        Buffer = frmClient.Socket2.RecvData
        lngXSize = lngXSize + LEN(Buffer)
        IF INT((lngXSize / lngFSize) * 100) < 101 THEN
            frmClient.pnlXferGauge.FloodPercent = INT((lngXSize / lngFSize) * 100)
        END IF
        IF ERR THEN
            FTPGetFile = False
            MsgBox ERROR$
            EXIT DO
        END IF
        IF intXferStop THEN
            FTPGetFile = False
            'if they exit, stop the transaction
            MsgBox "Transfer stopped by user."
            'frmClient.Socket1.Action = SOCKET_ABORT
            frmClient.Socket2.Shutdown = 0
            frmClient.Socket2.Action = SOCKET_ABORT
            EXIT DO
        END IF
        'did we hit EOF?
        IF frmClient.Socket2.RecvLen = 0 THEN EXIT DO
        'append packet to file
        PUT #1, , Buffer
        'permit other system operations
        DoEvents
    LOOP

    'close the data file
    CLOSE #1
    'if user cancelled, destroy partial file
    IF intXferStop THEN
        KILL LocalFile
    ELSE
        frmClient.pnlXferGauge.FloodPercent = 100
    END IF
    'close the secondary socket
    frmClient.Socket2.Action = SOCKET_CLOSE
    'wait for close verification
    Result = FTPResult(CtlData)

    'turn controls on
        frmClient.cmdLocRef.Enabled = True
        frmClient.cmdRemRef.Enabled = True
        frmClient.FileMenu.Enabled = True
        frmClient.mnuSession.Enabled = True
        frmClient.pnlXferStat.Visible = False
        frmClient.MousePointer = MOUSE_DEFAULT
END FUNCTION

FUNCTION FTPListen (intMode AS INTEGER)
    DIM Port AS INTEGER, Address AS STRING
    DIM Reply AS INTEGER, CtlData AS STRING
    DIM I AS INTEGER, P AS INTEGER

    'connect a second socket to the remote host
    'to listen for and execute remote commands
    'in essence, set up a server connection
    FTPListen = False
   
    'internet address
    frmClient.Socket2.AddressFamily = AF_INET
    'will be receiveing in binary
    frmClient.Socket2.BINARY = True
    'synchronous connection
    frmClient.Socket2.Blocking = True
    'do not buffer data
    frmClient.Socket2.BufferSize = 0
    'accept from any remote address
    frmClient.Socket2.HostAddress = INADDR_ANY
    'connect to any available port
    frmClient.Socket2.LocalPort = IPPORT_ANY
    'internet protocol
    frmClient.Socket2.Protocol = IPPROTO_TCP
    'set timeout for 60 seconds
    frmClient.Socket2.Timeout = 200000
    'streaming socket
    frmClient.Socket2.TYPE = SOCK_STREAM
    'start listening
    frmClient.Socket2.Action = SOCKET_LISTEN

    'listen will set these two to valid port and address
    Port = frmClient.Socket2.LocalPort
    'we use the address from the first socket, they should be the same
    Address = frmClient.Socket1.LocalAddress

    'convert . to , in address
    FOR I = 1 TO 3
        P = INSTR(Address, ".")
        IF P <> 0 THEN MID$(Address$, P, 1) = ","
    NEXT I
   
    'tell remote system which port gets the data
    CtlData = "PORT " & Address & "," & (Port  256) & "," & (Port MOD 256)
    IF NOT ftpcommand(CtlData) THEN GOTO OpenFailed
   
    'code 200 -command understood
    IF FTPResult(CtlData) <> 200 THEN GOTO OpenFailed
   
    'transfer in binary or ascii?
    IF intMode = 1 THEN
        CtlData = "TYPE I"  'binary
    ELSE
        CtlData = "TYPE A"  'ascii
    END IF
   
    IF NOT ftpcommand(CtlData) THEN GOTO OpenFailed
    'code 2?? -command understood
    IF LEFT$(STR$(FTPResult(CtlData)), 2) <> " 2" THEN GOTO OpenFailed
   
    FTPListen = True
    EXIT FUNCTION

OpenFailed:
    'disconnect new socket on error
    IF frmClient.Socket2.Listening THEN frmClient.Socket2.Action = SOCKET_CLOSE
    EXIT FUNCTION
END FUNCTION

FUNCTION FTPLogin (Username AS STRING, Password AS STRING) AS INTEGER
    DIM CtlData AS STRING, Reply AS INTEGER
    DIM Counter AS INTEGER
   
    FTPLogin = False

    'check receive buffer
    IF frmClient.Socket1.IsReadable THEN
        Reply = FTPResult(CtlData)
    END IF

    'clear all connect messages out of receive buffer
    WHILE Reply = 220 AND frmClient.Socket1.IsReadable
        Reply = FTPResult(CtlData)
    WEND

    'send the user command with the user id to remote host
    CtlData = "USER " & Username
    IF NOT ftpcommand(CtlData) THEN EXIT FUNCTION
    'check the response from remote host
    Reply = FTPResult(CtlData)

    'code 331 means ready for password
    IF Reply = 331 THEN
        'send the pass command and the password
        CtlData = "PASS " & Password
        IF NOT ftpcommand(CtlData) THEN EXIT FUNCTION
        'check the response
        Reply = FTPResult(CtlData)
    END IF
   
    'get all login messages out of receive buffer
    WHILE Reply = 230 AND frmClient.Socket1.IsReadable
        Reply = FTPResult(CtlData)
    WEND

    'code 230 - logon accepted
    IF Reply = 230 THEN
        FTPLogin = True
    ELSE
        MsgBox "Invalid user name or password"
    END IF

END FUNCTION

FUNCTION FTPPutFile (LocalFile AS STRING, REMoteFile As String)
    DIM CtlData AS STRING, Buffer AS STRING * 4096
    DIM Result AS INTEGER, Size AS LONG
    DIM intMode AS INTEGER
    DIM lngXSize AS LONG, lngFSize AS LONG

    'write the file onto the remote host

    FTPPutFile = False

    IF REMoteFile = "" Or LocalFile = "" Then Exit Function
    'start listening for remote host
    IF frmClient.rdoAscii.Value THEN
        intMode = 0
    ELSE
        intMode = 1
    END IF
    ERR = 0
    IF NOT FTPListen(intMode) THEN EXIT FUNCTION
    intXferStop = False
    'do not permit exit or refresh at this time
    frmClient.cmdLocRef.Enabled = False
    frmClient.cmdRemRef.Enabled = False
    frmClient.FileMenu.Enabled = False
    frmClient.mnuSession.Enabled = False
    Size = FileLen(LocalFile)
    lngFSize = Size
    lngXSize = 0
    frmClient.lblXferText.Caption = "Sending file '" & LocalFile & "' (" & lngFSize & " bytes)"
    frmClient.pnlXferGauge.FloodPercent = lngXSize
    frmClient.pnlXferStat.Visible = True
    SLEEP (3)
    'tell remote host to store this file
    IF NOT ftpcommand("STOR " & REMoteFile) Then
        GOSUB scrn_Reset
        EXIT FUNCTION
    END IF
    'If intXferStop Then
    '    GoSub scrn_Reset
    '    Exit Function
    'End If
    SLEEP (3)
    'code 150 -command accepted
    IF LEFT$(Str(FTPResult(CtlData)), 2) <> " 1" THEN
        GOSUB scrn_Reset
        EXIT FUNCTION
    END IF
    'If intXferStop Then
    '    GoSub scrn_Reset
    '    Exit Function
    'End If
   
    ON ERROR RESUME NEXT
    'start accepting commands from remote host
    frmClient.Socket2.Action = SOCKET_ACCEPT
   
    IF ERR THEN
        frmClient.Socket2.Action = SOCKET_CLOSE
        MsgBox ERROR$
        EXIT FUNCTION
    END IF
   
    'open the file for reading
    OPEN LocalFile FOR BINARY AS #1

    IF ERR THEN
        frmClient.Socket2.Action = SOCKET_CLOSE
        MsgBox ERROR$
        EXIT FUNCTION
    END IF

    FTPPutFile = True
    'send file in 4096 byte packets (buffer)
    DO
        GET #1, , Buffer
        'set transmit length to size of packet
        IF Size < LEN(Buffer) THEN
            frmClient.Socket2.SendLen = Size
            Size = 0
        ELSE
            frmClient.Socket2.SendLen = LEN(Buffer)
            Size = Size - LEN(Buffer)
        END IF
        'send packet
        frmClient.Socket2.SendData = Buffer
        IF ERR > 0 THEN
            FTPPutFile = False
            MsgBox ERROR$
            EXIT DO
        END IF
        lngXSize = lngXSize + LEN(Buffer)
        frmClient.pnlXferGauge.FloodPercent = INT((lngXSize / lngFSize) * 100)
        IF intXferStop THEN
            FTPPutFile = False
            MsgBox "Transfer stopped by user."
            Size = 0
        END IF
        'if file is empty, we're done
        IF Size = 0 THEN EXIT DO
        'allow other system events to fire
        DoEvents
    LOOP
    IF NOT intXferStop THEN
        frmClient.pnlXferGauge.FloodPercent = 100
    END IF

    'close local file
    CLOSE #1
    frmClient.cmdLocRef.Enabled = True
    frmClient.cmdRemRef.Enabled = True
    frmClient.FileMenu.Enabled = True
    frmClient.mnuSession.Enabled = True
    frmClient.pnlXferStat.Visible = False
    'close secondary socket
    frmClient.Socket2.Action = SOCKET_CLOSE
    'verify socket close
    Result = FTPResult(CtlData)
EXIT FUNCTION
scrn_Reset:
    frmClient.cmdLocRef.Enabled = True
    frmClient.cmdRemRef.Enabled = True
    frmClient.FileMenu.Enabled = True
    frmClient.mnuSession.Enabled = True
    frmClient.pnlXferStat.Visible = False
    'frmClient.Socket2.Shutdown = 1
    'frmClient.Socket2.Action = SOCKET_FLUSH
    'frmClient.Socket2.Action = SOCKET_ABORT
    ERR = 0
    'frmClient.Socket2.Action = SOCKET_CLOSE
RETURN
END FUNCTION

FUNCTION FTPResult (CtlData AS STRING) AS INTEGER
    DIM SockData AS STRING, Reply AS INTEGER

    'receive 255 bytes at a time
    frmClient.Socket1.RecvLen = 255
    'load sockdata with data from socket
    SockData = frmClient.Socket1.RecvData
    'print the data to the status window
    frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & SockData
    frmClient.txtStatus.SelStart = LEN(frmClient.txtStatus.Text)

    'reply is the first 3 characters (should be numeric)
    Reply = VAL(LEFT$(SockData, 3))
    IF MID$(SockData, 4, 1) = "-" THEN
        DO
            frmClient.Socket1.RecvLen = 255
            'check for longer warning message and clear the buffer
            SockData = frmClient.Socket1.RecvData
            IF VAL(LEFT$(SockData, 3)) = Reply THEN EXIT DO
            frmClient.txtStatus.Text = frmClient.txtStatus.Text & CHR$(13) & CHR$(10) & SockData
            frmClient.txtStatus.SelStart = LEN(frmClient.txtStatus.Text)
        LOOP
    END IF
    CtlData = RIGHT$(SockData, LEN(SockData) - INSTR(SockData, " "))
   
    FTPResult = Reply
END FUNCTION

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.
Resource Listings