From e679734d9f28e5ad5e036c940f6b7b9c4e0b95a7 Mon Sep 17 00:00:00 2001
From: Sergey Morozov
Date: Fri, 18 Apr 2014 23:25:34 +0400
Subject: [PATCH] Moved to Git repo from PST server
---
addr.py | 146 +++++++++++++++++++++++++
upload.py | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 460 insertions(+)
create mode 100644 addr.py
create mode 100755 upload.py
diff --git a/addr.py b/addr.py
new file mode 100644
index 0000000..c1d89c3
--- /dev/null
+++ b/addr.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+import string
+from copy import deepcopy
+class ipv4addr():
+ """Class for IPv4 address manipulation.\n\n"""\
+ """Initialization:\n"""\
+ """\tfrom addr import ipv4addr\n"""\
+ """\tmyAddress = ipv4addr(str, str) # for example: myAddress = ipv4addr("192.168.0.1", "255.255.255.0")\n"""\
+ """or:\n"""\
+ """\tmyAddress = ipv4addr(str, int) # for example: myAddress = ipv4addr("192.168.0.1", 24)\n\n"""\
+ """Functions:\n"""\
+ """\tnetwork() # returns subnet address\n"""\
+ """\tinMyNet(ipv4addr) # returns True or False\n"""\
+ """\t # True - if the specified ipv4addr object belongs to the network\n"""\
+ """\t # False - if the specified ipv4addr object not belongs to the network\n\n"""\
+ """Variables:\n"""\
+ """\tcidr # Subnet mask in cidr notation\n\n"""\
+ """ipv4addr class object is an iterator.\n"""\
+ """Examples of use ipv4addr object as iterator:\n"""\
+ """\t>>> myAddress = ipv4addr("192.168.0.1", 24)\n"""\
+ """\t>>> print(myAddress[0])\n"""\
+ """\t192\n"""\
+ """\t>>> print(myAddress[1])\n"""\
+ """\t168\n"""\
+ """\t>>> myAddress[2] = 1\n"""\
+ """\t>>> print(myAddress)\n"""\
+ """\t192.168.1.1/24\n"""
+
+ def __init__(self, addrstr = '0.0.0.0', netmask = 32):
+ octets = addrstr.split('.')
+ self._addr = None
+ self._setAddr([int(octets[0]),
+ int(octets[1]),
+ int(octets[2]),
+ int(octets[3])])
+ if type(netmask) == str:
+ self.cidr = self._strToMask(netmask)
+ else:
+ self.cidr = netmask
+ self.printMask = True
+
+ def _strToMask(self, netmask):
+ octets = netmask.split('.')
+ cidr = 0
+ for i in octets:
+ octet = int(i)
+ if octet > 0:
+ while((octet & 128) / 128):
+ cidr += 1
+ octet<<=1
+ return(cidr)
+
+ def _setAddr(self, octets):
+ self._addr = octets[0] * pow(256, 3) + octets[1] * pow(256, 2) + octets[2] * pow(256, 1) + octets[3] * pow(256, 0)
+
+ def _getOctet(self, key):
+ octet = self._addr
+ for i in xrange(3 - key):
+ octet >>= 8
+ octet = octet % 256
+ return(octet)
+
+ def _setOctet(self, key, value):
+ octets=[]
+ for i in xrange(4):
+ if i == key:
+ octets.append(value)
+ else:
+ octets.append(self._getOctet(i))
+ self._setAddr(octets)
+ def _mask(self):
+ mask = 0
+ for i in xrange(self.cidr):
+ mask = (mask << 1) + 1
+ for i in xrange(32-self.cidr):
+ mask <<= 1
+ return(mask)
+
+ def __str__(self):
+ result = str(self._getOctet(0)) + '.' + str(self._getOctet(1)) + '.' + str(self._getOctet(2)) + '.' + str(self._getOctet(3))
+ if self.printMask == True:
+ result+='/%s' % self.cidr
+ return(result)
+
+ def __repr__(self):
+ return(self.__str__())
+
+ def __iter__(self):
+ return(self)
+
+ def __getitem__(self, key):
+ return(self._getOctet(key))
+
+ def __setitem__(self, key, value):
+ self._setOctet(key, value)
+
+ def __len__(self):
+ return(4)
+
+ def __lt__(self, other):
+ if self._addr < other._addr:
+ return True
+ else:
+ return False
+
+ def __le__(self, other):
+ if self._addr <= other._addr:
+ return True
+ else:
+ return False
+
+ def __eq__(self, other):
+ if self._addr == other._addr:
+ return True
+ else:
+ return False
+
+ def __ne__(self, other):
+ if self._addr != other._addr:
+ return True
+ else:
+ return False
+
+ def __gt__(self, other):
+ if self._addr > other._addr:
+ return True
+ else:
+ return False
+
+ def __ge__(self, other):
+ if self._addr >= other._addr:
+ return True
+ else:
+ return False
+
+ def network(self):
+ network = deepcopy(self)
+ network._addr = self._addr & self._mask()
+ network.cidr = self.cidr
+ return(network)
+
+ def inMyNet(self, address):
+ if (address._addr & self._mask()) == self.network()._addr:
+ return(True)
+ else:
+ return(False)
diff --git a/upload.py b/upload.py
new file mode 100755
index 0000000..6a133ea
--- /dev/null
+++ b/upload.py
@@ -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 ''
+ print ''
+ print ''
+ print ' '
+ print ' PST File Exchange'
+ print ''
+ print ''
+ print ''
+ print ' Файлообменный ресурс PST Group |
'
+
+def printFooter():
+ print '
© 2010 Сергей Морозов
'
+ print ''
+ print ''
+ print ''
+
+def printForm():
+ print ' '
+ print '
'
+ print ' '
+ print ' Обращаем ваше внимание:'
+ print '
'
+ print ' - Русские имена файлов автоматически конвертируются в транслит;
'
+ print ' - На данный момент автоматическая проверка корректности e-mail адресов не производится, по-этому внимательно проверяйте указываемые вами данные;
'
+ print ' - Все поля являются обязательными для заполнения;
'
+ print ' - При больших объёмах файлов процесс выгрузки может занять достаточно длительное время, настоятельно просим не закрывать окно и дождаться окончания процесса.
'
+ print '
'
+ print '
'
+ print '
'
+
+def printChangeLog():
+ print ' '
+ print ' Список изменений:
'
+ print ' '
+ print ' '
+ for i in xrange(len(changelog)-1):
+ print ' - ' + changelog[i] + ';
'
+ print ' - ' + changelog[i+1] + '.
'
+ print '
'
+ print ' '
+ print ' '
+
+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 ' Вам запрещена отправка файлов на данный адрес. |
'
+ 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 'Файл успешно загружен на сервер, и запущен процесс его упаковки в архив.'
+ print '
По завершении процесса вам и получателю файла будут отправлены письма с дальнейшими инструкциями
'
+ 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 = 'Здравствуйте.
\n'\
+ 'Пользователь %s разместил для вас файл %s.
\n'\
+ 'Вы можете скачать этот файл по адресу %s.
\n'\
+ 'Пароль для распаковки файла: %s' % (uploader_email, uploader_email, filename, url, url, password)
+ msgbody_uploader = 'Здравствуйте.
\n'\
+ 'Ваш файл %s был успешно обработан и запакован.
\n'\
+ 'Файл доступен по адресу %s.
\n'\
+ 'Пароль для распаковки файла: %s
\n'\
+ 'Получателю файла было отправлено письмо следующего содержания:
\n'\
+ '' % (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 ' Будьте внимательны! Все поля обязательны для заполнения! |
'
+ printForm()
+ printChangeLog()
+ printFooter()
+