PureBasic: sFTPc

Aus Wikibooks
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  sFTPc - a simple FTP client
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InitNetwork()

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Structure to handle FTP-connections
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Structure connection
  id.l
  adress.s
  user.s
  pass.s
  port.l
EndStructure

Declare establishConnection(List connections.connection())
Declare checkConnection(n.l)
Declare closeConnection(List connections.connection())
Declare fileManager(n.l)
Declare showDir(n.l)
Declare handleFileOptions(n.l)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  List for saving FTP-connections
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NewList connections.connection()

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  The menu
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure mainMenu(List connections.connection())
  Repeat
    
    ClearConsole()
    PrintN("sFTPc-Main Menu//")
    PrintN("1 - Open FTP Connection")
    PrintN("2 - Close FTP Connection")
    PrintN("3 - File-Manager")
    PrintN("4 - Quit")
    PrintN("")
    
    ;; Print opened connections
    If ListSize(connections()) > 0
      FirstElement(connections())
      ForEach connections()
        PrintN("Connection number: "+Str(connections()\id))
        PrintN("Adress: "+connections()\adress)
        PrintN("Username: "+connections()\user)
        Print("Connection: ")
        checkConnection(connections()\id)
        PrintN("")
      Next
    Else
      PrintN("There are currenty no opened connections.")
    EndIf
    
    Print("Choose: ")
    
    Select Val(Input())
      Case 1
        establishConnection(connections())
      Case 2
        closeConnection(connections())
      Case 3
        ClearConsole()
        Print("Connection number: ")
        n = Val(Input())
        If IsFTP(n)
          fileManager(n)
        Else
          PrintN("Not a valid connection!")
          Print("Push enter.")
          Input()
          Continue
        EndIf
      Case 4
        End
      Default
        PrintN("Not a valid option!")
        Print("Push enter.")
        Input()
        Continue
    EndSelect
  ForEver
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Procedure to open a new connection
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure establishConnection(List connections.connection())
  LastElement(connections())
  
  If Not ListSize(connections()) = 0
    lastID = connections()\id
  Else
    lastID = 0
  EndIf
  
  *newElement.connection = AddElement(connections())
  
  ClearConsole()
  *newElement\id = lastID + 1
  Print("URL or IP: ")
  *newElement\adress = Input()
  Print("Username: ")
  *newElement\user = Input()
  Print("Password: ")
  *newElement\pass = Input()
  Print("Port (default is 21): ")
  *newElement\port = Val(Input())
    
  If *newElement\port = 0
    *newElement\port = 21
  EndIf
  
  ;; Check if the connection can get opened
  If 0 = OpenFTP(*newElement\id,*newElement\adress,*newElement\user,*newElement\pass)
    PrintN("Could not open FTP-connection!")
    Print("Push enter.")
    Input()
    ;; Couldn't get opened? Delete the element, it's trash
    LastElement(connections())
    DeleteElement(connections())
  EndIf
  
  ProcedureReturn
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Check the state of opened connections
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure checkConnection(n.l)
  If 0 = CheckFTPConnection(n)
    PrintN("Disconnected!")
  Else
    PrintN("OK!")
  EndIf
  ProcedureReturn
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Close a specific connection
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure closeConnection(List connections.connection())
  ClearConsole()
  ;; Print current connections
  If ListSize(connections()) > 0
    FirstElement(connections())
    ForEach connections()
      PrintN("Connection number: "+Str(connections()\id))
      PrintN("Adress: "+connections()\adress)
      PrintN("Username: "+connections()\user)
      PrintN("")
    Next
  Else
    PrintN("There are currenty no opened connections.")
    Print("Push enter.")
    Input()
    ProcedureReturn
  EndIf
  
  Print("Choose Connection to close: ")
  n = Val(Input())
  
  If n <= 0 Or n > ListSize(connections()) Or (Not IsFTP(n))
    PrintN("Not a valid value!")
    Print("Push enter.")
    Input()
    ProcedureReturn
  EndIf
  
  CloseFTP(n)
  ForEach connections()
    If connections()\id = n
      Break
    EndIf
  Next
  
  DeleteElement(connections(),1)
  ProcedureReturn     
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  The build-in fileManager
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure fileManager(n.l)
  Repeat
    ClearConsole()
    
    showDir(n)
    
    PrintN("")
    PrintN("Type help for options.")
    Print("> ")
    
    If 1 = handleFileOptions(n)
      ProcedureReturn
    EndIf
  ForEver
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Show current directory
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure showDir(n.l)
PrintN("Current directory: "+GetFTPDirectory(n))
  ExamineFTPDirectory(n)
  
  ;; List files
  While NextFTPDirectoryEntry(n)
    attributes = FTPDirectoryEntryAttributes(n)
    If attributes & #PB_FTP_ReadUser
      Print("r")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_WriteUser
      Print("w")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_ExecuteUser
      Print("x")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_ReadGroup
      Print("r")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_WriteGroup
      Print("w")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_ExecuteGroup
      Print("x")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_ReadAll
      Print("r")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_WriteAll
      Print("w")
    Else
      Print("-")
    EndIf
    If attributes & #PB_FTP_ExecuteAll
      Print("x")
    Else
      Print("-")
    EndIf
    Print(" "+FTPDirectoryEntryName(n))
    If FTPDirectoryEntryType(n) = #PB_FTP_File
      PrintN(" File")
    ElseIf FTPDirectoryEntryType(n) = #PB_FTP_Directory
      PrintN(" Dir")
    Else
      PrintN("")
    EndIf
  Wend
  
  ProcedureReturn
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Handle the options of the fm
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Procedure handleFileOptions(n.l)
  option.s = Input()
  Select option
    Case "changeDir"
      Print("Dir: ")
      newDir.s = Input()
      SetFTPDirectory(n, newDir)
      ProcedureReturn 0
      
    Case "createDir"
      Print("Name: ")
      name.s = Input()
      CreateFTPDirectory(n, name)
      ProcedureReturn 0
      
    Case "deleteDir"
      Print("Name: ")
      name.s = Input()
      DeleteFTPDirectory(n, name)
      ProcedureReturn 0
      
    Case "delete"
      Print("Name: ")
      name.s = Input()
      DeleteFTPFile(n, name)
      ProcedureReturn 0
      
    Case "download"
      Print("Name: ")
      name.s = Input()
      Print("Name for saving: ")
      saveName.s = Input()
      ReceiveFTPFile(n, name, saveName)
      ProcedureReturn 0
      
    Case "exit"
      ProcedureReturn 1
      
    Case "help"
      PrintN("changeDir -> change directory")
      PrintN("createDir -> create directory")
      PrintN("deleteDir -> delete EMPTY directory")
      PrintN("delete -> delete file")
      PrintN("download -> download file")
      PrintN("exit -> return to main menu")
      PrintN("help -> this help")
      PrintN("rename -> rename file or directory")
      PrintN("send -> send file to server")
      Print("Push enter.")
      Input()
      ProcedureReturn 0
      
    Case "rename"
      Print("Old Name: ")
      name.s = Input()
      Print("New name: ")
      newName.s = Input()
      RenameFTPFile(n, name, newName)
      ProcedureReturn 0
      
    Case "send"
      Print("File: ")
      name.s = Input()
      Print("Name for saving: ")
      saveName.s = Input()
      SendFTPFile(n, name, saveName)
      ProcedureReturn 0
      
    Default
      PrintN("Not a valid option")
      Print("Push enter.")
      Input()
      ProcedureReturn 0
      
  EndSelect
