1. TugaTech » Programação, Scripts e Webmasters » Tutoriais e Dicas
Siga-nos

Realize o Login na sua conta ou Registe-se para participar.

Ver o tópico anterior Ver o tópico seguinte Ir para baixo  Mensagem [Página 1 de 1]

#1Lâmpada [Python] Simple FTP Server - Sáb 26 maio 2012 - 19:39

zordY

Graúdo
zordY
Olá, mais uma vez comunidade!

Vou postar um pequeno trabalho que realizei, em python Razz

Código:

======================================================================= #
# Copyright (C) 20011-2012 Daneil Lameira' #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see . #
# #
#############################################################################
import os
import sys
import socket
from select import select
import asyncore
import time
import threading

#CONFIG FILE NAME
CONFIG_FILE = "Mikan-FTPd-config.cfg"
#SOCKET MESSAGE LEN
MSGLEN = 1024*256#4096

def getConfig():
try:
fd = open(os.path.join(os.getcwd(), CONFIG_FILE), "r")
except:
return False

cfg = {}
while True:
ln = fd.readline()
if not len(ln):
return cfg
ln = ln.replace("\r", "").replace("\n", "")
if ln[:1] != '#':
opt = ln.split("=")
if len(opt) == 2:
cfg[opt[0]] = opt[1]

class _Info:
def __init__( self, *args, **kwargs ):
self.__dict__.update( kwargs )

class ftpd:

def __init__(self, exitEvent, shareFolder, config):
log("FTPd - Initializing server")
self.config = config
self.exitEvent = exitEvent
self.shareFolder = shareFolder
self.mainsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.mainsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.mainsock.setblocking( False )
try:
self.mainsock.bind( ("127.0.0.1", int( self.config["bind_port"] ) ) )
except:
log( "FTPd - Error using bind_port=" )
log( "FTPd - Please check the %s file" % CONFIG_FILE )
return False

log( "FTPd - Running on ftp://127.0.0.1:%s" % ( self.config["bind_port"]))
if self.config["username"]:
log( "FTPd - Username: %s" % self.config["username"] )
if self.config["password"]:
log( "FTPd - Password: %s" % self.config["password"] )

self.mainsock.listen( 5 )
self.threads = []

def addFile(self, file):
self.shareFolder += file

def start(self):
clientCon = _Info()

log( "FTPd - Awaiting for connections..." )

while (True):
r_read, r_write, r_err = select([ self.mainsock ],[],[], 0.1)

if self.exitEvent.isSet():
break
elif len(r_read) and r_read[0] == self.mainsock:
(client , clientCon.addr) = self.mainsock.accept ()
clientCon.ip_addr = ','.join(clientCon.addr[0].split('.'))

self.clearThreads()

log( "FTPd - Connection created by %s." % clientCon.ip_addr )
name = "Thread-%s" % str(len(self.threads)+1)
t = _ftpd_manager_theread(name, client, self.shareFolder, self.exitEvent, self.config)
t.start()
self.threads.append(t)

log( "FTPd - Waiting for all threads to exit." )
for thread in self.threads:
thread.join()

def clearThreads(self):
n = []
for thread in self.threads:
if thread.isAlive():
n.append(thread)

self.threads = n

class _ftpd_manager_theread(threading.Thread):
def __init__(self, name, client, shareFolder, exitEvent, config):
threading.Thread.__init__(self)
self.ftpd = _ftpd_manager(name, client, shareFolder, exitEvent, config)

def run(self):
self.ftpd.start()

class _ftpd_manager:

def __init__(self, name, client, shareFolder, exitEvent, config):
self.config = config
self.shareFolder = shareFolder
self.pileWork = []
self.client = client
self.pasvConn = _Info()
self.pasvConn.rest = 0
self.pasvConn.connected = False
self.name = name
self.exitEvent = exitEvent

def start(self):
inLoop = True

log( "FTPd:%s - Establishing session." % self.name, True)
self.put( "220 127.0.0.1 Mikan FTPd Server ready." )

