pstfileshare/upload.py

315 lines
12 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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()