EndProcedure

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Start the program
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
OpenConsole()
EnableGraphicalConsole(1)
mainMenu(connections())

Was soll das Programm tun?[Bearbeiten]

Dieses Programm stellt einen einfachen, konsolenbasierten FTP-Client dar. Wenn das Programm gestartet wird, sieht man im Terminal ein Menü. Über den ersten Menüpunkt kann man eine FTP-Session eröffnen, über den zweiten kann man sie wieder schließen und über den dritten kann man die Dateien auf dem FTP-Server durchsuchen und bearbeiten. Der vierte schließt das Programm wieder. Das Programm ist dabei in der Lage mehrere FTP-Sessions zu verwalten. Man muss immer angeben, welche Session gerade bearbeitet werden soll.

Wie funktioniert das Programm?[Bearbeiten]

Am Anfang wird über InitNetwork() die Netzwerk-Bibliothek geladen, wodurch die Befehle für die FTP-Verwaltung verfügbar werden. Die Struktur ist da, um die FTP-Verbindungen zu verwalten. Danach folgt die Deklaration mehrerer Verbindungen, sowie die Deklaration einer Liste, in der die FTP-Verbindungen, repräsentiert über die Struktur connection, orgranisiert werden. Danach werden die Prozeduren definiert. Ganz am Ende des Programmes wird die Konsole geöffnet. EnableGraphicalConsole(1) ermöglicht das Löschen des Inhalts der Konsole. Der letzte Befehl ruft das Hauptmenü auf, dass in der ersten Prozedur definiert ist.

  • mainMenu(): Die Prozedur erwartet, dass man ihr die Liste mit den Verbindungen übergibt. Es wird lediglich das Menü dargestellt und auf Eingaben mittels Fallunterscheidungen reagiert. Wenn FTP-Verbindungen eröffnet wurden, stellt das Programm diese dar. Beim Schließen des Programms muss nicht darauf geachtet werden, dass alle Verbindungen geschlossen werden, dies wird automatisch beim Schließen erledigt.
  • establishConnection(): Diese Prozedur erwartet ebenfalls die Liste der Verbindungen. Zuerst wird die Nummer der letzten FTP-Verbindung herausgefunden. Das ist wichtig für die Vergabe einer Nummer an die neue Verbindung. Danach wird ein neues Element zur Liste hinzugefügt. AddElement() gibt die Adresse des neuen Elements zurück, die im Zeiger gespeichert wird. Über den Zeiger wird danach auf das Element zugegriffen und die Daten werden eingegeben. Mit OpenFTP() wird dann versucht die Verbindung herzustellen. Wenn sie nicht hergestellt werden kann, wird sie gelöscht.
  • checkConnection(): Diese Prozedur überprüft lediglich, ob die Verbindung noch besteht. Dies wird im Hauptmenü genutzt, wo dies angezeigt wird.
  • closeConnection(): Es werden alle geöffneten Verbindungen angezeigt. Man wählt eine aus und diese wird geschlossen und aus der Liste gelöscht. Es wird dabei überprüft, ob es sich wirklich um eine geöffnete Verbindung handelt.
  • fileManager(): Diese Prozedur steuert den Dateimanager. Es wird das aktuell ausgewählte Verzeichnis angezeigt und man kann mit diesem interagieren.
  • showDir(): Es wird einfach der Inhalt des Verzeichnis aufgelistet, zusammen mit den Rechten des Benutzers, mit dem die Verbindung eröffnet wurde.
  • handleFileOptions(): Diese Prozedur wird aus fileManager() aufgerufen. Man kann verschiedene Befehle eingeben. Welche das sind, wird über den Befehl help angezeigt.