while True:
try:
while True:
r_read, r_write, r_err = select([ self.client ],[],[], 0.1)
#print str(self.exitEvent.isSet()) + "\n"
if self.exitEvent.isSet():
log( "FTPd:%s - Event recieved, calling _exit() method" % self.name)
self._exit()
elif len(r_read) and r_read[0] == self.client:
data = self.get()#.upper()
break

except socket.error:
print "WARNING: %s - %s::%s (%d) - %s" % ( self.name, self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
self._exit()

log( "FTPd:%s <<< %s " % (self.name, data) )

if data[:4] == 'USER':
if not len(self.config["username"]) or self.config["username"] == data[5:]:
self.put( "331 User name okay, need password." )
else:
self.put( "530 User %s cannot log in." % data[5:] )
self._exit()
elif data[:4] == 'PASS':

if not len(self.config["password"]) or self.config["password"] == data[5:]:
self.put( "230 User logged in, proceed." )
else:
self.put( "530 User %s cannot log in." % data[5:] )
self._exit()

elif data[:3] == 'PWD':
self.put( '257 "/" is cwd.' )
elif data[:4] == 'TYPE':
self.put( "200 Type okay." )
elif data[:4] == 'PASV':
self.openPasvConnection()
elif data[:3] == 'CWD':
self.put( '250 "/" is new cwd.' )
elif data[:4] == 'NOOP':
self.put( "200 NOOP ZzZ zZz." )
elif data[:4] == 'FEAT':
self.put( "211-Features")
self.put("MDTM")
self.put("SIZE")
self.put("REST STREAM")
self.put("211 End")
elif data[:4] == 'SYST':
self.put( "215 %s." % os.environ.get( "OS", "n/a" ) )
elif data[:4] == 'QUIT':
self.put( "221 Bye Bye" )
self._exit()
elif data[:4] == 'ABOR':
self._closePasvConnection()
elif data[:4] == 'LIST':
if self.pasvConn.connected:
self.listVirtualDir()
self._closePasvConnection()
elif data[:4] == 'REST':
self.pasvConn.rest = int(data[5:])
self.put( "350 Restarting at %s. Send STORE or RETRIEVE to initiate transfer" % data[5:] )
elif data[:4] == 'SIZE':
f = self._fileExist( data[5:] )
if bool(f):
self.put( "213 %s" % self._filesize( f ))
elif data[:4] == 'MDTM':
f = self._fileExist( data[5:] )
if bool(f):
self.put( "213 20091021064247" )
elif data[:4] == 'RETR':
f = self._fileExist( data[5:] )
if bool(f):
if self.pasvConn.connected:
self.sendFile( f )
self._closePasvConnection()
else:
self._closePasvConnection()
else:
self.put( "502 Command not implemented." )

def _exit(self):
self._closePasvConnection()
self._closeConnection()
log( "FTPd:%s - Exiting" % self.name, True )
sys.exit()
#self.EXIT = True

def _filesize(self, name):
return os.path.getsize( os.path.join( self.shareFolder, name ) )

def _fileExist(self, name):
name = os.path.basename(name)
if self._getVirtualFile( name ):
return name
else:
self.put( "550 %s: No such file or directory" % name )
return False

def _getVirtualFile(self, name):
return os.path.isfile( os.path.join( self.shareFolder, name ) )

def listVirtualDir(self):
self.put( "125 Data connection already open; Transfer starting." )

try:
for fn in os.listdir( self.shareFolder ):
file = os.path.join(self.shareFolder, fn)
if os.path.isfile(file):
self.pasv.send( "-rw-r--r-- 1 mikan mikan %s Oct 21 2009 %s\r\n" % (os.path.getsize(file) , fn) )
self.pasv.send( "\r\n" )
except:
log( "WARNING: %s - %s::%s (%d) - %s" % ( self.name, self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], ) )
self.put( "226 Listing completed." )

