pstfileshare/upload.py

315 lines
12 KiB
Python
Raw Normal View History

2014-04-18 23:25:34 +04:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgi, cgitb, tempfile, commands, os, smtplib, sys, string
from random import Random
from email.mime.text import MIMEText
from addr import ipv4addr
# Debug:
cgitb.enable()
# Settings
storage = "/var/www/download.pstgroup.ru/storage"
passwordLength = 8
serverAdmin = "webmaster@pstgroup.ru"
proto = "http"
filesUri = ""
myNetworks = [
ipv4addr("82.140.81.64","255.255.255.248"),
ipv4addr("84.204.173.0",24),
ipv4addr("192.168.0.0",24),
ipv4addr("192.168.4.0",24),
ipv4addr("193.106.109.129",32),
ipv4addr("193.106.109.130",32),
ipv4addr("193.106.109.131",32)
]
myDomains = [
"pstgroup.ru",
"ust-luga-customs.ru",
"myoffice.spb.ru",
"iptgroup.net",
"ldshouse.ru"
]
internalExampleAddress = "pupkin@pstgroup.ru"
externalExampleAddress = "putin@kremlin.ru"
changelog = [
'29.08.2011 - Добавлена возможность отправки файлов внешними пользователями',
'25.04.2011 - Устранена проблема перекодировки имени файла, возникающая в случае наличия в нём некоторых символов Unicode',
'23.07.2010 - Устранены множественные проблемы с перекодировкой имени файла',
'01.07.2010 - Оптимизация кода',
'30.06.2010 - Косметические изменения',
'30.06.2010 - Добавлено отображение списка изменений',
'30.06.2010 - Исправлена проблема, возникающая из-за ошибки в некоторых браузерах и преводящая к некорректному имени файла',
'24.06.2010 - Исправлена ошибка перекодировки, возникающая в случае, если в имени файла содержится символ \"ъ\"'
]
urlBase = proto + '://' + os.environ.get('SERVER_NAME') + filesUri
scriptUrl = proto + '://' + os.environ.get('SERVER_NAME') + os.environ.get('REQUEST_URI')
client = ipv4addr(os.environ['REMOTE_ADDR'])
conversion = {
u'а' : 'a',
u'б' : 'b',
u'в' : 'v',
u'г' : 'g',
u'д' : 'd',
u'е' : 'e',
u'ё' : 'e',
u'ж' : 'zh',
u'з' : 'z',
u'и' : 'i',
u'й' : 'j',
u'к' : 'k',
u'л' : 'l',
u'м' : 'm',
u'н' : 'n',
u'о' : 'o',
u'п' : 'p',
u'р' : 'r',
u'с' : 's',
u'т' : 't',
u'у' : 'u',
u'ф' : 'f',
u'х' : 'h',
u'ц' : 'c',
u'ч' : 'ch',
u'ш' : 'sh',
u'щ' : 'sch',
u'ъ' : "'",
u'ы' : 'y',
u'ь' : "'",
u'э' : 'e',
u'ю' : 'ju',
u'я' : 'ja',
u'А' : 'A',
u'Б' : 'B',
u'В' : 'V',
u'Г' : 'G',
u'Д' : 'D',
u'Е' : 'E',
u'Ё' : 'E',
u'Ж' : 'ZH',
u'З' : 'Z',
u'И' : 'I',
u'Й' : 'J',
u'К' : 'K',
u'Л' : 'L',
u'М' : 'M',
u'Н' : 'N',
u'О' : 'O',
u'П' : 'P',
u'Р' : 'R',
u'С' : 'S',
u'Т' : 'T',
u'У' : 'U',
u'Ф' : 'F',
u'Х' : 'H',
u'Ц' : 'C',
u'Ч' : 'CH',
u'Ш' : 'SH',
u'Щ' : 'SCH',
u'Ъ' : "'",
u'Ы' : 'Y',
u'Ь' : "'",
u'Э' : 'E',
u'Ю' : 'JU',
u'Я' : 'JA',
}
clientIsInternal = False
for net in myNetworks:
if net.inMyNet(client):
clientIsInternal = True
def domainIsAllowed(mailAddress):
checkingDomain = mailAddress.split("@")[-1]
result = False
for domain in myDomains:
if checkingDomain == domain:
result = True
return(result)
def cyr2lat(s):
retval = ""
c = ''
for c in s:
try:
c = conversion[c]
except KeyError:
pass
try:
c = str(unicode(c))
except UnicodeEncodeError:
c = '.'
retval = retval + c
return retval
def printHeader():
print 'Content-type: text/html\n'
print '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
print '<html lang="ru">'
print '<head>'
print ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'
print ' <title> PST File Exchange</title>'
print '</head>'
print '<body>'
print '<font face="Calibri, Arial, Verdana, Sans">'
print ' <H1><table width="100%" bgcolor="#336299"><tr><td><p align="center"><font color="white">Файлообменный ресурс PST Group</font></p></td></tr></table></H1>'
def printFooter():
print '<br><br><p align="center"><font color="gray">&copy; 2010 Сергей Морозов</font></p>'
print '</font>'
print '</body>'
print '</html>'
def printForm():
print ' <form method="post" enctype="multipart/form-data" action="' + scriptUrl + '">'
print ' <p>'
print ' Введите <b>ваш</b> e-mail:<br>'
print ' <input type="text" name="uploader_email" id="uploader_email" size="30">'
if clientIsInternal:
print ' <font color="gray"><i>например: %s</i></font>' % internalExampleAddress
else:
print ' <font color="gray"><i>например: %s</i></font>' % externalExampleAddress
print ' </p>'
print ' <p>'
print ' Введите e-mail <b>получателя</b>:<br>'
print ' <input type="text" name="downloader_email" id="downloader_email" size="30">'
if clientIsInternal:
print ' <font color="gray"><i>например: %s</i></font>' % externalExampleAddress
else:
print ' <font color="gray"><i>например: %s</i></font>' % internalExampleAddress
print ' </p>'
print ' <p>'
print ' Выберите файл:<br>'
print ' <input type="file" name="datafile" id="datafile" size="40">'
print ' </p>'
print ' <input type="submit" value="Отправить">'
print ' </form>'
print ' <br><hr>'
print ' <p>'
print ' Обращаем ваше внимание:'
print ' <ul>'
print ' <li>Русские имена файлов автоматически конвертируются в транслит;</li>'
print ' <li>На данный момент автоматическая проверка корректности e-mail адресов не производится, по-этому внимательно проверяйте указываемые вами данные;</li>'
print ' <li>Все поля являются обязательными для заполнения;</li>'
print ' <li>При больших объёмах файлов процесс выгрузки может занять достаточно длительное время, настоятельно просим не закрывать окно и дождаться окончания процесса.</li>'
print ' </ul>'
print ' </p>'
print ' <br>'
def printChangeLog():
print ' <font color="gray">'
print ' <h4>Список изменений:</h4>'
print ' <i>'
print ' <ul>'
for i in xrange(len(changelog)-1):
print ' <li>' + changelog[i] + ';</li>'
print ' <li>' + changelog[i+1] + '.</li>'
print ' </ul>'
print ' </i>'
print ' </font>'
def fbuffer(f, chunk_size=10000):
while True:
chunk = f.read(chunk_size)
if not chunk: break
yield chunk
def runCommand(cmd):
status, text = commands.getstatusoutput(cmd)
exit_code = status >> 8 # higi byte
signal_num = status %256 # low byte
def pwgen(pw_length):
rng = Random()
pw = ''
allchars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
for i in range(pw_length):
pw = pw + rng.choice(allchars)
return pw
def fileBaseName(filename):
basename = string.split(filename, '/')[-1]
basename = string.split(basename, '\\')[-1]
return basename
form = cgi.FieldStorage()
if not form:
printHeader()
printForm()
printChangeLog()
printFooter()
else:
if form.has_key("uploader_email") and form.has_key("downloader_email") and not clientIsInternal and not domainIsAllowed(form["downloader_email"].value):
printHeader()
print ' <table bgcolor="#FFF9B4" width="100%"><tr><td align="center"><font color="red">Вам запрещена отправка файлов на данный адрес.</font></td></tr></table>'
printForm()
printChangeLog()
printFooter()
elif form.has_key("datafile") and form.has_key("uploader_email") and form.has_key("downloader_email") and form["datafile"].filename != '' and form["uploader_email"].value != '' and form["downloader_email"].value != '':
datafile = form["datafile"]
uploader_email = form["uploader_email"].value
downloader_email = form["downloader_email"].value
filename = fileBaseName(cyr2lat(unicode(datafile.filename,"UTF-8")))
if filename[0] == '.':
filename = str(unicode('_%s' % filename))
filepath = storage + '/' + filename
file = open(filepath, 'wb')
for chunk in fbuffer(datafile.file):
file.write(chunk)
file.close()
password = pwgen(passwordLength)
printHeader()
print '<p align="center">Файл успешно загружен на сервер, и запущен процесс его упаковки в архив.</a>'
print '<p align="center">По завершении процесса вам и получателю файла будут отправлены письма с дальнейшими инструкциями</p>'
printFooter()
sys.stdout.flush()
pid = os.fork()
if pid == 0:
os.setsid()
fw = open('/dev/null','w')
#fw = open('/tmp/download.html','w')
os.dup2(fw.fileno(),1)
os.dup2(fw.fileno(),2)
runCommand('zip -j -X -P ' + password + ' "' + filepath + '.zip" "' + filepath + '"')
os.remove(filepath)
url = urlBase + '/' + filename + '.zip'
msgbody_downloader = 'Здравствуйте.<br><br>\n'\
'Пользователь <a href=\"mailto:%s\">%s</a> разместил для вас файл <b>%s</b>.<br>\n'\
'Вы можете скачать этот файл по адресу <a href=\"%s\">%s</a>.<br>\n'\
'Пароль для распаковки файла: <b>%s</b>' % (uploader_email, uploader_email, filename, url, url, password)
msgbody_uploader = 'Здравствуйте.<br><br>\n'\
'Ваш файл <b>%s</b> был успешно обработан и запакован.<br>\n'\
'Файл доступен по адресу <a href="%s">%s</a>.<br>\n'\
'Пароль для распаковки файла: <b>%s</b><br>\n'\
'Получателю файла было отправлено письмо следующего содержания:<br>\n'\
'<blockquote><table bgcolor="lightgray" border="0" cellpadding="10"><tr><td>%s</td></tr></table></blockquote>' % (filename, url, url, password, msgbody_downloader)
msg_downloader = MIMEText(msgbody_downloader, 'html', 'utf-8')
msg_uploader = MIMEText(msgbody_uploader, 'html', 'utf-8')
#msg_downloader.set_charset('utf-8')
#msg_uploader.set_charset('utf-8')
msg_downloader['Subject'] = 'PST File Exchange'
msg_uploader['Subject'] = 'PST File Exchange'
msg_downloader['From'] = uploader_email
msg_uploader['From'] = serverAdmin
msg_downloader['To'] = downloader_email
msg_uploader['To'] = uploader_email
s = smtplib.SMTP()
s.connect()
s.sendmail(msg_downloader['From'], msg_downloader['To'], msg_downloader.as_string())
s.sendmail(msg_uploader['From'], msg_uploader['To'], msg_uploader.as_string())
s.quit
else:
sys.exit(0)
else:
printHeader()
print ' <table bgcolor="#FFF9B4" width="100%"><tr><td align="center"><font color="red">Будьте внимательны! Все поля обязательны для заполнения!</font></td></tr></table>'
printForm()
printChangeLog()
printFooter()