Skip to content

Instantly share code, notes, and snippets.

@humanium
Forked from scturtle/ftpserver.py
Created May 22, 2014 14:44

Revisions

  1. @scturtle scturtle revised this gist Aug 16, 2012. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion ftpserver.py
    Original file line number Diff line number Diff line change
    @@ -34,6 +34,13 @@ def run(self):
    #traceback.print_exc()
    self.conn.send('500 Sorry.\r\n')

    def SYST(self,cmd):
    self.conn.send('215 UNIX Type: L8\r\n')
    def OPTS(self,cmd):
    if cmd[5:-2].upper()=='UTF8 ON':
    self.conn.send('200 OK.\r\n')
    else:
    self.conn.send('451 Sorry.\r\n')
    def USER(self,cmd):
    self.conn.send('331 OK.\r\n')
    def PASS(self,cmd):
    @@ -86,7 +93,7 @@ def PASV(self,cmd): # from http://goo.gl/3if2U
    ip, port = self.servsock.getsockname()
    print 'open', ip, port
    self.conn.send('227 Entering Passive Mode (%s,%u,%u).\r\n' %
    ('.'.join(ip.split(',')), port>>8&0xFF, port&0xFF))
    (','.join(ip.split('.')), port>>8&0xFF, port&0xFF))

    def start_datasock(self):
    if self.pasv_mode:
    @@ -159,6 +166,7 @@ def REST(self,cmd):

    def RETR(self,cmd):
    fn=os.path.join(self.cwd,cmd[5:-2])
    #fn=os.path.join(self.cwd,cmd[5:-2]).lstrip('/')
    print 'Downlowding:',fn
    if self.mode=='I':
    fi=open(fn,'rb')
    @@ -214,5 +222,6 @@ def stop(self):
    ftp=FTPserver()
    ftp.daemon=True
    ftp.start()
    print 'On', local_ip, ':', local_port
    raw_input('Enter to end...\n')
    ftp.stop()
  2. @scturtle scturtle revised this gist Jul 6, 2012. 1 changed file with 52 additions and 17 deletions.
    69 changes: 52 additions & 17 deletions ftpserver.py
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,11 @@
    # coding: utf-8

    import os,socket,threading,time
    import traceback
    #import traceback

    allow_delete = False
    local_ip = socket.gethostbyname(socket.gethostname())
    local_port = 8888
    currdir=os.path.abspath('.')

    class FTPserverThread(threading.Thread):
    @@ -13,6 +16,7 @@ def __init__(self,(conn,addr)):
    self.basewd=currdir
    self.cwd=self.basewd
    self.rest=False
    self.pasv_mode=False
    threading.Thread.__init__(self)

    def run(self):
    @@ -34,6 +38,7 @@ def USER(self,cmd):
    self.conn.send('331 OK.\r\n')
    def PASS(self,cmd):
    self.conn.send('230 OK.\r\n')
    #self.conn.send('530 Incorrect.\r\n')
    def QUIT(self,cmd):
    self.conn.send('221 Goodbye.\r\n')
    def NOOP(self,cmd):
    @@ -65,20 +70,46 @@ def CWD(self,cmd):
    self.conn.send('250 OK.\r\n')

    def PORT(self,cmd):
    if self.pasv_mode:
    self.servsock.close()
    self.pasv_mode = False
    l=cmd[5:].split(',')
    self.dataAddr='.'.join(l[:4])
    self.dataPort=(int(l[4])<<8)+int(l[5])
    self.conn.send('200 Get port.\r\n')

    def PASV(self,cmd): # from http://goo.gl/3if2U
    self.pasv_mode = True
    self.servsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.servsock.bind((local_ip,0))
    self.servsock.listen(1)
    ip, port = self.servsock.getsockname()
    print 'open', ip, port
    self.conn.send('227 Entering Passive Mode (%s,%u,%u).\r\n' %
    ('.'.join(ip.split(',')), port>>8&0xFF, port&0xFF))

    def start_datasock(self):
    if self.pasv_mode:
    self.datasock, addr = self.servsock.accept()
    print 'connect:', addr
    else:
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))

    def stop_datasock(self):
    self.datasock.close()
    if self.pasv_mode:
    self.servsock.close()


    def LIST(self,cmd):
    self.conn.send('150 Here comes the directory listing.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    print self.cwd
    print 'list:', self.cwd
    self.start_datasock()
    for t in os.listdir(self.cwd):
    k=self.toListItem(os.path.join(self.cwd,t))
    self.datasock.send(k+'\r\n')
    self.datasock.close()
    self.stop_datasock()
    self.conn.send('226 Directory send OK.\r\n')

    def toListItem(self,fn):
    @@ -98,13 +129,19 @@ def MKD(self,cmd):

    def RMD(self,cmd):
    dn=os.path.join(self.cwd,cmd[4:-2])
    #os.rmdir(dn)
    self.conn.send('250 Directory deleted.\r\n')
    if allow_delete:
    os.rmdir(dn)
    self.conn.send('250 Directory deleted.\r\n')
    else:
    self.conn.send('450 Not allowed.\r\n')

    def DELE(self,cmd):
    fn=os.path.join(self.cwd,cmd[5:-2])
    #os.remove(fn)
    self.conn.send('250 File deleted.\r\n')
    if allow_delete:
    os.remove(fn)
    self.conn.send('250 File deleted.\r\n')
    else:
    self.conn.send('450 Not allowed.\r\n')

    def RNFR(self,cmd):
    self.rnfn=os.path.join(self.cwd,cmd[5:-2])
    @@ -128,17 +165,16 @@ def RETR(self,cmd):
    else:
    fi=open(fn,'r')
    self.conn.send('150 Opening data connection.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    if self.rest:
    fi.seek(self.pos)
    self.rest=False
    data= fi.read(1024)
    self.start_datasock()
    while data:
    self.datasock.send(data)
    data=fi.read(1024)
    fi.close()
    self.datasock.close()
    self.stop_datasock()
    self.conn.send('226 Transfer complete.\r\n')

    def STOR(self,cmd):
    @@ -149,20 +185,19 @@ def STOR(self,cmd):
    else:
    fo=open(fn,'w')
    self.conn.send('150 Opening data connection.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    self.start_datasock()
    while True:
    data=self.datasock.recv(1024)
    if not data: break
    fo.write(data)
    fo.close()
    self.datasock.close()
    self.stop_datasock()
    self.conn.send('226 Transfer complete.\r\n')

    class FTPserver(threading.Thread):
    def __init__(self):
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.bind(('',8888))
    self.sock.bind((local_ip,local_port))
    threading.Thread.__init__(self)

    def run(self):
    @@ -180,4 +215,4 @@ def stop(self):
    ftp.daemon=True
    ftp.start()
    raw_input('Enter to end...\n')
    ftp.stop()
    ftp.stop()
  3. @scturtle scturtle revised this gist Jun 21, 2011. 1 changed file with 68 additions and 28 deletions.
    96 changes: 68 additions & 28 deletions ftpserver.py
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,7 @@ def __init__(self,(conn,addr)):
    self.addr=addr
    self.basewd=currdir
    self.cwd=self.basewd
    self.rest=False
    threading.Thread.__init__(self)

    def run(self):
    @@ -25,14 +26,10 @@ def run(self):
    func=getattr(self,cmd[:4].strip().upper())
    func(cmd)
    except Exception,e:
    print e
    print 'ERROR:',e
    #traceback.print_exc()
    self.conn.send('500 Sorry.\r\n')

    def LoadCwd(self):
    os.chdir(self.cwd)
    def SaveCwd(self):
    self.cwd=os.getcwd()
    def USER(self,cmd):
    self.conn.send('331 OK.\r\n')
    def PASS(self,cmd):
    @@ -46,9 +43,9 @@ def TYPE(self,cmd):
    self.conn.send('200 Binary mode.\r\n')

    def CDUP(self,cmd):
    self.LoadCwd()
    os.chdir('..')
    self.SaveCwd()
    if not os.path.samefile(self.cwd,self.basewd):
    #learn from stackoverflow
    self.cwd=os.path.abspath(os.path.join(self.cwd,'..'))
    self.conn.send('200 OK.\r\n')
    def PWD(self,cmd):
    cwd=os.path.relpath(self.cwd,self.basewd)
    @@ -58,34 +55,29 @@ def PWD(self,cmd):
    cwd='/'+cwd
    self.conn.send('257 \"%s\"\r\n' % cwd)
    def CWD(self,cmd):
    self.LoadCwd()
    print 'NOW:',os.getcwd()
    chwd=cmd[4:-2]
    if chwd=='/':
    chwd=self.basewd
    self.cwd=self.basewd
    elif chwd[0]=='/':
    chwd=self.basewd+chwd
    os.chdir(chwd)
    print 'NOW:',os.getcwd()
    self.SaveCwd()
    self.cwd=os.path.join(self.basewd,chwd[1:])
    else:
    self.cwd=os.path.join(self.cwd,chwd)
    self.conn.send('250 OK.\r\n')

    def PORT(self,cmd):
    l=cmd[5:].split(',')
    self.dataAddr='.'.join(l[:4])
    self.dataPort=(int(l[4])<<8)+int(l[5])
    self.conn.send('200 I know.\r\n')
    self.conn.send('200 Get port.\r\n')

    def LIST(self,cmd):
    self.LoadCwd()
    self.conn.send('150 Here comes the directory listing.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    l=os.listdir('.')
    for t in l:
    k=self.toListItem(t)
    #print k,
    self.datasock.send(k)
    print self.cwd
    for t in os.listdir(self.cwd):
    k=self.toListItem(os.path.join(self.cwd,t))
    self.datasock.send(k+'\r\n')
    self.datasock.close()
    self.conn.send('226 Directory send OK.\r\n')

    @@ -97,25 +89,73 @@ def toListItem(self,fn):
    mode+=((st.st_mode>>(8-i))&1) and fullmode[i] or '-'
    d=(os.path.isdir(fn)) and 'd' or '-'
    ftime=time.strftime(' %b %d %H:%M ', time.gmtime(st.st_mtime))
    return d+mode+' 1 user group '+str(st.st_size)+ftime+os.path.basename(fn)+'\r\n'
    return d+mode+' 1 user group '+str(st.st_size)+ftime+os.path.basename(fn)

    def MKD(self,cmd):
    dn=os.path.join(self.cwd,cmd[4:-2])
    os.mkdir(dn)
    self.conn.send('257 Directory created.\r\n')

    def RMD(self,cmd):
    dn=os.path.join(self.cwd,cmd[4:-2])
    #os.rmdir(dn)
    self.conn.send('250 Directory deleted.\r\n')

    def DELE(self,cmd):
    fn=os.path.join(self.cwd,cmd[5:-2])
    #os.remove(fn)
    self.conn.send('250 File deleted.\r\n')

    def RNFR(self,cmd):
    self.rnfn=os.path.join(self.cwd,cmd[5:-2])
    self.conn.send('350 Ready.\r\n')

    def RNTO(self,cmd):
    fn=os.path.join(self.cwd,cmd[5:-2])
    os.rename(self.rnfn,fn)
    self.conn.send('250 File renamed.\r\n')

    def REST(self,cmd):
    self.pos=int(cmd[5:-2])
    self.rest=True
    self.conn.send('250 File position reseted.\r\n')

    def RETR(self,cmd):
    self.LoadCwd()
    print 'NOW:',os.getcwd()
    fn=cmd[5:-2]
    #fn=self.cwd+'/'+fn
    print 'Down:',fn
    fn=os.path.join(self.cwd,cmd[5:-2])
    print 'Downlowding:',fn
    if self.mode=='I':
    fi=open(fn,'rb')
    else:
    fi=open(fn,'r')
    self.conn.send('150 Opening data connection.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    if self.rest:
    fi.seek(self.pos)
    self.rest=False
    data= fi.read(1024)
    while data:
    self.datasock.send(data)
    data=fi.read(1024)
    fi.close()
    self.datasock.close()
    self.conn.send('226 Transfer complete.\r\n')

    def STOR(self,cmd):
    fn=os.path.join(self.cwd,cmd[5:-2])
    print 'Uplaoding:',fn
    if self.mode=='I':
    fo=open(fn,'wb')
    else:
    fo=open(fn,'w')
    self.conn.send('150 Opening data connection.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    while True:
    data=self.datasock.recv(1024)
    if not data: break
    fo.write(data)
    fo.close()
    self.datasock.close()
    self.conn.send('226 Transfer complete.\r\n')

  4. @scturtle scturtle created this gist Jun 20, 2011.
    143 changes: 143 additions & 0 deletions ftpserver.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,143 @@
    #!/usr/bin/env python2
    # coding: utf-8

    import os,socket,threading,time
    import traceback

    currdir=os.path.abspath('.')

    class FTPserverThread(threading.Thread):
    def __init__(self,(conn,addr)):
    self.conn=conn
    self.addr=addr
    self.basewd=currdir
    self.cwd=self.basewd
    threading.Thread.__init__(self)

    def run(self):
    self.conn.send('220 Welcome!\r\n')
    while True:
    cmd=self.conn.recv(256)
    if not cmd: break
    else:
    print 'Recieved:',cmd
    try:
    func=getattr(self,cmd[:4].strip().upper())
    func(cmd)
    except Exception,e:
    print e
    #traceback.print_exc()
    self.conn.send('500 Sorry.\r\n')

    def LoadCwd(self):
    os.chdir(self.cwd)
    def SaveCwd(self):
    self.cwd=os.getcwd()
    def USER(self,cmd):
    self.conn.send('331 OK.\r\n')
    def PASS(self,cmd):
    self.conn.send('230 OK.\r\n')
    def QUIT(self,cmd):
    self.conn.send('221 Goodbye.\r\n')
    def NOOP(self,cmd):
    self.conn.send('200 OK.\r\n')
    def TYPE(self,cmd):
    self.mode=cmd[5]
    self.conn.send('200 Binary mode.\r\n')

    def CDUP(self,cmd):
    self.LoadCwd()
    os.chdir('..')
    self.SaveCwd()
    self.conn.send('200 OK.\r\n')
    def PWD(self,cmd):
    cwd=os.path.relpath(self.cwd,self.basewd)
    if cwd=='.':
    cwd='/'
    else:
    cwd='/'+cwd
    self.conn.send('257 \"%s\"\r\n' % cwd)
    def CWD(self,cmd):
    self.LoadCwd()
    print 'NOW:',os.getcwd()
    chwd=cmd[4:-2]
    if chwd=='/':
    chwd=self.basewd
    elif chwd[0]=='/':
    chwd=self.basewd+chwd
    os.chdir(chwd)
    print 'NOW:',os.getcwd()
    self.SaveCwd()
    self.conn.send('250 OK.\r\n')

    def PORT(self,cmd):
    l=cmd[5:].split(',')
    self.dataAddr='.'.join(l[:4])
    self.dataPort=(int(l[4])<<8)+int(l[5])
    self.conn.send('200 I know.\r\n')

    def LIST(self,cmd):
    self.LoadCwd()
    self.conn.send('150 Here comes the directory listing.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    l=os.listdir('.')
    for t in l:
    k=self.toListItem(t)
    #print k,
    self.datasock.send(k)
    self.datasock.close()
    self.conn.send('226 Directory send OK.\r\n')

    def toListItem(self,fn):
    st=os.stat(fn)
    fullmode='rwxrwxrwx'
    mode=''
    for i in range(9):
    mode+=((st.st_mode>>(8-i))&1) and fullmode[i] or '-'
    d=(os.path.isdir(fn)) and 'd' or '-'
    ftime=time.strftime(' %b %d %H:%M ', time.gmtime(st.st_mtime))
    return d+mode+' 1 user group '+str(st.st_size)+ftime+os.path.basename(fn)+'\r\n'

    def RETR(self,cmd):
    self.LoadCwd()
    print 'NOW:',os.getcwd()
    fn=cmd[5:-2]
    #fn=self.cwd+'/'+fn
    print 'Down:',fn
    if self.mode=='I':
    fi=open(fn,'rb')
    else:
    fi=open(fn,'r')
    self.conn.send('150 Opening data connection.\r\n')
    self.datasock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.datasock.connect((self.dataAddr,self.dataPort))
    data= fi.read(1024)
    while data:
    self.datasock.send(data)
    data=fi.read(1024)
    self.datasock.close()
    self.conn.send('226 Transfer complete.\r\n')

    class FTPserver(threading.Thread):
    def __init__(self):
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.bind(('',8888))
    threading.Thread.__init__(self)

    def run(self):
    self.sock.listen(5)
    while True:
    th=FTPserverThread(self.sock.accept())
    th.daemon=True
    th.start()

    def stop(self):
    self.sock.close()

    if __name__=='__main__':
    ftp=FTPserver()
    ftp.daemon=True
    ftp.start()
    raw_input('Enter to end...\n')
    ftp.stop()