def _closeConnection(self):
self.client.close()
#self.mainsock.shutdown(socket.SHUT_RDWR)

def _closePasvConnection(self):
if self.pasvConn.connected:
try:
self.pasv.close()
except:
log( "WARNING: %s - %s::%s (%d) - %s" % ( self.name, self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], ) )
self.pasvConn.connected = False

def openPasvConnection(self):
try:
self.pasvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.pasvsock.bind( ("127.0.0.1", 0) )
self.pasvsock.listen(1)
self.pasvsock.settimeout(10)
self.pasvConn.port = self.pasvsock.getsockname()[1]
msg = "227 Entering Passive Mode (%s,%s,%s)" % ("127,0,0,1", str(self.pasvConn.port/256), str(self.pasvConn.port%256)),
self.put( msg )
(self.pasv, self.pasvConn.addr) = self.pasvsock.accept()
self.pasvConn.connected = True
except:
log( "WARNING: %s - %s::%s (%d) - %s" % ( self.name, self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], ) )

def sendFile(self, f):
self.put( "150 Opening BINARY mode data connection for %s (%s bytes)" % (f, self._filesize(f)) )
clientQuit = False

file = os.path.join(self.shareFolder, f)

fd = open(file, "rb")
fd.seek(self.pasvConn.rest)

while True:
if self.exitEvent.isSet():
fd.close()
self._exit()

chunk = fd.read(self.MSGLEN)
totalsent = 0
if chunk == "":
break

try:
select([], [ self.pasv ], [])
self.pasv.sendall( chunk )
except:
log( "FTPd - socket connection broken/closed" )
clientQuit = True
break
fd.close()

if not clientQuit:
self.put( "226 Transfer complete." )

self.pasvConn.rest = 0

def getcwd(self):
return "/"

def get(self):
return self.client.recv(1024).replace('\r', '').replace('\n', '')

def put(self, msg):
s = '%s\r\n' % (msg)

select([], [ self.client ], [])
sended = self.client.send(s)
if sended == 0:
log( "FTPd - socket connection broken, exiting .." )
self._exit()

log( "FTPd:%s >>> %s" % (self.name, msg) )

def log( msg, flag=True ):
global _init_mode

if not _init_mode["silent"]:
print msg

#if bool( _init_mode["debug_file"] ):
# _init_mode["debug_file"].write(msg)

class threadingFTPd(threading.Thread):
def __init__(self, exitEvent, virtualFiles, config):
threading.Thread.__init__(self)
self.ftpd = ftpd(exitEvent, virtualFiles, config)

def run(self):
self.ftpd.start()

if ( __name__ == "__main__" ):
shareFolder = ""
_init_mode = {
'silent' : False,
'debug_file' : False,
'pipe' : False
}

config = getConfig()
if not config:
print "FTPd - CRITICAL ERROR"
print "FTPd - No configuration file : %s" % CONFIG_FILE
sys.exit(1)

shareFolder = sys.argv[ len(sys.argv)-1 ]

log("FTPd - Sharing folder %s" % shareFolder)

if not os.path.isdir( shareFolder ):
print "invalid share dir"
print "Usage: %s [options] share_dir_name" % os.path.basename(sys.argv[0])
print "Options:"
print "-s: silent mode"
#print "-d: debug mode"
sys.exit()

for i in range(1, len(sys.argv)):

#Initiates silent mode
if sys.argv[i] == '-s' or sys.argv[i] == '--silent':
_init_mode["silent"] = True
elif sys.argv[i] == '-p' or sys.argv[i] == '--pipe':
log("FTPd - Pipes ON")
_init_mode["pipe"] = True
"""
#Initiates debug mode
elif sys.argv[i] == '-d' or sys.argv[i] == '--debug':
if os.path.isfile("ftpd-log.txt"):
old_log = os.path.join(os.getcwd(), "ftpd-log-old.txt")
if os.path.isfile(old_log):
os.unlink(old_log)
os.rename(os.path.join(os.getcwd(), "ftpd-log.txt"), old_log )
_init_mode["debug_file"] = open("ftpd-log.txt", "w")
"""

