Jump to content

ftp client !


arcker
 Share

Recommended Posts

ok now here is a working version

tested on a large collection of ftp sites

features :

-brute command send

-navigate like a classic ftp client

-and file download (maximum speed on my machine, 50Mbits/s, not bad isn't it ?

-support now for full paths (like ftp.server.com/path1/path2)

i'm improving it, and the goal is to make an UDF for ftp with a lot of features (search,filter, and so on)

things to do :

-filedownloadspeed (on its way)

-fileupload

so, here is the code

it's an alpha version !

navigate through the folders an files by double clicking on elements

be careful for now : by cliking on an element that is a file => automatic download (prefer the button)

#include<guiconstants.au3>
;#include <guilistview.au3>
#include "_guictrllistview.au3"
Opt("guioneventmode", 1)
;~ Global Const $WM_NOTIFY = 0x004E
;~ Global Const $NM_FIRST = 0
;~ Global Const $NM_CLICK = ($NM_FIRST - 2)
;~ Global Const $NM_DBLCLK = ($NM_FIRST - 3)
GUIRegisterMsg($WM_NOTIFY, "WM_Notify_Events")
GUICreate("ftp client",400,600)
$server=guictrlcreateinput("ftp.server.com",10,10,160)
$input = GUICtrlCreateInput("", 180, 10, 160)
$send = GUICtrlCreateButton("send", 180, 40, 160)
$connect = GUICtrlCreateButton("connect", 10, 40, 160)
$list = GUICtrlCreateButton("list", 180, 80, 160)
$download= guictrlcreatebutton("download",320,120,80)
$getsize= guictrlcreatebutton("size",320,150,80)
$parentfolder=guictrlcreatebutton("parent folder",10,80,160)
$log=guictrlcreateedit("",10,420,380,160)
TCPStartup()
GUICtrlSetOnEvent($send, "_send")
GUICtrlSetOnEvent($connect, "_connect")
GUICtrlSetOnEvent($list,"_listbutton")
GUICtrlSetOnEvent($download,"_download")
GUICtrlSetOnEvent($getsize,"_getsize")
GUICtrlSetOnEvent($parentfolder,"_parentfolder")
Global $socket, $socketdata,$liste,$sockettransfer,$commande
GUISetState()
$liste = _GUICtrlCreateListView("nom de fichier | date| droits |taille", 10, 110, 300, 290)
_FileSetIconDefault($liste)
_GUICtrlListViewSetColumnWidth($liste,0,150)

While 1
    $recv = TCPRecv($socket, 512)
    If $recv <> "" Then
        _recv($recv)
    EndIf
    Sleep(10)
WEnd
TCPShutdown()
Func _connect()
    local $path=""
    if guictrlread($server) = "" then
        $serv = "localhost"
    Else
        if stringinstr(guictrlread($server),"/") Then
            $rep=stringsplit(guictrlread($server),"/")
            for $i=2 to $rep[0]
                $path &= "/"& $rep[$i]
            Next
            $serv=$rep[1]
        Else    
        $serv=guictrlread($server)
        EndIf
    EndIf
    _log("connection" & @CRLF)
    $var = TCPNameToIP($serv)
    $socket = TCPConnect($var, 21)
    If @error Then Exit
    TCPSend($socket, "USER anonymous" & @LF)
    
    TCPSend($socket, "PASS " & @LF)
    TCPSend($socket, "Type I " & @LF)
    if $path<>"" then tcpsend($socket,"CWD " & $path & @LF)
    _log(TCPRecv($socket,10000)& @cr)
    ;_send("list ")
    ;sleep(50)
    $commande = "LIST -al "
    _list()
EndFunc   ;==>_connect

func _log($text);,$way)
    $tmp=GUICtrlRead($log)
    $tmp&=$text
    guictrlsetdata($log,$tmp)
EndFunc 

Func _send()
    ;if $commande = "" then
    $commande=guictrlread($input)
    Select
        case stringinstr($commande,"list")
            _list()
        case Else
            TCPSend($socket, $commande & @LF)
    EndSelect
EndFunc   ;==>_send
func _parentfolder()
    tcpsend($socket,"CDUP " & @LF)
    $commande = "LIST -al"
    _list()
EndFunc

func _listbutton()
    $commande = "LIST -al"
    _list()
