|
|
@ -0,0 +1,314 @@ |
|
|
|
#!/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">© 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() |
|
|
|
|