exitEvent = threading.Event()
FTPd = threadingFTPd(exitEvent, shareFolder, config)
FTPd.start()

if _init_mode["pipe"]:
open("stdin-pipe", "w").close()
stdin_pipe = open("stdin-pipe", "r")
size = 0

try:
while True:
cmd = ""

if _init_mode["pipe"]:
time.sleep(0.5)

if size != os.path.getsize("stdin-pipe"):
size = os.path.getsize("stdin-pipe")
cmd = stdin_pipe.readline().replace("\r", "").replace("\n", "")
else:
cmd = sys.stdin.readline().replace("\r", "").replace("\n", "")

if cmd != '':
if cmd == "quit":
break
else:
print "FTPd - Not found '%s'" % cmd
print "FTPd - ##################"
print "FTPd - quit - Exit FTPd"

if not FTPd.isAlive():
break;

except KeyboardInterrupt:
print "FTPd - Ctr-C detected"

exitEvent.set()
FTPd.join()

if bool(_init_mode["debug_file"]):
_init_mode["debug_file"].close()
if _init_mode["pipe"]:
stdin_pipe.close()

Créditos: zordY. > Próximo projeto, a pensar Rolling Eyes

#2Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 19:41

DJPRMF

Administrador
DJPRMF
Boas,

Qual é o objectivo/funcionalidade ao certo?
Wink


____________________________________________

[Python] Simple FTP Server Tugatechuserbar
[Python] Simple FTP Server 3
[Python] Simple FTP Server 2
TugaTech || Host TugaTech
https://tugatech.com.pt https://www.facebook.com/DJPRMF https://twitter.com/dj_prmf DJPRMF

#3Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 19:50

zordY

Graúdo
zordY
Para quem perçebe, como tu deves perçeber, isso é um genero de filezila.

Tens aí o codigo, se te quizeres, lançar, para um novo projeto do género, tens aí o code Smile

Mas, eu uso, para conectar-me aos meus servidores..

#4Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 21:03

DJPRMF

Administrador
DJPRMF
Era só para adicionar um pouco de descrição ao código em si, para quem não saiba. Very Happy


____________________________________________

[Python] Simple FTP Server Tugatechuserbar
[Python] Simple FTP Server 3
[Python] Simple FTP Server 2
TugaTech || Host TugaTech
https://tugatech.com.pt https://www.facebook.com/DJPRMF https://twitter.com/dj_prmf DJPRMF

#5Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 21:09

zordY

Graúdo
zordY
Tranquilo Mad

Obrigado,

#6Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 22:40

Diogomendes23

Avançado
Diogomendes23
xD Sou novato em programação,mas interessai me por esse tutorial...
zorDy Podias me explicar melhor para que serve ao certo esta funcionalidade? xD desculpa o incomodo Sad

Very Happy Sad Surprised Laughing Mad

#7Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 22:41

zordY

Graúdo
zordY
Isso é para tu, fazeres o teu próprio filezilla !

Alguma dúvida/erro apita.

Obrigado,

#8Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 22:46

Diogomendes23

Avançado
Diogomendes23
Obrigado Ja percebi Wink

#9Lâmpada Re: [Python] Simple FTP Server - Sáb 26 maio 2012 - 22:50

zordY

Graúdo
zordY
Na boa, estou a desenvolver, um mini, script para depois, postar para vocês.

Obrigado,

Ver o tópico anterior Ver o tópico seguinte Ir para o topo  Mensagem [Página 1 de 1]

Permissões neste sub-fórum
Não podes responder a tópicos




Aplicações do TugaTechAplicações TugaTechDiscord do TugaTechDiscord do TugaTechRSS TugaTechRSS do TugaTechSpeedtest TugaTechSpeedtest TugatechHost TugaTechHost TugaTech