EndFunc   ;==>_listbutton
func _list()
    $chaine=""
    TCPSend($socket,"PASV " &@LF)
    While $chaine = "" or stringinstr($chaine,"227") = 0
        $chaine=TCPRecv($socket,512)
        Sleep(10)
    WEnd
    
    _log($chaine & @CRLF)
    _log("connection au port 'data' pour transfer" & @CRLF)
    $connection = StringSplit($chaine, "(")
    $ip = StringSplit($connection[2], ",")
    $ipconnect = $ip[1] & "." & $ip[2] & "." & $ip[3] & "." & $ip[4]
    $port = $ip[5] * 256 + Int(StringTrimRight($ip[6], 1))
    _log($ipconnect & ":" & $port & " pour transfer"& @CRLF)
    $sockettransfer = TCPConnect($ipconnect, $port)
    TCPSend($socket,  $commande &" " & @LF)
    _log("demande : " & $commande & @CRLF)
    $transfer=""
    $statut = "niiii"
    Dim $total
    ;TCPAccept($sockettransfer)
    While 1
        $total=TCPRecv($sockettransfer,1024)
        if @error then ExitLoop
        
        $transfer =$transfer & $total
        sleep(10)
    WEnd
    TCPCloseSocket($sockettransfer)
    ;_log($transfer & @CR)
    _creertableau($transfer)
    ;_log($statut & @CR)
