Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions add-ftp-account.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

#-------------------------------------------
# $1 = User name
# $2 = Password
# $3 = Home directory
#-------------------------------------------

if [ "$#" -ne 3 ]; then
echo "Illegal number of parameters"
echo "Usage:"
echo " $0 <User name> <Password> <Home dir>"
echo
echo "Example:"
echo " ./add-ftp-account.sh user_name password user_home_dir"
echo
exit 1
fi

conf="conf/ftp.conf"
perm="elrwm"

#--CREATE NEW USER ACCOUNT
if [ -z "$( grep "name: $1" $conf )" ]; then
echo "" >> $conf
echo " - name: $1" >> $conf
echo " dir: $3" >> $conf
echo " password: $2" >> $conf
echo " permission: $perm" >> $conf
echo "Created new FTP account $1 having permission $perm"
else
echo "The user $1 already exists: ABORT !!!"
exit -1
fi

#--CREATE HOME DIR
if [ ! -d $3 ]; then
mkdir $3
chown www-data:www-data $3
chmod -R g+w $3
chmod g+s $3
echo "Created new home dir: $3"
fi

#echo "HOMEs:"
#echo "$( ls -l $3/.. )"

#--RESTART easyftp DAEMON TO ENABLE NEW ACCOUNT
daemon_restart="zdaemon -C conf/zdaemon.conf restart"
read -p "Do you want to restart EASYFTP daemon now ? ('Yes' or 'No')" response
if [ "${response^^}" == "YES" ]; then
$daemon_restart
else
echo
echo "ATTENTION:"
echo "Remember to restart daemon manually to apply config changes:"
echo " $daemon_restart"
fi

echo "Done!"

50 changes: 43 additions & 7 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import os
import yaml
import logging
import pyftpdlib.log

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
Expand All @@ -19,24 +21,41 @@ def read_conf(config_file=os.path.join(this_dir, '../conf/ftp.conf')):

class CustomHandler(FTPHandler):

my_log = logging.getLogger('CustomHandler')

def on_file_received(self, file):
import os
self.my_log.debug("Rename " + os.path.basename(file) + " to original file name")
head, tail = list(path.split(file))[0], list(path.split(file))[1]
os.rename(path.join(head, tail), path.join(head, tail[4:]))
os.rename(path.join(head, tail), path.join(head, tail[4:-1]))
pass


#Rob: it seems doesn't exist !
def on_incomplete_received(self, file):
import os
self.my_log.warn("on_incomplete_received('" + os.path.basename(file) + "')")
os.remove(file)


def ftp_STOR(self, file, mode='w'):
import os
self.my_log.debug("Rename " + os.path.basename(file) + " useing temp file name .in.xxx.")
head, tail = list(path.split(file))[0], list(path.split(file))[1]
file = path.join(head, ".in." + tail)

file = path.join(head, ".in." + tail + ".")
return FTPHandler.ftp_STOR(self, file, mode)

def on_incomplete_file_received(self, file):
import os
self.my_log.warn("Remove partially uploaded file " + os.path.basename(file))
# remove partially uploaded file
#This happens on connection interrupted but not when Ctrl+C is pressed on FTP client (rob)
os.remove(file)

#Rob: added by me
def on_incomplete_file_sent(self, file):
import os
self.my_log.warn("Remove partially downloaded file " + os.path.basename(file))
# remove partially downloaded files
os.remove(file)

def get_server(conf=None):

Expand All @@ -53,7 +72,8 @@ def get_server(conf=None):
# Instantiate FTP handler class
handler = CustomHandler
handler.authorizer = authorizer

handler.log_prefix = '[%(username)s@%(remote_ip)s:%(remote_port)s]'

# Define a customized banner (string returned when client connects)
handler.banner = "simpleftp ready!"

Expand All @@ -68,6 +88,7 @@ def get_server(conf=None):

address = (server.get('address', ''), server.get('port', '2121'))
server = FTPServer(address, handler)
pyftpdlib.log.LEVEL = log_level

# set a limit for connections
# server.max_cons = 256
Expand All @@ -78,5 +99,20 @@ def get_server(conf=None):
return server

if __name__ == '__main__':
server = get_server(read_conf())
conf = read_conf()
log_level = logging.DEBUG
if conf.get('log').get('level').upper() == 'INFO':
log_level = logging.INFO
elif conf.get('log').get('level').upper() == 'WARN':
log_level = logging.WARN
elif conf.get('log').get('level').upper() == 'ERROR':
log_level = logging.ERROR

logging.basicConfig(level=log_level,
format='%(asctime)s %(levelname)-5s %(name)-13s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
filename='/var/log/pyftpd.log',
filemode='a')

server = get_server(conf)
server.serve_forever()
5 changes: 4 additions & 1 deletion conf/ftp-example.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
log:
level: INFO

users:
- name: luca
dir: /Users/luca
Expand All @@ -16,4 +19,4 @@ server:
# masquerade_address: 8.8.8.8
passive_ports:
start: 60000
end: 65535
end: 65535
14 changes: 10 additions & 4 deletions conf/zdaemon.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<runner>
daemon on
program python ./app/main.py
socket-name ./socket/ftpserver.sock
transcript ./log/ftpserver.log
</runner>
program ./easyftp.sh
socket-name socket/ftpserver.sock
#transcript log/ftpserver.log
</runner>

<eventlog>
<logfile>
path log/easyftp.log
</logfile>
</eventlog>
6 changes: 6 additions & 0 deletions easyftp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

# This script is the EasyFTP launcher

python app/main.py