FTP Request
FTP Request
FTP Request
def get_port(port:int):
if port > 2**16-1:
raise ValueError("Unsupported port format: a port is a 16 bits or 2 bytes
unsigned integer")
port_str = "{0:b}".format(port)
while len(port_str) < 16:
port_str = "0" + port_str
return (int(port_str[0:8], 2), int(port_str[8:len(port_str)], 2))
def listener(port):
_socketListener = socket(AF_INET, SOCK_STREAM)
_socketListener.bind(("localhost", port))
while True:
_socketListener.listen()
conn = _socketListener.accept()[0]
while True:
r = select.select([conn], [], [])[0]
b = b""
if r != []:
b = conn.recv(128)
a += b
if len(b) < 128:
break
if a != b"":
print(a)
a = b""
_default_commands_port = 21
_default_data_port = 20
_version = 3659
_default_cmds = ["ABOR", "ACCT", "ALLO", "APPE", "DELE", "HELP", "LIST", "MKD",
"MODE", "NLST", "NOOP", "PASS", "PASV", "PORT", "QUIT", "REIN", "REST", "RETR",
"RNFR", "RNTO", "SITE", "STAT", "STOR", "STRU", "TYPE", "USER"]
class FileTransferProtocolError(ValueError):
pass
"""
Code Description
110 Restart marker reply.
120 Service ready in nnn minutes.
125 Data connection already open; transfer starting.
150 File status okay; about to open data connection.
200 Command okay.
202 Command not implemented, superfluous at this site.
211 System status, or system help reply.
212 Directory status.
213 File status.
214 Help message.
215 NAME system type.
220 Service ready for new user.
221 Service closing control connection.
225 Data connection open; no transfer in progress.
226 Closing data connection.
227 Entering Passive Mode <h1,h2,h3,h4,p1,p2>.
228 Entering Long Passive Mode.
229 Extended Passive Mode Entered.
230 User logged in, proceed.
250 Requested file action okay, completed.
257 "PATHNAME" created.
331 User name okay, need password.
332 Need account for login.
350 Requested file action pending further information.
421 Service not available, closing control connection.
425 Can't open data connection.
426 Connection closed; transfer aborted.
450 Requested file action not taken.
451 Requested action aborted. Local error in processing.
452 Requested action not taken.
500 Syntax error, command unrecognized.
501 Syntax error in parameters or arguments.
502 Command not implemented.
503 Bad sequence of commands.
504 Command not implemented for that parameter.
521 Supported address families are <af1, .., afn>
522 Protocol not supported.
530 Not logged in.
532 Need account for storing files.
550 Requested action not taken.
551 Requested action aborted. Page type unknown.
552 Requested file action aborted.
553 Requested action not taken.
554 Requested action not taken: invalid REST parameter.
555 Requested action not taken: type or stru mismatch.
Série Résultat
1xx Réponse d’initiation positive
L’action demandée a été correctement initiée ; Il faut toutefois attendre la
prochaine réponse pour lancer une nouvelle commande.
Envoyer une autre commande avant la réponse d’achèvement constituerait une
violation du protocole, mais les serveurs FTP sont censés mettre en attente toute
commande arrivant pendant l’exécution de la commande en cours.
Ce type de réponse permet d’indiquer que la commande a été acceptée et que les
connexions aux données sont en cours, notamment pour les cas où le suivi en temps
réel de la commande est difficile. Le processus sur le serveur FTP peut envoyer au
plus une réponse de ce type par commande.
2xx Réponse d'achèvement positif
L'action demandée a été effectuée avec succès. Une nouvelle demande peut être
initiée.
3xx Réponse intermédiaire positive
La commande a été acceptée, mais l’action requise ne peut pas encore être exécutée,
par manque d’information. L’utilisateur doit envoyer une autre commande en donnant
les informations requises.
Cette réponse est utilisée avec les groupes de commandes.
4xx Réponse temporaire d’achèvement négatif
La commande n’a pas été acceptée, et l’action requise n’a pas eu lieu, mais
l’erreur est temporaire, et l’action pourra être réessayée plus tard. L’utilisateur
doit revenir au début de la séquence de commandes. Il est difficile d’attribuer une
signification précise à "temporaire" ou "transitoire", surtout quand les processus
côté serveur et côté utilisateur doivent se mettre d’accord sur l’interprétation à
apporter. Chaque réponse de la catégorie 4xx peut avoir une valeur temporelle
différente, mais l’interprétation globale est que le processus utilisateur est
encouragé à réessayer. Pour déterminer si une réponse appartient à la catégorie 4xx
ou 5xx (Réponse permanente négative), on considère que la catégorie 4xx est pour
les réponses négatives aux commandes pouvant être relancées sans changement dans
leur forme ou leurs propriétés (mêmes arguments, mêmes fichiers, même
implémentation du serveur).
5xx Réponse permanente d’achèvement négatif
La commande n’a pas été acceptée, et l’action requise n’a pas eu lieu. Le processus
utilisateur ne doit pas répéter la même requête (dans la même séquence). Cependant,
certaines erreurs "permanentes" peuvent être corrigées, et l’utilisateur peut
indiquer à son processus de réinitialiser sa séquence de commandes directement à un
certain moment à l’avenir (par exemple, après un changement d’orthographe, ou de
statut du dossier courant).
6xx Réponse protégée
La norme RFC 2228 amène le concept des réponses protégées pour améliorer la
sécurité des communications utilisant le protocole FTP. Les réponses en 6xx sont
encodées en Base64, et sont utilisées comme réponses pour les commandes sécurisées.
Une fois correctement décodées, ces réponses se retrouvent dans les catégories ci-
dessus.
"""
"""
FTP SAMPLE:
Command:LIST Response:150 Opening ASCII mode data connection for file list.
Response:226 Transfer complete. Status:Directory listing successful
"""
def ftp_recv(sock):
from select import select
while True:
r, w, e = select([sock], [], [])
if r != []:
break
multiple_lines = False
status_code = sock.recv(3)
c = b""
c += sock.recv(1)
returned = status_code + c
del status_code
if c == b"-":
multiple_lines = True
del c
while True:
returned += sock.recv(1024)
if returned.decode('ascii').split("\r\n")
[len(returned.decode('ascii').split("\r\n"))-
2].startswith(returned[:3].decode('ascii')+" ") and multiple_lines:
break
if returned[len(returned)-2:len(returned)] == b"\r\n" and not
multiple_lines:
break
return returned
class FTPListener(Thread):
def __init__(self, address, port):
Thread.__init__(self)
self.daemon = True
self.host = address
self.port = port
self._socket = socket(AF_INET, SOCK_STREAM)
self._socket.bind((self.host, self.port))
def run(self):
a = b""
while True:
self._socket.listen()
conn, addr = self._socket.accept()
while True:
r, w, e = select.select([conn], [], [])
b = b""
if r != []:
b = conn.recv(128)
a += b
if len(b) < 128:
break
if a != b"":
print(a)
a = b""
a = FTPListener('192.168.1.73', 56000)
a.start()
ftp_terminal()