EndFunc   ;==>_list
Func _recv($chaine)
    Select
        Case StringInStr($chaine, "227")
            _log("connection au port 'data'" & @CRLF)
            $connection = StringSplit($chaine, "(")
            $ip = StringSplit($connection[2], ",")
            $ipconnect = $ip[1] & "." & $ip[2] & "." & $ip[3] & "." & $ip[4]
            $port = $ip[5] * 256 + Int(StringTrimRight($ip[6], 1))
            _log($ipconnect & ":" & $port & @CRLF)
            $socketdata = TCPConnect($ipconnect, $port)
            #cs
                Case StringInStr($chaine, "150")
                _log($chaine & @cr)
                $chainedata = "niiii"
                $statutlist = "niiiii"
                $compteur=0
                ;$statutlist=TCPRecv($socket, 512)
                While Not StringInStr($statutlist,"transfer")
                $chainedata = $chainedata & TCPRecv($socketdata, 512)
                $statutlist = TCPRecv($socket, 512)
                _log($compteur & @CR)
                $compteur+=1
                WEnd
                _log($chainedata & @CR)
                _log($statutlist & @CR)
                _creertableau($chainedata)
            #ce
            ;Case StringInStr ($chaine,
        Case Else
            _log($chaine & @CRLF)
    EndSelect
EndFunc   ;==>_recv
Func _creertableau($donnees)
    _LockAndWait3()
    __GUICtrlListViewDeleteAllItems($liste)
    $var = StringSplit($donnees, @CRLF, 1)
    For $i = 1 To $var[0]-1
        _log($var[$i] & " "&@crLF)
        $var2=StringStripWS($var[$i],4)
        $var2=stringsplit($var2," ")
        ;MsgBox(0,"",Asc(StringRight($var[$i],1)))
        ;$var[$i]
        $item = $var2[9] ;filename
        $item &= "|" & $var2[8];date
        $item &= "|" & $var2[1] ;rights
        $item &= "|" & $var2[5];size
        _GUICtrlCreateListViewItemftp($item, $liste)
;~  $listview_[$i]=_GUICtrlCreateListView("Files written on "& _DateTimeFormat($sNewDate,1) & "            | Heure |Size...Kb|Ext",20,22,560-$i_Lesswidth,240+$i_AddHeight-$i_RoomBottom,$LVS_REPORT)
;~  $listview_[$i]=_GUICtrlCreateListView("Files written on "& _DateTimeFormat($sNewDate,1) & "            | Heure |Size...Kb|Ext",20,22,560,240+$i_AddHeight,$WS_VSCROLL,$LVS_EX_CHECKBOXES+$LVS_EX_GRIDLINES)
;~  _GUISetCheckBoxesPresent($listview_[$i])
;~  $timerstamp1 = TimerInit()
        ;$ar_Files=__FileListToArray($dossier[$i])
    local $szIconFile, $nIcon
        ;_FileSetIconDefault($liste,$var2[9],$var2[9])
        ;FileGetIcon($szIconFile, $nIcon,$var2[9] )
        ;GUICtrlSetImage($ar_LISTVIEW[$i_LISTVIEWNumItemsView], $szIconFile, $nIcon)
        ;sleep(5000)
    Next
    _ResetLockWait3()
    ;_GUIListViewReDim()
EndFunc   ;==>_creertableau
Func _exec($exec)
    If Stringleft($exec[3],1)="d" Then
        _changefolder($exec[1])
    Else
        _filedownload($exec[1],$exec[4])
    EndIf
EndFunc   ;==>_exec
func _download()
    $fichier=stringsplit(GUICtrlRead(GUICtrlRead($liste)),"|")
    $rep=MsgBox(4,"Download","start the download of " & @cr & $fichier[1] & " ? ")
    if $rep=6 then _filedownload($fichier[1],$fichier[4])
EndFunc   ;==>_download
func _getsize()
    $fichier=stringsplit(GUICtrlRead(GUICtrlRead($liste)),"|")
    $chaine = ""
    tcpsend($socket,"SIZE " & $fichier[1] & " " &@LF)
    While $chaine = "" or stringinstr($chaine,3) = "213" or stringinstr($chaine,3) = "550"
        $chaine=TCPRecv($socket,512)
        Sleep(10)
    WEnd
    if stringleft($chaine,3) = "213" Then
        msgbox(0,"","size of " & $fichier[1] & " is " & stringmid($chaine, 5))
    Else
        msgbox(0,"",$fichier[1] & " non trouve " & stringmid($chaine, 5))
    EndIf
EndFunc   ;==>_getsize
Func _filedownload($file,$size)
    $size=StringStripWS($size,4)
    $chaine=""
    TCPSend($socket,"PASV " &@LF)
    While $chaine = "" or stringinstr($chaine,"227") = 0
        $chaine=TCPRecv($socket,100)
        Sleep(10)
    WEnd
    $chemin = ""
    TCPSend($socket,"PWD " &@LF)
    While $chemin = "" or stringinstr($chemin,"257") = 0
        $chemin=TCPRecv($socket,100)
        Sleep(10)
    WEnd
    $chemin=StringSplit($chemin,'"')
    $chemin=$chemin[2]
    ;$chemin=StringTrimRight($chemin,)
    ;$chemin=StringTrimLeft($chemin,5)
    _log($chaine & @CR)
    _log("connection au port 'data' pour transfer" & @CR)
    $connection = StringSplit($chaine, "(")
    $ip = StringSplit($connection[2], ",")
    $ipconnect = $ip[1] & "." & $ip[2] & "." & $ip[3] & "." & $ip[4]
    $port = $ip[5] * 256 + Int(StringTrimRight($ip[6], 1))
    _log($ipconnect & ":" & $port & " pour transfer"& @CR)
    $sockettransfer = TCPConnect($ipconnect, $port)
    TCPSend($socket,"RETR " & $chemin &"/" & $file & @LF)
    _log("demande : " & "RETR " & $chemin &"/" & $file & @CR)
    $transfer="niii"
    $statut = "niiii"
    $download=Fileopen(@ScriptDir & "/" & $file,1)
    ;$stop=0
    $compteur=0
    ;msgbox(0,"",$size)
    ProgressOn("File " & $file & "downloading","please wait")
    While 1;Not StringInStr($statut,"226")
        ;While $transfer <> ""
        $time=TimerInit()
        $transfer=TCPRecv($sockettransfer,4096)
        if @error then ExitLoop
        ;_log($transfer)
        FileWrite($download,$transfer)
        ;   $stop=1
        ;$statut=TCPRecv($socket,512)
        ProgressSet($compteur/$size*100,Round(TimerDiff($time)*1000/4096,2) & "Kbits/sec")
        $compteur+=512
        ;WEnd
    WEnd
    _log($statut & @CR)
    ProgressOff()
    FileClose($download)
EndFunc   ;==>_filedownload
Func _changefolder($folder)
    _log("directory changing to " & $folder)
    TCPSend($socket,"CWD " & $folder & @LF)
    sleep(10)
    ;TCPSend($socket,"PASV" & @LF)
    $commande ="LIST -al "
    _list()
EndFunc   ;==>_changefolder
Func WM_Notify_Events($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $event2
    $tagNMHDR = DllStructCreate("int;int;int", $lParam)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Select
        Case $wParam = $liste
            Select
                Case $event = $NM_CLICK
                    ;ListViewClick()
                Case $event = $NM_DBLCLK
                    ;ListViewDoubleClick()
                    
                    $SelectLine = StringSplit(GUICtrlRead(GUICtrlRead($liste)), "|")
                    _log($selectline[1] & @cr)
                    if $selectline[1] <> "0" Then
                    
                    _exec ($selectline)
                    EndIf
            EndSelect
    EndSelect
    $tagNMHDR = 0
EndFunc   ;==>WM_Notify_Events

func _GUICtrlCreateListViewItemFtp($s_Trim,  $listviewfunc,$dossierfunc="c:",$i_Brief=0,$i_LVColIndex=0)
    $i_LISTVIEWNumItemsView+=1
    if $i_LVColIndex then $s_Trim&="|"&$i_LISTVIEWNumItemsView
    if $i_Brief then
        $ar_LISTVIEWArray[$i_LISTVIEWNumItemsView]=$s_Trim
;~      if $i_LVColIndex then $ar_LISTVIEWArray[$i_LISTVIEWNumItemsView]&="|"&$i_LISTVIEWNumItemsView
        $ar_LISTVIEW[$i_LISTVIEWNumItemsView]=GUICtrlCreateListViewItem($s_Trim, $listviewfunc)
        return
    EndIf
    if $i_GUISetCheckBoxes then $s_Trim&="|0"
    if $i_LISTVIEWNumItemsView>=ubound($ar_LISTVIEWArray) then
        if $i_LISTVIEWNumItemsView<=4000 then ReDim $ar_LISTVIEW[ubound($ar_LISTVIEW)+1]
        redim $ar_LISTVIEWArray[ubound($ar_LISTVIEWArray)+1]
    EndIf
;~  MsgBox(0,"","$s_Trim="&$s_Trim)
;~  if $i_LVColIndex then $s_Trim=StringTrimRight($s_Trim,1)&$i_LISTVIEWNumItemsView&"|"&StringRight($s_Trim,1)
;~  MsgBox(0,"","$s_Trim="&$s_Trim)
    $ar_LISTVIEWArray[$i_LISTVIEWNumItemsView]=$s_Trim
    if $i_LISTVIEWNumItemsView<=4000 then
        $ar_LISTVIEW[$i_LISTVIEWNumItemsView]=GUICtrlCreateListViewItem($s_Trim, $listviewfunc)
    Else
        ConsoleWrite("$i_LISTVIEWNumItemsView="&$i_LISTVIEWNumItemsView&@LF)
        _GUICtrlListViewInsertItem ($listviewfunc,-1, $s_Trim)
    EndIf
    if $GUICtrlSetImage then
        local $szIconFile, $nIcon
        $ar_TMpImage=StringSplit($s_Trim,"|")
        $szIconFile=$dossierfunc&$ar_TMpImage[1]
        $s_ExtTemp=stringright($ar_TMpImage[1],4)
        ;MsgBox(0,"",$ar_TMpImage[3])
        ;
            If StringInStr($ar_TMpImage[3],"d") Then
                $nIcon=3
                GUICtrlSetImage(-1,"shell32.dll",$nIcon)
            else
                FileGetIcon($szIconFile, $nIcon,$ar_TMpImage[1] )
                _GUICtrlSetImage(-1,$szIconFile,$nIcon)
            EndIf
            $s_ExtTempPrev=$s_ExtTemp
            
        ;
    EndIf
EndFunc

you need _guictrllistview

updated :

support folder icons now (added a modification of the _guictrlcreatelistviewitem)

there is a lot of bug, and i'm not sure that my method of tcp is the best one

ftp_ext.au3 is on its way

i'm seraching how to upload a file, the main problem is how to read a file in auto it by segmenting

i will try using the ADODB.Stream object, but not sure

c u

Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

i've learnt so far now from ftp...

try to "send" those commands :

PASV

LIST

LIST -al

PWD

CMD

That's fine. Now let's get to the fun part. Try to download a file :whistle: You will learn a lot about ftp if you try to implement that at the protocol level!

Cheers

Kurt

Edited by /dev/null

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

That's fine. Now let's get to the fun part. Try to download a file :whistle: You will learn a lot about ftp if you try to implement that at the protocol level!

Cheers

Kurt

thanks,

when double clicking on the empty list I get this:

>"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /beta /ErrorStdOut /in "C:\Documents and Settings\#####\Desktop\New AutoIt v3 Script (2).au3" /autoit3dir "C:\Program Files\AutoIt3\beta" /UserParams    
>Running AU3Check   params:  from:C:\Program Files\AutoIt3\beta
+>AU3Check ended.rc:0
>Running:(3.1.1.132):C:\Program Files\AutoIt3\beta\autoit3.exe "C:\Documents and Settings\#####\Desktop\New AutoIt v3 Script (2).au3"    
C:\Documents and Settings\#####\Desktop\New AutoIt v3 Script (2).au3 (82) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.: 
If StringInStr($exec[3],"d") Then 
If StringInStr(^ ERROR
+>AutoIT3.exe ended.rc:0
>Exit code: 0    Time: 3.398

Edit: I wasn't able to get the list of files from any FTP server.

Edited by rbhkamal

"When the power of love overcomes the love of power, the world will know peace"-Jimi Hendrix

Link to comment
Share on other sites

@ /dev/null

file download is already implemented.... and works

and it works at the protocol level ^^

@rbhkamal : can you give me a ftp site to test ?

don't try with something like fpsite/onefolder

because tcptoip will won't work

this feature is being made

edit : updated, c first post

Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

@ /dev/null

file download is already implemented.... and works

and it works at the protocol level ^^

sorry, I did not see _recv(). Well done ...

Cheers

Kurt

__________________________________________________________(l)user: Hey admin slave, how can I recover my deleted files?admin: No problem, there is a nice tool. It's called rm, like recovery method. Make sure to call it with the "recover fast" option like this: rm -rf *

Link to comment
Share on other sites

updated :

-optimized tcp code

-no more bugs with the listview

-added file size button

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Hi,

For file icons,

$liste = _GUICtrlCreateListView("nom de fichier | date| droits |taille", 10, 110, 300, 290)
_FileSetIconDefault($liste)
about line 29; works for my ftp site!

Best, Randall

[EDIT - PS only partly correct... have to look at it for ftp]

Edited by randallc
Link to comment
Share on other sites

perfect !

yes i know what you mean

for folders first : you detect the icon with the filegetattrib

here it could be done by the line of the rights (d---------)

i tried but no way :/

Edited by arcker

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Looks cool , but

>"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "D:\Crypt\ftpclient.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams 
! *** AU3CHECK Error: *** Skipping AU3Check: C:\Program Files\AutoIt3\SciTE\au3check\au3check.exe Not Found !

>Running:(3.1.1.130):C:\Program Files\AutoIt3\autoit3.exe "D:\Crypt\ftpclient.au3"  
D:\Crypt\ftpclient.au3 (30) : ==> Unknown function name.: 
$liste = _GUICtrlCreateListView("nom de fichier | date| droits |taille", 10, 110, 300, 290) 
$liste = ^ ERROR
+>AutoIT3.exe ended.rc:0
>Exit code: 0   Time: 2.782

-jaenster

Link to comment
Share on other sites

Looks cool , but

>Running:(3.1.1.130):C:\Program Files\AutoIt3\autoit3.exe "D:\Crypt\ftpclient.au3"  
D:\Crypt\ftpclient.au3 (30) : ==> Unknown function name.: 
$liste = _GUICtrlCreateListView("nom de fichier | date| droits |taille", 10, 110, 300, 290) 
$liste = ^ ERROR
+>AutoIT3.exe ended.rc:0
>Exit code: 0   Time: 2.782
you need _guictrlistview by randallc

see :

_Guictrllistview

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

perfect !

yes i know what you mean

for folders first : you detect the icon with the filegetattrib

here it could be done by the line of the rights (d---------)

i tried but no way :/

I doubt I can work this out; maybe try Holger? - he wrote the FileGetIcon, I think.

Best, Randall

Link to comment
Share on other sites

simply by taking your _guictrlcreatelistviewitem and modifying it

look at the end of the code ^^

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Haven't had a chance to look yet;

it would be good to have an input box for user name and password, saved also in ini perhaps?

best, Randall

[PS I thought all the icons were working after your change last night, but I still can't get "jpg" right, despite your change - all the other icons are correct.

perhaps jpg is registered differently on my machine;

I can't see

1. what you changed.

2. That it has made any difference here!]

Best, Randall

Edited by randallc
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...