diff --git a/profile/unix/etc/pam.d/system-auth b/profile/unix/etc/pam.d/system-auth index 2273e14..49ff5e9 100644 --- a/profile/unix/etc/pam.d/system-auth +++ b/profile/unix/etc/pam.d/system-auth @@ -11,6 +11,14 @@ account required pam_unix.so account sufficient pam_ldap.so #?pkg(cracklib)!=# +<<<<<<< HEAD +======= +password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3 +#pkg# +#?pkg(passwdqc)!=# +password required pam_passwdqc.so min=8,8,8,8,8 retry=3 +#pkg# +>>>>>>> py3_forced password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3 #pkg# #?pkg(passwdqc)!=# diff --git a/pym/cl_base.py b/pym/cl_base.py new file mode 100644 index 0000000..cfe2437 --- /dev/null +++ b/pym/cl_base.py @@ -0,0 +1,1176 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import gettext +import os +import getopt +import sys +############################################################################## +import re +import copy +import types +import string +import filecmp +# import ConfigParser +import time +import socket +import random +import string +import cl_utils +from cl_xml import firstChild +import importlib +############################################################################## +_ = lambda x : x +_expand_lang = gettext._expand_lang + +def exit(codeExit): + """Метод выхода из программы""" + sys.exit(codeExit) + +def __findFileMO(domain, localedir=None, languages=None, all=0): + # Модифицинрованный метод модуля gettext ищет файл перевода + if localedir is None: + localedir = gettext._default_localedir + if languages is None: + languages = [] + for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): + val = os.environ.get(envar) + if val: + languages = val.split(':') + break + if 'C' not in languages: + languages.append('C') + # now normalize and expand the languages + nelangs = [] + for lang in languages: + for nelang in _expand_lang(lang): + if nelang not in nelangs: + nelangs.append(nelang) + # select a language + if all: + result = [] + else: + result = None + for lang in nelangs: + if lang == 'C': + break + mofile = os.path.join(localedir, '%s_%s.mo' % (domain,lang)) + if os.path.exists(mofile): + if all: + result.append(mofile) + else: + return mofile + return result + +gettext.find = __findFileMO + +class GlobalParam(type): + """ Метакласс для глобальных параметров + """ + def __init__(cls, *args): + cls.GP = [] + cls.GP.append("") + +class lang(metaclass=GlobalParam): + """Класс многоязыковой поддержки lang для перевода сообщений программ на +другие языки. + +Типичное использование: + import sys + import lang + + # язык сообщений английский + tr = lang.lang(en) + # язык определяется системой + #tr = lang.lang() + + #Установка домена переводаldap + # в последующем можно не использовать - задается глобально + tr.setGlobalDomain('calc') + # задается локально для одного файла + #tr.setLocalDomain('calc') + + # Установка метода перевода для текущего модуля + tr.setLanguage(sys.modules[__name__]) + +Где: + tr -- объект перевода + 'en' -- язык выводимых сообщений + sys.modules[__name__] -- модуль сообщения которого переводятся + calc - домен перевода - имя файла перевода без расширения + +Если файл перевода не найден то сообщения не переводятся +Если в модуле сообщения которого переводим, экспортируются другие модули то +они тоже переводятся. + +По умолчанию директория в которой находятся переводы: 'lang/i18h' относительно +исполняемого файла названия файлов перевода совпадают с названиями модулей +если не определен методом setDomainTranslate() - домен перевода. + """ + def __init__(self,l=''): + self.nameDomain = self.GP[0] + #self.nameDomain = '' + """ Название файла перевода (Домен) если используется 1 файл перевода + """ + self.__catalog = os.path.abspath('/usr/share/calculate-2.0/i18n') + """ Путь к каталогу переводов (в этом каталоге + ru_RU/LC_MESSAGES в котором файл перевода) + """ + env = os.environ + if l == "" and 'LANG' in env: + l = env['LANG'].split('.')[0].split("_")[0] + """ Определение языка """ + self.__modnames = {} + """ Словарь переведенных модулей + ключ --- имя модуля + значение --- был ли модуль переведен (1 или 0) + """ + self.__l = l + """Язык перевода для всех модулей""" + + def __translate(self,message): + """Метод translate возвращает полученное значение без +изменений""" + return message + + def setLanguage(self,module): + """ Установка языка перевода для модуля module. + + параметр --- экспортируемый модуль python + если в этом модуле экспортируются другие модули + то язык устанавливается и для них + Метод запускается после экспорта модуля который будем переводить + """ + t = vars(module) + for i in dir(module): + q = str(t[i]) + if 'module' in q and not '__' in i and not '/usr/lib' in q\ + and not 'built-in' in q : + mod = vars(module)[i] + self.__setLang(mod) + return self.__setLang(module) + + def __setLang(self,module): + """ Установка языка перевода для модуля module. + + В случае нахождения файла перевода возвращает истину. + Во всех случаях устанавливает метод перевода для модуля. + Если нет файла перевода метод перевода возвращает то же + значение что получает + """ + if module.__name__ in self.__modnames.keys(): + return True + + if self.nameDomain == '': + if module.__name__ == "__main__": + nameDomain = module.__file__.split('.')[0] + else: + nameDomain = module.__name__ + else: + nameDomain = self.nameDomain + + if self.__l == 'en': + module._ = self.__translate + ret = 1 + else: + la = [] + la.append(self.__l) + if gettext.find(nameDomain,self.__catalog,la): + """Если найден словарь то инициализируем переводчик""" + transl = gettext.translation(nameDomain\ + ,self.__catalog,la) + + #module._ = transl.ugettext + module._ = transl.gettext + ret = 1 + else: + module._ = self.__translate + ret = 0 + self.__modnames[module.__name__] = ret + return ret + + def getTranslatorByName(self,namemodule): + """ Метод который по имени модуля определяет, был ли модуль с этим + именем переведен + """ + if namemodule in self.__modnames: + return self.__modnames[namemodule] + return 0 + + def setGlobalDomain(self, nameDomain): + """ Метод для установки домена перевода (глобально для всех файлов) + """ + self.GP[0] = nameDomain + self.nameDomain = self.GP[0] + return True + + def setLocalDomain(self, nameDomain): + """ Метод для установки домена перевода (локально для одного файла) + """ + self.nameDomain = nameDomain + return True + +############################################################################## +# Перевод модуля на другой язык +tr = lang() +tr.setLocalDomain('cl_lib') +tr.setLanguage(sys.modules[__name__]) + +############################################################################## +class opt: + def __init__(self, shortOpt, longOpt=None): + """ Длинные и короткие опции командной строки допустимые в программе + a - короткая опция + >program -a + + a: - короткая опциия со значением + >program -a 10 + + a:: - короткая опциия у которой может быть или не быть значение + >program -a + >program -a 15 + + "ha:" - значение параметра shortOpt + две опции h - без значения, a - со значением + + help - длинная опция без значения + test= - длинная опция со значением + + ["help","test="] - значение парамера longOpt + >program -a + две опции help - без значения, test - со значением + """ + if longOpt is None: + longOpt = [] + self.shortOpt = shortOpt + self.longOpt = longOpt + self.sysArgv = sys.argv[1:] + + def getopt(self): + try: + opts, args = getopt.getopt(self.sysArgv,self.shortOpt,self.longOpt) + except getopt.GetoptError: + self.handlerErrOpt() + sys.exit(1) + for option, value in opts: + if len(option) == 2: + option = option[1:] + else: + option = option[2:] + self.handlerOpt(option,value) + for param in args: + self.handlerParam(param) + + def handlerErrOpt(self): + # Обработчик в случае неправильных параметров + pass + + def handlerOpt(self,option,value): + # Обработчик (параметр значение) + pass + + def handlerParam(self,param): + # Обработчик хвостов (значение) + pass + +############################################################################### +import cl_profile +# from . import cl_profile +class iniParser(cl_profile._error): + """Класс для работы с ini файлами + + """ + def __init__(self, iniFile): + # название ini файла + self.iniFile = iniFile + # права создаваемого ini-файла + self.mode = 0o640 + # Cоответствует ли формат файла нужному + self.checkIni = None + + def setMode(self, mode): + """установка прав создаваемого ini-файла""" + self.mode = mode + + def openIniFile(self): + if not os.access(self.iniFile, os.R_OK): + return "" + FD = open(self.iniFile, "r") + textIni = FD.read() + FD.close() + return textIni + + def writeIniFile(self, txtConfig): + if not os.path.exists(self.iniFile): + fd = os.open(self.iniFile, os.O_CREAT) + os.close(fd) + os.chmod(self.iniFile, self.mode) + if not os.path.exists(self.iniFile): + self.setError(_("Unable to create file") + ": " + self.iniFile) + return False + FD = open(self.iniFile, "r+") + FD.truncate(0) + FD.seek(0) + FD.write(txtConfig) + FD.close() + + def setVar(self, strHeader, dictVar): + """Заменяет или добавляет область и переменные + + Добавляет область в ini-файл или объединяет с существующей + strHeader - имя области + dictVar - словарь переменных + """ + textIni = self.openIniFile() + nameFomat = self.checkIniFile(textIni) + if not nameFomat: + return False + if type(strHeader) in (tuple, list): + # формат plasma + classObj = cl_profile.plasma + else: + if nameFomat == "plasma": + self.setError(_("In the file %s (format - 'plasma'), \ + write the variable in the format 'samba'")\ + %self.iniFile) + return False + # формат samba + classObj = cl_profile.samba + # создаем объект + # и записываем в него содержимое ini-файла + objIni = classObj(textIni) + # создаем текст из строки заголовка и + # словаря переменных области + txtConfig = objIni.createTxtConfig(strHeader, dictVar) + # создаем объект и записываем в него текст + objIniAdd = classObj(txtConfig) + # объединяем объекты для получения результирующего текста + objIni.join(objIniAdd) + # получаем текст + txtConfig = objIni.getConfig() + # записываем его в ini файл + self.writeIniFile(txtConfig) + return True + + def isEmptyFile(self, textIni): + """Является ли файл пустым""" + if not textIni.strip(): + return True + else: + return False + + def checkIniFile(self, textIni): + """Проверка на правильность формата файла""" + if self.checkIni == None: + # Ошибка + if textIni == False: + self.checkIni = False + return False + self.checkIni = "samba" + # В файле есть данные + textIni = re.sub(r"^#.*$",textIni,'',re.M) + if not self.isEmptyFile(textIni): + try: + objIni = cl_profile.plasma(textIni) + except: + self.setError(_("Incorrect format file") + ": " + \ + self.iniFile) + self.checkIni = False + return self.checkIni + allAreas = objIni.docObj.getAllAreas() + for xmlArea in allAreas: + parentNode = xmlArea.getparent() + if parentNode is not None and parentNode.tag == "area": + self.checkIni = "plasma" + break + if self.checkIni == "samba": + objIni = cl_profile.samba(textIni) + xmlBody = objIni.docObj.getNodeBody() + if firstChild(xmlBody) is None: + self.checkIni = False + return self.checkIni + + def delVar(self, strHeader, nameVar): + """Удаляем переменную из ini файла""" + delNameVar = "!%s" %(nameVar) + dictVar = {delNameVar:"del"} + res = self.setVar(strHeader, dictVar) + return res + + def delArea(self, strHeader): + """Удаляем область из ini файла""" + if type(strHeader) in (tuple, list): + # Формат plasma + delStrHeader = strHeader[:] + delStrHeader[-1] = "!%s"%delStrHeader[-1] + else: + # Формат samba + delStrHeader = "!%s" %(strHeader) + dictVar = {"del":"del"} + res = self.setVar(delStrHeader, dictVar) + return res + + def getVar(self, strHeader, nameVar): + """Получаем значение переменной из ini-файла""" + textIni = self.openIniFile() + nameFomat = self.checkIniFile(textIni) + if not nameFomat: + return False + formatPlasma = False + if type(strHeader) in (tuple, list): + # формат plasma + classObj = cl_profile.plasma + formatPlasma = True + else: + if nameFomat == "plasma": + self.setError(_("In the file %s (format - 'plasma'), \ + get the variable in the format 'samba'")\ + %self.iniFile) + return False + # формат samba + classObj = cl_profile.samba + # создаем объект и записываем в него содержимое ini-файла + objIni = classObj(textIni) + # получаем ноду body + xmlBody = objIni.docObj.getNodeBody() + flagFound, xmlBody = self.getLastNode(objIni, xmlBody, strHeader, + formatPlasma) + if flagFound and xmlBody is not None: + if formatPlasma: + strHeader = strHeader[-1] + # находим в области переменную + res = objIni.docObj.getAreaFieldValues(strHeader, nameVar, xmlBody) + else: + res = False + if res is False: + return "" + else: + return res + + + def getLastNode(self, objIni, xmlBody, strHeader, formatPlasma): + """Ищет область в XML в которой область с переменными""" + flagFound = True + lenStrHeader = len(strHeader) + if formatPlasma and lenStrHeader>0: + xmlAreas = [xmlBody] + for i in range(lenStrHeader-1): + flagFound = False + for xmlArea in xmlAreas: + xmlAreas = objIni.docObj.getArea(strHeader[i], xmlArea) + if xmlAreas: + flagFound = True + break + if xmlAreas: + xmlBody = xmlAreas[0] + return flagFound,xmlBody + + def getAreaVars(self, strHeader): + """Получаем все переменнные области из ini-файла""" + textIni = self.openIniFile() + nameFomat = self.checkIniFile(textIni) + if not nameFomat: + return False + formatPlasma = False + if type(strHeader) in (tuple, list): + # формат plasma + classObj = cl_profile.plasma + formatPlasma = True + else: + if nameFomat == "plasma": + self.setError(_("In the file %s (format - 'plasma'), \ + get all variables in the format 'samba'")\ + %self.iniFile) + return False + # формат samba + classObj = cl_profile.samba + # создаем объект типа samba и записываем в него содержимое ini-файла + objIni = classObj(textIni) + # получаем ноду body + xmlBody = objIni.docObj.getNodeBody() + flagFound, xmlBody = self.getLastNode(objIni, xmlBody, strHeader, + formatPlasma) + if flagFound and xmlBody is not None: + if formatPlasma: + strHeader = strHeader[-1] + # если находим область то выдаем словарем все переменные иначе False + res = objIni.docObj.getAreaFields(strHeader, xmlBody) + else: + res = False + if res is False: + return {} + else: + return res + + def getAllSectionNames(self): + """Получаем все имена секций определенных в ini файле + + Если формат ini файла plasma то имя секции - + имена нескольких секций через запятую + """ + textIni = self.openIniFile() + nameFomat = self.checkIniFile(textIni) + if not nameFomat: + return False + if nameFomat == "samba": + # создаем объект типа samba и записываем в него содержимое ini-файла + objIni = cl_profile.samba(textIni) + elif nameFomat == "plasma": + # создаем объект типа plasma и записываем в него содержимое + # ini-файла + objIni = cl_profile.plasma(textIni) + else: + return [] + xmlNodes = objIni.docObj.getAllAreas() + # Имена секций ini файла + namesSection = [] + if nameFomat == "plasma": + for xmlNode in xmlNodes: + nSect = objIni.docObj.getNameArea(xmlNode) + if nSect: + namesSect = [nSect] + parentNode = xmlNode.getparent() + while parentNode != objIni.docObj.body: + nameSect = objIni.docObj.getNameArea(parentNode) + if nameSect is not None: + namesSect.append(nameSect) + parentNode = parentNode.getparent() + else: + return [] + namesSection.append(",".join(reversed(namesSect))) + elif nameFomat == "samba": + # получаем ноду body + for xmlNode in xmlNodes: + nSect = objIni.docObj.getNameArea(xmlNode) + if nSect: + namesSection.append(nSect) + return namesSection + +############################################################################## + +class var: + '''Объект "Переменная окружения"''' + # название сервиса которому принадлежит переменная + #(Global, Builder, Client, Server итд) + service = None + # значение переменной + value = "" + # режим записи (атрибут mode) + mode = "r" + # переменная для внутреннего использования (official) + official = False + # количество вызовов метода заполнения + countFill = 0 + # объект в котором создан этот объект + parentObj = None + # запускать или нет метод заполнения + fillStart = True + # dynamic = True то переменная динамическая при повтороном запуске + # запускается метод заполнения + # метод заполнения не запускается только если fillStart = False + # (осторожно возможно зацикливание программы если методы заполнения + # переменных используют методы друг друга) + dynamic = False + + def __init__(self, parentObj): + # словарь зависимых переменных {имя:значение} + self.dependValues = {} + # тип переменной (атрибут type) + self.type = ('default') + # список допустимых значений переменных (select) + self.select = () + # объект который создал этот объект + self.parentObj = parentObj + + def is_update(self): + #Нужно ли перезапускать метод заполнения (если зависимые переменные + #обновились то нужно) + upd = False + for depVarName in self.dependValues.keys(): + value = self.parentObj.__getattribute__(depVarName).Get() + if self.dependValues[depVarName] != value: + self.dependValues[depVarName] =\ + self.parentObj.__getattribute__(depVarName).value + upd = True + break + return upd + + def Get(self): + """Получение значения переменной""" + if not self.fillStart: + return self.value + if self.dynamic: + self.value = self.Fill() + return self.value + if not self.value: + if self.countFill>0: + return self.value + self.countFill += 1 + self.value = self.Fill() + if self.dependValues and self.is_update(): + self.countFill += 1 + self.value = self.Fill() + return self.value + + def Set(self, value): + """Запись значения переменной""" + self.value = value + return self.value + + def Fill(self): + """Заполнение переменной в далнейшем заменяем методом заполнения""" + return self.value + + +class DataVars(): + class DataVarsError(Exception): + """Класс ошибок""" + pass + # добавляем пути к модулям если они не добавлены + if not os.path.abspath(\ + '/usr/lib/calculate/calculate-server/pym') in sys.path: + sys.path.insert(0,os.path.abspath(\ + '/usr/lib/calculate/calculate-server/pym')) + if not os.path.abspath(\ + '/usr/lib/calculate/calculate-lib/pym') in sys.path: + sys.path.insert(0,os.path.abspath(\ + '/usr/lib/calculate/calculate-lib/pym')) + if not os.path.abspath(\ + '/usr/lib/calculate/calculate-builder/pym') in sys.path: + sys.path.insert(0,os.path.abspath(\ + '/usr/lib/calculate/calculate-builder/pym')) + # Импортируемые модули - (раздел: модуль переменных, модуль заполнения + #переменных) + __modlist={ + 'Global':('cl_vars','cl_fill'), + 'Server':('cl_vars_server','cl_fill_server'), + 'Builder':('cl_vars_builder','cl_fill_builder'), + 'Client':('cl_vars_client','cl_fill_client'), + } + def __init__(self): + #self.t1 = fillVars() + #self.t1.Get = self.Get + #self.t1.Set = self.Set + # Для нахождения зависимостей переменных + self.__levelNumber = 0 + self.__LevelsVar = [] + # Для хранения импортированных модулей и объектов + #[(cекция,импортированный модуль переменных, объект заполнения),] + self._importList = [] + self._importData("Global") + + def _importData(self, section): + """Импортирует модули с переменными и модули с функциями заполнения + + section секция раздела (Global, Server, Client итд) + создает необходимые структуры данных + """ + if not section in self.__modlist.keys(): + raise self.DataVarsError(_("Unsupported section %s")%section) + modVar = self.__modlist[section][0] + modFill = self.__modlist[section][1] + # Импортируем класс описания переменных и класс заполнения + try: + # eval("import %s" % (modVar)) + modVar_imported = importlib.import_module(modVar) + except ImportError as e: + err1 = _("Error in import module %s")%modVar + err2 = _("error") + ": " +str(e) + raise self.DataVarsError("%s\n%s"%(err1,err2)) + flagFindFillModule = True + try: + # eval("import %s" % (modFill)) + modFill_imported = importlib.import_module(modFill) + except ImportError as e: + if "No module named" in str(e): + flagFindFillModule = False + else: + err1 = _("Error in import module %s")%modFill + err2 = _("error") + ": " + str(e) + raise self.DataVarsError("%s\n%s"%(err1,err2)) + if flagFindFillModule: + # Создаем объект с методами заполнения переменных + fillObj = modFill_imported.fillVars() + importlib.import_module(modFill) + # Подключаем методы получения и записи переменных + fillObj.Get = self.Get + fillObj.Set = self.Set + else: + fillObj = False + # Заполняем self._importList + self._importList.insert(0,(section, modVar_imported, fillObj)) + + + def __findVarData(self, nameVar): + """Находит данные для создания объекта переменная в модулях и + + объектах + """ + # Ищем переменную в модуле + dataVar = False + err = False + for section, moduleVar, fillobj in self._importList: + try: + # dataVar = moduleVar.Data.nameVar + dataVar = getattr(moduleVar.Data, nameVar) + except AttributeError as e: + err = e + if dataVar: + break + if dataVar == False: + err1 = _("Not found variable %s") % nameVar + err2 = "" + if err: + err2 = _("error") + ": " +str(err) + raise self.DataVarsError("%s\n%s" % (err1, err2)) + dataVar['service'] = section + # Ищем метод в объекте методов заполнения + nameMethod = "get_" + nameVar + flagFindMetod = False + for section, moduleVar, fillobj in self._importList: + if fillobj: + if nameMethod in dir(fillobj): + flagFindMetod = True + method = fillobj.__getattribute__(nameMethod) + break + if flagFindMetod: + return (dataVar,method) + else: + return (dataVar,False) + + def __setAttributesVar(self, var ,nameVar, dict): + """Установка аттрибутов для созданного объекта var + + название аттрибута и его значение берется из словаря dict + """ + dict['type'] = nameVar.split('_') + if not set(dict.keys()) <= set(dir(var)): + raise self.DataVarsError(\ + _("error initalize variable %s, incorrect data")%nameVar) + for nameAttr in dict.keys(): + setattr(var,nameAttr, dict[nameAttr]) + return True + + def __Get(self, nameVar): + ret = "" + self.__LevelsVar.append((self.__levelNumber, nameVar)) + self.__levelNumber += 1 + #nameMethod = "get_" + nameVar + if hasattr(self, nameVar): + ret = self.__getattribute__(nameVar).Get() + elif self.__findVarData(nameVar): + dictVar, methodFill =self.__findVarData(nameVar) + varobj = var(self) + # Устанавливаем аттрибуты + self.__setAttributesVar(varobj, nameVar, dictVar) + if methodFill: + varobj.Fill = methodFill + self.__setattr__(nameVar, varobj) + ret = self.__getattribute__(nameVar).Get() + self.__levelNumber -= 1 + if self.__levelNumber == 0 and\ + self.__getattribute__(nameVar).fillStart and\ + len(self.__LevelsVar)>1: + links = self.__getLinks(self.__LevelsVar) + for name in links.keys(): + for nameLink in links[name].keys(): + val = self.__getattribute__(nameLink).Get() + self.__getattribute__(name).dependValues[nameLink] = val + if self.__levelNumber == 0: + self.__LevelsVar = [] + return ret + + def Get(self, nameVar): + # tmp = self.__Get(nameVar) + # isBytes = isinstance(tmp, bytes) + # if isBytes: + # print(f"DEBUG: var {nameVar} returned bytes value: {tmp}") + # return tmp.decode("UTF-8") if isBytes else tmp + return self.__Get(nameVar) + + + def __Set(self, nameVar, value, force=False): + nameMethod = "get_" +nameVar + if not hasattr(self, nameVar) and self.__findVarData(nameVar): + dictVar, methodFill =self.__findVarData(nameVar) + varobj = var(self) + # Устанавливаем аттрибуты + self.__setAttributesVar(varobj, nameVar, dictVar) + if methodFill: + varobj.Fill = methodFill + self.__setattr__(nameVar, varobj) + if hasattr(self, nameVar): + if not force and "r" in getattr(self, nameVar).mode: + print(_("Attempt to rewrite a variable for reading:%s")\ + %nameVar) + return False + self.__getattribute__(nameVar).fillStart = False + return self.__getattribute__(nameVar).Set(value) + + def Set(self, nameVar, value, force=False): + return self.__Set(nameVar, value, force) + + def __frame(self, lVar): + """получить список областей зависимости переменных""" + data = [] + if not lVar: + return data + firstLevel = lVar[0][0] + for level, name in lVar[1:]: + if level> firstLevel: + data.append((level, name)) + else: + break + return data + + def __getLinks(self, lVar): + """Получить список переменных и от каких переменных они зависят + + на вход список [(уровень рекурсии, название переменной),] + """ + links = {} + frames = {} + levelLinks = {} + lVarFr = lVar + for level, name in lVar: + fr = self.__frame(lVarFr) + if name not in frames: + frames[name] = fr + levelLinks[name] = level+1 + lVarFr = lVarFr[1:] + for name in frames.keys(): + level = levelLinks[name] + fr = frames[name] + links[name] = {} + for lv, nm in fr: + if level == lv: + links[name][nm] = "" + return links + + def __getPathCalculateIni(self): + """Получить пути до ini файлов""" + return self.Get('cl_env_path') + + def __getSection(self, vname): + """секция для записи в ini файл переменной + + vname - имя переменной + """ + if hasattr(self, vname): + if getattr(self, vname).service == 'Global': + return 'calculate' + else: + return getattr(self, vname).service.lower() + + def __writeVarValue(self, vname, val, location, header): + '''Записать значение в calculate.ini + + Параметры: + vname имя переменной + val значение переменной + location расположение ini файла ('default', 'local', 'remote') + header раздел ini файла ('client', 'server', 'calculate') + + Возвращаемые значение: + True запись успешна + False запись не удалсь + ''' + # получаем все пути до ini файлов + calculate_ini = self.__getPathCalculateIni() + # получаем полный путь до файла ini + if location == 'default': + name_calculate_ini = calculate_ini[3] + elif location == 'custom': + name_calculate_ini = calculate_ini[2] + elif location == 'local': + name_calculate_ini = calculate_ini[1] + elif location == 'remote': + name_calculate_ini = calculate_ini[0] + else: + return False + # извлекаем из полного имени файла путь + onlydir = os.path.split(name_calculate_ini)[0] + try: + # проверяем чтобы путь до ини файла существовал + if not os.path.exists(onlydir): + # создаем его если отсутствует + os.makedirs(onlydir) + except OSError as e: + print(e) + return False + config = iniParser(name_calculate_ini) + # Получаем секцию конфигурационного файла + if not header: + header = self.__getSection(vname) + return config.setVar(header,{vname: cl_utils.convertStrListDict(val)}) + + def __deleteVarValue(self, vname, location, header): + '''Удалить переменную в calculate.ini + + Параметры: + vname имя переменной + location расположение ini файла ('default', 'local', 'remote') + header раздел ini файла ('client', 'server', 'calculate') + + Возвращаемые значение: + True удалено успешно + False удаление не удалсь + ''' + # получаем все пути до ini файлов + calculate_ini = self.__getPathCalculateIni() + # получаем полный путь до файла ini + if location == 'default': + name_calculate_ini = calculate_ini[3] + elif location == 'custom': + name_calculate_ini = calculate_ini[2] + elif location == 'local': + name_calculate_ini = calculate_ini[1] + elif location == 'remote': + name_calculate_ini = calculate_ini[0] + else: + return False + # извлекаем из полного имени файла путь + onlydir = os.path.split(name_calculate_ini)[0] + # проверяем чтобы путь до ини файла существовал + if not os.path.exists(onlydir): + return False + config = iniParser(name_calculate_ini) + # Получаем секцию конфигурационного файла + if not header: + header = self.__getSection(vname) + if not header: + self.Get(vname) + header = self.__getSection(vname) + # Удаляем переменную + retDelVar = config.delVar(header, vname) + retDelArea = True + if not config.getAreaVars(header): + retDelArea = config.delArea(header) + if retDelArea and retDelVar: + return True + else: + return False + + def Write(self, vname, val, force=False, location='default',header=False): + '''Установить и записать значение переменной в ini файл + + Параметры: + vname имя переменной + val значение переменной + force "принудительный режим" + location расположение ini файла ('default', 'local', 'remote') + header раздел ini файла ('client', 'server', 'calculate') + ''' + if self.__Set(vname, val, force)!= False: + if not val.strip(): + self.__deleteVarValue(vname, location, header) + self.__writeVarValue(vname, val, location, header) + return True + return False + + def Delete(self, vname, location='default', header=False): + '''Удалить переменную в calculate.ini + + Параметры: + vname имя переменной + location расположение ini файла ('default', 'local', 'remote') + + Возвращаемые значение: + True удалено успешна + False удаление не удалсь + ''' + return self.__deleteVarValue(vname, location, header) + + def __getActiveSections(self): + """активные секции в ini файле""" + act_section = [] + for service,t,t in self._importList: + if service == "Global": + act_section.append('calculate') + else: + act_section.append(service.lower()) + return act_section + + def flIniFile(self): + '''Заместить значение переменных значениями из ини файлов + + Возвращаемые значения: + cловарь импортированных переменных - переменные считаны + False - файл не был обнаружен + ''' + #Cловарь переменных из ini файлов + importVars = {} + calculate_ini = self.__getPathCalculateIni() + # активные секции (секции из которых будут использованы переменные) + act_section = self.__getActiveSections() + set_act_section = set(act_section) + i = 0 + locations = ['remote','local','custom','default'] + for name_calculate_ini in calculate_ini: + # проверить сущестование ini файла + if os.path.exists(name_calculate_ini): + # получить объект настроенный на ini + config = iniParser(name_calculate_ini) + # получаем все секции из конфигурационного файла + allsect = config.getAllSectionNames() + if not allsect: + continue + # находим встречающиеся у обоих секции + act_sect = tuple(set(allsect)& set_act_section) + # словарь переменных для ini - файла + importFileVars = {} + # получаем все переменные из всех секций + for section in act_sect: + allvars = config.getAreaVars(section) + if allvars == False: + return False + # словарь переменных для ini - файла + importFileVars = {} + # принудительно переписать все переменные окружения + # полученные из ini + for (k,v) in allvars.items(): + value = cl_utils.convertStrListDict(v) + self.Set(k, value, True) + importFileVars[k] = value + if i < 4: + importVars[locations[i]] = importFileVars + i += 1 + return importVars + + def flServer(self, **args): + '''Заполнить конфигурацию переменных, для ldap''' + # заполнить переменные окружения алгоритмом по умолнанию + self._importData("Server") + + def flClient(self, **args): + '''Заполнить конфигурацию переменных, для клиента''' + # заполнить переменные окружения алгоритмом по умолнанию + self._importData("Client") + + def flBuilder(self, **args): + '''Заполнить конфигурацию переменных, для билдера''' + self.Set('setup_pass','builder',True) + # заполнить переменные окружения алгоритмом по умолнанию + self._importData("Builder") + + def flInstall(self, **args): + '''Заполнить конфигурацию переменных для инсталятора''' + self.Set('setup_pass','install',True) + + + def defined(self, vname): + return True + + + + def exists(self, nameVar): + """ Определяет существует ли переменная с таким имененм + """ + if hasattr(self, nameVar): + return True + foundVar = False + # Ищем переменную в импортируемых модулях + for section, moduleVar, fillobj in self._importList: + if nameVar in moduleVar.Data.__dict__: + foundVar = True + break + return foundVar + + def getVars(self, type_names=None): + ret = {} + for section, moduleVar, fillobj in self._importList: + dataVar = moduleVar.Data + dictVars = dir(dataVar) + for nameVar in dictVars: + if not "__" in nameVar: + if not ("official" in getattr(dataVar,nameVar) and\ + getattr(dataVar,nameVar)['official']): + self.Get(nameVar) + if type_names: + #type_names.sort() + varType =list(getattr(dataVar,nameVar)['type']) + #varType.sort() + #print type_names + #print varType + #print + if not set(type_names)<=set(varType): + continue + ret[nameVar] = getattr(self,nameVar) + return ret + + #распечатать список переменных с значениями + def printVars(self,type_names=None): + var = None + var = self.getVars(type_names) + mlen_name = 0 + mlen_type = 0 + mlen_mode = 0 + for i,j in var.items(): + if len(i) > mlen_name: + mlen_name = len(i) + #if len(str(j.type))>mlen_type: + #mlen_type=len(str(j.type)) + vtype=str(type(var[i].value)).split(" ")[1][1] + if not '[' in var[i].mode: + if vtype in ['d','l']: + mode="[%s%s]"%(var[i].mode.lower(),vtype) + else: + mode="[%s]"%(var[i].mode.lower()) + var[i].mode = mode + if len(mode) > mlen_mode: + mlen_mode = len(mode) + plist = list(var.keys()) + plist.sort() + br = cl_utils.fillstr("-",mlen_name) + " " +\ + cl_utils.fillstr("-",mlen_mode) + " " + cl_utils.fillstr("-",10) + #cl_utils.fillstr("-",mlen_type) + " " +\ + + print("The list of variables:") + print("var name".center(mlen_name),\ + "Mode","Value") + #"Type".center(mlen_type),\ + + + print(br) + for i in plist: + #if var[i].value is None: + #continue + p_val = var[i].value + if var[i].official: + continue + cl_utils.columnWrite( i, mlen_name, var[i].mode.lower(), + mlen_mode, + #str(var[i].type), + #mlen_type, + p_val) + print(br) + + + +############################################################################## +class glob_attr: + """Глобальные аттрибуты для методов заполнения переменных""" + + def _runos(self,cmd, ret_first=None, env=None): + """Вернуть результат выполнения команды ОС""" + if not env: + env = {} + env.update(dict(os.environ)) + env.update([("PATH",cl_utils.getpathenv())]) + retCode, programOut = cl_utils.runOsCommand(cmd, None, ret_first, env) + if not retCode: + return programOut + return False diff --git a/pym/cl_fill.py b/pym/cl_fill.py new file mode 100644 index 0000000..3b81bf4 --- /dev/null +++ b/pym/cl_fill.py @@ -0,0 +1,304 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +_ = lambda x : x +import re +import os +import types +import cl_utils +import cl_base + +class fillVars(cl_base.glob_attr): + + def get_os_net_domain(self): + ''' Определим домен''' + domain=self._runos("hostname -d 2>&1") + if not domain: + print(_("Error:") + " " +_("Not found domain name")) + print(_("Command 'hostname -d' returns an empty value")) + cl_base.exit(1) + elif re.search("^hostname: ",domain): + return "local" + else: + return domain + + def get_os_linux_shortname(self): + '''Получить переменную короткого названия системы''' + path = '/etc/calculate/calculate.ini' + if os.path.exists(path): + FD = open(path) + data = FD.readlines() + FD.close() + shortNameList = [x for x in (len(y.split("=")) == 2 and\ + y.split("=")[0]=="calculate" and\ + y.split("=")[1].strip() for y in data) if x] + if shortNameList: + return shortNameList[0] + gentooFile = "/etc/gentoo-release" + shortName = "Linux" + if os.path.exists(gentooFile): + shortName = "Gentoo" + return shortName + + def get_os_linux_name(self): + """полное название системы""" + linuxShortName = self.Get("os_linux_shortname") + if linuxShortName: + dictLinuxName = {"CLD":"Calculate Linux Desktop", + "CLDX":"Calculate Linux Desktop", + "CLDG":"Calculate Linux Desktop", + "CDS":"Calculate Directory Server", + "Gentoo":"Gentoo"} + if linuxShortName in dictLinuxName.keys(): + return dictLinuxName[linuxShortName] + else: + return "Linux" + else: + return "Linux" + + def get_os_linux_subname(self): + """постфикс к названию системы""" + linuxShortName = self.Get("os_linux_shortname") + if linuxShortName: + dictLinuxSubName = {"CLD":"KDE", "CLDX":"XFCE", "CLDG":"GNOME"} + if linuxShortName in dictLinuxSubName.keys(): + return dictLinuxSubName[linuxShortName] + else: + return "" + else: + return "" + + def get_os_linux_ver(self): + '''Получить версию системы''' + path = '/etc/calculate/calculate.ini' + if os.path.exists(path): + FD = open(path) + data = FD.readlines() + FD.close() + shortNameList = [x for x in ( len(y.split("="))==2 and\ + y.split("=")[0]=="linuxver" and\ + y.split("=")[1].strip() for y in data) if x] + if shortNameList: + return shortNameList[0] + gentooFile = "/etc/gentoo-release" + systemVersion = "" + flagGentoo = False + if os.path.exists(gentooFile): + gentooLink = "/etc/make.profile" + if os.path.islink(gentooLink): + systemVersion = os.readlink(gentooLink).rpartition("/")[2] + flagGentoo = True + if not flagGentoo: + kernelVersion=self._runos("uname -r") + if kernelVersion: + systemVersion = kernelVersion.partition("-")[0] + return systemVersion + + def get_os_net_hostname(self): + '''Считать имя компьютера net_host''' + hostname=self._runos("hostname -s 2>&1") + if not hostname: + return "" + if re.search("^hostname: ",hostname): + hostname=self._runos("hostname 2>&1") + if not hostname: + return "" + if re.search("^hostname: ",hostname): + return self.Get('os_linux_shortname') + else: + if hostname=='livecd': + return self.Get('os_linux_shortname') + return hostname + + # все ip + def get_os_net_ip(self): + """все ip компьютера, разделитель запятая""" + return ",".join(cl_utils.getIp(x) for x in cl_utils.getInterfaces()) + + # Разрешенные сети (в данном случае все сети) + def get_os_net_allow(self): + """Разрешенные сети разделитель запятая""" + networks=[] + netInterfaces=cl_utils.getInterfaces() + for i in netInterfaces: + ipaddr, mask = cl_utils.getIp(i), \ + cl_utils.cidrToMask(cl_utils.getMask(i)) + if ipaddr and mask: + networks.append(cl_utils.getIpNet(ipaddr, mask)) + else: + networks.append("") + return ",".join(x for x in networks if x) + + def get_os_locale_locale(self): + """локаль (прим: ru_RU.UTF-8)""" + if "LANG" in os.environ: + return os.environ["LANG"] + else: + return "en_US.UTF-8" + + def get_os_locale_lang(self): + """язык (прим: ru_RU)""" + locale = self.Get("os_locale_locale") + if locale: + return locale.split(".")[0] + return "" + + def get_os_locale_language(self): + """язык (прим: ru)""" + lang = self.Get("os_locale_lang") + if lang: + return lang.split("_")[0] + return "" + + def get_os_locale_xkb(self): + """раскладка клавиатуры для X""" + path = '/etc/conf.d/keymaps' + mapDict={"by":"us,by", + "be-latin1":"be,us", + "br-abnt2":"br,us", + "cf":"ca,us", + "dk-latin1":"dk,us", + "fr-latin9":"fr,us", + "de-latin1":"de,us", + "is-latin1":"is,us", + "it":"it,us", + "no-latin1":"no,us", + "pl":"pl,us", + "-u ru4":"us,ru(winkeys)", + "es euro2":"es,us", + "sv-latin1":"se,us", + "ua-utf":"us,ua(winkeys)", + "uk":"gb,us", + "us":"us"} + if os.path.exists(path): + FD = open(path) + data = FD.readlines() + FD.close() + shortNameList = [x for x in (len(y.split("="))==2 and\ + y.split("=")[0]=="KEYMAP" and\ + y.split("=")[1].replace('"',"").strip() + for y in data) if x] + if shortNameList: + if shortNameList[0] in mapDict.keys(): + return mapDict[shortNameList[0]] + lang = self.Get("os_locale_lang") + # Языки: + # Португальский - pt_BR + # Французский - fr_FR + # Немецкий - de_DE + # Итальянский - it_IT + # Польский - pl_PL + # Русский - ru_RU + # Испанский - es_ES + # Украинский - uk_UA + # Английский - en_US + xkbDict = {'pt_BR':'br,us', + 'fr_FR':'fr,us', + 'de_DE':'de,us', + 'it_IT':'it,us', + 'pl_PL':'pl,us', + 'ru_RU':'us,ru(winkeys)', + 'es_ES':'es,us', + 'uk_UA':'us,ua(winkeys)', + 'en_US':'us'} + if lang: + if lang in xkbDict: + return xkbDict[lang] + return "" + + def get_os_locale_xkbname(self): + """названия используемых раскладок клавиатуры для X""" + localeXkb = self.Get("os_locale_xkb") + if localeXkb: + return localeXkb.split("(")[0] + return "" + + def get_os_arch_machine(self): + """архитектура процессора""" + march = self._runos("uname -m") + if not march: + return "" + return march + + def get_os_root_dev(self): + """корневой раздел файловой системы""" + for record in open('/proc/cmdline','rb').readlines(): + re_res=re.search('^root=(\/dev\/[a-z]+[0-9]).*',record.strip()) + if re_res: + return re_res.group(1) + else: + mountLunes = self._runos("mount") + if not mountLunes: + return "" + if type(mountLunes) == list: + root_dev = mountLunes[0].split("on / type")[0].strip() + if root_dev: + return root_dev + return "" + + def get_os_root_type(self): + """тип носителя (ram, hdd, livecd)""" + mountLunes = self._runos("mount") + if not mountLunes: + return "" + rootType = "hdd" + if type(mountLunes) == list: + flagCD = False + for line in mountLunes: + if "/dev/loop0 on / type" in line: + rootType = "ram" + break + elif "/dev/loop0 on /newroot/mnt/livecd type" in line: + rootType = "ram" + flagCD = True + break + if rootType == "ram": + if os.path.exists("/mnt/livecd") or flagCD: + rootType = "livecd" + return rootType + rootDev = self.Get("os_root_dev") + if rootType != "ram" and rootDev: + slpRootDev = rootDev.split("/dev/") + if len(slpRootDev) == 2: + rDev = slpRootDev[1] + devLines = self._runos("ls -la /dev/disk/by-id/", None, + {"LANG":"C"}) + if not devLines: + return "" + if type(devLines) == list: + for line in devLines: + if rDev in line and "usb-" in line: + rootType = "usb-hdd" + break + if rootType == "ram": + rootType = "hdd" + return rootType + else: + return "" + + def get_hr_virtual(self): + """Название виртуальной машины (virtualbox, vmware, qemu)""" + pciLines = self._runos("/usr/sbin/lspci") + if not pciLines: + return False + virtSysDict = {'VirtualBox':'virtualbox', + 'VMware':'vmware', + 'Qumranet':'qemu'} + virtName = '' + for vName in virtSysDict.keys(): + if [x for x in pciLines if vName in x]: + virtName = virtSysDict[vName] + break + return virtName diff --git a/pym/cl_fill_server.py b/pym/cl_fill_server.py index 04c303e..fb2c35b 100644 --- a/pym/cl_fill_server.py +++ b/pym/cl_fill_server.py @@ -13,12 +13,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import os import cl_base import cl_utils import hashlib +import re +import types + +# _ = lambda x: x -class fillVars(object, cl_base.glob_attr): +class fillVars(cl_base.glob_attr): def getHash(self, password, encrypt): """Получить хеш пароля @@ -30,7 +35,7 @@ class fillVars(object, cl_base.glob_attr): res = self._runos(runStr) if res: return res.strip() - print "Error generate hash (slappasswd)" + print("Error generate hash (slappasswd)") exit(1) def get_cl_profile_path(self): @@ -230,7 +235,7 @@ class fillVars(object, cl_base.glob_attr): for replServer in replServers: if replServer: md5hex = hashlib.md5(replServer).hexdigest() - data8bit = "".join(map(lambda x: str(int(x,16)/2),list(md5hex))) + data8bit = "".join((str(int(x,16)/2) for x in list(md5hex))) dStart = 0 dEnd = 3 dMax = 32 @@ -470,13 +475,13 @@ class fillVars(object, cl_base.glob_attr): netAllow = self.Get("sr_proxy_net_allow") if netAllow: netAllow = netAllow.split(",") - netAllow = map(lambda x: "acl localnet src %s"%x,netAllow) + netAllow = ["acl localnet src %s" % x for x in netAllow] netAllow = "\n".join(netAllow) return netAllow netAllow = self.Get("os_net_allow") if netAllow: netAllow = netAllow.split(",") - netAllow = map(lambda x: "acl localnet src %s"%x,netAllow) + netAllow = ["acl localnet src %s" % x for x in netAllow] netAllow = "\n".join(netAllow) return netAllow return "acl localnet src 127.0.0.1/32" @@ -543,14 +548,14 @@ class fillVars(object, cl_base.glob_attr): """Текст в ejabberd.cfg - имена хостов с которыми работает сервис""" jabberHosts = self.Get("sr_jabber_hosts") if jabberHosts: - return ", ".join(map(lambda x: '"'+x+'"', jabberHosts.split(","))) + return ", ".join(('"'+x+'"' for x in jabberHosts.split(","))) return "" def get_sr_jabber_hosts_yml(self): """Текст в ejabberd.cfg - имена хостов с которыми работает сервис""" jabberHosts = self.Get("sr_jabber_hosts") if jabberHosts: - return "\n".join(map(lambda x: ' - "%s"' % x, jabberHosts.split(","))) + return "\n".join((' - "%s"' % x for x in jabberHosts.split(","))) return "" def get_sr_jabber_user_name(self): @@ -591,7 +596,7 @@ class fillVars(object, cl_base.glob_attr): break if not foundLoc: netAllow.append("127.0.0.1") - netAllow = map(lambda x: "%s;"%x,netAllow) + netAllow = ["%s;" % x for x in netAllow] netAllow = " ".join(netAllow) return "listen-on { %s };"%netAllow netAllow = self.Get("sr_dns_net_allow") @@ -601,3 +606,5 @@ class fillVars(object, cl_base.glob_attr): if netAllow: return getNetAllow(netAllow) return "listen-on { 127.0.0.1; };" + + \ No newline at end of file diff --git a/pym/cl_ldap.py b/pym/cl_ldap.py index 870d4d2..95176e7 100644 --- a/pym/cl_ldap.py +++ b/pym/cl_ldap.py @@ -1,5 +1,3 @@ -#-*- coding: utf-8 -*- - # Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +16,7 @@ import os import sys import re import ldap -import cStringIO, StringIO +from io import StringIO, BytesIO from ldif import LDIFParser, LDIFWriter import cl_base import cl_profile @@ -41,17 +39,21 @@ import tempfile # Вывод в строку ввода import readline # Пути в XML документе -from xml import xpath +from cl_xml import xpath, firstChild, xml_to_str # Для 32 битного целого (генерация серийного номера DNS зоны) import ctypes +from functools import reduce Version = "calculate-server 2.1.20" - +_ = lambda x : x tr = cl_base.lang() tr.setLanguage(sys.modules[__name__]) pcs = cl_utils.prettyColumnStr +def cmp(a, b): + return (a > b) - (b < a) + class report: """Класс для выдачи данных в табличном виде""" def __init__(self, title, headerList, dataList): @@ -109,7 +111,7 @@ class report: def printReport(self): """Напечатать данные в табличном виде""" - print self.title + print(self.title) listStrSep = [] for lenCol in self.columnsWidth: listStrSep.append("-"*lenCol) @@ -123,16 +125,16 @@ class report: if printData[-1] == "\n": printData = printData[:-1] lines = printData.splitlines() - lenCols = map(lambda x: len(x), lines[0].strip().split(" ")) + lenCols = [len(x) for x in lines[0].strip().split(" ")] convLines = [] lenLines = len(lines) for i in range(lenLines): char = " | " if i == 0 or i == 2 or i == lenLines-1: - char ="-+-" + char = "-+-" convLines.append(self._insertStrChar(lines[i], lenCols, char)) - print "\n".join(convLines) - print "(%s %s)"%(len(self.dataList), _("rows")) + print("\n".join(convLines)) + print("(%s %s)" % (len(self.dataList), _("rows"))) return True def _insertStrChar(self, line, lenCols, char): @@ -152,7 +154,7 @@ class report: insertChar = char convLine += lineUnicode[prevPos:pos] + insertChar prevPos = pos + 1 - return convLine.encode("UTF-8") + return convLine def adminConnectLdap(fun): @@ -185,7 +187,7 @@ class iniLdapParser(cl_base.iniParser): self.nameIniFile = "/var/lib/calculate/calculate.ldap" cl_base.iniParser.__init__(self, self.nameIniFile) # права создаваемого ini-файла - self.setMode(0600) + self.setMode(0o600) pathIniFile = os.path.split(self.nameIniFile)[0] if not os.path.exists(pathIniFile): os.makedirs(pathIniFile) @@ -193,12 +195,12 @@ class iniLdapParser(cl_base.iniParser): class addLdif(LDIFParser): """Класс необходимый для добавления записей в LDAP""" def __init__(self, strInput,ldapCon): - FD = cStringIO.StringIO(strInput) + FD = StringIO(strInput) LDIFParser.__init__(self, FD) self.ldapCon = ldapCon def handle(self, dn, entry): - self.ldapCon.add_s(dn, entry.items()) + self.ldapCon.add_s(dn, list(entry.items())) class ldapFunction(cl_utils2.ldapFun): '''Объект для работы с LDAP сервером''' @@ -215,8 +217,8 @@ class ldapFunction(cl_utils2.ldapFun): # Записываем параметры из ldif файла в LDAP сервер parser = addLdif(strLdif,self.conLdap) parser.parse() - except ldap.LDAPError, e: - self.setError(e[0]['desc']) + except ldap.LDAPError as e: + self.setError(str(e)) return False except: self.setError("Error in ldif file") @@ -255,27 +257,27 @@ class shareIP: def getNet(self, ip, mask): """По ip и маске получаем сеть""" octetsMult = (0x1, 0x100, 0x10000, 0x1000000) - octetsIp = map(lambda x: int(x), ip.split(".")) - octetsMask = map(lambda x: int(x), mask.split(".")) + octetsIp = [int(x) for x in ip.split(".")] + octetsMask = [int(x) for x in mask.split(".")] ipNumb = 0 for i in octetsMult: - ipNumb += octetsIp.pop()*i + ipNumb += octetsIp.pop() * i maskNumb = 0 for i in octetsMult: - maskNumb += octetsMask.pop()*i + maskNumb += octetsMask.pop() * i startIpNumber = maskNumb&ipNumb x = startIpNumber - nMask = lambda y: len(filter(lambda x: y >> x &1 ,range(32))) + nMask = lambda y: len([x for x in range(32) if y >> x & 1]) return "%s.%s.%s.%s/%s"\ %(x>>24, x>>16&255, x>>8&255, x&255, nMask(maskNumb)) def getNumberIP(self, ip): """По строке ip получаем число (номер ip)""" - octetsIp = map(lambda x: int(x), ip.split(".")) + octetsIp = [int(x) for x in ip.split(".")] octetsMult = (0x1, 0x100, 0x10000, 0x1000000) ipNumb = 0 for i in octetsMult: - ipNumb += octetsIp.pop()*i + ipNumb += octetsIp.pop() * i return ipNumb def getNumberNetmask(self, netmask): @@ -360,14 +362,14 @@ class shareLdap(imp_cl_err, imp_cl_xml, imp_cl_help, imp_cl_smcon, prnServ): 'Administrators':self.addInfoGroup('Administrators', '544', 'Domain Members can fully \ -administer the computer/sambaDomainName', + administer the computer/sambaDomainName', '544', '5', "S-1-5-32-544"), 'Account Operators':self.addInfoGroup('Account Operators', '548', 'Domain Users to manipulate \ -users accounts', + users accounts', '548', '5', "S-1-5-32-548"), @@ -386,14 +388,14 @@ users accounts', 'Backup Operators':self.addInfoGroup('Backup Operators', '551', 'Domain Members can bypass \ -file security to back up files', + file security to back up files', '551', '5', "S-1-5-32-551"), 'Replicators':self.addInfoGroup('Replicators', '552', 'Domain Supports file replication \ -in a sambaDomainName', + in a sambaDomainName', '552', '5', "S-1-5-32-552"), @@ -490,7 +492,7 @@ in a sambaDomainName', while ldapObj.getError(): try: # Задержка - wait.next() + next(wait) except StopIteration: break # Очистка ошибки @@ -555,7 +557,7 @@ in a sambaDomainName', term = "" if resRestore == True: term = message - if not flagError and type(resRestore) == types.TupleType: + if not flagError and type(resRestore) == tuple: # Если cansel if resRestore[0] == "Cancel": # Удаляем пользователя @@ -589,7 +591,7 @@ in a sambaDomainName', # id пользователя strUid = "" if searchUnixUser: - strUid = searchUnixUser[0][0][1]['uidNumber'][0] + strUid = searchUnixUser[0][0][1]['uidNumber'][0].decode("UTF-8") else: resPasswd = servUnixObj.searchPasswdUser(userName) if resPasswd: @@ -600,7 +602,7 @@ in a sambaDomainName', "%s-%s"%(userName,strUid), service) if strUid and os.path.exists(delBackDir) and os.listdir(delBackDir): - if message == None or type(message) == types.BooleanType: + if message == None or type(message) == bool: dialogRes = message else: dialogRes = self.dialogYesNo(message) @@ -632,12 +634,12 @@ in a sambaDomainName', # id пользователя strUid = "" if searchUnixUser: - strUid = searchUnixUser[0][0][1]['uidNumber'][0] + strUid = searchUnixUser[0][0][1]['uidNumber'][0].decode("UTF-8") if strUid: delBackDir =\ os.path.join(self.clVars.Get("sr_deleted_path"), - "%s-%s"%(userName,strUid), - service) + "%s-%s"%(userName,strUid), + service) if os.path.exists(delBackDir) and os.listdir(delBackDir): self.printERROR(_("Found deleted user data dir %s")\ %delBackDir) @@ -647,15 +649,15 @@ in a sambaDomainName', else: delBackDir =\ os.path.join(self.clVars.Get("sr_deleted_path"), - "%s"%(userName), - service) + "%s"%(userName), + service) i = 0 while os.path.exists(delBackDir): i += 1 delBackDir =\ os.path.join(self.clVars.Get("sr_deleted_path"), - "%s_%s"%(userName,i), - service) + "%s_%s"%(userName, i), + service) # Cоздаем директорию хранения удаленных пользователей if not os.path.exists(self.clVars.Get("sr_deleted_path")): os.makedirs(self.clVars.Get("sr_deleted_path")) @@ -664,23 +666,23 @@ in a sambaDomainName', self.copyDir(delBackDir,srcDir) except: self.printERROR(_("Can not copy deleted user data in dir %s")\ - %delBackDir) + % delBackDir) return False self.printSUCCESS(_("Created deleted user data dir %s")\ - %delBackDir) + % delBackDir) return True - def stringIsJpeg(self, string): - """Определяет является ли строка jpeg изображением""" - if len(string)<8: + def dataIsJpeg(self, bytes): + """Определяет является ли набор байтов jpeg изображением""" + if len(bytes)<8: return False - FD = cStringIO.StringIO(string) + FD = BytesIO(bytes) isJpeg = False FD.seek(0, 0) (firstByte, secondByte) = FD.read(2) - if (ord(firstByte) == 0xff and ord(secondByte) == 0xd8): + if (firstByte == 0xff and secondByte == 0xd8): (firstByte, secondByte) = FD.read(2) - if (ord(firstByte) == 0xff and ord(secondByte) == 0xe0): + if (firstByte == 0xff and secondByte == 0xe0): isJpeg = True return isJpeg @@ -692,9 +694,9 @@ in a sambaDomainName', self.printERROR(_("ERROR") + ": " + execStr) return False else: - splLines = filter(lambda x: len(x)==2 and "default" in x[1],\ - map(lambda x: x.split("|"),textLine)) - splLines = map(lambda x: x[0].strip(), splLines) + splLines = [x for x in (y.split("|") for y in textLine) + if len(x)==2 and "default" in x[1]] + splLines = [x[0].strip() for x in splLines] return splLines @@ -782,7 +784,7 @@ in a sambaDomainName', self.printERROR(clProf.getError()) return False else: - if verbose and type(data) == types.TupleType: + if verbose and type(data) == tuple: dirs, files = data return files return True @@ -804,7 +806,7 @@ in a sambaDomainName', if not service in self.servicesDaemons.keys(): self.printERROR(_("Not supported service '%s'")%service) self.printERROR(\ - _("Can not deleted service from default runlevel")) + _("Can not deleted service from default runlevel")) flagError = True break for daemon in self.servicesDaemons[service]: @@ -833,12 +835,12 @@ in a sambaDomainName', prnService = self.printNameService(service) if flagError: self.printNotOK(_("Starting") + " " + prnService + " " +\ - _("service") + " ...") + _("service") + " ...") return False else: if printSuccess: self.printOK(_("Starting") + " " + prnService + " "+\ - _("service") + " ...") + _("service") + " ...") return True def startServices(self, servInstalled, printSuccess=True): @@ -903,7 +905,7 @@ in a sambaDomainName', ret = self.execProg("/etc/init.d/%s stop"%daemon) if ret == False: self.printERROR(servicePrn + " " +\ - _("service is not stopped")) + _("service is not stopped")) flagError = True break # Удаляем процессы ejabberd @@ -918,10 +920,10 @@ in a sambaDomainName', if "erlang" in process: killPid.append(process.split(" ")[0]) if killPid and " ".join(killPid).strip(): - textLine=self.execProg("kill %s" %" ".join(killPid)) + textLine=self.execProg("kill %s" % " ".join(killPid)) if textLine == False: self.printERROR(_("Can not 'kill %s'")\ - %" ".join(killPid)) + % " ".join(killPid)) flagError = True break elif daemon == "squid" and self.getRunDaemons(["squid"]): @@ -948,11 +950,12 @@ in a sambaDomainName', tic = 0 if errStopProxy: self.printOnlyNotOK(" ",\ - self.lenString(message)+\ - offset+3) + self.lenString(message)+\ + offset + 3) else: - self.printOnlyOK(" ",self.lenString(message)+\ - offset+3) + self.printOnlyOK(" ", + self.lenString(message)+\ + offset + 3) else: sys.stdout.flush() if os.system("/etc/init.d/squid stop &>/dev/null"): @@ -990,17 +993,17 @@ in a sambaDomainName', pwDialog - структура для вывода приглашения в режиме диалога """ userPwd = "" - if optStdIn and options.has_key(optStdIn): + if optStdIn and optStdIn in options: pwdA = sys.stdin.readline().rstrip() pwdB = pwdA - elif optDialog and options.has_key(optDialog): + elif optDialog and optDialog in options: if not pwDialog: pwDialog = [_("New password"), _("Retype new password")] pwdA = getpass.getpass(pwDialog[0]+":") pwdB = getpass.getpass(pwDialog[1]+":") - if (optStdIn and options.has_key(optStdIn)) or\ - (optDialog and options.has_key(optDialog)): + if (optStdIn and optStdIn in options) or\ + (optDialog and optDialog in options): if not pwdA or not (pwdA == pwdB): self.printERROR (_("ERROR") + ": " +\ _("password incorrect")+ ": " + _("try again")) @@ -1032,11 +1035,11 @@ in a sambaDomainName', runDaemons['postfix'] = False continue addDirDict = {"slapd":("openldap","slapd.pid"), - "dovecot":("dovecot","master.pid"), - "proftpd":("","proftpd.pid"), - "squid":("","squid.pid"), - "calculate-profile":("","calculate-profile.pid"), - "sortmilter":("","sortmilter.pid")} + "dovecot":("dovecot","master.pid"), + "proftpd":("","proftpd.pid"), + "squid":("","squid.pid"), + "calculate-profile":("","calculate-profile.pid"), + "sortmilter":("","sortmilter.pid")} baselayoutDir = "/var/lib/init.d/daemons" if not flagBaselayoutDir: if os.path.exists(baselayoutDir): @@ -1057,7 +1060,7 @@ in a sambaDomainName', else: pidDir = os.path.join(baseDir,addDirDict[daemon][0]) if os.access(pidDir, os.F_OK) and os.listdir(pidDir) and\ - os.path.exists(os.path.join(pidDir,addDirDict[daemon][1])): + os.path.exists(os.path.join(pidDir, addDirDict[daemon][1])): runDaemons[daemon] = True else: runDaemons[daemon] = False @@ -1074,24 +1077,24 @@ in a sambaDomainName', """Хеш пароля используя slappasswd""" if not crypt: self.printERROR(_("ERROR") + " getHashPasswd: " +\ - _("crypto algoritm empty")) + _("crypto algoritm empty")) return False - cryptStr = "{%s}"%crypt.upper() + cryptStr = "{%s}" % crypt.upper() lenCryptStr = len(cryptStr) pwd = re.sub("(\W)", r"\\\1", password) - pwdHash = self.execProg("slappasswd -s %s -h %s" %(pwd,cryptStr)) - if pwdHash and len(pwdHash)>lenCryptStr and\ + pwdHash = self.execProg("slappasswd -s %s -h %s" % (pwd, cryptStr)) + if pwdHash and len(pwdHash) > lenCryptStr and\ pwdHash[:lenCryptStr] == cryptStr: return pwdHash self.printERROR(_("ERROR") + " getHashPasswd: " +\ - _("create crypto password")) + _("create crypto password")) return False def getRunService(self, nameService, printError=False): """Проверка, запущен ли сервис с данным именем""" flagError = False if not nameService in self.servicesDaemons.keys(): - self.printERROR(_("Can1 not supported service '%s'")%nameService) + self.printERROR(_("Can1 not supported service '%s'") % nameService) self.printERROR(_("Can not check run service")) return False # Названия демонов для сервиса @@ -1101,7 +1104,7 @@ in a sambaDomainName', if flagError: if printError: self.printERROR(self.printNameService(nameService) + " " +\ - _("service is not started")) + _("service is not started")) return False return True @@ -1111,11 +1114,12 @@ in a sambaDomainName', [not x in retList and retList.append(x) for x in listEl] return retList + #TODO debug magick png to jpeg encoding def setJpegPhotoUser(self, userName, photoPath, attr="uid"): """Добавляем jpeg фотографию пользователя в LDAP""" import subprocess try: - FD = open(photoPath) + FD = open(photoPath, "rb") photoData = FD.read() FD.close() except: @@ -1124,38 +1128,38 @@ in a sambaDomainName', searchUser = self.searchLdapDN(userName, self.relUsersDN, attr) if not searchUser: self.printERROR(_("User") + " " + str(userName) + " "+\ - _("not found")) + _("not found")) return False modAttrs = [] - if not self.stringIsJpeg(photoData): + if not self.dataIsJpeg(photoData): if self.execProg("which convert") is False: self.printERROR(_("Can not found package imagemagick")) return False flagError = False pipe = subprocess.Popen("convert '%s' jpg:-" %photoPath, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True, - shell=True) + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, close_fds=True, + shell=True) fOut, fIn, fErr = (pipe.stdout, pipe.stdin, pipe.stderr) fIn.close() # Код возврата retcode = pipe.wait() if retcode != 0: self.printERROR(_("Can not convert file '%s' in jpeg format")\ - %photoPath) + % photoPath) flagError = True fErr.close() if not flagError: photoData = fOut.read() - if not self.stringIsJpeg(photoData): + if not self.dataIsJpeg(photoData): self.printERROR(\ - _("Can not convert file '%s' in jpeg format") %photoPath) + _("Can not convert file '%s' in jpeg format") % photoPath) flagError = True fOut.close() if flagError: return False - if searchUser[0][0][1].has_key('jpegPhoto'): + if 'jpegPhoto' in searchUser[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'jpegPhoto', photoData)) else: modAttrs.append((ldap.MOD_ADD, 'jpegPhoto', photoData)) @@ -1184,7 +1188,7 @@ in a sambaDomainName', for linkRm in scanObjs[0].links: # Удаляем ссылки os.unlink(linkRm[1]) - scanObjs[0].dirs.sort(lambda x, y: cmp(len(y), len(x))) + scanObjs[0].dirs.sort(key=len, reverse=True) for dirRm in scanObjs[0].dirs: # Удаляем директории os.rmdir(dirRm) @@ -1204,7 +1208,7 @@ in a sambaDomainName', break return True - def createUserDir(self, uid, gid, userDir, mode=0700): + def createUserDir(self, uid, gid, userDir, mode=0o700): """Создание пользовательской директории""" if not os.path.exists(userDir): os.makedirs(userDir) @@ -1216,7 +1220,7 @@ in a sambaDomainName', self.printERROR(_("Path %s exists") %userDir) return False - def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644): + def createUserFile(self, fileName, fileTxt, uid, gid, mode=0o644): """Создает пользовательский файл с содержимым Если директория файла не существует то ошибка @@ -1326,9 +1330,9 @@ in a sambaDomainName', strInput = "" if promptText: # Получаем текст введенный пользователем - strInput = raw_input(promptText) + strInput = input(promptText) else: - strInput = raw_input() + strInput = input() if inputText: # Сбрасываем строку ввода readline.set_pre_input_hook(None) @@ -1342,10 +1346,10 @@ in a sambaDomainName', splNet = strNetworks.replace(","," ").split(" ") if checkNet: checkIP = False - res=re.compile("^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?\/\d\d?$") + res = re.compile("^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?\/\d\d?$") else: checkIP = True - res=re.compile("^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?$") + res = re.compile("^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?$") flagError = False networks = [] for i in splNet: @@ -1357,8 +1361,8 @@ in a sambaDomainName', flagError = True break else: - splIP = map(lambda x: 255>=int(x.split("/")[0]) and\ - x.split("/")[0], find.group().split(".")) + splIP = [255>=int(x.split("/")[0]) and x.split("/")[0] for x + in find.group().split(".")] if not splIP[0] or splIP[0] and int(splIP[0]) == 0: flagError = True break @@ -1367,13 +1371,13 @@ in a sambaDomainName', break if checkNet: netList = r.split("/") - if len(netList)==2: + if len(netList) == 2: try: netMaskInt = int(netList[1]) except: flagError = True break - if netMaskInt>31 or netMaskInt<4: + if netMaskInt > 31 or netMaskInt<4: flagError = True break else: @@ -1400,9 +1404,9 @@ in a sambaDomainName', вывод - список доверительных сетей """ def printW(): - print _("Incorrect string allow networks") - print _("Example - allow networks: 10.0.0.0/24 10.0.10.0/24") - print _("Try again\n") + print(_("Incorrect string allow networks")) + print(_("Example - allow networks: 10.0.0.0/24 10.0.10.0/24")) + print(_("Try again\n")) strNet = self.raw_input(strPrompt, strNetAllow) i = 0 while i<3 and not self.isCorrectStringNet(strNet): @@ -1412,7 +1416,7 @@ in a sambaDomainName', if i == 3 and not self.isCorrectStringNet(strNet): printW() self.printERROR(_("You used four attempts, \ -if you want to continue to run the program again")) + if you want to continue to run the program again")) return False return self.isCorrectStringNet(strNet) @@ -1477,8 +1481,8 @@ if you want to continue to run the program again")) """Добавление узла в LDAP""" try: self.conLdap.add_s(DN, entry) - except ldap.LDAPError, e: - self.printERROR(_("LDAP Error") + ": " + e[0]['desc'].strip()) + except ldap.LDAPError as e: + self.printERROR(_("LDAP Error") + ": " + str(e).strip()) self.printERROR(errorMessage) return False return True @@ -1538,23 +1542,23 @@ This command is not allowed.")) @adminConnectLdap def modAttrsDN(self, relDN, modAttrs): """Модифицирует аттрибуты DN""" - DN = self.addDN(relDN,self.baseDN) + DN = self.addDN(relDN, self.baseDN) if modAttrs: try: self.conLdap.modify_s(DN, modAttrs) - except ldap.LDAPError, e: - self.printERROR(e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR(str(e)) return False return True @adminConnectLdap def modifyElemDN(self, relDN, newFirstDn): """Изменяет основной элемент DN (uid, cn и др.)""" - DN = self.addDN(relDN,self.baseDN) + DN = self.addDN(relDN, self.baseDN) try: self.conLdap.modrdn_s(DN, newFirstDn) - except ldap.LDAPError, e: - self.printERROR(e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR(str(e)) return False return True @@ -1564,8 +1568,8 @@ This command is not allowed.")) DN = self.addDN(relDN,self.baseDN) try: self.conLdap.delete_s(DN) - except ldap.LDAPError, e: - self.printERROR(e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR(str(e)) return False return True @@ -1577,7 +1581,7 @@ This command is not allowed.")) lst.append(0) if resSearch: for scope in resSearch: - if scope[0][1].has_key(attrSearch): + if attrSearch in scope[0][1]: uid = int(scope[0][1][attrSearch][0]) if uid<=numMax and uid>=numMin: lst.append(uid) @@ -1593,10 +1597,10 @@ This command is not allowed.")) dnList = self.conLdap.search_s(DN, ldap.SCOPE_SUBTREE, ldapFilter,None) - except ldap.LDAPError, e: - self.printERROR("fullElementDN: "+e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR("fullElementDN: " + str(e)) return False - FDOUT = StringIO.StringIO("") + FDOUT = StringIO("") writer = LDIFWriter(FDOUT) for dn, f in dnList: writer.unparse(dn, f) @@ -1672,21 +1676,22 @@ This command is not allowed.")) ldap.SCOPE_SUBTREE, '(objectclass=*)', ['']) - except ldap.LDAPError, e: - self.printERROR("deleteDN: "+e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR("deleteDN: "+ str(e)) return False for dn, f in dnList: delListDN.append(dn) - delListDN.sort(lambda x, y: cmp(len(y), len(x))) + delListDN.sort(key=len, reverse=True) + for dn in delListDN: try: self.conLdap.delete_s(dn) - except ldap.LDAPError, e: - self.printERROR("deleteDN: "+e[0]['desc']) + except ldap.LDAPError as e: + self.printERROR("deleteDN: " + str(e)) return False return True - def execProg(self, cmdStrProg, inStr=False, retFull=True, envProg={}): + def execProg(self, cmdStrProg, inStr=False, retFull=True, envProg=None): """Выполняет внешнюю программу Параметры: @@ -1695,9 +1700,15 @@ This command is not allowed.")) Возвращаемые параметры: строка которую выведет внешняя программа или False в случае ошибки """ - env_path = {"PATH":cl_utils.getpathenv()} + if not envProg: + envProg = {} + env_path = {"PATH" : cl_utils.getpathenv()} env = {} - env.update(os.environ.items() + env_path.items() + envProg.items()) + env.update(dict(os.environ)) + env.update(env_path) + env.update(envProg) + + retCode,programOut = cl_utils.runOsCommand(cmdStrProg,inStr,retFull,env) if not retCode: return programOut @@ -1780,7 +1791,7 @@ This command is not allowed.")) while ldapObj.getError(): try: # Задержка - wait.next() + next(wait) except StopIteration: break # Очистка ошибки @@ -1882,11 +1893,11 @@ This command is not allowed.")) sslBits=1024, userName="root",groupName="root", certFile="/tmp/server.pem", - certFileMode=0400, + certFileMode=0o400, keyFile="/tmp/server.key", - keyFileMode=0400, + keyFileMode=0o400, dhFile=None, - dhFileMode=0400, + dhFileMode=0o400, genDH=False): """Создает сертификат""" sslFile = "/usr/bin/openssl" @@ -1897,7 +1908,7 @@ This command is not allowed.")) if genDH and dhFile: certAndKeyFiles = [dhFile, certFile, keyFile] - foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles) + foundCertFiles = [x for x in certAndKeyFiles if os.path.exists(x)] if not os.path.exists(dhFile): rndFile = "/tmp/%s.rnd" %strData self.execProg("dd if=/dev/urandom of=%s count=1"%rndFile) @@ -1914,23 +1925,23 @@ This command is not allowed.")) return False if os.path.exists(rndFile): os.remove(rndFile) - foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles) + foundCertFiles = [x for x in certAndKeyFiles if os.path.exists(x)] if len(foundCertFiles)==3: return True else: if genDH: keyFile = certFile certAndKeyFiles = [certFile] - foundCertFiles = filter(lambda x: os.path.exists(x),certAndKeyFiles) + foundCertFiles = [x for x in certAndKeyFiles if os.path.exists(x)] if len(foundCertFiles)==1: return True else: certAndKeyFiles = [certFile, keyFile] - foundCertFiles = filter(lambda x: os.path.exists(x), certAndKeyFiles) + foundCertFiles = [x for x in certAndKeyFiles if os.path.exists(x)] if len(foundCertFiles)==2: return True # Удаляем файл сертификата - map(lambda x: os.remove(x), foundCertFiles) + [os.remove(x) for x in foundCertFiles] uidAndGid = self.getUserUidAndGid(userName, groupName) if not uidAndGid: return False @@ -1965,9 +1976,9 @@ nsCertType = %s for fileName in certAndKeyFiles: dirName = os.path.split(fileName)[0] if not os.path.exists(dirName): - self.createUserDir(0, 0, dirName, 0755) + self.createUserDir(0, 0, dirName, 0o755) # Создание конфигурационного файла - self.createUserFile(cnfFile, textCnf, 0, 0, 0600) + self.createUserFile(cnfFile, textCnf, 0, 0, 0o600) # Создание сертификата textLine = self.execProg(\ "%s req -new -x509 -nodes -config %s -days %s -out %s -keyout %s"\ @@ -2058,8 +2069,7 @@ class servUnix(shareLdap): # Алгоритм шифрования пароля для LDAP пользователя userCrypt = "ssha" # Используемые ldif файлы - ldifFileMachine =\ - "/usr/lib/calculate/calculate-server/ldif/samba_machine.ldif" + ldifFileMachine = "/usr/lib/calculate/calculate-server/ldif/samba_machine.ldif" ldifFileUser = "/usr/lib/calculate/calculate-server/ldif/unix_user.ldif" ldifFileGroup = "/usr/lib/calculate/calculate-server/ldif/unix_group.ldif" ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/unix_base.ldif" @@ -2137,7 +2147,7 @@ class servUnix(shareLdap): os.symlink(src,dst) #Изменение прав на ссылки os.lchown(dst, uid, gid) - os.chmod(homeDir, 0700) + os.chmod(homeDir, 0o700) os.chown(homeDir, uid,gid) return True @@ -2217,8 +2227,8 @@ class servUnix(shareLdap): groupErrors.append(groupName) flagError = True continue - userGroupNames[res[0][0][1]['cn'][0]]=\ - res[0][0][1]['gidNumber'][0] + userGroupNames[res[0][0][1]['cn'][0].decode("UTF-8")]=\ + res[0][0][1]['gidNumber'][0].decode("UTF-8") continue gidNumber = gid res = self.searchUnixGid(gidNumber) @@ -2226,7 +2236,8 @@ class servUnix(shareLdap): gidErrors.append(gidNumber) flagError = True continue - userGroupNames[res[0][0][1]['cn'][0]] = res[0][0][1]['gidNumber'][0] + userGroupNames[res[0][0][1]['cn'][0].decode("UTF-8")] =\ + res[0][0][1]['gidNumber'][0].decode("UTF-8") if flagError: errorMessage = "" if groupErrors: @@ -2299,10 +2310,11 @@ class servUnix(shareLdap): return False else: findUsers = [] - if res[0][0][1].has_key('memberUid'): + if 'memberUid' in res[0][0][1]: usersInGroup = res[0][0][1]['memberUid'] for userName in usersNames: - if userName in usersInGroup: + userName_encoded = userName.encode("UTF-8") + if userName_encoded in usersInGroup: findUsers.append(userName) return findUsers @@ -2336,7 +2348,7 @@ class servUnix(shareLdap): return False # Если группа существует выходим без ошибки flagSearchGroups = True - if options.has_key('f'): + if 'f' in options: flagSearchGroups = False if flagSearchGroups and self.searchGroupGroupName(groupName): self.printERROR(\ @@ -2357,7 +2369,7 @@ class servUnix(shareLdap): self.clVars.Set("ur_group",groupName) # номер группы gid = str(self.getMaxGid()) - if options.has_key('g'): + if 'g' in options: gid = options['g'] try: int(gid) @@ -2378,20 +2390,20 @@ class servUnix(shareLdap): self.clVars.Set("ur_group_id", gid) # Коментарий к группе gecos = self.groupGecos - if options.has_key('c'): + if 'c' in options: gecos = options['c'] self.clVars.Set("ur_group_comment",gecos) ldifFile = self.ldifFileGroup groupLdif = self.createLdif(ldifFile) if not groupLdif: - print self.getError() + print(self.getError()) return False if not self.ldapObj.getError(): self.ldapObj.ldapAdd(groupLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False - if options.has_key('p'): + if 'p' in options: sys.stdout.write(gid) else: if printSuccess: @@ -2412,7 +2424,7 @@ class servUnix(shareLdap): return False resSearch = self.servSambaObj.searchSambaGroupName(groupName) if resSearch: - groupId = resSearch[0][0][1]['gidNumber'][0] + groupId = resSearch[0][0][1]['gidNumber'][0].decode("UTF-8") else: gr = self.staticGroups["Domain Computers"] groupId = gr.gid @@ -2438,7 +2450,7 @@ class servUnix(shareLdap): #Добавляем пользователя в LDAP self.ldapObj.ldapAdd(userLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printSUCCESS(_("Added machine")) return True @@ -2461,15 +2473,15 @@ class servUnix(shareLdap): self.clVars.Set("ur_name", userName) baseDir = self.baseDir # Базовая домашняя директория - if options.has_key('b'): + if 'b' in options: baseDir = options['b'] # Устанавливаем скелетную директорию - if options.has_key('k'): + if 'k' in options: skelDir = options['k'] else: skelDir = self.skelDir # Устанавливаем домашнюю директорию - if options.has_key('d'): + if 'd' in options: homeDir = options['d'] else: homeDir = os.path.join(baseDir, userName) @@ -2477,22 +2489,22 @@ class servUnix(shareLdap): fullNameUser = self.fullNameUser # Полное имя пользователя - if options.has_key('c'): + if 'c' in options: fullNameUser = options['c'] self.clVars.Set("ur_fio",fullNameUser) # По умолчанию пользователя не видно visible = '0' - if options.has_key('v'): + if 'v' in options: visible = '1' self.clVars.Set("ur_visible",visible) # Оболочка пользователя userShell = self.userShell - if options.has_key('s'): + if 's' in options: userShell = options['s'] self.clVars.Set("ur_shell", userShell) # id пользователя - if options.has_key('u'): + if 'u' in options: userId = options['u'] try: int(userId) @@ -2511,27 +2523,27 @@ class servUnix(shareLdap): self.clVars.Set("ur_id",userId) # Добавляем пользователя в группы (находим имена групп) - if options.has_key('G'): + if 'G' in options: userGroups = options['G'].split(',') data = self.servSambaObj.searchUnixAndSambaGroups(userGroups, callSamba) - if data and type(data) == types.TupleType: + if data and type(data) == tuple: userGroupNamesUnix, userGroupNamesSamba = data else: return False userGid = str(self.getMaxGid()) # Группа пользователя - if options.has_key('g'): + if 'g' in options: userGid = options['g'] retCondUnix, userGidNamesUnix, errMessUnix =\ self.searchGroupsUnix([userGid], False) - userGidNamesUnix = userGidNamesUnix.keys() + userGidNamesUnix = list(userGidNamesUnix.keys()) userGidNamesSamba = False # В случае вызова из Samba объекта if callSamba: retCondSamba, userGidNamesSamba, errMessSamba =\ self.servSambaObj.searchGroupsSamba([userGid], False) - userGidNamesSamba = userGidNamesSamba.keys() + userGidNamesSamba = list(userGidNamesSamba.keys()) userGidNamesPasswd = self.searchGroupsGroups([userGid], False) if userGidNamesUnix: #Имя группы пользователя @@ -2589,7 +2601,7 @@ class servUnix(shareLdap): # флаги добавления flagAdd = {} # Добавление основной группы пользователя - if options.has_key('g'): + if 'g' in options: resLdap = self.searchUnixGroupName(groupName) if not resLdap and callSamba: resLdap = self.servSambaObj.searchSambaGroupName(groupName) @@ -2601,7 +2613,7 @@ class servUnix(shareLdap): if resGroup: userGid = resGroup.split(":")[2] if resLdap: - userGid = resLdap[0][0][1]['gidNumber'][0] + userGid = resLdap[0][0][1]['gidNumber'][0].decode("UTF-8") else: flagAddGroup = self.addGroupUnixServer(userName,{},False) flagAdd['group'] = flagAddGroup @@ -2617,14 +2629,14 @@ class servUnix(shareLdap): self.ldapObj.ldapAdd(userLdif) #Добавляем пользователя в дополнительные группы (опция G) - if options.has_key('G') and userGroupNamesUnix: + if 'G' in options and userGroupNamesUnix: for group in userGroupNamesUnix: if not self.addUsersGroupUnix([userName], group): flagError = True break # не переделывать на else if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) flagError = True removeHomeBack = False if not flagError: @@ -2647,14 +2659,14 @@ class servUnix(shareLdap): if not flagError and not self.setShadowLastChange(userName): flagError = True # Добавим домашнюю директорию - if not flagError and createDirHome and options.has_key('m'): + if not flagError and createDirHome and 'm' in options: if not os.path.exists(homeDir): if not self.createHomeDir(userName, homeDir, skelDir): self.printERROR (_("ERROR") + ": " +\ _("cannot create HOME dir")) flagError = True #загружаем картинку - if not flagError and options.has_key('i'): + if not flagError and 'i' in options: photoFile = options['i'] if not self.setJpegPhotoUser(userName, photoFile): self.printERROR(_("Can not add jpeg photo for user") + " " +\ @@ -2665,11 +2677,11 @@ class servUnix(shareLdap): self.printERROR (_("Can not add user")+ " " + str(userName)) return False if printSuccess: - if flagAdd.has_key('group'): + if 'group' in flagAdd: self.printSUCCESS(_("Added group in Unix service")) - if createDirHome and options.has_key('m'): + if createDirHome and 'm' in options: self.printSUCCESS(_("Created home dir %s")%homeDir) - if options.has_key('i'): + if 'i' in options: self.printSUCCESS(_("Added jpeg photo %s")% photoFile) self.printSUCCESS(_("Added user in Unix service")) return True @@ -2680,10 +2692,10 @@ class servUnix(shareLdap): if not searchUser: return True modAttrs = [] - if searchUser[0][0][1].has_key('registeredAddress'): - modAttrs.append((ldap.MOD_REPLACE, 'registeredAddress', jabberID)) + if 'registeredAddress' in searchUser[0][0][1]: + modAttrs.append((ldap.MOD_REPLACE, 'registeredAddress', jabberID.encode("UTF-8"))) else: - modAttrs.append((ldap.MOD_ADD, 'registeredAddress', jabberID)) + modAttrs.append((ldap.MOD_ADD, 'registeredAddress', jabberID.encode("UTF-8"))) userDN = self.addDN('uid='+userName,self.relUsersDN) if not self.modAttrsDN(userDN, modAttrs): self.printERROR(_("Can not modify registeredAddress attribute in \ @@ -2698,8 +2710,8 @@ Unix service")) self.printERROR(_("User %s not found in Unix service")\ %str(userName)) return False - if searchUser[0][0][1].has_key('registeredAddress'): - return searchUser[0][0][1]['registeredAddress'][0] + if 'registeredAddress' in searchUser[0][0][1]: + return searchUser[0][0][1]['registeredAddress'][0].decode("UTF-8") else: return "" @@ -2722,10 +2734,10 @@ in Unix service")) %str(userName)) return False modAttrs = [] - if searchUser[0][0][1].has_key('mail'): - modAttrs.append((ldap.MOD_REPLACE, 'mail', mail)) + if 'mail' in searchUser[0][0][1]: + modAttrs.append((ldap.MOD_REPLACE, 'mail', mail.encode("UTF-8"))) else: - modAttrs.append((ldap.MOD_ADD, 'mail', mail)) + modAttrs.append((ldap.MOD_ADD, 'mail', mail.encode("UTF-8"))) userDN = self.addDN('uid='+userName,self.relUsersDN) if not self.modAttrsDN(userDN, modAttrs): self.printERROR(_("Can not modify mail attribute in Unix service")) @@ -2739,8 +2751,8 @@ in Unix service")) self.printERROR(_("User %s not found in Unix service")\ %str(userName)) return False - if searchUser[0][0][1].has_key('mail'): - return searchUser[0][0][1]['mail'][0] + if 'mail' in searchUser[0][0][1]: + return searchUser[0][0][1]['mail'][0].decode("UTF-8") else: return "" @@ -2785,9 +2797,9 @@ service")) addUsers.append(user) modAttrs = [] for userName in addUsers: - modAttrs.append((ldap.MOD_ADD, 'memberUid', userName)) + modAttrs.append((ldap.MOD_ADD, 'memberUid', userName.encode("UTF-8"))) if modAttrs: - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) return True @@ -2809,11 +2821,11 @@ service")) if self.isServiceSetup("samba", False): maxGidSamba = self.servSambaObj.getMaxGidSamba() maxGids.append(maxGidSamba) - maxGid = max(map(lambda x: int(x), maxGids)) + maxGid = max(int(x) for x in maxGids) if maxGid == 0: return self.minGid else: - return maxGid+1 + return maxGid + 1 def getMaxGidGroupSystem(self): """Получаем максимальный добавленный gid из /etc/group @@ -2945,12 +2957,12 @@ service")) self.printERROR (_("ERROR") + ": " +\ _("User %s is not found in Unix service") % str(userName)) return False - if options.has_key('r'): + if 'r' in options: backup = False homeDir = False - if resLdap[0][0][1].has_key('homeDirectory'): + if 'homeDirectory' in resLdap[0][0][1]: #Домашняя директория пользователя - homeDir = resLdap[0][0][1]['homeDirectory'][0] + homeDir = resLdap[0][0][1]['homeDirectory'][0].decode("UTF-8") if backup and os.path.exists(homeDir) and\ os.path.isdir(homeDir) and os.listdir(homeDir): # Делаем сохранение домашней директории @@ -2964,8 +2976,8 @@ service")) # Удаляем пользователя из групп if not self.delUserInGroup(userName): return False - if resLdap[0][0][1].has_key('gidNumber'): - gid = resLdap[0][0][1]['gidNumber'][0] + if 'gidNumber' in resLdap[0][0][1]: + gid = resLdap[0][0][1]['gidNumber'][0].decode("UTF-8") else: resPasswd = self.searchPasswdUser(userName) if resPasswd: @@ -2980,11 +2992,10 @@ service")) if resGroupSamba: # В случае отсутствия других пользователей удаляем # основную группу в Samba сервисе - if not resGroupSamba[0][0][1].has_key('memberUid'): - groupName = resGroupSamba[0][0][1]['cn'][0] + if 'memberUid' not in resGroupSamba[0][0][1]: + groupName = resGroupSamba[0][0][1]['cn'][0].decode("UTF-8") # Находим группы у которых есть аттрибут type - groupsSambaList = filter(\ - lambda x: x[1].type, self.staticGroups.items()) + groupsSambaList = [x for x in self.staticGroups.items() if x[1].type] groupsSamba = {} groupsSamba.update(groupsSambaList) # Группы которые нельзя удалять @@ -2998,8 +3009,8 @@ service")) if resGroup: # В случае отсутствия других пользователей # удаляем основную группу в Unix сервисе - if not resGroup[0][0][1].has_key('memberUid'): - groupName = resGroup[0][0][1]['cn'][0] + if 'memberUid' not in resGroup[0][0][1]: + groupName = resGroup[0][0][1]['cn'][0].decode("UTF-8") if not self.delGroupUnixServer(groupName, {}, False): return False # Удаляем пользователя из ветки Worked в случае репликации @@ -3031,7 +3042,7 @@ service")) _("Group %s is not found in Unix service")%groupName) return False if checkPrimaryGroup: - groupId = res[0][0][1]['gidNumber'][0] + groupId = res[0][0][1]['gidNumber'][0].decode("UTF-8") if self.searchUnixUserPrimGroup(groupId): self.printWARNING(_("cannot remove user's primary group") + ".") return True @@ -3057,11 +3068,11 @@ service")) _("User %s is not found in Unix service")%str(userName)) return False # Новые группы в которые входит пользователь - if options.has_key('G'): + if 'G' in options: userGroups = options['G'].split(',') data = self.servSambaObj.searchUnixAndSambaGroups(userGroups, callSamba) - if data and type(data) == types.TupleType: + if data and type(data) == tuple: userGroupNamesUnix, userGroupNamesSamba = data else: return False @@ -3078,11 +3089,11 @@ service")) if printSuccess: self.printSUCCESS(_("Replaced list of supplementary group")) # Добавляем группы в которые входит пользователь - elif options.has_key('a'): + elif 'a' in options: userGroups = options['a'].split(',') data = self.servSambaObj.searchUnixAndSambaGroups(userGroups, callSamba) - if data and type(data) == types.TupleType: + if data and type(data) == tuple: userGroupNamesUnix, userGroupNamesSamba = data else: return False @@ -3099,18 +3110,18 @@ service")) # Изменяемые аттрибуты пользователя modAttrs = [] # Изменяем первичную группу пользователя - if options.has_key('g'): + if 'g' in options: newFirstGroup = options['g'] # В случае вызова из Samba объекта ищем gid в Unix и Samba if callSamba: retCondUnix, userGroupNames, errMessUnix =\ self.searchGroupsUnix([newFirstGroup],False) - userGroupNames = userGroupNames.keys() + userGroupNames = list(userGroupNames.keys()) if not userGroupNames: retCondSamba ,userGroupNames, errMessSamba =\ self.servSambaObj.searchGroupsSamba([newFirstGroup], False) - userGroupNames = userGroupNames.keys() + userGroupNames = list(userGroupNames.keys()) if not userGroupNames: self.printERROR(\ _("Group %s is not found in Unix and Samba services")%\ @@ -3119,7 +3130,7 @@ service")) else: retCondUnix, userGroupNames, errMessUnix =\ self.searchGroupsUnix([newFirstGroup]) - userGroupNames = userGroupNames.keys() + userGroupNames = list(userGroupNames.keys()) if not retCondUnix: return False groupName = userGroupNames[0] @@ -3134,39 +3145,39 @@ service")) if resGroup: userGid = resGroup.split(":")[2] if resLdap: - userGid = resLdap[0][0][1]['gidNumber'][0] - modAttrs += [(ldap.MOD_REPLACE, 'gidNumber', userGid)] + userGid = resLdap[0][0][1]['gidNumber'][0].decode("UTF-8") + modAttrs += [(ldap.MOD_REPLACE, 'gidNumber', userGid.encode("UTF-8"))] visible = False # пользователя видно - if options.has_key('V'): - visible = '1' + if 'V' in options: + visible = b'1' # пользователя не видно - if options.has_key('I'): - visible = '0' + if 'I' in options: + visible = b'0' if visible: modAttrs += [(ldap.MOD_REPLACE, 'shadowFlag', visible)] # Изменяем домашнюю директорию - if options.has_key('d'): + if 'd' in options: homeDir = options['d'] - modAttrs += [(ldap.MOD_REPLACE, 'homeDirectory', homeDir)] + modAttrs += [(ldap.MOD_REPLACE, 'homeDirectory', homeDir.encode("UTF-8"))] # Включаем пользователя - if options.has_key('U'): - modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "-1")] + if 'U' in options: + modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', b"-1")] # Выключаем пользователя - if options.has_key('L'): - modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "1")] + if 'L' in options: + modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', b"1")] # Изменяем комментарий к пользователю - if options.has_key('c'): + if 'c' in options: comment = options['c'] - if res[0][0][1].has_key('displayName'): - modAttrs += [(ldap.MOD_REPLACE, 'displayName', comment), - (ldap.MOD_REPLACE, 'cn', comment)] + if 'displayName' in res[0][0][1]: + modAttrs += [(ldap.MOD_REPLACE, 'displayName', comment.encode("UTF-8")), + (ldap.MOD_REPLACE, 'cn', comment.encode("UTF-8"))] else: - modAttrs += [(ldap.MOD_REPLACE, 'cn', comment)] + modAttrs += [(ldap.MOD_REPLACE, 'cn', comment.encode("UTF-8"))] # Изменяем оболочку пользователя - if options.has_key('s'): + if 's' in options: shell = options['s'] - modAttrs.append((ldap.MOD_REPLACE, 'loginShell', shell)) + modAttrs.append((ldap.MOD_REPLACE, 'loginShell', shell.encode("UTF-8"))) # Изменяем пароль пользователя userPwd = self.getUserPassword(options, "p", "P") if userPwd == False: @@ -3175,31 +3186,31 @@ service")) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False # Переносим домашнюю директорию пользователя - if options.has_key('d') and options.has_key('m'): - homeDirOld = res[0][0][1]['homeDirectory'][0] + if 'd' in options and 'm' in options: + homeDirOld = res[0][0][1]['homeDirectory'][0].decode("UTF-8") homeDirNew = homeDir textLine = self.execProg("mv %s %s" %(homeDirOld, homeDirNew)) if textLine == False: self.printERROR(_("Can not move home directory")) modAttrs = [(ldap.MOD_REPLACE, 'homeDirectory', - homeDirOld)] + homeDirOld.encode("UTF-8"))] self.modAttrsDN(DN, modAttrs) return False else: if printSuccess: self.printSUCCESS(_("Moved home directory")) - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: # Изменим время последнего измения пароля пользователя if not self.setShadowLastChange(userName): return False @@ -3207,7 +3218,7 @@ service")) self.printSUCCESS(\ _("Modified user password of Unix service")) if printSuccess: - if options.has_key('g'): + if 'g' in options: flagInt = False try: int(newFirstGroup) @@ -3218,20 +3229,20 @@ service")) if flagInt: self.printSUCCESS(_("Modified GID primary group to %s")\ %newFirstGroup) - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified comment")) - if options.has_key('s'): + if 's' in options: self.printSUCCESS(_("Modified shell")) - if options.has_key('d'): + if 'd' in options: self.printSUCCESS(_("Modified home directory")) - if options.has_key('U'): + if 'U' in options: self.printSUCCESS(_("Unlocked user %s")% str(userName)) - if options.has_key('I'): + if 'I' in options: self.printSUCCESS(\ _("User %s is invisible")% str(userName)) - if options.has_key('V'): + if 'V' in options: self.printSUCCESS(_("User %s is visible")% str(userName)) - if options.has_key('L'): + if 'L' in options: self.printSUCCESS(_("Locked user %s")% str(userName)) return True @@ -3248,19 +3259,19 @@ service")) # Изменяемые аттрибуты пользователя modAttrs = [] # Удаляем пароль пользователя - if options.has_key('d'): - if res[0][0][1].has_key('userPassword'): + if 'd' in options: + if 'userPassword' in res[0][0][1]: modAttrs += [(ldap.MOD_DELETE, 'userPassword', None)] else: self.printERROR(\ _("User %s has not password for Unix service")%\ str(userName)) # Включаем пользователя - if options.has_key('u'): - modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "-1")] + if 'u' in options: + modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', b"-1")] # Выключаем пользователя - elif options.has_key('l'): - modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "1")] + elif 'l' in options: + modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', b"1")] if not options: optPasswd = {"p":""} if pwd: @@ -3272,25 +3283,25 @@ service")) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('d'): + if 'd' in options: self.printSUCCESS( _("Deleted password of Unix service for user")+ " " +\ str(userName)) - if options.has_key('l'): + if 'l' in options: self.printSUCCESS(_("Locked user") + " " + str(userName) +\ " " +_("of Unix service")) - if options.has_key('u'): + if 'u' in options: self.printSUCCESS(_("Unlocked user") + " " + str(userName) +\ " " +_("of Unix service")) if not options: @@ -3310,7 +3321,7 @@ service")) self.printERROR(_("group name not found in Unix service")) return False # Добавляем список пользователей в группу - if options.has_key('a'): + if 'a' in options: # добавляемые пользователи в группу users = options['a'].split(',') res = self.addUsersGroupUnix(users, groupName) @@ -3323,7 +3334,7 @@ service")) " " + str(groupName)) return False # Удаляем список пользователей из группы - if options.has_key('d'): + if 'd' in options: # удаляемые пользователи из группы users = options['d'].split(',') res = self.delUsersGroupUnix(users, groupName) @@ -3337,7 +3348,7 @@ service")) return False modGroupName = groupName # Изменяем имя группы - if options.has_key('n'): + if 'n' in options: newGroupName = options['n'] if self.searchUnixGroupName(newGroupName): self.printERROR( @@ -3364,19 +3375,19 @@ service")) return False modAttrs = [] # Изменяем комментарий к группе - if options.has_key('c'): + if 'c' in options: gecos = options['c'] modAttrs.append((ldap.MOD_REPLACE, 'description', gecos)) if modAttrs: groupDN = self.addDN("cn=" + modGroupName, self.relGroupsDN) res = self.modAttrsDN(groupDN, modAttrs) if res: - if options.has_key('c'): + if 'c' in options: if printSuccess: self.printSUCCESS(_("Modified group comment")) return True else: - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Can not modify group comment")) return False @@ -3385,7 +3396,7 @@ service")) def delUserInGroup(self, userName): """Удаление из групп в которые входит пользователь""" userInGroups = self.searchUnixMemberGid(userName) - modAttrs = [(ldap.MOD_DELETE, 'memberUid', userName)] + modAttrs = [(ldap.MOD_DELETE, 'memberUid', userName.encode("UTF-8"))] flagError = False for group in userInGroups: groupName = group[0][1]['cn'][0] @@ -3403,7 +3414,7 @@ service")) """Удаление пользователей из списка из группы Unix""" def getPrimaryUsers(): - gidNumber = res[0][0][1]["gidNumber"][0] + gidNumber = res[0][0][1]["gidNumber"][0].decode("UTF-8") searchUsers = self.searchUnixUserPrimGroup(gidNumber) foundUserNames = [] if searchUsers: @@ -3421,7 +3432,7 @@ service")) if not res : self.printERROR(_("group name is not found in Unix service")) return False - if not res[0][0][1].has_key("memberUid"): + if "memberUid" not in res[0][0][1]: if not getPrimaryUsers(): return False self.printERROR( @@ -3430,7 +3441,8 @@ service")) memberUsers = res[0][0][1]["memberUid"] flagError =False for user in users: - if not user in memberUsers: + user_encoded = user.encode("UTF-8") + if not user_encoded in memberUsers: flagError = True break if flagError: @@ -3442,8 +3454,8 @@ service")) return False modAttrs = [] for userName in users: - modAttrs.append((ldap.MOD_DELETE, 'memberUid', userName)) - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + modAttrs.append((ldap.MOD_DELETE, 'memberUid', userName.encode("UTF-8"))) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) @@ -3454,7 +3466,7 @@ service")) # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): return False - if options.has_key("f"): + if "f" in options: forceOptions = True # В случае если сервер установлен if self.clVars.Get("sr_unix_set") == "on" and\ @@ -3550,7 +3562,7 @@ service")) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printOK(_("Added ldif file") + " ...") # Записываем данные администратора сервиса Unix @@ -3566,8 +3578,8 @@ service")) """Изменим последнюю дату измениня пароля на текущую""" # число дней от 1970 года date = int(time.time()/86400) - modAttrs = [(ldap.MOD_REPLACE, 'shadowLastChange', str(date))] - userDN = self.addDN('uid='+userName,self.relUsersDN) + modAttrs = [(ldap.MOD_REPLACE, 'shadowLastChange', str(date).encode("UTF-8"))] + userDN = self.addDN('uid=' + userName,self.relUsersDN) if not self.modAttrsDN(userDN, modAttrs): self.printERROR(_("Can not modify shadowLastChange attribute")) return False @@ -3621,7 +3633,7 @@ class servMail(shareLdap): if not searchEmailGroup: flagError = True break - userGroupNames.append(searchEmailGroup[0][0][1]['cn'][0]) + userGroupNames.append(searchEmailGroup[0][0][1]['cn'][0].decode("UTF-8")) else: searchNameGroup = self.searchMailGroupToName(userGroup) if not searchNameGroup: @@ -3641,7 +3653,7 @@ class servMail(shareLdap): return False return userGroupNames - def delUserMailServer(self,userName,options,printSuccess=True,backup=True): + def delUserMailServer(self, userName, options, printSuccess=True, backup=True): """Удаляем Mail пользователя""" # Проверим установлен ли сервис Mail if not self.initialChecks("mail"): @@ -3655,7 +3667,7 @@ class servMail(shareLdap): #почтовая директория пользователя mailDir = os.path.join(self.clVars.Get("sr_mail_path"), userName) - if options.has_key('r'): + if 'r' in options: backup = False # Делаем сохранение данных удаляемого пользователя if backup and os.path.exists(mailDir) and os.listdir(mailDir): @@ -3671,8 +3683,8 @@ class servMail(shareLdap): servReplObj = servRepl() if not servReplObj.delReplMailAlias(userName): self.printERROR (_("ERROR") + ": " +\ - _("Cannot delete email alias \ -for user %s in 'Replication/Mail' branch") %str(userName)) + _("Cannot delete email alias \ + for user %s in 'Replication/Mail' branch") %str(userName)) return False # Удаляем пользователя из групп if not self.delUserInGroup(userName): @@ -3715,7 +3727,7 @@ for user %s in 'Replication/Mail' branch") %str(userName)) _("Mail user or email %s are not found in Mail service")%\ str(nameOrMail)) return False - userMail = resSearchUser[0][0][1]['mail'][0] + userMail = resSearchUser[0][0][1]['mail'][0].decode("UTF-8") resSearchGroup = self.searchLdapDN(userMail, self.relGroupsDN, "rfc822member") return (userMail, resSearchGroup) @@ -3727,10 +3739,10 @@ for user %s in 'Replication/Mail' branch") %str(userName)) return False userMail = resSearch[0] userInGroups = resSearch[1] - modAttrs = [(ldap.MOD_DELETE, 'rfc822member', userMail)] + modAttrs = [(ldap.MOD_DELETE, 'rfc822member', userMail.encode("UTF-8"))] flagError = False for group in userInGroups: - groupName = group[0][1]['cn'][0] + groupName = group[0][1]['cn'][0].decode("UTF-8") groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) if not self.modAttrsDN(groupDN, modAttrs): flagError = True @@ -3746,7 +3758,7 @@ for user %s in 'Replication/Mail' branch") %str(userName)) if not res : self.printERROR(_("group name is not found in Mail service")) return False - if not res[0][0][1].has_key("rfc822member"): + if "rfc822member" not in res[0][0][1]: self.printERROR(\ _("Member list of group %s is empty")%str(groupName)) return False @@ -3754,7 +3766,7 @@ for user %s in 'Replication/Mail' branch") %str(userName)) flagError = False memberUsers = {} for mailUser in memberMailUsers: - userName = mailUser.split("@")[0] + userName = mailUser.decode("UTF-8").split("@")[0] memberUsers[userName] = mailUser for user in users: if not user in memberUsers.keys(): @@ -3762,14 +3774,15 @@ for user %s in 'Replication/Mail' branch") %str(userName)) break if flagError: self.printERROR(\ - _("User %s is not found in group")%str(user)+" "+\ + _("User %s is not found in group") % str(user) + " " +\ str(groupName)) return False modAttrs = [] for user in users: mailUser = memberUsers[user] + #mailUser - bytes modAttrs.append((ldap.MOD_DELETE, 'rfc822member', mailUser)) - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) def delGroupMailServer(self, groupName, options): @@ -3782,7 +3795,7 @@ for user %s in 'Replication/Mail' branch") %str(userName)) self.printERROR( _("Group %s is not found in Mail service")%groupName) return False - delDN = self.addDN("cn="+groupName, self.relGroupsDN) + delDN = self.addDN("cn=" + groupName, self.relGroupsDN) res = self.delDN(delDN) if res: # В случае почтовой репликации удаляем алиас в ветке @@ -3794,7 +3807,8 @@ for user %s in 'Replication/Mail' branch") %str(userName)) if not servReplObj.delReplMailAlias(groupName): self.printERROR (_("ERROR") + ": " +\ _("Cannot delete email alias \ -for group %s in 'Replication/Mail' branch") %str(userName)) + for group %s in 'Replication/Mail' branch") \ + % str(groupName)) return False self.printSUCCESS( _("Mail group %s is deleted")%groupName) return True @@ -3808,7 +3822,7 @@ for group %s in 'Replication/Mail' branch") %str(userName)) res = self.searchMailUserToName(userName) if not res: return False - if not res[0][0][1].has_key('mailAlternateAddress'): + if 'mailAlternateAddress' not in res[0][0][1]: return True modAttrs = [(ldap.MOD_DELETE, 'mailAlternateAddress', None)] userDN = self.addDN("uid=" + userName, self.relUsersDN) @@ -3825,13 +3839,13 @@ for group %s in 'Replication/Mail' branch") %str(userName)) if not searchGroup: self.printERROR(_("group name not found in Mail service")) return False - if options.has_key('n') and options.has_key('e'): + if 'n' in options and 'e' in options: self.printERROR(_("Command Line Options '-n' and '-e' are \ -incompatible, use one of the options")) + incompatible, use one of the options")) return False - if options.has_key('hide') and options.has_key('hide-off'): + if 'hide' in options and 'hide-off' in options: self.printERROR(_("Command Line Options '--hide' and '--hide-off' \ -are incompatible, use one of the options")) + are incompatible, use one of the options")) return False attrDelete = [] attrDeleteFirst = [] @@ -3843,21 +3857,21 @@ are incompatible, use one of the options")) # Объект сервис репликации servReplObj = servRepl() filterHosts = [] - if options.has_key('hide'): + if 'hide' in options: filterHosts = options['hide'].split(",") - if searchGroup[0][0][1].has_key('filtersender'): + if 'filtersender' in searchGroup[0][0][1]: attrDeleteFirst.append((ldap.MOD_DELETE, 'filtersender', None)) domain = self.clVars.Get('os_net_domain') # Если необходимо добавляем домен к именам хостов - fHosts = map(lambda x: (not '.' in x and x+"."+domain) or x, - filterHosts) + fHosts = [(not '.' in x and x + "." + domain) or x for x in filterHosts] for host in fHosts: - attrAppend.append((ldap.MOD_ADD, 'filtersender', host)) - if options.has_key('hide-off'): - if searchGroup[0][0][1].has_key('filtersender'): + attrAppend.append((ldap.MOD_ADD, 'filtersender', host.encode("UTF-8"))) + if 'hide-off' in options: + if 'filtersender' in searchGroup[0][0][1]: attrDeleteFirst.append((ldap.MOD_DELETE, 'filtersender', None)) - if options.has_key('e'): + if 'e' in options: altMails = options['e'].split(",") + # в этот раз не трогаем кодировку email = searchGroup[0][0][1]["mail"][0] altEmails = searchGroup[0][0][1]["mailAlternateAddress"] # Удаляем альтернативные адреса, кроме первого @@ -3871,7 +3885,7 @@ are incompatible, use one of the options")) if "@" in altMail: if len(altMail.split("@")) != 2: self.printERROR(_("Incorrect alternate adresses \ -option '-e'")) + option '-e'")) return False mail = altMail else: @@ -3881,21 +3895,23 @@ option '-e'")) (not (mail in altEmails) and len(searchGroupMail) == 1 or\ len(searchGroupMail) != 1)): self.printERROR( - _("Alternate email address %s is found in Mail service")%\ - str(mail)) + _("Alternate email address %s is found in Mail service")%\ + str(mail)) return False if i == 0: attrAppend.append((ldap.MOD_REPLACE, 'mailAlternateAddress', - mail)) + mail.encode("UTF-8"))) else: attrAppend.append((ldap.MOD_ADD, 'mailAlternateAddress', - mail)) + mail.encode("UTF-8"))) i += 1 if servReplObj: if not altMails and filterHosts: - altMails = searchGroup[0][0][1]["mailAlternateAddress"] + altMails = [x.decode("UTF-8") for x in searchGroup[0][0][1]["mailAlternateAddress"]] if altMails: - for mail in altMails: + #NOTE: there used to be a typo: + # for mail in altMails: + for altMail in altMails: if "@" in altMail: mail = altMail else: @@ -3906,30 +3922,32 @@ option '-e'")) flagError = False foundReplUsers = foundReplAlias[0][0][1]['cn'] for foundReplUser in foundReplUsers: - if foundReplUser!=groupName: + foundReplUser_decoded = foundReplUser.decode("UTF-8") + if foundReplUser_decoded != groupName: flagError = True break if flagError: self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser_decoded) return False - if not servReplObj.modReplMailAlias(groupName, altMails, + if not servReplObj.modReplMailAlias(groupName, + altMails, filterHosts): errorMsg = _("Can not set replication mail alias,") +\ - " " + _("for name %s")%groupName + " " +\ - "(%s)"%", ".join(altMails) + " " + _("for name %s") % groupName + " " +\ + "(%s)" % ", ".join(altMails) self.printERROR(errorMsg) return False - if options.has_key('hide-off'): + if 'hide-off' in options: if not servReplObj.deleteHideHosts(groupName): errorMsg = _("Can not delete hide host in mail alias,") +\ - " " + _("for name %s")%groupName + " " + _("for name %s") % groupName self.printERROR(errorMsg) return False # Добавляем список пользователей в группу - if options.has_key('a'): + if 'a' in options: # добавляемые пользователи в группу users = options['a'].split(',') res = self.addUsersGroupMail(users, groupName) @@ -3941,7 +3959,7 @@ mail user or group: %s")%foundReplUser) " " + str(groupName)) return False # Удаляем список пользователей из группы - if options.has_key('d'): + if 'd' in options: # удаляемые пользователи из группы users = options['d'].split(',') res = self.delUsersGroupMail(users, groupName) @@ -3954,7 +3972,7 @@ mail user or group: %s")%foundReplUser) return False # Изменяем имя группы modGroupName = groupName - if options.has_key('n'): + if 'n' in options: newGroupName = options['n'] if self.searchMailGroupToName(newGroupName): self.printERROR( @@ -3964,13 +3982,13 @@ mail user or group: %s")%foundReplUser) # изменяем адрес и альтернативный адрес altEmails = searchGroup[0][0][1]["mailAlternateAddress"] for altEmail in altEmails: - splAltEmail = altEmail.split("@") - grName = splAltEmail[0] + splAltEmail = altEmail.split(b"@") + grName = splAltEmail[0].decode("UTF-8") if groupName == grName: - altEmailDomen = "" + altEmailDomen = b"" if len(splAltEmail)==2: altEmailDomen = splAltEmail[1] - newAltEmail = "%s@%s" %(newGroupName,altEmailDomen) + newAltEmail = b"%s@%s" %(newGroupName.encode("UTF-8"), altEmailDomen) attrDelete.append( (ldap.MOD_DELETE, 'mailAlternateAddress', altEmail)) @@ -3978,15 +3996,17 @@ mail user or group: %s")%foundReplUser) (ldap.MOD_ADD, 'mailAlternateAddress', newAltEmail)) break + #no decoding on purpose email = searchGroup[0][0][1]["mail"][0] - splEmail = email.split("@") - emailDomen = "" + splEmail = email.split(b"@") + emailDomen = b"" if len(splEmail)==2: emailDomen = splEmail[1] - newEmail = "%s@%s" %(newGroupName,emailDomen) + newGroupName_encoded = newGroupName.encode("UTF-8") + newEmail = b"%s@%s" %(newGroupName_encoded, emailDomen) attrAppend.append((ldap.MOD_REPLACE, 'mail', newEmail)) attrAppend.append((ldap.MOD_REPLACE, 'mailMessageStore', - newGroupName + "/")) + newGroupName_encoded + b"/")) newFirstDn = "cn=" + newGroupName oldDN = self.addDN("cn=" + groupName, self.relGroupsDN) @@ -3995,7 +4015,7 @@ mail user or group: %s")%foundReplUser) if servReplObj: if not servReplObj.renameReplMailAlias(groupName, newGroupName): self.printERROR(_("Failed modify name '%s' mail alias \ -in 'Replication/Mail' branch") %groupName) + in 'Replication/Mail' branch") %groupName) return False if res: self.printSUCCESS(_("Group renamed to %s")\ @@ -4006,11 +4026,11 @@ in 'Replication/Mail' branch") %groupName) return False modAttrs = attrDeleteFirst + attrAppend + attrDelete # Изменяем комментарий к группе - if options.has_key('c'): + if 'c' in options: gecos = options['c'] - modAttrs.append((ldap.MOD_REPLACE, 'description', gecos)) + modAttrs.append((ldap.MOD_REPLACE, 'description', gecos.encode("UTF-8"))) if not modAttrs: - if options.has_key('hide-off'): + if 'hide-off' in options: self.printWARNING(\ _("Hide mail hosts have already been deleted")) return True @@ -4018,23 +4038,23 @@ in 'Replication/Mail' branch") %groupName) groupDN = self.addDN("cn=" + modGroupName, self.relGroupsDN) res = self.modAttrsDN(groupDN, modAttrs) if res: - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified group comment")) - if options.has_key('e'): + if 'e' in options: self.printSUCCESS(_("Modified mail alternate address")) - if options.has_key('hide'): + if 'hide' in options: self.printSUCCESS(_("Modified hide mail hosts")) - if options.has_key('hide-off'): + if 'hide-off' in options: self.printSUCCESS(_("Deleted hide mail hosts")) return True else: - if options.has_key('c'): + if 'c' in options: self.printERROR(_("Can not modify group comment")) - if options.has_key('e'): + if 'e' in options: self.printERROR(_("Can not modify mail alternate address")) - if options.has_key('hide'): + if 'hide' in options: self.printERROR(_("Can not modify hide mail hosts")) - if options.has_key('hide-off'): + if 'hide-off' in options: self.printERROR(_("Can not delete hide mail hosts")) return False return True @@ -4052,7 +4072,7 @@ in 'Replication/Mail' branch") %groupName) str(userName)) return False # Новые группы в которые входит пользователь - if options.has_key('G'): + if 'G' in options: userGroups = options['G'].split(',') #список имен добавляемых групп userGroupNames = self.searchGroupsMail(userGroups) @@ -4070,7 +4090,7 @@ in 'Replication/Mail' branch") %groupName) return False self.printSUCCESS(_("Replaced list of supplementary group")) # Добавляем группы в которые входит пользователь - elif options.has_key('a'): + elif 'a' in options: userGroups = options['a'].split(',') #список имен добавляемых групп userGroupNames = self.searchGroupsMail(userGroups) @@ -4087,15 +4107,15 @@ in 'Replication/Mail' branch") %groupName) # Изменяемые аттрибуты пользователя modAttrs = [] # Включаем пользователя - if options.has_key('U'): - modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "active")] + if 'U' in options: + modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', b"active")] # Выключаем пользователя - elif options.has_key('L'): - modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "passive")] + elif 'L' in options: + modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', b"passive")] # Изменяем комментарий к пользователю - if options.has_key('c'): - comment = options['c'] + if 'c' in options: + comment = options['c'].encode("UTF-8") modAttrs += [(ldap.MOD_REPLACE, 'sn', comment), (ldap.MOD_REPLACE, 'cn', comment)] # Изменяем пароль пользователя @@ -4106,89 +4126,92 @@ in 'Replication/Mail' branch") %groupName) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) # Заменяем альтернативные почтовые адреса # Первичный почтовый адрес primaryMail = "" altMails = [] - if options.has_key('e'): + if 'e' in options: altEmails = res[0][0][1]["mailAlternateAddress"] altMails = options['e'].split(",") for altMail in altMails: if "@" in altMail: if len(altMail.split("@")) != 2: self.printERROR(_("Incorrect alternate adresses \ -option '-e'")) + option '-e'")) return False mail = altMail else: - mail = "%s@%s" %(altMail,self.clVars.Get("sr_mail_host")) + mail = "%s@%s" %(altMail, self.clVars.Get("sr_mail_host")) if not primaryMail: primaryMail = mail searchUserMail = self.searchUserToMail(mail) if self.searchGroupToMail(mail) or (searchUserMail and\ - (not (mail in altEmails) and len(searchUserMail) == 1 or\ - len(searchUserMail) != 1)): + (mail.encode("UTF-8" not in altEmails) and len(searchUserMail) == 1 or\ + len(searchUserMail) != 1)): self.printERROR( _("Alternate email address %s is found in Mail service")%\ str(mail)) return False - modAttrs.append((ldap.MOD_ADD, 'mailAlternateAddress', mail)) + modAttrs.append((ldap.MOD_ADD, 'mailAlternateAddress', mail.encode("UTF-8"))) # Удаляем предыдущие адреса self.delAlternateAddress(userName) # Изменяем основной почтовый адрес if primaryMail: if not self.servUnixObj.setUserMail(userName, primaryMail): self.printERROR(_("Failed set primary email for user %s \ -in Unix service") %str(primaryMail)) + in Unix service") % str(primaryMail)) return False # Если включена репликация почты if self.clVars.Get("ld_repl_mail_set") == "on": # Объект сервис репликации servReplObj = servRepl() if altMails: - for mail in altMails: - if "@" in altMail: - mail = altMail + #NOTE: there used to be a typo + # for mail in altMails: + for altMail in altMails: + if b"@" in altMail: + mail = altMail.decode("UTF-8") else: - mail = "%s@%s" %(altMail,\ + mail = "%s@%s" %(altMail.decode("UTF-8"),\ self.clVars.Get("sr_mail_host")) foundReplAlias = servReplObj.searchMailAddress(mail) if foundReplAlias: flagError = False foundReplUsers = foundReplAlias[0][0][1]['cn'] for foundReplUser in foundReplUsers: - if foundReplUser!=userName: + foundReplUser_decoded = foundReplUser.decode("UTF-8") + if foundReplUser_decoded != userName: flagError = True break if flagError: self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser_decoded) return False if not servReplObj.modReplMailAlias(userName, altMails): self.printERROR(_("Failed modify mail aliases \ -for user %s in 'Replication/Mail' branch") %userName) + for user %s in 'Replication/Mail' branch") % userName) return False if modAttrs: - DN = self.addDN("uid="+userName, self.relUsersDN) + DN = self.addDN("uid=" + userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified comment")) - if options.has_key('L'): - self.printSUCCESS(_("Locked Mail user %s")%str(userName)) - if options.has_key('U'): - self.printSUCCESS(_("Unlocked Mail user %s")%str(userName)) - if options.has_key('e'): + if 'L' in options: + self.printSUCCESS(_("Locked Mail user %s") % str(userName)) + if 'U' in options: + self.printSUCCESS(_("Unlocked Mail user %s") % str(userName)) + if 'e' in options: self.printSUCCESS(_("Modified Mail alternate addresses")) - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: self.printSUCCESS(_("Modified Mail user password")) return True @@ -4205,84 +4228,84 @@ for user %s in 'Replication/Mail' branch") %userName) servReplObj = servRepl() if servReplObj.searchMailAlias(groupName): self.printERROR(_("Mail group %s is found in \ -'Replication/Mail' branch")%groupName) + 'Replication/Mail' branch") % groupName) return False #Проверяем альтернативные почтовые адреса modAttrs = [] altMails = [] - if options.has_key('e'): + if 'e' in options: altMails = options['e'].split(",") for altMail in altMails: if "@" in altMail: if len(altMail.split("@")) != 2: self.printERROR(_("Incorrect alternate adresses \ -option '-e'")) + option '-e'")) return False mail = altMail else: - mail = "%s@%s" %(altMail,self.clVars.Get("sr_mail_host")) + mail = "%s@%s" % (altMail, self.clVars.Get("sr_mail_host")) if self.searchUserToMail(mail) or\ self.searchGroupToMail(mail): self.printERROR( - _("Alternate email address %s is found in Mail service")%\ - str(mail)) + _("Alternate email address %s is found in Mail service")%\ + str(mail)) return False if servReplObj: foundReplAlias = servReplObj.searchMailAddress(mail) if foundReplAlias: - foundReplUser = foundReplAlias[0][0][1]['cn'][0] + foundReplUser = foundReplAlias[0][0][1]['cn'][0].decode("UTF-8") self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser) return False - modAttrs.append('mailAlternateAddress: %s' %mail) + modAttrs.append('mailAlternateAddress: %s' % mail) # Фильтр почты (hostname) fHostNames = [] - if options.has_key('hide'): + if 'hide' in options: fHostNames = options['hide'].split(",") for fHostName in fHostNames: if not "." in fHostName: - fHostName = "%s.%s" %(fHostName, - self.clVars.Get('os_net_domain')) - modAttrs.append('filtersender: %s' %fHostName) + fHostName = "%s.%s" % (fHostName, + self.clVars.Get('os_net_domain')) + modAttrs.append('filtersender: %s' % fHostName) if self.searchMailGroupToName(groupName): self.printERROR( - _("group name %s is found in Mail service")%\ + _("group name %s is found in Mail service")%\ str(groupName)) return False - mail = "%s@%s" %(groupName,self.clVars.Get("sr_mail_host")) + mail = "%s@%s" %(groupName, self.clVars.Get("sr_mail_host")) if self.searchUserToMail(mail) or\ self.searchGroupToMail(mail): self.printERROR( - _("Email address %s is found in Mail service")%\ + _("Email address %s is found in Mail service")%\ str(mail)) return False if servReplObj: foundReplAlias = servReplObj.searchMailAddress(mail) if foundReplAlias: - foundReplUser = foundReplAlias[0][0][1]['cn'][0] + foundReplUser = foundReplAlias[0][0][1]['cn'][0].decode("UTF-8") self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser) return False self.clVars.Set("ur_group", groupName) # Комментарий к группе groupGecos = self.servUnixObj.groupGecos - if options.has_key('c'): + if 'c' in options: groupGecos = options['c'] - self.clVars.Set("ur_group_comment",groupGecos) + self.clVars.Set("ur_group_comment", groupGecos) ldifFile = self.ldifFileGroup groupRawLdif = self.createLdif(ldifFile) if not groupRawLdif: - print self.getError() + print(self.getError()) return False groupLdif = groupRawLdif.rstrip() + "\n" + "\n".join(modAttrs) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(groupLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False if servReplObj: # Записываем почтовые алиасы в ветку @@ -4291,7 +4314,7 @@ mail user or group: %s")%foundReplUser) altMails, fHostNames): self.printERROR(_("Failed set mail aliases \ -for user %s in 'Replication/Mail' branch") %str(primaryMail)) +for user %s in 'Replication/Mail' branch") %str(mail)) return False self.printSUCCESS(_("Added group '%s' in Mail service")\ %groupName) @@ -4311,11 +4334,11 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) # Изменяемые аттрибуты пользователя modAttrs = [] # Включаем пользователя - if options.has_key('u'): - modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "active")] + if 'u' in options: + modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', b"active")] # Выключаем пользователя - elif options.has_key('l'): - modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "passive")] + elif 'l' in options: + modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', b"passive")] if not options: optPasswd = {"p":""} userPwd = self.getUserPassword(optPasswd, "p", False) @@ -4324,20 +4347,20 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: - DN = self.addDN("uid="+userName, self.relUsersDN) + DN = self.addDN("uid=" + userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('l'): - self.printSUCCESS(_("Locked Mail user %s")% str(userName)) - if options.has_key('u'): - self.printSUCCESS(_("Unlocked Mail user %s")% str(userName)) + if 'l' in options: + self.printSUCCESS(_("Locked Mail user %s") % str(userName)) + if 'u' in options: + self.printSUCCESS(_("Unlocked Mail user %s") % str(userName)) if not options: self.printSUCCESS(_("Changed Mail user password")) return True @@ -4355,12 +4378,12 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) return False else: findUsers = [] - if res[0][0][1].has_key('rfc822member'): + if 'rfc822member' in res[0][0][1]: usersInGroup = res[0][0][1]['rfc822member'] for userName in usersNames: userMail = "%s@%s" %(userName, self.clVars.Get("sr_mail_host")) - if userMail in usersInGroup: + if userMail.encode("UTF-8") in usersInGroup: findUsers.append(userName) return findUsers @@ -4443,7 +4466,7 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) for userName in users: if not self.searchMailUserToName(userName): self.printERROR( - _("User %s is not found in Mail service")%\ + _("User %s is not found in Mail service")%\ str(userName)) flagFalse = True break @@ -4459,10 +4482,10 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) addUsers.append(user) modAttrs = [] for userName in addUsers: - userMail = "%s@%s" %(userName,self.clVars.Get("sr_mail_host")) - modAttrs.append((ldap.MOD_ADD, 'rfc822member', userMail)) + userMail = "%s@%s" % (userName, self.clVars.Get("sr_mail_host")) + modAttrs.append((ldap.MOD_ADD, 'rfc822member', userMail.encode("UTF-8"))) if modAttrs: - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) return True @@ -4492,65 +4515,65 @@ for user %s in 'Replication/Mail' branch") %str(primaryMail)) servReplObj = servRepl() if servReplObj.searchMailAlias(userName): self.printERROR(_("Mail user %s is found in \ -'Replication/Mail' branch")%userName) + 'Replication/Mail' branch") % userName) return False #Проверяем альтернативные почтовые адреса modAttrs = [] primaryMail = "" altMails = [] - if options.has_key('e'): + if 'e' in options: altMails = options['e'].split(",") for altMail in altMails: if "@" in altMail: if len(altMail.split("@")) != 2: self.printERROR(_("Incorrect alternate adresses option \ -'-e'")) + '-e'")) return False mail = altMail else: - mail = "%s@%s" %(altMail,self.clVars.Get("sr_mail_host")) + mail = "%s@%s" %(altMail, self.clVars.Get("sr_mail_host")) if not primaryMail: primaryMail = mail if self.searchUserToMail(mail) or\ self.searchGroupToMail(mail): self.printERROR(\ - _("Alternate email address %s is found in Mail service")%\ - str(mail)) + _("Alternate email address %s is found in Mail service")%\ + str(mail)) return False if servReplObj: foundReplAlias = servReplObj.searchMailAddress(mail) if foundReplAlias: - foundReplUser = foundReplAlias[0][0][1]['cn'][0] + foundReplUser = foundReplAlias[0][0][1]['cn'][0].decode("UTF-8") self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser) return False - modAttrs.append("mailAlternateAddress: %s" %mail) + modAttrs.append("mailAlternateAddress: %s" % mail) else: self.printERROR(\ - _("Must be added one or more alternative addresses")) + _("Must be added one or more alternative addresses")) self.printWARNING("cl-useradd -e gst@calculate.org guest mail") return False if self.searchMailUserToName(userName): self.printERROR(_("User exists in Mail service")) return False else: - mail = "%s@%s" %(userName,self.clVars.Get("sr_mail_host")) + mail = "%s@%s" %(userName, self.clVars.Get("sr_mail_host")) if self.searchUserToMail(mail) or\ self.searchGroupToMail(mail): self.printERROR( - _("Email address %s is found in Mail service")%\ - str(mail)) + _("Email address %s is found in Mail service")%\ + str(mail)) return False if servReplObj: foundReplAlias = servReplObj.searchMailAddress(mail) if foundReplAlias: - foundReplUser = foundReplAlias[0][0][1]['cn'][0] + foundReplUser = foundReplAlias[0][0][1]['cn'][0].decode("UTF-8") self.printERROR(_("Mail address %s is found in \ -'Replication/Mail' branch")%mail) + 'Replication/Mail' branch") % mail) self.printERROR(_("The address belongs to \ -mail user or group: %s")%foundReplUser) + mail user or group: %s") % foundReplUser) return False # Почтовая директория пользователя mailDir = os.path.join(self.clVars.Get("sr_mail_path"), userName) @@ -4572,7 +4595,7 @@ mail user or group: %s")%foundReplUser) # Флаг создания группы по умолчанию flagCreateUnixGroup = False # Группа пользователя - if options.has_key('g'): + if 'g' in options: optUnix['g'] = options['g'] else: optUnix['g'] = self.defaultUnixGroup["name"] @@ -4588,7 +4611,7 @@ mail user or group: %s")%foundReplUser) if not self.servUnixObj.searchUnixGroupName(optUnix['g']): flagCreateUnixGroup = True # Полное имя пользователя - if options.has_key('c'): + if 'c' in options: optUnix['c'] = options['c'] # Если нужно создаем новую Unix группу if flagCreateUnixGroup: @@ -4609,12 +4632,12 @@ mail user or group: %s")%foundReplUser) self.clVars.Set("ur_name", userName) #Полное имя пользователя fullNameUser = self.servUnixObj.fullNameUser - if options.has_key('c'): + if 'c' in options: fullNameUser = options['c'] else: - if resUnix and resUnix[0][0][1].has_key('cn'): - fullNameUser = resUnix[0][0][1]['cn'][0] - self.clVars.Set("ur_fio",fullNameUser) + if resUnix and 'cn' in resUnix[0][0][1]: + fullNameUser = resUnix[0][0][1]['cn'][0].decode("UTF-8") + self.clVars.Set("ur_fio", fullNameUser) if not userPwd: userPwdHash = "crypt{xxx}" else: @@ -4623,11 +4646,11 @@ mail user or group: %s")%foundReplUser) if flagCreateUnixUser: self.servUnixObj.delUserUnixServer(userName, {}, False, False) return False - self.clVars.Set("ur_hash",userPwdHash) + self.clVars.Set("ur_hash", userPwdHash) ldifFile = self.ldifFileUser userRawLdif = self.createLdif(ldifFile) if not userRawLdif: - print self.getError() + print(self.getError()) if flagCreateUnixUser: self.servUnixObj.delUserUnixServer(userName, {}, False, False) return False @@ -4639,7 +4662,7 @@ mail user or group: %s")%foundReplUser) # не переделывать на else flagError = False if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) flagError = True if not flagError: if resUnix: @@ -4654,7 +4677,7 @@ mail user or group: %s")%foundReplUser) if not flagError: # Востановим удаленного пользователя message = _("Do you want to restore deleted user %s data?")\ - %userName + "\n" + "'yes', 'no'" + % userName + "\n" + "'yes', 'no'" resMailDir = self.restorePathDelUser(userName, mailDir, "mail", message) removeMailDirBack = False @@ -4672,14 +4695,14 @@ mail user or group: %s")%foundReplUser) # Записываем основной почтовый адрес в ветку Unix if not self.servUnixObj.setUserMail(userName, primaryMail): self.printERROR(_("Failed set primary email for user %s in \ -Unix service") %str(primaryMail)) + Unix service") %str(primaryMail)) flagError = True # Записываем почтовые алиасы в ветку # репликации Replication/Mail if not flagError and servReplObj: if not servReplObj.addReplMailAlias(userName, altMails): self.printERROR(_("Failed set mail aliases \ -for user %s in 'Replication/Mail' branch") %userName) + for user %s in 'Replication/Mail' branch") %userName) flagError = True if not flagError and removeMailDirBack\ and os.path.exists(removeMailDirBack): @@ -4701,8 +4724,8 @@ for user %s in 'Replication/Mail' branch") %userName) self.clVars должен быть определен """ - print _("Enter the allowed ip addresses and network for %s service")\ - %"Mail" + " (" + _("comma or space delimited") + ")" + print(_("Enter the allowed ip addresses and network for %s service")\ + %"Mail" + " (" + _("comma or space delimited") + ")") strPrompt = _("allow networks: ") netAllow = self.clVars.Get("sr_mail_net_allow") strNetAllow = "" @@ -4734,10 +4757,10 @@ for user %s in 'Replication/Mail' branch") %userName) return False def printW(): - print _("Incorrect string hostname") - print _("Try again\n") + print(_("Incorrect string hostname")) + print(_("Try again\n")) - print _("Enter the hostname for %s service")%"Mail" + print(_("Enter the hostname for %s service")%"Mail") strPrompt = _("hostname: ") hostname = self.clVars.Get("sr_mail_host") hostname = self.raw_input(strPrompt, hostname) @@ -4749,7 +4772,7 @@ for user %s in 'Replication/Mail' branch") %userName) if i == 3 and not correctHostname(hostname): printW() self.printERROR(_("You used four attempts, \ -if you want to continue to run the program again")) + if you want to continue to run the program again")) return False # Установка имени хоста fullHostName = correctHostname(hostname) @@ -4779,7 +4802,7 @@ if you want to continue to run the program again")) """Начальная настройка Mail сервиса""" # Принудительная установка forceOptions = False - if options.has_key("f"): + if "f" in options: forceOptions = True # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): @@ -4811,13 +4834,13 @@ if you want to continue to run the program again")) _("input 'yes'") +", "+ _("if not 'no'") if not self.dialogYesNo(messDialog): return True - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: return False else: - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: @@ -4867,7 +4890,7 @@ if you want to continue to run the program again")) # Почтовый ност fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'), self.clVars.Get('os_net_domain')) - if options.has_key("host"): + if "host" in options: fullHostName = options['host'] if not "." in fullHostName: fullHostName = "%s.%s" %(fullHostName, @@ -4875,7 +4898,7 @@ if you want to continue to run the program again")) self.clVars.Set("sr_mail_host",fullHostName,True) history,history_domain,history_path = self.getMailHistoryData(options) mailType = "imap" - if options.has_key("t"): + if "t" in options: mailType = options['t'] if mailType: if not set(mailType.split(",")) <= set(["imap","pop3"]): @@ -4889,7 +4912,7 @@ if you want to continue to run the program again")) return False self.clVars.Set("sr_mail_type", mailType) mailCrypt = "tls" - if options.has_key("c"): + if "c" in options: mailCrypt = options['c'] if not mailCrypt in ["none", "tls"]: self.printERROR(_("Мail encryption not 'none' or 'tls'")) @@ -4933,7 +4956,7 @@ if you want to continue to run the program again")) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Записываем данные администратора сервиса Mail ldapParser = iniLdapParser() @@ -5090,13 +5113,13 @@ class servJabber(shareLdap): str(userName)) return False modAttrs = [] - descr = groupSearch[0][0][1]["cn"][0] - uid = userSearch[0][0][1]["uid"][0] - if userSearch[0][0][1].has_key('departmentNumber'): - modAttrs.append((ldap.MOD_REPLACE, 'departmentNumber', descr)) + descr = groupSearch[0][0][1]["cn"][0].decode("UTF-8") + uid = userSearch[0][0][1]["uid"][0].decode("UTF-8") + if 'departmentNumber' in userSearch[0][0][1]: + modAttrs.append((ldap.MOD_REPLACE, 'departmentNumber', descr.encode("UTF-8"))) else: - modAttrs.append((ldap.MOD_ADD, 'departmentNumber', descr)) - userDN = self.addDN("uid="+uid, self.relUsersDN) + modAttrs.append((ldap.MOD_ADD, 'departmentNumber', descr.encode("UTF-8"))) + userDN = self.addDN("uid=" + uid, self.relUsersDN) return self.modAttrsDN(userDN, modAttrs) def renameJabberId(self, userName, newJabberId): @@ -5107,11 +5130,11 @@ class servJabber(shareLdap): str(userName)) return False modAttrs = [] - if searchUser[0][0][1].has_key('mail'): - modAttrs.append((ldap.MOD_REPLACE, 'mail', newJabberId)) + if 'mail' in searchUser[0][0][1]: + modAttrs.append((ldap.MOD_REPLACE, 'mail', newJabberId.encode("UTF-8"))) else: - modAttrs.append((ldap.MOD_ADD, 'mail', newJabberId)) - userDN = self.addDN("uid="+userName, self.relUsersDN) + modAttrs.append((ldap.MOD_ADD, 'mail', newJabberId.encode("UTF-8"))) + userDN = self.addDN("uid=" + userName, self.relUsersDN) return self.modAttrsDN(userDN, modAttrs) @adminConnectLdap @@ -5151,7 +5174,7 @@ in Jabber service")) flagFalse = True break if not replaceFlag and\ - userSearch[0][0][1].has_key('departmentNumber'): + 'departmentNumber' in userSearch[0][0][1]: self.printERROR(_("User %s is found in group")%\ str(userName) + " " + str(groupName)) flagFalse = True @@ -5176,7 +5199,7 @@ in Jabber service")) res = True for userName in users: userSearch = self.searchUserToNameOrId(userName) - if userSearch and userSearch[0][0][1].has_key('departmentNumber'): + if userSearch and 'departmentNumber' in userSearch[0][0][1]: if not userSearch[0][0][1]['departmentNumber'][0] == \ groupSearch[0][0][1]['cn'][0]: self.printERROR(_("User %s is not found in group")%\ @@ -5192,9 +5215,9 @@ in Jabber service")) return False for userName in users: userSearch = self.searchUserToNameOrId(userName) - uid = userSearch[0][0][1]['uid'][0] + uid = userSearch[0][0][1]['uid'][0].decode("UTF-8") modAttrs = [(ldap.MOD_DELETE, 'departmentNumber', None)] - userDN = self.addDN("uid="+uid, self.relUsersDN) + userDN = self.addDN("uid=" + uid, self.relUsersDN) res = self.modAttrsDN(userDN, modAttrs) if not res: break @@ -5219,6 +5242,7 @@ in Jabber service")) for data in searchUsers: uid = data[0][1]['uid'][0] userDN = self.addDN("uid="+uid, self.relUsersDN) + # newName is a number? modAttrs = [(ldap.MOD_REPLACE, 'departmentNumber', newName)] @@ -5247,31 +5271,32 @@ in Jabber service")) # Изменяемые аттрибуты пользователя modAttrs = [] # Включаем пользователя - if options.has_key('u'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "Yes")] + if 'u' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"Yes")] # Выключаем пользователя - elif options.has_key('l'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "No")] + elif 'l' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"No")] if not options: optPasswd = {"p":""} userPwd = self.getUserPassword(optPasswd, "p", False) if userPwd == False: return False userPwdHash = userPwd - if resSearch[0][0][1].has_key('userPassword'): + if 'userPassword' in resSearch[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: - uid = resSearch[0][0][1]['uid'][0] - DN = self.addDN("uid="+userName, self.relUsersDN) + uid = resSearch[0][0][1]['uid'][0].decode("UTF-8") + #NOTE: userName used instead of uid? bug? + DN = self.addDN("uid=" + userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('l'): + if 'l' in options: self.printSUCCESS(_("Locked Jabber user %s")% str(userName)) - if options.has_key('u'): + if 'u' in options: self.printSUCCESS(_("Unlocked Jabber user %s")%\ str(userName)) if not options: @@ -5294,7 +5319,7 @@ in Jabber service")) modAttrs = [] # Изменяем Jabber ID jabber_hosts = self.get_jabber_hosts() - if options.has_key('j'): + if 'j' in options: # Изменяем JID jabberId = options['j'] if not "@" in jabberId: @@ -5309,7 +5334,7 @@ in Jabber service")) return False searchUser = self.searchUserToId(jabberId) if searchUser: - foundUserName = searchUser[0][0][1]['uid'][0] + foundUserName = searchUser[0][0][1]['uid'][0].decode("UTF-8") if foundUserName != userName: self.printERROR(_("User %s") %str(foundUserName) + " " +\ _("has a JID %s") %jabberId) @@ -5320,13 +5345,13 @@ in Jabber service")) self.printERROR(_("Failed set jabberID for user %s \ in Unix service") %str(jabberId)) return False - if res[0][0][1].has_key('mail'): - modAttrs.append((ldap.MOD_REPLACE, 'mail', jabberId)) + if 'mail' in res[0][0][1]: + modAttrs.append((ldap.MOD_REPLACE, 'mail', jabberId.encode("UTF-8"))) else: - modAttrs.append((ldap.MOD_ADD, 'mail', jabberId)) - modAttrs.append((ldap.MOD_REPLACE,'cn',jabberId.partition("@")[0])) + modAttrs.append((ldap.MOD_ADD, 'mail', jabberId.encode("UTF-8"))) + modAttrs.append((ldap.MOD_REPLACE,'cn', jabberId.partition("@")[0].encode("UTF-8"))) # Изменяет группу в которую входит пользователь - if options.has_key('g'): + if 'g' in options: userGroup = options['g'] if self.setUserGroup(userName, userGroup, res): self.printSUCCESS(_("Replaced user group")) @@ -5334,53 +5359,53 @@ in Unix service") %str(jabberId)) self.printERROR(_("Not replaced user group")) return False #загружаем картинку - if options.has_key('i'): + if 'i' in options: photoFile = options['i'] if not self.setJpegPhotoUser(userName, photoFile): self.printERROR(_("Can not add jpeg photo for user") + " " +\ str(userName)) return False # Включаем пользователя - if options.has_key('U'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "Yes")] + if 'U' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"Yes")] # Выключаем пользователя - elif options.has_key('L'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "No")] + elif 'L' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"No")] # Изменяем комментарий к пользователю - if options.has_key('c'): + if 'c' in options: comment = options['c'] - modAttrs += [(ldap.MOD_REPLACE, 'sn', comment)] + modAttrs += [(ldap.MOD_REPLACE, 'sn', comment.encode("UTF-8"))] # Изменяем пароль пользователя userPwd = self.getUserPassword(options, "p", "P") if userPwd == False: return False if userPwd: userPwdHash = userPwd - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: - uid = res[0][0][1]['uid'][0] - DN = self.addDN("uid="+uid, self.relUsersDN) + uid = res[0][0][1]['uid'][0].decode("UTF-8") + DN = self.addDN("uid=" + uid, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False if printSuccess: - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified comment (full name)")) - if options.has_key('L'): + if 'L' in options: self.printSUCCESS(_("Locked Jabber user %s")%str(userName)) - if options.has_key('U'): + if 'U' in options: self.printSUCCESS(_("Unlocked Jabber user %s")\ %str(userName)) - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: self.printSUCCESS(_("Modified Jabber user password")) - if options.has_key('j'): + if 'j' in options: self.printSUCCESS(_("JID changed, a new JID is %s")\ %jabberId) - if printSuccess and options.has_key('i'): + if printSuccess and 'i' in options: self.printSUCCESS(_("Set image %s for Jabber user")%\ str(options['i']) + " " + str(userName)) return True @@ -5396,7 +5421,7 @@ in Unix service") %str(jabberId)) %str(groupName)) return False # Добавляем список пользователей в группу - if options.has_key('a'): + if 'a' in options: # добавляемые пользователи в группу users = options['a'].split(',') res = self.addUsersGroupJabber(users, groupName) @@ -5408,7 +5433,7 @@ in Unix service") %str(jabberId)) " " + str(groupName)) return False # Удаляем список пользователей из группы - if options.has_key('d'): + if 'd' in options: # удаляемые пользователи из группы users = options['d'].split(',') res = self.delUsersGroupJabber(users, groupName) @@ -5420,9 +5445,9 @@ in Unix service") %str(jabberId)) " " + str(groupName)) return False # Изменяем комментарий к группе - if options.has_key('c'): + if 'c' in options: gecos = options['c'] - modAttrs = [(ldap.MOD_REPLACE, 'description', gecos)] + modAttrs = [(ldap.MOD_REPLACE, 'description', gecos.encode("UTF-8"))] groupDN = self.addDN("cn="+groupName, self.relGroupsDN) if self.modAttrsDN(groupDN, modAttrs): self.printSUCCESS(_("Modified group comment")) @@ -5431,9 +5456,9 @@ in Unix service") %str(jabberId)) " " + str(groupName)) return False # Изменяем имя группы - if options.has_key('n'): + if 'n' in options: newGroupName = options['n'] - oldGroupName = searchGroup[0][0][1]["cn"][0] + oldGroupName = searchGroup[0][0][1]["cn"][0].decode("UTF-8") if self.renameGroup(oldGroupName, newGroupName): self.printSUCCESS(_("Group renamed to %s")\ %newGroupName) @@ -5454,7 +5479,7 @@ in Unix service") %str(jabberId)) self.printERROR (_("ERROR") + ": " +\ _("User %s is not found in Jabber service") % str(userName)) return False - uid = resSearch[0][0][1]['uid'][0] + uid = resSearch[0][0][1]['uid'][0].decode("UTF-8") # Удаляем jabberID из Unix сервиса # удаляем jabberID из Unix if self.isServiceSetup("unix",False) and\ @@ -5517,18 +5542,18 @@ in Unix service") %str(jabberId)) self.clVars.Set("ur_group",groupName) # Комментарий к группе groupGecos = self.servUnixObj.groupGecos - if options.has_key('c'): + if 'c' in options: groupGecos = options['c'] self.clVars.Set("ur_group_comment",groupGecos) ldifFile = self.ldifFileGroup groupLdif = self.createLdif(ldifFile) if not groupLdif: - print self.getError() + print(self.getError()) return False if not self.ldapObj.getError(): self.ldapObj.ldapAdd(groupLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printSUCCESS(_("Added group '%s' in Jabber service")\ %groupName) @@ -5544,7 +5569,7 @@ in Unix service") %str(jabberId)) searchUsers = self.searchAllUsers() flagError = False for fieldUser in searchUsers: - if fieldUser[0][1].has_key("mail"): + if "mail" in fieldUser[0][1]: userName = fieldUser[0][1]['uid'][0] jabberId = fieldUser[0][1]['mail'][0] cn = fieldUser[0][1]['cn'][0] @@ -5581,7 +5606,7 @@ in Unix service") %str(jabberId)) return False #jabber id jabberId = "%s@%s" %(userName,self.clVars.Get("sr_jabber_host")) - if options.has_key('j'): + if 'j' in options: # Изменяем JID jabberId = options['j'] if not "@" in jabberId: @@ -5617,7 +5642,7 @@ in Unix service") %str(jabberId)) self.clVars.Set("ur_name", userName) #Полное имя пользователя fullNameUser = self.servUnixObj.fullNameUser - if options.has_key('c'): + if 'c' in options: fullNameUser = options['c'] else: # Проверяем установку сервиса не печатая ошибку в случае @@ -5625,9 +5650,9 @@ in Unix service") %str(jabberId)) if self.isServiceSetup("unix",False): resUnix = self.servUnixObj.searchUnixUser(userName) # Берем комментарий для пользователя из Unix - if resUnix and resUnix[0][0][1].has_key('cn'): - fullNameUser = resUnix[0][0][1]['cn'][0] - self.clVars.Set("ur_fio",fullNameUser) + if resUnix and 'cn' in resUnix[0][0][1]: + fullNameUser = resUnix[0][0][1]['cn'][0].decode("UTF-8") + self.clVars.Set("ur_fio", fullNameUser) ldifFile = self.ldifFileUser userLdif = self.createLdif(ldifFile) if not self.ldapObj.getError(): @@ -5636,10 +5661,10 @@ in Unix service") %str(jabberId)) #ldapObj.ldapAdd(userLdif1) # не переделывать на else if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # загружаем картинку - if options.has_key('i'): + if 'i' in options: photoFile = options['i'] if not self.setJpegPhotoUser(userName, photoFile): self.printERROR(_("Can not add jpeg photo for user") + " " +\ @@ -5653,7 +5678,7 @@ in Unix service") %str(jabberId)) """Начальная настройка Jabber сервиса""" # Принудительная установка forceOptions = False - if options.has_key("f"): + if "f" in options: forceOptions = True # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): @@ -5712,14 +5737,14 @@ in Unix service") %str(jabberId)) fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'), self.clVars.Get('os_net_domain')) jabberHosts = fullHostName - if options.has_key("host"): + if "host" in options: fullHostName = options['host'] if not "." in fullHostName: fullHostName = "%s.%s" %(fullHostName, self.clVars.Get('os_net_domain')) self.clVars.Set("sr_jabber_host",fullHostName,True) # Устанавливаем дополнительные хосты jabber cервиса - if options.has_key("hosts"): + if "hosts" in options: hosts = options['hosts'].split(",") jabberHostsList = [self.clVars.Get("sr_jabber_host")] for host in hosts: @@ -5768,12 +5793,12 @@ in Unix service") %str(jabberId)) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Администратор сервиса adminName = "admin" adminFullName = "%s@%s" %(adminName, self.clVars.Get("sr_jabber_host")) - print _("Enter the %s password") %adminFullName + print(_("Enter the %s password") %adminFullName) if not self.addUserJabberServer(adminName,{'p':""}, False): return False # Записываем данные администратора сервиса Jabber @@ -5850,7 +5875,7 @@ class servSamba(shareLdap): Если группы нет она будет добавлена в противном случае пропущена """ # Находим группы у которых есть аттрибут type - groupsSambaList = filter(lambda x: x[1].type, self.staticGroups.items()) + groupsSambaList = [x for x in self.staticGroups.items() if x[1].type] groupsSamba = {} groupsSamba.update(groupsSambaList) flagError = False @@ -5903,7 +5928,7 @@ class servSamba(shareLdap): warning += _("If all clients of this server are calculate-client \ of version > 2.1.10, then you can delete this file.") + "\n" if not self.createUserFile(fileReplRun,warning,0,0, - mode=0644): + mode=0o644): return False return True @@ -5916,14 +5941,14 @@ of version > 2.1.10, then you can delete this file.") + "\n" """Удаление пользователей из списка из группы Samba""" def getPrimaryUsers(): - gidNumber = res[0][0][1]["gidNumber"][0] + gidNumber = res[0][0][1]["gidNumber"][0].decode("UTF-8") searchUsers = self.servUnixObj.searchUnixUserPrimGroup(gidNumber) foundUserNames = [] if searchUsers: for data in searchUsers: - foundUserNames.append(data[0][1]["uid"][0]) + foundUserNames.append(data[0][1]["uid"][0].decode("UTF-8")) if foundUserNames: - primaryUsers = list(set(foundUserNames)&set(users)) + primaryUsers = list(set(foundUserNames) & set(users)) if primaryUsers: self.printERROR(_("%s is primary group")% groupName + " " +\ _("for users (%s)")%", ".join(primaryUsers)) @@ -5934,35 +5959,35 @@ of version > 2.1.10, then you can delete this file.") + "\n" if not res : self.printERROR(_("group name is not found in Samba service")) return False - if not res[0][0][1].has_key("memberUid"): + if "memberUid" not in res[0][0][1]: if not getPrimaryUsers(): return False self.printERROR( - _("Member list of group %s is empty")%str(groupName)) + _("Member list of group %s is empty") % str(groupName)) return False memberUsers = res[0][0][1]["memberUid"] - flagError =False + flagError = False for user in users: - if not user in memberUsers: + if user.encode("UTF-8") not in memberUsers: flagError = True break if flagError: if not getPrimaryUsers(): return False self.printERROR( - _("User %s is not found in group")%str(user)+" "+\ + _("User %s is not found in group") % str(user)+ " " +\ str(groupName)) return False modAttrs = [] for userName in users: - modAttrs.append((ldap.MOD_DELETE, 'memberUid', userName)) - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + modAttrs.append((ldap.MOD_DELETE, 'memberUid', userName.encode("UTF-8"))) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) def delUserInGroup(self, userName): """Удаление из групп в которые входит пользователь""" userInGroups = self.searchSambaMemberGid(userName) - modAttrs = [(ldap.MOD_DELETE, 'memberUid', userName)] + modAttrs = [(ldap.MOD_DELETE, 'memberUid', userName.encode("UTF-8"))] flagError = False for group in userInGroups: groupName = group[0][1]['cn'][0] @@ -5987,11 +6012,11 @@ of version > 2.1.10, then you can delete this file.") + "\n" _("Group %s is not found in Samba service")%groupName) return False if checkPrimaryGroup: - groupId = res[0][0][1]['gidNumber'][0] + groupId = res[0][0][1]['gidNumber'][0].decode("UTF-8") if self.servUnixObj.searchUnixUserPrimGroup(groupId): self.printWARNING(_("cannot remove user's primary group") + ".") return True - delDN = self.addDN("cn="+groupName, self.relGroupsDN) + delDN = self.addDN("cn=" + groupName, self.relGroupsDN) res = self.delDN(delDN) if res: if printSuccess: @@ -6001,10 +6026,12 @@ of version > 2.1.10, then you can delete this file.") + "\n" self.printERROR(_("Can not delete group") + " " + groupName) return False - def delUserSambaServer(self,userName,options,printSuccess=True, - backup=True, notDeletedDirs=[]): + def delUserSambaServer(self, userName, options, printSuccess=True, + backup=True, notDeletedDirs=None): """Удаляем Samba пользователя""" # Проверим установлен ли сервис samba + if not notDeletedDirs: + notDeletedDirs = [] if not self.initialChecks("samba"): return False if "$" in userName: @@ -6038,7 +6065,7 @@ of version > 2.1.10, then you can delete this file.") + "\n" userNetlogonDir =\ os.path.join(self.clVars.Get("sr_samba_winlogon_path"), userName) - if options.has_key('r'): + if 'r' in options: backup = False # Делаем сохранение данных удаляемого пользователя if backup: @@ -6110,7 +6137,7 @@ of version > 2.1.10, then you can delete this file.") + "\n" if checkSetup and not self.initialChecks("samba"): return False # Добавление машины samba - if options.has_key('w'): + if 'w' in options: if self.addMachineSambaServer(userName, options): return True else: @@ -6119,7 +6146,7 @@ of version > 2.1.10, then you can delete this file.") + "\n" uidUnixUser = False resSearch = self.servUnixObj.searchUnixUser(userName) if resSearch: - uidUnixUser = resSearch[0][0][1]['uidNumber'][0] + uidUnixUser = resSearch[0][0][1]['uidNumber'][0].decode("UTF-8") ## создание пользователя Unix опция f #if not resSearch and not options.has_key('f'): #self.printERROR( @@ -6146,25 +6173,25 @@ of version > 2.1.10, then you can delete this file.") + "\n" # Добавим пользователя LDAP optUnix = {} # id пользователя - if options.has_key('u'): + if 'u' in options: optUnix['u'] = options['u'] # Группа пользователя - if options.has_key('g'): + if 'g' in options: optUnix['g'] = options['g'] # Группы в которые входит пользователь - if options.has_key('G'): + if 'G' in options: optUnix['G'] = options['G'] # Полное имя пользователя - if options.has_key('c'): + if 'c' in options: optUnix['c'] = options['c'] # shell - if options.has_key('s'): + if 's' in options: optUnix['s'] = options['s'] # Домашняя директория - if options.has_key('d'): + if 'd' in options: optUnix['d'] = options['d'] # Cделаем пользователя видимым - if optUnix.has_key('u'): + if 'u' in optUnix: try: int(optUnix['u']) except: @@ -6199,11 +6226,11 @@ of version > 2.1.10, then you can delete this file.") + "\n" if textLine != False: flagError = False - if options.has_key('G'): + if 'G' in options: # Изменяем Samba группы пользователя userGroups = options['G'].split(',') data = self.searchUnixAndSambaGroups(userGroups, True) - if data and type(data) == types.TupleType: + if data and type(data) == tuple: userGroupNamesUnix, userGroupNamesSamba = data else: flagError = True @@ -6294,12 +6321,13 @@ of version > 2.1.10, then you can delete this file.") + "\n" uid = int(resPasswd.split(":")[2]) gid = int(resPasswd.split(":")[3]) # Не удаляемые директории - notDeletedDirs = filter(lambda x:x and os.path.exists(x), - (createDirHome,createDirLogon, + notDeletedDirs = [x for x in (createDirHome, createDirLogon, createDirWin7Profile, - createDirWinProfile,createDirLinProfile)) + createDirWinProfile, createDirLinProfile) + if x and os.path.exists(x)] + if (resPasswd or resSearchUnix) and\ - (options.has_key('n') or int(uid) >=1000): + ('n' in options or int(uid) >=1000): # Cоздаем домашнюю директорию if createDirHome: if not self.createUserDir(uid, gid, createDirHome): @@ -6417,10 +6445,10 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) return False else: findUsers = [] - if res[0][0][1].has_key('memberUid'): + if 'memberUid' in res[0][0][1]: usersInGroup = res[0][0][1]['memberUid'] for userName in usersNames: - if userName in usersInGroup: + if userName.encode("UTF-8") in usersInGroup: findUsers.append(userName) return findUsers @@ -6430,7 +6458,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) rezultUnix, groupNamesUnix, errMessUnix =\ self.servUnixObj.searchGroupsUnix(userGroups, False) grUnix = groupNamesUnix - groupNamesUnix = groupNamesUnix.keys() + groupNamesUnix = list(groupNamesUnix.keys()) # Если установлен сервис Samba groupNamesSamba = [] gidNotFound = [] @@ -6438,7 +6466,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) rezultSamba, groupNamesSamba, errMessSamba =\ self.searchGroupsSamba(userGroups, False) grSamba = groupNamesSamba - groupNamesSamba = groupNamesSamba.keys() + groupNamesSamba = list(groupNamesSamba.keys()) userGroupNames = [] for userGr in userGroups: try: @@ -6484,7 +6512,6 @@ Samba and Unix services") %", ".join(exclGroup) resSearch = self.searchLdapDN(groupName, self.relGroupsDN, "cn") return resSearch - def searchGroupsSamba(self, userGroups, printError=True): """Ищет список групп из списка userGroups в LDAP @@ -6499,14 +6526,14 @@ Samba and Unix services") %", ".join(exclGroup) try: int(gid) except: - groupName = gid + groupName = gid.strip('\"').strip("\'") res = self.searchSambaGroupName(groupName) if not res: groupErrors.append(groupName) flagError = True continue - userGroupNames[res[0][0][1]['cn'][0]]=\ - res[0][0][1]['gidNumber'][0] + userGroupNames[res[0][0][1]['cn'][0].decode("UTF-8")]=\ + res[0][0][1]['gidNumber'][0].decode("UTF-8") continue gidNumber = gid res = self.searchSambaGid(gidNumber) @@ -6514,7 +6541,8 @@ Samba and Unix services") %", ".join(exclGroup) gidErrors.append(gidNumber) flagError = True continue - userGroupNames[res[0][0][1]['cn'][0]] = res[0][0][1]['gidNumber'][0] + userGroupNames[res[0][0][1]['cn'][0].decode("UTF-8")] =\ + res[0][0][1]['gidNumber'][0].decode("UTF-8") if flagError: errorMessage = "" if groupErrors: @@ -6532,6 +6560,7 @@ Samba and Unix services") %", ".join(exclGroup) return (False, userGroupNames, errorMessage) return (True, userGroupNames, "") + def searchSambaGid(self, groupId): """Находит группу сервиса Samba по ёе id""" resSearch = self.searchLdapDN(str(groupId), self.relGroupsDN, @@ -6559,7 +6588,7 @@ Samba and Unix services") %", ".join(exclGroup) addUsers.append(user) modAttrs = [] for userName in addUsers: - modAttrs.append((ldap.MOD_ADD, 'memberUid', userName)) + modAttrs.append((ldap.MOD_ADD, 'memberUid', userName.encode("UTF-8"))) if modAttrs: groupDN = self.addDN("cn="+groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) @@ -6574,7 +6603,7 @@ Samba and Unix services") %", ".join(exclGroup) return False # Если группа существует выходим без ошибки flagSearchGroups = True - if options.has_key('f'): + if 'f' in options: flagSearchGroups = False if flagSearchGroups and\ self.servUnixObj.searchGroupGroupName(groupName): @@ -6595,7 +6624,7 @@ Samba and Unix services") %", ".join(exclGroup) self.clVars.Set("ur_group",groupName) # номер группы gid = str(self.servUnixObj.getMaxGid()) - if options.has_key('g'): + if 'g' in options: gid = options['g'] try: int(gid) @@ -6613,7 +6642,7 @@ Samba and Unix services") %", ".join(exclGroup) return False groupSid = "" # Получаем sid - if options.has_key('s'): + if 's' in options: # Проверяем кoрректность sid sidRe = re.compile("^S-(?:\d+-)+\d+$") if not sidRe.search(options['s']): @@ -6626,7 +6655,7 @@ Samba and Unix services") %", ".join(exclGroup) return False # Получаем samba rid sambaRid = str(2*int(gid)+1001) - if options.has_key('r'): + if 'r' in options: try: int(options['r']) except: @@ -6640,7 +6669,7 @@ Samba and Unix services") %", ".join(exclGroup) return False # По умолчанию тип группы - доменная группа groupType = "2" - if options.has_key('t'): + if 't' in options: try: int(options['t']) except: @@ -6660,20 +6689,20 @@ Samba and Unix services") %", ".join(exclGroup) self.clVars.Set("ur_group_id", gid) # Комментарий к группе gecos = self.servUnixObj.groupGecos - if options.has_key('c'): + if 'c' in options: gecos = options['c'] self.clVars.Set("ur_group_comment",gecos) ldifFile = self.ldifFileGroup groupLdif = self.createLdif(ldifFile) if not groupLdif: - print self.getError() + print(self.getError()) return False if not self.ldapObj.getError(): self.ldapObj.ldapAdd(groupLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False - if options.has_key('p'): + if 'p' in options: sys.stdout.write(gid) else: if printSuccess: @@ -6722,18 +6751,18 @@ Samba and Unix services") %", ".join(exclGroup) machineGid = resSearch[0][0][1]['gidNumber'][0] else: mGr = self.staticGroups["Domain Computers"] - machineGid = mGr.gid + machineGid = mGr.gid.encode("UTF-8") searchAllMachines = self.searchAllSambaMachines() if searchAllMachines: for data in searchAllMachines: - machineName = data[0][1]['uid'][0] + machineName = data[0][1]['uid'][0].decode("UTF-8") machineDN = self.addDN("uid=" + machineName, self.relComputersDN) res = self.modAttrsDN(machineDN, [(ldap.MOD_REPLACE, 'gidNumber', machineGid)]) if not res: self.printERROR(_("Can not replace machine %s \ -'gidNumber'")%machineName) + 'gidNumber'")%machineName) flagError = True break if flagError: @@ -6750,7 +6779,7 @@ Samba and Unix services") %", ".join(exclGroup) self.printERROR(_("group name not found in Samba service")) return False # Добавляем список пользователей в группу - if options.has_key('a'): + if 'a' in options: # добавляемые пользователи в группу users = options['a'].split(',') res = self.addUsersGroupSamba(users, groupName) @@ -6762,7 +6791,7 @@ Samba and Unix services") %", ".join(exclGroup) " " + str(groupName)) return False # Удаляем список пользователей из группы - if options.has_key('d'): + if 'd' in options: # удаляемые пользователи из группы users = options['d'].split(',') res = self.delUsersGroupSamba(users, groupName) @@ -6775,7 +6804,7 @@ Samba and Unix services") %", ".join(exclGroup) return False modGroupName = groupName # Изменяем имя группы - if options.has_key('n'): + if 'n' in options: newGroupName = options['n'] if self.servUnixObj.searchUnixGroupName(newGroupName): self.printERROR( @@ -6799,7 +6828,7 @@ Samba and Unix services") %", ".join(exclGroup) return False modAttrs = [] # Изменяем тип группы - if options.has_key('t'): + if 't' in options: try: int(options['t']) except: @@ -6812,25 +6841,25 @@ Samba and Unix services") %", ".join(exclGroup) 5 (builtin group).")) return False groupType = options['t'] - modAttrs.append((ldap.MOD_REPLACE, 'sambaGroupType', groupType)) + modAttrs.append((ldap.MOD_REPLACE, 'sambaGroupType', groupType.encode("UTF-8"))) # Изменяем комментарий к группе - if options.has_key('c'): + if 'c' in options: gecos = options['c'] - modAttrs.append((ldap.MOD_REPLACE, 'description', gecos)) - modAttrs.append((ldap.MOD_REPLACE, 'displayName', gecos)) + modAttrs.append((ldap.MOD_REPLACE, 'description', gecos.encode("UTF-8"))) + modAttrs.append((ldap.MOD_REPLACE, 'displayName', gecos.encode("UTF-8"))) if modAttrs: groupDN = self.addDN("cn=" + modGroupName, self.relGroupsDN) res = self.modAttrsDN(groupDN, modAttrs) if res: - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified group comment")) - if options.has_key('t'): + if 't' in options: self.printSUCCESS(_("Modified group type")) return True else: - if options.has_key('c'): + if 'c' in options: self.printERROR(_("Can not modify group comment")) - if options.has_key('t'): + if 't' in options: self.printERROR(_("Can not modify group type")) return False return True @@ -6840,7 +6869,7 @@ Samba and Unix services") %", ".join(exclGroup) machineLogin = machineName.replace('$','') + "$" res = self.searchSambaMachine(machineLogin) if res: - if res[0][0][1].has_key('sambaSID'): + if 'sambaSID' in res[0][0][1]: self.printERROR(_("machine")+" "+machineLogin+" "+\ "is found in Samba service") return True @@ -6871,7 +6900,7 @@ Samba and Unix services") %", ".join(exclGroup) resSearch = self.searchLdapDN("*", self.relDN, "sambaDomainName", ["sambaSID"]) if resSearch: - return resSearch[0][0][1]['sambaSID'][0] + return resSearch[0][0][1]['sambaSID'][0].decode("UTF-8") self.printERROR(_("Not found sambaSID in LDAP")) return False @@ -6883,8 +6912,8 @@ Samba and Unix services") %", ".join(exclGroup) self.clVars должен быть определен """ - print _("Enter the allowed ip addresses and network for %s service")\ - %"Samba" + " (" + _("comma or space delimited") + ")" + print(_("Enter the allowed ip addresses and network for %s service")\ + %"Samba" + " (" + _("comma or space delimited") + ")") strPrompt = _("allow networks: ") netAllow = self.clVars.Get("sr_samba_net_allow") strNetAllow = "" @@ -6905,7 +6934,7 @@ Samba and Unix services") %", ".join(exclGroup) # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): return False - if options.has_key("f"): + if "f" in options: forceOptions = True if self.clVars.Get("sr_unix_set") != "on": self.printERROR(_("Unix service is not setuped")) @@ -6932,13 +6961,13 @@ Samba and Unix services") %", ".join(exclGroup) _("input 'yes'") +", "+ _("if not 'no'") if not self.dialogYesNo(messDialog): return True - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: return False else: - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: @@ -6974,7 +7003,7 @@ Samba and Unix services") %", ".join(exclGroup) # Устанавливаем доступные сети self.clVars.Set("sr_samba_net_allow",allowNet,True) # Задаем рабочую группу (домен) - if options.has_key("w"): + if "w" in options: workgroup = options['w'].strip() if len(workgroup)>15: self.printERROR(_("A very long name of the command line \ @@ -6982,10 +7011,10 @@ options '-w, --workgroup'")) return False self.clVars.Set("sr_samba_domain",workgroup) # Задаем netbios имя - if options.has_key("n"): + if "n" in options: netbios = options['n'].strip() # Проверка на неравенство workgroup и netbios - if options.has_key("w") and workgroup == netbios: + if "w" in options and workgroup == netbios: self.printERROR(_("Value of command line option \ '-w, --workgroup' equal to value of command line option '-n, --netbios'")) return False @@ -7059,7 +7088,7 @@ options '-w, --workgroup'")) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printOK(_("Added ldif file") + " ...") for service_initd, service_name in [("samba", "Samba"), ("calculate-profile", "Calculate Profile")]: @@ -7133,12 +7162,12 @@ options '-w, --workgroup'")) # права и владелец /var/calculate/remote if os.path.exists(remotePath): os.chown(remotePath,0,int(cl.gid)) - os.chmod(remotePath,02755) + os.chmod(remotePath,0o2755) # изменяем владельца remote на client if not os.path.exists(remoteEnvFile): fd = os.open(remoteEnvFile, os.O_CREAT) os.close(fd) - os.chmod(remoteEnvFile, 0640) + os.chmod(remoteEnvFile, 0o640) if os.path.exists(remoteEnvFile): os.chown(remoteEnvFile,0,int(cl.gid)) if not self.setDaemonAutostart("slapd"): @@ -7187,7 +7216,7 @@ options '-w, --workgroup'")) _("Samba user %s is not found")%str(userName)) return False # отключаем samba account - if options.has_key('l'): + if 'l' in options: textLine = self.execProg("smbpasswd -d %s" %(userName)) if textLine == False: self.printERROR(_("Can not disable Samba user")+ " "+\ @@ -7196,7 +7225,7 @@ options '-w, --workgroup'")) else: self.printSUCCESS(_("Disabled Samba user %s")%str(userName)) # включаем Samba account - if options.has_key('u'): + if 'u' in options: textLine = self.execProg("smbpasswd -e %s" %(userName)) if textLine == False: self.printERROR(_("Can not enable Samba user")+ " "+\ @@ -7204,14 +7233,14 @@ options '-w, --workgroup'")) return False else: self.printSUCCESS(_("Enabled Samba user %s")%str(userName)) - if not options or options.has_key('s'): + if not options or 's' in options: optPasswd = {"p":""} userPwd = self.getUserPassword(optPasswd, "p", False) if userPwd == False: return False if userPwd: # Опция s пароль только для Samba - if not options.has_key('s'): + if 's' not in options: if not self.servUnixObj.modUserUnixPasswd(userName,{}, userPwd): return False @@ -7240,7 +7269,7 @@ options '-w, --workgroup'")) str(userName)) return False # отключаем Samba account - if options.has_key('L'): + if 'L' in options: textLine = self.execProg("smbpasswd -d %s" %(userName)) if textLine == False: self.printERROR(_("Can not disable Samba user")+ " "+\ @@ -7249,7 +7278,7 @@ options '-w, --workgroup'")) else: self.printSUCCESS(_("Disabled Samba user %s")%str(userName)) # включаем samba account - elif options.has_key('U'): + elif 'U' in options: textLine = self.execProg("smbpasswd -e %s" %(userName)) if textLine == False: self.printERROR(_("Can not enable Samba user")+ " "+\ @@ -7258,14 +7287,14 @@ options '-w, --workgroup'")) else: self.printSUCCESS(_("Enabled Samba user %s")%str(userName)) # модифицируем пароль - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: pwDialog = [_("New SMB password"), _("Retype new SMB password")] userPwd = self.getUserPassword(options, "p", "P", pwDialog) if userPwd == False: return False # Опция s пароль только для Samba - if not options.has_key('s'): + if 's' not in options: if not self.servUnixObj.modUserUnixPasswd(userName,{}, userPwd): return False @@ -7276,17 +7305,17 @@ options '-w, --workgroup'")) return False self.printSUCCESS(_("Modified Samba user password")) - if options.has_key("g"): + if "g" in options: optUnix = {'g':options['g']} if not self.servUnixObj.modUserUnixServer(userName, optUnix, True, True): return False # изменяем Unix и Samba группы в которые включен пользователь - if options.has_key("G"): + if "G" in options: # Изменяем Samba группы пользователя userGroups = options['G'].split(',') data = self.searchUnixAndSambaGroups(userGroups, True) - if data and type(data) == types.TupleType: + if data and type(data) == tuple: userGroupNamesUnix, userGroupNamesSamba = data else: return False @@ -7309,12 +7338,12 @@ options '-w, --workgroup'")) if printSuccess: self.printSUCCESS(_("Replaced list of supplementary group")) # Изменяем комментарий к пользователю - if options.has_key('c'): + if 'c' in options: comment = options['c'] - if res[0][0][1].has_key('displayName'): - modAttrs = [(ldap.MOD_REPLACE, 'displayName', comment)] + if 'displayName' in res[0][0][1]: + modAttrs = [(ldap.MOD_REPLACE, 'displayName', comment.encode("UTF-8"))] else: - modAttrs = [(ldap.MOD_ADD, 'displayName', comment)] + modAttrs = [(ldap.MOD_ADD, 'displayName', comment.encode("UTF-8"))] DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False @@ -7388,7 +7417,7 @@ class servLdap(shareLdap): try: FD = open (fileName, "w+") FD.close() - os.chmod(fileName,0600) + os.chmod(fileName,0o600) FD = open (fileName, "w+") FD.write(data) FD.close() @@ -7417,8 +7446,8 @@ class servLdap(shareLdap): deltaTime = timeLocal - timeFile if deltaTime.days == 0: deltaSec = deltaTime.seconds - dHours = int(deltaSec/3600) - dMinutes = int((deltaSec - dHours*3600)/60) + dHours = int(deltaSec//3600) + dMinutes = int((deltaSec - dHours*3600)//60) dSeconds = deltaSec - dHours*3600 - dMinutes*60 hours = _("hours") minutes = _("minutes") @@ -7444,7 +7473,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) # В случае создания сервера репликации из файла backup c # другого компьютера replServices = [] - if options.has_key("repl"): + if "repl" in options: # Находим имена сервисов репликации для этого сервера # и инициализируем переменные replServices = self.getArchReplServices() @@ -7467,9 +7496,9 @@ outdated. If the backup is obsolete, use cl-backup-server.")) return False verbose = False opt = {} - if options.has_key("v"): + if "v" in options: opt['v'] = '' - if options.has_key("a"): + if "a" in options: opt['a'] = '' # Сервисы для которых не будет задаваться вопрос о доступных сетях # при включенной опции allow @@ -7485,9 +7514,13 @@ outdated. If the backup is obsolete, use cl-backup-server.")) """Перегенерирует конфигурационные файлы, и базу данных LDAP""" return self.rebuildServer(options) - def applyProfilesFromService(self, service, verbose=False, dirsFilter = [], - filesFilter = []): + def applyProfilesFromService(self, service, verbose=False, dirsFilter=None, + filesFilter=None): """Применяем профили для данного сервиса""" + if dirsFilter is None: + dirsFilter = [] + if filesFilter is None: + filesFilter = [] # Cоздаем объект профиль устанавливая директорию # service для файлов профилей clProf = cl_profile.profile(self.clVars,service,dirsFilter,filesFilter) @@ -7497,7 +7530,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) self.printERROR(clProf.getError()) return False else: - if verbose and type(data) == types.TupleType: + if verbose and type(data) == tuple: dirs, files = data return files return True @@ -7514,12 +7547,14 @@ outdated. If the backup is obsolete, use cl-backup-server.")) return True def updateServer(self, options, serviceUpdate, clVars=False, - noInputAllowNetServices=[], printReplServ=True): + noInputAllowNetServices=None, printReplServ=True): """Перегенерируем конфигурационные файлы определенного или всех сервисов """ # Создаем переменные + if not noInputAllowNetServices: + noInputAllowNetServices = [] if clVars: self.clVars = clVars else: @@ -7552,7 +7587,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) # Настройка прокси if serviceUpdate in ["all","proxy"]: # Порт для прокси сервера - if options.has_key("p"): + if "p" in options: proxyPort = options['p'] try: numberProxyPort = int(proxyPort) @@ -7561,11 +7596,11 @@ outdated. If the backup is obsolete, use cl-backup-server.")) return False proxyPort = str(numberProxyPort) self.clVars.Set("sr_proxy_port", proxyPort, True) - if options.has_key("host"): + if "host" in options: fullHostName = options['host'] if not "." in fullHostName: fullHostName = "%s.%s" %(fullHostName, - self.clVars.Get('os_net_domain')) + self.clVars.Get('os_net_domain')) self.clVars.Set("sr_proxy_host",fullHostName,True) # Настройка почты if serviceUpdate in ["all","mail"]: @@ -7574,7 +7609,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) return False history,history_domain,history_path = \ self.getMailHistoryData(options) - if options.has_key("t"): + if "t" in options: mailType = options['t'] if mailType: if not set(mailType.split(",")) <= set(["imap","pop3"]): @@ -7587,7 +7622,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) self.printERROR(_("Мail type incorrect")) return False self.clVars.Set("sr_mail_type", mailType) - if options.has_key("c"): + if "c" in options: mailCrypt = options['c'] if not mailCrypt in ["none", "tls"]: self.printERROR(_("Мail encryption not 'none' or 'tls'")) @@ -7602,11 +7637,11 @@ outdated. If the backup is obsolete, use cl-backup-server.")) # Устанавливаем основной хост jabber cервиса if not self.createJabberCertificate(): return False - if options.has_key("host"): + if "host" in options: newHostName = options['host'] if not "." in newHostName: newHostName = "%s.%s" %(newHostName, - self.clVars.Get('os_net_domain')) + self.clVars.Get('os_net_domain')) if newHostName != previousJabberHost: # Устанавливаем перемемнную self.clVars.Set("sr_jabber_host",newHostName,True) @@ -7618,14 +7653,14 @@ outdated. If the backup is obsolete, use cl-backup-server.")) jabberHosts = ",".join(unicHostsList) self.clVars.Set("sr_jabber_hosts",jabberHosts,True) # Устанавливаем дополнительные хосты jabber cервиса - if options.has_key("hosts"): + if "hosts" in options: hosts = options['hosts'].split(",") jabberHostsList = [self.clVars.Get("sr_jabber_host")] for host in hosts: apHost = host if not "." in host: apHost = "%s.%s" %(host, - self.clVars.Get('os_net_domain')) + self.clVars.Get('os_net_domain')) jabberHostsList.append(apHost) unicHostsList = [] for host in jabberHostsList: @@ -7664,13 +7699,13 @@ outdated. If the backup is obsolete, use cl-backup-server.")) adminPw = ldapParser.getVar(servicePwd,"PASS") if not adminPw: self.printERROR(_("Not found password from service %s")\ - %servicePwd) + %servicePwd) flagError = True break self.clVars.Set("ld_%s_pw"%servicePwd, adminPw, True) # Наложение профилей verbose = False - if options.has_key("v"): + if "v" in options: verbose = True # Cервисы которые рестартуют servicesRestart = [] @@ -7685,7 +7720,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) if service == "samba": # Получаем от пoльзователя доверительные сети # для сервиса Samba - if options.has_key("a") and\ + if "a" in options and\ not service in noInputAllowNetServices: self.servSambaObj.clVars = self.clVars if not self.servSambaObj.getAllowNet(): @@ -7732,7 +7767,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) if service == "mail": # Получаем от пользователя доверительные сети # для сервиса Mail - if options.has_key("a") and\ + if "a" in options and\ not service in noInputAllowNetServices: self.servMailObj.clVars = self.clVars if not self.servMailObj.getAllowNet(): @@ -7745,7 +7780,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) if service == "proxy": # Получаем от пользователя доверительные сети # для сервиса Proxy - if options.has_key("a") and\ + if "a" in options and\ not service in noInputAllowNetServices: self.servProxyObj.clVars = self.clVars if not self.servProxyObj.getAllowNet(): @@ -7767,7 +7802,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) if not files: flagError = True break - if verbose and type(files) == types.ListType: + if verbose and type(files) == list: self.printSUCCESS(_("Updating config from service %s")\ %self.printNameService(service)) for applyFile in files: @@ -7839,7 +7874,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) if not flagError and serviceUpdate in ["all","jabber"]: # Замена имени хоста для сервиса Jabber в LDAP - if options.has_key("host"): + if "host" in options: if self.clVars.Get("sr_jabber_host") != previousJabberHost: # Установка в LDAP ветке Jabber cервиса нового имени хоста if not self.servJabberObj.setHostName(newHostName, @@ -7961,7 +7996,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) foundFiles = clProf.scanProfiles(serviceName) if not foundFiles: return [] - foundFiles = filter(lambda x: os.path.exists(x), foundFiles) + foundFiles = [x for x in foundFiles if os.path.exists(x)] return foundFiles def backupNotLdap(self): @@ -8045,7 +8080,7 @@ outdated. If the backup is obsolete, use cl-backup-server.")) # если существуют удаляем файлы в /tmp self.removeTmpFiles() if os.path.exists(bFile): - os.chmod(bFile,0600) + os.chmod(bFile,0o600) self.printSUCCESS(_("Created archive file") + ": " +\ str(bFile)) return True @@ -8306,8 +8341,8 @@ service %s")%service replArchFilesUnix.append(additFile) replArchFilesUnix = self.unicList(replArchFilesUnix) # Удаляем начальный "/" - replArchFilesUnix = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesUnix) + replArchFilesUnix = ["/".join(y for y in x.split("/") if y) + for x in replArchFilesUnix] replArchFilesUnix.sort() if "samba" in replServices: # Дополнительные файлы добавляемые в архив @@ -8318,8 +8353,8 @@ service %s")%service replArchFilesSamba.append(additFile) replArchFilesSamba += replArchFilesUnix # Удаляем начальный "/" - replArchFilesSamba = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesSamba) + replArchFilesSamba = ["/".join(y for y in x.split("/") if y) + for x in replArchFilesSamba] replArchFilesSamba = self.unicList(replArchFilesSamba) replArchFilesSamba.sort() if "mail" in replServices: @@ -8335,9 +8370,8 @@ service %s")%service additFiles = list(set(additFilesMailUnix)|set(additFiles)) for additFile in additFilesMailUnix: replArchFilesMailUnix.append(additFile) - replArchFilesMailUnix = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),\ - replArchFilesMailUnix) + replArchFilesMailUnix = ["/".join(y for y in x.split("/") if y) + for x in replArchFilesMailUnix] replArchFilesMailUnix = self.unicList(replArchFilesMailUnix) replArchFilesMailUnix.sort() if "samba" in replServices: @@ -8346,14 +8380,13 @@ service %s")%service additFiles = list(set(additFilesMailSamba)|set(additFiles)) for additFile in additFilesMailSamba: replArchFilesMailSamba.append(additFile) - replArchFilesMailSamba = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),\ - replArchFilesMailSamba) + replArchFilesMailSamba = ["/".join(y for y in x.split("/") if y) + for x in replArchFilesMailSamba] replArchFilesMailSamba=self.unicList(replArchFilesMailSamba) replArchFilesMailSamba.sort() # Удаляем начальный "/" - replArchFilesMail = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesMail) + replArchFilesMail = ["/".join(y for y in x.split("/") if y) + for x in replArchFilesMail] replArchFilesMail = self.unicList(replArchFilesMail) replArchFilesMail.sort() for additFile in additFiles: @@ -8424,15 +8457,14 @@ service %s")%service return False # Удаляем dovecot, procmailrc из списка файлов # а также ненужные алиасы - replArchFilesMail = map(lambda x:"/".join(x),\ - filter(lambda x:\ - not 'dovecot' in x and\ - not 'procmailrc' == x[-1] and\ - not 'ldap-aliases-gr.cf' == x[-1] and\ - not 'ldap-aliases.cf' == x[-1] and\ - not 'ldap-recipient-gr.cf' == x[-1] and\ - not 'ldap-recipient.cf' == x[-1],\ - map(lambda x:x.split("/"),replArchFilesMail))) + replArchFilesMail = ["/".join(x) + for x in (y.split("/") for y in replArchFilesMail) + if not 'dovecot' in x and + not 'procmailrc' == x[-1] and + not 'ldap-aliases-gr.cf' == x[-1] and + not 'ldap-aliases.cf' == x[-1] and + not 'ldap-recipient-gr.cf' == x[-1] and + not 'ldap-recipient.cf' == x[-1]] if not self.savePrivateFile (self.replListFileMail, "\n".join(replArchFilesMail)): self.printERROR(_("Can not create list archive files")+\ @@ -8483,7 +8515,7 @@ service %s")%service # если существуют удаляем файлы в /tmp self.removeTmpFiles() if os.path.exists(bFile): - os.chmod(bFile,0600) + os.chmod(bFile,0o600) self.printSUCCESS(_("Created archive file") + ": " +\ str(bFile)) return True @@ -8493,7 +8525,7 @@ service %s")%service return False def backupLdapServer(self, options): - if not options or (options and options.has_key("b")): + if not options or (options and "b" in options): # Создаем объект переменных clVars self.createClVars(self.clVars) # находим установленные сервисы @@ -8508,7 +8540,7 @@ service %s")%service return self.backupServer() else: return self.backupNotLdap() - if options.has_key("r"): + if "r" in options: return self.restoreServer() def startAllSetupServices(self): @@ -8522,7 +8554,7 @@ service %s")%service # заменяем mail на mail_relay if set(["mail","ldap"]) == set(servInstalled) and\ self.clVars.Get("sr_mail_relay_set") == "on": - servInstalled = filter(lambda x: x!="mail",servInstalled) +\ + servInstalled = [x for x in servInstalled if x != "mail"] +\ ["mail_relay"] return self.startServices(servInstalled) @@ -8565,7 +8597,7 @@ service %s")%service self.printERROR(_('Can not execute "%s"')%strCmd) return False # удаляем из элементов переводы строк - archFiles = map(lambda x: "".join(x.split('\n')),textListFiles) + archFiles = ("".join(x.split('\n')) for x in textListFiles) if self.archLdifFile[1:] in archFiles: return True return False @@ -8582,7 +8614,7 @@ service %s")%service self.printERROR(_('Can not execute "%s"')%strCmd) return False # удаляем из элементов переводы строк - archFiles = map(lambda x: "".join(x.split('\n')),textListFiles) + archFiles = ["".join(x.split('\n')) for x in textListFiles] flagError = False # Находим в списке файлов файлы списки для сервисов listReplFiles = list(set([self.replListFileSamba[1:], @@ -8747,8 +8779,8 @@ for running replication")%bFile) allArchFiles = [self.replArchLdifFileMail, self.replListFileMail] # Удаляем начальный '/' - allArchFiles = map(lambda x:\ - "/".join(filter(lambda y:y ,x.split("/"))),allArchFiles) + allArchFiles = ["/".join(y for y in x.split("/") if y) + for x in allArchFiles] # Удаляем временные файлы self.removeTmpFiles() # Сохраняем файл - список извлекаемых файлов (файл ldif) @@ -8785,7 +8817,7 @@ for running replication")%bFile) # Добавляем в базу из ldif self.ldapObj.ldapAdd(ldif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Останавливаем LDAP сервер if not self.stopLdapServer(): @@ -8907,7 +8939,9 @@ for running replication")%bFile) os.remove(rmFile) #удаляем ссылки for linkRemove in scanObjs[0].links: - rmLink = flinkRemove.split(backupDir)[1] + # is this a typo? + # rmLink = flinkRemove.split(backupDir)[1] + rmLink = linkRemove.split(backupDir)[1] if os.path.exists(rmLink): os.unlink(rmLink) return True @@ -8941,7 +8975,7 @@ for running replication")%bFile) while ldapObj.getError(): try: # Задержка - wait.next() + next(wait) except StopIteration: break # Очистка ошибки @@ -8966,7 +9000,7 @@ for running replication")%bFile) # Принудительная установка forceOptions = False self.createClVars() - if options.has_key("f"): + if "f" in options: forceOptions = True if self.clVars.Get("sr_ldap_set") == "on" and\ not forceOptions: @@ -9052,7 +9086,7 @@ for running replication")%bFile) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printOK(_("Added ldif file") + " ...") # Второй проход, @@ -9625,12 +9659,12 @@ to this group") #'helpChapter':_("Samba service options"), #'help':_("create unix user account and Samba user account") #}, - #{'progAccess':(3,), - #'shortOption':"f", - #'longOption':"force", - #'helpChapter':_("Mail service options"), - #'help':_("create unix user account and mail user account") - #}, + {'progAccess':(3,6,), + 'shortOption':"f", + 'longOption':"force", + 'helpChapter':_("Mail service options"), + 'help':_("create unix user account and mail user account") + }, {'progAccess':(3,), 'shortOption':"n", 'longOption':"create-profile", @@ -10030,6 +10064,12 @@ the password will be changed only for Samba account") 'helpChapter':_("DHCP service options"), 'help':_("forced setup service") }, + {'progAccess':(6,), + 'shortOption':"f", + 'longOption':"force", + 'helpChapter':_("Samba service options"), + 'help':_("forced setup service") + }, {'progAccess':(6,), 'longOption':"net", 'optVal':"NET", @@ -11027,6 +11067,7 @@ example: --range 192.168.0.2,192.168.0.50') 'help':_("password for distinguished name (dn) - service DNS from \ file") }, + #{'progAccess':(0,1,2,4,5,6), #'shortOption':"s", #'longOption':"set", @@ -11462,10 +11503,10 @@ service") for pkg in pkgs: category,package = pkg.split('/') catDir = os.path.join(pkgDir,category) - package = "%s-"%package + package = "%s-" % package if not (os.path.exists(catDir) and - filter(lambda x:x.startswith(package),os.listdir(catDir))): - self.printERROR(_("Package '%s' is not installed")%pkg) + [x for x in os.listdir(catDir) if x.startswith(package)]): + self.printERROR(_("Package '%s' is not installed") % pkg) return False return True @@ -11488,7 +11529,7 @@ service") # если установки параметрв не произошло if not datavars.flFromCmdParam(options['s']): # вывод - print _("Bad enviroment parameters") + print(_("Bad enviroment parameters")) return False # если опция отображения параметров if 'e' in options: @@ -11538,9 +11579,9 @@ service") """Записывает в аттрибут self.allServ названия всех сервисов""" sServ = re.compile("\s*([^\s]+)\s*") for par in self.data: - if par.has_key('helpChapter') and\ + if 'helpChapter' in par and\ par['helpChapter'] == _("Services") and\ - par.has_key('help') and self.access(par): + 'help' in par and self.access(par): res = sServ.search(par['help']) if res: self.allServ.append(res.group(1)) @@ -11572,7 +11613,7 @@ class servFtp(shareLdap): """Начальная настройка FTP сервиса""" # Принудительная установка forceOptions = False - if options.has_key("f"): + if "f" in options: forceOptions = True # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): @@ -11668,7 +11709,7 @@ class servFtp(shareLdap): if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Записываем данные администратора сервиса FTP ldapParser = iniLdapParser() @@ -11708,12 +11749,12 @@ class servFtp(shareLdap): ftpTmpPath = os.path.join(ftpPath,"tmp") if not os.path.exists(ftpTmpPath): os.makedirs(ftpTmpPath) - os.chmod(ftpTmpPath,0777) + os.chmod(ftpTmpPath,0o777) #cоздаем директорию pub ftpPubPath = os.path.join(ftpPath,"pub") if not os.path.exists(ftpPubPath): os.makedirs(ftpPubPath) - os.chmod(ftpPubPath,0755) + os.chmod(ftpPubPath,0o755) #запишем переменные для клиента clientVars = ["cl_remote_ftp"] if not self.saveVarsClient(clientVars): @@ -11754,8 +11795,8 @@ class servFtp(shareLdap): # Изменяемые аттрибуты пользователя modAttrs = [] # Изменяем комментарий к пользователю - if options.has_key('c'): - comment = options['c'] + if 'c' in options: + comment = options['c'].encode("UTF-8") modAttrs += [(ldap.MOD_REPLACE, 'sn', comment), (ldap.MOD_REPLACE, 'cn', comment)] # Изменяем пароль пользователя @@ -11766,20 +11807,20 @@ class servFtp(shareLdap): userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if resSearch[0][0][1].has_key('userPassword'): + if 'userPassword' in resSearch[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: - uid = resSearch[0][0][1]['uid'][0] - DN = self.addDN("uid="+uid, self.relUsersDN) + uid = resSearch[0][0][1]['uid'][0].decode("UTF-8") + DN = self.addDN("uid=" + uid, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified comment (full name)")) - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: self.printSUCCESS(_("Modified FTP user password")) return True @@ -11803,14 +11844,14 @@ class servFtp(shareLdap): userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if resSearch[0][0][1].has_key('userPassword'): + if 'userPassword' in resSearch[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: - uid = resSearch[0][0][1]['uid'][0] + uid = resSearch[0][0][1]['uid'][0].decode("UTF-8") DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False @@ -11832,7 +11873,7 @@ class servFtp(shareLdap): self.printERROR(_("User not exists in FTP service")) return False # FTP директория пользователя - ftpUserDir = resFtp[0][0][1]['homeDirectory'][0] + ftpUserDir = resFtp[0][0][1]['homeDirectory'][0].decode("UTF-8") ftpPath = self.clVars.Get("sr_ftp_path") if ftpUserDir == ftpPath: ftpUserDir = os.path.join(ftpPath,"pub/users",userName) @@ -11873,7 +11914,7 @@ class servFtp(shareLdap): # Флаг создания группы по умолчанию flagCreateUnixGroup = False # Группа пользователя - if options.has_key('g'): + if 'g' in options: optUnix['g'] = options['g'] else: optUnix['g'] = self.defaultUnixGroup["name"] @@ -11889,7 +11930,7 @@ class servFtp(shareLdap): if not self.servUnixObj.searchUnixGroupName(optUnix['g']): flagCreateUnixGroup = True # Полное имя пользователя - if options.has_key('c'): + if 'c' in options: optUnix['c'] = options['c'] # Если нужно создаем новую Unix группу if flagCreateUnixGroup: @@ -11910,12 +11951,12 @@ class servFtp(shareLdap): self.clVars.Set("ur_name", userName) #Полное имя пользователя fullNameUser = self.servUnixObj.fullNameUser - if options.has_key('c'): + if 'c' in options: fullNameUser = options['c'] else: - if resUnix and resUnix[0][0][1].has_key('cn'): - fullNameUser = resUnix[0][0][1]['cn'][0] - self.clVars.Set("ur_fio",fullNameUser) + if resUnix and 'cn' in resUnix[0][0][1]: + fullNameUser = resUnix[0][0][1]['cn'][0].decode("UTF-8") + self.clVars.Set("ur_fio", fullNameUser) if not userPwd: userPwdHash = "crypt{xxx}" else: @@ -11940,7 +11981,7 @@ class servFtp(shareLdap): # Корневая FTP директория ftpDir = self.clVars.Get("sr_ftp_path") # FTP директория пользователя - if options.has_key('d') and options.has_key('m'): + if 'd' in options and 'm' in options: ftpUserDir = options['d'] if ftpUserDir[0] == "/": ftpUserDir = ftpUserDir[1:] @@ -11955,14 +11996,14 @@ class servFtp(shareLdap): self.ldapObj.ldapAdd(userLdif) # не переделывать на else if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False flagError = False # FTP директория пользователя - if not options.has_key('d'): + if 'd' not in options: ftpUserDir = os.path.join(ftpDir,"pub/users",userName) # Создаем FTP директорию пользователя - if options.has_key('m'): + if 'm' in options: if not self.createUserDir(uid, gid, ftpUserDir): flagError = True if flagError: @@ -12055,7 +12096,7 @@ class servRepl(shareLdap): clVars.flServer() calculate_ini = self.clVars.Get("cl_env_path") remoteIni = "" - if calculate_ini and type(calculate_ini) == types.ListType: + if calculate_ini and type(calculate_ini) == list: remoteIni = calculate_ini[0] if remoteIni: # проверить сущестование ini файла @@ -12078,8 +12119,8 @@ class servRepl(shareLdap): # принудительно переписать все переменные окружения # полученные из ini for (k,v) in allvars.items(): - k = k.encode("UTF-8") - v = v.encode("UTF-8") + # k = k.encode("UTF-8") + # v = v.encode("UTF-8") clVars.Set(k, cl_utils.convertStrListDict(v), True) return (True, clVars) @@ -12171,8 +12212,8 @@ class servRepl(shareLdap): self.restoreLocalVar) # Получаем от пользователя доверительные сети для сервиса Samba # Переназначаем объект переменных - print _("Replications servers for Samba: %s")\ - % " ".join(replSambaServers) + print(_("Replications servers for Samba: %s")\ + % " ".join(replSambaServers)) self.servSambaObj.clVars = self.clVars if not self.servSambaObj.getAllowNet(): return False @@ -12199,8 +12240,8 @@ class servRepl(shareLdap): self.restoreRemoteClientVar = [] # Получаем от пользователя доверительные сети для сервиса Mail # Переназначаем объект переменных - print _("Replications servers for Mail: %s")\ - % " ".join(replMailServers) + print(_("Replications servers for Mail: %s")\ + % " ".join(replMailServers)) self.servMailObj.clVars = self.clVars if not self.servMailObj.getAllowNet(): return False @@ -12230,8 +12271,8 @@ class servRepl(shareLdap): self.restoreRemoteClientVar = [] # Получаем от пользователя доверительные сети для сервиса Mail # Переназначаем объект переменных - print _("Replications servers for Mail: %s")\ - % " ".join(replMailServers) + print(_("Replications servers for Mail: %s")\ + % " ".join(replMailServers)) self.servMailObj.clVars = self.clVars if not self.servMailObj.getAllowNet(): return False @@ -12247,15 +12288,15 @@ class servRepl(shareLdap): self.restoreLocalVar) # Получаем от пользователя доверительные сети для сервиса Samba # Переназначаем объект переменных - print _("Replications servers for Samba: %s")\ - % " ".join(replSambaServers) + print(_("Replications servers for Samba: %s")\ + % " ".join(replSambaServers)) self.servSambaObj.clVars = self.clVars if not self.servSambaObj.getAllowNet(): return False # Получаем от пользователя доверительные сети для сервиса Mail # Переназначаем объект переменных - print _("Replications servers for Mail: %s")\ - % " ".join(replMailServers) + print(_("Replications servers for Mail: %s")\ + % " ".join(replMailServers)) self.servMailObj.clVars = self.clVars if not self.servMailObj.getAllowNet(): return False @@ -12303,12 +12344,12 @@ class servRepl(shareLdap): # права и владелец /var/calculate/remote if os.path.exists(remotePath): os.chown(remotePath,0,int(cl.gid)) - os.chmod(remotePath,02755) + os.chmod(remotePath,0o2755) # изменяем владельца remote на client if not os.path.exists(remoteEnvFile): fd = os.open(remoteEnvFile, os.O_CREAT) os.close(fd) - os.chmod(remoteEnvFile, 0640) + os.chmod(remoteEnvFile, 0o640) if os.path.exists(remoteEnvFile): os.chown(remoteEnvFile,0,int(cl.gid)) return True @@ -12337,11 +12378,11 @@ class servRepl(shareLdap): os.path.exists(os.path.join(x, self.logOutFile)) or \ os.path.exists(os.path.join(x, self.srvFile)) or\ os.path.exists(os.path.join(x, self.deskFile)) - return filter(filterFunc, - [profileDir] + map(lambda x: os.path.join(profileDir, x),\ - filter(lambda x:\ - os.path.isdir(os.path.join(profileDir, x)) ,\ - os.listdir(profileDir)))) + return [x for x + in [profileDir] + [os.path.join(profileDir, y) + for y in os.listdir(profileDir) + if os.path.isdir(os.path.join(profileDir, y))] + if filterFunc(x)] @adminConnectLdap def deleteLogoutFile(self, userName, logoutFile): @@ -12380,7 +12421,7 @@ class servRepl(shareLdap): uid = int(resPasswd.split(":")[2]) gid = int(resPasswd.split(":")[3]) if uid == None or gid == None: - print _("User %s not found in Unix service") + print(_("User %s not found in Unix service")) return False winProfDir =\ os.path.join(self.clVars.Get("sr_samba_winprof_path"), @@ -12495,7 +12536,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False return True @@ -12525,7 +12566,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Если ветка Replication/Mail не существует - добавляем ее if not self.isReplMailDNExists(): @@ -12535,8 +12576,8 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) try: self.conLdap.add_s(self.clVars.Get("ld_repl_mail_dn"), entry) - except ldap.LDAPError, e: - self.printERROR(_("LDAP Error") + ": " + e[0]['desc'].strip()) + except ldap.LDAPError as e: + self.printERROR(_("LDAP Error") + ": " + str(e).strip()) self.printERROR(errorMessage) return False except: @@ -12550,8 +12591,8 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) try: self.conLdap.add_s(self.clVars.Get("ld_repl_worked_dn"), entry) - except ldap.LDAPError, e: - self.printERROR(_("LDAP Error") + ": " + e[0]['desc'].strip()) + except ldap.LDAPError as e: + self.printERROR(_("LDAP Error") + ": " + str(e).strip()) self.printERROR(errorMessage) return False except: @@ -12613,7 +12654,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if fullDel: foundUsers = self.searchWorkedUser(userName+"@*") if foundUsers: - deleteUserNames = map(lambda x: x[0][1]["uid"][0], foundUsers) + deleteUserNames = (x[0][1]["uid"][0] for x in foundUsers) for delUser in deleteUserNames: delDN = self.addDN("uid=" + delUser, relWorkedDN) if not self.delDN(delDN): @@ -12658,7 +12699,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) rez = self.searchMailAlias(oldName) if not rez: return True - email = rez[0][0][1]["rfc822member"][0] + email = rez[0][0][1]["rfc822member"][0].decode("UTF-8") splEmail = email.split("@") attrAppend = [] relMailDN = self.getRelMailDN() @@ -12666,9 +12707,9 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if len(splEmail)==2: emailDomen = splEmail[1] newEmail = "%s@%s" %(newName,emailDomen) - attrAppend.append((ldap.MOD_REPLACE, 'rfc822member', newEmail)) + attrAppend.append((ldap.MOD_REPLACE, 'rfc822member', newEmail.encode("UTF-8"))) attrAppend.append((ldap.MOD_REPLACE, 'mailMessageStore', - newName + "/")) + (newName + "/").encode("UTF-8"))) if not self.modAttrsDN(oldDN, attrAppend): return False newFirstDn = "cn=" + newName @@ -12683,7 +12724,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) rez = self.searchMailAlias(aliasName) if not rez: return True - if rez[0][0][1].has_key('filtersender'): + if 'filtersender' in rez[0][0][1]: attrDelete = [] relMailDN = self.getRelMailDN() aliasDN = self.addDN("cn=%s"%aliasName, relMailDN) @@ -12693,10 +12734,12 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) return True @adminConnectLdap - def modReplMailAlias(self, userName, srcMails, filterHosts=[]): + def modReplMailAlias(self, userName, srcMails, filterHosts=None): """Изменяем запись в Replication/Mail (имя пользователя, список почтовых адресов пользователя""" + if filterHosts is None: + filterHosts = [] rez = self.searchMailAlias(userName) if not rez: # Если алиас не найден создаем его @@ -12709,26 +12752,23 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) self.clVars.Set('sr_mail_host',fullHostName,True) mailHost = fullHostName # Получаем почтовые алиасы (почтовые адреса на других серверах) - userMails = filter(lambda x:\ - len(x.split("@"))==2 and x.split('@')[1] != mailHost,\ - filter(lambda x: "@" in x, srcMails)) + userMails = [x for x in (y for y in srcMails if "@" in y) + if len(x.split("@")) == 2 and x.split('@')[1] != mailHost] if userMails: # Внешний почтовый адрес пользователя (первый в списке) userMail = userMails[0] # Убирает первый адрес из списка - userMails = list(set(filter(lambda x: x != userMail, - userMails))) + userMails = list(set(x for x in userMails if x != userMail)) attrAppend = [] attrDelete = [] attrReplace = [] if filterHosts: domain = self.clVars.Get('os_net_domain') # Если необходимо добавляем домен к именам хостов - fHosts = map(lambda x: (not '.' in x and x+"."+domain) or x, - filterHosts) + fHosts = [(not '.' in x and x + "." + domain) or x for x in filterHosts] for host in fHosts: - attrAppend.append((ldap.MOD_ADD, 'filtersender', host)) - if rez[0][0][1].has_key('filtersender'): + attrAppend.append((ldap.MOD_ADD, 'filtersender', host.encode("UTF-8"))) + if 'filtersender' in rez[0][0][1]: attrDelete.append((ldap.MOD_DELETE, 'filtersender', None)) email = rez[0][0][1]["mail"][0] altEmails = rez[0][0][1]["mailAlternateAddress"] @@ -12739,31 +12779,34 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) (ldap.MOD_DELETE, 'mailAlternateAddress', altEmail)) # Заменяем первый адрес - attrReplace.append((ldap.MOD_REPLACE, 'mail',userMail)) + attrReplace.append((ldap.MOD_REPLACE, 'mail', + userMail.encode("UTF-8"))) attrReplace.append((ldap.MOD_REPLACE, 'mailAlternateAddress', - userMail)) + userMail.encode("UTF-8"))) relMailDN = self.getRelMailDN() - aliasDN = self.addDN("cn=%s"%userName,relMailDN) + aliasDN = self.addDN("cn=%s" % userName, relMailDN) # Добавляем альтернативные адреса for mail in userMails: attrAppend.append((ldap.MOD_ADD, 'mailAlternateAddress', - mail)) + mail.encode("UTF-8"))) modAttrs = attrDelete + attrReplace + attrAppend if not self.modAttrsDN(aliasDN, modAttrs): return False else: relMailDN = self.getRelMailDN() - aliasDN = self.addDN("cn=%s"%userName,relMailDN) + aliasDN = self.addDN("cn=%s" % userName, relMailDN) # Удаляем почтовый алиас if not self.delDN(aliasDN): return False return True @adminConnectLdap - def addReplMailAlias(self, userName, srcMails , filterHosts=[]): + def addReplMailAlias(self, userName, srcMails, filterHosts=None): """Добавляем запись в Replication/Mail (имя пользователя, список почтовых адресов пользователя""" + if filterHosts is None: + filterHosts = [] rez = self.searchMailAlias(userName) if not rez: ldifFile = self.ldifFileMailUser @@ -12776,36 +12819,33 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) self.clVars.Set('sr_mail_host',fullHostName,True) mailHost = fullHostName # Получаем почтовые алиасы (почтовые адреса на других серверах) - userMails = filter(lambda x:\ - len(x.split("@"))==2 and x.split('@')[1] != mailHost,\ - filter(lambda x: "@" in x, srcMails)) + userMails = [x for x in (y for y in srcMails if "@" in y) + if len(x.split("@")) == 2 and x.split('@')[1] != mailHost] if userMails: # Внешний почтовый адрес пользователя (первый в списке) userMail = userMails[0] # Убираем первый адрес из списка - userMails = list(set(filter(lambda x: x != userMail, - userMails))) + userMails = list(set(x for x in userMail if x != userMail)) self.clVars.Set("ur_mail", userMail) baseLdif = self.createLdif(ldifFile) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": "+self.ldapObj.getError().strip() + print(_("LDAP Error") + ": "+self.ldapObj.getError().strip()) return False modAttrs = [] relMailDN = self.getRelMailDN() aliasDN = self.addDN("cn=%s"%userName,relMailDN) for mail in userMails: modAttrs.append((ldap.MOD_ADD, 'mailAlternateAddress', - mail)) + mail.encode("UTF-8"))) if filterHosts: domain = self.clVars.Get('os_net_domain') # Если необходимо добавляем домен к именам хостов - fHosts = map(lambda x: (not '.' in x and x+"."+domain) or x, - filterHosts) + fHosts = [(not '.' in x and x + "." + domain) or x for x in filterHosts] for host in fHosts: modAttrs.append((ldap.MOD_ADD, 'filtersender', - host)) + host.encode("UTF-8"))) res = self.modAttrsDN(aliasDN, modAttrs) # Если ошибка то удаляем почтовый алиас if not res: @@ -12825,34 +12865,36 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False rez = self.searchWorkedUser(userName) replHost = self.clVars.Get("ld_repl_host") if not replHost: - print _("Variable Error: not set a variable ld_repl_host") + print(_("Variable Error: not set a variable ld_repl_host")) return False if rez: - host = rez[0][0][1]['host'][0] + host = rez[0][0][1]['host'][0].decode("UTF-8") if host != replHost: # Изменяемые аттрибуты - modAttrs = [(ldap.MOD_REPLACE, 'host', replHost)] + modAttrs = [(ldap.MOD_REPLACE, 'host', replHost.encode("UTF-8"))] relWorkedDN = self.getRelWorkedDN() - DN = self.addDN("uid="+userName, relWorkedDN) + DN = self.addDN("uid=" + userName, relWorkedDN) if not self.modAttrsDN(DN, modAttrs): return False else: - print _("Can not add user %s in branch 'Replication'")%userName + print(_("Can not add user %s in branch 'Replication'")%userName) return False return True - def maxDateAndListInDir(self, scanDir, listFiles, skipPathTime=[], + def maxDateAndListInDir(self, scanDir, listFiles, skipPathTime=None, checkTime=True, prefix=None, maxTime=None, flagDir=False): """Время последней модификации внутри директории scanDir Генерация списка файлов и директорий """ + if skipPathTime is None: + skipPathTime = [] startCheckTime = checkTime if not prefix: prefix = os.path.join(scanDir,"") @@ -12916,7 +12958,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) uid = int(resPasswd.split(":")[2]) gid = int(resPasswd.split(":")[3]) if uid == None or gid == None: - print _("User %s not found in Unix service") + print(_("User %s not found in Unix service")) return False linProfDir =\ os.path.join(self.clVars.Get("sr_samba_linprof_path"), @@ -13006,7 +13048,7 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios) if os.path.exists(archPathProcess): os.rename(archPathProcess, archPathSuccess) if ret: - self.printERROR(_("Can not create %s")%archPath) + self.printERROR(_("Can not create %s") % archPathTmp) return False else: return True @@ -13156,7 +13198,7 @@ remove user %s in the LDAP branch 'Worked'")%str(userName)) if supportSections: sections = list(set(sections)-set(["command"])) sections = set(sections)-set(supportSections) - delSections = map(lambda x: x.split(","), sections) + delSections = (x.split(",") for x in sections) for delSect in delSections: txtConfig.delArea(delSect) # Если включена репликация и нет команды на упаковку @@ -13212,16 +13254,16 @@ remove user %s in the LDAP branch 'Worked'")%str(userName)) errMessages = [] # Опция выключает вывод cообщений на экран verboseMode = True - if options.has_key('s'): + if 's' in options: verboseMode = False login = "" logout = "" makeDir = "" - isLogin = options.has_key('login') - isLogout = options.has_key('logout') - isMakeDir = options.has_key('makedir') + isLogin = 'login' in options + isLogout = 'logout' in options + isMakeDir = 'makedir' in options dictOpt = {"login":isLogin, "logout":isLogout, "makedir":isMakeDir} - firstOpt = filter(lambda x: x[1] ,dictOpt.items()) + firstOpt = [x for x in dictOpt.items() if x[1]] lenOpt = len(firstOpt) if lenOpt == 1: if isLogin: @@ -13332,14 +13374,14 @@ incompatible")) errMessages = [] # Опция выключает вывод cообщений на экран verboseMode = True - if options.has_key('s'): + if 's' in options: verboseMode = False logout = "" makeDir = "" - isLogout = options.has_key('logout') - isMakeDir = options.has_key('makedir') + isLogout = 'logout' in options + isMakeDir = 'makedir' in options dictOpt = {"logout":isLogout, "makedir":isMakeDir} - firstOpt = filter(lambda x: x[1] ,dictOpt.items()) + firstOpt = [x for x in dictOpt.items() if x[1]] lenOpt = len(firstOpt) if lenOpt == 1: if isLogout: @@ -13519,7 +13561,7 @@ remove user %s in the LDAP branch 'Worked'")%str(userName)) if supportSections: sections = list(set(sections)-set(["command"])) sections = set(sections)-set(supportSections) - delSections = map(lambda x: x.split(","), sections) + delSections = (x.split(",") for x in sections) for delSect in delSections: txtConfig.delArea(delSect) # Если включена репликация и нет команды на упаковку @@ -13562,20 +13604,21 @@ remove user %s in the LDAP branch 'Worked'")%str(userName)) """ varsData = ("unix_hash", "samba_lm_hash", "samba_nt_hash", "samba_nt_hash_old") - if not set(varsData)<=set(varsDict.keys()): + if not set(varsData) <= set(varsDict.keys()): notFoundVars = set(varsData) - set(varsDict.keys()) - if len(notFoundVars) 2.4)")%openLdapVesion) return False listGroupMail = [] for i in resSearch: - if i[0][1].has_key('filtersender'): + if 'filtersender' in i[0][1]: listGroupMail.append((i[0][1]["cn"][0], i[0][1]["mailAlternateAddress"], i[0][1]["filtersender"])) else: listGroupMail.append((i[0][1]["cn"][0], - i[0][1]["mailAlternateAddress"],[])) + i[0][1]["mailAlternateAddress"], [])) return listGroupMail def setupReplServer(self, options, service): @@ -13921,7 +13964,7 @@ use the new version. (openldap > 2.4)")%openLdapVesion) # Определяем поддерживает ли openldap репликацию if not self.supportReplOpenldap(self.clVars): return False - if options.has_key('off'): + if 'off' in options: if self.clVars.Get("ld_repl_set") == "off": self.printWARNING(_("Replication off for all services")) return True @@ -13944,7 +13987,7 @@ use the new version. (openldap > 2.4)")%openLdapVesion) 'cl-rebuild --repl'")) bFile = self.servLdapObj.getArchFile() if not bFile: - return Falses + return False archFileTime = time.localtime(os.stat(bFile)[stat.ST_MTIME]) timeFile = datetime.datetime(archFileTime[0],archFileTime[1], archFileTime[2],archFileTime[3], @@ -13960,9 +14003,9 @@ file %s")%bFile) deltaTime = timeLocal - timeFile if deltaTime.days == 0: deltaSec = deltaTime.seconds - dHours = int(deltaSec/3600) - dMinutes = int((deltaSec - dHours*3600)/60) - dSeconds = deltaSec - dHours*3600 - dMinutes*60 + dHours = int(deltaSec // 3600) + dMinutes = int((deltaSec - dHours * 3600) // 60) + dSeconds = deltaSec - dHours * 3600 - dMinutes * 60 hours = _("hours") minutes = _("minutes") seconds = _("seconds") @@ -13993,19 +14036,19 @@ file %s")%bFile) self.clVars.Write("ld_repl_set", "off") # Включаем репликацию self.clVars.Set("ld_repl_set", "on") - if not options.has_key('off') and\ - (not options.has_key('r') or not options['r']): + if 'off' not in options and\ + ('r' not in options or not options['r']): self.printERROR(\ _("Not specified replication servers \ (command line option '-r')")) return False - if options.has_key('off') and options.has_key('r'): + if 'off' in options and 'r' in options: self.printERROR(\ _("You can not use the option to '--off', \ together with option '-r'")) return False replServers = [] - if options.has_key('r'): + if 'r' in options: replServers = options['r'].split(',') # Преобразуем короткие имена в длинные hostName = self.clVars.Get('os_net_hostname') @@ -14032,29 +14075,28 @@ together with option '-r'")) self.printERROR(\ _("Set Replication error, Unix service not setuped")) return False - if options.has_key('r'): + if 'r' in options: replSambaServers = self.clVars.Get("ld_repl_samba_servers") replMailServers = self.clVars.Get("ld_repl_mail_servers") dictServers = {"samba":replSambaServers, "mail":replMailServers, "unix":",".join(replServers)} - listServersRepl = map(lambda x: (x[0],set(x[1].split(","))), - filter(lambda x: x[1], - dictServers.items())) + listServersRepl = [(x[0],set(x[1].split(","))) for x + in dictServers.items() if x[1]] # Все серверы репликации - replAllServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - listServersRepl,("",set()))[1]) + replAllServers = list(reduce(lambda x, y: ('', x[1] | y[1]), + listServersRepl, ("", set()))[1]) # Серверы репликации для ветки Unix - replUnixServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - filter(lambda x: x[0] in ['samba','unix'], - listServersRepl),("",set()))[1]) + replUnixServers = list(reduce(lambda x, y: ('', x[1] | y[1]), + [z for z in listServersRepl if z[0] in ['samba','unix']], + ("", set()))[1]) # Устанавливаем переменную серверы репл. для Unix сервиса self.clVars.Set("ld_repl_unix_servers", ",".join(replUnixServers),True) # Устанавливаем переменную серверы репл. для всех сервисов self.clVars.Set("ld_repl_servers", ",".join(replAllServers),True) - elif options.has_key('off'): + elif 'off' in options: # Выключаем репликацию для сервисов Samba и Mail if self.clVars.Get("ld_repl_mail_set") == "on" and\ self.clVars.Get("ld_repl_mail_servers"): @@ -14079,7 +14121,7 @@ together with option '-r'")) replUnixServers = self.clVars.Get("ld_repl_unix_servers") if replUnixServers: replUnixServers = replUnixServers.split(",") - if options.has_key('off'): + if 'off' in options: # Очищаем cерверы репликации Samba self.clVars.Set("ld_repl_samba_servers", "", True) self.clVars.Delete("ld_repl_samba_servers","local","server") @@ -14093,19 +14135,18 @@ together with option '-r'")) dictServers = {"samba":",".join(replServers), "mail":replMailServers, "unix":",".join(diffReplServers)} - listServersRepl = map(lambda x: (x[0],set(x[1].split(","))), - filter(lambda x: x[1], dictServers.items())) + listServersRepl = [(x[0], set(x[1].split(","))) for x in dictServers.items() if x[1]] # Все серверы репликации replAllServers = list(reduce(lambda x,y: ('',x[1]|y[1]), listServersRepl,("",set()))[1]) # Серверы репликации для ветки Unix - replUnixServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - filter(lambda x: x[0] in ['samba','unix'], - listServersRepl),("",set()))[1]) + replUnixServers = list(reduce(lambda x, y: ('', x[1] | y[1]), + [z for z in listServersRepl if z[0] in ['samba','unix']], + ("", set()))[1]) # Серверы репликации для ветки Samba - replSambaServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - filter(lambda x: x[0] in ['samba'], - listServersRepl),("",set()))[1]) + replSambaServers = list(reduce(lambda x, y: ('', x[1] | y[1]), + [z for z in listServersRepl if z[0] in ['samba']], + ("", set()))[1]) # Устанавливаем переменную серверы репл. для Samba сервиса self.clVars.Set("ld_repl_samba_servers", ",".join(replSambaServers),True) @@ -14124,7 +14165,7 @@ together with option '-r'")) _("Set Replication error, Mail service not setuped")) return False replUnixServers = self.clVars.Get("ld_repl_unix_servers") - if options.has_key('off'): + if 'off' in options: # Очищаем cерверы репликации Mail self.clVars.Set("ld_repl_mail_servers", "", True) self.clVars.Delete("ld_repl_mail_servers","local","server") @@ -14133,15 +14174,15 @@ together with option '-r'")) dictServers = {"samba":replSambaServers, "mail":",".join(replServers), "unix":replUnixServers} - listServersRepl = map(lambda x: (x[0],set(x[1].split(","))), - filter(lambda x: x[1], dictServers.items())) + listServersRepl = [(x[0], set(x[1].split(","))) + for x in dictServers.items() if x[1]] # Все серверы репликации - replAllServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - listServersRepl,("",set()))[1]) + replAllServers = list(reduce(lambda x,y: ('', x[1] | y[1]), + listServersRepl, ("", set()))[1]) # Серверы репликации для ветки Mail - replMailServers = list(reduce(lambda x,y: ('',x[1]|y[1]), - filter(lambda x: x[0] in ['mail'], - listServersRepl),("",set()))[1]) + replMailServers = list(reduce(lambda x,y: ('', x[1] | y[1]), + [z for z in listServersRepl if z[0] in ['mail']], + ("", set()))[1]) # Устанавливаем переменную серверы репл. для Mail сервиса self.clVars.Set("ld_repl_mail_servers", ",".join(replMailServers),True) @@ -14163,7 +14204,7 @@ together with option '-r'")) #Cоединение с Ldap (администратор) if not shareLdap.getLdapObjInFile(self): return False - if options.has_key('r'): + if 'r' in options: # Проверяем существует ли id текущего сервера if not self.clVars.Get("ld_repl_id"): self.printERROR(_("Not found 'serverID' this server")) @@ -14172,7 +14213,7 @@ together with option '-r'")) # Делаем update cервиса Samba в случае опции off и не показываем # реплицируемые серверы if service == "unix" and self.clVars.Get("sr_samba_set") == "on" and\ - options.has_key('off'): + 'off' in options: if not self.servLdapObj.updateServer({},"samba",self.clVars, [],False): return False @@ -14210,9 +14251,8 @@ together with option '-r'")) # Получаем почтовые группы groupsMail = self.getGroupsMail() # объединяет usersMail и groupsMail - usersAndGroupsMail = map(lambda x: (len(x)==2 and\ - (x[0],x[1],[])) or x, reduce(lambda x, y: x+y,\ - map(lambda x: x or [], [usersMail,groupsMail]),[])) + usersAndGroupsMail = [(len(x) == 2 and (x[0], x[1], [])) or x + for x in reduce(lambda x, y: x + y, [z or [] for z in [usersMail,groupsMail]],[])] if usersAndGroupsMail: flagError = False for name, mails, hosts in usersAndGroupsMail: @@ -14258,15 +14298,15 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): strService = self.printNameService(service) # Информация сервиса DHCP # Информация о всех сетях DHCP - if service == "dhcp" and options.has_key("n"): + if service == "dhcp" and "n" in options: dhcpObj = dncpTxt() dataNets = dhcpObj.getDataInAllSubnet() dataList = [] for net, data in dataNets: dataTmp = [] - if data.has_key('net'): + if 'net' in data: dataTmp.append(data['net'][0]) - if data.has_key('mask'): + if 'mask' in data: dataTmp.append(data['mask'][0]) if len(dataTmp) == 2: dataList.append(["%s/%s"%(dataTmp[0],\ @@ -14279,7 +14319,7 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): repObj.printReport() return True # Информация о сети DHCP - if service == "dhcp" and options.has_key("N"): + if service == "dhcp" and "N" in options: # ip сети и сетевая маска /24 net = options["N"] # cоздаем объект DHCP @@ -14339,7 +14379,7 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): return True # Информация о статическом носте DHCP - if service == "dhcp" and options.has_key("H"): + if service == "dhcp" and "H" in options: hostname = options["H"] # Проверка правильности названия хоста if '.' in hostname: @@ -14379,13 +14419,13 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): return True # Информация о всех статических хостах DHCP - if service == "dhcp" and options.has_key("hosts"): + if service == "dhcp" and "hosts" in options: dhcpObj = dncpTxt() dataHosts = dhcpObj.getDataInAllHost() dataList = [] for hostname, data in dataHosts: ip = "" - if data.has_key("fixed-address"): + if "fixed-address" in data: if data["fixed-address"]: ip = data["fixed-address"][0] dataList.append([hostname,ip]) @@ -14398,8 +14438,8 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): return True # Информация о DNS - if service == "dns" and options.has_key("z") or options.has_key("Z") or\ - options.has_key("r"): + if service == "dns" and "z" in options or "Z" in options or\ + "r" in options: # cоздаем объект DNS servDnsObj = servDns() # Проверим установлен ли сервис dns @@ -14407,9 +14447,9 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): return False objTxtZone = dnsTxt() # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # Информация о всех DNS зонах - if service == "dns" and options.has_key("z"): + if service == "dns" and "z" in options: # Зоны в файле namesZonesFile = objTxtZone.getAllNamesZones() if namesZonesFile == False: @@ -14417,15 +14457,13 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): # Зоны в LDAP namesZonesLDAP = servDnsObj.searchAllZonesInLDAP() # Подчиненные зоны - slaveZones = list(set(namesZonesFile)-set(namesZonesLDAP)) + slaveZones = list(set(namesZonesFile) - set(namesZonesLDAP)) # Обратные зоны if namesZonesLDAP: namesZonesLDAP.sort() - reverseZones = filter(lambda x: '.in-addr.arpa' in x,\ - namesZonesLDAP) + reverseZones = [x for x in namesZonesLDAP if '.in-addr.arpa' in x] # Прямые зоны - forwardZones = filter(lambda x: not '.in-addr.arpa' in x,\ - namesZonesLDAP) + forwardZones = [x for x in namesZonesLDAP if '.in-addr.arpa' not in x] # Формирование строки для отчета title=_("Information about the master DNS zones in LDAP") headerList = [_("DNS zone"), @@ -14434,12 +14472,10 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): # Получение домена getDomain = lambda x: not '.in-addr.arpa' in x and x or "" # Получение сети - getNet = lambda x: ".".join(map(lambda x:x,\ - reversed('.in-addr.arpa' in x and ["0/24"] +\ - x.rpartition(".in-addr.arpa")[0].split(".") or []))) - dataList = map(lambda x:\ - [x, getDomain(x), getNet(x)],\ - forwardZones + reverseZones) + getNet = lambda x: ".".join(x for x + in reversed('.in-addr.arpa' in x and ["0/24"] +\ + x.rpartition(".in-addr.arpa")[0].split(".") or [])) + dataList = [[x, getDomain(x), getNet(x)] for x in forwardZones + reverseZones] repObj = report(title, headerList, dataList) repObj.printReport() if slaveZones: @@ -14454,30 +14490,26 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): if xmlNodes: masterIPNode = xmlNodes[0] xmlNodes = xpath.Evaluate( "child::value", masterIPNode) - ips = map(lambda x: x.firstChild.nodeValue.strip(),\ - xmlNodes) + ips = (firstChild(x).text.strip() for x in xmlNodes) flagAddIPs = True slaveIPs.append(",".join(ips)) if not flagAddIPs: slaveIPs.append("") - reverseZones = filter(lambda x: '.in-addr.arpa' in x,\ - slaveZones) + reverseZones = [x for x in slaveZones if '.in-addr.arpa' in x] # Прямые зоны - forwardZones = filter(lambda x: not '.in-addr.arpa' in x,\ - slaveZones) + forwardZones = [x for x in slaveZones if '.in-addr.arpa' not in x] # Формирование строки для отчета title=_("Information about the slave DNS zones in \ -/etc/bind/named.conf") + /etc/bind/named.conf") headerList = [_("DNS zone"),_("IP master DNS servers")] - dataList = map(lambda x: [x], forwardZones + reverseZones) - dataList = map(lambda x: dataList[x]+[slaveIPs[x]],\ - range(len(dataList))) + dataList = [[x] for x in forwardZones + reverseZones] + dataList = [dataList[x] + [slaveIPs[x]] for x in range(len(dataList))] repObj = report(title, headerList, dataList) - print "" + print("") repObj.printReport() return True # Информация о DNS зоне - if service == "dns" and options.has_key("Z"): + if service == "dns" and "Z" in options: zoneName = options["Z"] if not zoneName: self.printERROR(_('Incorrect zone name')) @@ -14523,15 +14555,13 @@ class cl_info(cl_utils2.cl_smartcon, prnServ): if xmlNodes: masterIPNode = xmlNodes[0] xmlNodes = xpath.Evaluate( "child::value", masterIPNode) - ipMasterServers = map(lambda x:\ - x.firstChild.nodeValue.strip(),\ - xmlNodes) + ipMasterServers = [firstChild(x).text.strip() for x in xmlNodes] if not ipMasterServers: self.printERROR(_("The program does not support information \ -for %s DNS zone")%zoneName) + for %s DNS zone")%zoneName) return False title=_("Information about slave DNS zone %s in \ -/etc/bind/named.conf") %zoneName + /etc/bind/named.conf") %zoneName headerList = [_("Field"), _("Value")] flagF = True dataList = [] @@ -14550,16 +14580,16 @@ for %s DNS zone")%zoneName) self.printERROR(_("Can not found SOA-record in zone %s")\ %zoneName) return False - soaRecord = zoneData[0][0][1]['sOARecord'][0] + soaRecord = zoneData[0][0][1]['sOARecord'][0].decode("UTF-8") # Все авторитативные сервера зоны nSRecords = zoneData[0][0][1]['nSRecord'] mXRecords = [] - if zoneData[0][0][1].has_key('mXRecord'): + if 'mXRecord' in zoneData[0][0][1]: mXRecords = zoneData[0][0][1]['mXRecord'] aRecords = [] - if zoneData[0][0][1].has_key('aRecord'): + if 'aRecord' in zoneData[0][0][1]: aRecords = zoneData[0][0][1]['aRecord'] - soaData = map(lambda x: delDot(x), soaRecord.split(" ")) + soaData = [delDot(x) for x in soaRecord.split(" ")] if len(soaData)!=7: self.printERROR(_("Incorrect SOA-record in DNS zone %s")\ %zoneName) @@ -14591,14 +14621,14 @@ for %s DNS zone")%zoneName) [_("Expiry"), expiry], [_("Minimum"), minimum]] if mXRecords: - map(lambda x:dataList.insert(2,["",x]) ,reversed(mXRecords[1:])) - dataList.insert(2,[_("MX-record"), mXRecords[0]]) + [dataList.insert(2, ["", x.decode("UTF-8")]) for x in reversed(mXRecords[1:])] + dataList.insert(2,[_("MX-record"), mXRecords[0].decode("UTF-8")]) if aRecords: - map(lambda x:dataList.insert(2,["",x]) ,reversed(aRecords[1:])) - dataList.insert(2,[_("A-record"), aRecords[0]]) + [dataList.insert(2, ["", x.decode("UTF-8")]) for x in reversed(aRecords[1:])] + dataList.insert(2,[_("A-record"), aRecords[0].decode("UTF-8")]) if nSRecords: - map(lambda x:dataList.insert(2,["",x]), reversed(nSRecords[1:])) - dataList.insert(2,[_("NS-record"), nSRecords[0]]) + [dataList.insert(2, ["", x.decode("UTF-8")]) for x in reversed(nSRecords[1:])] + dataList.insert(2,[_("NS-record"), nSRecords[0].decode("UTF-8")]) repObj = report(title, headerList, dataList) repObj.printReport() recordsSearch = servDnsObj.searchAllRecordInZone(zoneName) @@ -14610,16 +14640,16 @@ for %s DNS zone")%zoneName) dataMXList = [] for record in recordsSearch: domainName = "%s.%s"\ - %(record[0][1]["relativeDomainName"][0],\ + %(record[0][1]["relativeDomainName"][0].decode("UTF-8"),\ zoneName) - if record[0][1].has_key("aRecord"): + if "aRecord" in record[0][1]: dataAList.append([domainName, - record[0][1]["aRecord"][0]]) - if record[0][1].has_key("mXRecord"): + record[0][1]["aRecord"][0].decode("UTF-8")]) + if "mXRecord" in record[0][1]: flagFirst = True flagError = False for mxData in record[0][1]["mXRecord"]: - mxDataSpl = mxData.split(" ") + mxDataSpl = mxData.decode("UTF-8").split(" ") if len(mxDataSpl) != 2: flagError = True break @@ -14638,10 +14668,10 @@ for %s DNS zone")%zoneName) _("Incorrect MX-records in A-record %s")\ %domainName) return False - elif record[0][1].has_key("cNAMERecord"): + elif "cNAMERecord" in record[0][1]: dataCNList.append([domainName, - delDot(record[0][1]["cNAMERecord"][0])]) - allDataList = [dataAList, dataCNList,dataMXList] + delDot(record[0][1]["cNAMERecord"][0].decode("UTF-8"))]) + allDataList = [dataAList, dataCNList, dataMXList] allRecordList = ["A","CNAME","MX"] allHeaderList = [(_("Domain"), "ip"), (_("Domain"), _("CNAME Domain")), @@ -14650,29 +14680,29 @@ for %s DNS zone")%zoneName) for i in range(len(allRecordList)): if allDataList[i]: title=_("Information about %s-records")\ - %allRecordList[i] + " " +\ - _("in master DNS zone %s")%zoneName + % allRecordList[i] + " " +\ + _("in master DNS zone %s") % zoneName headerList = allHeaderList[i] dataList = allDataList[i] repObj = report(title, headerList, dataList) - print "" + print("") repObj.printReport() # Если обратная зона else: dataPTRList = [] # Получение из названия зоны cтроки из 3-х частей IP - getThreeOctetsIP = lambda x: ".".join(map(lambda x:x,\ - reversed('.in-addr.arpa' in x and\ - x.rpartition(".in-addr.arpa")[0].split(".") or []))) + getThreeOctetsIP = lambda x: ".".join(x + for x in reversed('.in-addr.arpa' in x and\ + x.rpartition(".in-addr.arpa")[0].split(".") or [])) threeOctetsIP = getThreeOctetsIP(zoneName) if not threeOctetsIP: - self.printERROR(_("Incorrect zone name %s")%zoneName) + self.printERROR(_("Incorrect zone name %s") % zoneName) return False for record in recordsSearch: - if record[0][1].has_key("pTRRecord"): + if "pTRRecord" in record[0][1]: IP = "%s.%s"%(threeOctetsIP,\ - record[0][1]["relativeDomainName"][0]) - domainName = delDot(record[0][1]["pTRRecord"][0]) + record[0][1]["relativeDomainName"][0].decode("UTF-8")) + domainName = delDot(record[0][1]["pTRRecord"][0].decode("UTF-8")) dataPTRList.append([IP, domainName]) if dataPTRList: title=_("Information about %s-records")\ @@ -14681,11 +14711,11 @@ for %s DNS zone")%zoneName) headerList = ("ip", _("Domain")) dataList = dataPTRList repObj = report(title, headerList, dataList) - print "" + print("") repObj.printReport() return True # Информация о DNS записи - if service == "dns" and options.has_key("r"): + if service == "dns" and "r" in options: hostOrIP = options["r"] # Флаг True - hostOrIP является хостом hostInForwardZone = servDnsObj.isForwardName(hostOrIP) @@ -14696,7 +14726,7 @@ for %s DNS zone")%zoneName) headerList = [_("Field"), _("Value")] dataList = [] # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # hostOrIP является именем хоста if hostInForwardZone: domainName = delDot(hostOrIP.lower()) @@ -14713,10 +14743,10 @@ for %s DNS zone")%zoneName) flagF = True for record in dataRecords: dataList.append([_("Domain name"), domainName]) - if record[0][1].has_key("aRecord"): + if "aRecord" in record[0][1]: dataList.append([_("A-record"),\ - record[0][1]["aRecord"][0]]) - if record[0][1].has_key("mXRecord"): + record[0][1]["aRecord"][0].decode("UTF-8")]) + if "mXRecord" in record[0][1]: flagFirst = True flagError = False for mxData in record[0][1]["mXRecord"]: @@ -14725,28 +14755,28 @@ for %s DNS zone")%zoneName) flagError = True break if flagFirst: - dataList.append([_("MX-record") ,mxData]) + dataList.append([_("MX-record"), mxData.decode("UTF-8")]) flagFirst = False else: - dataList.append(["", mxData]) + dataList.append(["", mxData.decode("UTF-8")]) if flagError: self.printERROR(\ _("Incorrect MX-records in A-record %s")\ - %domainName) + % domainName) return False typeRecord = "A" - elif record[0][1].has_key("cNAMERecord"): + elif "cNAMERecord" in record[0][1]: dataList.append([_("CNAME-record"),\ - record[0][1]["cNAMERecord"][0]]) + record[0][1]["cNAMERecord"][0].decode("UTF-8")]) typeRecord = "CNAME" title=_("Information about %s-record")\ %typeRecord + " " +\ - _("in master DNS zone %s")%zoneName + _("in master DNS zone %s") % zoneName repObj = report(title, headerList, dataList) if flagF: flagF = False else: - print "" + print("") repObj.printReport() # hostOrIP является ip else: @@ -14760,7 +14790,7 @@ for %s DNS zone")%zoneName) self.printERROR(_("IP address %s incorrectly")%ip) return False hostNamePTR, domainNamePTR, zoneNamePTR = dataIP - dataRecords=servDnsObj.searchAllDomainNamesInLDAP(domainNamePTR) + dataRecords = servDnsObj.searchAllDomainNamesInLDAP(domainNamePTR) if not dataRecords: self.printERROR(_("Record %s not exists in LDAP")\ %domainNamePTR) @@ -14769,8 +14799,8 @@ for %s DNS zone")%zoneName) typeRecord = "Unknown" for record in dataRecords: dataList.append(["ip", ip]) - if record[0][1].has_key("pTRRecord"): - domainNameDot = record[0][1]["pTRRecord"][0] + if "pTRRecord" in record[0][1]: + domainNameDot = record[0][1]["pTRRecord"][0].decode("UTF-8") dataList.append([_("PTR-record"), domainNameDot]) typeRecord = "PTR" title=_("Information about %s-record")\ @@ -14780,77 +14810,76 @@ for %s DNS zone")%zoneName) if flagF: flagF = False else: - print "" + print("") repObj.printReport() return True # Информация о компьютере - if options.has_key("M"): + if "M" in options: machineName = options["M"] data = self.getMachine(machineName, service) if not data: return False headerList, dataList = data - title=_("Information about machine %s") %machineName + " " +\ - _("for service %s") %strService + title=_("Information about machine %s") % machineName + " " +\ + _("for service %s") % strService # Информация о пользователе - elif options.has_key("U"): + elif "U" in options: userName = options["U"] data = self.getUser(userName, service) if not data: return False headerList, dataList = data - title=_("Information about user %s") %userName + " " +\ - _("for service %s") %strService + title=_("Information about user %s") % userName + " " +\ + _("for service %s") % strService # Информация о группе - elif options.has_key("G"): + elif "G" in options: groupName = options["G"] data = self.getGroup(groupName, service) if not data: return False headerList, dataList = data - title=_("Information about group %s") %groupName + " " +\ - _("for service %s") %strService + title=_("Information about group %s") % groupName + " " +\ + _("for service %s") % strService # Информация о компьютерах - elif options.has_key("m"): + elif "m" in options: fields = "short" - if options.has_key("full"): + if "full" in options: fields = "full" data = self.getAllMachines(fields, service) if not data: return False headerList, dataList = data - title=_("All machines in LDAP for service %s")%strService + title=_("All machines in LDAP for service %s") % strService # Информация о пользователях - elif options.has_key("u"): + elif "u" in options: fields = "short" - if options.has_key("full"): + if "full" in options: fields = "full" data = self.getAllUsers(fields, service) if not data: return False headerList, dataList = data - title=_("All users in LDAP for service %s")%strService + title=_("All users in LDAP for service %s") % strService # Информация о группах - elif options.has_key("g"): + elif "g" in options: fields = "short" - if options.has_key("full"): + if "full" in options: fields = "full" data = self.getAllGroups(fields, service) if not data: return False headerList, dataList = data - title=_("All groups in LDAP for service %s")%strService + title=_("All groups in LDAP for service %s") % strService - if options.has_key("M") or options.has_key("m") or\ - options.has_key("U") or options.has_key("G") or\ - options.has_key("u") or options.has_key("g"): + if "M" in options or "m" in options or\ + "U" in options or "G" in options or\ + "u" in options or "g" in options: repObj = report(title, headerList, dataList) repObj.printReport() return True - if len(options) == 1 and options.has_key("full"): - + if len(options) == 1 and "full" in options: self.printERROR(_("Can not use a single command line option \ 'full'.")) self.printERROR(_("This option should be used in conjunction \ @@ -14865,23 +14894,23 @@ with another option.")) branchData = {'users':'relUsersDN', 'groups':'relGroupsDN', 'computers':'relComputersDN'} - if not branchData.has_key(branch): - self.printERROR("getQueryLDAP service=%s"%service) - self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s")%branch) + if branch not in branchData: + self.printERROR("getQueryLDAP service=%s" % service) + self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s") % branch) return False relAttr = branchData[branch] try: - exec ("servObj=serv%s()" %service.capitalize()) + servObj = eval("serv%s()" %service.capitalize()) except: self.printERROR(\ - _("ERROR: getQueryLDAP incorrect service=%s")%service) + _("ERROR: getQueryLDAP incorrect service=%s") % service) return False # Если сервис не установлен то ошибка if not servObj.isServiceSetup(service): return False - if not servObj.__dict__.has_key(relAttr): - self.printERROR("getQueryLDAP service=%s"%service) - self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s")%branch) + if relAttr not in servObj.__dict__: + self.printERROR("getQueryLDAP service=%s" % service) + self.printERROR(_("ERROR: getQueryLDAP incorrect branch=%s") % branch) return False searchRes = servObj.searchLdapDN(searchStr, getattr(servObj, relAttr), searchAttr, retrAttrs) @@ -14903,9 +14932,9 @@ with another option.")) %self.printNameService(service)) return False headers = [_("Field"),_("Value")] - attributes = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) - retClVars=False + attributes = [x[0] for x in data] + retrAttrs = [x[1] for x in data] + retClVars = False searchRes = self.getQueryLDAP(service, "computers", searchAttr, searchStr, retrAttrs) if searchRes == False: @@ -14921,8 +14950,9 @@ with another option.")) if attr in info[0][1]: ldapValue = info[0][1][attr] # Изменяем значения аттрибутов для вывода на печать + #modUserAttr already decodes ldapValue[0] = self.modUserAttr(attr, ldapValue[0], - service) + service) flagFirst = False for value in ldapValue: if not flagFirst: @@ -14936,14 +14966,14 @@ with another option.")) attrApp = _("Supplementary groups") if service == "samba": if value: - memberGroups.insert(0,value) + memberGroups.insert(0, value) flagFirst = False - for value in memberGroups: + for member_group in memberGroups: if not flagFirst: - data.append((attrApp, value)) + data.append((attrApp, member_group)) flagFirst = True else: - data.append(("", value)) + data.append(("", member_group)) else: data.append((attrName, _("No"))) return (headers, data) @@ -14958,8 +14988,8 @@ with another option.")) %self.printNameService(service)) return False headers = [_("Field"),_("Value")] - attributes = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + attributes = [x[0] for x in data] + retrAttrs = [x[1] for x in data] retClVars=False searchRes = self.getQueryLDAP(service, "groups", searchAttr, searchStr, retrAttrs) @@ -14970,7 +15000,7 @@ with another option.")) if service == "proxy": for i in searchRes: memberList = i[0][1]['member'] - i[0][1]['member']=map(lambda x: x.partition("=")[2],memberList) + i[0][1]['member'] = [x.partition(b"=")[2] for x in memberList] if service == "jabber": servObj = servJabber() resMemberSearch = servObj.searchUsersToGroup(groupName) @@ -14980,23 +15010,23 @@ with another option.")) memberUid.append(dataGroup[0][1]['uid'][0]) for i in searchRes: i[0][1]['memberUid'] = memberUid - data.append((_("Member UID"),"memberUid")) - attributes = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + data.append((_("Member UID"), "memberUid")) + attributes = [x[0] for x in data] + retrAttrs = [x[1] for x in data] data = [] lenRetrAttrs = len(retrAttrs) # Добавляем первичные группы if service in ("unix", "samba"): memberUid = [] - if searchRes[0][0][1].has_key('memberUid'): + if 'memberUid' in searchRes[0][0][1]: memberUid = searchRes[0][0][1]['memberUid'] - groupId = searchRes[0][0][1]['gidNumber'][0] + groupId = searchRes[0][0][1]['gidNumber'][0].decode("UTF-8") primaryUids = self.getUnixUidPrimGroup(groupId) - memberUid = primaryUids + memberUid + memberUid = [x.encode("UTF-8") for x in primaryUids] + memberUid uniqueUid = [] # Удаляем одинаковые элементы for uid in memberUid: - if not uid in uniqueUid: + if uid not in uniqueUid: uniqueUid.append(uid) if uniqueUid: searchRes[0][0][1]['memberUid'] = uniqueUid @@ -15008,6 +15038,7 @@ with another option.")) ldapValue = info[0][1][attr] # Изменяем значения аттрибутов для вывода на печать for i in range(len(ldapValue)): + #modGroupAttr already decodes ldapValue[i] = self.modGroupAttr(attr, ldapValue[i], service) flagFirst = False @@ -15032,11 +15063,11 @@ with another option.")) %self.printNameService(service)) return False headers = [_("Field"), _("Value")] - attributes = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) - retClVars=False + attributes = [x[0] for x in data] + retrAttrs = [x[1] for x in data] + retClVars = False if service in ["mail", "samba"]: - retClVars=True + retClVars = True searchRes = self.getQueryLDAP(service, "users", searchAttr, searchStr, retrAttrs, retClVars) if searchRes == False: @@ -15051,7 +15082,7 @@ with another option.")) if service == "mail": for i in searchRes: i[0][1]['homeDirectory'] = [os.path.join(\ - clVars.Get("sr_mail_path"),i[0][1]['uid'][0])] + clVars.Get("sr_mail_path").encode("UTF-8"), i[0][1]['uid'][0])] data.append((_("Home directory"),"homeDirectory")) # Добавляем директории пользователя для сервиса samba # а так же первичную и дополнительные группы @@ -15066,14 +15097,14 @@ with another option.")) #i[0][1]['uidNumber'] = [uidNumber] #data.insert(0,(_("ID"),"uidNumber")) - gidNumber = searchResUnix[0][0][1]['gidNumber'][0] + gidNumber = searchResUnix[0][0][1]['gidNumber'][0].decode("UTF-8") #sambaGroup = servObj.searchSambaGid(gidNumber) #if sambaGroup: i[0][1]['gidNumber'] = [gidNumber] data.append((_("Primary group"),"gidNumber")) homePath = os.path.join(\ clVars.Get("sr_samba_home_path"), - i[0][1]['uid'][0]) + i[0][1]['uid'][0].decode("UTF-8")) if os.path.exists(homePath): i[0][1]['homePath'] = [homePath] data.append((_("Home directory"),"homePath")) @@ -15083,24 +15114,24 @@ with another option.")) data.append((_("Share directory"),"sharePath")) linProfPath = os.path.join(\ clVars.Get("sr_samba_linprof_path"), - i[0][1]['uid'][0]) + i[0][1]['uid'][0].decode("UTF-8")) if os.path.exists(linProfPath): i[0][1]['linProfPath'] = [linProfPath] data.append((_("Linux profile"),"linProfPath")) winProfPath = os.path.join(\ clVars.Get("sr_samba_winprof_path"), - i[0][1]['uid'][0]) + i[0][1]['uid'][0].decode("UTF-8")) if os.path.exists(winProfPath): i[0][1]['winProfPath'] = [winProfPath] data.append((_("Windows profile"),"winProfPath")) winLogonPath = os.path.join(\ clVars.Get("sr_samba_winlogon_path"), - i[0][1]['uid'][0]) + i[0][1]['uid'][0].decode("UTF-8")) if os.path.exists(winLogonPath): i[0][1]['winLogonPath'] = [winLogonPath] data.append((_("Windows logon"),"winLogonPath")) - attributes = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + attributes = [x[0] for x in data] + retrAttrs = [x[1] for x in data] data = [] lenRetrAttrs = len(retrAttrs) @@ -15166,9 +15197,9 @@ with another option.")) %self.printNameService(service)) return False if fields == "short": - data = filter(lambda x: not x[0] in delData, data) - headers = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + data = [x for x in data if x[0] not in delData] + headers = [x[0] for x in data] + retrAttrs = [x[1] for x in data] machines = [] searchRes = self.getQueryLDAP(service, "computers", searchAttr, searchStr, retrAttrs) @@ -15203,9 +15234,9 @@ with another option.")) %self.printNameService(service)) return False if fields == "short": - data = filter(lambda x: not x[0] in delData, data) - headers = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + data = [x for x in data if x[0] not in delData] + headers = [x[0] for x in data] + retrAttrs = [x[1] for x in data] groups = [] searchRes = self.getQueryLDAP(service, "groups", searchAttr, searchStr, retrAttrs) @@ -15215,15 +15246,14 @@ with another option.")) return (headers , []) for info in searchRes: if service in ("proxy",): - if info[0][1].has_key('member'): + if 'member' in info[0][1]: memberList = info[0][1]['member'] - info[0][1]['member'] = map(lambda x: x.partition("=")[2],\ - memberList) + info[0][1]['member'] = [x.partition("=")[2] for x in memberList] listAttr = [] # Добавляем первичные группы if service in ("unix", "samba"): memberUid = [] - if info[0][1].has_key('memberUid'): + if 'memberUid' in info[0][1]: memberUid = info[0][1]['memberUid'] groupId = info[0][1]['gidNumber'][0] primaryUids = self.getUnixUidPrimGroup(groupId) @@ -15382,9 +15412,9 @@ with another option.")) %self.printNameService(service)) return False if fields == "short": - data = filter(lambda x: not x[0] in delData, data) - headers = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + data = [x for x in data if x[0] not in delData] + headers = [x[0] for x in data] + retrAttrs = [x[1] for x in data] loginsUsers = [] retClVars=False @@ -15403,13 +15433,13 @@ with another option.")) # Добавляем директорию хранения писем для сервиса mail for i in searchRes: i[0][1]['homeDirectory'] = [os.path.join(\ - clVars.Get("sr_mail_path"),i[0][1]['uid'][0])] - data.append((_("Home directory"),"homeDirectory")) + clVars.Get("sr_mail_path"), i[0][1]['uid'][0].decode("UTF-8"))] + data.append((_("Home directory"), "homeDirectory")) delData.append(_("Home directory")) if fields == "short": - data = filter(lambda x: not x[0] in delData, data) - headers = map(lambda x: x[0], data) - retrAttrs = map(lambda x: x[1], data) + data = [x for x in data if x[0] not in delData] + headers = [x[0] for x in data] + retrAttrs = [x[1] for x in data] for info in searchRes: listAttr = [] for attr in retrAttrs: @@ -15435,18 +15465,18 @@ with another option.")) users = [] if searchUsers: for dataUser in searchUsers: - users.append(dataUser[0][1]['uid'][0]) + users.append(dataUser[0][1]['uid'][0].decode("UTF-8")) return users def modGroupAttr(self, attr, value, service): """Модифицирует аттрибуты группы для вывода на печать""" - retValue = value + retValue = value.decode("UTF-8") if isinstance(value, bytes) else value # Заменяем mail на имя пользователя if service == "mail" and attr == "rfc822member": servObj = servMail() searchUser = servObj.searchUserToMail(value) if searchUser: - retValue = searchUser[0][0][1]['uid'][0] + retValue = searchUser[0][0][1]['uid'][0].decode("UTF-8") else: retValue = "Not found" # Заменяем тип группы названием типа @@ -15462,65 +15492,66 @@ with another option.")) def modUserAttr(self, attr, value, service): """Модифицирует аттрибуты пользователя для вывода на печать""" # Конвертируем время в текстовый формат - retValue = value + retValue = value.decode("UTF-8") if isinstance(value, bytes) else value if attr == "shadowLastChange" or\ attr == "sambaPwdLastSet": retValue = self._convDatatoStr(value) # Находим имя группы elif attr == "gidNumber" and service in ("unix", "ftp"): - retValue = self._getUserGroupName(value, "unix") + retValue = self._getUserGroupName(retValue, "unix") elif attr == "gidNumber" and service in ("samba",): - retValue = self._getUserGroupName(value, service) + retValue = self._getUserGroupName(retValue, service) # Ставим Y в случае выставленного флага elif attr == "initials": - if value == "No": + if retValue == "No": retValue = _("Yes") else: retValue = _("No") elif attr == "accountStatus": - if value == "passive": + if retValue == "passive": retValue = _("Yes") else: retValue = _("No") elif attr == "shadowExpire": - if value == "1": + if retValue == "1": retValue = _("Yes") else: retValue = _("No") elif attr == "sambaAcctFlags": - if "D" in value: + if "D" in retValue: retValue = _("Yes") else: retValue = _("No") elif attr == "userPassword": - if value == "crypt{xxx}": + if retValue == "crypt{xxx}": retValue = _("No") else: retValue = _("Yes") elif attr == "shadowFlag": - if value == "1": + if retValue == "1": retValue = _("Yes") else: retValue = _("No") elif attr == "sambaNTPassword": retValue = _("Yes") - return retValue + return retValue.decode("UTF-8") if isinstance(retValue, bytes) else retValue def _convDatatoStr(self, dataDays): """Конвертирует количество дней или секунд с 1970, в строку даты""" if dataDays: if len(str(dataDays)) <= 6: - value = long(dataDays)*86400 + value = int(dataDays) * 86400 elif len(str(dataDays)) > 6: - value = long(dataDays) - return reduce(lambda x,y: y+"."+x,map(lambda x: (len(str(x))==1 and\ - "0"+str(x)) or str(x), time.localtime(value)[:3])) + value = int(dataDays) + return reduce(lambda x,y: y + "." + x, [(len(str(x)) == 1 + and "0" + str(x)) or str(x) + for x in time.localtime(value)[:3]]) return "" def _getUserGroupName(self, userGid, service): """Находит имя группы по ее номеру""" try: - exec ("servObj=serv%s()" %service.capitalize()) + servObj = eval("serv%s()" % service.capitalize()) except: self.printERROR(\ _("ERROR: _getUserGroupName incorrect service=%s")%service) @@ -15528,7 +15559,7 @@ with another option.")) if service == "unix": retCondUnix, userGidNamesLdap, errMessUnix =\ servObj.searchGroupsUnix([userGid], False) - userGidNamesLdap = userGidNamesLdap.keys() + userGidNamesLdap = list(userGidNamesLdap.keys()) userGidNamesPasswd = servObj.searchGroupsGroups([userGid], False) if userGidNamesPasswd: #Имя группы пользователя @@ -15542,7 +15573,7 @@ with another option.")) if service == "samba": retCondSamba, userGidNamesLdap, errMessUnix =\ servObj.searchGroupsSamba([userGid], False) - userGidNamesLdap = userGidNamesLdap.keys() + userGidNamesLdap = list(userGidNamesLdap.keys()) if userGidNamesLdap: #Имя группы пользователя groupName = userGidNamesLdap[0] @@ -15554,7 +15585,7 @@ with another option.")) def _getUserMemberGroups(self, userName, service): """Находит имена групп в которые входит пользователь""" try: - exec ("servObj=serv%s()" %service.capitalize()) + servObj = eval("serv%s()" % service.capitalize()) except: self.printERROR(\ _("ERROR: _getUserGroupsNames incorrect service=%s")%service) @@ -15563,15 +15594,15 @@ with another option.")) if service == "unix": userInGroups = servObj.searchUnixMemberGid(userName) for group in userInGroups: - memberGroups.append(group[0][1]['cn'][0]) + memberGroups.append(group[0][1]['cn'][0].decode("UTF-8")) if service == "samba": userInGroups = servObj.searchSambaMemberGid(userName) for group in userInGroups: - memberGroups.append(group[0][1]['cn'][0]) + memberGroups.append(group[0][1]['cn'][0].decode("UTF-8")) if service == "proxy": userInGroups = servObj.searchMemberGroups(userName) for group in userInGroups: - memberGroups.append(group[0][1]['cn'][0]) + memberGroups.append(group[0][1]['cn'][0].decode("UTF-8")) if service == "mail": resSearch = servObj.searchMailMember(userName) if not resSearch: @@ -15582,8 +15613,9 @@ with another option.")) altMailGroup = group[0][1]['mailAlternateAddress'] listMail = mailGroup + altMailGroup for mail in listMail: - if not mail in memberGroups: - memberGroups.append(mail) + mail_decoded = mail.decode("UTF-8") + if mail_decoded not in memberGroups: + memberGroups.append(mail_decoded) return memberGroups class servProxy(shareLdap): @@ -15662,20 +15694,20 @@ class servProxy(shareLdap): def filterProxyServer(self, options): """Фильтр Proxy групп для доступа пользователя""" optPwd = ["p","P"] - listOptPwd = filter(lambda x: x in optPwd, options.keys()) + listOptPwd = [x for x in options.keys() if x in optPwd] if len(listOptPwd) > 1: self.printERROR(_("Command line options '-p' and '-P' are \ incompatible, use one of the options")) return False - if not (options.has_key("s") and options.has_key("b") and\ - (options.has_key("p") or options.has_key("P"))): + if not ("s" in options and "b" in options and\ + ("p" in options or "P" in options)): self.printERROR(_("Not found the options '-s' and '-b' and ('-p' \ or '-P')")) return False adminDn = options['s'] - if options.has_key("p"): + if "p" in options: adminPw = options['p'] - elif options.has_key("P"): + elif "P" in options: pathPasswd = options['P'] if os.path.exists(pathPasswd): try: @@ -15696,7 +15728,7 @@ or '-P')")) try: strInput = sys.stdin.readline() strInput = strInput[:-1] - params = map(lambda x: x, strInput.split(" ")) + params = strInput.split(" ") if params == ['']: sys.stdout.write("ERR\n") sys.stdout.flush() @@ -15724,7 +15756,7 @@ or '-P')")) def searchProxyGroups(self, groupNames): """Ищет группы. Находит все группы - True иначе - False""" - notFindGroup=filter(lambda x: not self.searchGroupToName(x), groupNames) + notFindGroup = [x for x in groupNames if not self.searchGroupToName(x)] if notFindGroup: self.printERROR(_("Groups %s is not found in Proxy service")\ %", ".join(notFindGroup)) @@ -15752,13 +15784,13 @@ or '-P')")) self.clVars.Set("ur_group",groupName) # Комментарий к группе groupGecos = self.servUnixObj.groupGecos - if options.has_key('c'): + if 'c' in options: groupGecos = options['c'] self.clVars.Set("ur_group_comment",groupGecos) # Тип группы groupType = "port" accessPorts = "" - if options.has_key('p'): + if 'p' in options: accessPorts = options['p'] reFalseString = re.compile("[^\d,\-]|^,|^-|,-|-,|,$|-$") if reFalseString.search(accessPorts): @@ -15773,12 +15805,12 @@ is not valid ") %accessPorts) ldifFile = self.ldifFileGroup groupLdif = self.createLdif(ldifFile) if not groupLdif: - print self.getError() + print(self.getError()) return False if not self.ldapObj.getError(): self.ldapObj.ldapAdd(groupLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printSUCCESS(_("Added group '%s' in Proxy service")\ %groupName) @@ -15798,9 +15830,9 @@ is not valid ") %accessPorts) groupName = group[0][1]['cn'][0] lenMember = len(group[0][1]['member']) if lenMember == 1: - modAttrs = [(ldap.MOD_REPLACE, 'member', "")] + modAttrs = [(ldap.MOD_REPLACE, 'member', b"")] else: - modAttrs = [(ldap.MOD_DELETE, 'member', "uid="+userName)] + modAttrs = [(ldap.MOD_DELETE, 'member', b"uid=" + userName.encode("UTF-8"))] groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) if not self.modAttrsDN(groupDN, modAttrs): flagError = True @@ -15852,7 +15884,7 @@ is not valid ") %accessPorts) self.clVars.Set("ur_name", userName) #Полное имя пользователя (комментарий) fullNameUser = self.servUnixObj.fullNameUser - if options.has_key('c'): + if 'c' in options: fullNameUser = options['c'] else: # Проверяем установку сервиса не печатая ошибку в случае @@ -15860,8 +15892,8 @@ is not valid ") %accessPorts) if self.isServiceSetup("unix",False): resUnix = self.servUnixObj.searchUnixUser(userName) # Берем комментарий для пользователя из Unix - if resUnix and resUnix[0][0][1].has_key('cn'): - fullNameUser = resUnix[0][0][1]['cn'][0] + if resUnix and 'cn' in resUnix[0][0][1]: + fullNameUser = resUnix[0][0][1]['cn'][0].decode("UTF-8") self.clVars.Set("ur_fio",fullNameUser) ldifFile = self.ldifFileUser userLdif = self.createLdif(ldifFile) @@ -15871,7 +15903,7 @@ is not valid ") %accessPorts) #ldapObj.ldapAdd(userLdif1) # не переделывать на else if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False self.printSUCCESS(_("Added user in Proxy service")) return True @@ -15896,21 +15928,20 @@ is not valid ") %accessPorts) # Группа не пуста flagEmptyGroup = False # Если есть пустой member аттрибут (пустая группа) - if filter(lambda x: not x.strip(), searchGroup[0][0][1]['member']): + if [x for x in searchGroup[0][0][1]['member'] if not x.strip()]: flagEmptyGroup = True addUsers = users else: - memberUsers = map(lambda x:x.rpartition("=")[2],\ - searchGroup[0][0][1]["member"]) - addUsers = filter(lambda x: not x in memberUsers, users) + memberUsers = [x.decode("UTF-8").rpartition("=")[2] for x in searchGroup[0][0][1]["member"]] + addUsers = [x for x in users if x not in memberUsers] for userName in addUsers: if flagEmptyGroup: - modAttrs.append((ldap.MOD_REPLACE, 'member', "uid="+userName)) + modAttrs.append((ldap.MOD_REPLACE, 'member', b"uid=" + userName.encode("UTF-8"))) flagEmptyGroup = False else: - modAttrs.append((ldap.MOD_ADD, 'member', "uid="+userName)) + modAttrs.append((ldap.MOD_ADD, 'member', b"uid=" + userName.encode("UTF-8"))) if modAttrs: - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) return True @@ -15945,12 +15976,11 @@ is not valid ") %accessPorts) %str(groupName)) return False # Если группа пуста - if filter(lambda x: not x.strip(), searchGroup[0][0][1]['member']): + if [x.decode("UTF-8") for x in searchGroup[0][0][1]['member'] if not x.strip()]: self.printERROR( _("Member list of group %s is empty")%str(groupName)) - return False - memberUsers = map(lambda x:x.rpartition("=")[2],\ - searchGroup[0][0][1]["member"]) + memberUsers = [x.decode("UTF-8").rpartition("=")[2] for x + in searchGroup[0][0][1]["member"]] flagError = False for user in users: if not user in memberUsers: @@ -15969,8 +15999,8 @@ is not valid ") %accessPorts) if i >= lenMemberUsers: modAttrs.append((ldap.MOD_REPLACE, 'member', "")) else: - modAttrs.append((ldap.MOD_DELETE, 'member', "uid="+userName)) - groupDN = self.addDN("cn="+groupName, self.relGroupsDN) + modAttrs.append((ldap.MOD_DELETE, 'member', b"uid=" + userName.encode("UTF-8"))) + groupDN = self.addDN("cn=" + groupName, self.relGroupsDN) return self.modAttrsDN(groupDN, modAttrs) def modUserProxyPasswd(self, userName, options): @@ -15986,11 +16016,11 @@ is not valid ") %accessPorts) # Изменяемые аттрибуты пользователя modAttrs = [] # Включаем пользователя - if options.has_key('u'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "Yes")] + if 'u' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"Yes")] # Выключаем пользователя - elif options.has_key('l'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "No")] + elif 'l' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"No")] if not options: optPasswd = {"p":""} userPwd = self.getUserPassword(optPasswd, "p", False) @@ -15999,20 +16029,20 @@ is not valid ") %accessPorts) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('l'): + if 'l' in options: self.printSUCCESS(_("Locked user") + " " + str(userName) +\ " " +_("of Proxy service")) - if options.has_key('u'): + if 'u' in options: self.printSUCCESS(_("Unlocked user") + " " + str(userName) +\ " " +_("of Proxy service")) if not options: @@ -16031,7 +16061,7 @@ is not valid ") %accessPorts) _("User %s is not found in Proxy service")%str(userName)) return False # Новые группы в которые входит пользователь - if options.has_key('G'): + if 'G' in options: userGroups = options['G'].split(',') if not self.searchProxyGroups(userGroups): return False @@ -16047,7 +16077,7 @@ is not valid ") %accessPorts) return False self.printSUCCESS(_("Replaced list of supplementary group")) # Добавляем группы в которые входит пользователь - elif options.has_key('a'): + elif 'a' in options: userGroups = options['a'].split(',') if not self.searchProxyGroups(userGroups): return False @@ -16062,14 +16092,14 @@ is not valid ") %accessPorts) # Изменяемые аттрибуты пользователя modAttrs = [] # Включаем пользователя - if options.has_key('U'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "Yes")] + if 'U' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"Yes")] # Выключаем пользователя - elif options.has_key('L'): - modAttrs += [(ldap.MOD_REPLACE, 'initials', "No")] + elif 'L' in options: + modAttrs += [(ldap.MOD_REPLACE, 'initials', b"No")] # Изменяем комментарий к пользователю - if options.has_key('c'): - comment = options['c'] + if 'c' in options: + comment = options['c'].encode("UTF-8") modAttrs += [(ldap.MOD_REPLACE, 'sn', comment), (ldap.MOD_REPLACE, 'cn', comment)] # Изменяем пароль пользователя @@ -16080,23 +16110,23 @@ is not valid ") %accessPorts) userPwdHash = self.getHashPasswd(userPwd, self.userCrypt) if not userPwdHash: return False - if res[0][0][1].has_key('userPassword'): + if 'userPassword' in res[0][0][1]: modAttrs.append((ldap.MOD_REPLACE, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) else: modAttrs.append((ldap.MOD_ADD, 'userPassword', - userPwdHash)) + userPwdHash.encode("UTF-8"))) if modAttrs: DN = self.addDN("uid="+userName, self.relUsersDN) if not self.modAttrsDN(DN, modAttrs): return False - if options.has_key('P') or options.has_key('p'): + if 'P' in options or 'p' in options: self.printSUCCESS(_("Modified user password")) - if options.has_key('c'): + if 'c' in options: self.printSUCCESS(_("Modified comment")) - if options.has_key('U'): + if 'U' in options: self.printSUCCESS(_("Unlocked user %s")% str(userName)) - if options.has_key('L'): + if 'L' in options: self.printSUCCESS(_("Locked user %s")% str(userName)) return True @@ -16111,7 +16141,7 @@ is not valid ") %accessPorts) %str(groupName)) return False # Добавляем список пользователей в группу - if options.has_key('a'): + if 'a' in options: # добавляемые пользователи в группу users = options['a'].split(',') res = self.addUsersGroupProxy(users, groupName) @@ -16123,7 +16153,7 @@ is not valid ") %accessPorts) " " + str(groupName)) return False # Удаляем список пользователей из группы - if options.has_key('d'): + if 'd' in options: # удаляемые пользователи из группы users = options['d'].split(',') res = self.delUsersGroupProxy(users, groupName) @@ -16135,9 +16165,9 @@ is not valid ") %accessPorts) " " + str(groupName)) return False # Изменяем комментарий к группе - if options.has_key('c'): + if 'c' in options: gecos = options['c'] - modAttrs = [(ldap.MOD_REPLACE, 'description', gecos)] + modAttrs = [(ldap.MOD_REPLACE, 'description', gecos.encode("UTF-8"))] groupDN = self.addDN("cn="+groupName, self.relGroupsDN) if self.modAttrsDN(groupDN, modAttrs): self.printSUCCESS(_("Modified group comment")) @@ -16146,7 +16176,7 @@ is not valid ") %accessPorts) " " + str(groupName)) return False # Изменяем имя группы - if options.has_key('n'): + if 'n' in options: newGroupName = options['n'] newFirstDn = "cn=" + newGroupName oldDN = self.addDN("cn=" + groupName, self.relGroupsDN) @@ -16167,8 +16197,8 @@ is not valid ") %accessPorts) self.clVars должен быть определен """ - print _("Enter the allowed ip addresses and network for %s service")\ - %"Proxy" + " (" + _("comma or space delimited") + ")" + print(_("Enter the allowed ip addresses and network for %s service")\ + %"Proxy" + " (" + _("comma or space delimited") + ")") strPrompt = _("allow networks: ") netAllow = self.clVars.Get("sr_proxy_net_allow") strNetAllow = "" @@ -16187,7 +16217,7 @@ is not valid ") %accessPorts) """Начальная настройка Proxy сервиса""" # Принудительная установка forceOptions = False - if options.has_key("f"): + if "f" in options: forceOptions = True # Создаем объект переменных и начальная проверка if not self.initialChecksSetup(): @@ -16204,7 +16234,7 @@ is not valid ") %accessPorts) _("Proxy server is configured")+ ".") return True # Порт для прокси сервера - if options.has_key("p"): + if "p" in options: proxyPort = options['p'] try: numberProxyPort = int(proxyPort) @@ -16227,13 +16257,13 @@ is not valid ") %accessPorts) _("input 'yes'") +", "+ _("if not 'no'") if not self.dialogYesNo(messDialog): return True - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: return False else: - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: @@ -16253,7 +16283,7 @@ is not valid ") %accessPorts) self.createClVars() # Устанавливаем доступные сети self.clVars.Set("sr_proxy_net_allow", allowNet, True) - if options.has_key("p"): + if "p" in options: self.clVars.Set("sr_proxy_port",proxyPort, True) # Удаляем из автозапуска демона if not self.delDaemonAutostart("squid"): @@ -16268,7 +16298,7 @@ is not valid ") %accessPorts) fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'), self.clVars.Get('os_net_domain')) jabberHosts = fullHostName - if options.has_key("host"): + if "host" in options: fullHostName = options['host'] if not "." in fullHostName: fullHostName = "%s.%s" %(fullHostName, @@ -16307,7 +16337,7 @@ is not valid ") %accessPorts) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Записываем данные администратора сервиса Proxy ldapParser = iniLdapParser() @@ -16431,7 +16461,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): (ip, '\tfixed-address %s;'%ip), (mac,'\thardware ethernet %s;'%mac), (True, '}')] - templateList = map(lambda x: x[1], filter(lambda x: x[0], templateList)) + templateList = [x[1] for x in templateList if x[0]] template = "".join(templateList) return template @@ -16462,7 +16492,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): %(delChar,domainNameServers)), (iprange, '\t%srange %s;'%(delChar, iprange)), (True, '}')] - templateList = map(lambda x: x[1], filter(lambda x: x[0], templateList)) + templateList = [x[1] for x in templateList if x[0]] template = "".join(templateList) return template @@ -16475,9 +16505,10 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): "child::area/child::caption/child::name", xmlNodeBody) if not namesArea: return [] - return filter(lambda x: x.firstChild and x.firstChild.nodeValue and\ - len(x.firstChild.nodeValue) > 4 and\ - 'host' in x.firstChild.nodeValue[:4], namesArea) + return [x for x in namesArea + if firstChild(x) is not None and firstChild(x).text and\ + len(firstChild(x).text) > 4 and\ + 'host' in firstChild(x).text[:4]] def getAllXMLSubnet(self): """Получаем все XML ноды подсетей""" @@ -16488,26 +16519,27 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): "child::area/child::caption/child::name", xmlNodeBody) if not namesArea: return [] - return filter(lambda x: x.firstChild and x.firstChild.nodeValue and\ - len(x.firstChild.nodeValue) > 6 and\ - 'subnet' in x.firstChild.nodeValue[:6], namesArea) + return [x for x in namesArea + if firstChild(x) is not None and firstChild(x).text and\ + len(firstChild(x).text) > 6 and\ + 'subnet' in firstChild(x).text[:6]] def getDataInAllHost(self): """Получить информацию о статических хостах""" if self.getError(): - return False + return [] allXmlNames = self._getAllXMLStaticHosts() - allXmlAreas = map(lambda x: x.parentNode.parentNode, allXmlNames) + allXmlAreas = [x.getparent().getparent() for x in allXmlNames] # Информация dataHost = [] iterXmlNames = iter(allXmlNames) for xmlArea in allXmlAreas: #print xmlArea.toprettyxml() # Ност - xmlNodeName = iterXmlNames.next() - strNameNode = xmlNodeName.firstChild.nodeValue + xmlNodeName = next(iterXmlNames) + strNameNode = firstChild(xmlNodeName).text # название хоста - hostname = strNameNode.partition("host")[2].strip().encode("UTF-8") + hostname = strNameNode.partition("host")[2].strip() # Параметры статического хоста dataPars = self.dataParsHost.copy() # Заполняем словарь dataPars реальными параметрами @@ -16521,21 +16553,21 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): if self.getError(): return False allXmlNames = self.getAllXMLSubnet() - allXmlAreas = map(lambda x: x.parentNode.parentNode, allXmlNames) + allXmlAreas = [x.getparent().getparent() for x in allXmlNames] # Информация dataNet = [] iterXmlNames = iter(allXmlNames) for xmlArea in allXmlAreas: # Сеть - xmlNodeName = iterXmlNames.next() + xmlNodeName = next(iterXmlNames) # Название области - strNameNode = xmlNodeName.firstChild.nodeValue + strNameNode = firstChild(xmlNodeName).text # ip сети netIP = strNameNode.partition("subnet")[2].partition("netmask")[0] - netIP = netIP.encode("UTF-8") + # netIP = netIP.encode("UTF-8") # Маска сети netMask = strNameNode.partition("subnet")[2].partition("netmask")[2] - netMask = netMask.encode("UTF-8") + # netMask = netMask.encode("UTF-8") # Параметры сети dataPars = self.dataParsNet.copy() # Заполняем словарь dataPars реальными параметрами @@ -16560,15 +16592,15 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): binList = [] numb = int(string) while numb: - binList.append(numb%2) - numb = numb/2 + binList.append(numb % 2) + numb = numb // 2 return binList[::-1] listOctMask = ipNetMask.split('.') - if filter(lambda x: not isNumber(x), listOctMask): + if [x for x in listOctMask if not isNumber(x)]: return "" - countOne = lambda z: filter(lambda x:x==1, strToBinList(z)) - numberMask = sum(map(lambda x: sum(countOne(x)), listOctMask)) + countOne = lambda z: [x for x in strToBinList(z) if x == 1] + numberMask = sum(sum(countOne(x)) for x in listOctMask) return str(numberMask) @@ -16583,11 +16615,9 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): for node in nodesFind: nodesXml = xpath.Evaluate("child::value", node) for nodeFind in nodesXml: - if nodeFind.firstChild: - listOpt = map(lambda x: x.encode("UTF-8"),\ - filter(lambda x: x,\ - nodeFind.firstChild.nodeValue.replace("\t",\ - " ").split(" "))) + if firstChild(nodeFind) is not None: + listOpt = [x for x + in firstChild(nodeFind).text.replace("\t"," ").split(" ") if x] dataPars[opt] = listOpt return dataPars @@ -16601,8 +16631,8 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): if not xmlStaticHosts: return [] slpHostName = 'host%s' %hostName.lower() - return map(lambda x: x.parentNode.parentNode, filter(lambda x:\ - slpHostName == x.firstChild.nodeValue.lower(), xmlStaticHosts)) + return [x.getparent().getparent() for x in xmlStaticHosts + if slpHostName == firstChild(x).text.lower()] def getXMLNet(self, net): """Получить XML ноду подсети по ip""" @@ -16614,10 +16644,9 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): return [] slpNetName = 'subnet%s' %net.lower() lenSlpNetName = len(slpNetName) - return map(lambda x: x.parentNode.parentNode, filter(lambda x:\ - len(x.firstChild.nodeValue)>lenSlpNetName and\ - slpNetName==x.firstChild.nodeValue[:lenSlpNetName].lower(),\ - xmlSubnets)) + return [x.getparent().getparent() for x in xmlSubnets + if len(firstChild(x).text) > lenSlpNetName and + slpNetName == firstChild(x).text[:lenSlpNetName].lower()] def createStaticHost(self, hostname, ip, mac): """Создает статический хост в файле конфигурации dhcp""" @@ -16628,7 +16657,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): xmlNodeBodyNewNet = dhcpObj.docObj.getNodeBody() namesAreaNew = xpath.Evaluate("child::area/child::caption/child::name", xmlNodeBodyNewNet) - splNameNewNode = namesAreaNew[0].firstChild.nodeValue + splNameNewNode = firstChild(namesAreaNew[0]).text hostnameNode = splNameNewNode.partition("host")[2].strip() if self.getXMLStaticHost(hostnameNode): self.setError(_('DHCP static host "%s" exists')%hostnameNode) @@ -16636,7 +16665,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): # Объединение конфигураций self.join(dhcpObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def modNetOpts(self,xmlNode,routers="",domainName="",dnsIPs="",iprange=""): @@ -16644,11 +16673,11 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): if self.getError(): return False namesArea = xpath.Evaluate("child::caption/child::name", xmlNode) - splNameNewNode = namesArea[0].firstChild.nodeValue + splNameNewNode = firstChild(namesArea[0]).text netIPList = splNameNewNode.partition("subnet")[2].partition("netmask") - netIP = netIPList[0].strip().encode("UTF-8") - netMask = netIPList[2].partition("{")[0].strip().encode("UTF-8") - if not filter(lambda x: x, (routers, domainName, dnsIPs, iprange)): + netIP = netIPList[0].strip() + netMask = netIPList[2].partition("{")[0].strip() + if not any((routers, domainName, dnsIPs, iprange)): self.setError(_("empty modify options")) return False textNet = self.getTextSubnet(netIP, "", routers, domainName, @@ -16658,7 +16687,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): # Объединение конфигураций self.join(dhcpObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def modHostOpts(self, xmlNode, ip, mac): @@ -16666,9 +16695,9 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): if self.getError(): return False namesArea = xpath.Evaluate("child::caption/child::name", xmlNode) - splNameNewNode = namesArea[0].firstChild.nodeValue - hostname = splNameNewNode.partition("host")[2].strip().encode("UTF-8") - if not filter(lambda x: x, (ip, mac)): + splNameNewNode = firstChild(namesArea[0]).text + hostname = splNameNewNode.partition("host")[2].strip() + if not any((ip, mac)): self.setError(_("empty modify options")) return False textHost = self.getTextStaticIP(hostname, ip, mac) @@ -16676,7 +16705,7 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): # Объединение конфигураций self.join(dhcpObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def createNet(self, net, routers, domainNames, dnsIPs, ipranges): @@ -16698,33 +16727,35 @@ class dncpTxt(cl_profile.dhcp, shareTxt, shareIP): xmlNodeBodyNewNet = dhcpObj.docObj.getNodeBody() namesAreaNew = xpath.Evaluate("child::area/child::caption/child::name", xmlNodeBodyNewNet) - splNameNewNode = namesAreaNew[0].firstChild.nodeValue + splNameNewNode = firstChild(namesAreaNew[0]).text netIP = splNameNewNode.partition("subnet")[2].partition("netmask")[0] - netIP = netIP.encode("UTF-8") + # netIP = netIP.encode("UTF-8") if self.getXMLNet(netIP): self.setError(_('DHCP subnet "%s" exists')%netIP) return False # Объединение конфигураций self.join(dhcpObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def deleteAllNetAndHosts(self): """Удаляет все сети и статические хосты из конфигурационного файла""" # IP всех сетей - delNamesNets = map(lambda x:\ -x.firstChild.nodeValue.partition("subnet")[2].partition("netmask")[0].\ -encode("UTF-8"), filter(lambda x: x.firstChild, self.getAllXMLSubnet())) + delNamesNets = [firstChild(x).text.partition("subnet")[2].\ + partition("netmask")[0] + for x in self.getAllXMLSubnet() + if firstChild(x) is not None] # Имена всех статических хостов - delNamesHosts = map(lambda x:\ - x.firstChild.nodeValue.partition("host")[2].strip().encode("UTF-8"),\ - filter(lambda x: x.firstChild, self._getAllXMLStaticHosts())) + delNamesHosts = [firstChild(x).text.partition("host")[2].\ + strip() + for x in self._getAllXMLStaticHosts() + if firstChild(x) is not None] # Удаление - for term in map(lambda x: self.deleteNet(x), delNamesNets): + for term in (self.deleteNet(x) for x in delNamesNets): if not term: return False - for term in map(lambda x: self.deleteStaticHost(x), delNamesHosts): + for term in (self.deleteStaticHost(x) for x in delNamesHosts): if not term: return False return True @@ -16741,19 +16772,19 @@ encode("UTF-8"), filter(lambda x: x.firstChild, self.getAllXMLSubnet())) return False # Удаление областей xmlNodeBody = self.docObj.getNodeBody() - nextNode = lambda x: x.nextSibling - prevNode = lambda x: x.previousSibling + nextNode = lambda x: x.getnext() + prevNode = lambda x: x.getprevious() delNodesNext = [] delNodesPrev = [] for node in deletesNodes: nNode = node nNode = nextNode(nNode) - while nNode and self.docObj.getTypeField(nNode)=="br": + while nNode is not None and self.docObj.getTypeField(nNode)=="br": delNodesNext.append(nNode) nNode = nextNode(nNode) pNode = node pNode = prevNode(pNode) - while pNode and self.docObj.getTypeField(pNode)=="br": + while pNode is not None and self.docObj.getTypeField(pNode)=="br": delNodesPrev.append(pNode) pNode = prevNode(pNode) @@ -16771,17 +16802,18 @@ encode("UTF-8"), filter(lambda x: x.firstChild, self.getAllXMLSubnet())) elif delNodesNext and len(delNodesNext)==1: delNodesNext.pop() delNodes = delNodesPrev + delNodesNext - # Удаляем переводы строк - map(lambda x: xmlNodeBody.removeChild(x), delNodes) - #print xmlNodeBody.toprettyxml().encode("UTF-8") - # Удаляем области - for term in map(lambda x: xmlNodeBody.removeChild(x), deletesNodes): - if not term: - self.setError(_('Can not remove static host "%s"')%hostname+\ - " " + _("in config file %s")%self.nameConfigFile) - return False + try: + # Удаляем переводы строк + [xmlNodeBody.remove(x) for x in delNodes] + # Удаляем области + [xmlNodeBody.remove(x) for x in deletesNodes] + except Exception as e: + self.setError(_('Can not remove static host "%s"') % hostname +\ + " " + _("in config file %s") % self.nameConfigFile+\ + f"\n{str(e)}") + return False # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def deleteNet(self, net): @@ -16796,19 +16828,19 @@ encode("UTF-8"), filter(lambda x: x.firstChild, self.getAllXMLSubnet())) return False # Удаление областей xmlNodeBody = self.docObj.getNodeBody() - nextNode = lambda x: x.nextSibling - prevNode = lambda x: x.previousSibling + nextNode = lambda x: x.getnext() + prevNode = lambda x: x.getprevious() delNodesNext = [] delNodesPrev = [] for node in deletesNodes: nNode = node nNode = nextNode(nNode) - while nNode and self.docObj.getTypeField(nNode)=="br": + while nNode is not None and self.docObj.getTypeField(nNode)=="br": delNodesNext.append(nNode) nNode = nextNode(nNode) pNode = node pNode = prevNode(pNode) - while pNode and self.docObj.getTypeField(pNode)=="br": + while pNode is not None and self.docObj.getTypeField(pNode)=="br": delNodesPrev.append(pNode) pNode = prevNode(pNode) @@ -16826,17 +16858,18 @@ encode("UTF-8"), filter(lambda x: x.firstChild, self.getAllXMLSubnet())) elif delNodesNext and len(delNodesNext)==1: delNodesNext.pop() delNodes = delNodesPrev + delNodesNext - # Удаляем переводы строк - map(lambda x: xmlNodeBody.removeChild(x), delNodes) - #print xmlNodeBody.toprettyxml().encode("UTF-8") - # Удаляем области - for term in map(lambda x: xmlNodeBody.removeChild(x), deletesNodes): - if not term: - self.setError(_('Can not remove subnet "%s"')%net+\ - " " + _("in config file %s")%self.nameConfigFile) - return False + try: + # Удаляем переводы строк + [xmlNodeBody.remove(x) for x in delNodes] + # Удаляем области + [xmlNodeBody.remove(x) for x in deletesNodes] + except Exception as e: + self.setError(_('Can not remove subnet "%s"')%net +\ + " " + _("in config file %s")%self.nameConfigFile +\ + f"\n{str(e)}") + return False # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) class dnsTxt(cl_profile.bind,shareTxt): @@ -16854,8 +16887,10 @@ class dnsTxt(cl_profile.bind,shareTxt): if not self.getError(): cl_profile.bind.__init__(self, text) - def getTextZone(self, clVars, zoneName, zoneType, zoneMasters=[]): + def getTextZone(self, clVars, zoneName, zoneType, zoneMasters=None): """Создание текста DNS зоны""" + if zoneMasters is None: + zoneMasters = [] if zoneType == "master": dnsBaseDN = clVars.Get("ld_dns_dn") dnsCommaSplDN = dnsBaseDN.replace(",","%2c") @@ -16867,22 +16902,23 @@ class dnsTxt(cl_profile.bind,shareTxt): # прямая зона dnsDN = "ou=Forward,%s"%dnsBaseDN template = 'zone "%s" in {\n\ -\ttype %s;\n\ -\tdatabase "ldap ldap://127.0.0.1/zoneName=%s,%s????\ -!bindname=%s,!x-bindpw=%s 178600";\n\ -};' %(zoneName,zoneType,zoneName,dnsDN,dnsCommaSplDN,dnsBasePw) + \ttype %s;\n\ + \tdatabase "ldap ldap://127.0.0.1/zoneName=%s,%s????\ + !bindname=%s,!x-bindpw=%s 178600";\n\ + };' %(zoneName,zoneType,zoneName,dnsDN,dnsCommaSplDN,dnsBasePw) return template elif zoneType == "slave": if not zoneMasters: self.setError(\ - _('Can not found master DNS server in the DNS zone "%s"')%zoneName) + _('Can not found master DNS server\ + in the DNS zone "%s"')%zoneName) return False zoneFile = "%s.zone" %zoneName.split(".in-addr.arpa")[0] template = 'zone "%s" {\n\ -\ttype %s;\n\ -\tfile "sec/%s";\n\ -\tmasters { %s; };\n\ -};' %(zoneName,zoneType,zoneFile, "; ".join(zoneMasters)) + \ttype %s;\n\ + \tfile "sec/%s";\n\ + \tmasters { %s; };\n\ + };' %(zoneName,zoneType,zoneFile, "; ".join(zoneMasters)) return template else: self.setError(_('DNS zone type %s unsupported')%zoneType) @@ -16897,8 +16933,9 @@ class dnsTxt(cl_profile.bind,shareTxt): "child::area/child::caption/child::name", xmlNodeBody) if not namesArea: return [] - return filter(lambda x: x.firstChild and x.firstChild.nodeValue and\ - 'zone"' in x.firstChild.nodeValue, namesArea) + return [x for x in namesArea + if firstChild(x) is not None and firstChild(x).text and\ + 'zone"' in firstChild(x).text] def getXMLZoneToName(self, nameZone): """Получить XML ноду DNS зоны по ее имени""" @@ -16911,10 +16948,10 @@ class dnsTxt(cl_profile.bind,shareTxt): if not xmlZonesNames: return [] nameZoneL = nameZone.lower() - return map(lambda x: x.parentNode.parentNode, filter(lambda x:\ - nameZoneL == \ - x.firstChild.nodeValue.lower().partition('"')[2].partition('"')[0],\ - xmlZonesNames)) + return [x.getparent().getparent() + for x in xmlZonesNames + if nameZoneL == \ + firstChild(x).text.lower().partition('"')[2].partition('"')[0]] def getAllNamesZones(self): """Получить все имена нод областей (кроме служебных)""" @@ -16926,16 +16963,16 @@ class dnsTxt(cl_profile.bind,shareTxt): if not xmlZonesNames: return retNodesNames for nodeZone in xmlZonesNames: - if '"."' in nodeZone.firstChild.nodeValue.lower(): + if '"."' in firstChild(nodeZone).text.lower(): continue - elif '"localhost"' in nodeZone.firstChild.nodeValue.lower(): + elif '"localhost"' in firstChild(nodeZone).text.lower(): continue - elif '"127.in-addr.arpa"' in nodeZone.firstChild.nodeValue.lower(): + elif '"127.in-addr.arpa"' in firstChild(nodeZone).text.lower(): continue retNodesNames.append(\ - nodeZone.firstChild.nodeValue.rpartition('"')[0].partition('"')[2]) - retNodesNames = filter(lambda x: x, retNodesNames) - return map(lambda x: x.encode("UTF-8"), retNodesNames) + firstChild(nodeZone).text.rpartition('"')[0].partition('"')[2]) + retNodesNames = [x for x in retNodesNames if x] + return retNodesNames def deleteZone(self, zoneName): """Удаляет зону из конфигурационного файла bind""" @@ -16949,47 +16986,49 @@ class dnsTxt(cl_profile.bind,shareTxt): return False # Удаление областей xmlNodeBody = self.docObj.getNodeBody() - nextNode = lambda x: x.nextSibling - prevNode = lambda x: x.previousSibling + nextNode = lambda x: x.getnext() + prevNode = lambda x: x.getprevious() delNodesNext = [] delNodesPrev = [] for node in deletesNodes: nNode = node nNode = nextNode(nNode) - while nNode and self.docObj.getTypeField(nNode)=="br": + while nNode is not None and self.docObj.getTypeField(nNode) == "br": delNodesNext.append(nNode) nNode = nextNode(nNode) pNode = node pNode = prevNode(pNode) - while pNode and self.docObj.getTypeField(pNode)=="br": + while pNode is not None and self.docObj.getTypeField(pNode) == "br": delNodesPrev.append(pNode) pNode = prevNode(pNode) # Оставляем два перевода строки сверху - if delNodesPrev and len(delNodesPrev)>=2: + if delNodesPrev and len(delNodesPrev) >= 2: delNodesPrev.pop() delNodesPrev.pop() - elif delNodesNext and len(delNodesNext)>=2: + elif delNodesNext and len(delNodesNext) >= 2: delNodesNext.pop() delNodesNext.pop() - elif delNodesPrev and len(delNodesPrev)==1: + elif delNodesPrev and len(delNodesPrev) == 1: delNodesPrev.pop() - if delNodesNext and len(delNodesNext)==1: + if delNodesNext and len(delNodesNext) == 1: delNodesNext.pop() - elif delNodesNext and len(delNodesNext)==1: + elif delNodesNext and len(delNodesNext) == 1: delNodesNext.pop() delNodes = delNodesPrev + delNodesNext - # Удаляем переводы строк - map(lambda x: xmlNodeBody.removeChild(x), delNodes) - #print xmlNodeBody.toprettyxml().encode("UTF-8") - # Удаляем области - for term in map(lambda x: xmlNodeBody.removeChild(x), deletesNodes): - if not term: - self.setError(_('Can not remove DNS zone "%s"')%zoneName+\ - " " + _("in config file %s")%self.nameConfigFile) - return False + try: + + # Удаляем переводы строк + [xmlNodeBody.remove(x) for x in delNodes] + # Удаляем области + [xmlNodeBody.remove(x) for x in deletesNodes] + except Exception as e: + self.setError(_('Can not remove DNS zone "%s"')%zoneName+\ + " " + _("in config file %s")%self.nameConfigFile+\ + f"\n{str(e)}") + return False # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def deleteAllZones(self, functPrintSuccess=False): @@ -17009,7 +17048,7 @@ class dnsTxt(cl_profile.bind,shareTxt): if not xmlZonesNames: return True for nodeZone in xmlZonesNames: - nodeValue = nodeZone.firstChild.nodeValue.lower() + nodeValue = firstChild(nodeZone).text.lower() if '"."' in nodeValue: continue elif '"localhost"' in nodeValue: @@ -17017,25 +17056,24 @@ class dnsTxt(cl_profile.bind,shareTxt): elif '"127.in-addr.arpa"' in nodeValue: continue else: - nodeValue = nodeValue.encode("UTF-8") # Название зоны nameZ = nodeValue.rpartition('"')[0].partition('"')[2] - deletesNodes.append((nodeZone.parentNode.parentNode,nameZ)) + deletesNodes.append((nodeZone.getparent().getparent(), nameZ)) # Удаление областей xmlNodeBody = self.docObj.getNodeBody() - nextNode = lambda x: x.nextSibling - prevNode = lambda x: x.previousSibling + nextNode = lambda x: x.getnext() + prevNode = lambda x: x.getprevious() delNodesNext = [] delNodesPrev = [] for node, zoneNameTmp in deletesNodes: nNode = node nNode = nextNode(nNode) - while nNode and self.docObj.getTypeField(nNode)=="br": + while nNode is not None and self.docObj.getTypeField(nNode)=="br": delNodesNext.append(nNode) nNode = nextNode(nNode) pNode = node pNode = prevNode(pNode) - while pNode and self.docObj.getTypeField(pNode)=="br": + while pNode is not None and self.docObj.getTypeField(pNode)=="br": delNodesPrev.append(pNode) pNode = prevNode(pNode) # Оставляем два перевода строки сверху @@ -17057,24 +17095,27 @@ class dnsTxt(cl_profile.bind,shareTxt): if not delNode in delNodes: delNodes.append(delNode) # Удаляем переводы строк - map(lambda x: xmlNodeBody.removeChild(x), delNodes) - #print xmlNodeBody.toprettyxml().encode("UTF-8") + [xmlNodeBody.remove(x) for x in delNodes] # Удаляем области for delNode, zoneName in deletesNodes: - if xmlNodeBody.removeChild(delNode): + try: + xmlNodeBody.remove(delNode) # Печатаем сообщение о успешном удалении зоны if flagPrintSuccess: functPrintSuccess(zoneName) - else: + except Exception as e: self.setError(_('Can not remove DNS zone "%s"')%zoneName+\ - " " + _("in config file %s")%self.nameConfigFile) + " " + _("in config file %s")%self.nameConfigFile +\ + f"\n{str(e)}") return False # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) - def createZone(self, clVars, zoneName, zoneType, zoneMasters=[]): + def createZone(self, clVars, zoneName, zoneType, zoneMasters=None): """Создает зону в файле конфигурации bind""" + if zoneMasters is None: + zoneMasters = [] if self.getError(): return False textZone = self.getTextZone(clVars, zoneName, zoneType, @@ -17086,7 +17127,7 @@ class dnsTxt(cl_profile.bind,shareTxt): namesAreaNew = xpath.Evaluate(\ "child::area/child::caption/child::name", xmlNodeBodyNewZone) splNameNewNode =\ - namesAreaNew[0].firstChild.nodeValue.replace("{","").split('"') + firstChild(namesAreaNew[0]).text.replace("{","").split('"') splNameNewNode = splNameNewNode[1] if self.getXMLZoneToName(splNameNewNode): self.setError(_('DNS zone "%s" exists')%splNameNewNode) @@ -17094,7 +17135,7 @@ class dnsTxt(cl_profile.bind,shareTxt): # Объединение конфигураций self.join(bindObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) def notFoundZones(self, zoneNames): @@ -17102,13 +17143,15 @@ class dnsTxt(cl_profile.bind,shareTxt): existsZones = self.getAllNamesZones() return sorted(list(set(zoneNames)-set(existsZones))) - def createExclZones(self, clVars, zoneNames, zoneType, zoneMasters=[]): + def createExclZones(self, clVars, zoneNames, zoneType, zoneMasters=None): """Создает зоны в файле конфигурации bind Будут созданы зоны которых нет в конфигурационном файле zoneNames - зоны которые будут созданы Не проверяется наличие зон в конфигурационном файле """ + if zoneMasters is None: + zoneMasters = [] if self.getError(): return False # Находим зоны отсутствующие в конфигурационном файле @@ -17130,7 +17173,7 @@ class dnsTxt(cl_profile.bind,shareTxt): # Объединение конфигураций self.join(bindObj) # Запись файла - text = self.getConfig().encode("UTF-8") + text = self.getConfig() return self.writeInConfig(text) class servDns(shareLdap): @@ -17223,6 +17266,7 @@ class servDns(shareLdap): """Находим DNS зону в LDAP""" relZonesDN = self.getRelZonesDN(zoneName) resSearch = self.searchLdapDN(zoneName, relZonesDN, "zoneName") + #returns encoded bytes list return resSearch def searchAllZonesInLDAP(self): @@ -17231,8 +17275,7 @@ class servDns(shareLdap): ["zoneName"]) resSearchRev = self.searchLdapDN('*', self.relReverseDN, "zoneName", ["zoneName"]) - return map (lambda x: x[0][1]['zoneName'][0],\ - resSearchFwd + resSearchRev) + return [x[0][1]['zoneName'][0].decode("UTF-8") for x in resSearchFwd + resSearchRev] def searchAllRecordInZone(self, zoneName): @@ -17241,12 +17284,12 @@ class servDns(shareLdap): Кроме SOA записи (имя домена @) """ relZonesDN = self.getRelZonesDN(zoneName) - relZoneDN = self.addDN("zoneName=%s"%zoneName,relZonesDN) + relZoneDN = self.addDN("zoneName=%s" % zoneName, relZonesDN) resSearch = self.searchLdapDN("*", relZoneDN,"relativeDomainName") if resSearch: - resSearch = filter(lambda x:\ - not x[0][1]["relativeDomainName"][0]=="@",\ - resSearch) + resSearch = [x for x in resSearch + if not x[0][1]["relativeDomainName"][0] == b"@"] + #returns encoded bytes list return resSearch def searchAllDomainNamesInLDAP(self, domainName): @@ -17259,6 +17302,7 @@ class servDns(shareLdap): if hostName == "*": hostName = r"\*" resSearch = self.searchLdapDN(hostName, relZoneDN, "relativeDomainName") + #returns encoded bytes list return resSearch def searchDomainNameInLDAP(self, domainName): @@ -17268,8 +17312,9 @@ class servDns(shareLdap): """ resSearch = self.searchAllDomainNamesInLDAP(domainName) if resSearch: - resSearch=filter(lambda x: not x[0][1].has_key("cNAMERecord"),\ - resSearch) + resSearch = [x for x in resSearch + if "cNAMERecord" not in x[0][1]] + #returns encoded bytes list return resSearch def searchCNameInLDAP(self, domainName): @@ -17279,8 +17324,9 @@ class servDns(shareLdap): """ resSearch = self.searchAllDomainNamesInLDAP(domainName) if resSearch: - resSearch=filter(lambda x: x[0][1].has_key("cNAMERecord"),\ - resSearch) + resSearch = [x for x in resSearch + if "cNAMERecord" in x[0][1]] + #returns encoded bytes list return resSearch def searchIPinForward(self, ip): @@ -17290,9 +17336,9 @@ class servDns(shareLdap): """ resSearch = self._searchLdapDNSub(ip, self.relForwardDN, "aRecord") if resSearch: - resSearch = filter(lambda x:\ - not x[0][1]["relativeDomainName"][0]=="@",\ - resSearch) + resSearch = [x for x in resSearch + if not x[0][1]["relativeDomainName"][0] == b"@"] + #returns encoded bytes list return resSearch def searchHostsForIPinForward(self, ip): @@ -17302,9 +17348,10 @@ class servDns(shareLdap): if foundNames: for aRecord in foundNames: relDomainNames = aRecord[0][1]['relativeDomainName'] - zoneName = aRecord[0][1]['zoneName'][0] - domainNames = map(lambda x:"%s.%s"%(x,zoneName),relDomainNames) + zoneName = aRecord[0][1]['zoneName'][0].decode("UTF-8") + domainNames = ["%s.%s" % (x.decode("UTF-8"), zoneName) for x in relDomainNames] hostNames += domainNames + #returns decoded str list return hostNames def searchHostinReverse(self, host): @@ -17312,12 +17359,12 @@ class servDns(shareLdap): Ищет в LDAP """ - hostDot = "%s."%host - resSearch = self._searchLdapDNSub(hostDot,self.relReverseDN,"pTRRecord") + hostDot = "%s." % host + resSearch = self._searchLdapDNSub(hostDot,self.relReverseDN, "pTRRecord") if resSearch: - resSearch = filter(lambda x:\ - not x[0][1]["relativeDomainName"][0]=="@",\ - resSearch) + resSearch = [x for x in resSearch + if not x[0][1]["relativeDomainName"][0] == b"@"] + #returns encoded bytes list return resSearch def searchIPForHostInReverse(self, host): @@ -17327,8 +17374,8 @@ class servDns(shareLdap): if foundIPs: for ptrRecord in foundIPs: lastOctIPs = ptrRecord[0][1]['relativeDomainName'] - zoneName = ptrRecord[0][1]['zoneName'][0] - domainNames = map(lambda x:"%s.%s"%(x,zoneName),lastOctIPs) + zoneName = ptrRecord[0][1]['zoneName'][0].decode("UTF-8") + domainNames = ["%s.%s" % (x.decode("UTF-8"), zoneName) for x in lastOctIPs] for name in domainNames: listOctRev = name.rpartition(".in-addr.arpa")[0].split(".") listOctRev.reverse() @@ -17364,13 +17411,13 @@ class servDns(shareLdap): def createMasterZone(self, zoneName, nameServer="", emailAddr="", - namesServers = [], + namesServers=None, serialNumber="1", refresh=zoneRefresh, updateRetry=zoneUpdateRetry, expiry=zoneExpiry, minimum=zoneMinimum, - ip="", mxList=[]): + ip="", mxList=None): """Создание первичной DNS зоны в конфигурационном файле и в LDAP Параметры: nameServer - имя первичного мастер сервера DNS зоны @@ -17392,6 +17439,10 @@ class servDns(shareLdap): mx - MX записи для зоны """ # Добавление зоны в конфигурационный файл + if namesServers is None: + namesServers = [] + if mxList is None: + mxList = [] ldapParser = iniLdapParser() part = "dns" self.clVars.Set("ld_dns_dn",ldapParser.getVar(part,"DN"),True) @@ -17432,7 +17483,7 @@ class servDns(shareLdap): flagDeleteZone = True else: self.printWARNING(_("Can not found zone %s in \ -/etc/bind/named.conf")%zoneName) + /etc/bind/named.conf")%zoneName) # Если зона найдена в LDAP удаляем ее if self.searchZoneInLDAP(zoneName): # Удаление зоны из LDAP @@ -17503,15 +17554,15 @@ class servDns(shareLdap): regTime = re.compile("^\d+[smhdwSMHDW]?$") sOATimeParams = [refresh,updateRetry,expiry,minimum] # Проверка корректности значений интервалов времени - incorrectTimeValues = filter(lambda x: not regTime.search(x),\ - sOATimeParams) + incorrectTimeValues = [x for x in sOATimeParams + if not regTime.search(x)] if incorrectTimeValues: self.printERROR(_("Values %s incorrect in SOA-record")\ %", ".join(incorrectTimeValues)) return False # Добавление точки если необходимо в каждое имя DNS сервера # Имена авторитативных DNS серверов для зоны - namesServersDot = map(lambda x: addDot(x), namesServers) + namesServersDot = [addDot(x).encode("UTF-8") for x in namesServers] # Получение текста sOA записи sOARecord = " ".join([nameServerDot,emailAddrDot,serialNumber] +\ sOATimeParams) @@ -17537,25 +17588,25 @@ class servDns(shareLdap): # прямая зона zoneBaseDN = "zoneName=%s,%s,%s" %(zoneName, self.relFwdDN, baseDN) - zoneBaseEntry = [('objectclass', ['top','dNSZone']), - ('relativeDomainName', [zoneName]), - ('zoneName',[zoneName])] + zoneBaseEntry = [('objectclass', [b'top', b'dNSZone']), + ('relativeDomainName', [zoneName.encode("UTF-8")]), + ('zoneName',[zoneName.encode("UTF-8")])] zoneBaseErrorMessage = _("Can not add in LDAP DNS zone %s") %zoneName if not self.addEntry(zoneBaseDN, zoneBaseEntry, zoneBaseErrorMessage): return False zoneDomainDN = self.addDN("relativeDomainName=@",zoneBaseDN) zoneDomainErrorMessage = _("Can not add SOA-record in zone %s")%zoneName - zoneDomainEntry = [('objectclass', ['top','dNSZone']), - ('relativeDomainName', ["@"]), - ('zoneName',[zoneName]), - ('sOARecord',[sOARecord]), - ('nSRecord',namesServersDot)] + zoneDomainEntry = [('objectclass', [b'top', b'dNSZone']), + ('relativeDomainName', [b"@"]), + ('zoneName', [zoneName.encode("UTF-8")]), + ('sOARecord', [sOARecord.encode("UTF-8")]), + ('nSRecord', namesServersDot)] if ip: - zoneDomainEntry += [('aRecord',ip)] + zoneDomainEntry += [('aRecord', ip.encode("UTF-8"))] if mxList: - mxListDot = map(lambda x: addDot(x), mxList) - mxValues = map(lambda x: "%s %s" %(x*10+10, mxListDot[x]),\ - range(len(mxListDot))) + mxListDot = [addDot(x).encode("UTF-8") for x in mxList] + mxValues = [b"%s %s" % (x * 10 + 10, mxListDot[x]) + for x in range(len(mxListDot))] zoneDomainEntry += [('mXRecord', mxValues)] if not self.addEntry(zoneDomainDN, zoneDomainEntry, zoneDomainErrorMessage): @@ -17580,22 +17631,22 @@ class servDns(shareLdap): # Проверим установлен ли сервис dns if not self.isServiceSetup("dns"): return False - optKeys = options.keys() + optKeys = list(options.keys()) incompKeys = ["host","ip"] if set(incompKeys)<=set(optKeys): self.printERROR(_('Command line option "--host" (A-record) \ -incompatible with option "--ip" (PTR-record)')) + incompatible with option "--ip" (PTR-record)')) return False # Флаг MX - записи flagDeleteMX = False - if options.has_key('mx'): + if 'mx' in options: flagDeleteMX = True # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) domainName = "" ip = "" typeRec = "" - if options.has_key('host'): + if 'host' in options: # Доменное имя (имя включающее домен) typeRec = "a" domainName = delDot(options['host'].lower()) @@ -17604,10 +17655,10 @@ incompatible with option "--ip" (PTR-record)')) if not zoneName: self.printERROR(_("Domain name %s incorrectly")%domainName) return False - elif options.has_key('ip'): + elif 'ip' in options: if flagDeleteMX: self.printERROR(_('Command line option "--mx" (MX-record) \ -incompatible with option "--ip" (PTR-record)')) + incompatible with option "--ip" (PTR-record)')) return False # ip адрес typeRec = "ptr" @@ -17623,15 +17674,15 @@ incompatible with option "--ip" (PTR-record)')) self.printERROR(_("Record %s not exists in LDAP")%domainName) return False if foundDomain: - foundIP = foundDomain[0][0][1]['aRecord'][0] + foundIP = foundDomain[0][0][1]['aRecord'][0].decode("UTF-8") elif foundDomainCName: - foundCName = foundDomainCName[0][0][1]['cNAMERecord'][0] + foundCName = foundDomainCName[0][0][1]['cNAMERecord'][0].decode("UTF-8") typeRec = "cname" # Если MX запись if flagDeleteMX: # Удаляем MX запись из A записи if foundDomain: - if not foundDomain[0][0][1].has_key('mXRecord'): + if 'mXRecord' not in foundDomain[0][0][1]: self.printERROR(\ _("Can not found MX-records in A-record %s"%domainName)) return False @@ -17659,7 +17710,7 @@ incompatible with option "--ip" (PTR-record)')) if not foundDomain: self.printERROR(_("PTR-record %s not exists in LDAP")%domainName) return False - foundDomainName = foundDomain[0][0][1]['pTRRecord'][0] + foundDomainName = foundDomain[0][0][1]['pTRRecord'][0].decode("UTF-8") # Удаляем PTR запись ret = self.deleteDNSRecord(domainNamePTR) if not ret: @@ -17718,10 +17769,10 @@ incompatible with option "--ip" (PTR-record)')) if not self.isServiceSetup("dns"): return False # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # Имя зоны zoneName = "" - if options.has_key('n'): + if 'n' in options: zoneName = delDot(options["n"].lower()) if not zoneName: self.printERROR(_('Incorrect zone name')) @@ -17735,9 +17786,8 @@ incompatible with option "--ip" (PTR-record)')) if not netmask == "24" or \ not self.isCorrectStringNet(zoneName): self.printERROR(_('Incorrect network %s for reverse zone')\ - %zoneName) - self.printWARNING(_("Example network for reverse zone") +\ - " :") + %zoneName) + self.printWARNING(_("Example network for reverse zone") + " :") self.printWARNING('"-n 192.168.0.0/24"') return False dataIP = self.getDomainAndZoneFromIP(network) @@ -17748,44 +17798,43 @@ incompatible with option "--ip" (PTR-record)')) if not zoneName: self.printERROR(_("Not enough command line option %s")%"-n") return False - if options.has_key('ip') or options.has_key('mx'): + if 'ip' in options or 'mx' in options: # Получение данных зоны из LDAP zoneData = self.searchAllDomainNamesInLDAP("@.%s"%zoneName) if not zoneData: self.printERROR(_("Can not found SOA-record in zone %s")\ - %zoneName) + %zoneName) return False # Удаление A записи - if options.has_key('ip'): - if not zoneData[0][0][1].has_key('aRecord'): + if 'ip' in options: + if 'aRecord' not in zoneData[0][0][1]: self.printERROR(_("Can not found A-records in zone %s")\ - %zoneName) + %zoneName) return False - if options.has_key('mx'): - if not zoneData[0][0][1].has_key('mXRecord'): + if 'mx' in options: + if 'mXRecord' not in zoneData[0][0][1]: self.printERROR(\ _("Can not found MX-records in zone %s")\ - %zoneName) + %zoneName) return False relZoneDN = self.getRelZoneDN(zoneName) modAttrs =[(ldap.MOD_DELETE, 'aRecord', None)] DN = self.addDN("relativeDomainName=@", relZoneDN) if not self.modAttrsDN(DN, modAttrs): self.printERROR(\ - _("Can not delete A-records for zone %s")\ - %zoneName) + _("Can not delete A-records for zone %s")\ + %zoneName) return False self.printSUCCESS(_("Deleted A-records for zone %s")%zoneName) ret = True # Удаление MX записей - if options.has_key('mx'): - if not zoneData[0][0][1].has_key('mXRecord'): + if 'mx' in options: + if 'mXRecord' not in zoneData[0][0][1]: self.printERROR(_("Can not found MX-records in zone %s")\ - %zoneName) + %zoneName) return False # Удаляем все MX записи в записи зоны - ret = self.modMXRecord("@", zoneName, zoneName, - True, []) + ret = self.modMXRecord("@", zoneName, zoneName, True, []) # Увеличиваем на 1 серийный номер зоны if not self.incrementSerialNumberZone(zoneName): return False @@ -17800,7 +17849,7 @@ incompatible with option "--ip" (PTR-record)')) # Проверим установлен ли сервис dns if not self.isServiceSetup("dns"): return False - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = [] # Тип зоны по умолчанию zoneType = "master" @@ -17819,22 +17868,21 @@ incompatible with option "--ip" (PTR-record)')) else: self.printERROR(_("Zone type %s unsupported")%zoneType) self.printWARNING(_("Supported zone types: %s")\ - %", ".join(["master","slave"])) + %", ".join(["master","slave"])) return False - if not set(minKeys)<=set(optKeys): + if not set(minKeys) <= set(optKeys): notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + notFoundKeys (len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys) self.printERROR(_("Not enough command line options: %s")\ - %", ".join(notFoundKeys)) + %", ".join(notFoundKeys)) return False # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # Имя зоны zoneName = "" forwardZone = True - if options.has_key('n'): + if 'n' in options: zoneName = delDot(options["n"].lower()) if not zoneName: self.printERROR(_('Incorrect zone name')) @@ -17851,22 +17899,22 @@ incompatible with option "--ip" (PTR-record)')) else: # Проверка на недопустимые ключи для обратной зоны # ip зоны для обратной зоны недопустим - if options.has_key('ip'): + if 'ip' in options: self.printERROR(_('Command line option "--ip" \ -incompatible with reverse DNS zone %s')%zoneName) + incompatible with reverse DNS zone %s')%zoneName) return False # MX записи для обратной зоны недопустимы - if options.has_key('mx'): + if 'mx' in options: self.printERROR(_('Command line option "--mx" \ -incompatible with reverse DNS zone %s')%zoneName) + incompatible with reverse DNS zone %s')%zoneName) return False network, spl, netmask = zoneName.rpartition("/") if not netmask == "24" or \ not self.isCorrectStringNet(zoneName): self.printERROR(_('Incorrect network %s for reverse zone')\ - %zoneName) + %zoneName) self.printWARNING(_("Example network for reverse zone") +\ - " :") + " :") self.printWARNING('"-n 192.168.0.0/24"') return False netSpl = network.split(".") @@ -17883,11 +17931,11 @@ incompatible with reverse DNS zone %s')%zoneName) objTxtZone = dnsTxt() if zoneName in objTxtZone.getAllNamesZones(): self.printERROR(_("DNS zone %s exists in /etc/bind/named.conf")\ - %zoneName) + %zoneName) return False # ip зоны zoneIP = "" - if options.has_key('ip'): + if 'ip' in options: zoneIP = options["ip"] if "," in zoneIP or \ not self.isCorrectStringNet(zoneIP, False): @@ -17895,23 +17943,23 @@ incompatible with reverse DNS zone %s')%zoneName) return False # Почтовые серверы для зоны zoneListMX = [] - if options.has_key('mx'): - zoneListMX = map(lambda x: delDot(x.lower()),\ - options['mx'].split(",")) + if 'mx' in options: + zoneListMX = [delDot(x.lower()) for x + in options['mx'].split(",")] zoneListMX = self.unicList(zoneListMX) if not self.checkMXDomains(zoneListMX): return False # Все авторитативные сервера зоны, в случае slаve зоны # ip авторитативных серверов хранения зоны namesServers = [] - if options.has_key('servers'): + if 'servers' in options: namesServers = options['servers'].split(",") # Проверка на ip if not flagZoneMaster: if not self.isCorrectStringNet(options['servers'], False): self.printERROR(_('Incorrect autoritatives servers IP')) self.printERROR(_('Error in command line option \ -"--servers"')) + "--servers"')) self.printWARNING(_('Example:')) self.printWARNING('--servers 192.168.0.1,192.168.0.2') return False @@ -17924,7 +17972,7 @@ incompatible with reverse DNS zone %s')%zoneName) if flagErrorNs: self.printERROR(_('Incorrect autoritatives servers names')) self.printERROR(_('Error in command line option \ -"--servers"')) + "--servers"')) self.printWARNING(_('Example:')) self.printWARNING('--servers ns.domain.ru,ns1.domain.ru') return False @@ -17935,19 +17983,19 @@ incompatible with reverse DNS zone %s')%zoneName) warningsMX = [] # Авторитативный сервер nameServer = "" - if options.has_key('server'): + if 'server' in options: nameServer = delDot(options["server"].lower()) if self.isCorrectStringNet(nameServer, False): self.printERROR(_('Incorrect autoritative server')) self.printERROR(_('Error in command line option \ -"--server"')) + "--server"')) self.printWARNING(_('Example:')) self.printWARNING('--server ns.domain.com') return False if not nameServer: self.printERROR(_('Incorrect autoritative server name')) self.printERROR(_('Error in command line option \ -"--server"')) + "--server"')) return False # Добавляем мастер сервер в имена авторитативаных серверов if not nameServer in namesServers: @@ -17959,16 +18007,16 @@ incompatible with reverse DNS zone %s')%zoneName) if nameServer == zoneName or nsZoneName == zoneName or\ (self.searchZoneInLDAP(nsZoneName) and\ not self.searchDomainNameInLDAP(nameServer)): - if not options.has_key('ipserver'): + if 'ipserver' not in options: self.printERROR(_('Not found A-record for "%s" \ -(master server DNS)')%nameServer) + (master server DNS)')%nameServer) self.printERROR(_('Not enough command line option \ -"--ipserver"')) + "--ipserver"')) return False else: if nameServer == zoneName and zoneIP: self.printERROR(_("The same zone name and name of \ -the primary authoritative server for the zone")) + the primary authoritative server for the zone")) self.printERROR(_('We do not need the option "--ip"')) return False ipserver = options["ipserver"] @@ -17977,20 +18025,22 @@ the primary authoritative server for the zone")) self.printERROR(_("IP address %s incorrectly")%ipserver) return False else: - if options.has_key('ipserver'): + if 'ipserver' in options: if self.searchZoneInLDAP(nsZoneName) and\ self.searchDomainNameInLDAP(nameServer): self.printERROR(_('Command line option "--ipserver" \ -is not needed, as the host name "%s" found in the DNS server')%nameServer) + is not needed, as the host name "%s" found in\ + the DNS server')%nameServer) else: self.printERROR(_('Command line option "--ipserver" \ -is not needed, as the host name "%s" does not belong to the existing zones on \ -this DNS server')%nameServer) + is not needed, as the host name "%s" does not\ + belong to the existing zones on \ + this DNS server')%nameServer) return False # Почтовый адрес администратора зоны # по умолчанию email = "%s@%s"%("root",zoneName) - if options.has_key('email'): + if 'email' in options: email = options['email'] # refresh - интервал времени для обновления зоны # update - интервал времени после неудачного обновления зоны @@ -18003,7 +18053,7 @@ this DNS server')%nameServer) for nameOpt in zoneTimeIntervals.keys(): valueOpt = zoneTimeIntervals[nameOpt] locals()[nameOpt] = valueOpt - if options.has_key(nameOpt): + if nameOpt in options: valueOpt = options[nameOpt] locals()[nameOpt] = valueOpt.upper() if not self.checkTimeValue(locals()[nameOpt]): @@ -18069,13 +18119,12 @@ this DNS server')%nameServer) return False foundReverseDomain =self.searchDomainNameInLDAP(domainNamePTR) if foundReverseDomain: - zoneName = foundReverseDomain[0][0][1]['zoneName'][0] + zoneName = foundReverseDomain[0][0][1]['zoneName'][0].decode("UTF-8") relativeDomainName = \ - foundReverseDomain[0][0][1]['relativeDomainName'][0] - pTRRecord = foundReverseDomain[0][0][1]['pTRRecord'][0] + foundReverseDomain[0][0][1]['relativeDomainName'][0].decode("UTF-8") + pTRRecord = foundReverseDomain[0][0][1]['pTRRecord'][0].decode("UTF-8") # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x,\ - y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) reverseHost = delDot(pTRRecord) listOctRev = \ zoneName.rpartition(".in-addr.arpa")[0].split(".") @@ -18099,8 +18148,7 @@ this DNS server')%nameServer) notCmdKey = list(set(optKeys) - set(minKeys)) if notCmdKey: # Добавляем кавычки и -- - addQ = lambda y: map(lambda x:\ - len(x)>1 and '"--%s"'%x or '"-%s"'%x, y) + addQ = lambda y: [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in y] self.printERROR(_("Incorrect command line options %s")\ %", ".join(addQ(notCmdKey))) return False @@ -18111,7 +18159,7 @@ this DNS server')%nameServer) def modARecord(self, hostName, domainName, zoneName, otherIP, newIP): """Изменение IP A записи (прямая зона)""" relZoneDN = self.getRelZoneDN(zoneName) - modAttrs = [(ldap.MOD_REPLACE, 'aRecord', newIP)] + modAttrs = [(ldap.MOD_REPLACE, 'aRecord', newIP.encode("UTF-8"))] DN = self.addDN("relativeDomainName=%s"\ %hostName, relZoneDN) if not self.modAttrsDN(DN, modAttrs): @@ -18136,7 +18184,7 @@ this DNS server')%nameServer) for mxServer in mxServers: i += 10 mxString = "%s %s" %(i, addDot(mxServer)) - modAttrs.append((ldap.MOD_ADD, 'mXRecord', mxString)) + modAttrs.append((ldap.MOD_ADD, 'mXRecord', mxString.encode("UTF-8"))) DN = self.addDN("relativeDomainName=%s"%hostName, relZoneDN) if not self.modAttrsDN(DN, modAttrs): if hostName == "@": @@ -18185,7 +18233,7 @@ this DNS server')%nameServer) addDot = lambda x: (len(x)>0 and x[-1]!="." and "%s."%x) or x relZoneDN = self.getRelZoneDN(PTRZoneName) modAttrs = [(ldap.MOD_REPLACE, 'pTRRecord',\ - addDot(newDomainName))] + addDot(newDomainName).encode("UTF-8"))] DN = self.addDN("relativeDomainName=%s"\ %PTRHostName, relZoneDN) if not self.modAttrsDN(DN, modAttrs): @@ -18205,7 +18253,7 @@ this DNS server')%nameServer) addDot = lambda x: (len(x)>0 and x[-1]!="." and "%s."%x) or x relZoneDN = self.getRelZoneDN(zoneName) modAttrs = [(ldap.MOD_REPLACE, 'cNAMERecord',\ - addDot(newCname))] + addDot(newCname).encode("UTF-8"))] DN = self.addDN("relativeDomainName=%s" %hostName, relZoneDN) if not self.modAttrsDN(DN, modAttrs): self.printERROR(\ @@ -18269,10 +18317,10 @@ this DNS server')%nameServer) if not self.isServiceSetup("dns"): return False # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # Имя зоны zoneName = "" - if options.has_key('n'): + if 'n' in options: zoneName = delDot(options["n"].lower()) if not zoneName: self.printERROR(_('Incorrect zone name')) @@ -18304,23 +18352,21 @@ this DNS server')%nameServer) self.printERROR(_("Can not found master zone %s in LDAP")%zoneName) return False # Проверка на mx совместно с mxmod - if options.has_key('mx') and options.has_key('mxmod'): + if 'mx' in options and 'mxmod' in options: self.printERROR('Command line option "-mx" is incompatible \ -with option "--mxmod"') + with option "--mxmod"') return False # MX серверы mxServers = [] - if options.has_key('mx'): - mxServers=map(lambda x: delDot(x.lower()), - options['mx'].split(",")) + if 'mx' in options: + mxServers = [delDot(x.lower()) for x in options['mx'].split(",")] mxServers = self.unicList(mxServers) # Переименование mx записи # modMxServers[0] - cтарая запись # modMxServers[1] - новая запись modMxServers = [] - if options.has_key('mxmod'): - modMxServers=map(lambda x: delDot(x.lower()),\ - options['mxmod'].split(",")) + if 'mxmod' in options: + modMxServers = [delDot(x.lower()) for x in options['mxmod'].split(",")] modMxServers = self.unicList(modMxServers) if len(modMxServers)!=2: self.printERROR(_('Incorrect command line option "--mxmod"')) @@ -18329,7 +18375,7 @@ with option "--mxmod"') return False # ip зоны zoneIP = "" - if options.has_key('ip'): + if 'ip' in options: zoneIP = options["ip"] if "," in zoneIP or \ not self.isCorrectStringNet(zoneIP, False): @@ -18340,56 +18386,58 @@ with option "--mxmod"') if not zoneData: self.printERROR(_("Can not found SOA-record in zone %s")%zoneName) return False - soaRecord = zoneData[0][0][1]['sOARecord'][0] + #these return lists + soaRecord = zoneData[0][0][1]['sOARecord'][0].decode("UTF-8") nSRecords = zoneData[0][0][1]['nSRecord'] - soaData = map(lambda x: delDot(x), soaRecord.split(" ")) + soaData = [delDot(x) for x in soaRecord.split(" ")] if len(soaData)!=7: self.printERROR(_("Incorrect SOA-record in DNS zone %s")%zoneName) return False # Все авторитативные сервера зоны, в случае slаve зоны - namesServers = map(lambda x: delDot(x), nSRecords) - oldNamesServers = map(lambda x: delDot(x), nSRecords) + namesServers = [delDot(x.decode("UTF-8")) for x in nSRecords] + oldNamesServers = [delDot(x.decode("UTF-8")) for x in nSRecords] # Изменяем ip зоны if zoneIP: - addDot = lambda x: (len(x)>0 and x[-1]!="." and "%s."%x) or x + addDot = lambda x: (len(x) > 0 and x[-1] != "." and "%s." % x) or x relZoneDN = self.getRelZoneDN(zoneName) modAttrs = [] - if zoneData[0][0][1].has_key('aRecord'): + if 'aRecord' in zoneData[0][0][1]: modAttrs =[(ldap.MOD_DELETE, 'aRecord', None)] - modAttrs.append((ldap.MOD_ADD, 'aRecord', zoneIP)) + modAttrs.append((ldap.MOD_ADD, 'aRecord', zoneIP.encode("UTF-8"))) DN = self.addDN("relativeDomainName=@", relZoneDN) if not self.modAttrsDN(DN, modAttrs): self.printERROR(_("Can not modify A-record in zone %s")\ - %zoneName) + % zoneName) return False - self.printSUCCESS(_("Modified A-record in zone %s")%zoneName) - self.printSUCCESS("%s --> %s"%(zoneName, zoneIP)) + self.printSUCCESS(_("Modified A-record in zone %s") % zoneName) + self.printSUCCESS("%s --> %s" % (zoneName, zoneIP)) self.printSUCCESS("") # Изменяем MX записи if mxServers or modMxServers: flagFoundMX = False - if zoneData[0][0][1].has_key('mXRecord'): + if 'mXRecord' in zoneData[0][0][1]: flagFoundMX = True # Изменяем почтовый хост на другой почтовый хост if modMxServers: if not flagFoundMX: self.printERROR(_("Can not found MX-record in zone %s")\ - %zoneName) + % zoneName) return False # Находим нужную запись - foundMxServers = map(lambda x: len(x.split(" "))==1\ - and delDot(x) or delDot(x.split(" ")[1]),\ - zoneData[0][0][1]['mXRecord']) + foundMxServers = [len(x.decode("UTF-8").split(" ")) == 1 + and delDot(x.decode("UTF-8")) + or delDot(x.decode("UTF-8").split(" ")[1]) + for x in zoneData[0][0][1]['mXRecord']] oldMxHost = modMxServers[0] newMxHost = modMxServers[1] if not oldMxHost in foundMxServers: self.printERROR(_("Can not found MX host %s")\ - %oldMxHost +" " + _("in zone %s")%zoneName) + %oldMxHost +" " + _("in zone %s") % zoneName) return False # Проверка наличия новой MX записи в A записи if newMxHost in foundMxServers: self.printERROR(_("MX host %s exists")\ - %newMxHost +" " + _("in zone %s")%zoneName) + % newMxHost +" " + _("in zone %s") % zoneName) return False # Проверка существования A записи для MX хоста if not self.checkMXDomains([newMxHost]): @@ -18413,7 +18461,7 @@ with option "--mxmod"') if not self.modMXRecord("@", zoneName, zoneName, flagFoundMX, mxServers): return False - if options.has_key('servers'): + if 'servers' in options: namesServers = options['servers'].split(",") flagErrorNs = False for ns in namesServers: @@ -18428,19 +18476,19 @@ with option "--mxmod"') return False # Авторитативный сервер nameServer = soaData[0] - if options.has_key('server'): + if 'server' in options: nameServer = delDot(options["server"].lower()) if self.isCorrectStringNet(nameServer, False): self.printERROR(_('Incorrect autoritative server')) self.printERROR(_('Error in command line option \ -"--server"')) + "--server"')) self.printWARNING(_('Example:')) self.printWARNING('--server ns.domain.com') return False if not nameServer: self.printERROR(_('Incorrect autoritative server name')) self.printERROR(_('Error in command line option \ -"--server"')) + "--server"')) return False # Добавляем мастер сервер в имена авторитативаных серверов if not nameServer in namesServers: @@ -18451,16 +18499,16 @@ with option "--mxmod"') if self.searchZoneInLDAP(nsZoneName) and\ not self.searchDomainNameInLDAP(nameServer): self.printERROR(_("Can not found host name %s in LDAP")\ - %nameServer) + %nameServer) self.printWARNING(\ _("Add A-record %s (autoritative DNS server) in LDAP")\ - %nameServer) + % nameServer) return False # Почтовый адрес администратора зоны splEmail = soaData[1].partition(".") - email = "%s@%s"%(splEmail[0], delDot(splEmail[2])) + email = "%s@%s" % (splEmail[0], delDot(splEmail[2])) oldEmail = email - if options.has_key('email'): + if 'email' in options: email = options['email'] # Серийный номер зоны serialNumber = str(ctypes.c_uint32(int(soaData[2])).value + 1) @@ -18475,7 +18523,7 @@ with option "--mxmod"') for nameOpt in zoneTimeIntervals.keys(): valueOpt = zoneTimeIntervals[nameOpt] locals()[nameOpt] = valueOpt - if options.has_key(nameOpt): + if nameOpt in options: valueOpt = options[nameOpt] locals()[nameOpt] = valueOpt.upper() if not self.checkTimeValue(locals()[nameOpt]): @@ -18491,22 +18539,22 @@ with option "--mxmod"') locals()['update'], locals()['expiry'], locals()['minimum']] - optKeys = options.keys() + optKeys = list(options.keys()) if len(optKeys)>1: sOARecord = " ".join(sOAList) relZoneDN = self.getRelZoneDN(zoneName) - modAttrs = [(ldap.MOD_REPLACE, 'sOARecord', sOARecord)] - if options.has_key('server') or options.has_key('servers'): + modAttrs = [(ldap.MOD_REPLACE, 'sOARecord', sOARecord.encode("UTF-8"))] + if 'server' in options or 'servers' in options: # Добавляем мастер сервер в имена авторитативаных серверов if not nameServer in namesServers: namesServers.insert(0, nameServer) modAttrs.append((ldap.MOD_DELETE, 'nSRecord', None)) modAttrs.append((ldap.MOD_ADD, 'nSRecord',\ - map(lambda x: addDot(x), namesServers))) + [addDot(x).encode("UTF-8") for x in namesServers])) DN = self.addDN("relativeDomainName=@", relZoneDN) if not self.modAttrsDN(DN, modAttrs): self.printERROR(_("Can not modify new SOA-record for zone %s \ -in LDAP")%zoneName) + in LDAP") % zoneName) return False # Результат исполнения для пользователя # Изменен ли главный сервер авторизации @@ -18519,7 +18567,7 @@ in LDAP")%zoneName) # Изменены ли авторитативные DNS сервера зоны if set(oldNamesServers) != set(namesServers): self.printSUCCESS(\ - _("Modified all autoritative DNS servers for zone")) + _("Modified all autoritative DNS servers for zone")) # Вывод модифицированных параметров времени for nameOpt in zoneTimeIntervals.keys(): valueOld = zoneTimeIntervals[nameOpt] @@ -18542,15 +18590,15 @@ in LDAP")%zoneName) if "f" in options.keys(): checkDHCPConfig = False # Проверка на имя хоста вместе с ip - if options.has_key('ip') and options.has_key('host'): + if 'ip' in options and 'host' in options: self.printERROR('Command line option "--host" is incompatible \ -with option "--ip"') + with option "--ip"') return False # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) # модификация другой записи A -> PTR, PTR -> A modOther = True - if options.has_key('automod'): + if 'automod' in options: autoMod = options['automod'] if autoMod == "on": modOther = True @@ -18558,28 +18606,28 @@ with option "--ip"') modOther = False else: self.printERROR(_('Command line option "--automod %s" \ -incorrect, use "--automod on" or "--automod off"')%autoMod) + incorrect, use "--automod on" or "--automod off"')%autoMod) return False # По умолчанию прямой тип записи typeRec = "a" - if options.has_key('t'): + if 't' in options: # Тип модифицируемой записи typeRec = options['t'].lower() supportTypes = ("a","ptr","cname","mx") if not typeRec in supportTypes: self.printERROR(_("Record type %s unsupported")%typeRec) self.printWARNING(_("Supported record types: %s")\ - %", ".join(supportTypes)) + %", ".join(supportTypes)) return False # Проверка на mx совместно с mxmod - if options.has_key('mx') and options.has_key('mxmod'): + if 'mx' in options and 'mxmod' in options: self.printERROR('Command line option "-mx" is incompatible \ -with option "--mxmod"') + with option "--mxmod"') return False # Добавляем кавычки и -- - addQ = lambda y: map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x, y) + addQ = lambda y: [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in y] # Ключи опций - optKeys = options.keys() + optKeys = list(options.keys()) # Обязательные опции requiredOpt = [] # Необязательные опции @@ -18612,14 +18660,14 @@ with option "--mxmod"') typeRec = "cname" else: self.printERROR(_("Incorrect command line options %s")\ - %", ".join(addQ(optKeys))) + %", ".join(addQ(optKeys))) return False # Проверка обязательных опций - if not set(requiredOpt)<=set(optKeys): - notFoundReqOpt = list(set(requiredOpt)-set(optKeys)) + if not set(requiredOpt) <= set(optKeys): + notFoundReqOpt = list(set(requiredOpt) - set(optKeys)) self.printERROR(_('Can not found required command line options %s')\ - %", ".join(addQ(notFoundReqOpt))) + %", ".join(addQ(notFoundReqOpt))) return False if "f" in options.keys(): optionalOpt['f'] = options['f'] @@ -18632,53 +18680,51 @@ with option "--mxmod"') break if errorOptionalOpt: self.printERROR(\ - _('Optional comand line option %s it has a wrong value')\ - %addQ([key])[0]) + _('Optional comand line option %s it has a wrong value')\ + %addQ([key])[0]) self.printWARNING(_('Valid values are the options %s')\ - %addQ([key])[0] + " " + '(%s)'\ - % (" "+_("or")+" ").join(map(lambda x: '"%s"'%x, value))) + %addQ([key])[0] + " " + '(%s)'\ + % (" "+_("or")+" ").join(('"%s"' % x for x in value))) return False # Проверка лишних опций - unnecessaryOpt = list(set(optKeys)-set(requiredOpt+optionalOpt.keys())) + unnecessaryOpt = list(set(optKeys) - set(requiredOpt + list(optionalOpt.keys()))) if unnecessaryOpt: self.printERROR(_("Exists unnecessary command line options %s")\ - %",".join(addQ(unnecessaryOpt))) + %",".join(addQ(unnecessaryOpt))) return False mxServers = [] - if options.has_key('mx'): + if 'mx' in options: # Оключаем модификацию обратной зоны modOther = False # Почтовые серверы для доменного имени if typeRec == "ptr": self.printERROR(_('Command line option "--mx" \ -incompatible with PTR-record (option "-t")')) + incompatible with PTR-record (option "-t")')) return False if typeRec == "cname": self.printERROR(_('Command line option "--mx" \ -incompatible with CNAME-record (option "-t")')) + incompatible with CNAME-record (option "-t")')) return False - mxServers=map(lambda x: delDot(x.lower()), - options['mx'].split(",")) + mxServers = [delDot(x.lower()) for x in options['mx'].split(",")] mxServers = self.unicList(mxServers) # Переименование mx записи # modMxServers[0] - cтарая запись # modMxServers[1] - новая запись modMxServers = [] - if options.has_key('mxmod'): + if 'mxmod' in options: # Отключаем модификацию обратной зоны modOther = False # Почтовые cерверы для доменного имени if typeRec == "ptr": self.printERROR(_('Command line option "--mxmod" \ -incompatible with PTR-record (option "-t")')) + incompatible with PTR-record (option "-t")')) return False if typeRec == "cname": self.printERROR(_('Command line option "--mxmod" \ -incompatible with CNAME-record (option "-t")')) + incompatible with CNAME-record (option "-t")')) return False - modMxServers=map(lambda x: delDot(x.lower()),\ - options['mxmod'].split(",")) + modMxServers = [delDot(x.lower()) for x in options['mxmod'].split(",")] modMxServers = self.unicList(modMxServers) if len(modMxServers)!=2: self.printERROR(_('Incorrect command line option "--mxmod"')) @@ -18686,7 +18732,7 @@ incompatible with CNAME-record (option "-t")')) self.printWARNING("--mxmod old.mail.host,new.mail.host") return False cnameServer = "" - if options.has_key('cname'): + if 'cname' in options: # Оключаем модификацию обратной зоны modOther = False # Доменное имя (имя включающее домен) @@ -18701,7 +18747,7 @@ incompatible with CNAME-record (option "-t")')) newZoneName = "" # Новая запись является CNAME foundNewCnameRecord = False - if options.has_key('host'): + if 'host' in options: # Доменное имя (имя включающее домен) newDomainName = delDot(options['host'].lower()) # Имя хоста, имя зоны @@ -18718,14 +18764,14 @@ incompatible with CNAME-record (option "-t")')) if foundNewDomain: if foundNewCnameRecord: self.printERROR(_("CNAME-record %s exists in LDAP")\ - %newDomainName) + %newDomainName) self.printERROR("%s --> %s"%(newDomainName,\ - delDot(foundNewDomain[0][0][1]['cNAMERecord'][0]))) + delDot(foundNewDomain[0][0][1]['cNAMERecord'][0].decode("UTF-8")))) else: self.printERROR(_("A-record %s exists in LDAP")\ - %newDomainName) + %newDomainName) self.printERROR("%s --> %s"\ - %(newDomainName, foundNewDomain[0][0][1]['aRecord'][0])) + %(newDomainName, foundNewDomain[0][0][1]['aRecord'][0].decode("UTF-8"))) self.printERROR("") return False # Проверка существования обратной записи @@ -18755,23 +18801,24 @@ incompatible with CNAME-record (option "-t")')) if foundNewDomain: if foundNewCnameRecord: self.printERROR(_("CNAME-record %s exists in LDAP")\ - %newDomainName) + %newDomainName) self.printERROR("%s --> %s"%(newDomainName,\ - delDot(foundNewDomain[0][0][1]['cNAMERecord'][0]))) + delDot(foundNewDomain[0][0][1]['cNAMERecord'][0].decode("UTF-8")))) else: self.printERROR(_("A-record %s exists in LDAP")\ - %newDomainName) + %newDomainName) self.printERROR("%s --> %s"\ - %(newDomainName, foundNewDomain[0][0][1]['aRecord'][0])) + %(newDomainName, foundNewDomain[0][0][1]['aRecord'][0]\ + .decode("UTF-8"))) self.printERROR("") return False newIP = "" newZoneNameIP = "" newHostNameIP = "" - if options.has_key('ip'): + if 'ip' in options: if typeRec == "cname": self.printERROR('Command line option "-t cname" \ -is incompatible with option "--ip"') + is incompatible with option "--ip"') return False # newIP адрес newIP = options['ip'] @@ -18797,7 +18844,7 @@ is incompatible with option "--ip"') if foundNewIp: self.printERROR(_("IP address %s exists in LDAP")%newIP) self.printERROR("%s --> %s"%(newIP,\ - delDot(foundNewIp[0][0][1]['pTRRecord'][0]))) + delDot(foundNewIp[0][0][1]['pTRRecord'][0].decode("UTF-8")))) self.printERROR("") return False # Проверка существования обратной записи @@ -18828,7 +18875,7 @@ is incompatible with option "--ip"') if foundNewIp: self.printERROR(_("IP address %s exists in LDAP")%newIP) self.printERROR("%s --> %s"%(newIP,\ - delDot(foundNewIp[0][0][1]['pTRRecord'][0]))) + delDot(foundNewIp[0][0][1]['pTRRecord'][0].decode("UTF-8")))) self.printERROR("") return False # Имена изменяемых зон @@ -18856,15 +18903,15 @@ is incompatible with option "--ip"') # найдена CNAME запись? if self.searchCNameInLDAP(domainName): self.printERROR(_("CNAME-record %s exists in LDAP")\ - %domainName) + %domainName) self.printWARNING(_('Use command line option "-t cname"')) return False foundMain = self.searchDomainNameInLDAP(domainName) if not foundMain: self.printERROR(_("Record %s not exists in LDAP")\ - %domainName) + %domainName) return False - otherIP = delDot(foundMain[0][0][1]['aRecord'][0]) + otherIP = delDot(foundMain[0][0][1]['aRecord'][0].decode("UTF-8")) # Поиcк в обратной зоне в случае необходимости if modOther: dataIP = self.getDomainAndZoneFromIP(otherIP) @@ -18875,14 +18922,14 @@ is incompatible with option "--ip"') foundOther = self.searchAllDomainNamesInLDAP(otherDomain) if not foundOther: self.printERROR(_("PTR-record %s not exists in LDAP")\ - %otherDomain) + %otherDomain) return False # Проверка на соответствие имени хоста - if domainName!=delDot(foundOther[0][0][1]['pTRRecord'][0]): + if domainName!=delDot(foundOther[0][0][1]['pTRRecord'][0].decode("UTF-8")): self.printERROR(_("Found PTR-record %s in LDAP")\ - %otherDomain) + %otherDomain) self.printERROR("%s --> %s"%(otherIP,\ - delDot(foundOther[0][0][1]['pTRRecord'][0]))) + delDot(foundOther[0][0][1]['pTRRecord'][0].decode("UTF-8")))) self.printERROR("") return False # Изменяем в двух зонах @@ -18943,7 +18990,7 @@ is incompatible with option "--ip"') IPs = self.searchIPForHostInReverse(domainName) if not IPs: self.printERROR(_("Can not found %s in reverse zone")\ - %domainName) + %domainName) return False if len(IPs)>1: self.printERROR(_("Found multiple records in reverse zone")) @@ -18968,22 +19015,22 @@ is incompatible with option "--ip"') foundMain = self.searchAllDomainNamesInLDAP(domainNamePTR) if not foundMain: self.printERROR(_("PTR-record %s not exists in LDAP")\ - %domainNamePTR) + %domainNamePTR) return False # Поиcк в обратной зоне в случае необходимости if modOther: - otherDomain = delDot(foundMain[0][0][1]['pTRRecord'][0]) + otherDomain = delDot(foundMain[0][0][1]['pTRRecord'][0].decode("UTF-8")) foundOther = self.searchAllDomainNamesInLDAP(otherDomain) if not foundOther: self.printERROR(_("A-record %s not exists in LDAP")\ - %otherDomain) + %otherDomain) return False # Проверка на соответствие ip хоста - if ip != foundOther[0][0][1]['aRecord'][0]: + if ip != foundOther[0][0][1]['aRecord'][0].decode("UTF-8"): self.printERROR(_("Found A-record %s in LDAP")\ - %otherDomain) + %otherDomain) self.printERROR("%s --> %s"\ - %(otherDomain, foundOther[0][0][1]['aRecord'][0])) + %(otherDomain, foundOther[0][0][1]['aRecord'][0].decode("UTF-8"))) self.printERROR("") return False # Модифицируем PTR запись @@ -18995,7 +19042,7 @@ is incompatible with option "--ip"') return False # Изменение IP A записи (прямая зона) if not self.modARecord(hostName, domainName, zoneName, - otherIP, newIP): + otherIP, newIP): return False # Изменяемая обратная зона namesZones.append(otherZoneName) @@ -19034,8 +19081,8 @@ is incompatible with option "--ip"') # Если изменяется доменное имя # Изменение доменного имени PTR записи (обратная зона) if not self.modPTRRecord(otherIP, otherHostName, - otherDomainName, otherZoneName, - newDomainName): + otherDomainName, otherZoneName, + newDomainName): return False # Изменяемая обратная зона namesZones.append(otherZoneName) @@ -19043,20 +19090,20 @@ is incompatible with option "--ip"') foundMain = self.searchCNameInLDAP(domainName) if not foundMain: self.printERROR(_("CNAME-record %s not exists in LDAP")\ - %domainName) + %domainName) return False # Изменяем cname указатель if cnameServer: if not self.modCNAMERecord(hostName, domainName, zoneName, - cnameServer): + cnameServer): return False # Изменяемая прямая зона namesZones.append(zoneName) # CNAME запись (изменяем имя домена) if newDomainName: - oldCname = delDot(foundMain[0][0][1]['cNAMERecord'][0]) + oldCname = delDot(foundMain[0][0][1]['cNAMERecord'][0].decode("UTF-8")) if not self.moveCNAMERecord(oldCname,domainName, - newDomainName): + newDomainName): return False # Изменяемая прямая зона namesZones.append(zoneName) @@ -19067,27 +19114,28 @@ is incompatible with option "--ip"') foundMain = self.searchDomainNameInLDAP(domainName) if not foundMain: self.printERROR(_("Record %s not exists in LDAP")\ - %domainName) + %domainName) return False flagFoundMX = False - if foundMain[0][0][1].has_key('mXRecord'): + if 'mXRecord' in foundMain[0][0][1]: flagFoundMX = True # Изменяем почтовый хост на другой почтовый хост if modMxServers: if not flagFoundMX: self.printERROR(\ - _("Can not found MX-record in A-record %s")\ - %domainName) + _("Can not found MX-record in A-record %s")\ + %domainName) return False # Находим нужную запись - foundMxServers = map(lambda x: len(x.split(" "))==1\ - and delDot(x) or delDot(x.split(" ")[1]),\ - foundMain[0][0][1]['mXRecord']) + foundMxServers = [len(x.decode("UTF-8").split(" ")) == 1\ + and delDot(x.decode("UTF-8")) + or delDot(x.decode("UTF-8").split(" ")[1]) + for x in foundMain[0][0][1]['mXRecord']] oldMxHost = modMxServers[0] newMxHost = modMxServers[1] if not oldMxHost in foundMxServers: self.printERROR(_("Can not found MX host %s")\ - %oldMxHost +" " + _("in A-record %s")%domainName) + %oldMxHost +" " + _("in A-record %s")%domainName) return False # Проверка наличия новой MX записи в A записи if newMxHost in foundMxServers: @@ -19106,7 +19154,7 @@ is incompatible with option "--ip"') else: addMxServers.append(foundMxServer) if not self.modMXRecord(hostName, domainName, zoneName, - flagFoundMX, addMxServers): + flagFoundMX, addMxServers): return False # Изменяемая прямая зона namesZones.append(zoneName) @@ -19116,7 +19164,7 @@ is incompatible with option "--ip"') if not self.checkMXDomains(mxServers): return False if not self.modMXRecord(hostName, domainName, zoneName, - flagFoundMX, mxServers): + flagFoundMX, mxServers): return False # Изменяемая прямая зона namesZones.append(zoneName) @@ -19130,11 +19178,11 @@ is incompatible with option "--ip"') otherIP = ip if typeRec == "cname": self.printERROR(_('IP address %s')%ip + " " +\ - _('incompatible with CNAME-record (option "-t")')) + _('incompatible with CNAME-record (option "-t")')) return False if "cname" in optKeys: self.printERROR(_('IP address %s')%ip + " " +\ - _('incompatible with CNAME-record (option "--cname")')) + _('incompatible with CNAME-record (option "--cname")')) return False # Поиск модифицируемой записи в DNS # Поиск основной записи @@ -19153,9 +19201,9 @@ is incompatible with option "--ip"') foundMain = self.searchAllDomainNamesInLDAP(domainNamePTR) if not foundMain: self.printERROR(_("PTR-record %s not exists in LDAP")\ - %domainNamePTR) + %domainNamePTR) return False - otherDomain = delDot(foundMain[0][0][1]['pTRRecord'][0]) + otherDomain = delDot(foundMain[0][0][1]['pTRRecord'][0].decode("UTF-8")) # Модификация domainName = otherDomain # Модификация @@ -19165,14 +19213,14 @@ is incompatible with option "--ip"') foundOther = self.searchAllDomainNamesInLDAP(otherDomain) if not foundOther: self.printERROR(_("A-record %s not exists in LDAP")\ - %otherDomain) + %otherDomain) return False # Проверка на соответствие ip хоста - if ip != foundOther[0][0][1]['aRecord'][0]: + if ip != foundOther[0][0][1]['aRecord'][0].decode("UTF-8"): self.printERROR(_("Found A-record %s in LDAP")\ - %otherDomain) + %otherDomain) self.printERROR("%s --> %s"\ - %(otherDomain, foundOther[0][0][1]['aRecord'][0])) + %(otherDomain, foundOther[0][0][1]['aRecord'][0].decode("UTF-8"))) self.printERROR("") return False # Модифицируем PTR запись @@ -19244,17 +19292,17 @@ is incompatible with option "--ip"') # найдена CNAME запись? if self.searchCNameInLDAP(domainName): self.printERROR(_("CNAME-record %s exists in LDAP")\ - %domainName) + %domainName) self.printWARNING(_('Use command line option "-t cname"')) return False foundMain = self.searchDomainNameInLDAP(domainName) if not foundMain: self.printERROR(_("Record %s not exists in LDAP")\ - %domainName) + %domainName) return False # Поиcк в обратной зоне в случае необходимости if modOther: - otherIP = delDot(foundMain[0][0][1]['aRecord'][0]) + otherIP = delDot(foundMain[0][0][1]['aRecord'][0].decode("UTF-8")) dataIP = self.getDomainAndZoneFromIP(otherIP) if not dataIP: self.printERROR(_("IP address %s incorrectly")%otherIP) @@ -19263,14 +19311,14 @@ is incompatible with option "--ip"') foundOther = self.searchAllDomainNamesInLDAP(otherDomain) if not foundOther: self.printERROR(_("PTR-record %s not exists in LDAP")\ - %otherDomain) + %otherDomain) return False # Проверка на соответствие имени хоста - if domainName!=delDot(foundOther[0][0][1]['pTRRecord'][0]): + if domainName != delDot(foundOther[0][0][1]['pTRRecord'][0].decode("UTF-8")): self.printERROR(_("Found PTR-record %s in LDAP")\ - %otherDomain) + %otherDomain) self.printERROR("%s --> %s"%(otherIP,\ - delDot(foundOther[0][0][1]['pTRRecord'][0]))) + delDot(foundOther[0][0][1]['pTRRecord'][0].decode("UTF-8")))) self.printERROR("") return False # Изменяем в двух зонах @@ -19343,24 +19391,25 @@ is incompatible with option "--ip"') %domainName) return False flagFoundMX = False - if foundMain[0][0][1].has_key('mXRecord'): + if 'mXRecord' in foundMain[0][0][1]: flagFoundMX = True # Изменяем почтовый хост на другой почтовый хост if modMxServers: if not flagFoundMX: self.printERROR(\ - _("Can not found MX-record in A-record %s")\ - %domainName) + _("Can not found MX-record in A-record %s")\ + %domainName) return False # Находим нужную запись - foundMxServers = map(lambda x: len(x.split(" "))==1\ - and delDot(x) or delDot(x.split(" ")[1]),\ - foundMain[0][0][1]['mXRecord']) + foundMxServers = [len(x.decode("UTF-8").split(" ")) == 1\ + and delDot(x.decode("UTF-8")) + or delDot(x.decode("UTF-8").split(" ")[1]) + for x in foundMain[0][0][1]['mXRecord']] oldMxHost = modMxServers[0] newMxHost = modMxServers[1] if not oldMxHost in foundMxServers: self.printERROR(_("Can not found MX host %s")\ - %oldMxHost +" " + _("in A-record %s")%domainName) + %oldMxHost +" " + _("in A-record %s")%domainName) return False # Проверка существования A записи для MX хоста if not self.checkMXDomains([newMxHost]): @@ -19445,7 +19494,7 @@ is incompatible with option "--ip"') data = foundOld[0][0][1] data["zoneName"] = [newZoneName] data["relativeDomainName"] = [newHostName] - domainEntry = data.items() + domainEntry = [x.encode("UTF-8") for x in data.items()] # Добавляем новую запись baseDN = self.clVars.Get("ld_dns_dn") ouZonesDN = self.getOUZonesDN(newZoneName) @@ -19479,20 +19528,20 @@ is incompatible with option "--ip"') # Проверим установлен ли сервис dns if not self.isServiceSetup("dns"): return False - optKeys = options.keys() + optKeys = list(options.keys()) # Опция force if "f" in optKeys: checkDHCPConfig = False # По умолчанию прямой тип записи typeRec = "a" - if options.has_key('t'): + if 't' in options: # Тип добавлямой записи typeRec = options['t'].lower() supportTypes = ("a","ptr","cname") if not typeRec in supportTypes: self.printERROR(_("Record type %s unsupported")%typeRec) self.printWARNING(_("Supported record types: %s")\ - %", ".join(supportTypes)) + %", ".join(supportTypes)) return False if typeRec == "cname": minKeys = ["cname","host"] @@ -19500,21 +19549,20 @@ is incompatible with option "--ip"') minKeys = ["host","ip"] if not set(minKeys)<=set(optKeys): notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ - %", ".join(notFoundKeys)) + %", ".join(notFoundKeys)) return False # Флаг автоматического создания PTR записи createPtr = True - if options.has_key('autoptr'): + if 'autoptr' in options: if typeRec == "ptr": self.printERROR(_('Command line option "--autoptr" \ -incompatible with type DNS record PTR (option "-t")')) + incompatible with type DNS record PTR (option "-t")')) return False if typeRec == "cname": self.printERROR(_('Command line option "--autoptr" \ -incompatible with type DNS record CNAME (option "-t")')) + incompatible with type DNS record CNAME (option "-t")')) return False autoPtr = options['autoptr'] if autoPtr == "on": @@ -19523,14 +19571,14 @@ incompatible with type DNS record CNAME (option "-t")')) createPtr = False else: self.printERROR(_('Command line option "--autoptr %s" \ -incorrect, use "--autoptr on" or "--autoptr off"')%autoPtr) + incorrect, use "--autoptr on" or "--autoptr off"')%autoPtr) return False # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) domainName = "" hostName = "" zoneName = "" - if options.has_key('host'): + if 'host' in options: # Доменное имя (имя включающее домен) domainName = delDot(options['host'].lower()) # Имя хоста, имя зоны @@ -19541,14 +19589,14 @@ incorrect, use "--autoptr on" or "--autoptr off"')%autoPtr) cnDomainName = "" cnHostName = "" cnZoneName = "" - if options.has_key('cname'): - if options.has_key('ip'): + if 'cname' in options: + if 'ip' in options: self.printERROR(_('Command line option "--ip" incompatible \ -with type DNS record CNAME (option "-t")')) + with type DNS record CNAME (option "-t")')) return False - if options.has_key('mx'): + if 'mx' in options: self.printERROR(_('Command line option "--mx" incompatible \ -with type DNS record CNAME (option "-t")')) + with type DNS record CNAME (option "-t")')) return False # Доменное каноническое имя (имя включающее домен) для CNAME cnDomainName = delDot(options['cname'].lower()) @@ -19558,7 +19606,7 @@ with type DNS record CNAME (option "-t")')) self.printERROR(_("Domain name %s incorrectly")%cnDomainName) return False ip = "" - if options.has_key('ip'): + if 'ip' in options: # ip адрес ip = options['ip'] if "," in ip or not self.isCorrectStringNet(ip, False): @@ -19573,14 +19621,13 @@ with type DNS record CNAME (option "-t")')) if not servDhcpObj.isCorrectStaticIP(ip): return False mxServers = [] - if options.has_key('mx'): + if 'mx' in options: # Почтовые серверы для доменного имени if typeRec == "ptr": self.printERROR(_('Command line option "--mx" incompatible \ -with type DNS record PTR (option "-t")')) + with type DNS record PTR (option "-t")')) return False - mxServers = map(lambda x: delDot(x.lower()),\ - options['mx'].split(",")) + mxServers = [delDot(x.lower()) for x in options['mx'].split(",")] mxServers = self.unicList(mxServers) ret = False # Флаг создания A записи @@ -19634,36 +19681,36 @@ with type DNS record PTR (option "-t")')) # Поиск имени хоста if not self.searchDomainNameInLDAP(cnDomainName): self.printERROR(_("Can not found A-record %s in LDAP")\ - %cnDomainName) + %cnDomainName) return False # Поиск зоны if not self.searchZoneInLDAP(zoneName): - self.printERROR(_("Can not found DNS zone %s in LDAP")%zoneName) + self.printERROR(_("Can not found DNS zone %s in LDAP") % zoneName) return False # Поиск CNAME записи findCName = self.searchCNameInLDAP(domainName) if findCName: self.printERROR(_("CNAME-record %s exists in LDAP")\ - %domainName) + %domainName) cnameHosts = findCName[0][0][1]['cNAMERecord'] for cnameHost in cnameHosts: - self.printERROR("%s --> %s"%(domainName,cnameHost)) + self.printERROR("%s --> %s"%(domainName,cnameHost.decode("UTF-8"))) self.printERROR("") return False # Метод добавляющий в конце текста точку если ее нет addDot = lambda x: (len(x)>0 and x[-1]!="." and "%s."%x) or x - domainEntry = [('objectclass', ['top','dNSZone']), - ('relativeDomainName', [hostName]), - ('dNSClass', ['IN']), - ('zoneName',[zoneName]), - ('cNAMERecord',[addDot(cnDomainName)])] + domainEntry = [('objectclass', [b'top', b'dNSZone']), + ('relativeDomainName', [hostName.encode("UTF-8")]), + ('dNSClass', [b'IN']), + ('zoneName', [zoneName.encode("UTF-8")]), + ('cNAMERecord', [addDot(cnDomainName).encode("UTF-8")])] baseDN = self.clVars.Get("ld_dns_dn") ouZonesDN = self.getOUZonesDN(zoneName) zoneBaseDN = "zoneName=%s,%s,%s" %(zoneName, ouZonesDN, baseDN) domainDN = self.addDN("relativeDomainName=%s"%hostName,zoneBaseDN) errorMessage = _("Can not add CNAME-record in LDAP") # Добавляем запись для хоста - if not self.addEntry(domainDN, domainEntry,errorMessage): + if not self.addEntry(domainDN, domainEntry, errorMessage): return False # Увеличиваем на 1 серийный номер зоны if not self.incrementSerialNumberZone(zoneName): @@ -19673,7 +19720,7 @@ with type DNS record PTR (option "-t")')) def checkTimeValue(self, timeValue): """Проверяет корректность переменной времени""" # разбиваем строку на символы - charList = map(lambda x: timeValue[x:x+1], range(len(timeValue))) + charList = [timeValue[x:x + 1] for x in range(len(timeValue))] if not charList: return False # Проверяем последний символ на число @@ -19699,12 +19746,10 @@ with type DNS record PTR (option "-t")')) (зона для доменного имени существует, доменного имени в ней нет) """ # Имена серверов которые могут находится в существующих зонах - serversInZones = filter(lambda x:\ - self.searchZoneInLDAP(x.partition(".")[2]),\ - namesServers) - notFoundServers = filter(lambda x:\ - not self.searchDomainNameInLDAP(x),\ - serversInZones) + serversInZones = [x for x in namesServers + if self.searchZoneInLDAP(x.partition(".")[2])] + notFoundServers = [x for x in serversInZones + if not self.searchDomainNameInLDAP(x)] return notFoundServers @@ -19713,15 +19758,17 @@ with type DNS record PTR (option "-t")')) notFoundMailServers = self.getNotFoundRecords(namesMailServers) if notFoundMailServers: self.printERROR(\ - _("Can not found A-records for MX-records - %s")\ - %", ".join(notFoundMailServers)) + _("Can not found A-records for MX-records - %s")\ + %", ".join(notFoundMailServers)) self.printWARNING(\ _("First, add the A-records required for MX-records")) return False return True - def addDNSRecord(self, domainName, ipAddrOrHost, namesMailServers=[]): + def addDNSRecord(self, domainName, ipAddrOrHost, namesMailServers=None): """Добавляем DNS запись в LDAP прямую или обратную""" + if namesMailServers is None: + namesMailServers = [] hostName, spl, zoneName = domainName.partition(".") # При поиске зоны создается объект переменных и соединение LDAP if not self.searchZoneInLDAP(zoneName): @@ -19729,12 +19776,12 @@ with type DNS record PTR (option "-t")')) return False if self.searchDomainNameInLDAP(domainName): self.printERROR(_("Record %s exists in LDAP")\ - %domainName) + %domainName) return False # Поиск CNAME записи if self.searchCNameInLDAP(domainName): self.printERROR(_("CNAME-record %s exists in LDAP")\ - %domainName) + %domainName) return False flagForward = self.isForwardZone(zoneName) # Метод добавляющий в конце текста точку если ее нет @@ -19743,22 +19790,22 @@ with type DNS record PTR (option "-t")')) # Проверка существования A записей для MX хостов if not self.checkMXDomains(namesMailServers): return False - namesMailServersDot = map(lambda x: addDot(x), namesMailServers) - domainEntry = [('objectclass', ['top','dNSZone']), - ('relativeDomainName', [hostName]), - ('dNSClass', ['IN']), - ('zoneName',[zoneName]), - ('aRecord',[ipAddrOrHost])] - mxValues=map(lambda x: "%s %s" %(x*10+10, namesMailServersDot[x]),\ - range(len(namesMailServersDot))) + namesMailServersDot = [addDot(x).encode("UTF-8") for x in namesMailServers] + domainEntry = [('objectclass', [b'top', b'dNSZone']), + ('relativeDomainName', [hostName.encode("UTF-8")]), + ('dNSClass', [b'IN']), + ('zoneName',[zoneName.encode("UTF-8")]), + ('aRecord',[ipAddrOrHost.encode("UTF-8")])] + mxValues = [b"%s %s" % (x * 10 + 10, namesMailServersDot[x]) + for x in range(len(namesMailServersDot))] if mxValues: # Добавляем MX записи domainEntry.append(('mXRecord', mxValues)) else: - domainEntry = [('objectclass', ['top','dNSZone']), - ('relativeDomainName', [hostName]), - ('zoneName',[zoneName]), - ('pTRRecord',[addDot(ipAddrOrHost)])] + domainEntry = [('objectclass', [b'top', b'dNSZone']), + ('relativeDomainName', [hostName.encode("UTF-8")]), + ('zoneName',[zoneName.encode("UTF-8")]), + ('pTRRecord',[addDot(ipAddrOrHost).encode("UTF-8")])] baseDN = self.clVars.Get("ld_dns_dn") ouZonesDN = self.getOUZonesDN(zoneName) zoneBaseDN = "zoneName=%s,%s,%s" %(zoneName, ouZonesDN, baseDN) @@ -19768,7 +19815,7 @@ with type DNS record PTR (option "-t")')) else: errorMessage = _("Can not add PTR-record in LDAP") # Добавляем запись для хоста - if not self.addEntry(domainDN, domainEntry,errorMessage): + if not self.addEntry(domainDN, domainEntry, errorMessage): return False # Увеличиваем на 1 серийный номер зоны if not self.incrementSerialNumberZone(zoneName): @@ -19803,9 +19850,9 @@ with type DNS record PTR (option "-t")')) foundNames = self.searchDomainNameInLDAP("@.%s"%zoneName) if not foundNames: self.printERROR(_("Can not found SOA-record in DNS zone %s")\ - %zoneName) + %zoneName) return False - sOARecord = foundNames[0][0][1]['sOARecord'][0] + sOARecord = foundNames[0][0][1]['sOARecord'][0].decode("UTF-8") sOAList = sOARecord.split(" ") if len(sOAList)!=7: self.printERROR(_("Incorrect SOA-record in DNS zone %s")%zoneName) @@ -19815,16 +19862,16 @@ with type DNS record PTR (option "-t")')) except: self.printERROR(_("Incorrect SOA-record in DNS zone %s")%zoneName) self.printERROR(_("Incorrect serial number %s in SOA-record")\ - %str(sOAList[2])) + %str(sOAList[2])) return False sOAList[2] = serialNumber sOARecord = " ".join(sOAList) relZoneDN = self.getRelZoneDN(zoneName) - modAttrs = [(ldap.MOD_REPLACE, 'sOARecord', sOARecord)] + modAttrs = [(ldap.MOD_REPLACE, 'sOARecord', sOARecord.encode("UTF-8"))] DN = self.addDN("relativeDomainName=@", relZoneDN) if not self.modAttrsDN(DN, modAttrs): self.printERROR(_("Can not write new serial number for zone %s \ -in LDAP")%zoneName) + in LDAP")%zoneName) return False return True @@ -19835,8 +19882,8 @@ in LDAP")%zoneName) self.clVars должен быть определен """ - print _("Enter the allowed ip addresses and network for %s service")\ - %"DNS" + " (" + _("comma or space delimited") + ")" + print(_("Enter the allowed ip addresses and network for %s service")\ + %"DNS" + " (" + _("comma or space delimited") + ")") strPrompt = _("allow networks: ") netAllow = self.clVars.Get("sr_dns_net_allow") strNetAllow = "" @@ -19854,12 +19901,11 @@ in LDAP")%zoneName) """Проверка ключа sdb-ldap bind""" pathBind = "/var/db/pkg/net-dns" if os.path.exists(pathBind): - subPathsBind = filter(lambda x: re.search("bind-\d",x),\ - os.listdir(pathBind)) + subPathsBind = [x for x in os.listdir(pathBind) if re.search("bind-\d", x)] if subPathsBind: - pathsUSE = (os.path.join(pathBind,subPathsBind[0],"IUSE"), - os.path.join(pathBind,subPathsBind[0],"USE")) - if filter(lambda x: not os.path.exists(x), pathsUSE): + pathsUSE = (os.path.join(pathBind, subPathsBind[0], "IUSE"), + os.path.join(pathBind, subPathsBind[0], "USE")) + if [x for x in pathsUSE if not os.path.exists(x)]: return False for pathUSE in pathsUSE: flagFound = False @@ -19882,11 +19928,11 @@ in LDAP")%zoneName) if not self.checkSDBLDAP(): self.printERROR(_('Can not found USE="sdb-ldap" in package bind')) self.printWARNING(_('Key USE="sdb-ldap" added to the package \ -net-dns/bind version>=9.6.1')) + net-dns/bind version>=9.6.1')) return False # Принудительная установка forceOptions = False - if options.has_key("f"): + if "f" in options: forceOptions = True # Создаем объект переменных self.createClVars() @@ -19899,7 +19945,7 @@ net-dns/bind version>=9.6.1')) if self.clVars.Get("sr_dns_set") == "on" and\ not forceOptions: self.printWARNING (_("WARNING") + ": " +\ - _("DNS server is configured")+ ".") + _("DNS server is configured")+ ".") return True # Доверительные сети по умолчанию allowNet = self.clVars.Get("os_net_allow") @@ -19916,13 +19962,13 @@ net-dns/bind version>=9.6.1')) _("input 'yes'") +", "+ _("if not 'no'") if not self.dialogYesNo(messDialog): return True - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: return False else: - if options.has_key("a"): + if "a" in options: # Получаем от пользователя доверительные сети allowNet = self.getAllowNet() if not allowNet: @@ -20004,7 +20050,7 @@ net-dns/bind version>=9.6.1')) if not self.ldapObj.getError(): self.ldapObj.ldapAdd(baseLdif) if self.ldapObj.getError(): - print _("LDAP Error") + ": " + self.ldapObj.getError().strip() + print(_("LDAP Error") + ": " + self.ldapObj.getError().strip()) return False # Записываем данные администратора сервиса Proxy ldapParser = iniLdapParser() @@ -20049,15 +20095,13 @@ class servDhcp(shareLdap, shareIP): # Проверим установлен ли сервис dhcp if checkSetup and not self.isServiceSetup("dhcp"): return False - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = ["host", "ip", "mac"] # Проверка на наличие всех нужных опций - if not set(minKeys)<=set(optKeys): - notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) - self.printERROR(_("Not enough command line options: %s")\ - %", ".join(notFoundKeys)) + if not set(minKeys) <= set(optKeys): + notFoundKeys = list(set(minKeys) - set(optKeys)) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys] + self.printERROR(_("Not enough command line options: %s") % ", ".join(notFoundKeys)) return False # имя хоста hostname = options["host"] @@ -20127,25 +20171,25 @@ class servDhcp(shareLdap, shareIP): for net, data in dataNets: if netNoMask == net: notFoundOpts = [] - if data.has_key("range"): - ranges = filter(lambda x: x.strip(), data["range"]) + if "range" in data: + ranges = [x for x in data["range"] if x.strip()] if not ranges: notFoundOpts.append(("range", "--range ")) - if data.has_key("optiondomain-name-servers"): + if "optiondomain-name-servers" in data: dnsIPs = data["optiondomain-name-servers"][0].split(",") if not dnsIPs: notFoundOpts.append(("option domain-name-servers", "--dnsip ")) - if data.has_key("optiondomain-name"): - domainNames = map(lambda x: x.strip().replace('"',''),\ - data["optiondomain-name"]) + if "optiondomain-name" in data: + domainNames = [x.strip().replace('"', '') + for x in data["optiondomain-name"]] if not domainNames: notFoundOpts.append(("option domain-name", "--dnames ")) if notFoundOpts: - optionsPr = map(lambda x: "'%s'"%x[0], notFoundOpts) - optionsCmdPr = map(lambda x: x[1], notFoundOpts) + optionsPr = ["'%s'" % x[0] for x in notFoundOpts] + optionsCmdPr = [x[1] for x in notFoundOpts] self.printERROR(_("Can not create DNS zone %s") %net) self.printERROR(\ _('Can not found %s')%",".join(optionsPr) + " "+\ @@ -20190,9 +20234,9 @@ class servDhcp(shareLdap, shareIP): ipNumb = self.getNumberIP(ip) domainNames = [] if isRange(ipNumb, minNumber, maxNumber): - if data.has_key("optiondomain-name"): - domainNames = map(lambda x: x.strip().replace('"',''),\ - data["optiondomain-name"]) + if "optiondomain-name" in data: + domainNames = [x.strip().replace('"','') + for x in data["optiondomain-name"]] break else: self.printERROR(\ @@ -20236,16 +20280,15 @@ class servDhcp(shareLdap, shareIP): minNumber, maxNumber = self.getMinAndMaxIpNumb(net) osNets = self.clVars.Get("os_net_allow") serverNets = osNets.split(',') - dataMinMaxIP = map(lambda x: self.getMinAndMaxIpNumb(x), serverNets) + dataMinMaxIP = [self.getMinAndMaxIpNumb(x) for x in serverNets] # Проверка на попадание в диапазон сети isRange = lambda n, minN, maxN: minN<=n<=maxN - if filter(lambda x: isRange(minNumber,x[0],x[1]) and\ - isRange(maxNumber,x[0],x[1]), dataMinMaxIP): + if [x for x in dataMinMaxIP if isRange(minNumber, x[0], x[1]) and isRange(maxNumber, x[0], x[1])]: return True self.printERROR("Can not found network %s in network interfaces: \ -eth0, eth1, ... etc."%net) + eth0, eth1, ... etc."%net) if osNets: - self.printWARNING(_("Existing nets: %s")%osNets) + self.printWARNING(_("Existing nets: %s") % osNets) return False def isCorrectMacAddress(self, mac): @@ -20256,7 +20299,8 @@ eth0, eth1, ... etc."%net) flagOK = True for hexNumber in macNumbers: try: - exec("0x%s"%hexNumber) + # exec("0x%s"%hexNumber) + tmp = int(hexNumber, 16) except: flagOK = False break @@ -20281,7 +20325,7 @@ eth0, eth1, ... etc."%net) _("in config file %s") %dhcpObj.nameConfigFile) return False ip = "" - if options.has_key("ip"): + if "ip" in options: # ip адрес хоста ip = options["ip"] # проверка правильности ip @@ -20302,7 +20346,7 @@ eth0, eth1, ... etc."%net) if not self.modifyDNSHostIP(fullHostName, ip): return False mac = "" - if options.has_key("mac"): + if "mac" in options: # mac адрес хоста mac = options["mac"] if mac: @@ -20351,7 +20395,7 @@ eth0, eth1, ... etc."%net) xmlNodesNet = dhcpObj.getXMLNet(network) # ip роутера router = "" - if options.has_key("router"): + if "router" in options: router = options["router"] # Проверка коректности ip роутера if "," in router or not self.isCorrectStringNet(router, False): @@ -20361,13 +20405,13 @@ eth0, eth1, ... etc."%net) self.printERROR(_("IP address %s incorrectly")%router) return False domainNames = [] - if options.has_key("dnames"): + if "dnames" in options: # доменные имена для поиска - domainNames = map(lambda x: x.lower(), options["dnames"].split(",")) + domainNames = [x.lower() for x in options["dnames"].split(",")] domainNames = self.unicList(domainNames) # проверка доменных имен на ip - incorrectDomains = filter(lambda x:\ - self.isCorrectStringNet(x, False), domainNames) + incorrectDomains = [x for x in domainNames + if self.isCorrectStringNet(x, False)] if incorrectDomains: self.printERROR(_('Incorrect command line option "--dnames"')) self.printWARNING(_("Example") + ":") @@ -20375,7 +20419,7 @@ eth0, eth1, ... etc."%net) return False dhcpObj = dncpTxt() ranges = [] - if options.has_key("range"): + if "range" in options: # Диапазон динамических ip ranges = self.isCorrectIPRangeListAndSort(net, options["range"].split(",")) @@ -20393,7 +20437,7 @@ eth0, eth1, ... etc."%net) return False dnsIP = "" # ip адреса dns серверов - if options.has_key("dnsip"): + if "dnsip" in options: dnsIP = options["dnsip"] # проверка правильности ip if not self.isCorrectStringNet(dnsIP, False) or\ @@ -20423,14 +20467,13 @@ eth0, eth1, ... etc."%net) hostname = self.servDnsObj.clVars.Get("os_net_hostname") if hostname: zone = oldDomainNames[0] - fullServerDNSName = "%s.%s"%(hostname,zone) - if not filter(lambda x: fullServerDNSName==x[0],\ - moveRecords): + fullServerDNSName = "%s.%s" % (hostname, zone) + if not [x for x in moveRecords if fullServerDNSName == x[0]]: foundServ = self.servDnsObj.searchDomainNameInLDAP(\ fullServerDNSName) if foundServ: - serverIP = foundServ[0][0][1]['aRecord'][0] - moveRecords.append((fullServerDNSName,serverIP)) + serverIP = foundServ[0][0][1]['aRecord'][0].decode("UTF-8") + moveRecords.append((fullServerDNSName, serverIP)) data = [oldDnsIPs, oldRanges, net] if not self.modifyDNSZoneName(oldDomainNames[0], domainNames[0], moveRecords, data): @@ -20465,13 +20508,13 @@ eth0, eth1, ... etc."%net) # Проверим установлен ли сервис dhcp if not self.isServiceSetup("dhcp"): return False - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = ["host"] # Проверка на наличие всех нужных опций - if not set(minKeys)<=set(optKeys): - notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + if not set(minKeys) <= set(optKeys): + notFoundKeys = list(set(minKeys) - set(optKeys)) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x + for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ %", ".join(notFoundKeys)) return False @@ -20490,7 +20533,7 @@ eth0, eth1, ... etc."%net) # Находим ip хоста dataHosts = dhcpObj.getDataInAllHost() for host, data in dataHosts: - if hostname == host and data.has_key("fixed-address"): + if hostname == host and "fixed-address" in data: if data["fixed-address"]: ip = data["fixed-address"][0] break @@ -20518,8 +20561,7 @@ eth0, eth1, ... etc."%net) self.printERROR(_("Can not found networks in config file %s")\ %dhcpObj.nameConfigFile) return False - getPar = lambda opt, data: map(lambda x: opt in x[1].keys() and\ - (x[0],x[1][opt]) or (), data) + getPar = lambda opt, data: [opt in x[1].keys() and (x[0], x[1][opt]) or () for x in data] nets = getPar('mask', dataNets) if not nets: self.printERROR(\ @@ -20549,13 +20591,12 @@ eth0, eth1, ... etc."%net) # Проверим установлен ли сервис dhcp if not self.isServiceSetup("dhcp"): return False - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = ["net"] # Проверка на наличие всех нужных опций if not set(minKeys)<=set(optKeys): notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ %", ".join(notFoundKeys)) return False @@ -20598,19 +20639,19 @@ eth0, eth1, ... etc."%net) FD = open(self.resolvFile) lines = FD.readlines() FD.close() - linesSearchDomains = filter(lambda x: "search " in x or\ - "search\t" in x, lines) + linesSearchDomains = [x for x in lines if "search " in x or\ + "search\t" in x] if linesSearchDomains: - searchDomains = filter(lambda x: x,\ - linesSearchDomains[0].partition("search")[2].replace("\t",\ - " ").split(" ")) - return map(lambda x: x.rstrip(), searchDomains) + searchDomains = [x for x in linesSearchDomains[0].\ + partition("search")[2].replace("\t",\ + " ").split(" ") if x] + return [x.rstrip() for x in searchDomains] def createResolvFile(self, searchDomains): """Создание и модификация /etc/resolv.conf""" dnsIP = "127.0.0.1" - mode = 0644 - domainNames = map(lambda x: x.lower(), searchDomains.split(",")) + mode = 0o644 + domainNames = [x.lower() for x in searchDomains.split(",")] domainNames = self.unicList(domainNames) searchDomains = " ".join(domainNames) if not os.path.exists(self.resolvFile): @@ -20633,7 +20674,7 @@ eth0, eth1, ... etc."%net) def createHostsFile(self, fullHostName): """Создание и модификация /etc/hosts""" dnsIP = "127.0.0.1" - mode = 0644 + mode = 0o644 hostname, spl, domainName = fullHostName.partition(".") if not domainName: domainName = "local" @@ -20669,13 +20710,12 @@ eth0, eth1, ... etc."%net) # Проверим установлен ли сервис dhcp if checkSetup and not self.isServiceSetup("dhcp"): return False - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = ["net", "router", "range", "dnames", "dnsip"] # Проверка на наличие всех нужных опций if not set(minKeys)<=set(optKeys): notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ %", ".join(notFoundKeys)) return False @@ -20699,12 +20739,12 @@ eth0, eth1, ... etc."%net) return False # доменные имена для поиска domainNames = [] - if options.has_key("dnames"): - domainNames = map(lambda x: x.lower(), options["dnames"].split(",")) + if "dnames" in options: + domainNames = [x.lower() for x in options["dnames"].split(",")] domainNames = self.unicList(domainNames) # проверка доменных имен на ip - incorrectDomains = filter(lambda x:\ - self.isCorrectStringNet(x, False), domainNames) + incorrectDomains = [x for x in domainNames + if self.isCorrectStringNet(x, False)] if incorrectDomains: self.printERROR(_('Incorrect command line option "--dnames"')) self.printWARNING(_("Example") + ":") @@ -20720,7 +20760,7 @@ eth0, eth1, ... etc."%net) return False dnsIP = "" # ip адреса dns серверов - if options.has_key("dnsip"): + if "dnsip" in options: dnsIP = options["dnsip"] # проверка правильности ip if not self.isCorrectStringNet(dnsIP, False) or\ @@ -20754,8 +20794,8 @@ eth0, eth1, ... etc."%net) recData = self.servDnsObj.searchAllDomainNamesInLDAP(fullHostName) ip = "" if recData: - if recData[0][0][1].has_key('aRecord'): - ip = recData[0][0][1]['aRecord'][0] + if 'aRecord' in recData[0][0][1]: + ip = recData[0][0][1]['aRecord'][0].decode("UTF-8") # Удаляем A запись if not self.servDnsObj.delRecordDnsServer({"host":fullHostName}, False): @@ -20773,12 +20813,11 @@ eth0, eth1, ... etc."%net) deleteIP = self.servDnsObj.searchIPForHostInReverse(\ fullHostName) if recData: - if recData[0][0][1].has_key('pTRRecord'): + if 'pTRRecord' in recData[0][0][1]: hostList = recData[0][0][1]['pTRRecord'] # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x,\ - y.split("."))) - hostList = map(lambda x: delDot(x),hostList) + delDot = lambda y: ".".join(x for x in y.split(".") if x) + hostList = [delDot(x.decode("UTF-8")) for x in hostList] if not fullHostName in hostList: deleteIP.append(ip) deleteIP = list(set(deleteIP)) @@ -20806,7 +20845,7 @@ eth0, eth1, ... etc."%net) return False if recData: flagDelARecord = True - if recData[0][0][1].has_key('aRecord'): + if 'aRecord' in recData[0][0][1]: aRecords = recData[0][0][1]['aRecord'] if ip in aRecords: flagCreateARecord = False @@ -20818,7 +20857,7 @@ eth0, eth1, ... etc."%net) # Проверка на диапазон адресов flagCorrect, flagError =\ self.isCorrectDynamicIP(\ - fullHostName.partition(".")[0], ipAdr, dhcpObj, + fullHostName.partition(".")[0], ipAdr.decode("UTF-8"), dhcpObj, False) if flagError: return False @@ -20885,14 +20924,13 @@ eth0, eth1, ... etc."%net) # Флаг создания обратной записи flagCreatePTRRecord = True if recData: - if recData[0][0][1].has_key('pTRRecord'): + if 'pTRRecord' in recData[0][0][1]: hostList = recData[0][0][1]['pTRRecord'] # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x,\ - y.split("."))) - hostList = map(lambda x: delDot(x),hostList) + delDot = lambda y: ".".join(x for x in y.split(".") if x) + hostList = [delDot(x.decode("UTF-8")) for x in hostList] if fullHostName in hostList: - deleteIP = filter(lambda x: x!=ip, deleteIP) + deleteIP = [x for x in deleteIP if x != ip] flagCreatePTRRecord = False else: deleteIP.append(ip) @@ -20940,27 +20978,27 @@ eth0, eth1, ... etc."%net) self.printERROR = printERROR self.servDnsObj.printERROR = printERROR - optKeys = options.keys() + optKeys = list(options.keys()) minKeys = ["ip", "domain", "host", "s", "b"] # Проверка на наличие всех нужных опций - if not set(minKeys)<=set(optKeys): - notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + if not set(minKeys) <= set(optKeys): + notFoundKeys = list(set(minKeys) - set(optKeys)) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x + for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ %", ".join(notFoundKeys)) return False optPwd = ["p","P"] - listOptPwd = filter(lambda x: x in optPwd, options.keys()) + listOptPwd = [x for x in options.keys() if x in optPwd] if len(listOptPwd) > 1: self.printERROR(_("Command line options '-p' and '-P' are \ incompatible, use one of the options")) return False adminDn = options['s'] - if options.has_key("p"): + if "p" in options: adminPw = options['p'] - elif options.has_key("P"): + elif "P" in options: pathPasswd = options['P'] if os.path.exists(pathPasswd): try: @@ -20982,7 +21020,7 @@ incompatible, use one of the options")) self.printERROR(_("IP address %s incorrectly")%ip) return False domain = options['domain'] - listDomain = filter(lambda x: x.strip(), domain.split(" ")) + listDomain = [x for x in domain.split(" ") if x.strip()] if not listDomain: self.printERROR(_('Incorrect command line option "--domain"')) return False @@ -21029,7 +21067,7 @@ incompatible, use one of the options")) # Поиск статических DHCP хостов в DNS for hostname, data in dataHosts: ip = "" - if not data.has_key("fixed-address"): + if "fixed-address" not in data: self.printERROR(_("Can not found ip static host %s")\ %hostname+ " " + _("in config file %s")\ %dhcpObj.nameConfigFile) @@ -21052,7 +21090,7 @@ incompatible, use one of the options")) recData = self.servDnsObj.searchAllDomainNamesInLDAP(\ fullDomainName) if recData: - if recData[0][0][1].has_key('aRecord'): + if 'aRecord' in recData[0][0][1]: aRecords = recData[0][0][1]['aRecord'] if ip in aRecords: retData[fullDomainName] = ip @@ -21060,7 +21098,7 @@ incompatible, use one of the options")) self.printERROR(_("DHCP static host %s")%hostname) self.printERROR(_("DHCP ip %s")%ip) self.printERROR(_("DNS host %s")%fullDomainName) - self.printERROR(_("DNS ip %s")%",".join(aRecords)) + self.printERROR(_("DNS ip %s")%",".join(x.decode("UTF_8") for x in aRecords)) self.printERROR(_("IP addresses do not match")) flagError = True break @@ -21085,7 +21123,7 @@ incompatible, use one of the options")) retData.update(dynamicHosts) if flagError: return False - return retData.items() + return list(retData.items()) def foundDynamicDNSRecords(self, zoneName, minIpRange, maxIpRange): """Находит имена динамических хостов @@ -21100,12 +21138,12 @@ incompatible, use one of the options")) domainName = "%s.%s"\ %(record[0][1]["relativeDomainName"][0],\ zoneName) - if record[0][1].has_key("aRecord"): + if "aRecord" in record[0][1]: ip = record[0][1]["aRecord"][0] # ip в диапазоне динамических адресов if isRange(self.getNumberIP(ip), minIpRange, maxIpRange): retData[domainName] = ip - return retData.items() + return list(retData.items()) def removeDynamicDNSRecords(self, netAndMask): """Удаляет динамические адреса для сети""" @@ -21139,7 +21177,7 @@ incompatible, use one of the options")) def moveDNSRecords(self, newZoneName, moveRecords): """Перенос записей в новую зону""" # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x, y.split("."))) + delDot = lambda y: ".".join(x for x in y.split(".") if x) flagError = False for hostname, ip in moveRecords: newHostName = ".".join([hostname.partition(".")[0],newZoneName]) @@ -21148,7 +21186,7 @@ incompatible, use one of the options")) foundMain = self.servDnsObj.searchDomainNameInLDAP(hostname) if not foundMain: continue - otherIP = foundMain[0][0][1]['aRecord'][0] + otherIP = foundMain[0][0][1]['aRecord'][0].decode("UTF-8") # Поиcк в обратной зоне dataIP = self.servDnsObj.getDomainAndZoneFromIP(otherIP) otherHostName, otherDomain, otherZoneName = dataIP @@ -21169,12 +21207,12 @@ incompatible, use one of the options")) # Поиск в новой зоне A записи foundNewARec = self.servDnsObj.searchDomainNameInLDAP(newHostName) if foundNewARec: - if foundNewARec[0][0][1].has_key('aRecord'): - if foundNewARec[0][0][1]['aRecord'][0] != otherIP: + if 'aRecord' in foundNewARec[0][0][1]: + if foundNewARec[0][0][1]['aRecord'][0].decode("UTF-8") != otherIP: self.printERROR(_("Record %s exists in DNS service")\ %newHostName) self.printERROR("%s --> %s"%(newHostName,\ - foundNewARec[0][0][1]['aRecord'][0])) + foundNewARec[0][0][1]['aRecord'][0].decode("UTF-8"))) self.printERROR("") flagError = True break @@ -21253,8 +21291,7 @@ incompatible, use one of the options")) dnsIP = ",".join(dnsIPs) if not self.servDnsObj.searchZoneInLDAP(zoneName): # Находим все ip DNS cервера - IPs = filter(None, - self.servDnsObj.clVars.Get("os_net_ip").split(",")) + IPs = [x for x in self.servDnsObj.clVars.Get("os_net_ip").split(",") if x] if not IPs: self.printERROR(_("Can not found ip in net interfaces")) return False @@ -21269,10 +21306,10 @@ incompatible, use one of the options")) if flagErrorRange: self.printERROR(\ _('Command line option "--range %s" incorrectly')\ - %",".join(ranges)) + % ",".join(ranges)) self.printERROR( _("Invalid range of network addresses for the network %s")\ - %net) + % net) return False flagFoundDnsIp = False for ipDns in dnsIPs: @@ -21285,7 +21322,7 @@ incompatible, use one of the options")) _('Command line option "--dnsip %s" incorrectly')\ %dnsIP) self.printERROR(_("Can not found ip address dns servers in \ -network %s")%net) +network %s") % net) return False ipserver = "" for ipIntr in IPs: @@ -21296,8 +21333,8 @@ network %s")%net) if not ipserver: self.printERROR(\ _("Ip addresses on the interfaces of the system (%s)")\ - %",".join(IPs)+" "+_("does not belong to the network %s")\ - %net) + % ",".join(IPs) + " " + _("does not belong to the network %s")\ + % net) return False # опции добавления DNS зоны optionsDns = {"n":zoneName, @@ -21308,8 +21345,7 @@ network %s")%net) return False # Ищем обратные зоны в DNS listNet24 = self.nets24ToIpAndMask(net) - listStrNet24 = map(lambda x: ".".join(map(lambda y: str(y), x)), - listNet24) + listStrNet24 = [".".join(str(y) for y in x) for x in listNet24] # Получаем имена обратных зон reverseZoneNames = [] for net24 in listStrNet24: @@ -21317,7 +21353,7 @@ network %s")%net) netSpl.pop() netSpl.reverse() # Имя обратной зоны - reverseZoneNames.append("%s.in-addr.arpa" %".".join(netSpl)) + reverseZoneNames.append("%s.in-addr.arpa" % ".".join(netSpl)) # Создаем обратные зоны в тексте конфигурационного файла objTxtZone = dnsTxt() if not objTxtZone.createExclZones(self.servDnsObj.clVars, @@ -21362,8 +21398,8 @@ network %s")%net) for net, data in dataNets: notFoundOpts = [] ranges = [] - if data.has_key("range"): - ranges = filter(lambda x: x.strip(), data["range"]) + if "range" in data: + ranges = [x for x in data["range"] if x.strip()] if not ranges: notFoundOpts.append(("range", "--range ")) @@ -21375,21 +21411,21 @@ network %s")%net) " " + _("in config file %s") %dhcpObj.nameConfigFile) return False dnsIPs = [] - if data.has_key("optiondomain-name-servers"): + if "optiondomain-name-servers" in data: dnsIPs = data["optiondomain-name-servers"][0].split(",") if not dnsIPs: notFoundOpts.append(("option domain-name-servers", "--dnsip ")) domainNames = [] - if data.has_key("optiondomain-name"): - domainNames = map(lambda x: x.strip().replace('"',''),\ - data["optiondomain-name"]) + if "optiondomain-name" in data: + domainNames = [x.strip().replace('"', '') + for x in data["optiondomain-name"]] if not domainNames: notFoundOpts.append(("option domain-name", "--dnames ")) if notFoundOpts: - optionsPr = map(lambda x: "'%s'"%x[0], notFoundOpts) - optionsCmdPr = map(lambda x: x[1], notFoundOpts) + optionsPr = ["'%s'" % x[0] for x in notFoundOpts] + optionsCmdPr = [x[1] for x in notFoundOpts] self.printERROR(_("Can not create DNS zone %s") %net) self.printERROR(\ _('Can not found %s')%",".join(optionsPr) + " "+\ @@ -21411,7 +21447,7 @@ network %s")%net) dataHosts = dhcpObj.getDataInAllHost() for hostname, data in dataHosts: ip = "" - if not data.has_key("fixed-address"): + if "fixed-address" not in data: self.printERROR(_("Can not create static host")) self.printERROR(_("Can not found ip static host %s")\ %hostname+ " " + _("in config file %s")\ @@ -21440,7 +21476,7 @@ network %s")%net) recData = self.servDnsObj.searchAllDomainNamesInLDAP(\ fullDomainName) if recData: - if recData[0][0][1].has_key('aRecord'): + if 'aRecord' in recData[0][0][1]: aRecords = recData[0][0][1]['aRecord'] if not ip in aRecords: flagError = True @@ -21469,14 +21505,13 @@ network %s")%net) # Флаг создания обратной записи flagCreatePTR = True if recData: - if recData[0][0][1].has_key('pTRRecord'): + if 'pTRRecord' in recData[0][0][1]: hostList = recData[0][0][1]['pTRRecord'] # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x,\ - y.split("."))) - hostList = map(lambda x: delDot(x),hostList) + delDot = lambda y: ".".join(x for x in y.split(".") if x) + hostList = [delDot(x.decode("UTF-8")) for x in hostList] if hostname in hostList: - deleteIP = filter(lambda x: x!=ip, deleteIP) + deleteIP = [x for x in deleteIP if x != ip] flagCreatePTR = False else: deleteIP.append(ip) @@ -21545,8 +21580,8 @@ network %s")%net) if not dhcpObj: dhcpObj = dncpTxt() dataHosts = dhcpObj.getDataInAllHost() - getPar = lambda opt, data: map(lambda x: opt in x[1].keys() and\ - (x[0],x[1][opt]) or (), data) + getPar = lambda opt, data:\ + [opt in x[1].keys() and (x[0],x[1][opt]) or () for x in data] flagCorrect = True staticMACs = getPar('hardwareethernet', dataHosts) for data in staticMACs: @@ -21607,12 +21642,11 @@ network %s")%net) " " + _("for network %s")%net) return False netList = self.nets24ToMinIpAndMaxIp(minNumber, maxNumber) - strNetList = map(lambda x: ".".join(map(lambda y: str(y), x[0:3])), - netList) + strNetList = [".".join(str(y) for y in x[0:3]) for x in netList] # Проверка на статические хосты dataHosts = dhcpObj.getDataInAllHost() - getPar = lambda opt, data: map(lambda x: opt in x[1].keys() and\ - (x[0],x[1][opt]) or (), data) + getPar = lambda opt, data: [opt in x[1].keys() and\ + (x[0],x[1][opt]) or () for x in data] staticIPs = getPar('fixed-address', dataHosts) for data in staticIPs: if not data: @@ -21646,8 +21680,8 @@ network %s")%net) dhcpObj = dncpTxt() dataNets = dhcpObj.getDataInAllSubnet() dataHosts = dhcpObj.getDataInAllHost() - getPar = lambda opt, data: map(lambda x: opt in x[1].keys() and\ - (x[0],x[1][opt]) or (), data) + getPar = lambda opt, data: [opt in x[1].keys() and\ + (x[0], x[1][opt]) or () for x in data] ranges = getPar('range', dataNets) try: numbIp = self.getNumberIP(ip) @@ -21743,8 +21777,8 @@ network %s")%net) dhcpObj = dncpTxt() dataNets = dhcpObj.getDataInAllSubnet() dataHosts = dhcpObj.getDataInAllHost() - getPar = lambda opt, data: map(lambda x: opt in x[1].keys() and\ - (x[0],x[1][opt]) or (), data) + getPar = lambda opt, data: [opt in x[1].keys() and\ + (x[0], x[1][opt]) or () for x in data] ranges = getPar('range', dataNets) if not ranges: self.printERROR(_("Can not found 'range' in config file %s")\ @@ -21819,12 +21853,13 @@ network %s")%net) isNotRange(maxIpRanges, minNumber, maxNumber): return [] # Проверка на коректность сетевых адресов - if filter(lambda x: not self.isCorrectStringNet(x, False), (ipA, ipB)): + if [x for x in (ipA, ipB) if not self.isCorrectStringNet(x, False)]: return [] return [self.getIPinNumber(minIpRanges),self.getIPinNumber(maxIpRanges)] def createLogFile(self): """Создание файла лога или если нужно изменение владельца файла лога""" + # from . import cl_log import cl_log # Полное имя файла лога (путь плюс имя файла) logFullFile = os.path.join(cl_log.log.logDir, self.errorLogFile) @@ -21838,9 +21873,9 @@ network %s")%net) # Создаем файловый объект fileObj = cl_profile._file() dMode, dUid, dGid = fileObj.getModeFile(cl_log.log.logDir) - if dMode != 0755: + if dMode != 0o755: try: - os.chmod(cl_log.log.logDir,0755) + os.chmod(cl_log.log.logDir,0o755) except: self.printERROR(_("Can not set mode 0755 for %s")\ %cl_log.log.logDir) @@ -21893,7 +21928,7 @@ network %s")%net) # Принудительная установка forceOptions = False minKeys = [] - if options.has_key("f"): + if "f" in options: forceOptions = True minKeys = ["f"] # Создаем объект переменных @@ -21918,13 +21953,12 @@ network %s")%net) set(bakupObj.notLdapServices)) if listServicesLDAP: flagLdap = True - optKeys = options.keys() + optKeys = list(options.keys()) minKeys += ["net", "router", "range", "dnames", "dnsip"] # Проверка на наличие всех нужных опций - if not set(minKeys)<=set(optKeys): - notFoundKeys = list(set(minKeys)-set(optKeys)) - notFoundKeys = map(lambda x: len(x)>1 and '"--%s"'%x or '"-%s"'%x,\ - notFoundKeys) + if not set(minKeys) <= set(optKeys): + notFoundKeys = list(set(minKeys) - set(optKeys)) + notFoundKeys = [len(x) > 1 and '"--%s"' % x or '"-%s"' % x for x in notFoundKeys] self.printERROR(_("Not enough command line options: %s")\ %", ".join(notFoundKeys)) return False @@ -21999,26 +22033,26 @@ network %s")%net) return False # Создаем текстовый блок в конфигурационном файле для новой сети netOptions = {} - if options.has_key("net"): + if "net" in options: netOptions["net"] = options["net"] - if options.has_key("router"): + if "router" in options: netOptions["router"] = options["router"] - if options.has_key("dnames"): + if "dnames" in options: netOptions["dnames"] = options["dnames"] - if options.has_key("dnsip"): + if "dnsip" in options: netOptions["dnsip"] = options["dnsip"] - if options.has_key("range"): + if "range" in options: netOptions["range"] = options["range"] if not self.createNetDhcpServer(netOptions, False): return False # Добавляем в статические хосты имя текущего хоста hostname = self.clVars.Get("os_net_hostname") if hostname: - domainNames = map(lambda x: x.lower(), options["dnames"].split(",")) + domainNames = [x.lower() for x in options["dnames"].split(",")] domainNames = self.unicList(domainNames) domain = domainNames[0] fullHostNameServer = "%s.%s"%(hostname,domain) - IPs = filter(None,self.clVars.Get("os_net_ip").split(",")) + IPs = [x for x in self.clVars.Get("os_net_ip").split(",") if x] if not any(IPs): self.printERROR(_("Can not found ip in net interfaces")) return False @@ -22039,7 +22073,7 @@ network %s")%net) # Ищем A запись в DNS recData = self.servDnsObj.searchDomainNameInLDAP(\ fullHostNameServer) - if recData and recData[0][0][1].has_key('aRecord'): + if recData and 'aRecord' in recData[0][0][1]: flagFoundARecord = True if ipServer in recData[0][0][1]['aRecord']: flagCreateDNSRecord = False @@ -22052,13 +22086,12 @@ network %s")%net) # Находим ptr запись в DNS recData = self.servDnsObj.searchAllDomainNamesInLDAP(\ PTRDomainName) - if recData and recData[0][0][1].has_key('pTRRecord'): + if recData and 'pTRRecord' in recData[0][0][1]: if not flagCreateDNSRecord: hostList = recData[0][0][1]['pTRRecord'] # Удаляет лишние точки в названии - delDot = lambda y: ".".join(filter(lambda x: x,\ - y.split("."))) - hostList = map(lambda x: delDot(x),hostList) + delDot = lambda y: ".".join(x for x in y.split(".") if x) + hostList = [delDot(x.decode("UTF-8")) for x in hostList] if not fullHostNameServer in hostList: flagCreateDNSRecord = True flagDeletePTRRecord = True @@ -22142,15 +22175,15 @@ class tsOpt(cl_base.opt): tuple(set(self.opt.keys()).intersection(helpObj.relOptions.keys())) #Если есть опции help if len(helpopt) > 0: - print helpObj.getHelp(helpObj.relOptions[helpopt[0]]) + print(helpObj.getHelp(helpObj.relOptions[helpopt[0]])) self.flagHelp = True #Если нет хвостов elif not self.params: if optService or lastOpt: - print helpObj.getHelp(helpObj.relOptions['h']) + print(helpObj.getHelp(helpObj.relOptions['h'])) self.flagHelp = True else: - if self.params.has_key('service'): + if 'service' in self.params: if lastOpt: pass elif not (self.params['service'] in helpObj.allServ): @@ -22163,13 +22196,13 @@ class tsOpt(cl_base.opt): self.handlerErrOpt() self.flagHelp = True # В случае отсутствия опций командной строки - if notOptError and not self.opt and self.params.has_key('service'): + if notOptError and not self.opt and 'service' in self.params: self.printErrorNotOpt() self.flagHelp = True def printErrorNotOpt(self): """Сообщение в случае отсутствия опций""" - print _("Options are absent.") + print(_("Options are absent.")) def handlerOpt(self,option,value): # Обработчик (опция значение) @@ -22184,9 +22217,9 @@ class tsOpt(cl_base.opt): # Обработчик ошибок self.errorOpt = True argv = " ".join(sys.argv[1:]) - print _("Unrecognized option") + ' "' + argv + '"\n' + \ + print(_("Unrecognized option") + ' "' + argv + '"\n' + \ _("Try") + ' "' + sys.argv[0].split("/")[-1] + ' --help" ' +\ -_("for more information.") +_("for more information.")) def handlerParam(self,param): # Обработчик хвостов (значение) diff --git a/pym/cl_log.py b/pym/cl_log.py new file mode 100644 index 0000000..d6aca9c --- /dev/null +++ b/pym/cl_log.py @@ -0,0 +1,59 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import time + +class log(): + """Класс для записи в лог""" + # Директория хранения логов + logDir = "/var/log/calculate" + def __init__(self,fileName, addDataTime=True): + self.logFile = os.path.join(self.logDir,fileName) + if not os.path.exists(self.logDir): + os.makedirs(self.logDir) + self.addDataTime = addDataTime + + def addLog(self, textLog): + """Добавляет текст в лог файл""" + if not os.path.exists(self.logFile): + try: + fd = os.open(self.logFile, os.O_CREAT,0o600) + os.close(fd) + except: + print("Error creating file %s" % self.logFile) + return False + textWrite = textLog + if not textLog[-1:] == "\n" : + textWrite = "%s\n" % textLog + if self.addDataTime: + textWrite = "%s %s" % (time.strftime("%d/%m/%Y %H:%M:%S",\ + time.localtime()), textWrite) + try: + FD = open (self.logFile, "a") + FD.write(textWrite) + FD.close() + except: + print("Error writing to file %s" % self.logFile) + return False + return True + + def writeError(self, textLog): + """Добавляет сообщение об ошибке в log""" + return self.addLog("ERROR: %s" % textLog) + + def writeSuccess(self, textLog): + """Добавляет сообщение об успехе в log""" + return self.addLog("SUCCESS: %s" % textLog) diff --git a/pym/cl_profile.py b/pym/cl_profile.py new file mode 100644 index 0000000..03773f1 --- /dev/null +++ b/pym/cl_profile.py @@ -0,0 +1,6314 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import os +import cl_base +import stat +import re +import cl_xml +from cl_xml import xpath, firstChild,\ + insertBefore, str_to_xml_doc, xml_to_str, xmlShare,\ + xmlNode, xmlField, xmlFields, xmlArea, xmlDoc +import subprocess +import types +import copy +import random +import string +import time +from copy import deepcopy +from collections.abc import Iterable +_ = lambda x : x +tr = cl_base.lang() +tr.setLocalDomain('cl_lib') +tr.setLanguage(sys.modules[__name__]) + +def cmp(a, b): + return (a > b) - (b < a) + +class _error: + # Здесь ошибки, если они есть + error = [] + def getError(self): + """Выдать ошибки""" + if not self.error: + return False + error = "" + for e in self.error: + error += e + "\n" + return error + + def setError(self, error): + """Установка ошибки""" + self.error.append(error) + return True + + +class _terms(_error): + """Вычисление условий применяемых в профилях + + """ + # регулярное выражение для не версии + _re_not_Version = re.compile("[^0-9\.]|^$") + # регулярное выражение для функции + _reFunction = re.compile(\ + "([a-zA-Z0-9\_\-]+)\([a-zA-Z0-9_\-\+\,\*\/\.\'\"~]+\)") + # Регулярное выражение для названия переменной + _reDenyName = re.compile("[^a-zA-Z0-9\_\-]") + # Регулярное выражение для сравниваемого значения + _reDenyValue = re.compile("[^0-9a-zA-Z_\.-]") + + def _convertVers(self, verA, verB): + """Конвертирование номеров версий для корректного сравнения + """ + elemA = verA.split(".") + elemB = verB.split(".") + if len(elemA) > len(elemB): + maxElemB = len(elemB)-1 + for i in range(len(elemA)): + if i > maxElemB: + elemB.append("0") + else: + maxElemA = len(elemA)-1 + for i in range(len(elemB)): + if i > maxElemA: + elemA.append("0") + for i in range(len(elemB)): + lenA = len(elemA[i]) + lenB = len(elemB[i]) + if lenA == lenB: + pass + elif lenA > lenB: + res = lenA - lenB + for z in range(res): + elemB[i] = "0" + elemB[i] + elif lenB > lenA: + res = lenB - lenA + for z in range(res): + elemA[i] = "0" + elemA[i] + return (".".join(elemA), ".".join(elemB)) + + def _equalTerm(self, term, textError, function=False): + """Вычисление логических выражений для условий + + Для корректной работы в классе который наследует этот класс + должен быть объявлен аттрибут self.objVar + (объект для работы с переменными) + function - функция для для обработки функций в заголовке блока + """ + trm = {"&":" and ","||":" or "} + rule = ["==", "!=", ">=", "<=", ">", "<"] + listEqual = [] + for k in trm.keys(): + if k in term: + term = term.replace(k, trm[k]) + trs = term.split(" ") + for t in trs: + flagRule = False + for sepF in rule: + if sepF in t: + flagRule = True + vals = t.split(sepF) + break + + if not flagRule: + flagLog = False + for k in trm.values(): + if k.strip() == t: + flagLog = True + break + if not flagLog: + self.setError("'%s'" % term + " " + _("incorrect")) + self.setError (textError) + return False + else: + listEqual.append(k) + else: + #проверка на допустимость названия переменной + flagFunction = False + if self._reDenyName.search(vals[0]): + #проверка на допустимость функции + flagError = True + if function: + searchFunct = self._reFunction.search(vals[0]) + if searchFunct: + flagError = False + flagFunction = True + if flagError: + self.setError("'%s'"%term + " " + _("incorrect")) + self.setError(textError) + return False + #проверка на допустимость значения + if self._reDenyValue.search(vals[1]): + self.setError("'%s'"%term + " " + _("incorrect")) + self.setError(textError) + return False + flagIntTypeVar = None + if flagFunction: + valVars = function("#-%s-#"%vals[0]) + if valVars is False: + self.setError("'%s'"%term + " " + _("incorrect")) + self.setError(textError) + return False + if "load" == searchFunct.group(1): + if re.search("\(\s*num\s*,",vals[0]): + if valVars: + try: + valVars = int(valVars) + except: + self.setError("'%s'"%term + " " + \ + _("incorrect")) + self.setError (textError) + return False + flagIntTypeVar = True + else: + flagIntTypeVar = False + else: + if valVars == "" and\ + not self._re_not_Version.search(vals[1]): + valVars = "0" + elif vals[1] == "" and\ + not self._re_not_Version.search(valVars): + vals[1] = "0" + else: + try: + valVars = self.objVar.Get(vals[0]) + except self.objVar.DataVarsError as e: + print(textError) + print(e) + cl_base.exit(1) + # Номера версий для ini + flagNotIniFunct = True + # Два значения не пусты + flagNotEmptyVals = not (valVars == "" and vals[1] == "") + if flagFunction and flagNotEmptyVals and\ + searchFunct.group(1) == "ini": + # Проверка значения на версию + if not self._re_not_Version.search(valVars) and\ + not self._re_not_Version.search(vals[1]): + verFile, verVar = self._convertVers(vals[1],valVars) + res = eval("("+"'"+verVar+"'"+sepF+"'"+verFile+"'"+")") + if res: + listEqual.append("1") + else: + listEqual.append("0") + flagNotIniFunct = False + # Cравниваем номера версий + if flagNotIniFunct: + if flagNotEmptyVals and\ + ("_ver" in vals[0] or\ + (flagFunction and searchFunct.group(1) == "pkg") or\ + (flagFunction and searchFunct.group(1) == "load" and\ + re.search("\(\s*ver\s*,",vals[0]))): + # Проверка значения на версию + if self._re_not_Version.search(vals[1]): + self.setError("'%s'"%term + " " + _("incorrect")) + self.setError (_("Value is not version")) + return False + # Проверка значения функции на версию + if self._re_not_Version.search(valVars): + self.setError("'%s'"%term + " " + _("incorrect")) + self.setError (_("Value function is not version")) + return False + verFile, verVar = self._convertVers(vals[1],valVars) + res = eval("("+"'"+verVar+"'"+sepF+"'"+verFile+"'"+")") + if res: + listEqual.append("1") + else: + listEqual.append("0") + flagNotIniFunct = False + else: + if flagIntTypeVar == None: + flagIntTypeVar = True + try: + valVars = int(valVars) + except: + flagIntTypeVar = False + if flagIntTypeVar: + if not vals[1].strip(): + vals[1] = 0 + try: + valFile = int(vals[1]) + except: + self.setError("'%s'" % term +" " +_("incorrect")) + self.setError (textError) + return False + valVar = valVars + res = eval("(%d%s%d)" % (valVar,sepF,valFile)) + if res: + listEqual.append("1") + else: + listEqual.append("0") + else: + if sepF == "!=" or sepF == "==": + if not vals[1].strip(): + vals[1] = "" + valFile = vals[1] + valVar = valVars + res = eval("("+'"""'+valVar+'"""'+sepF+"'"+valFile+"'"+")") + if res: + listEqual.append("1") + else: + listEqual.append("0") + else: + if not flagNotEmptyVals: + listEqual.append("0") + else: + self.setError("'%s'"%term + " "\ + + _("incorrect")) + self.setError (textError) + return False + res = eval("(%s)"%("".join(listEqual))) + return res + +class fileHeader(_terms): + """Обработка заголовков профилей и конфигурационных файлов + + """ + # Допустимые параметры заголовка + allowParam = ["format", "format_conf", "comment", "append", "force", + "link", "mirror", "symbolic", "chmod", "chown", "name"] + # Корректность заголовка + headerCorrect = True + + # Тип профиля + fileType = "" + # Тип вставки профиля + typeAppend = "" + # Возможные типы вставки профилей + _fileAppend = "join", "before", "after", "replace", "remove" + # Интерпретатор (#!/bin/bash) (#!/usr/bin/python) + execStr = "" + # Символ комментария + comment = False + # Выражение для поиска строки интерпретатора + reExecStr = re.compile("^#!.+\s*",re.I) + # условные операторы + terms = ('>', '<', '==', '!=', '>=', '<=') + # параметры без значения + listParNotVal = ("symbolic", "force", "mirror") + # Результат вычисления условия в заголовке + headerTerm = True + # Сообщение о ошибке + errorMessage = "" + + def __init__(self, text, comment=False, fileType=False, objVar=False, + function=False): + self.body = text + # Объект с переменными + self.objVar=objVar + # Параметры описанные в заголовке файла профиля + self.params = {} + # некорректные параметры + incorrectParams = set([]) + # Удаление Заголовка Calculate + if comment: + # В случае текста XML + if type(comment) == tuple and len(comment) == 2: + _titleList = (_("Modified"), _("File of a profile")) + reCalcHeader =\ + re.compile("\s*%s\s+%s.+Calculate.+\s+%s.+\s+%s\s?" % (\ + comment[0], + _titleList[0], + _titleList[1], + comment[1], + ), + re.M|re.I|re.U) + textUnicode = text + reS = reCalcHeader.search(textUnicode) + if reS: + textBody = textUnicode[:reS.start()]+textUnicode[reS.end():] + if textBody: + self.body = textBody + else: + reCalcHeader =\ + re.compile("\s*%s\-+\s+%s.+Calculate.+\s+%s.+\s+%s\-+\s?"%(\ + comment, + comment, + comment, + comment, + ), + re.M|re.I) + reS = reCalcHeader.search(text) + if reS: + self.body = text[reS.end():] + + if fileType != False: + if fileType=="bin": + self.params["format"] = fileType + self.fileType = self._getType() + self.typeAppend = self._getAppend() + else: + textLines = text.splitlines() + if textLines: + textLine = textLines[0] + rePar = re.compile("\s*#\s*calculate\s+",re.I) + reP = rePar.search(textLine) + if reP: + reL = False + reLns = re.compile(r"\A([^\\\n]*\\\n)+[^\n]*\n*",re.M) + reLs = reLns.search(text) + if reLs: + reL = reLs + paramLine = text[reP.end():reLs.end()] + paramLine = paramLine.replace("\\"," ") + else: + reLn = re.compile("\n") + reL = reLn.search(text) + paramLine = textLine[reP.end():] + if reL: + self.body = text[reL.end():] + else: + self.body = "" + paramList = re.split("\s+",paramLine) + if paramList: + for i in paramList: + foundTerm = False + for term in self.terms: + if term in i: + foundTerm = True + if function: + rezTerm = self._equalTerm(i,\ + _("header profile not valid: ") + \ + i,function) + else: + rezTerm = self._equalTerm(i,\ + _("header profile not valid: ") + \ + i) + if not rezTerm: + self.headerTerm = False + break + if not foundTerm: + par = i.split("=") + if len(par) == 1: + if i in self.listParNotVal: + self.params[i] = "True" + else: + if i.strip(): + incorrectParams = set([i]) + elif len(par) == 2: + self.params[par[0]] = par[1] + + self.comment = self._getComment() + self.fileType = self._getType() + self.typeAppend = self._getAppend() + reExecRes = self.reExecStr.search(self.body) + if reExecRes: + self.execStr = self.body[reExecRes.start():reExecRes.end()] + self.body = self.body[reExecRes.end():] + if not incorrectParams: + incorrectParams = set(self.params.keys()) - set(self.allowParam) + if incorrectParams: + self.headerTerm = False + self.headerCorrect = False + self.errorMessage = _("incorrect header parameters - '%s'")\ + % " ".join(list(incorrectParams)) + + def _getType(self): + """Выдать тип файла""" + if "format" in self.params: + return self.params["format"] + else: + return "raw" + + def _getAppend(self): + """Выдать тип добавления файла""" + if "append" in self.params and self.params["append"] in\ + self._fileAppend: + return self.params["append"] + else: + if self.fileType != "raw" and self.fileType != "bin" and\ + self.fileType != "": + self.params["append"] = "join" + return "join" + self.params["append"] = "replace" + return "replace" + + def _getComment(self): + """Выдать символ комментария файла""" + if "comment" in self.params: + return self.params["comment"] + else: + return False + + +class dirHeader(_terms): + """Обработка заголовков профилей директорий + + """ + # Допустимые параметры заголовка + allowParam = ["append", "chmod", "chown", "name"] + # Корректность заголовка + headerCorrect = True + + # Тип вставки профиля + typeAppend = "" + # Возможные типы вставки профилей + _fileAppend = "join", "remove" + # условные операторы + terms = ('>', '<', '==', '!=', '>=', '<=') + # параметры без значения + listParNotVal = ("symbolic", "force") + # Результат вычисления условия в заголовке + headerTerm = True + # Сообщение о ошибке + errorMessage = "" + + def __init__(self, text, objVar=False, function=False): + self.body = text + # Объект с переменными + self.objVar=objVar + # Параметры описанные в заголовке файла профиля + self.params = {} + # некорректные параметры + incorrectParams = set([]) + + textLines = text.splitlines() + flagErrorBody = False + if textLines: + textLine = textLines[0] + rePar = re.compile("\s*#\s*calculate\s+",re.I) + reP = rePar.search(textLine) + if reP: + reL = False + reLns = re.compile(r"\A([^\\\n]*\\\n)+[^\n]*\n*",re.M) + reLs = reLns.search(text) + if reLs: + reL = reLs + paramLine = text[reP.end():reLs.end()] + paramLine = paramLine.replace("\\"," ") + else: + reLn = re.compile("\n") + reL = reLn.search(text) + paramLine = textLine[reP.end():] + if reL: + self.body = text[reL.end():] + else: + self.body = "" + if self.body.strip(): + self.headerTerm = False + self.headerCorrect = False + self.errorMessage = _("incorrect text in profile: '%s'")\ + %self.body + flagErrorBody = True + if not flagErrorBody: + paramList = re.split("\s+",paramLine) + if paramList: + for i in paramList: + foundTerm = False + for term in self.terms: + if term in i: + foundTerm = True + if function: + rezTerm = self._equalTerm(i,\ + _("header profile not valid: ") + \ + i,function) + else: + rezTerm = self._equalTerm(i,\ + _("header profile not valid: ") + \ + i) + if not rezTerm: + self.headerTerm = False + break + if not foundTerm: + par = i.split("=") + if len(par) == 1: + if i in self.listParNotVal: + self.params[i] = "True" + else: + if i.strip(): + incorrectParams = set([i]) + elif len(par) == 2: + self.params[par[0]] = par[1] + self.typeAppend = self._getAppend() + if not flagErrorBody: + if not incorrectParams: + incorrectParams = set(self.params.keys()) - set(self.allowParam) + if incorrectParams: + self.headerTerm = False + self.headerCorrect = False + self.errorMessage = _("incorrect header parameters - '%s'")\ + % " ".join(list(incorrectParams)) + + def _getAppend(self): + """Выдать тип добавления директории""" + if "append" in self.params and self.params["append"] in\ + self._fileAppend: + return self.params["append"] + else: + return "join" + +class objShare: + """Общий клас для объектов, наследуем + + """ + + def createFieldTerm(self, name, value, quote, docObj): + """Создание поля переменная - значение + + при создании поля проверяется первый символ названия переменной + и добавляется тег action + "!" - drop удаляет + "+" - join добавляет + "-" - replace заменяет + """ + fieldAction = False + if name: + if name[0] == "!" or name[0] == "-" or name[0] == "+": + qnt = self.removeSymbolTerm(quote) + fieldXML = docObj.createField("var",[qnt], + name[1:], [value], + False, False) + if name[0] == "!": + fieldAction = "drop" + elif name[0] == "+": + fieldXML.set("type", "seplist") + fieldAction = "join" + else: + fieldXML = docObj.createField("var", + [quote.replace("\n","")], + name, [value], + False, False) + else: + fieldXML = docObj.createField("var", + [quote.replace("\n","")], + name, [value], + False, False) + if fieldAction: + docObj.setActionField(fieldXML, fieldAction) + return fieldXML + + def removeSymbolTerm(self, text): + """Удаляет первый символ названия переменной в строке + + Если первый встречающийся символ с начала строки + '+', '-', '!' то он из этой строки будет удален, + если перед этим символом были пробельные символы, + то они будут сохранены, так-же если в строке есть символ + перевода строки он будет удален. + """ + reTerm = re.compile("^[ \t]*(\!|\+|\-)") + textNS = text.replace("\n","") + res = reTerm.search(textNS) + if res: + textNS = textNS[res.start():res.end()-1] + textNS[res.end():] + return textNS + + def getConfig(self): + """Выдает конфигурационный файл""" + listConfigTxt = [] + childNodes = list(self.docObj.getNodeBody()) + for node in childNodes: + if node.tag == "field": + listConfigTxt.append(self.docObj.getQuoteField(node)) + elif node.tag == "area": + self.docObj.xmlToText([node], listConfigTxt) + return "".join(listConfigTxt) + + def splitToFields(self, txtBloc): + """Разбиваем текст на поля (объекты) которые имеют следующие аттрибуты + + self.name - если переменная то имя переменной + self.value - если у переменной есть значение то значение переменной + self.comment - если комментарий то текст комментария + self.br - если перевод строки то текст перед переводом из пробелов + + Результат список объектов полей + """ + finBloc = "\n" + if txtBloc[-1] != "\n": + finBloc = "" + + linesBlocTmp = txtBloc.splitlines() + linesBloc = [] + brBloc = [] + z = 0 + lenLines = len(linesBlocTmp) + for i in linesBlocTmp: + if self.reComment.split(i)[0]: + findCooment = self.reComment.search(i) + comment = False + par = i + if findCooment: + par = i[:findCooment.start()] + comment = i[findCooment.start():] + fields = self.reSepFields.split(par) + lenFields = len(fields) + if lenFields > 1: + for fi in range(lenFields-1): + linesBloc.append(fields[fi]+ self.sepFields) + if fi == lenFields-2: + if comment: + brBloc.append("") + else: + if (lenLines-1)== z: + brBloc.append(finBloc) + else: + brBloc.append("\n") + else: + brBloc.append("") + if comment: + linesBloc.append(comment) + if (lenLines-1)== z: + brBloc.append(finBloc) + else: + brBloc.append("\n") + else: + linesBloc.append(i) + if (lenLines-1)== z: + brBloc.append(finBloc) + else: + brBloc.append("\n") + else: + linesBloc.append(i) + if (lenLines-1)== z: + brBloc.append(finBloc) + else: + brBloc.append("\n") + z +=1 + fields = self.setDataField(linesBloc, brBloc) + return fields + +class xmlCaption: + """Класс XML заголовок + + """ + def __init__(self): + #Заголовок области XML нода + self.caption = False + + + def createCaption(self, doc, name, quotes, action=False): + """Создание заголовка области""" + tmpNode = xmlNode() + self.caption = tmpNode.createNode(doc, "caption") + nameNode = tmpNode.createNode(doc, "name",name) + self.caption.append(nameNode) + if action: + actNode = tmpNode.createNode(doc, "action", action) + self.caption.append(actNode) + for q in quotes: + quoteNode = tmpNode.createNode(doc, "quote", q) + self.caption.append(quoteNode) + return self.caption + + def getCaption(self): + """Выдает XML ноду заголовка области""" + return self.caption + +class blocText: + """Разбиваем текст на блоки""" + + def splitTxtToBloc(self, text ,openTxtBloc,closeTxtBloc, + commentTxtBloc, sepField): + """Делит текст на блоки (без заголовков) + + openTxtBloc - регулярное выражение для начала блока + closeTxtBloc - регулярное выражение для конца блока + commentTxtBloc - регулярное выражение - комментарий + возвращает блоки текста + """ + blocs = [] + level = 0 + # Нахождение нескольких блоков в строке + # разделители линий, разделителями могут быть ("","\n") + sepsLines = [] + # линии + txtLines = [] + # Исходные строки + txtLinesSrc = text.splitlines() + for line in txtLinesSrc: + lineBR = "" + lineTmpA = line + closeBl = False + txtLinesTmp = [] + commentSpl = commentTxtBloc.split(line) + flagCommentLine = False + if commentSpl[0].strip(): + closeBl = True + if len(commentSpl) > 1: + commentBl = commentTxtBloc.search(line) + textLine =commentSpl[0] + commentLine = line[commentBl.start(0):] + lineTmpA = textLine + flagCommentLine = True + + while (closeBl): + closeBl = sepField.search(lineTmpA) + if closeBl: + lineTmpB = lineTmpA[closeBl.end(0):] + txtLinesTmp.append(lineTmpA[:closeBl.end(0)]) + lineTmpA = lineTmpB + if lineTmpA.strip(): + txtLinesTmp.append(lineTmpA) + # Если есть значение и комментарий в строке + if flagCommentLine: + for l in txtLinesTmp: + txtLines.append(l) + sepsLines.append("") + if not txtLinesTmp: + txtLines.append(textLine) + sepsLines.append("") + txtLines.append(commentLine) + sepsLines.append("\n") + # Если есть несколько блоков в строке + elif len(txtLinesTmp)>1 and txtLinesTmp[1].strip(): + lenTmpLines = len(txtLinesTmp) + for l in range(lenTmpLines): + txtLines.append(txtLinesTmp[l]) + if l == lenTmpLines-1: + sepsLines.append("\n") + else: + sepsLines.append("") + # Cтрока не преобразована + else: + txtLines.append(line) + sepsLines.append("\n") + + # разбивание на блоки + z = 0 + bl = "" + for i in txtLines: + if commentTxtBloc.split(i)[0].strip() and openTxtBloc.search(i): + level += len(openTxtBloc.split(i)) - 1 + if commentTxtBloc.split(i)[0].strip() and closeTxtBloc.search(i): + level -= len(closeTxtBloc.split(i)) - 1 + bl += i + sepsLines[z] + if level == 0: + if bl: + blocs.append(bl) + bl = "" + z += 1 + # cоздание блоков с элементами не входящими в блоки + realBlocs = [] + z = 0 + bl = "" + for i in blocs: + txtLines = i.splitlines() + if len(txtLines) > 0: + line = txtLines[0] + else: + line = i + if commentTxtBloc.split(i)[0].strip() and openTxtBloc.search(line): + if bl: + realBlocs.append(bl) + bl = "" + realBlocs.append(i) + else: + bl += i + z += 1 + if bl: + realBlocs.append(bl) + bl = "" + if level == 0: + if text and text[-1] != "\n": + tmpBlocs = realBlocs.pop() + tmpBlocs = tmpBlocs[:-1] + realBlocs.append(tmpBlocs) + return realBlocs + else: + return [] + + def findArea(self, text, reTextHeader, reTextArea, numGroupArea=0): + """ Делит текст на области (с заголовками) + + reTextHeader - регулярное выражение для заголовка области + reTextArea - регулярное выражение для всей области + numGroupArea - номер групы результата поиска по регулярному выражению + по всей области + возвращает два списка: первый - заголовки, второй - тела областей без + заголоков + """ + # Заголовки областей + headersArea = [] + # Тексты областей без заголовков + textBodyArea = [] + r = reTextArea.search(text) + if not r: + headersArea.append("") + textBodyArea.append(text) + return (headersArea, textBodyArea) + + txtWr = text + while r: + textArea = r.group(numGroupArea) + txtSpl = txtWr.split(textArea) + area = txtSpl[0] + txtWr = txtSpl[1] + if area: + headersArea.append("") + textBodyArea.append(area) + res = reTextHeader.search(textArea) + header = textArea[:res.end()] + body = textArea[res.end():] + + headersArea.append(header) + textBodyArea.append(body) + + if txtWr: + r = reTextArea.search(txtWr) + else: + r = False + if txtWr: + headersArea.append("") + textBodyArea.append(txtWr) + return (headersArea, textBodyArea) + + + def findBloc(self, text, captionTxtBloc, bodyTxtBloc): + """ Делит текст на блоки (с заголовками) + + captionTxtBloc - регулярное выражение для заголовка блока + bodyTxtBloc - регулярное выражение для тела блока + возвращает два списка: первый - заголовки, второй - тела блоков + """ + # Заголовки блоков + headersTxt = [] + # Тексты блоков + blocsTxt = [] + r = captionTxtBloc.search(text) + if r: + headersTxt.append(r.group(0)) + txtSpl = text.split(r.group(0)) + blocTxt = txtSpl[0] + txtWr = txtSpl[1] + rb = bodyTxtBloc.search(blocTxt) + if not blocTxt: + blocsTxt.append(blocTxt) + if rb: + blocsTxt.append(rb.group(0)) + while (r): + r = captionTxtBloc.search(txtWr) + if r: + headersTxt.append(r.group(0)) + txtSpl = txtWr.split(r.group(0)) + blocTxt = txtSpl[0] + txtWr = txtSpl[1] + rb = bodyTxtBloc.search(blocTxt) + if rb: + blocsTxt.append(rb.group(0)) + else: + blocsTxt.append(txtWr) + if headersTxt and blocsTxt: + if len(headersTxt)>len(blocsTxt): + blocsTxt.insert(0,"") + elif len(headersTxt)= 4: + l = 4 + elif lenSymb >= 3: + l = 3 + elif lenSymb >= 2: + l = 2 + else: + if symbols[0] == '_ch_': + return (True,1) + else: + return (False,1) + result = False + for i in range(l): + if i == 0 and symbols[i] != '_fb_': + break + elif i > 0 and symbols[i] != '_nb_': + break + if lenTail>1 and lenTail != i: + return (False,1) + if i > 0: + result = True + return (result, i) + + def _intToChar(self, x): + he = hex(x)[2:] + return chr(int(he, 16)) + + def _hexToChar(self, he): + return chr(int(he, 16)) + + def encode(self, text): + """Кодирует смешанный формат в UTF-8""" + ind = 0 + l = 0 + utf = [] + lenUtf = [] + indErr = [] + i = 0 + for ch in text: + r, l = self._retUTF(ch) + utf.append(r) + lenUtf.append(l) + i+=1 + while 1: + if utf[ind] == '_fb_': + res, l = self._sumbUtf(utf[ind:],lenUtf[ind]) + if res is False: + indErr.append(ind) + if l>0: + ind +=l + if ind >= len(utf): + break + else: + if utf[ind] != '_ch_': + indErr.append(ind) + ind +=1 + if ind >= len(utf): + break + if indErr: + lenIndErr = len(indErr) + block = [] + blocks = [] + if lenIndErr > 1: + i = 1 + while 1: + if i == 1: + block.append(indErr[i-1]) + if indErr[i] - indErr[i-1] == 1: + block.append(indErr[i]) + else: + if block: + blocks.append(block) + block = [] + block.append(indErr[i]) + i +=1 + if i >= lenIndErr: + break + else: + block.append(indErr[0]) + if block: + blocks.append(block) + listErr = [] + for block in blocks: + string = "" + for elem in block: + string += hex(ord(text[elem]))[-2:] + listErr.append((block[0],"__hex__?%s?__hex__" %string,elem)) + textOut = text + deltaInd = 0 + for erEl in listErr: + startInd = erEl[0] + deltaInd + endInd = erEl[2] + 1 + deltaInd + textOut = textOut[:startInd] + erEl[1] + textOut[endInd:] + deltaInd += len(erEl[1])-(erEl[2]-erEl[0]+1) + #if i == 1: + #break + #i += 1 + return textOut + + def decode(self, text): + """Декодирует UTF-8 в смешанный формат""" + varStart = "__hex__\?" + varEnd = "\?__hex__" + # -1 Это экранирование '?' которое тоже считается + deltVarStart = len(varStart)-1 + deltVarEnd = len(varEnd)-1 + reVar = re.compile(("%s[a-f0-9]+%s")%(varStart,varEnd),re.M) + resS = reVar.search(text) + textProfileTmp = text + while resS: + mark = textProfileTmp[resS.start():resS.end()] + hexString = mark[deltVarStart:-deltVarEnd] + i = 0 + stringInsert = "" + hexCode = "" + for ch in hexString: + if i>=1: + hexCode += ch + stringInsert += self._hexToChar(hexCode) + hexCode = "" + i = 0 + else: + hexCode += ch + i += 1 + textProfileTmp = textProfileTmp.replace(mark, stringInsert) + resS = reVar.search(textProfileTmp) + return textProfileTmp + + def getUserDataInLDAP(self, userName): + """Получаем домашнюю директорию пользователя из LDAP""" + if not self.conLdap: + # from . import cl_utils2 + import cl_utils2 + data = self.getLDAPDataInConfig() + if not data: + return "" + serverName, usersDN, bindDN, bindPW = data + # Подключаемся к LDAP + ldapObj = cl_utils2.ldapFun(bindDN, bindPW, serverName) + if self.getError(): + return "" + self.conLdap = ldapObj.conLdap + searchScope = ldap.SCOPE_ONELEVEL + searchFilter = "uid=%s" %(userName) + retrieveAttributes = ["uidNumber", + "gidNumber" + "homeDirectory"] + resSearch = ldapObj.ldapSearch(usersDN, searchScope, + searchFilter, retrieveAttributes) + if resSearch: + if 'uidNumber' in resSearch[0][0][1] and\ + 'gidNumber' in resSearch[0][0][1] and\ + 'homeDirectory' in resSearch[0][0][1]: + uid = resSearch[0][0][1]['uidNumber'][0].decode("UTF-8") + gid = resSearch[0][0][1]['gidNumber'][0].decode("UTF-8") + # uid = searchUser[0][0][1]['uidNumber'][0] + # gid = searchUser[0][0][1]['gidNumber'][0] + homeDir = resSearch[0][0][1]['homeDirectory'][0].decode("UTF-8") + return uid, gid, homeDir + return "" + + +class processingTemplates: + """Класс для обработки шаблонов""" + + def processingFile(self, path, prefix): + """Обработка в случае профиля файла""" + return True + + def processingDirectory(self, path, prefix): + """Обработка в случае директории если возвращаем None то пропуск дир.""" + return True + + def scanningTemplates(self, scanDir, skipFile=None, skipDir=None, + prefix=None, flagDir=False): + """Время последней модификации внутри директории scanDir""" + if skipFile is None: + skipFile = [] + if skipDir is None: + skipDir = [] + ret = True + if prefix is None: + prefix = os.path.join(scanDir,"")[:-1] + if not flagDir: + # проверка корневой директории + retDir = self.processingDirectory(scanDir, scanDir) + if retDir is None: + return None + elif retDir is False: + return False + if flagDir or stat.S_ISDIR(os.lstat(scanDir)[stat.ST_MODE]): + for fileOrDir in sorted(os.listdir(scanDir)): + absPath = os.path.join(scanDir,fileOrDir) + relPath = absPath.split(prefix)[1] + stInfo = os.lstat(absPath) + statInfo = stInfo[stat.ST_MODE] + if stat.S_ISREG(statInfo): + # Обработка файла + if relPath in skipFile: + continue + if not self.processingFile(absPath, prefix): + ret = False + break + elif stat.S_ISDIR(statInfo): + # Обработка директории + if relPath in skipDir: + continue + retDir = self.processingDirectory(absPath, prefix) + if retDir is None: + continue + elif retDir is False: + ret = False + break + ret = self.scanningTemplates(absPath, skipFile, + skipDir, prefix, True) + if ret is False: + break + return ret + + +class profile(_file, _terms, xmlShare, processingTemplates): + """Класс для работы с профилями + + На вход 2 параметра: объект хранения переменных, имя сервиса - не + обязательный параметр + + """ + # Словарь установленных программ {"имя программы":[версии]} + installProg = {} + + # Cписок просканированных категорий установленных программ + installCategory = [] + + # Флаг сканирования всех установленных программ + flagAllPkgScan = False + + # Название файла профиля директории + profDirNameFile = ".calculate_directory" + + # стек глобальных переменных + stackGlobalVars = [] + + # директория установленных программ + basePkgDir = "/var/db/pkg" + + # регулярное выражение для поиска версии + reFindVer = re.compile("(?<=\-)\d+\.?\d*\.?\d*") + + def __init__(self, objVar, servDir=False, dirsFilter=None, filesFilter=None): + # Необрабатываемые директории + self.dirsFilter = dirsFilter if dirsFilter is not None else [] + # Необрабатываемые файлы + self.filesFilter = filesFilter if filesFilter is not None else [] + _file.__init__(self) + # Словарь для создания объектов новых классов по образцу + self.newObjProt = {'proftpd':(apache,),} + # Заголовок title + self.__titleHead = "--------------------------------------\ +----------------------------------------" + self._titleBody = "" + self._titleList = (_("Modified"), _("File of a profile")) + + # Метки + varStart = "#-" + varEnd = "-#" + self._reVar = re.compile(("%s[a-zA-Z0-9_-]+%s")%(varStart,varEnd),re.M) + self._reFunc = re.compile(("%s[a-zA-Z0-9_\-\+\(\)\, \*\/\.\'\"~]+%s")\ + %(varStart,varEnd),re.M) + self._deltVarStart = len(varStart) + self._deltVarEnd = len(varEnd) + # Условия + self._reTermBloc = re.compile("#\?(?P[a-zA-Z0-9\-_]+)\ +(?P\([a-zA-Z0-9_\-\+\,\*\/\.\'\"~]+\))?\ +(?P[\>\<\=\!\&\|]+\ +[a-zA-Z0-9\>\<\=\!\|\&\-\+\*\/_\.\,\(\)\'\"~]*)#\ +\n*(?P.+?)\n*#(?P=rTerm)#(?P[ ,\t]*\n?)",re.M|re.S) + # Объект с переменными + self.objVar = objVar + # Базовая директория переноса профилей "/mnt/calculate" или "/" и.т.д + baseDir = self.objVar.Get("cl_root_path") + #self._baseDir = os.path.split(baseDir)[0] + self._baseDir = baseDir + if self._baseDir == "/": + self._baseDir = "" + # Последняя часть директории профиля (имя сервиса: samba, mail) + self._servDir = servDir + if self._servDir: + if self._servDir[0] != "/": + self._servDir = "/" + self._servDir + if self._servDir[-1] != "/": + self._servDir += "/" + self._servDir = os.path.split(self._servDir)[0] + # Созданные директории + self.createdDirs = [] + # Примененные файлы + self.filesApply = [] + # номер обрабатываемого файла + self.numberProcessProf = 0 + # имя текущей программы + _nameProgram = self.objVar.Get("cl_name").capitalize() + # версия текущей программы + _versionProgram = self.objVar.Get("cl_ver") + # имя и версия текущей программы + self.programVersion = "%s %s"%(_nameProgram, _versionProgram) + # Словарь измененных директорий + self.changeDirs = {} + # Словарь директорий с количесвом файлов шаблонов + self.dictTemplates = {} + # Общее количество шаблонов + self.allTemplates = 0 + # Аттрибуты для функции шаблона ini() + # Первоначальный словарь переменных для ini() + self.prevDictIni = {} + # Текущий словарь переменных для ini() + self.currDictIni = {} + # Время модификации конфигурационного файла для ini() + self.timeIni = -1 + self.uid, self.gid, self.homeDir = self.getDataUser() + # Путь к конфигурационному файлу для ini() + self.pathConfigIni = os.path.join(self.homeDir, ".calculate") + self.fileConfigIni = os.path.join(self.pathConfigIni,"ini.env") + # Словарь времен модификации env файлов + self.timeConfigsIni = {} + + def getDataUser(self): + """Получить информацию о пользователе""" + userName = self.objVar.Get("ur_login") + if not userName: + userName = "root" + import pwd + try: + pwdObj = pwd.getpwnam(userName) + uid = pwdObj.pw_uid + gid = pwdObj.pw_gid + homeDir = pwdObj.pw_dir + except: + print(_("Can not found user %s")%str(userName)) + cl_base.exit(1) + return uid, gid, homeDir + + + # Преобразование восьмеричного в целое (ввод строка, вывод число) + def __octToInt(self, strOct): + if strOct: + try: + # exec("res =" + "0" + strOct) + res = int(strOct, 8) + except: + self.setError (_("Not valid oct value: ") + str(strOct)) + return False + return res + else: + self.setError (_("Empty oct value")) + return False + + def removeDir(self, rmDir): + """Рекурсивное удаление директории + + входной параметр директория + Обязательно должен быть определен метод self.printERROR + """ + if not os.path.exists(rmDir): + self.printERROR(_("Not found remove dir %s") %rmDir) + return False + fileObj = _file() + # Сканируем директорию + scanObjs = fileObj.scanDirs([rmDir]) + for socketRm in scanObjs[0].sockets: + # Удаляем сокеты + if os.path.exists(socketRm): + os.remove(socketRm) + for linkRm in scanObjs[0].links: + # Удаляем ссылки + os.unlink(linkRm[1]) + for fileRm in scanObjs[0].files: + # Удаляем файлы + os.remove(fileRm) + scanObjs[0].dirs.sort(key=len, reverse=True) + for dirRm in scanObjs[0].dirs: + # Удаляем директории + os.rmdir(dirRm) + if rmDir: + os.rmdir(rmDir) + return True + + + def createDir(self, baseProfDir, profDir, baseDirMv, createDir): + """Создает директорию + + baseDirMv + результат вычитания из profDir baseProfDir + createDir - создаваемая директория + """ + if baseDirMv and not os.access(baseDirMv, os.F_OK): + os.makedirs(baseDirMv) + # Созданные директории + createDirs = [] + baseDir = baseProfDir + if baseProfDir[-1] == "/": + baseDir = baseProfDir[:-1] + # Директория в системе относительно baseDirMv без условий + if baseDirMv: + dirMvNoTerm = createDir.partition(baseDirMv)[2] + else: + dirMvNoTerm = createDir + # директория в системе + dirMv = profDir.partition(baseDir)[2] + if len(dirMv)>1 and dirMv[-1] == "/": + dirMv = dirMv[:-1] + ## директория в системе без условий + #dirMvNoTerm = "/".join(map(lambda x:x.split("?")[0],\ + #dirMv.split("/"))) + listDirMv = dirMv.split("/") + listDirMvNoTerm = dirMvNoTerm.split("/") + if len(listDirMv) != len(listDirMvNoTerm): + self.setError (_("Error in profile") + " :" + profDir) + return False + genIn = listDirMv.__iter__() + genOut = listDirMvNoTerm.__iter__() + inAndOutDirs = [[x,next(genOut)] for x in genIn] + createDirs = [] + createDir = [] + while (len(inAndOutDirs)>1): + tmpDirIn = baseDir + "/".join(x[0] for x in inAndOutDirs) + tmpDirOut = baseDirMv + "/".join(x[1] for x in inAndOutDirs) + if os.access(tmpDirOut, os.F_OK): + break + else: + createDir.append((tmpDirIn, tmpDirOut)) + inAndOutDirs.pop() + createDir.reverse() + for crDirIn,crDirOut in createDir: + try: + mode,uid,gid = self.getModeFile(crDirIn) + except OSError: + self.setError (_("not access dir:" ) + crDirIn) + return False + createDirs.append(crDirOut) + os.mkdir(crDirOut, mode) + os.chown(crDirOut, uid, gid) + return createDirs + + + def applyVarsProfile(self, textProfile, nameProfile): + """ Заменяет переменные на их значения + """ + resS = self._reVar.search(textProfile) + textProfileTmp = textProfile + while resS: + mark = textProfileTmp[resS.start():resS.end()] + varName = mark[self._deltVarStart:-self._deltVarEnd] + varValue = "" + try: + varValue = str(self.objVar.Get(varName)) + except self.objVar.DataVarsError as e: + print(_("error in profile %s")%nameProfile) + print(e) + cl_base.exit(1) + textProfileTmp = textProfileTmp.replace(mark, varValue) + resS = self._reVar.search(textProfileTmp) + return textProfileTmp + + + def applyFuncProfile(self, textProfile, nameProfile, nameSystemFile): + """ Применяет функции к тексту профиля + """ + def equalTerm(term, sNum, sMD, localVars): + """Локальная функция для вычисления выражения""" + terms = sNum.findall(term) + if terms: + strNumers = [] + for n in terms: + strNum = n.strip() + if "*" in strNum or "/" in strNum: + strNum = multAndDiv(strNum,sNum,sMD,localVars) + try: + num = int(strNum) + except: + minus = False + if strNum[:1] == "-": + minus = True + strNum = strNum[1:] + if strNum in localVars: + try: + num = int(localVars[strNum]) + except: + print(_("error in profile %s")%nameProfile) + print(_("error local var %s not int")\ + %str(strNum)) + cl_base.exit(1) + elif self.objVar.exists(strNum): + try: + num = int(self.objVar.Get(strNum)) + except: + print(_("error in profile %s")%nameProfile) + print(_("error var %s not int")%str(strNum)) + cl_base.exit(1) + else: + print(_("error in profile %s")%nameProfile) + print(_("error local var %s not defined")\ + %str(strNum)) + cl_base.exit(1) + if minus: + num =-num + strNumers.append(num) + return sum(strNumers) + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s, incorrect data")%str(term)) + cl_base.exit(1) + + def multAndDiv(term,sNum,sMD,localVars): + """локальная функция для умножения и деления""" + termTmp = term + varsLocal = sMD.findall(term) + for var in varsLocal: + flagVarTxt = True + try: + int(var) + except: + flagVarTxt = False + if flagVarTxt: + continue + varReplace = str(equalTerm(var,sNum,sMD,localVars)) + termTmp = termTmp.replace(var,varReplace) + ret = eval(termTmp) + return ret + + def funcSum(funTxt,resS,localVars,textProfileTmp): + """локальная функция вычисляет первую функцию sum() в профиле""" + terms = funTxt[4:-1].replace(" ","").split(",") + # Название локальной переменной + nameLocVar = terms[0] + if nameLocVar not in localVars: + localVars[nameLocVar] = 0 + if len(terms) == 2: + if terms[1].strip(): + localVars[nameLocVar] = equalTerm(terms[1],sNum,sMD, + localVars) + replace = str(localVars[nameLocVar]) + else: + replace = "" + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + elif len(terms) == 3: + if terms[1].strip(): + replaceInt = equalTerm(terms[1],sNum,sMD,localVars) + replace = str(replaceInt) + else: + replace = "" + localVars[nameLocVar] = equalTerm(terms[2], + sNum,sMD,localVars) + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + return textProfileTmp + + + def funcExists(funTxt,resS,textProfileTmp): + """если файл существует читает из файла локальную переменную + + если один параметр - выводит значение локальной переменной + """ + terms = funTxt[7:-1].replace(" ","").split(",") + if len(terms) !=1: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + fileName = terms[0].strip() + if fileName[0] == "~": + # Получаем директорию пользователя + fileName = os.path.join(self.homeDir, + fileName.partition("/")[2],"")[:-1] + elif fileName[0] != "/": + path = os.path.split(nameSystemFile)[0] + fileName=os.path.join(path,fileName) + replace = "" + if os.path.exists(fileName): + replace = "1" + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def funcLoad(funTxt,resS,textProfileTmp): + """если файл существует читает из файла локальную переменную + + если один параметр - выводит значение локальной переменной + """ + terms = funTxt[5:-1].replace(" ","").split(",") + if not terms[0].strip() or\ + (len(terms)==2 and not terms[1].strip()) or\ + len(terms)>2: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + if len(terms) == 2: + if not terms[0] in ["ver","num","char","key"]: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("first argument function is not 'ver' or 'num' or\ + 'char'")) + cl_base.exit(1) + if len(terms) == 1: + fileName = terms[0].strip() + # Если домашняя директория + if fileName[0] == "~": + # Получаем директорию пользователя + fileName = os.path.join(self.homeDir, + fileName.partition("/")[2],"")[:-1] + elif fileName[0] != "/": + path = os.path.split(nameSystemFile)[0] + fileName=os.path.join(path,fileName) + else: + fileName = terms[1].strip() + # Если домашняя директория + if fileName[0] == "~": + # Получаем директорию пользователя + fileName = os.path.join(self.homeDir, + fileName.partition("/")[2],"")[:-1] + elif fileName[1] != "/": + path = os.path.split(nameSystemFile)[0] + fileName=os.path.join(path,fileName) + replace = "" + if os.path.exists(fileName): + FD = open(fileName) + replace = FD.read().strip() + FD.close + if not replace and len(terms) == 2 and terms[0] in ["ver","num"]: + replace = "0" + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def getInstallPkgGentoo(): + """Выдает словарь инсталлированных программ и номеров версий""" + pkgs = [] + for dirname, dirs, files in os.walk(self.basePkgDir): + for nameFile in dirs + files: + absNameFile = os.path.join(dirname, nameFile) + if os.path.isdir(absNameFile): + tail = absNameFile.split(self.basePkgDir) + if len(tail) == 2: + tail = tail[1].split('/') + if len(tail) == 3 and tail[1] != 'virtual': + pkgs.append(tail[2]) + + return sharePkg(pkgs) + + def sharePkg(pkgs): + """Получение имен и номеров версий программ""" + pkgs.sort() + installProg = {} + for pkg in pkgs: + findVer = self.reFindVer.search(pkg) + if findVer: + version = findVer.group() + name = pkg.split(version)[0][:-1] + if name in installProg: + installProg[name].append(version) + else: + installProg[name] = [version] + return installProg + + def pkg(nameProg, installProg): + """Выдает установленные версии по имени программы""" + if nameProg in installProg: + return installProg[nameProg][-1] + else: + return "" + + def funcPkg(funTxt,resS,textProfileTmp): + """локальная функция выдает номер версии программы""" + terms = funTxt[4:-1].replace(" ","") + # Название программы + nameProg = terms + # Замена функции в тексте шаблона + replace = "" + if "/" in nameProg: + if nameProg in self.installProg: + replace = pkg(nameProg, self.installProg) + else: + category, spl, nProg = terms.partition("/") + if not category in self.installCategory: + self.installCategory.append(category) + pathCategory = os.path.join(self.basePkgDir, category) + if os.path.exists(pathCategory): + pkgs = os.listdir(pathCategory) + pkgs = [os.path.join(category, x) for x in pkgs] + installProg = sharePkg(pkgs) + replace = pkg(nameProg, installProg) + self.installProg.update(installProg) + else: + if not self.flagAllPkgScan: + installProg = getInstallPkgGentoo() + self.installProg.update(installProg) + profile.flagAllPkgScan = True + replace = pkg(nameProg, self.installProg) + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def funcRnd(funTxt,resS,textProfileTmp): + """локальная функция выдает строку случайных символов + + первый аргумент: + 'num' - числа, + 'pas' - цифры и буквы + второй аргумент: + количество символов + """ + terms = funTxt[4:-1].replace(" ","").split(",") + if not terms[0].strip() or\ + (len(terms)==2 and not terms[1].strip()) or\ + len(terms)!=2: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + fArgvNames = ['num','pas'] + if not terms[0] in fArgvNames: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("first argument function is not 'num' or 'pas'")) + cl_base.exit(1) + try: + lenStr = int(terms[1]) + except: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("two argument function is not number")) + cl_base.exit(1) + if terms[0] == fArgvNames[0]: + replace=''.join([random.choice(string.digits)\ + for i in range(lenStr)]) + elif terms[0] == fArgvNames[1]: + replace=''.join([random.choice(string.ascii_letters + \ + string.digits) for i in range(lenStr)]) + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def funcCase(funTxt,resS,textProfileTmp): + """локальная функция выдает переменную в определенном регистре + + первый аргумент: + 'upper' - верхний регистр, + 'lower' - нижний регистр, + 'capitalize' - первая буква в верхнем регистре + второй аргумент: + название переменной + """ + terms = funTxt[5:-1].replace(" ","").split(",") + if not terms[0].strip() or\ + (len(terms)==2 and not terms[1].strip()) or len(terms)!=2: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + fArgvNames = ['upper','lower','capitalize'] + if not terms[0] in fArgvNames: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("first argument function is not 'upper' or 'lower' or\ + 'capitalize'")) + cl_base.exit(1) + try: + strValue = str(self.objVar.Get(terms[1])) + except: + print(_("error in profile %s")%nameProfile) + print(_("error var %s not found")%str(terms[1])) + cl_base.exit(1) + replace = "" + # strValue = self._toUNICODE(strValue) + if terms[0] == 'upper': + replace = strValue.upper() + elif terms[0] == 'lower': + replace = strValue.lower() + elif terms[0] == 'capitalize': + replace = strValue.capitalize() + # if replace: + # replace = replace.encode("UTF-8") + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def funcPush(funTxt,resS,localVars,textProfileTmp): + """локальная функция записывает значение переменной + + в стек глобальных переменных + """ + terms = funTxt[5:-1].replace(" ","").split(",") + # Название локальной переменной + nameLocVar = terms[0] + flagFoundVar = False + if nameLocVar in localVars.keys(): + flagFoundVar = True + value = localVars[nameLocVar] + else: + try: + value = self.objVar.Get(nameLocVar) + flagFoundVar = True + except: + pass + if flagFoundVar: + # Если переменная существует + if len(terms) == 1: + self.stackGlobalVars.append(str(value)) + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("error var %s exists")%str(nameLocVar)) + cl_base.exit(1) + else: + # Если переменная не существует + if len(terms) == 1: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("error var %s not exists")%str(nameLocVar)) + cl_base.exit(1) + elif len(terms) == 2: + value = terms[1].strip() + self.stackGlobalVars.append(str(value)) + localVars[nameLocVar] = value + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + replace = "" + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def funcPop(funTxt,resS,localVars,textProfileTmp): + """локальная функция получает значение + + из стека глобальных переменных и присвает локальной переменной + + """ + terms = funTxt[4:-1].replace(" ","").split(",") + # Название локальной переменной + nameLocVar = terms[0] + if len(terms) == 1: + if self.stackGlobalVars: + localVars[nameLocVar] = self.stackGlobalVars.pop() + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + print(_("error, gloval variables stack is empty")) + cl_base.exit(1) + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + replace = "" + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return textProfileTmp + + def loadVarsIni(iniFileName): + """ Читает файл fileName + создает и заполняет переменные на основе этого файла + Используеться совместно c funcIni + """ + localVarsIni = {} + # Выходим если есть предыдущие ошибки + if self.getError(): + return False + # получить объект ini файла + config = cl_base.iniParser(iniFileName) + # получаем все секции из конфигурационного файла + allsect = config.getAllSectionNames() + if not allsect: + if self.getError(): + # Очистка ошибки + _error.error = [] + return localVarsIni + # Заполняем переменные для funcIni + for sect in allsect: + sectVars = config.getAreaVars(sect) + for name in sectVars.keys(): + nameVar = "%s.%s"%(sect,name) + valueVar = sectVars[name] + localVarsIni[nameVar] = valueVar + return localVarsIni + + def getTimeFile(fileName): + # Получаем время модификации файла + if fileName in self.timeConfigsIni: + return self.timeConfigsIni[fileName] + return 0 + + def funcIni(funTxt, resS, textProfileTmp): + """локальная функция записывает и считывает значение переменной + + из ini файла ~./calculate/ini.env + """ + # Создаем директорию + if not os.path.exists(self.pathConfigIni): + os.makedirs(self.pathConfigIni) + os.chown(self.pathConfigIni, int(self.uid), int(self.gid)) + termsRaw = funTxt[4:-1].split(",") + flagFirst = True + terms = [] + for term in termsRaw: + if flagFirst: + terms.append(term.replace(" ","")) + flagFirst = False + else: + val = term.strip() + # Флаг (не найдены кавычки) + flagNotFoundQuote = True + for el in ('"',"'"): + if val.startswith(el) and val.endswith(el): + terms.append(val[1:-1]) + flagNotFoundQuote = False + break + if flagNotFoundQuote: + terms.append(val) + # Название локальной переменной + nameLocVar = terms[0] + namesVar = nameLocVar.split(".") + if len(namesVar) == 1: + nameLocVar = "main.%s"%nameLocVar + elif len(namesVar)>2: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + replace = "" + # Получаем время модификации конфигурационного файла + curTime = getTimeFile(self.fileConfigIni) + if len(terms) == 1: + if self.timeIni != curTime: + # читаем переменные из файла + self.prevDictIni = loadVarsIni(self.fileConfigIni) + self.currDictIni.update(self.prevDictIni) + self.timeIni = getTimeFile(self.fileConfigIni) + if nameLocVar in self.currDictIni.keys(): + replace = self.currDictIni[nameLocVar] + elif len(terms) == 2: + if self.timeIni != curTime: + # читаем переменные из файла + self.prevDictIni = loadVarsIni(self.fileConfigIni) + self.currDictIni.update(self.prevDictIni) + self.timeIni = getTimeFile(self.fileConfigIni) + # Значение локальной переменной + valueLocVar = terms[1] + self.currDictIni[nameLocVar] = valueLocVar + else: + print(_("error in profile %s")%nameProfile) + print(_("error profile term %s")%str(funTxt)) + cl_base.exit(1) + textProfileTmp = textProfileTmp[:resS.start()] + replace +\ + textProfileTmp[resS.end():] + return (textProfileTmp) + + # Локальные переменные + localVars = {} + # Регулярное выражние для сложения + sNum = re.compile("\-[^\-\+]+|[^\-\+]+") + # Регулярное выражение для умножениея и деления + sMD = re.compile("[^\-\+\*\/]+") + resS = self._reFunc.search(textProfile) + textProfileTmp = textProfile + flagIniFunc = False + while resS: + mark = textProfileTmp[resS.start():resS.end()] + funTxt = mark[self._deltVarStart:-self._deltVarEnd] + # Функция sum + if funTxt.startswith("sum("): + textProfileTmp = funcSum(funTxt,resS,localVars,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + # Функция load + elif funTxt.startswith("load("): + textProfileTmp = funcLoad(funTxt,resS,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("pkg("): + textProfileTmp = funcPkg(funTxt,resS,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("rnd("): + textProfileTmp = funcRnd(funTxt,resS,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("case("): + textProfileTmp = funcCase(funTxt,resS,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("pop("): + textProfileTmp = funcPop(funTxt,resS,localVars,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("push("): + textProfileTmp = funcPush(funTxt,resS,localVars,textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("ini("): + flagIniFunc = True + textProfileTmp = funcIni(funTxt, resS, textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + elif funTxt.startswith("exists("): + textProfileTmp = funcExists(funTxt, resS, textProfileTmp) + resS = self._reFunc.search(textProfileTmp) + else: + resS = False + if flagIniFunc: + # Очистка файла в случае его ошибочного чтения + if not self.prevDictIni and os.path.exists(self.fileConfigIni): + FD = open(self.fileConfigIni, "r+") + FD.truncate(0) + FD.seek(0) + FD.close() + # Если конф. файл модифицирован шаблоном + curTime = getTimeFile(self.fileConfigIni) + if curTime != self.timeIni: + # Считаем переменные из конф. файла + self.prevDictIni = loadVarsIni(self.fileConfigIni) + self.currDictIni.update(self.prevDictIni) + self.timeIni = curTime + # Если словари переменных не совпадают + if self.prevDictIni != self.currDictIni: + # Запишем переменные в конфигурационный файл + # Создание объекта парсера + config = cl_base.iniParser(self.fileConfigIni) + # секции будущего конфигурационного файла + sects = list(set(x.split(".")[0] for x in self.currDictIni.keys())) + # запись переменных в файл + for sect in sects: + dictVar = {} + for varName in self.currDictIni.keys(): + if varName.startswith("%s."%sect): + nameVar = varName.rpartition(".")[2] + valueVar = self.currDictIni[varName] + if valueVar: + dictVar[nameVar] = valueVar + if dictVar: + # Запись переменных в секцию + config.setVar(sect, dictVar) + # читаем переменные из файла + self.prevDictIni = loadVarsIni(self.fileConfigIni) + self.currDictIni.update(self.prevDictIni) + self.timeConfigsIni[self.fileConfigIni] = float(time.time()) + self.timeIni = getTimeFile(self.fileConfigIni) + # Меняем владельца в случае необходимости + if os.path.exists(self.fileConfigIni): + fd = os.open(self.fileConfigIni, os.O_RDONLY) + fst = os.fstat(fd) + uid = fst.st_uid + gid = fst.st_gid + os.close(fd) + if self.uid!=uid or self.gid!=gid: + os.chown(self.fileConfigIni, int(self.uid), int(self.gid)) + return textProfileTmp + + def applyTermsProfile(self, textProfile, nameProfile, nameSystemFile=False): + """ Применяет условия, к условным блокам текста + """ + textTerm = "" + resS = self._reTermBloc.search(textProfile) + textProfileTmp = textProfile + def function(text): + """Функция обработки функций в заголовке""" + return self.applyFuncProfile(text, nameProfile, nameSystemFile) + if nameSystemFile: + while resS: + mark = resS.group(0) + body = resS.group("body") + end = resS.group("end") + parent = resS.group("func") + if not parent: + parent = "" + term = resS.group("rTerm") + parent +\ + resS.group("lTerm") + if self._equalTerm(term, _("content profile not valid: ")+\ + nameProfile, function): + textProfileTmp = textProfileTmp.replace(mark, body+end) + else: + textProfileTmp = textProfileTmp.replace(mark, "") + resS = self._reTermBloc.search(textProfileTmp) + else: + while resS: + mark = resS.group(0) + body = resS.group("body") + end = resS.group("end") + term = resS.group("rTerm") + resS.group("lTerm") + if self._equalTerm(term, _("content profile not valid: ")+\ + nameProfile): + textProfileTmp = textProfileTmp.replace(mark, body+end) + else: + textProfileTmp = textProfileTmp.replace(mark, "") + resS = self._reTermBloc.search(textProfileTmp) + return textProfileTmp + + def getNeedProfile(self, fileProfile): + """Применяем правила к названию файла""" + dirP,fileP = os.path.split(fileProfile) + if fileP: + spFile = fileP.split("?") + realFileName = spFile[0] + if len(spFile)>1: + flagTrue = False + for term in spFile[1:]: + if self._equalTerm(term, _("name profile not valid: ")+\ + fileProfile): + flagTrue = True + break + if flagTrue: + return True + else: + return False + else: + return True + else: + self.setError (_("name profile not valid: ")+ str(fileProfile)) + return False + + def getTitle(self, comment, commentList): + """Выдает заголовок профиля ( версия и.т.д)""" + if comment: + commentFirst = comment + commentInsert = comment + commentLast = comment + flagList = False + # В случае открывающего и закрывающего комментария + if type(comment) == tuple and len(comment) == 2: + commentFirst = comment[0] + commentInsert = "" + commentLast = comment[1] + flagList = True + if flagList: + self._titleBody = commentFirst + "\n" + else: + self._titleBody = commentFirst + self.__titleHead + "\n" + z = 0 + lenCommentList = len(commentList) - 1 + for com in self._titleList: + if lenCommentList < z: + self._titleBody += commentInsert + " " + com + "\n" + else: + self._titleBody += commentInsert + " " + com +\ + " " + commentList[z] + "\n" + z += 1 + if flagList: + self._titleBody += commentLast +"\n" + else: + self._titleBody += commentLast + self.__titleHead + "\n" + return self._titleBody + else: + return "" + + def numberAllProfiles(self, number): + """Количество профилей + + Вызов происходит перед наложением профилей + в момент вызова в number находится количество обрабатываемых файлов + Наследуемая функция + Используется для отображения прогресса при наложениии профилей + """ + return True + + def numberProcessProfiles(self, number): + """Номер текущего обрабатываемого профиля + + Вызов происходит при наложении профиля + в момент вызова в number находится номер обрабатываемого профиля + Наследуемая функция + Используется для отображения прогресса при наложениии профилей + """ + return True + + def scanDirs(self, profilesDirs, objVar=False): + """Измененный метод сканирования директорий""" + dirs = [] + class dirProf: + def __init__(self): + self.baseDir = False + self.dirs = [] + self.files = [] + self.links = [] + self.sockets = [] + flagError = False + blockDirs = [] + + for profileDir in profilesDirs: + if profileDir: + # Обработка условий в названии директории + if self.getNeedProfile(profileDir): + if self.getError(): + flagError = True + break + dirP = dirProf() + dirP.baseDir = profileDir + for dirname, dirs, files in os.walk(profileDir): + for nameFile in dirs + files: + absNameFile = dirname + "/" + nameFile + findBlock = False + for blDir in blockDirs: + st,mid,end = absNameFile.partition(blDir) + if (not st) and mid and end: + findBlock = True + break + if not findBlock: + if os.path.islink(absNameFile): + dest = absNameFile + src = os.readlink(absNameFile) + dirP.links.append((src,dest)) + elif os.path.isfile(absNameFile): + # Добавляем файлы кроме описаний директорий + if self.profDirNameFile != nameFile: + dirP.files.append(absNameFile) + elif os.path.isdir(absNameFile): + # Обработка условий в названии директории + if self.getNeedProfile(absNameFile): + if self.getError(): + blockDirs.append(absNameFile) + flagError = True + break + dirP.dirs.append(absNameFile) + else: + if self.getError(): + blockDirs.append(absNameFile) + flagError = True + break + blockDirs.append(absNameFile) + elif stat.S_ISSOCK(os.stat(absNameFile)[stat.ST_MODE]): + dirP.sockets.append(absNameFile) + dirs.append(dirP) + else: + if self.getError(): + flagError = True + break + if flagError: + return [] + return dirs + + + def applyProfiles(self): + """Применяет профили к конфигурационным файлам""" + + def createDictTemplates(path, prefix, dictTemplates): + """Создает словарь {"директория":"кол-во шаблонов" ...} + + и считает общее количество шаблонов + """ + # Количество шаблонов + self.allTemplates += 1 + dirTemplate = os.path.split(path)[0] + while(True): + if dirTemplate in dictTemplates.keys(): + dictTemplates[dirTemplate] += 1 + else: + dictTemplates[dirTemplate] = 1 + if dirTemplate == prefix: + break + dirTemplate = os.path.split(dirTemplate)[0] + return dictTemplates + + if not self.objVar.defined("cl_profile_path"): + self.setError (_("not defined Var: ") + "cl_profile_path") + return False + dirsProfiles = self.objVar.Get("cl_profile_path") + dirsProfiles.sort() + # Словарь измененных директорий + self.changeDirs = {} + # Созданные директории + self.createdDirs = [] + # Примененные файлы + self.filesApply = [] + # Номер применяемого шаблона + self.numberProcessProf = 0 + # Словарь директорий с количеством файлов шаблонов + self.dictTemplates = {} + # Количество шаблонов + self.allTemplates = 0 + # Время доступа к конфигурационному файлу функции шаблона ini() + self.timeIni = -1 + # Первоначальный словарь переменных для ini() + self.prevDictIni = {} + # Текущий словарь переменных для ini() + self.currDictIni = {} + # Словарь времен модификации env файлов + self.timeConfigsIni = {} + if self._servDir: + tmpDirsProfiles = [] + for dirP in dirsProfiles: + dirProf = dirP + self._servDir + if os.access(dirProf, os.F_OK): + # Если директория существует + tmpDirsProfiles.append(dirProf) + dirsProfiles = tmpDirsProfiles + scanObj = processingTemplates() + scanObj.processingFile = lambda x,y: createDictTemplates(x, y,\ + self.dictTemplates) + # Считаем количество шаблонов + for dirTemplate in dirsProfiles: + scanObj.scanningTemplates(dirTemplate, + skipFile=self.filesFilter, + skipDir=self.dirsFilter) + self.numberAllProfiles(self.allTemplates) + for dirTemplate in dirsProfiles: + if self.scanningTemplates(dirTemplate, + skipFile=self.filesFilter, + skipDir=self.dirsFilter) is False: + return False + return (self.createdDirs, self.filesApply) + + + def processingFile(self, path, prefix): + """Обработка в случае профиля файла""" + self.numberProcessProf += 1 + self.numberProcessProfiles(self.numberProcessProf) + # Пропуск шаблонов директорий + if self.profDirNameFile == os.path.split(path)[1]: + return True + if self.getNeedProfile(path): + if self.getError(): + return False + fileProfileChange = path + findChangeDir = False + listD = list(self.changeDirs.items()) + listD.reverse() + for dirChangeIn, dirChangeOut in listD: + st,mid,end = path.partition(dirChangeIn) + if (not st) and mid and end: + findChangeDir = True + break + if findChangeDir: + oldFile = dirChangeOut + end + else: + oldFile = path.partition(prefix)[2] + # файл в системе без условий + oldFile = "/".join(x.split("?")[0] for x in oldFile.split("/")) + if not findChangeDir: + oldFile = self._baseDir + oldFile + # Фильтрация профилей по названию файла + if oldFile in self.filesFilter: + return True + listProfTitle = prefix.split("/")[-2:] + profTitle = '"' + "/".join(listProfTitle) + '"' + # Записываем в переменную обрабатываемый файл + self.objVar.Set("cl_pass_file",oldFile) + # Пишем время модификации *.env файлов + if oldFile.endswith(".env"): + self.timeConfigsIni[oldFile] = float(time.time()) + filesApl = self.join(path, oldFile, + (self.programVersion,profTitle)) + if filesApl: + self.filesApply += filesApl + else: + if self.getError(): + #print self.getError() + return False + return True + + def processingDirectory(self, path, prefix): + """Обработка в случае директории если возвращаем None то пропуск дир.""" + # Файл шаблона директории + dirInfoFile = os.path.join(path, self.profDirNameFile) + # Проверяем заголовок + ret = self.__isApplyHeadDir(dirInfoFile) + if not ret: + if self.getError(): + self.setError(_("Incorrect profile: " ) + dirInfoFile) + return False + # Добавление количества файлов в пропущенной директории + if path in self.dictTemplates.keys(): + self.numberProcessProf += self.dictTemplates[path] + return None + newDir = self._baseDir + path.partition(prefix)[2] + newDir = "/".join(x.split("?")[0] for x in newDir.split("/")) + # Применяем шаблон + pathDir, objHeadDir = self.__getApplyHeadDir(newDir, + dirInfoFile, + self.changeDirs) + # Фильтрация профилей по названию директории + if pathDir in self.dirsFilter: + # Добавление количества файлов в пропущенной директории + if path in self.dictTemplates.keys(): + self.numberProcessProf += self.dictTemplates[path] + return None + if objHeadDir: + if isinstance(objHeadDir, dirHeader): + if not objHeadDir.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + self.setError(objHeadDir.errorMessage) + return False + if not objHeadDir.headerTerm: + if objHeadDir.getError(): + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + return False + if "name" in objHeadDir.params: + self.changeDirs[path] = pathDir + crDirs = self.createDir(prefix, path, + self._baseDir, pathDir) + if crDirs is False: + return False + self.createdDirs += crDirs + else: + if self.getError(): + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + return False + # Добавление количества файлов в пропущенной директории + if path in self.dictTemplates.keys(): + self.numberProcessProf += self.dictTemplates[path] + return None + return True + + def __getGenHeadDir(self, newDir, profileDirFile, changeDirs): + """Определяет название создаваемой директории""" + + def function(text): + """Функция обработки функций в заголовке""" + return self.applyFuncProfile(text, newDir, profileDirFile) + + newDirMv = newDir + findChangeDir = False + #Меняем путь к директории + listD = list(changeDirs.items()) + listD.reverse() + for dirChangeIn, dirChangeOut in listD: + st,mid,end = profileDirFile.partition(dirChangeIn) + if (not st) and mid: + findChangeDir = True + break + if findChangeDir: + pathRel = dirChangeOut + lenPathRel = len(pathRel.split("/")) + lenNewDir = len(newDir.split("/")) + lenEndDir = lenNewDir - lenPathRel + tmpDir = newDir + namesDirs = [] + for i in range(lenEndDir): + namesDirs.append(os.path.split(tmpDir)[1]) + tmpDir = os.path.split(tmpDir)[0] + namesDirs.reverse() + nameDir = "/".join(namesDirs) + newDirMv = os.path.join(pathRel, nameDir) + applyDir = newDirMv + if not os.path.exists(profileDirFile): + return (applyDir, True) + try: + FD = open(profileDirFile) + textProfile = FD.read() + FD.close() + except: + self.setError(_("Error open profile: " ) +\ + profileDirFile) + return (applyDir, False) + objHead = dirHeader(textProfile, self.objVar,function) + if not objHead.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + self.setError(objHead.errorMessage) + return (applyDir, False) + if not objHead.headerTerm: + if objHead.getError(): + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + return (applyDir, False) + # Изменяем название директории + if "name" in objHead.params: + nameDir = objHead.params['name'] + if "/" in nameDir or nameDir == ".." or nameDir == ".": + self.setError (_("False value 'name' in profile: " ) +\ + profileDirFile) + return (applyDir, False) + if not findChangeDir: + pathRel = os.path.split(os.path.abspath(newDirMv))[0] + # Новый путь к оригинальному файлу + newDirMv = os.path.join(pathRel, nameDir) + applyDir = newDirMv + # При удаленнии директории + if objHead.typeAppend == "remove": + return (applyDir, False) + return (applyDir, objHead) + + def scanProfiles(self, serviceName=False, dirObjs=False): + """Сканирует директории профилей - выводит список файлов""" + if not self.objVar.defined("cl_profile_path"): + self.setError (_("not defined Var: ") + "cl_profile_path") + return False + if not dirObjs: + if serviceName : + self._servDir = serviceName + if self._servDir: + if self._servDir[0] != "/": + self._servDir = "/" + self._servDir + if self._servDir[-1] != "/": + self._servDir += "/" + self._servDir = os.path.split(self._servDir)[0] + dirsProfiles = self.objVar.Get("cl_profile_path") + if self._servDir: + tmpDirsProfiles = [] + for dirP in dirsProfiles: + dirProf = dirP + self._servDir + if os.access(dirProf, os.F_OK): + # Если директория существует + tmpDirsProfiles.append(dirProf) + else: + tmpDirsProfiles.append(False) + dirsProfiles = tmpDirsProfiles + dirObjs = self.scanDirs(dirsProfiles,self.objVar) + #файлы к которым были применены профили + filesApply = [] + # Словарь измененных директорий + changeDirs = {} + dirObjsApply = [] + for dirObj in dirObjs: + dirInfoFile = os.path.join(dirObj.baseDir, self.profDirNameFile) + ret = self.__isApplyHeadDir(dirInfoFile) + if ret: + dirObjsApply.append(dirObj) + else: + if self.getError(): + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + return False + for dirObj in dirObjsApply: + # сортируем файлы по названию + if dirObj.files: + dirObj.files.sort() + # сортируем директории по названию + if dirObj.dirs: + dirObj.dirs.sort() + blockDirs = [] + for dirProfile in dirObj.dirs: + newDir = self._baseDir + dirProfile.partition(dirObj.baseDir)[2] + newDir = "/".join(x.split("?")[0] for x in newDir.split("/")) + # Проверяем условие на директорию + dirInfoFile = os.path.join(dirProfile, self.profDirNameFile) + pathDir, objHeadDir = self.__getGenHeadDir(newDir, + dirInfoFile, + changeDirs) + # Фильтрация профилей по названию директории + if pathDir in self.dirsFilter: + blockDirs.append(dirProfile) + continue + if objHeadDir: + if isinstance(objHeadDir, dirHeader): + if not objHeadDir.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + self.setError(objHeadDir.errorMessage) + return False + if not objHeadDir.headerTerm: + if objHeadDir.getError(): + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + return False + if "name" in objHeadDir.params: + changeDirs[dirProfile] = pathDir + else: + if self.getError(): + self.setError(_("Incorrect profile: " ) +\ + dirInfoFile) + return False + blockDirs.append(dirProfile) + for fileProfile in dirObj.files: + findBlock = False + for blDir in blockDirs: + st,mid,end = fileProfile.partition(blDir) + if (not st) and mid and end: + findBlock = True + break + if findBlock: + continue + if self.getNeedProfile(fileProfile): + if self.getError(): + #print self.getError() + return False + fileProfileChange = fileProfile + findChangeDir = False + listD = list(changeDirs.items()) + listD.reverse() + for dirChangeIn, dirChangeOut in listD: + st,mid,end = fileProfile.partition(dirChangeIn) + if (not st) and mid and end: + findChangeDir = True + break + if findChangeDir: + oldFile = dirChangeOut + end + else: + oldFile = fileProfile.partition(dirObj.baseDir)[2] + # файл в системе без условий + oldFile = "/".join(x.split("?")[0] for x in oldFile.split("/")) + if not findChangeDir: + oldFile = self._baseDir + oldFile + # Фильтрация профилей по названию файла + if oldFile in self.filesFilter: + continue + filesApply.append(oldFile) + else: + if self.getError(): + return False + return filesApply + + def __isApplyHeadDir(self, profileDirFile): + """Будет ли применен профиль корневой директории + + Возвращает True, False + """ + + def function(text): + """Функция обработки функций в заголовке""" + return self.applyFuncProfile(text, "", profileDirFile) + + if not os.path.exists(profileDirFile): + return True + try: + FD = open(profileDirFile) + textProfile = FD.read() + FD.close() + except: + self.setError(_("Error open profile: " ) +\ + profileDirFile) + return False + # Заменяем переменные на их значения + textProfile = self.applyVarsProfile(textProfile, profileDirFile) + # Обработка заголовка + objHead = dirHeader(textProfile, self.objVar,function) + if not objHead.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + self.setError(objHead.errorMessage) + return False + if not objHead.headerTerm: + if objHead.getError(): + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + return False + + ## Изменяем название директории + #if objHead.params.has_key("name"): + #self.setError (_("Invalid name 'name' in profile: " ) +\ + #profileDirFile) + #return False + + ## Удаляем директорию + #if objHead.typeAppend == "remove": + #self.setError (_("Invalid name 'remove' in profile: " ) +\ + #profileDirFile) + #return False + + ## chmod - изменяем права + #if objHead.params.has_key("chmod"): + #self.setError (_("Invalid name 'chmod' in profile: " ) +\ + #profileDirFile) + #return False + + ## chown - изменяем владельца и группу + #if objHead.params.has_key("chown"): + #self.setError (_("Invalid name 'chown' in profile: " ) +\ + #profileDirFile) + #return False + return True + + def __getApplyHeadDir(self, newDir, profileDirFile, changeDirs): + """Применяет профиль к директории (права, владелец, и.т. д)""" + + def function(text): + """Функция обработки функций в заголовке""" + return self.applyFuncProfile(text, newDir, profileDirFile) + + newDirMv = newDir + findChangeDir = False + #Меняем путь к директории + listD = list(changeDirs.items()) + listD.reverse() + for dirChangeIn, dirChangeOut in listD: + st,mid,end = profileDirFile.partition(dirChangeIn) + if (not st) and mid: + findChangeDir = True + break + if findChangeDir: + pathRel = dirChangeOut + lenPathRel = len(pathRel.split("/")) + lenNewDir = len(newDir.split("/")) + lenEndDir = lenNewDir - lenPathRel + tmpDir = newDir + namesDirs = [] + for i in range(lenEndDir): + namesDirs.append(os.path.split(tmpDir)[1]) + tmpDir = os.path.split(tmpDir)[0] + namesDirs.reverse() + nameDir = "/".join(namesDirs) + newDirMv = os.path.join(pathRel, nameDir) + applyDir = newDirMv + if not os.path.exists(profileDirFile): + return (applyDir, True) + try: + FD = open(profileDirFile) + textProfile = FD.read() + FD.close() + except: + self.setError(_("Error open profile: " ) +\ + profileDirFile) + return (applyDir, False) + # Заменяем переменные на их значения + textProfile = self.applyVarsProfile(textProfile, profileDirFile) + # Обработка заголовка + objHead = dirHeader(textProfile, self.objVar,function) + if not objHead.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + self.setError(objHead.errorMessage) + return (applyDir, False) + if not objHead.headerTerm: + if objHead.getError(): + self.setError(_("Incorrect profile: " ) +\ + profileDirFile) + return (applyDir, False) + + # Изменяем название директории + if "name" in objHead.params: + nameDir = objHead.params['name'] + if "/" in nameDir or nameDir == ".." or nameDir == ".": + self.setError (_("False value 'name' in profile: " ) +\ + profileDirFile) + return (applyDir, False) + if not findChangeDir: + pathRel = os.path.split(os.path.abspath(newDirMv))[0] + # Новый путь к оригинальному файлу + newDirMv = os.path.join(pathRel, nameDir) + applyDir = newDirMv + + # Удаляем директорию + if objHead.typeAppend == "remove": + if os.path.isdir(newDirMv): + # удаляем директорию + try: + self.removeDir(newDirMv) + except: + self.setError(_("Can not delete dir: " ) +\ + newDirMv) + return (applyDir, False) + + # chmod - изменяем права + if "chmod" in objHead.params: + mode = self.__octToInt(objHead.params['chmod']) + if mode: + if not os.path.exists(newDirMv): + os.mkdir(newDirMv, mode) + else: + os.chmod(newDirMv, mode) + else: + self.setError (_("False value 'chmod' in profile: " ) +\ + profileDirFile) + return (applyDir, False) + # chown - изменяем владельца и группу + if "chown" in objHead.params: + owner = objHead.params['chown'] + if owner: + if ":" in owner: + strUid, strGid = owner.split(":") + import pwd + try: + uid = pwd.getpwnam(strUid)[2] + except: + self.setError (_("Not user in this system: ") + strUid) + self.setError (_("False value 'chown' in profile: " )+\ + profileDirFile) + return (applyDir, False) + try: + import grp + gid = grp.getgrnam(strGid)[2] + except: + self.setError (_("Not group in this system: ")+strGid) + self.setError (_("False value 'chown' in profile: " )+\ + profileDirFile) + return (applyDir, False) + + if not os.path.exists(newDirMv): + dirProfile = os.path.split(profileDirFile)[0] + try: + mode,uidTmp,gidTmp = self.getModeFile(dirProfile) + except OSError: + self.setError (_("not access dir:" ) + newDirMv) + return (applyDir, False) + os.mkdir(newDirMv, mode) + os.chown(newDirMv, uid, gid) + else: + self.setError (_("False value 'chown' in profile: " ) +\ + profileDirFile) + return (applyDir, False) + else: + self.setError (_("False value 'chown' in profile: " ) +\ + profileDirFile) + return (applyDir, False) + return (applyDir, objHead) + + def __getApplyHeadProfile(self ,newFile, oldFile, copyFile): + """Применяет заголовок к профилю (права, владелец, и.т. д)""" + + def function(text): + """Функция обработки функций в заголовке""" + return self.applyFuncProfile(text, newFile, oldFile) + + self.closeFiles() + # Файлы в системе к которым были применены профили + applyFiles = [oldFile] + if copyFile: + self.nameFileNew = self.absFileName(newFile) + self.FN = self.openNewFile(self.nameFileNew) + self.newProfile = self.FN.read() + self.closeNewFile() + objHeadNew = fileHeader(self.newProfile, False, + self.getFileType(),objVar=self.objVar, + function=function) + if not objHeadNew.headerCorrect: + self.setError(_("Incorrect profile: " ) +\ + newFile) + self.setError(objHeadNew.errorMessage) + return (applyFiles, False) + if not objHeadNew.headerTerm: + if objHeadNew.getError(): + self.setError(_("Incorrect profile: " ) +\ + newFile) + return (applyFiles, False) + + pathProg = "" + # Путь к оригинальному файлу + pathOldFile = oldFile + # Изменяем путь к оригинальному файлу + if "name" in objHeadNew.params: + nameFile = objHeadNew.params['name'] + if "/" in nameFile or nameFile == ".." or nameFile == ".": + self.setError (_("False value 'name' in profile: " ) + newFile) + return False + pathRel = os.path.split(os.path.abspath(oldFile))[0] + # Новый путь к оригинальному файлу + pathOldFile = os.path.join(pathRel,nameFile) + + # В случае force + if "force" in objHeadNew.params: + if os.path.islink(pathOldFile): + # удаляем ссылку + try: + os.unlink(pathOldFile) + except: + self.setError(_("Can not delete link: " ) +\ + pathOldFile) + return (applyFiles, False) + if os.path.isfile(pathOldFile): + # удаляем файл + try: + os.remove(pathOldFile) + except: + self.setError(_("Can not delete file: " ) +\ + pathOldFile) + return (applyFiles, False) + + # Удаляем оригинальный файл + if objHeadNew.typeAppend == "remove": + if os.path.islink(pathOldFile): + # удаляем ссылку + try: + os.unlink(pathOldFile) + except: + self.setError(_("Can not delete link: " ) +\ + pathOldFile) + if os.path.isfile(pathOldFile): + # удаляем файл + try: + os.remove(pathOldFile) + except: + self.setError(_("Can not delete file: " ) +\ + pathOldFile) + return (applyFiles, False) + + flagSymlink = False + flagForce = False + # Если есть параметр mirror + if "mirror" in objHeadNew.params: + if "link" in objHeadNew.params: + profileFile = objHeadNew.params['link'] + if not os.path.exists(profileFile): + if os.path.exists(pathOldFile): + os.remove(pathOldFile) + return (applyFiles, False) + elif not os.path.exists(pathOldFile): + return (applyFiles, False) + # Если есть указатель на файл профиля (link) + if "link" in objHeadNew.params and\ + "symbolic" not in objHeadNew.params: + profileFile = objHeadNew.params['link'] + foundProfileFile = os.path.exists(profileFile) + if foundProfileFile: + FO = self.openNewFile(profileFile) + buff = FO.read() + FO.close() + if os.path.exists(pathOldFile): + os.remove(pathOldFile) + if foundProfileFile: + fd = os.open(pathOldFile, os.O_CREAT) + os.close(fd) + os.chmod(pathOldFile, self._mode) + os.chown(pathOldFile, self._uid, self._gid) + FON = open (pathOldFile, "r+") + FON.write(buff) + FON.close() + + # Если символическая ссылка + if "symbolic" in objHeadNew.params: + prevOldFile = pathOldFile + pathOldFile = objHeadNew.params['link'] + flagSymlink = True + if not "/" == pathOldFile[0]: + pathLink = os.path.split(os.path.abspath(prevOldFile))[0] + pathProg = os.getcwd() + os.chdir(pathLink) + + # chmod - изменяем права + if "chmod" in objHeadNew.params: + mode = self.__octToInt(objHeadNew.params['chmod']) + if mode: + if not os.path.exists(pathOldFile): + fd = os.open(pathOldFile, os.O_CREAT) + os.close(fd) + os.chmod(pathOldFile, mode) + else: + self.setError (_("False value 'chmod' in profile: " ) +\ + newFile) + return (applyFiles, False) + + # chown - изменяем владельца и группу + if "chown" in objHeadNew.params: + owner = objHeadNew.params['chown'] + if owner: + if ":" in owner: + strUid, strGid = owner.split(":") + import pwd + try: + uid = pwd.getpwnam(strUid)[2] + except: + self.setError (_("Not user in this system: ") + strUid) + self.setError (_("False value 'chown' in profile: " )+\ + newFile) + return (applyFiles, False) + try: + import grp + gid = grp.getgrnam(strGid)[2] + except: + self.setError (_("Not group in this system: ")+strGid) + self.setError (_("False value 'chown' in profile: " )+\ + newFile) + return (applyFiles, False) + + if not os.path.exists(pathOldFile): + FO = self.openNewFile(newFile) + FO.close() + fd = os.open(pathOldFile, os.O_CREAT) + os.close(fd) + os.chmod(pathOldFile, self._mode) + os.chown(pathOldFile, uid, gid) + else: + self.setError (_("False value 'chown' in profile: " ) +\ + newFile) + return (applyFiles, False) + else: + self.setError (_("False value 'chown' in profile: " ) +\ + newFile) + return (applyFiles, False) + + self.openFiles(newFile, pathOldFile) + if flagSymlink: + if os.path.exists(prevOldFile) or os.path.islink(prevOldFile): + if os.path.islink(prevOldFile): + # если ссылка то удаляем её + os.unlink(prevOldFile) + else: + # иначе удаляем файл + os.remove(prevOldFile) + if not "/" == pathOldFile[0]: + os.symlink(pathOldFile, prevOldFile) + applyFiles = [prevOldFile,os.path.join(pathLink,pathOldFile)] + else: + os.symlink(pathOldFile, prevOldFile) + applyFiles = [prevOldFile,pathOldFile] + if not objHeadNew.body.strip(): + return (applyFiles, False) + else: + applyFiles = [pathOldFile] + if pathProg: + os.chdir(pathProg) + # Если файлы заменяются не нужно их обрабатывать дальше + if objHeadNew.typeAppend == "replace" and\ + "symbolic" not in objHeadNew.params and\ + "link" in objHeadNew.params: + return (applyFiles, False) + return (applyFiles, objHeadNew) + + def createNewClass(self, name, bases, attrs=None): + """Создает объект нового класса + + createNewClass(self, name, bases, attrs) + name - имя класса - str, + bases - cписок наследуемых классов - (tuple), + attrs - аттрибуты класса - {dict} + """ + if attrs is None: + attrs = {} + class newMethod: + #Объединяем конфигурации + def join(self, newObj): + if newObj.__class__.__name__ == self.__class__.__name__: + self.docObj.joinDoc(newObj.doc) + # Пост обработка + if 'postXML' in dir(self): + self.postXML() + attrsNew = {} + attrsNew["configName"] = name + if attrs: + for key in attrs.keys(): + attrsNew[key] = attrs[key] + newCl = type(name, bases + (newMethod, object,), attrsNew) + return newCl + + def fileIsUtf(self, fileName): + """Проверяет файл на кодировку UTF-8""" + if os.path.exists(fileName): + try: + with open(fileName, encoding="utf-8", errors="strict") as FD: + newProfile = FD.read() + except: + return False + return True + + def join(self, newFile, oldFile, ListOptTitle): + """Объединения профиля и конф. файла + + join(newFile, oldFile, ListOptTitle) + Объединение профиля newFile и конф. файла oldFile, + ListOptTitle - список строк которые добавятся в заголовок + """ + # Выполняем условия для блока текста а так-же заменяем переменные + self.nameFileNew = self.absFileName(newFile) + self.FN = self.openNewFile(self.nameFileNew) + self.newProfile = self.FN.read() + self.closeNewFile() + copyFile = True + if self.getFileType() != "bin": + # Вычисляем условные блоки + self.newProfile = self.applyTermsProfile(self.newProfile, + newFile, oldFile) + #print "|%s|" %(self.newProfile) + # Заменяем переменные на их значения + self.newProfile = self.applyVarsProfile(self.newProfile, + newFile) + # Вычисляем функции + self.newProfile = self.applyFuncProfile(self.newProfile, + newFile, oldFile) + copyFile = False + filesApply, objHeadNew = self.__getApplyHeadProfile(newFile, oldFile, + copyFile) + if not objHeadNew: + return filesApply + # Флаг - кодировка с бинарными примесями у файла профиля включаем при + # условии текстового файла и кодировки отличной от UTF-8 + flagNotUtf8New = False + # Флаг - кодировка с бинарными примесями у оригинального файла + flagNotUtf8Old = False + if not copyFile: + # проверяем кодировку профиля + if not self.fileIsUtf(newFile): + flagNotUtf8New = True + if not ("link" in objHeadNew.params and\ + "symbolic" in objHeadNew.params): + # проверяем кодировку оригинального файла + if not self.fileIsUtf(oldFile): + flagNotUtf8Old = True + self.newProfile = objHeadNew.body + #if objHeadNew.fileType != "bin": + #self.newProfile = self.applyTermsProfile(self.newProfile, + #newFile) + #self.newProfile = self.applyVarsProfile(self.newProfile) + + # Титл конфигурационного файла + title = "" + if ListOptTitle: + title = self.getTitle(objHeadNew.comment, + ListOptTitle) + + objHeadOld = False + if objHeadNew.comment: + objHeadOld = fileHeader(self.oldProfile, objHeadNew.comment) + # Тестирование + #print self.nameFileOld + #print objHeadNew.typeAppend + if objHeadNew.fileType: + # Создаем объект в случае параметра format в заголовке + if (objHeadNew.typeAppend == "replace" or\ + objHeadNew.typeAppend == "before" or\ + objHeadNew.typeAppend == "after") and\ + not (objHeadNew.fileType == "bin" or\ + objHeadNew.fileType == "raw"): + # Преобразовываем бинарные файлы + if flagNotUtf8New: + objTxtCoder = utfBin() + self.newProfile = objTxtCoder.encode(self.newProfile) + try: + objProfNew = eval("%s(self.newProfile)"%\ + (objHeadNew.fileType)) + except NameError: + #Создаем объект из self.newObjProt с помощью + # метаклассов + if objHeadNew.fileType in self.newObjProt: + objProfNewCl = self.createNewClass(\ + objHeadNew.fileType, + self.newObjProt[objHeadNew.fileType]) + objProfNew = objProfNewCl(self.newProfile) + else: + self.setError (\ + _("False join profile for type profile: ")\ + + objHeadNew.fileType + " : " +\ + newFile) + return False + + if "xml_" in objHeadNew.fileType: + if objProfNew.getError(): + self.setError (_("False profile: " ) + newFile) + return False + nameRootNode = oldFile.rpartition("/")[2].split(".")[0] + objProfNew.setNameBodyNode(nameRootNode) + # Объект Документ + docObj = objProfNew.docObj + # Удаление комментариев из документа + docObj.removeComment(docObj.getNodeBody()) + # Добавление необходимых переводов строк + docObj.insertBRtoBody(docObj.getNodeBody()) + # Добавление необходимых разделителей между областями + docObj.insertBeforeSepAreas(docObj.getNodeBody()) + # Пост обработка + if 'postXML' in dir(objProfNew): + objProfNew.postXML() + # Получение текстового файла из XML документа + self.newProfile = objProfNew.getConfig() + # Если не UTF-8 производим преобразование + if flagNotUtf8New: + self.newProfile = objTxtCoder.decode(self.newProfile) + # Титл для объединения + if ListOptTitle: + title = self.getTitle(objProfNew._comment, + ListOptTitle) + # Замена + if objHeadNew.typeAppend == "replace": + if "xml_" in objHeadNew.fileType: + data = self.newProfile.split("\n") + data.insert(1,title) + self.oldProfile = "\n".join(data) + else: + if objHeadNew.execStr: + self.oldProfile = objHeadNew.execStr+title+\ + self.newProfile + else: + self.oldProfile = title + self.newProfile + self.saveOldFile() + return filesApply + # Впереди + elif objHeadNew.typeAppend == "before": + if "xml_" in objHeadNew.fileType: + self.setError (\ + _("False option append=before in profile %s") %newFile) + return False + if objHeadOld and objHeadOld.body: + self.oldProfile = objHeadOld.body + if self.newProfile[-1] == "\n": + tmpProfile = self.newProfile + self.oldProfile + else: + tmpProfile = self.newProfile + "\n" + self.oldProfile + if objHeadNew.execStr: + self.oldProfile = objHeadNew.execStr + title + tmpProfile + elif objHeadOld.execStr: + self.oldProfile = objHeadOld.execStr + title + tmpProfile + else: + self.oldProfile = title + tmpProfile + + #print self.oldProfile + self.saveOldFile() + return filesApply + # Cзади + elif objHeadNew.typeAppend == "after": + if "xml_" in objHeadNew.fileType: + self.setError (\ + _("False option append=after in profile %s") %newFile) + return False + if objHeadOld and objHeadOld.body: + self.oldProfile = objHeadOld.body + if self.newProfile[-1] == "\n": + tmpProfile = self.oldProfile + self.newProfile + else: + tmpProfile = self.oldProfile + "\n" + self.newProfile + if objHeadNew.execStr: + self.oldProfile = objHeadNew.execStr + title + tmpProfile + elif objHeadOld.execStr: + self.oldProfile = objHeadOld.execStr + title + tmpProfile + else: + self.oldProfile = title + tmpProfile + self.saveOldFile() + return filesApply + # Объединение + elif objHeadNew.typeAppend == "join": + if flagNotUtf8New: + objTxtCoder = utfBin() + self.newProfile = objTxtCoder.encode(self.newProfile) + try: + objProfNew = eval("%s(self.newProfile)"%\ + (objHeadNew.fileType)) + except NameError: + #Создаем объект из self.newObjProt с помощью + # метаклассов + if objHeadNew.fileType in self.newObjProt: + objProfNewCl = self.createNewClass(\ + objHeadNew.fileType, + self.newObjProt[objHeadNew.fileType]) + objProfNew = objProfNewCl(self.newProfile) + else: + self.setError (\ + _("False join profile for type profile: ")\ + + objHeadNew.fileType + " : " +\ + newFile) + return False + if "xml_" in objHeadNew.fileType: + if objProfNew.getError(): + self.setError (_("False profile: " ) + newFile) + return False + nameRootNode = oldFile.rpartition("/")[2].split(".")[0] + objProfNew.setNameBodyNode(nameRootNode) + # Титл для объединения + if ListOptTitle: + title = self.getTitle(objProfNew._comment, + ListOptTitle) + + # В случае пустого конфигурационного файла + reNoClean = re.compile("[^\s]",re.M) + if not self.oldProfile or\ + not reNoClean.search(self.oldProfile): + self.oldProfile = "" + #if objHeadNew.execStr: + #self.oldProfile = objHeadNew.execStr + \ + #title + objProfNew.getConfig().encode("UTF-8") + #else: + #self.oldProfile = title +\ + #objProfNew.getConfig().encode("UTF-8") + #self.saveOldFile() + #return True + + objHeadOld = fileHeader(self.oldProfile, objProfNew._comment) + if objHeadOld.body: + self.oldProfile = objHeadOld.body + else: + self.oldProfile = "" + if flagNotUtf8Old: + objTxtCoder = utfBin() + self.oldProfile = objTxtCoder.encode(self.oldProfile) + if objHeadNew.fileType in self.newObjProt: + objProfOldCl = self.createNewClass(\ + objHeadNew.fileType, + self.newObjProt[objHeadNew.fileType]) + objProfOld = objProfOldCl(self.oldProfile) + else: + objProfOld = eval("%s(self.oldProfile)"%\ + (objHeadNew.fileType)) + if "xml_" in objHeadNew.fileType: + if objProfOld.getError(): + self.setError (_("False profile: " ) + oldFile) + return False + nameRootNode = oldFile.rpartition("/")[2].split(".")[0] + objProfOld.setNameBodyNode(nameRootNode) + + #print "#%s#" %(objProfOld.docObj.body.toprettyxml()) + #print "#%s#" %(objProfNew.docObj.body.toprettyxml()) + objProfOld.join(objProfNew) + #print objProfOld.doc.toprettyxml() + #print objProfNew.doc.toprettyxml() + if "xml_" in objHeadNew.fileType: + if objProfOld.getError(): + self.setError (_("False profile: " ) + newFile) + return False + data = \ + objProfOld.getConfig().split("\n") + data.insert(1,title) + self.oldProfile = "\n".join(data) + else: + if objHeadNew.execStr: + self.oldProfile = objHeadNew.execStr + title +\ + objProfOld.getConfig() + elif objHeadOld.execStr: + self.oldProfile = objHeadOld.execStr + title +\ + objProfOld.getConfig() + else: + self.oldProfile = title +\ + objProfOld.getConfig() + # Декодируем если кодировка не UTF-8 + if flagNotUtf8New or flagNotUtf8Old: + self.newProfile = objTxtCoder.decode(self.newProfile) + self.oldProfile = objTxtCoder.decode(self.oldProfile) + self.saveOldFile() + return filesApply + else: + self.setError (_("False (type append) profile: " ) +\ + objHeadNew.typeAppend) + return False + else: + self.setError (_("Type profile not found: ") + newFile) + return False + return filesApply + +class samba(objShare): + """Класс для обработки конфигурационного файла типа samba + + """ + _comment = "#" + configName = "samba" + configVersion = "0.1" + reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n",re.M) + reBody = re.compile(".+",re.M|re.S) + reComment = re.compile("\s*%s.*|\s*;.*"%(_comment)) + reSeparator = re.compile("\s*=\s*") + sepFields = "\n" + reSepFields = re.compile(sepFields) + + def __init__(self,text): + self.text = text + self.blocTextObj = blocText() + self._splitToFields = self.splitToFields + # Объект документ + self.docObj = self._textToXML() + # XML документ + self.doc = self.docObj.doc + + def postXML(self): + """Последующая постобработка XML""" + # удаляем пустые области + xmlAreas = xpath.Evaluate("child::area", self.docObj.body) + removeList = [] + for xmlArea in xmlAreas: + xmlFields = xpath.Evaluate("child::field/name", xmlArea) + if not xmlFields: + removeList.append(xmlArea) + for xmlArea in removeList: + parentNode = xmlArea.getparent() + parentNode.remove(xmlArea) + + # Для добавления перевода строки между областями если его нет + xmlAreas = xpath.Evaluate("child::area", self.docObj.body) + xmlArea = None + for xmlArea in xmlAreas: + xmlFields = xpath.Evaluate("child::field", xmlArea) + if not (xmlFields and ( + self.docObj.getTypeField(xmlFields[-1]) == "br" or + self.docObj.getTypeField(xmlFields[-1]) == "comment")): + if xmlArea.getnext() is not None: + parentNode = xmlArea.getparent() + nextNode = xmlArea.getnext() + insertBefore(parentNode, self.docObj.createField( + "br", [], "", [], False, False), nextNode) + # Добавление переводов строк между полями + if xmlFields: + for node in xmlFields: + # Добавление перевода строк в если его нет между полями + if (self.docObj.getTypeField(node) == "var" and + node.getprevious() is not None and + not (self.docObj.getTypeField( + node.getprevious()) in ("br", "comment"))): + insertBefore(xmlArea, self.docObj.createField( + "br", [], "", [], False, False), node) + + # Удаление лишних переводов строк + childNodes = self.docObj.getFieldsArea(self.docObj.body) + lenBr = 0 + removeBrNodes = [] + for node in childNodes: + if (node.tag == "field" and + self.docObj.getTypeField(node) == "br"): + lenBr += 1 + if lenBr > 2: + removeBrNodes.append(node) + else: + lenBr = 0 + # Удаление + for rmNode in removeBrNodes: + self.docObj.body.remove(rmNode) + + # Если после есть BR а за ним ничего нет, удаляем BR + if xmlArea is not None: + if (xmlArea.getnext() is not None and + self.docObj.getTypeField(xmlArea.getnext()) == "br"): + if xmlArea.getnext().getnext() is None: + parentNode = xmlArea.getnext().getparent() + parentNode.remove(xmlArea.getnext()) + + + def join(self, sambaObj): + """Объединяем конфигурации""" + if isinstance(sambaObj, samba): + self.docObj.joinDoc(sambaObj.doc) + self.postXML() + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len(nameValue) > 2: + valueList = nameValue[1:] + nameValue = [nameValue[0], "=".join(valueList)] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields, "") + field.name = name.replace(" ", "").replace("\t", "") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + + def splitCleanBloc(self, txtBloc): + """Делим блок на две части (переменные, пустые строки в конце)""" + txtLines = txtBloc.split("\n") + firstBloc = [] + nextBloc = [] + txtLines.reverse() + z = 0 + for txtLine in txtLines: + if not txtLine.strip(): + nextBloc.append(txtLine) + else: + break + z += 1 + txtLines.reverse() + firstBloc = txtLines[:-z] + nextBloc.reverse() + if nextBloc: + firstBloc.append("") + if nextBloc and "\n".join(nextBloc): + return ("\n".join(firstBloc), "\n".join(nextBloc)) + else: + return False + + def getFullAreas(self, blocs): + """Делит текст на области, (Заголовок, тело) + + Возвращает два списка: заголовки, тела + """ + headsAreas = [] + bodyAreas = [] + if not blocs: + return [] + lenBlocs = len(blocs[0]) + for i in range(lenBlocs): + txtBloc = blocs[1][i] + clean = self.splitCleanBloc(txtBloc) + if clean: + headsAreas.append(blocs[0][i]) + bodyAreas.append(clean[0]) + headsAreas.append("") + bodyAreas.append(clean[1]) + else: + headsAreas.append(blocs[0][i]) + bodyAreas.append(blocs[1][i]) + return (headsAreas, bodyAreas) + + def createTxtConfig(self, strHeader, dictVar): + """Cоздает область с заголовком + + создает текст конфигурационного файла в формате samba из + заголовка (строка) и словаря переменных + """ + if not strHeader: + return "" + outTxt = "[" + strHeader + "]\n" + for key in dictVar.keys(): + outTxt += "%s = %s\n" %(key,dictVar[key]) + return outTxt + + def _textToXML(self): + """Преобразует текст в XML""" + blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) + blocs = self.getFullAreas(blTmp) + headers = [] + startHeaders = [] + finHeaders = [] + docObj = xmlDoc() + docObj.createDoc(self.configName, self.configVersion) + rootNode = docObj.getNodeBody() + # Если пустой текст то создаем пустой документ + if not blocs: + return docObj + + for h in blocs[0]: + listfinH = h.split("]") + finH = listfinH[0] + if "[" in finH: + startHeaders.append(finH + "]") + else: + startHeaders.append(finH) + if len(listfinH) == 2: + finHeaders.append(listfinH[1]) + else: + finHeaders.append("") + headers.append(finH.replace("[","").replace("]","").strip()) + bodys = blocs[1] + + z = 0 + for h in headers: + if not bodys[z]: + z += 1 + continue + areaAction = False + if h: + if h[0] == "!": + docObj.createCaption(h[1:], [startHeaders[z],""]) + areaAction = "drop" + elif h[0] == "-": + docObj.createCaption(h[1:], [startHeaders[z],""]) + areaAction = "replace" + else: + docObj.createCaption(h, [startHeaders[z],""]) + else: + docObj.createCaption(h, [startHeaders[z],""]) + + if "\n" in blocs[0][z]: + if self.reComment.search(finHeaders[z]): + docObj.createField('comment', [finHeaders[z]]) + elif not finHeaders[z].strip() and\ + finHeaders[z].replace("\n",""): + docObj.createField('br', + [finHeaders[z].replace("\n","")]) + else: + docObj.createField('br') + fields = self._splitToFields(bodys[z]) + for f in fields: + if f.name != False and f.value!=False and f.br!=False: + # Обработка условий для samba + if f.name[0] == "!" or f.name[0] == "-" or\ + f.name[0] == "+": + qns = self.removeSymbolTerm(f.br) + xmlField = docObj.createField("var", + [qns], + f.name[1:], [f.value]) + if f.name[0] == "!": + # Удаляемое в дальнейшем поле + docObj.setActionField(xmlField, "drop") + else: + docObj.createField("var",[f.br.replace("\n","")], + f.name, [f.value]) + docObj.createField('br') + elif f.comment != False: + docObj.createField('comment', [f.comment]) + elif f.br != False: + docObj.createField('br', [f.br.replace("\n","")]) + if h.strip(): + area = docObj.createArea() + if areaAction: + docObj.setActionArea(area, areaAction) + rootNode.append(area) + else: + fieldsNodes = docObj.tmpFields.getFields() + for fieldNode in fieldsNodes: + rootNode.append(fieldNode) + docObj.clearTmpFields() + z += 1 + #print docObj.doc.toprettyxml() + return docObj + +class compiz(samba): + """Класс для обработки конфигурационного файла типа compiz + + """ + _comment = "#" + configName = "compiz" + configVersion = "0.1" + reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n",re.M) + reBody = re.compile(".+",re.M|re.S) + reComment = re.compile("\s*%s.*"%(_comment)) + reSeparator = re.compile("\s*=\s*") + sepFields = "\n" + reSepFields = re.compile(sepFields) + + def __init__(self,text): + samba.__init__(self,text) + + def join(self, compizObj): + """Объединяем конфигурации""" + if isinstance(compizObj, compiz): + self.docObj.joinDoc(compizObj.doc) + self.postXML() + +class bind(objShare): + """Класс для обработки конфигурационного файла типа bind + + """ + _comment = "//" + configName = "bind" + configVersion = "0.1" + __openArea = "{" + __closeArea = "[ \t]*\}[ \t]*;[ \t]*" + sepFields = ";" + reOpen = re.compile(__openArea) + reClose = re.compile(__closeArea) + reCloseArea = re.compile(__closeArea + "\s*\Z") + reComment = re.compile("[ \t]+%s|^%s|(?<=;)%s"%(_comment,_comment,_comment)) + reSepFields = re.compile(sepFields) + reSeparator = re.compile("[ \t]+") + + def __init__(self,text): + self.text = text + self.blocTextObj = blocText() + # Объект документ + self.docObj = self.textToXML() + # Создаем поля-массивы + self.docObj.postParserList() + # XML документ + self.doc = self.docObj.doc + + # Делим область на составные части + def findOpenClose(self, text, reOpen, reClose, reComment): + """Делит область на составные части + + начальный текстовый блок, + открывающий блок, + блок-тело, + закрывающий блок + """ + firstBloc = "" + startBloc = "" + bodyBloc = "" + endBloc = "" + textLines = text.splitlines() + findOpen = False + if textLines: + findOpen = reOpen.search(textLines[0]) + openBl = reOpen.search(text) + if findOpen and reComment.split(text)[0].strip(): + blocA = text[openBl.end():] + firstBloc = text[:openBl.start()] + startBloc = text[openBl.start():openBl.end()] + closeBl = reClose.search(blocA) + endBloc = blocA[closeBl.start():closeBl.end()] + bodyBloc = blocA[:closeBl.start()] + return (firstBloc, startBloc, bodyBloc, endBloc) + else: + return (firstBloc, startBloc, text, endBloc) + + + # Делим текст на области включая вложенные (areas массив областей) + def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea, + reComment, reSepFields): + """Делит текст на области включая вложенные + + возвращает список объектов областей (переменная areas) + """ + class area: + def __init__(self): + self.header = False + self.start = False + self.fields = [] + self.end = False + + blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose, + reComment,reSepFields) + for i in blocs: + areaA = area() + first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea, + reComment) + areaA.header = first.replace(" ","").replace("\t","") + areaA.start = first + start + areaA.end = end + + if areaA.end: + blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose, + reComment,reSepFields) + if blocsA and blocsA[0] == body: + areaA.fields.append(body) + areas.append(areaA) + else: + for ar in blocsA: + self.splitToAllArea(ar, areaA.fields, reOpen, + reClose, + reCloseArea, reComment, + reSepFields) + areas.append(areaA) + else: + areaA.fields.append(body) + areas.append(areaA) + return areas + + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len (nameValue) == 1: + field.name = "" + field.value = textLine.replace(self.sepFields,"") + field.br = textLine + fields.append(field) + field = fieldData() + + if len(nameValue) > 2: + valueList = nameValue[1:] + nameValue =[nameValue[0]," ".join(valueList).replace(\ + self.sepFields,"")] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def createCaptionTerm(self, header, start, end, docObj): + """Создание пустой области с заголовком + + при создании области проверяется первый символ заголовка + и добавляется тег action + "!" - drop + "-" - replace + """ + areaAction = False + if header: + if header[0] == "!": + docObj.createCaption(header[1:], [start, + end.replace("\n","")]) + areaAction = "drop" + elif header[0] == "-": + docObj.createCaption(header[1:], [start, + end.replace("\n","")]) + areaAction = "replace" + else: + docObj.createCaption(header, [start, + end.replace("\n","")]) + else: + docObj.createCaption(header, [start, + end.replace("\n","")]) + + areaXML = docObj.createArea() + if areaAction: + docObj.setActionArea(areaXML, areaAction) + return areaXML + + def createXML(self, areas, rootNode, docObj): + """Создаем из массивов областей XML""" + for i in areas: + if str(i.__class__.__name__) == "area": + if i.header and i.start: + areaXML = self.createCaptionTerm(i.header, i.start, + i.end.replace("\n",""), + docObj) + else: + areaXML = rootNode + for f in i.fields: + if str(f.__class__.__name__) == "area": + if f.header and f.start: + areaXMLChild = self.createCaptionTerm(f.header, + f.start, + f.end.replace("\n",""), + docObj) + + self.createXML(f.fields, areaXMLChild, docObj) + + areaXML.append(areaXMLChild) + else: + self.createXML(f.fields, areaXML, docObj) + if "\n" in f.end: + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + areaXML.append(fieldXMLBr) + else: + if not f: + continue + fields = self.splitToFields(f) + for field in fields: + if field.name != False: + fieldXML = self.createFieldTerm(field.name, + field.value, + field.br, docObj) + areaXML.append(fieldXML) + if field.br[-1] == "\n": + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + areaXML.append(fieldXMLBr) + elif field.comment != False: + fieldXML = docObj.createField("comment", + [field.comment], + "", [], + False, False) + areaXML.append(fieldXML) + elif field.br != False: + brText = field.br.replace("\n","") + if brText: + fieldXML = docObj.createField('br', + [brText], + "", [], + False, False) + else: + fieldXML = docObj.createField('br', + [], + "", [], + False, False) + areaXML.append(fieldXML) + + if i.header and i.start: + rootNode.append(areaXML) + if "\n" in i.end: + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + rootNode.append(fieldXMLBr) + + else: + fields = self.splitToFields(i) + for field in fields: + if field.name != False: + fieldXML = self.createFieldTerm(field.name, + field.value, + field.br, docObj) + rootNode.append(fieldXML) + if field.br[-1] == "\n": + fieldXMLBr = docObj.createField("br",[],"", [], + False, False) + rootNode.append(fieldXMLBr) + elif field.comment != False: + fieldXML = docObj.createField("comment", + [field.comment], + "", [], + False, False) + rootNode.append(fieldXML) + elif field.br != False: + brText = field.br.replace("\n","") + if brText: + fieldXML = docObj.createField('br', [brText],"",[], + False, False) + else: + fieldXML = docObj.createField('br', [], "", [], + False, False) + rootNode.append(fieldXML) + #rootNode.append(areaXML) + + def textToXML(self): + """Преобразуем текст в XML""" + areas = [] + if self.text.strip(): + self.splitToAllArea(self.text, areas, self.reOpen, self.reClose, + self.reCloseArea,self.reComment,self.reSepFields) + docObj = xmlDoc() + # Создание объекта документ c пустым разделителем между полями + docObj.createDoc(self.configName, self.configVersion) + if not areas: + return docObj + self.createXML(areas, docObj.getNodeBody(), docObj) + return docObj + + + def join(self, bindObj): + """Объединяем конфигурации""" + if isinstance(bindObj, bind): + self.docObj.joinDoc(bindObj.doc) + +class apache(bind): + """Класс для обработки конфигурационного файла типа apache + + """ + _comment = "#" + configName = "apache" + configVersion = "0.1" + __headerArea = "[^\<\> \t]+[ \t]+[^\<\> \t]+" + __openArea = "[ \t]*\<%s\>"%(__headerArea) + __closeArea = "[ \t]*\<\/[^\<\>]+\>" + sepFields = "\n" + reOpen = re.compile(__openArea) + reClose = re.compile(__closeArea) + reCloseArea = re.compile(__closeArea + "\s*\Z") + reComment = re.compile("[ \t]*%s"%(_comment)) + reSepFields = re.compile(sepFields) + reSeparator = re.compile("[ \t]+") + reHeader = re.compile(__headerArea) + + def __init__(self,text): + self.text = text + self.blocTextObj = blocText() + # Объект документ + self.docObj = self.textToXML() + # Создаем поля-массивы + self.docObj.postParserList() + # Создаем поля разделенные массивы + self.docObj.postParserListSeplist(self.docObj.body) + # XML документ + self.doc = self.docObj.doc + + def postXML(self): + """Последующая постобработка XML""" + # Для добавления перевода строки перед закрывающим тегом + # конфигурационного файла + xmlFields = xpath.Evaluate("child::fields", self.docObj.body) + if not (xmlFields and\ + self.docObj.getTypeField(xmlFields[-1]) == "br"): + self.docObj.body.append(self.docObj.createField("br", + [],"",[], + False,False)) + xmlAreas = xpath.Evaluate("child::area", self.docObj.body) + for xmlArea in xmlAreas: + xmlFields = xpath.Evaluate("child::field", xmlArea) + if not (xmlFields and\ + self.docObj.getTypeField(xmlFields[-1]) == "br"): + xmlArea.append(self.docObj.createField("br", + [],"",[], + False,False)) + + def join(self, apacheObj): + """Объединяем конфигурации""" + if isinstance(apacheObj, apache): + #print self.docObj.doc.toprettyxml() + self.docObj.joinDoc(apacheObj.doc) + self.postXML() + + # Делим область на составные части + def findOpenClose(self, text, reOpen, reClose, reComment, reHeader): + """Делит область на составные части + + начальный текстовый блок, + открывающий блок, + блок-тело, + закрывающий блок + """ + firstBloc = "" + startBloc = "" + bodyBloc = "" + endBloc = "" + textLines = text.splitlines() + findOpen = False + if textLines: + findOpen = reOpen.search(textLines[0]) + openBl = reOpen.search(text) + if findOpen and reComment.split(text)[0].strip(): + blocA = text[openBl.end():] + firstBloc = "" + startBloc = text[openBl.start():openBl.end()] + headBl = reHeader.search(startBloc) + if headBl: + firstBloc = headBl.group(0) + closeBl = reClose.search(blocA) + endBloc = blocA[closeBl.start():closeBl.end()] + bodyBloc = blocA[:closeBl.start()] + return (firstBloc, startBloc, bodyBloc, endBloc) + else: + return (firstBloc, startBloc, text, endBloc) + + # Делим текст на области включая вложенные (areas массив областей) + def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea, + reComment, reSepFields, reHeader): + """Делит текст на области включая вложенные + + возвращает список объектов областей (переменная areas) + """ + class area: + def __init__(self): + self.header = False + self.start = False + self.fields = [] + self.end = False + + blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose, + reComment,reSepFields) + for i in blocs: + areaA = area() + first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea, + reComment, reHeader) + areaA.header = first.replace(" ","").replace("\t","") + areaA.start = start + areaA.end = end + + if areaA.end: + blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose, + reComment,reSepFields) + if blocsA and blocsA[0] == body: + areaA.fields.append(body) + areas.append(areaA) + else: + for ar in blocsA: + self.splitToAllArea(ar, areaA.fields, reOpen, + reClose, + reCloseArea, reComment, + reSepFields, reHeader) + areas.append(areaA) + else: + areaA.fields.append(body) + areas.append(areaA) + + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + #print "#"+brBloc[z]+"#" + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len (nameValue) == 1: + field.name = "" + field.value = textLine.replace(self.sepFields,"") + field.br = textLine + fields.append(field) + field = fieldData() + + if len(nameValue) == 3: + valueList = nameValue[2:] + nameValue =["".join(nameValue[:2])," ".join(valueList)] + + if len(nameValue) > 3: + valueList = nameValue[1:] + nameValue =[nameValue[0]," ".join(valueList).replace(\ + self.sepFields,"")] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + + def textToXML(self): + """Преобразуем тект в XML""" + areas = [] + self.splitToAllArea(self.text, areas, self.reOpen, self.reClose, + self.reCloseArea,self.reComment,self.reSepFields, + self.reHeader) + docObj = xmlDoc() + + # Создание объекта документ c пустым разделителем между полями + docObj.createDoc(self.configName, self.configVersion) + if not areas: + return docObj + self.createXML(areas, docObj.getNodeBody(), docObj) + return docObj + +class postfix(apache): + """Класс для обработки конфигурационного файла типа postfix + + """ + _comment = "#" + configName = "postfix" + configVersion = "0.1" + sepFields = "\n" + reComment = re.compile("[ \t]*%s"%(_comment)) + reSepFields = re.compile(sepFields) + # разделитель названия и значения переменной + reSeparator = re.compile("\s*=\s*") + def __init__(self,text): + self.text = text + # Объект документ + self.docObj = self.textToXML() + # Создаем поля разделенные массивы + self.docObj.postParserListSeplist(self.docObj.body) + # XML документ + self.doc = self.docObj.doc + + def join(self, postfixObj): + """Объединяем конфигурации""" + if isinstance(postfixObj, postfix): + self.docObj.joinDoc(postfixObj.doc) + + def textToXML(self): + """Преобразуем текст в XML""" + class area: + def __init__(self): + self.header = False + self.start = False + self.fields = [] + self.end = False + areas = [] + oneArea = area() + oneArea.header = "" + oneArea.start = "" + oneArea.fields = [self.text] + oneArea.end = "" + areas.append(oneArea) + docObj = xmlDoc() + # Создание объекта документ c пустым разделителем между полями + docObj.createDoc(self.configName, self.configVersion) + if not areas: + return docObj + self.createXML(areas, docObj.getNodeBody(), docObj) + return docObj + + + def setDataField(self, txtLines, endtxtLines): + """Cоздаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + #print "#"+brBloc[z]+"#" + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len (nameValue) == 1: + field.name = "" + field.value = textLine.replace(self.sepFields,"") + field.br = textLine + fields.append(field) + field = fieldData() + + if len(nameValue) > 2: + valueList = nameValue[1:] + nameValue =[nameValue[0],"=".join(valueList).replace(\ + self.sepFields,"")] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + +class ldap(samba): + """Класс для обработки конфигурационного файла типа ldap + + """ + _comment = "#" + configName = "ldap" + configVersion = "0.1" + # Регулярное выражение для заголовка области + reHeader = re.compile("^[\t ]*(access|syncrepl)[^\n]+\n?") + # Регулярное выражения для области + reArea = re.compile("([\t ]*(access|syncrepl)[^\n]+\ +\n([\t ]+[^\n]+\n?)+)",re.M|re.S) + reComment = re.compile("\s*%s.*"%(_comment)) + # разделитель между переменной и значением переменной + reSeparator = re.compile("\s+|\s*=\s*") + # разделитель полей + sepFields = "\n" + # регулярное выражение для разделителя полей + reSepFields = re.compile(sepFields) + + def __init__(self,text): + self.text = text + self.blocTextObj = blocText() + self._splitToFields = self.splitToFields + # Объект документ + self.docObj = self._textToXML() + # Создаем поля-массивы + self.docObj.postParserList() + # Создаем поля разделенные массивы + self.docObj.postParserListSeplist(self.docObj.body) + # XML документ + self.doc = self.docObj.doc + + def join(self, ldapObj): + """Объединяем конфигурации""" + if isinstance(ldapObj, ldap): + self.docObj.joinDoc(ldapObj.doc) + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len(nameValue) > 2: + valueList = nameValue[2:] + nameValue =[nameValue[0]+nameValue[1]," ".join(valueList)] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def _textToXML(self): + """Преобразует текст в XML""" + blTmp = self.blocTextObj.findArea(self.text,self.reHeader,self.reArea) + blocs = self.getFullAreas(blTmp) + headers = [] + startHeaders = [] + finHeaders = [] + docObj = xmlDoc() + docObj.createDoc(self.configName, self.configVersion) + rootNode = docObj.getNodeBody() + # Если пустой текст то создаем пустой документ + if not blocs: + return docObj + + for h in blocs[0]: + headers.append(h.rstrip()) + bodys = blocs[1] + + z = 0 + for h in headers: + if not bodys[z]: + z += 1 + continue + areaAction = False + if h: + if h[0] == "!": + header = self.removeSymbolTerm(h.strip()) + headerQuote = self.removeSymbolTerm(h) + docObj.createCaption(header,[headerQuote,""]) + areaAction = "drop" + elif h[0] == "-": + header = self.removeSymbolTerm(h.strip()) + headerQuote = self.removeSymbolTerm(h) + docObj.createCaption(header,[headerQuote,""]) + areaAction = "replace" + else: + docObj.createCaption(h.strip(), [h.rstrip(),""]) + else: + docObj.createCaption(h.strip(), [h.rstrip(),""]) + + if "\n" in blocs[0][z]: + resHead = self.reComment.search(h) + if resHead: + docObj.createField('comment', + blocs[0][z][resHead.start():]) + else: + docObj.createField('br') + + fields = self._splitToFields(bodys[z]) + for f in fields: + if f.name != False and f.value!=False and f.br!=False: + # Обработка условий для samba + if f.name[0] == "!" or f.name[0] == "-" or\ + f.name[0] == "+": + qns = self.removeSymbolTerm(f.br) + xmlField = docObj.createField("var", + [qns], + f.name[1:], [f.value]) + if f.name[0] == "!": + # Удаляемое в дальнейшем поле + docObj.setActionField(xmlField, "drop") + elif f.name[0] == "+": + # Добавляем уникальное поле + xmlField.set("type", "seplist") + docObj.setActionField(xmlField, "join") + else: + docObj.createField("var",[f.br.replace("\n","")], + f.name, [f.value]) + docObj.createField('br') + elif f.comment != False: + docObj.createField('comment', [f.comment]) + elif f.br != False: + docObj.createField('br', [f.br.replace("\n","")]) + if h.strip(): + area = docObj.createArea() + if areaAction: + docObj.setActionArea(area, areaAction) + rootNode.append(area) + else: + fieldsNodes = docObj.tmpFields.getFields() + for fieldNode in fieldsNodes: + rootNode.append(fieldNode) + docObj.clearTmpFields() + z += 1 + #print docObj.doc.toprettyxml() + return docObj + + def getConfig(self): + """Выдает конфигурационный файл""" + listConfigTxt = [] + childNodes = list(self.docObj.getNodeBody()) + for node in childNodes: + if node.tag == "field": + listConfigTxt.append(self.docObj.getQuoteField(node)) + elif node.tag == "area": + self.docObj.xmlToText([node], listConfigTxt) + tmp = "".join(listConfigTxt) + return "\n".join(x for x in tmp.split("\n") if x.strip()) + +class dovecot(bind): + """Класс для обработки конфигурационного файла типа dovecot + + """ + _comment = "#" + configName = "dovecot" + configVersion = "0.1" + __openArea = "{" + __closeArea = "[ \t]*\}[ \t]*" + sepFields = "\n" + reOpen = re.compile(__openArea) + reClose = re.compile(__closeArea) + reCloseArea = re.compile(__closeArea + "\s*\Z") + reComment = re.compile("[ \t]*%s" %(_comment)) + reSepFields = re.compile(sepFields) + # разделитель названия и значения переменной + reSeparator = re.compile("\s*=\s*") + + def __init__(self, text): + bind.__init__(self,text) + + def postXML(self, xmlArea=None): + """Последующая постобработка XML""" + # Добавляем перевод строки если его нет в конец области + if xmlArea is None: + xmlArea = self.docObj.body + xmlFields = xpath.Evaluate("child::field", xmlArea) + if xmlFields and not (\ + self.docObj.getTypeField(xmlFields[-1]) == "br" or\ + self.docObj.getTypeField(xmlFields[-1]) == "comment"): + xmlArea.append(self.docObj.createField("br", + [],"",[], + False,False)) + xmlAreas = xpath.Evaluate("child::area", xmlArea) + for area in xmlAreas: + self.postXML(area) + + def join(self, dovecotObj): + """Объединяем конфигурации""" + if isinstance(dovecotObj, dovecot): + #print self.docObj.doc.toprettyxml() + self.docObj.joinDoc(dovecotObj.doc) + # Для добавления перевода строки перед закрывающим тегом + # конфигурационного файла + self.postXML() + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len (nameValue) == 1 and \ + ( nameValue[0].startswith("!include") or + nameValue[0][1:].startswith("!include")): + field.name = textLine.replace(self.sepFields,"") + field.value = "" + field.br = textLine + fields.append(field) + field = fieldData() + elif len (nameValue) == 1: + field.name = "" + field.value = textLine.replace(self.sepFields,"") + field.br = textLine + fields.append(field) + field = fieldData() + + elif len(nameValue) > 2: + valueList = nameValue[1:] + nameValue =[nameValue[0]," ".join(valueList).replace(\ + self.sepFields,"")] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def createFieldTerm(self, name, value, quote, docObj): + """Создание поля переменная - значение + + при создании поля проверяется первый символ названия переменной + и добавляется тег action + "!" - drop удаляет + "+" - join добавляет + "-" - replace заменяет + """ + fieldAction = False + if name: + if name.startswith("!include") or name[1:].startswith("!include"): + prefix = "!" + name = re.sub(r"(include)\s*(\S)",r"\1 \2", name[1:]) + else: + prefix = "" + if name[0] == "!" or name[0] == "-" or name[0] == "+": + qnt = self.removeSymbolTerm(quote) + fieldXML = docObj.createField("var",[qnt], + prefix+name[1:], [value], + False, False) + if name[0] == "!": + fieldAction = "drop" + elif name[0] == "+": + fieldXML.set("type", "seplist") + fieldAction = "join" + else: + fieldXML = docObj.createField("var", + [quote.replace("\n","")], + prefix+name, [value], + False, False) + else: + fieldXML = docObj.createField("var", + [quote.replace("\n","")], + name, [value], + False, False) + if fieldAction: + docObj.setActionField(fieldXML, fieldAction) + return fieldXML + +class procmail(objShare): + """Класс для обработки конфигурационного файла типа procmail + + """ + _comment = "#" + configName = "procmail" + configVersion = "0.1" + sepFields = "\n" + reComment = re.compile("[ \t]*%s" %(_comment)) + reSepFields = re.compile(sepFields) + # разделитель названия и значения переменной + reSeparator = re.compile("=") + def __init__(self, text): + self.text = text + self.docObj = self.textToXML() + self.doc = self.docObj.doc + + def postXML(self): + """Последующая постобработка XML""" + xmlFields = xpath.Evaluate("child::field", self.docObj.body) + # Добавление переводов строк между полями + for node in xmlFields: + # Добавление перевода строк в если его нет между полями + if (self.docObj.getTypeField(node) == "var" and + node.getprevious() is not None and + (self.docObj.getTypeField(node.getprevious()) not in + ("br", "comment"))): + insertBefore(self.docObj.body, self.docObj.createField( + "br", [], "", [], False, False), node) + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def textToXML(self): + docObj = xmlDoc() + docObj.createDoc(self.configName, self.configVersion) + if self.text: + nodeBody = docObj.getNodeBody() + fields = self.splitToFields(self.text) + for field in fields: + if field.name != False: + fieldXML = self.createFieldTerm(field.name, + field.value, + field.br, docObj) + nodeBody.append(fieldXML) + if field.br[-1] == "\n": + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + nodeBody.append(fieldXMLBr) + elif field.comment != False: + fieldXML = docObj.createField("comment", + [field.comment], + "", [], + False, False) + nodeBody.append(fieldXML) + elif field.br != False: + brText = field.br.replace("\n","") + if brText: + fieldXML = docObj.createField('br', + [brText], + "", [], + False, False) + else: + fieldXML = docObj.createField('br', + [], + "", [], + False, False) + nodeBody.append(fieldXML) + return docObj + + def join(self, procmailObj): + """Объединяем конфигурации""" + if isinstance(procmailObj, procmail): + #print self.docObj.doc.toprettyxml() + self.docObj.joinDoc(procmailObj.doc) + self.postXML() + +class kde(samba): + """Класс для обработки конфигурационного файла типа kde + + """ + _comment = "#" + configName = "kde" + configVersion = "0.1" + reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n?",re.M) + reBody = re.compile(".+",re.M|re.S) + reComment = re.compile("^\s*%s.*"%(_comment)) + reSeparator = re.compile("=") + sepFields = "\n" + reSepFields = re.compile(sepFields) + + def __init__(self,text): + samba.__init__(self,text) + + + def _textToXML(self): + """Преобразует текст в XML""" + blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) + blocs = self.getFullAreas(blTmp) + headers = [] + startHeaders = [] + finHeaders = [] + docObj = xmlDoc() + docObj.createDoc(self.configName, self.configVersion) + rootNode = docObj.getNodeBody() + # Если пустой текст то создаем пустой документ + if not blocs: + return docObj + + for h in blocs[0]: + reH = re.compile("]\s*$") + #listfinH = h.split("]") + listfinH = reH.split(h) + finH = listfinH[0] + if "[" in finH: + startHeaders.append(finH + "]") + else: + startHeaders.append(finH) + if len(listfinH) == 2: + finHeaders.append(listfinH[1]) + else: + finHeaders.append("") + head=finH.replace("][",".").replace("[","").replace("]","").strip() + headers.append(head) + bodys = blocs[1] + + z = 0 + for h in headers: + if not bodys[z]: + z += 1 + continue + areaAction = False + if h: + if h[0] == "!": + docObj.createCaption(h[1:], [startHeaders[z],""]) + areaAction = "drop" + elif h[0] == "-": + docObj.createCaption(h[1:], [startHeaders[z],""]) + areaAction = "replace" + else: + docObj.createCaption(h, [startHeaders[z],""]) + else: + docObj.createCaption(h, [startHeaders[z],""]) + + if "\n" in blocs[0][z]: + if self.reComment.search(finHeaders[z]): + docObj.createField('comment', [finHeaders[z]]) + elif not finHeaders[z].strip() and\ + finHeaders[z].replace("\n",""): + docObj.createField('br', + [finHeaders[z].replace("\n","")]) + else: + docObj.createField('br') + fields = self._splitToFields(bodys[z]) + for f in fields: + if f.name != False and f.value!=False and f.br!=False: + # Обработка условий для samba + if f.name[0] == "!" or f.name[0] == "-" or\ + f.name[0] == "+": + qns = self.removeSymbolTerm(f.br) + xmlField = docObj.createField("var", + [qns], + f.name[1:], [f.value]) + if f.name[0] == "!": + # Удаляемое в дальнейшем поле + docObj.setActionField(xmlField, "drop") + else: + docObj.createField("var",[f.br.replace("\n","")], + f.name, [f.value]) + docObj.createField('br') + elif f.comment != False: + docObj.createField('comment', [f.comment]) + elif f.br != False: + docObj.createField('br', [f.br.replace("\n","")]) + if h.strip(): + area = docObj.createArea() + if areaAction: + docObj.setActionArea(area, areaAction) + rootNode.append(area) + else: + fieldsNodes = docObj.tmpFields.getFields() + for fieldNode in fieldsNodes: + rootNode.append(fieldNode) + docObj.clearTmpFields() + z += 1 + #print docObj.doc.toprettyxml() + return docObj + + def join(self, kdeObj): + """Объединяем конфигурации""" + if isinstance(kdeObj, kde): + self.docObj.joinDoc(kdeObj.doc) + self.postXML() + +class PlasmaArea(): + def __init__(self): + self.header = False + self.start = False + self.fields = [] + self.end = "" + +class xmlDocPlasma: + """Класс для замены метода joinArea в xmlDoc для plasma""" + # заменяемый метод для xmlDoc + def joinArea(self, baseNode, xmlNewArea): + """Объединяет область c областью Body (xmlNewArea c baseNode)""" + def appendArea(baseNode, xmlNewArea): + fieldsRemove = xpath.Evaluate(\ + "descendant::field[child::action='drop']", xmlNewArea) + for rmNode in fieldsRemove: + parentNode = rmNode.getparent() + parentNode.remove(rmNode) + captionAreasRemove = xpath.Evaluate(\ + "descendant::area/child::caption[child::action='drop']", + xmlNewArea) + for rmNodeCapt in captionAreasRemove: + rmNode = rmNodeCapt.getparent() + parentNode = rmNode.getparent() + parentNode.remove(rmNode) + self.setActionArea(xmlNewArea, "append") + # Добавляем разделитель областей во вложенные области + areaNodes = xpath.Evaluate('descendant::area',xmlNewArea) + for areaNode in areaNodes: + self.setActionArea(areaNode,"append") + parentNode = areaNode.getparent() + insertBefore(parentNode, deepcopy(self.sepAreas), + areaNode) + baseNode.append(xmlNewArea) + # Добавляем разделитель областей + insertBefore(baseNode, deepcopy(self.sepAreas), xmlNewArea) + + nodesNames = xpath.Evaluate('child::area/caption/name',baseNode) + nodesNewArea = xpath.Evaluate('child::caption/name',xmlNewArea) + if not nodesNames: + # Добавляем область + if nodesNewArea: + newAreaAction = self.getActionArea(xmlNewArea) + if not (newAreaAction == "drop"): + appendArea(baseNode, xmlNewArea) + return True + if not nodesNames or not nodesNewArea: + return False + nameArea = "" + if firstChild(nodesNewArea[0]) is not None: + nameArea = firstChild(nodesNewArea[0]).text.strip() + flagFindArea = False + baseNodes = [] + newAreaAction = None + for oName in nodesNames: + newAreaAction = self.getActionArea(xmlNewArea) + oArea = oName.getparent().getparent() + oNameTxt = "" + if firstChild(oName) is not None: + oNameTxt = firstChild(oName).text + if nameArea == oNameTxt: + flagFindArea = True + # При использовании удаления + if newAreaAction == "drop": + prevNode = oName.getparent().getparent().getprevious() + removePrevNodes = [] + while prevNode is not None\ + and self.getTypeField(prevNode) == "br": + removePrevNodes.append(prevNode) + prevNode = prevNode.getprevious() + for removeNode in removePrevNodes: + baseNode.remove(removeNode) + baseNode.remove(oName.getparent().getparent()) + continue + elif newAreaAction == "replace": + oldAreaNode = oName.getparent().getparent() + newAreaCaption = xpath.Evaluate('child::caption', + xmlNewArea)[0] + oldAreaCaption = xpath.Evaluate('child::caption', + oldAreaNode)[0] + if newAreaCaption and oldAreaCaption: + xmlNewArea.replace(newAreaCaption, oldAreaCaption) + self.setActionArea(xmlNewArea,"replace") + baseNode.replace(oldAreaNode, xmlNewArea) + continue + baseNodes.append(oName.getparent().getparent()) + + # Заменяем QUOTE + oldAreaNode = oName.getparent().getparent() + oldAreaQuote = xpath.Evaluate('child::caption/quote', + oldAreaNode)[0] + if oldAreaQuote and\ + firstChild(oldAreaQuote) is None: + newAreaQuote = xpath.Evaluate('child::caption/quote', + xmlNewArea)[0] + oldAreaCaption = xpath.Evaluate('child::caption', + oldAreaNode)[0] + if newAreaQuote and oldAreaCaption: + oldAreaCaption.replace(oldAreaQuote, newAreaQuote) + + newFields = xpath.Evaluate('child::field',xmlNewArea) + + joinNewFields = xpath.Evaluate(\ + "child::field[child::action='join']" + ,xmlNewArea) + self.addNewFielsOldArea(newFields, joinNewFields, oArea) + + + if not flagFindArea: + # Добавляем область + if not (newAreaAction == "drop"): + appendArea(baseNode, xmlNewArea) + else: + tmpXmlNewAreas = xpath.Evaluate('child::area',xmlNewArea) + for na in tmpXmlNewAreas: + for bn in baseNodes: + self.joinArea(bn, na) + return True + +class plasma(samba): + """Класс для обработки конфигурационного файла типа kde + + """ + _comment = "#" + configName = "plasma" + configVersion = "0.1" + reHeader = re.compile("^[\t ]*\[[^\[\]]+\].*\n?",re.M) + reBody = re.compile(".+",re.M|re.S) + reComment = re.compile("^\s*%s.*"%(_comment)) + reSeparator = re.compile("=") + sepFields = "\n" + reSepFields = re.compile(sepFields) + + def __init__(self,text): + samba.__init__(self,text) + + # Делим текст на области включая вложенные (areas массив областей) + def splitToAllArea(self, text, areas): + """Делит текст на области включая вложенные + + возвращает список объектов областей (переменная areas) + """ + area = PlasmaArea + + + def findPathArea(listPath, areaF): + """Ищет путь в области + + areaF - объект area + listPath - cписок названий областей + """ + ret = False + if not listPath: + return ret + flagList = False + if isinstance(areaF, list): + fields = areaF + flagList = True + else: + fields = areaF.fields + if areaF.header == listPath[0]: + ret = areaF + else: + return ret + for i in fields: + if isinstance(i, PlasmaArea): + add = False + if not flagList: + add = listPath.pop(0) + if not listPath: + break + ret = False + if i.header == listPath[0]: + ret = findPathArea(listPath, i) + break + else: + if add: + listPath.insert(0,add) + if ret == areaF and len(listPath)>1: + ret = False + return ret + + + blTmp = self.blocTextObj.findBloc(self.text,self.reHeader,self.reBody) + blocs = self.getFullAreas(blTmp) + reH = re.compile("\[([^\[\]]+)\]") + # Список имен блоков + namesBlockList = [] + # Временные поля + fieldsTmp = [] + # Добавляем заголовки + z = 0 + for h in blocs[0]: + if not h: + if blocs[1][z] == "": + fieldsTmp.append("") + #fieldsTmp.append("\n") + else: + fieldsTmp.append(blocs[1][z]) + #print '"' + blocs[1][z] + '"' + z += 1 + continue + #print '"' + blocs[1][z] + '"' + z += 1 + slpNamesBlock = reH.split(h) + # Отступ слева для заголовка + indentionLeft = slpNamesBlock[0] + namesBlock = [x for x in slpNamesBlock if x.strip()] + #namesBlock = map(lambda x: self.removeSymbolTerm(x), namesBlock) + findArea = findPathArea(copy.copy(namesBlock), areas) + namesBlockList.append(namesBlock) + if findArea: + if len(namesBlock) > 1: + namesBlockView = [self.removeSymbolTerm(x) for x in namesBlock] + else: + namesBlockView = namesBlock + findArea.start = indentionLeft + "[" + \ + "][".join(namesBlockView) + "]" + else: + i = 0 + lenNamesBlock = len(namesBlock) + namesBlockTmp = [] + for nameB in namesBlock: + namesBlockTmp.append(nameB) + findArea = findPathArea(copy.copy(namesBlockTmp), areas) + i += 1 + if not findArea: + areaNew = area() + areaNew.header = nameB + if lenNamesBlock == i: + if len(namesBlock) > 1: + namesBlockView = [self.removeSymbolTerm(x) for x in namesBlock] + else: + namesBlockView = namesBlock + areaNew.start = indentionLeft + "[" + \ + "][".join(namesBlockView) + "]" + else: + areaNew.start = "" + areaNew.end = "" + if i == 1: + if lenNamesBlock == i: + areas += fieldsTmp + areas.append(areaNew) + findAreaPrev = areas[-1] + else: + if (lenNamesBlock == i and + isinstance(findAreaPrev, area)): + findAreaPrev.fields += fieldsTmp + findAreaPrev.fields.append(areaNew) + findAreaPrev = findAreaPrev.fields[-1] + else: + findAreaPrev = findArea + fieldsTmp = [] + i = 0 + delt = 0 + # Добавляем тела + for body in blocs[1]: + #print "#" + body + "#" + #print + if not blocs[0][i]: + i += 1 + delt +=1 + continue + ## В случае последнего комментария не добавляем перевод строки + #if self.reComment.search(body.splitlines()[-1]): + body = "\n" + body + + namesBlock = namesBlockList[i-delt] + findArea = findPathArea(copy.copy(namesBlock), areas) + if isinstance(findArea, area): + #if findArea.fields: + #if type(findArea.fields[0]) == types.StringType: + #findArea.fields.pop(0) + findArea.fields.insert(0, body) + i += 1 + + #eee = 1 + #def prAreas(ar, eee): + #for a in ar: + #if type(a) == types.StringType: + #print 'field', a + #else: + #print "--------------------" + #print "HEADER =", a.header + #print "START =", a.start + #print "FIELDS =", a.fields + #print "LEVEL", eee + #if type(a) != types.StringType: + #if a.fields: + #eee += 1 + #prAreas(a.fields, eee) + + #prAreas(areas, eee) + return areas + + def createCaptionTerm(self, header, start, end, docObj): + """Создание пустой области с заголовком + + при создании области проверяется первый символ заголовка + и добавляется тег action + "!" - drop + "-" - replace + """ + areaAction = False + if header: + if header[0] == "!": + docObj.createCaption(header[1:], [start, + end.replace("\n","")]) + areaAction = "drop" + elif header[0] == "-": + docObj.createCaption(header[1:], [start, + end.replace("\n","")]) + areaAction = "replace" + else: + docObj.createCaption(header, [start, + end.replace("\n","")]) + else: + docObj.createCaption(header, [start, + end.replace("\n","")]) + + areaXML = docObj.createArea() + if areaAction: + docObj.setActionArea(areaXML, areaAction) + return areaXML + + def createXML(self, areas, rootNode, docObj): + """Создаем из массивов областей XML""" + for i in areas: + if isinstance(i, PlasmaArea): + if i.header: + areaXML = self.createCaptionTerm(i.header, i.start, + i.end.replace("\n",""), + docObj) + for f in i.fields: + if isinstance(f, PlasmaArea): + if f.header: + areaXMLChild = self.createCaptionTerm(f.header, + f.start, + f.end.replace("\n",""), + docObj) + + self.createXML(f.fields, areaXMLChild, docObj) + + areaXML.append(areaXMLChild) + else: + self.createXML(f.fields, areaXML, docObj) + if "\n" in f.end: + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + areaXML.append(fieldXMLBr) + else: + if not f: + continue + fields = self.splitToFields(f) + for field in fields: + if field.name != False: + fieldXML = self.createFieldTerm(field.name, + field.value, + field.br, docObj) + areaXML.append(fieldXML) + if field.br[-1] == "\n": + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + areaXML.append(fieldXMLBr) + elif field.comment != False: + fieldXML = docObj.createField("comment", + [field.comment], + "", [], + False, False) + areaXML.append(fieldXML) + elif field.br != False: + brText = field.br.replace("\n","") + if brText: + fieldXML = docObj.createField('br', + [brText], + "", [], + False, False) + else: + fieldXML = docObj.createField('br', + [], + "", [], + False, False) + if areaXML: + areaXML.append(fieldXML) + + if i.header: + rootNode.append(areaXML) + if "\n" in i.end: + fieldXMLBr = docObj.createField("br",[], + "",[], + False, False) + rootNode.append(fieldXMLBr) + + else: + if not i: + continue + fields = self.splitToFields(i) + for field in fields: + if field.name != False: + fieldXML = self.createFieldTerm(field.name, + field.value, + field.br, docObj) + rootNode.append(fieldXML) + if field.br[-1] == "\n": + fieldXMLBr = docObj.createField("br",[],"", [], + False, False) + rootNode.append(fieldXMLBr) + elif field.comment != False: + fieldXML = docObj.createField("comment", + [field.comment], + "", [], + False, False) + rootNode.append(fieldXML) + elif field.br != False: + brText = field.br.replace("\n","") + if brText: + fieldXML = docObj.createField('br', [brText],"",[], + False, False) + else: + fieldXML = docObj.createField('br', [], "", [], + False, False) + rootNode.append(fieldXML) + #rootNode.append(areaXML) + + + def createTxtConfig(self, strHeader, dictVar): + """Cоздает область с заголовком + + создает текст конфигурационного файла в формате samba из + заголовка (строка) и словаря переменных + """ + if not strHeader: + return "" + if type(strHeader) in (tuple, list): + outTxt = "".join("["+x+"]" for x in strHeader) + if not outTxt: + return "" + outTxt += "\n" + else: + outTxt = "[" + strHeader + "]\n" + for key in dictVar.keys(): + outTxt += "%s=%s\n" %(key,dictVar[key]) + return outTxt + + def _textToXML(self): + """Преобразуем текст в XML""" + areas = [] + if self.text.strip(): + self.splitToAllArea(self.text, areas) + # docObj = xmlDoc() + # Создаем новый класс xmlDoc с измененным методом joinArea + # Создаем экземпляр нового класса + docObj = xmlDocPlasma() + # Создание объекта документ c пустым разделителем между полями + docObj.createDoc(self.configName, self.configVersion) + if not areas: + return docObj + self.createXML(areas, docObj.getNodeBody(), docObj) + return docObj + + def postXML(self): + """Последующая постобработка XML""" + # Для добавления перевода строки между областями если его нет + def getQuotesArea(xmlArea): + quotes = [] + xmlQuotes = xpath.Evaluate('child::caption/quote', xmlArea) + for node in xmlQuotes: + if firstChild(node) is not None: + quotes.append(firstChild(node).text) + if len(quotes) == 0: + quotes.append("") + quotes.append("") + elif len(quotes) == 1: + quotes.append("") + return quotes + + xmlAreas = xpath.Evaluate("descendant::area", self.docObj.body) + for xmlArea in xmlAreas: + # Перед пустой областью и после нее удаляем переводы строк + if getQuotesArea(xmlArea) == ["", ""]: + if (xmlArea.getprevious() is not None and + self.docObj.getTypeField( + xmlArea.getprevious()) == "br"): + parentNode = xmlArea.getprevious().getparent() + prev_prev_sbl = xmlArea.getprevious().getprevious() + if (prev_prev_sbl and + self.docObj.getTypeField( + prev_prev_sbl) == "br"): + parentNode.remove( + xmlArea.getprevious().getprevious()) + parentNode.remove(xmlArea.getprevious()) + if (xmlArea.getnext() is not None and + self.docObj.getTypeField( + xmlArea.getnext()) == "br"): + parentNode = xmlArea.getnext().getparent() + next_next_sbl = xmlArea.getnext().getnext() + if (next_next_sbl is not None and + self.docObj.getTypeField( + next_next_sbl) == "br"): + parentNode.remove(xmlArea.getnext().getnext()) + parentNode.remove(xmlArea.getnext()) + continue + + # Собираем поля в кучку + xmlChildAreas = xpath.Evaluate("child::area", xmlArea) + if xmlChildAreas: + childNodes = self.docObj.getFieldsArea(xmlArea) + firstChildArea = xmlChildAreas[0] + + if (firstChildArea.getprevious() and + self.docObj.getTypeField( + firstChildArea.getprevious()) == "br"): + prev_prev_sbl = ( + firstChildArea.getprevious().getprevious()) + if prev_prev_sbl: + if self.docObj.getTypeField(prev_prev_sbl) == "br": + firstChildArea = firstChildArea.getprevious() + flagFoundArea = False + it = 0 + lenChild = len(childNodes) + for node in childNodes: + it += 1 + if node.tag == "area": + flagFoundArea = True + continue + if flagFoundArea and node.tag == "field": + if self.docObj.getTypeField(node) == "var": + insertBefore(xmlArea, node, firstChildArea) + if it < lenChild: + node_type = self.docObj.getTypeField( + childNodes[it]) + if node_type == "br": + insertBefore(xmlArea, childNodes[it], + firstChildArea) + # Добавление перевода строк в если его нет между полями + if (self.docObj.getTypeField(node) == "var" and + node.getprevious() and + not (self.docObj.getTypeField( + node.getprevious()) in ("br", "comment"))): + insertBefore(xmlArea, self.docObj.createField( + "br", [], "", [], False, False), node) + + # Добавляем BR если его нет первым полем + xmlFields = xpath.Evaluate("child::field", xmlArea) + if not (xmlFields and + (self.docObj.getTypeField(xmlFields[0]) == "br" or + self.docObj.getTypeField( + xmlFields[0]) == "comment")): + if xmlFields: + insertBefore(xmlArea, self.docObj.createField("br", + [], "", [], + False, False), + xmlFields[0]) + # Добавление переводов строк между полями + if xmlFields: + for node in xmlFields: + # Добавление перевода строк в если его нет между полями + if (self.docObj.getTypeField(node) == "var" and + node.getprevious() is not None and + not (self.docObj.getTypeField( + node.getprevious()) in ("br", "comment"))): + insertBefore(xmlArea, self.docObj.createField("br", + [], "", [], + False, + False), + node) + # Если последним полем BR, удаляем его + if xmlFields and self.docObj.getTypeField(xmlFields[-1]) == "br": + if not xmlFields[-1].getnext(): + xmlArea.remove(xmlFields[-1]) + + # Если предыдущим полем не (BR или комментарий) - добавляем BR + if (xmlArea.getprevious() is not None and + not (self.docObj.getTypeField( + xmlArea.getprevious()) == "br" or + self.docObj.getTypeField( + xmlArea.getprevious()) == "comment")): + parentNode = xmlArea.getparent() + insertBefore(parentNode, self.docObj.createField( + "br", [], "", [], False, False), xmlArea) + # Если есть предыдущее поле, и поле предыдущеее предыдущему + # не равно BR или комментарий то добавляем BR + if xmlArea.getprevious() is not None: + prPrSibling = xmlArea.getprevious().getprevious() + if (prPrSibling is not None and + not (self.docObj.getTypeField( + prPrSibling) == "br" or + self.docObj.getTypeField( + prPrSibling) == "comment")): + parentNode = xmlArea.getparent() + insertBefore(parentNode, self.docObj.createField( + "br", [], "", [], False, False), xmlArea) + # Если после есть BR а за ним ничего нет, удаляем BR + if (xmlArea.getnext() is not None and + self.docObj.getTypeField(xmlArea.getnext()) == "br"): + if xmlArea.getnext().getnext() is None: + parentNode = xmlArea.getnext().getparent() + parentNode.remove(xmlArea.getnext()) + + + def join(self, kdeObj): + """Объединяем конфигурации""" + if isinstance(kdeObj, plasma): + self.docObj.joinDoc(kdeObj.doc) + self.postXML() + +class xml_xfce(_error): + """Класс для объединения xfce-xml файлов""" + # root нода + rootNode = False + # body нода + bodyNode = False + # Документ + doc = False + # Текст профиля + text = "" + # Комментарий + _comment = ("") + + def __init__(self, text): + self.text = text + # Создаем пустой объект + self.docObj = type("_empty_class", (object,), {})() + # Названия аттрибутов для пустого объекта + emptyMethods = ["getNodeBody","removeComment","insertBRtoBody", + "insertBeforeSepAreas"] + # Добавляем необходимые аттрибуты пустому объекту + for method in emptyMethods: + setattr(self.docObj, method, self.emptyMethod) + # Создаем XML документ + self.doc = self.textToXML() + + def emptyMethod(self, *arg , **argv): + """Пустой метод""" + return True + + def setNameBodyNode(self, name): + """Устанавливает название для корневой ноды документа""" + if not self.bodyNode: + return False + self.bodyNode.set("name", name) + return True + + def textToXML(self): + """Создание из текста XML документа + Храним xml в своем формате + """ + if not self.text.strip(): + self.text = ''' + +''' + try: + self.doc = str_to_xml_doc(self.text) + except Exception as e: + print(e) + self.setError(_("The template content is not XML")) + return False + self.rootNode = self.doc.getroottree().getroot() + self.bodyNode = self.rootNode + return self.doc + + def join(self, xml_xfceObj): + """Объединяем конфигурации""" + if isinstance(xml_xfceObj, xml_xfce): + try: + self.joinDoc(xml_xfceObj.doc) + except: + self.setError(_("Can not join profile")) + return False + return True + + def _removeDropNodesAndAttrAction(self, xmlNode): + """Удаляет ноды с аттрибутом action='drop' + + Также удаляет аттрибут action у всех нод + """ + childNodes = list(xmlNode) + if "action" in xmlNode.keys(): + nAction = xmlNode.get("action") + if nAction not in ("join", "replace", "drop"): + textError = _("In the text of the XML template, " + "reserved attribute 'action' comes with an " + "incorrect value.\n" + "Valid values of the 'action' attribute are: " + '(action="join", action="replace",' + 'action="drop")') + self.setError(textError) + return False + xmlNode.removeAttribute("action") + if nAction == "drop": + parentNode = xmlNode.getparent() + if parentNode: + parentNode.remove(xmlNode) + if childNodes: + for node in childNodes: + if not self._removeDropNodesAndAttrAction(node): + return False + return True + + def postXML(self): + """Последующая постобработка XML""" + # Удаляем теги action и удаляемые ноды + self._removeDropNodesAndAttrAction(self.bodyNode) + + def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True): + """Объединение корневой ноды шаблона и корневой ноды файла""" + xmlNode = xmlNewNode + childNodes = list(xmlNode) + nextOldNode = xmlOldNode + # if xmlNode.nodeType == xmlNode.ELEMENT_NODE: + n = xmlNode + nType = '' + nValue = '' + nAction = '' + attrName = '' + attrType = '' + path = n.tag + if "name" in n.keys(): + nName = n.get("name") + attrName = "attribute::name='%s'" % nName + if "type" in n.keys(): + nType = n.get("type") + attrType = "attribute::type='%s'" % nType + if "value" in n.keys(): + nValue = n.get("value") + if "action" in n.keys(): + nAction = n.get("action") + if not nAction in ("join", "replace", "drop"): + textError = _( + "In the text of the XML template, " + "reserved attribute 'action' comes with an " + "incorrect value.\n" + "Valid values of the 'action' attribute are: " + '(action="join", action="replace", action="drop")') + self.setError(textError) + return False + if xmlNewNode.getparent() is not None: + strAttr = [attrName, attrType] + findAttr = [x for x in strAttr if x] + findAttrStr = '' + if findAttr: + strAttr = ' and '.join(findAttr) + findAttrStr = "[%s]" % strAttr + findPath = "child::%s%s" % (path, findAttrStr) + # Рабочая нода + if flagRootNode: + workNode = xmlOldNode.getparent() + else: + workNode = xmlOldNode + oldNodes = xpath.Evaluate(findPath, workNode) + # Новая нода список + flagArray = nType == "array" + flagDrop = False + flagJoin = True + flagReplace = False + if nAction == "replace": + flagJoin = False + flagReplace = True + elif nAction == "drop": + flagJoin = False + flagDrop = True + if flagRootNode: + textError = _('Incorrect action="drop" in ' + 'the root node') + self.setError(textError) + return False + if oldNodes: + if len(oldNodes) > 1: + textError = _("Ambiguity in this template: " + "the same nodes are on a same level") + self.setError(textError) + return False + nextOldNode = oldNodes[0] + # Замещаем ноду в случае массива + if flagArray and not flagDrop: + replaceXmlNode = deepcopy(xmlNode) + if nAction: + del replaceXmlNode.attrib["action"] + workNode.replace(nextOldNode, replaceXmlNode) + flagJoin = False + flagReplace = False + childNodes = False + # Объединение нод + if flagJoin: + if "value" in nextOldNode.keys(): + oValue = nextOldNode.get("value") + if nValue != oValue: + nextOldNode.set("value", nValue) + # Замещение ноды + elif flagReplace: + replaceXmlNode = deepcopy(xmlNode) + if not self._removeDropNodesAndAttrAction( + replaceXmlNode): + return False + workNode.replace(nextOldNode, replaceXmlNode) + childNodes = False + # Удаление ноды + elif flagDrop: + workNode.remove(nextOldNode) + childNodes = False + else: + # Добавление ноды + childNodes = False + if not flagDrop: + appendXmlNode = deepcopy(xmlNode) + if not self._removeDropNodesAndAttrAction( + appendXmlNode): + return False + workNode.append(appendXmlNode) + if isinstance(childNodes, Iterable): + for node in childNodes: + if not self._join(node, nextOldNode, False): + return False + return True + + def joinDoc(self, doc): + """Объединение документа шаблона и документа файла""" + if self.doc is None: + self.setError(_("The text file is not XML")) + return False + if doc is None: + self.setError(_("The text file is not XML")) + return False + # Импортируем корневую ноду нового документа в текущий документ + # newImportBodyNode = self.doc.importNode(doc.documentElement, True) + # Объединение корневой ноды шаблона и корневой ноды файла + if not self._join(doc, self.bodyNode): + return False + return True + + def getConfig(self): + """Получение текстового файла из XML документа""" + data = xml_to_str(self.doc).split("\n") + data = [x for x in data if x.strip()] + data.insert(0, '\n') + return "\n".join(data).replace("\t", " ") + +class squid(procmail): + """Класс для обработки конфигурационного файла типа squid + + """ + configName = "squid" + configVersion = "0.1" + # разделитель названия и значения переменной + reSeparator = re.compile(" ") + + def __init__(self, text): + procmail.__init__(self, text) + # Создаем поля-массивы + self.docObj.postParserList() + # Создаем поля разделенные массивы + self.docObj.postParserListSeplist(self.docObj.body) + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + flagVariable = True + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + flagVariable = False + elif findComment: + if textLine[:findComment.start()].strip(): + field.comment = textLine[findComment.start():] + textLine = textLine[:findComment.start()] + else: + field.comment = textLine + flagVariable = False + fields.append(field) + field = fieldData() + if flagVariable: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len(nameValue) > 2: + valueList = nameValue[1:] + nameValue =[nameValue[0]," ".join(valueList)] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def join(self, squidObj): + """Объединяем конфигурации""" + if isinstance(squidObj, squid): + #print squidObj.getConfig() + self.docObj.joinDoc(squidObj.doc) + +class xml_xfcepanel(xml_xfce): + """Класс для объединения xfce-panel файлов""" + def __init__(self, text): + xml_xfce.__init__(self, text) + self.panelNumbers = {} + + def textToXML(self): + """Создание из текста XML документа + Храним xml в своем формате + """ + if not self.text.strip(): + self.text = ''' + + +''' + try: + self.doc = str_to_xml_doc(self.text) + except: + self.setError(_("Can not text profile is XML")) + return False + self.rootNode = self.doc.getroottree().getroot() + self.bodyNode = self.rootNode + return self.doc + + + def setNameBodyNode(self, name): + """Пустой метод""" + return True + + def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): + """Объединение корневой ноды шаблона и корневой ноды файла""" + xmlNode = xmlNewNode + childNodes = list(xmlNode) + nextOldNode = xmlOldNode + n = xmlNode + flagArray = False + nValue = '' + nAction = '' + attrName = '' + path = n.tag + if path == "items": + flagArray = True + if not flagArray: + if "name" in n.keys(): + nName = n.get("name") + attrName = "attribute::name='%s'" % nName + if "value" in n.keys(): + nValue = n.get("value") + if "action" in n.keys(): + nAction = n.get("action") + if not nAction in ("join", "replace", "drop"): + textError = _("In the text of the XML template, " + "reserved attribute 'action' comes with an " + "incorrect value.\n" + "Valid values of the 'action' attribute are: " + '(action="join", action="replace", ' + 'action="drop")') + self.setError(textError) + return False + if xmlNewNode.getparent() is not None: + findAttrStr = "" + if attrName: + findAttrStr = "[%s]" % attrName + findPath = "child::%s%s" % (path, findAttrStr) + # Рабочая нода + if flagRootNode: + workNode = xmlOldNode.getparent() + else: + workNode = xmlOldNode + oldNodes = xpath.Evaluate(findPath, workNode) + flagDrop = False + flagJoin = True + flagReplace = False + flagAppend = False + if nAction == "replace": + flagJoin = False + flagReplace = True + elif nAction == "drop": + flagJoin = False + flagDrop = True + if flagRootNode: + textError = _('Incorrect action="drop" ' + 'in the root node') + self.setError(textError) + return False + if path == "panel": + flagJoin = False + if levelNumber in self.panelNumbers.keys(): + self.panelNumbers[levelNumber] += 1 + else: + self.panelNumbers[levelNumber] = 0 + if oldNodes: + if len(oldNodes) > 1 and path != "panel": + textError = _("Ambiguity in this template: the " + "same nodes are on a same level") + self.setError(textError) + return False + if path == "panel": + if len(oldNodes) <= self.panelNumbers[levelNumber]: + nextOldNode = oldNodes[-1] + # Добавляем ноду + if not flagDrop: + flagAppend = True + flagReplace = False + childNodes = False + else: + nextOldNode = oldNodes[ + self.panelNumbers[levelNumber]] + else: + nextOldNode = oldNodes[0] + # Замещаем ноду в случае массива + if flagArray and not flagDrop: + replaceXmlNode = deepcopy(xmlNode) + if nAction: + del replaceXmlNode.attrib["action"] + workNode.replace(nextOldNode, replaceXmlNode) + flagJoin = False + flagReplace = False + childNodes = False + # Объединение нод + if flagJoin: + if "value" in nextOldNode.keys(): + oValue = nextOldNode.get("value") + if nValue != oValue: + nextOldNode.set("value", nValue) + # Замещение ноды + elif flagReplace: + replaceXmlNode = deepcopy(xmlNode) + if not self._removeDropNodesAndAttrAction( + replaceXmlNode): + return False + workNode.replace(nextOldNode, replaceXmlNode) + childNodes = False + # Удаление ноды + elif flagDrop: + workNode.remove(nextOldNode) + childNodes = False + else: + flagAppend = True + flagDrop = False + if flagAppend and not flagDrop: + # Добавление ноды + childNodes = False + if not flagDrop: + appendXmlNode = deepcopy(xmlNode) + if not self._removeDropNodesAndAttrAction( + appendXmlNode): + return False + workNode.append(appendXmlNode) + if isinstance(childNodes, Iterable): + for node in childNodes: + levelNumber += 1 + if not self._join(node, nextOldNode, False, levelNumber): + return False + levelNumber -= 1 + return True + + def join(self, xml_xfceObj): + """Объединяем конфигурации""" + if isinstance(xml_xfceObj, xml_xfcepanel): + try: + self.joinDoc(xml_xfceObj.doc) + except Exception: + self.setError(_("Failed to join the template")) + return False + return True + + +class dhcp(bind): + """Класс для обработки конфигурационного файла типа dhcp + + """ + _comment = "#" + configName = "dhcp" + configVersion = "0.1" + __openArea = "{" + __closeArea = "[ \t]*\}[ \t]*" + sepFields = ";" + reOpen = re.compile(__openArea) + reClose = re.compile(__closeArea) + reCloseArea = re.compile(__closeArea + "\s*\Z") + reComment = re.compile("^[ \t]*%s"%(_comment)) + reSepFields = re.compile(sepFields) + reSeparator = re.compile("[ \t]+") + + def __init__(self,text): + bind.__init__(self,text) + + def setDataField(self, txtLines, endtxtLines): + """Создаем список объектов с переменными""" + class fieldData: + def __init__(self): + self.name = False + self.value = False + self.comment = False + self.br = False + fields = [] + field = fieldData() + z = 0 + for k in txtLines: + textLine = k + endtxtLines[z] + z += 1 + findComment = self.reComment.search(textLine) + if not textLine.strip(): + field.br = textLine + fields.append(field) + field = fieldData() + elif findComment: + field.comment = textLine + fields.append(field) + field = fieldData() + else: + pars = textLine.strip() + nameValue = self.reSeparator.split(pars) + if len (nameValue) == 1: + field.name = textLine.replace(self.sepFields,"").strip() + field.value = "" + field.br = textLine + fields.append(field) + field = fieldData() + + if len(nameValue) > 2: + nameCheck = nameValue[0] + if nameValue[0][:1] in ["+","-","!"]: + nameCheck = nameValue[0][1:] + if nameCheck == "option" or nameCheck == "hardware" or\ + nameCheck == "set": + valueList = nameValue[2:] + nameValue =[nameValue[0]+nameValue[1], + " ".join(valueList).replace(\ + self.sepFields,"")] + else: + valueList = nameValue[1:] + nameValue =[nameValue[0]," ".join(valueList).replace(\ + self.sepFields,"")] + if len(nameValue) == 2: + name = nameValue[0] + value = nameValue[1].replace(self.sepFields,"") + field.name = name.replace(" ","").replace("\t","") + field.value = value + field.br = textLine + fields.append(field) + field = fieldData() + return fields + + def join(self, dhcpObj): + """Объединяем конфигурации""" + if isinstance(dhcpObj, dhcp): + self.docObj.joinDoc(dhcpObj.doc) + + +class xml_gconf(xml_xfce): + """Класс для объединения gconf-xml файлов""" + # root нода + rootNode = False + # body нода + bodyNode = False + # Документ + doc = False + # Текст профиля + text = "" + # Текущее время в секундах + currentTime = "" + # Комментарий + _comment = ("") + # поддерживаемые аттрибуты тега entry. Пример + supportEntryTypes = ("int", "bool", "float", "string", "list", "pair") + # регулярное выражения для поиска \t в начале строки (преобразование xml) + reStartTabs = re.compile("^(\t+)(.*)$") + + def __init__(self, text): + self.text = text + # Создаем пустой объект + self.docObj = type("_empty_class", (object,), {})() + # Названия аттрибутов для пустого объекта + emptyMethods = ["getNodeBody", "removeComment", "insertBRtoBody", + "insertBeforeSepAreas"] + # Добавляем необходимые аттрибуты пустому объекту + for method in emptyMethods: + setattr(self.docObj, method, self.emptyMethod) + # Пустой метод (не нужно имя файла для корневой ноды) + setattr(self, "setNameBodyNode", self.emptyMethod) + # Создаем XML документ + self.doc = self.textToXML() + + def getCurrentTime(self): + """Получение текущего времени в секундах""" + return str(int(time.time())) + + def textToXML(self): + """Создание из текста XML документа + Храним xml в своем формате + """ + if not self.text.strip(): + self.text = '''''' + try: + self.doc = str_to_xml_doc(self.text) + except Exception: + self.setError(_("Can not text profile is XML")) + return False + self.rootNode = self.doc.getroottree().getroot() + self.bodyNode = self.rootNode #? a mistake, maybe? + return self.doc + + def cmpListsNodesEntry(self, listXmlA, listXmlB): + """Сравнение содержимого двух списков XML нод""" + def getTextsNodes(listXml): + for node in (deepcopy(x) + for x in listXml):# if x.nodeType == x.ELEMENT_NODE): + if "mtime" in node.keys(): + # node.removeAttribute("mtime") + del node.attrib["mtime"] + text = node.toxml() + yield text.replace(" ", "").replace("\t", "").replace("\n", "") + if set(getTextsNodes(listXmlA)) == set(getTextsNodes(listXmlB)): + return True + return False + + def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0): + """Объединение корневой ноды профиля и корневой ноды файла""" + if levelNumber > 1: + return True + xmlNode = xmlNewNode + childNodes = list(xmlNode) + nextOldNode = xmlOldNode + # if xmlNode.nodeType == xmlNode.ELEMENT_NODE: + n = xmlNode + tagName = n.tag + nAction = '' + nType = '' + nValue = '' + nSchema = '' + attrName = '' + if flagRootNode: + if not tagName == "gconf": + self.setError(_("The text is not a valid gconf-XML format \ +(not found '...')")) + return False + flagType = False + flagValue = False + flagSchema = False + else: + if not tagName == "entry": + self.setError(_("The text is not a valid gconf-XML format \ +(found '<%(tag)s>..')") % {'tag': tagName}) + return False + if "name" not in n.keys(): + self.setError( + _("Attribute \"name\" not found in the tag entry")) + return False + flagType = "type" in n.keys() + flagValue = False + flagSchema = "schema" in n.keys() + if flagSchema: + nSchema = n.get("schema") + if not flagType and not flagSchema: + self.setError( + _("Attribute \"type\" not found in the tag entry")) + return False + nName = n.get("name") + attrName = "attribute::name='%s'" % nName + if flagType: + flagValue = "value" in n.keys() + nType = n.get("type") + # Проверка правильности аттрибута type + if nType not in self.supportEntryTypes: + self.setError(_("Incorrect \"type\" attribute " + ": ") % nType) + return False + if flagValue: + nValue = n.get("value") + if "action" in n.keys(): + nAction = n.get("action") + if nAction not in ("join", "replace", "drop"): + textError = _("In the text of the XML template, " + "reserved attribute 'action' comes with an " + "incorrect value.\n" + "Valid values of the 'action' attribute are: " + '(action="join", action="replace",' + 'action="drop")') + self.setError(textError) + return False + if xmlNewNode.getparent(): + findAttrStr = "" + if attrName: + findAttrStr = "[%s]" % attrName + findPath = "child::%s%s" % (tagName, findAttrStr) + # Рабочая нода + if flagRootNode: + workNode = xmlOldNode.getparent() + else: + workNode = xmlOldNode + oldNodes = xpath.Evaluate(findPath, workNode) + # По умолчанию - объединение + flagJoin = True + flagReplace = False + flagDrop = False + # Замещаем ноду + if nType == "string" or nAction == "replace": + flagJoin = False + flagReplace = True + # Замещаем ноду в случае массива + elif nType == "list" or nType == "pair": + flagJoin = False + flagReplace = True + # Удаляем ноду + elif nAction == "drop": + flagJoin = False + flagDrop = True + if flagRootNode: + textError = _('Incorrect action="drop" in ' + 'the root node') + self.setError(textError) + return False + if oldNodes: + if len(oldNodes) > 1: + textError = _("Ambiguity in this template: the same " + "nodes are on a same level") + self.setError(textError) + return False + nextOldNode = oldNodes[0] + # Объединение нод + if flagJoin: + if flagType and flagValue: + flagChange = False + if "value" in nextOldNode.keys(): + oValue = nextOldNode.get("value") + if nValue != oValue: + flagChange = True + else: + flagChange = True + if flagChange: + nextOldNode.set("mtime", self.currentTime) + nextOldNode.set("value", nValue) + elif flagSchema: + flagChange = False + if "schema" in nextOldNode.keys(): + oSchema = nextOldNode.get("schema") + if nSchema != oSchema: + flagChange = True + else: + flagChange = True + if flagChange: + nextOldNode.set("mtime", self.currentTime) + nextOldNode.set("schema", nSchema) + # Замещение ноды + elif flagReplace: + replaceXmlNode = deepcopy(xmlNode) + # Сравнение содержимого нод + if not self.cmpListsNodesEntry([replaceXmlNode], + [nextOldNode]): + replaceXmlNode.set("mtime", + self.currentTime) + if not self._removeDropNodesAndAttrAction( + replaceXmlNode): + return False + workNode.replace(nextOldNode, replaceXmlNode) + childNodes = False + # Удаление ноды + elif flagDrop: + workNode.remove(nextOldNode) + childNodes = False + else: + # Добавление ноды + childNodes = False + if not flagDrop: + appendXmlNode = deepcopy(xmlNode) + appendXmlNode.set("mtime", self.currentTime) + if not self._removeDropNodesAndAttrAction( + appendXmlNode): + return False + workNode.append(appendXmlNode) + if isinstance(childNodes, Iterable): + for node in childNodes: + levelNumber += 1 + if not self._join(node, nextOldNode, False, levelNumber): + return False + levelNumber -= 1 + return True + + def join(self, xml_gconfObj): + """Объединяем конфигурации""" + # Получаем текущее время + self.currentTime = self.getCurrentTime() + if isinstance(xml_gconfObj, xml_gconf): + try: + self.joinDoc(xml_gconfObj.doc) + except Exception: + self.setError(_("Can not join profile")) + return False + return True + + def getConfig(self): + """Получение текстового файла из XML документа""" + + def expandStartTabs(s): + if s.startswith("\t"): + res = self.reStartTabs.search(s) + if res: + return str(res.group(1)).replace("\t", " ") + res.group(2) + return s + else: + return s + + data = xml_to_str(self.doc).split("\n") + data = [expandStartTabs(x) for x in data if x.strip()] + dataOut = [] + z = 0 + lenData = len(data) + lenM2 = lenData - 2 + for i in range(lenData): + if z > 0: + z -= 1 + continue + if i < lenM2 and data[i].endswith(">") and "<" not in data[i + 1]: + dataOut.append( + data[i] + data[i + 1].strip() + data[i + 2].strip()) + z = 2 + continue + dataOut.append(data[i]) + dataOut.insert(0, '\n') + return "\n".join(dataOut) \ No newline at end of file diff --git a/pym/cl_utils.py b/pym/cl_utils.py new file mode 100644 index 0000000..5c0190e --- /dev/null +++ b/pym/cl_utils.py @@ -0,0 +1,609 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import filecmp +import string +from random import choice +from re import search, compile, S +import os +import types +import subprocess +import socket +import struct +import fcntl +import math +import ctypes +from functools import reduce + +def getdirlist(s_path): + #Получить список директорий по указаному пути + fdir=filecmp.dircmp(s_path, s_path) + dir_list=fdir.common_dirs + return dir_list + +def prettyColumnStr(*cols): + '''Функция преобразования строк в текстовые колонки. Если указанный текст + не помещается в колонку, то строка переносится на следующую этой же колонки + перенос текста идет по словам, и текст выравнивается по ширине колонки за + счет дополнительных пробелов между словами. Если в строке используется + перенос строки, то текст переносится не просто на следующую строку, а также + на следующую строку колонки, причем если используется \r текст выравнива- + ется по ширине, а если \n, то просто перевод строки. + + Параметры: + cols множестово пар: текст, ширина колонки, причем, если у последней + колонки не указывать ширину, то она будет выведена вся. + + Возвращаемые параметры: + строка, которую можно использовать для вывода на экран + + Пример: columnWrite( "Some text", 10, "Next column", 20 ) + ''' + # шаблон поиска переводов строк + wherenr = compile( '[\n\r]', S ) + retstr = "" + # перевести кортеж в список, т.к. изменяется + cols = list(cols) + # перевести текст в юникод, заодно перевести числа в строку + noconvert = False + space = u' ' + nospace = u'' + for i in range(0,len(cols),2): + cols[i] = _toUNICODE(cols[i]) + # флаг "есть еще текст для вывода" + repeat = True + while repeat: + # сбросить итератор на первый элемент + q = 0 + repeat = False + # пока не закончили перебирать параметры (перебираем по парам) + while q < len(cols): + # если это последний параметр, и для него не указана ширина + if q == len(cols)-1: + # выводим его полностью не смотря на ширину окна + retstr += cols[q] + " " + cols[q] = '' + else: + # вывести часть строки не больше указанной ширины колонки + partstr = cols[q][:cols[q+1]] + # искать перевод строки с полученной части + brfind = wherenr.search(partstr) + # если это не последняя колонка + if q + 2 < len(cols): + # добавить разделитель между колонками + cellspacing = space + else: + # разделитель не нужен + cellspacing = nospace + + # если перевод строки найден, то + if brfind != None: + # для текущего вывода в колонку + # берем часть строки до перевода + partstr = partstr[:brfind.start()] + # остальная часть идет в остаток (без перевода) + cols[q] = cols[q][brfind.start()+1:] +# # если используется перевод каретки +# if brfind.group() == '\r': +# # то выравниваем по ширине колонки +# partstr = partstr.ljust(cols[q+1], ' ') +# else: +# # добавить отступы чтобы закончить колонку + partstr = partstr.ljust(cols[q+1], ' ') + # если взята часть строки + elif len(partstr) == cols[q+1] and partstr != cols[q]: + # если взята часть строки (разрыв в слове) + if cols[q][cols[q+1]] != ' ': + # ищем ближайший пробел справа + spacepos = partstr.rfind(' ') + # если пробел найти не удалось + if spacepos == -1: + # то на вывод идет часть строки равной ширине + cols[q] = cols[q][cols[q+1]:] + # если пробел найден + else: + # обрезаем строку до найденного пробела + partstr = partstr[:spacepos] + cols[q] = cols[q][spacepos+1:] + # если взята часть строки (разрыв на пробеле) + else: + # ислючить переносной пробел + cols[q] = cols[q][cols[q+1]+1:] + # выровнить текст по ширине колонки + partstr = partstr.ljust(cols[q+1], ' ') + #partstr = justify(partstr, cols[q+1]) + # остатки строки + else: + # добавить отступы чтобы закончить колонку + partstr = partstr.ljust(cols[q+1], ' ') + cols[q] = '' + + retstr+= partstr + cellspacing + + # остальную часть строки оставить на следующую итерацию + # если от строки что то осаталось + if len(cols[q]) > 0: + # отметить запуск еще одной итерации по параметрам + repeat = True + # следующая пара + q += 2 + # колонки отображены + retstr += "\n" + return retstr + +def columnStr(*cols): + '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную + колонку, то они переносятся на следующую строку в нужную колонку. В строку. + + Параметры: + cols множестово пар: текст, ширина колонки, причем, если у последней + колонки не указывать ширину, то она будет выведена вся. + + Возвращаемые параметры: + строка, которую можно использовать для вывода на экран + + Пример: columnWrite( "Some text", 10, "Next column", 20 ) + ''' + retstr = "" + # перевести кортеж в список, т.к. изменяется + cols = list(cols) + # перевести текст в юникод, заодно перевести числа в строку + for i in range(0,len(cols),2): + cols[i] = (str(cols[i])) + + # флаг "есть еще текст для вывода" + repeat = True + while repeat: + # сбросить итератор на первый элемент + q = 0 + repeat = False + # пока не закончили перебирать параметры (перебираем по парам) + while q < len(cols): + # если это последний параметр, и для него не указана ширина + if q == len(cols)-1: + # выводим его полностью не смотря на ширину окна + retstr += cols[q] + " " + cols[q] = '' + else: + # вывести часть строки не больше указанной ширины колонки + retstr+=(cols[q][:cols[q+1]].ljust(cols[q+1])) \ + + " " + # остальную часть строки оставить на следующую итерацию + cols[q] = cols[q][cols[q+1]:] + # если от строки что то осаталось + if len(cols[q]) > 0: + # отметить запуск еще одной итерации по параметрам + repeat = True + # следующая пара + q += 2 + # колонки отображены + retstr += "\n" + return retstr + +def columnWrite(*cols): + '''Вывод данных по колонкам, причем, если данные не вмещаются в указнаную + колонку, то они переносятся на следующую строку в нужную колонку. + + Параметры: + cols множестово пар: текст, ширина колонки, причем, если у последней + колонки не указывать ширину, то она будет выведена вся. + + Пример: columnWrite( "Some text", 10, "Next column", 20 ) + ''' + # перевести кортеж в список, т.к. изменяется + cols = list(cols) + # перевести текст в юникод, заодно перевести числа в строку + for i in range(0,len(cols),2): + cols[i] = (str(cols[i])) + + # флаг "есть еще текст для вывода" + repeat = True + while repeat: + # сбросить итератор на первый элемент + q = 0 + repeat = False + # пока не закончили перебирать параметры (перебираем по парам) + while q < len(cols): + # если это последний параметр, и для него не указана ширина + if q == len(cols)-1: + # выводим его полностью не смотря на ширину окна + print(cols[q], end=' ') + cols[q] = '' + else: + # вывести часть строки не больше указанной ширины колонки + print((cols[q][:cols[q+1]].ljust(cols[q+1])), end=' ') + # остальную часть строки оставить на следующую итерацию + cols[q] = cols[q][cols[q+1]:] + # если от строки что то осаталось + if len(cols[q]) > 0: + # отметить запуск еще одной итерации по параметрам + repeat = True + # следующая пара + q += 2 + # колонки отображены + print() + +def justify(s, width): + '''Выровнить текст по ширине + + Параметры: + s выводимая строка + width ширина на которую надо выровнить строку + + Возвращаямые параметры: + Выровненная строка + ''' + # если подана строка без пробелов - прекратить обработку + if s.find(' ') == -1: + return s + pos = 0 + # переводим в юникод для правильного вычисления длины + try: + s = s + # пропуск если это не utf-8 + except UnicodeEncodeError: + pass + # пока длина строки меньше указанной + while len(s) < width: + # находим очередной пробел + pos = s.find( ' ', pos ) + # если не найден искать сначала + if pos == -1: + pos = s.find(' ') + # вставить в позицию еще один пробел + s = s[:pos] +' ' +s[pos:] + # оставить удвоенный пробел + pos += 3 + # вернуть строку в utf8 если она пришла в utf8 + return s + +def runOsCommand(cmd, inStr=None, ret_first=None, env_dict=None): + """Выполняет внешнюю программу + + Параметры: + cmd внешняя программа + inStr данные передаваемые программе на страндартный вход. + ret_first вернуть только первую строку + env_dict словарь переменных окружения + Возвращаемые параметры: + строка/строки которую выведет внешняя программа + Возвращает код возврата, stdout+stderr + """ + pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env_dict, + close_fds=True, + shell=True) + fout, fin, ferr = (pipe.stdout, pipe.stdin, pipe.stderr) + # если есть данные на вход, передать их + if inStr: + inStr = inStr.encode("UTF-8") if isinstance(inStr, str) else inStr + fin.write(inStr) + fin.close() + # Код возврата + retcode = pipe.wait() + res = fout.readlines() + fout.close() + if not ("dovecot start" in cmd or "dovecot restart" in cmd): + res += ferr.readlines() + ferr.close() + if res: + if len(res) == 1 or ret_first: + return retcode, res[0].decode("UTF-8").strip() + else: + return retcode, [x.decode("UTF-8") for x in res] + return retcode, None + + +def genpassword(passlen=9): + '''Вернуть случайный пассворд указанной длины + + Параметры: + passlen длина пароля который нужно сгенерировать + + Возвращаемые параметры: + Сгенерированный пароль указанной длины + ''' + res=''.join([choice(string.ascii_letters+string.digits)\ + for i in range(passlen)]) + return res + +def fillstr(char, width): + '''Заполнить строку указанным числом символов. Псеводоним символ*кол-во''' + return str(char) * width + + #вернуть пути для запуска утилит +def getpathenv(): + bindir=['/sbin','/bin','/usr/sbin','/usr/bin'] + env=os.environ + if env and 'PATH' in env: + lpath=env['PATH'].split(":") + npath = [] + for dirname in bindir: + if os.path.exists(dirname) and dirname not in lpath: + npath.append(dirname) + lpath=npath+lpath + return ":".join(lpath) + +#класс для работы с установленными пакетами +class pakages: + #путь к директории установленнх пакетов + pkgdir="/var/db/pkg/" + #список установленных пакетов + pkglist = {} + #Объект содержащий параметры пакета + class pakage(): + #имя пакета с версией + fullname="" + #имя пакета + name="" + #версия + ver="" + #тип пакета в портежах + portdir="" + def __init__(self, **args): + for atname, atvalue in args.items(): + setattr(self,atname, atvalue) + + def __init__(self): + self.pkglist=self.__getpkglist() + + #разбить имя пакета на тип и имя + def __getpkgver(self, fname): + res=search('^(.+)\-([0-9]+.*)$',fname) + if res: + return res.groups() + else: + return (None,None) + + #собрать установленные в системе пакеты + def __getpkglist(self): + portageDirs = [] + instaledPkg = {} + #проверим на существование директории с установленными пакетами + if os.path.exists(self.pkgdir): + #получим список типов пакетов + portageDirs=getdirlist(self.pkgdir) + if len(portageDirs)>0: + #обрабатываем содержимое каждого из типов + for portageDir in portageDirs: + pkgList=getdirlist(self.pkgdir+portageDir) + for pkg in pkgList: + fullname=pkg + pkgName,pkgVer= self.__getpkgver(pkg) + pobj=self.pakage(fullname=fullname, + name=pkgName, \ + ver=pkgVer,\ + portdir=portageDir) + fpkg=portageDir+"/"+pkgName + if fpkg in instaledPkg: + instaledPkg[fpkg].append(pobj) + else: + instaledPkg[fpkg]=[pobj] + return instaledPkg + + #разбить pkgname на составляющие имени пакета + def __partname(self, pkgname): + if not pkgname.strip(): + return False + res=search('^(.+\/)?(.+)',pkgname) + tname=None + if res.group(1): + tname=res.group(1) + if res.group(2): + res2=search('^(.+)(\-[0-9]+.+$)',res.group(2)) + if res2: + name=res2.group(1) + ver=res2.group(2) + else: + name=res.group(2) + ver=None + if res: + if name and name[-1:]=='-': + name=name[:-1] + if tname and tname[-1:]=='/': + tname=tname[:-1] + if ver and ver[0]=='-': + ver=ver[1:] + return [tname, name, ver] + + + #проверить установленн ли пакет + #isinstalled('dev-db/postgresql') + def isinstalled(self, pkgname): + res=self.getinstpkg(pkgname) + if len(res)>0: + return True + else: + return False + + #вернуть список объектов pakage() соответствующих pkgname + #getinstpkg('dev-db/postgresql') + #в случае отсутствия пакетов возвращает пустой список + def getinstpkg(self, pkgname): + pinfo=self.__partname(pkgname) + if pinfo: + ret = [] + if pinfo[0] and pinfo[1] and pinfo[2]: + if pinfo[0]+'/'+pinfo[1] not in self.pkglist: + return [] + fpkg=self.pkglist[pinfo[0]+'/'+pinfo[1]] + ret = [] + for i in fpkg: + if i.ver==pinfo[2]: + ret.append(i) + return ret + elif pinfo[0] and pinfo[1]: + if pinfo[0]+'/'+pinfo[1] not in self.pkglist: + return [] + return self.pkglist[pinfo[0]+'/'+pinfo[1]] + elif pinfo[1] and pinfo[2]: + for i in self.pkglist.keys(): + if search('^.+\/%s$'%(pinfo[1]),i): + for el in self.pkglist[i]: + if el.ver==pinfo[2]: + ret.append(el) + return ret + elif pinfo[1]: + for i in self.pkglist.keys(): + if search('^.+\/%s$'%(pinfo[1]),i): + ret+=self.pkglist[i] + return ret + return [] + + def getListPkg(self): + return self.pkglist + +def list2str(list): + '''Функция переводит список в строку''' + return '['+','.join(list)+']' + +def str2list(s): + '''Функция переводит строку в список''' + return s[1:-1].split(',') + +def dict2str(dict): + '''Функция перводит словарь в строку''' + return '{'+','.join(["%s:%s" % (str(k),str(v)) \ + for (k,v) in dict.items()])+'}' #: + +def str2dict(s): + '''Функция переводит строку в словарь''' + dict = {} + for i in s[1:-1].split(','): + k,v = i.split(':') + dict[k] = v + return dict + +def convertStrListDict(val): + '''Функция определеяется что на входе (строка, список, словарь) + и переводит их в строку и обратно''' + # если подан список + if type(val) == list: + return list2str(val) + # если подан словарь + elif type(val) == dict: + return dict2str(val) + # если подана строка + else: + # если поданная строка содержит словарь + if ':' in val and '{' in val: + return str2dict(val) + # если поданная строка содержит список + elif ',' in val and '[' in val: + return str2list(val) + # если это просто строка + else: + return val + +def _toUNICODE(val): + """перевод текста в юникод""" + if type(val) == str: + return val + else: + return str(val) + +SYSFS_NET_PATH = "/sys/class/net" + +# From linux/sockios.h +SIOCGIFADDR = 0x8915 +SIOCGIFNETMASK = 0x891B +SIOCGIFHWADDR = 0x8927 + +def getInterfaces(): + """ + Get available interfaces (discard which hasn't device) + """ + try: + return [x for x in os.listdir(SYSFS_NET_PATH) if x!= "lo"] + except: + return [] + +def getIp(iface): + sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + ifreq = struct.pack('16sH14s', iface.encode("UTF-8"), socket.AF_INET, b'\x00'*14) + try: + res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq) + except IOError: + return "" + finally: + sockfd.close() + ip = struct.unpack('16sH2x4s8x', res)[2] + return socket.inet_ntoa(ip) + +def getMask(iface): + """ + Get mask for interface + """ + sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + ifreq = struct.pack('16sH14s', iface.encode("UTF-8"), socket.AF_INET, b'\x00'*14) + try: + res = fcntl.ioctl(sockfd, SIOCGIFNETMASK, ifreq) + except IOError: + return 0 + finally: + sockfd.close() + netmask = socket.ntohl(struct.unpack('16sH2xI8x', res)[2]) + return 32 - int(math.log(ctypes.c_uint32(~netmask).value + 1, 2)) + +def getMac(iface): + """ + Get mac for interface + """ + sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + ifreq = struct.pack('16sH14s', iface.encode("UTF-8"), socket.AF_UNIX, b'\x00'*14) + res = fcntl.ioctl(sockfd, SIOCGIFHWADDR, ifreq) + address = struct.unpack('16sH14s', res)[2] + mac = struct.unpack('6B8x', address) + sockfd.close() + return ":".join(['%02X' % i for i in mac]) + +def intIpToStrIp(addr): + """Convert ip specified by integer to string""" + return "{0}.{1}.{2}.{3}".format( + addr>>24,(addr>>16)&0xff,(addr>>8)&0xff,addr&0xff) + +def maskToCidr(mask): + """Convert mask specified by str to net""" + mask = strIpToIntIp(mask) + return 32-int(math.log(((~mask) & 0xffffffff)+1,2)) + +def cidrToMask(cidr): + """Convert net to mask specified by str""" + return intIpToStrIp((2**cidr-1)<<(32-cidr)) + +def strIpToIntIp(addr): + """Convert ip specified by string to integer""" + addr = addr.split('.') + return ((int(addr[0])<<24)| + (int(addr[1])<<16)| + (int(addr[2])<<8)| + (int(addr[3]))) + return reduce(lambda x,y:x+(int(y[1])<<(y[0]*8)), + enumerate(reversed(addr.split("."))),0) + +def getIpNet(ip,mask=None,cidr=None): + """Get net (xx.xx.xx.xx/xx) by ip address and mask""" + ip = strIpToIntIp(ip) + if mask is not None: + net = maskToCidr(mask) + else: + net = int(cidr) + mask = cidrToMask(net) + mask = strIpToIntIp(mask) + return "{ip}/{net}".format(ip=intIpToStrIp(ip&mask), + net=net) diff --git a/pym/cl_utils2.py b/pym/cl_utils2.py new file mode 100644 index 0000000..f0e6dc8 --- /dev/null +++ b/pym/cl_utils2.py @@ -0,0 +1,564 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import struct +import termios +import fcntl +# from . import cl_utils +# from . import cl_profile +import cl_utils +import cl_profile +import ldap +class ldapFun(cl_profile._error): + '''Объект для работы с LDAP сервером + + подключение к серверу и поиск данных + ''' + def __init__(self, dnUser, password, host="localhost"): + self.conLdap = False + # Получаем соединение с LDAP + try: + self.conLdap = self.__ldapConnect(dnUser, password, host) + except ldap.LDAPError as e: + self.setError(str(e)) + + def __ldapConnect(self, dnUser, password, host): + """Соединение с LDAP сервером""" + conLdap = ldap.initialize('ldap://%s'%host, bytes_mode=False) + conLdap.simple_bind_s(dnUser, password) + return conLdap + + def ldapSearch(self,baseDN, searchScope, searchFilter, retrieveAttributes): + try: + ldap_result_id = self.conLdap.search(baseDN, searchScope, + searchFilter, + retrieveAttributes) + result_set = [] + while 1: + result_type, result_data = self.conLdap.result(ldap_result_id, + 0) + if (result_data == []): + break + else: + if result_type == ldap.RES_SEARCH_ENTRY: + result_set.append(result_data) + except ldap.NO_SUCH_OBJECT: + return [] + except: + return False + return result_set + +pcs = cl_utils.prettyColumnStr + +class cl_help: + """Объект для работы со справкой, и обработкой параметров. + + Конструктор __init__ должен определить следующие переменные: + + self.chapter список разделов справки, каждый элементы состоит из + имени раздела, флаг видимый/скрытый, кол-во переводов строк + после названия раздела, количество строк после раздела, + тип раздела + Пример: [("Copyright",False,0,2),"options"] + self.relService словарь связей сервисов и действующих опций + ключ - название сервиса, значение - список отображаемых + разделов отмеченных как "options" + Пример: {"samba":[_("Common options"), + _("Service Samba options")]} + self.relOptions словарь связей длинных опций помощи и выводимых разделов + помощи с опциями + ключ - параметр справки, значение список отображаемых + разделов справки + Пример: {"help-ldap":[_("Common options"), + _("Service LDAP options)]} + self.progName словарь имена используемых программ и их номера для + доступа к переменным + Пример: {'cl-groupadd':0, 'cl-groupdel':1} + self.data список данных для справки, каждый элемент словарь: + progAccess: список номеров программ отображающих + Пример: {'progAccess':(0,), + 'shortOption':"g", + 'longOption':"gid", + 'optVal':"GID", + 'helpChapter':_("Options"), + 'help':_("use GID for the new group") + }, + после заполнения параметров необходимо выполнить + self._cl_help__setParamHelp() для заполнения справки + + """ + def __init__(self, cmdName): + # ширина консоли взята за 80 + # -1 чтобы компенсировать расстрояние между колонками + self.consolewidth = 79 + self.column_width = 32 + self.cmdName = cmdName + #короткие опции командной строки + self.shortOpt = [] + #длинные опции командной строки + self.longOpt = [] + # массив разделов (заполняется в __setParamHelp) + self.chapterBloc = [] + #optEnd = "" + #if "user" in self.cmdName and not "mod" in self.cmdName: + #optEnd = _("user") + #elif "group" in self.cmdName and not "mod" in self.cmdName: + #optEnd = _("group") + #self.__setParamHelp() + + def getChapterNumber(self,NameChapter): + """Получить номер раздела по имени""" + num = 0 + for i in self.chapter: + if i[0] == NameChapter: + return num + num += 1 + return False + + def __setParamHelp(self): + """Внутренняя функция формирования справки по данным + + Перебирает все элементы списка data, проверяет их на доступность + данной программы, разбирает опции на среди data и формирует + для по ним справку. + """ + # сформировать нужное количество блоков раздела + self.chapterBloc = [""] * len(self.chapter) + # + sp = {} + i = 0 + # перебираем все элементы справки собираем элементы опции + # так же формируем разделы не опции + for par in self.data: + # перебираем только те опции, которые принадлежат команде + if self.access(par): + # есть короткая (возможно есть и длинная) + if "shortOption" in par: + sp[par["shortOption"]+":"+par["helpChapter"]] = i + # есть только длинная опция + elif "longOption" in par: + sp[par["longOption"]+":"+par["helpChapter"]] = i + # формирование разделов не опций + else: + helpTxt = par['help'] + numChapter = self.getChapterNumber(par['helpChapter']) + self.addChapterHelp(numChapter,helpTxt) + i += 1 + # перебираем все "собранные" опции + # опции перебираются по порядку в списке date + # для сортировки по ключам следует применить код: + # for index in sorted(sp.keys()): + # par = self.data[sp[index]] + for index in sorted(sp.values()): + par = self.data[index] + numChapter = self.getChapterNumber(par['helpChapter']) + # если есть и короткая и длинная + if "shortOption" in par and "longOption" in par: + paraminfo = "-%s, --%s "%(par["shortOption"],par["longOption"]) + # если есть только короткая + elif "shortOption" in par: + paraminfo = "-%s "%par["shortOption"] + # если только длинная + else: + paraminfo = "--%s "%par["longOption"] + # если указан параметр для опции + if "optVal" in par: + optVal = par["optVal"] + else: + optVal = "" + + # вывод вида: " [-o, ][--option] [PARAM]" "helpstring" + helpTxt = pcs(" "+paraminfo+optVal, self.column_width, \ + par['help'], self.consolewidth-self.column_width) + # добавить строку в нужный раздел + self.addChapterHelp(numChapter,helpTxt) + + def getHelp(self, optionsChapters=False): + """Выдать справку. + + Выдает справку в случае если указан optionsChapters, то фильтрует по + типу разделов. + + Параметры: + optionsChapters Flase или список опциональных разделов для + отображения + + Возвращаемые параметры: + Строка со справкой. + """ + # Выдать справку + help = "" + # перебираем все элементы справочных блоков + iterChapterBloc = iter(self.chapterBloc) + # перебираем все разделы по параметрам + for (nameChapter, visibleChapter, beforeStrChapter, \ + afterStrChapter, typeChapter) in self.chapter: + # получаем следующий блок (т.о. textChapterBloc соответ, chapter) + textChapterBloc = next(iterChapterBloc) + # если тип раздела опциональный + if optionsChapters and typeChapter=="options": + # проверяем нужно ли его отображать + if not (nameChapter in optionsChapters): + continue + bef = "\n" * beforeStrChapter + aft = "\n" * afterStrChapter + # если блок не пустой и раздел отображаемый + if len(textChapterBloc) > 0: + if visibleChapter: + help += nameChapter + ": " + bef + help += textChapterBloc + aft + help = help.rstrip() + "\n" + return help + + def addChapterHelp(self, numChapter, helpTxt): + """Добавить в раздел помощи numChapteк тектстовую строку helpTxt + + Параметры: + numChapter номер раздела в который нужно добавить данные справки + helpTxt строка, содержащая данные + """ + self.chapterBloc[numChapter] += helpTxt + return True + + def addData(self,dataHash): + # На будущее (добавляет опции) + self.data.append(dataHash) + return True + + def handleCheckAccess(self,dataHash): + """Замещаемый дополнительный обработчик проверки + доступности опции. + + Входные параметры: + dataHash элементы списка данных справки (self.data) + """ + return True + + def access(self,dataHash): + """Доступна ли опция вызывающей программе + + Параметры: + dataHash словарь элемент типа self.data + + Возвращаемые параметры: + True/False доступна/недоступна + """ + # доступна ли опция вызывающей программе + # опция без progAccess доступна + numProg = self.progName[self.cmdName] + if 'progAccess' in dataHash: + if numProg in dataHash['progAccess']: + # вызов дополнительной проверки доступа к опции + return self.handleCheckAccess(dataHash) + else: + return False + else: + # вызов дополнительной проверки доступа к опции + return self.handleCheckAccess(dataHash) + + def getTypeChapter(self, nameChapter): + """Получить тип раздела по его имени + + Параметры: + nameChapter название раздела + + Возвращаемые параметры: + строка тип раздела + Flase(Boolean) такой раздел отсутствует + """ + # фильтруем список по имени раздела, помещаем в список тип раздела + filtered = [typeChapter for name, na, na, na, typeChapter \ + in self.chapter if name == nameChapter] + # если среди фильтрованных есть хоть один элемент + if len(filtered) > 0: + # возвращаем - он запрашиваемый + return filtered[0] + else: + # такой раздел отсутствует + return False + + def clearAllOpt(self): + """Очистить все опции, полученные посредством getAllOpt""" + if len(self.shortOpt) > 0: + self.shortOpt = [] + if len(self.longOpt) > 0: + self.longOpt = [] + return True + + def getAllOpt(self,typeOpt="all", optionsChapters=False): + """Получить все доступные опции + + Параметры: + typeOpt 'short'/'long'/'all', вернуть короткие или длинные + опции или все (возвращаются кортежем) + optionsChapters фильтр для опций по типам разделов (список,кортеж) + + Возвращаемые параметры: + строка коротки или список строк длинных опций ('hb:c:wg:G:k:ms:u:') + """ + # Выдать все действующие опции + if typeOpt=="short" or typeOpt=="all": + if len(self.shortOpt) == 0: + for par in self.data: + if optionsChapters and\ + self.getTypeChapter(par['helpChapter'])=="options": + if not (par['helpChapter'] in optionsChapters): + continue + if "shortOption" in par and self.access(par): + if "optVal" in par: + self.shortOpt.append(par["shortOption"]+':') + else: + self.shortOpt.append(par["shortOption"]) + if typeOpt=="long" or typeOpt=="all": + if len(self.longOpt) == 0: + for par in self.data: + if optionsChapters and\ + self.getTypeChapter(par['helpChapter'])=="options": + #print par["longOption"] + if not (par['helpChapter'] in optionsChapters): + continue + if "longOption" in par and self.access(par): + if "optVal" in par: + self.longOpt.append(par["longOption"]+'=') + else: + self.longOpt.append(par["longOption"]) + if typeOpt=="short": + return "".join(self.shortOpt) + elif typeOpt=="long": + return self.longOpt + elif typeOpt=="all": + return ("".join(self.shortOpt),self.longOpt) + + def getShortOpt(self,option): + """Из любой опции получить короткую опцию. + + Фильтрация также происходит и по названию команды. + + Параметры: + option запрашиваемая опция + + Возвращаемые параметры: + короткая опция, если же для длинной опции нет короткой, возвращается + пустая строка. + """ + # Из любой опции получаем короткую опцию + for par in self.data: + if "shortOption" in par and self.access(par): + if ("longOption" in par and\ + par["longOption"] == option) or \ + par["shortOption"] == option: + return par["shortOption"] + break + return "" + +class cl_smartcon(): + + def getconsolewidth(self): + """Получить ширину текущей консоли""" + s = struct.pack("HHHH", 0, 0, 0, 0) + fd_stdout = sys.stdout.fileno() + try: + x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s) + except IOError: + # если ошибка то ширина 80 символов + return 80 + #(rows, cols, x pixels, y pixels) + return struct.unpack("HHHH", x)[1] + + def printRight(self, offsetLeft, offsetRight): + """Добавляет необходимое количество пробелов: + + количество пробелов = (ширина консоли - offsetLeft - offsetRight) + """ + cols = self.getconsolewidth() + for i in range(cols - offsetLeft - offsetRight): + sys.stdout.write(" ") + + def colorPrint(self,attr,fg,bg,string): + """Раскрашивает выводимое сообщение + + Параметры: + attr - это атрибут + fg - цвет символа + bg - цвет фона + + в случае если параметр равен "" то он не изменяется + + attr может принимать следующие значения: + 0 сбросить все атрибуты (вернуться в нормальный режим) + 1 яркий (обычно включает толстый шрифт) + 2 тусклый + 3 подчёркнутый + 5 мигающий + 7 реверсный + 8 невидимый + + fg может принимать следующие значения: + 30 чёрный + 31 красный + 32 зелёный + 33 жёлтый + 34 синий + 35 фиолетовый + 36 голубой + 37 белый + + bg может принимать следующие значения: + 40 чёрный + 41 красный + 42 зелёный + 43 жёлтый + 44 синий + 45 фиолетовый + 46 голубой + 47 белый + """ + lst = [] + if attr: + lst.append(attr) + if fg: + lst.append(fg) + if bg: + lst.append(bg) + sys.stdout.write("\033[%sm%s\033[0m" %(";".join(lst),string)) + + def redBrightPrint(self, string): + """Печатает яркое красное сообщение""" + self.colorPrint("1","31","",string) + + def greenBrightPrint(self, string): + """Печатает яркое зеленое сообщение""" + self.colorPrint("1","32","",string) + + def yellowBrightPrint(self, string): + """Печатает яркое желтое сообщение""" + self.colorPrint("1","33","",string) + + def blueBrightPrint(self, string): + """Печатает яркое cинее сообщение""" + self.colorPrint("1","34","",string) + + def lenString(self, string): + """Получаем длинну строки""" + stringUnicode = cl_utils._toUNICODE(string) + lenString = len(stringUnicode) + return lenString + + + def defaultPrint(self, string): + sys.stdout.write(string) + sys.stdout.flush() + + def printLine(self, argL, argR, offsetL=0, printBR=True): + """Печатает справа и слева консоли цветные сообщения""" + #Допустимые цвета + colorDict = {\ + # цвет по умолчанию + '':self.defaultPrint, + # ярко зеленый + 'greenBr':self.greenBrightPrint, + # ярко голубой + 'blueBr':self.blueBrightPrint, + # ярко красный + 'redBr':self.redBrightPrint, + # ярко желтый + 'yellowBr':self.yellowBrightPrint, + } + # cмещение от левого края консоли + #offsetL = 0 + for color,leftString in argL: + offsetL += self.lenString(leftString) + if color in colorDict: + # печатаем и считаем смещение + colorDict[color](leftString) + else: + colorDict[''](leftString) + # cмещение от правого края консоли + offsetR = 0 + for color,rightString in argR: + offsetR += self.lenString(rightString) + # Добавляем пробелы + if offsetR: + self.printRight(offsetL, offsetR) + for color,rightString in argR: + if color in colorDict: + # печатаем и считаем смещение + colorDict[color](rightString) + else: + colorDict[''](rightString) + if printBR: + print("") + + def printNotOK(self, string, offsetL=0, printBR=True): + """Вывод на печать в случае сбоя""" + self.printLine((('greenBr',' * '), + ('',string), + ), + (('blueBr','['), + ('redBr',' !! '), + ('blueBr',']'), + ), offsetL, printBR) + + def printOnlyNotOK(self, string, offsetL=0, printBR=True): + """Вывод на печать в случае сбоя""" + self.printLine((('', string),), + (('blueBr','['), + ('redBr',' !! '), + ('blueBr',']'), + ), offsetL, printBR) + + def printOK(self, string, offsetL=0, printBR=True): + """Вывод на печать в случае успеха""" + self.printLine((('greenBr',' * '), + ('',string), + ), + (('blueBr','['), + ('greenBr',' ok '), + ('blueBr',']'), + ), offsetL, printBR) + + def printOnlyOK(self, string, offsetL=0, printBR=True): + """Вывод на печать в случае успеха""" + self.printLine((('',string),), + (('blueBr','['), + ('greenBr',' ok '), + ('blueBr',']'), + ), offsetL, printBR) + + def printWARNING(self, string, offsetL=0, printBR=True): + """Вывод на печать предупреждения""" + self.printLine((('yellowBr',' * '), + ('',string), + ), + (('',''), + ), offsetL, printBR) + + def printERROR(self, string, offsetL=0, printBR=True): + """Вывод на печать предупреждения""" + self.printLine((('redBr',' * '), + ('',string), + ), + (('',''), + ), offsetL, printBR) + + def printSUCCESS(self, string, offsetL=0, printBR=True): + """Вывод на печать в случае успеха без [ok] справа""" + self.printLine((('greenBr',' * '), + ('',string), + ), + (('',''), + ), offsetL, printBR) diff --git a/pym/cl_vars.py b/pym/cl_vars.py new file mode 100644 index 0000000..2c3dd2a --- /dev/null +++ b/pym/cl_vars.py @@ -0,0 +1,92 @@ +#-*- coding: utf-8 -*- + +# Copyright 2008-2010 Mir Calculate. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#Допустимые ключи значений +# mode - режим переменной r-не переназначается из командной строки, +# w-переназначается из командной строки +# type - тип переменной состоит из двух элементов(что это и для чего +# это) +# value - значение переменной + +class Data: + + # имя компьютера + os_net_hostname = {'mode':"w"} + # разрешенные сети + os_net_allow = {} + # ip на всех интерфейсах + os_net_ip = {} + + #короткое название системы (CLD) + os_linux_shortname = {} + + #домен + os_net_domain = {'mode':"w"} + + # Пути к ini файлам + cl_env_path = {'value':['/var/calculate/remote/calculate.env', + '/var/calculate/calculate.env', + '/etc/calculate/calculate.env', + '/var/lib/calculate/calculate.env']} + + # локаль (прим: ru_RU.UTF-8) + os_locale_locale = {} + # язык (прим: ru_RU) + os_locale_lang = {} + # язык (прим: ru) + os_locale_language = {} + + # раскладка клавиатуры для X + os_locale_xkb = {} + + # названия используемых раскладок клавиатуры для X + os_locale_xkbname = {} + + # архитектура компьютера (i686,x86_64) + os_arch_machine = {} + + #проход при наложении профилей 1,2,3,4,5 и.т д + cl_pass_step = {'mode':"w"} + + # обрабатываемый файл профиля + cl_pass_file = {'mode':"w"} + + # корневой раздел файловой системы + os_root_dev = {} + + # тип носителя (ram, hdd, usb-hdd, livecd) + os_root_type = {} + + # полное название системы + os_linux_name = {} + + # постфикс к названию системы + os_linux_subname = {} + + # название виртуальной машины (virtualbox, vmware, qemu) + hr_virtual = {} + + # версия системы + os_linux_ver = {} + + # Тип профиля + cl_pass_type = {'mode':"w"} + + # Действие программы + cl_pass_run = {'mode':"w"} + + #Логин пользователя + ur_login = {'mode':"w"} diff --git a/pym/cl_vars_server.py b/pym/cl_vars_server.py index 2eeb339..053967a 100644 --- a/pym/cl_vars_server.py +++ b/pym/cl_vars_server.py @@ -253,24 +253,24 @@ class Data: ld_samba_hash = {} # Директория настроек пользователя windows - sr_samba_winprof_path = {\ - 'value':'/var/calculate/server-data/samba/profiles/win'} + sr_samba_winprof_path = \ + {'value':'/var/calculate/server-data/samba/profiles/win'} # Директория хранения настроек пользователя linux - sr_samba_linprof_path = {\ - 'value':'/var/calculate/server-data/samba/profiles/unix'} + sr_samba_linprof_path = \ + {'value':'/var/calculate/server-data/samba/profiles/unix'} # Домашняя директория - sr_samba_home_path = {\ - 'value':'/var/calculate/server-data/samba/home'} + sr_samba_home_path = \ + {'value':'/var/calculate/server-data/samba/home'} # Директория netlogon - sr_samba_winlogon_path = {\ - 'value':'/var/calculate/server-data/samba/netlogon'} + sr_samba_winlogon_path = \ + {'value':'/var/calculate/server-data/samba/netlogon'} # Директория share - sr_samba_share_path = {\ - 'value':'/var/calculate/server-data/samba/share'} + sr_samba_share_path = \ + {'value':'/var/calculate/server-data/samba/share'} # Настроен или нет сервис Samba sr_samba_set = {'mode':"w", diff --git a/pym/cl_xml.py b/pym/cl_xml.py new file mode 100644 index 0000000..60a8eba --- /dev/null +++ b/pym/cl_xml.py @@ -0,0 +1,1042 @@ +# -*- coding: utf-8 -*- + +# 2015 Calculate Ltd. http://www.calculate-linux.org +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from lxml import etree as ET +from copy import deepcopy + + +def display_xml(xml): + print(xml_to_str(xml)) + +def xml_to_str(xml): + return str(ET.tostring(xml, pretty_print=True), encoding="UTF-8") + +def str_to_xml_doc(text): + return ET.XML(bytes(bytearray(text, encoding="UTF-8"))) + +#backwards compat +class xpath(): + @staticmethod + def Evaluate(xpath, xml): + f = ET.XPath(xpath) + return f(xml) + +#can't add methods to Cython lib. +#have to do this the ugly way +def firstChild(element): + if(element.text): + return element + if(len(element) == 0): + return None + return element[0] + +def insertBefore(elem, new_child, ref_child): + + child_parent = new_child.getparent() + if child_parent is not None: + child_parent.remove(new_child) + if(ref_child is None): + elem.append(new_child) + ref_child.addprevious(new_child) + return new_child + +class xmlShare(): + """Общий класс для объектов XML, наследуем + """ + + def _createElement(self, doc, tag, text="", attributes=None): + """Создание нового XML элемента""" + if not isinstance(attributes, dict): + attributes = {} + element = ET.Element(tag, attributes) + if text: + element.text = text + return element + + +class xmlNode(xmlShare): + """Класс для создания нод без аттрибутов + """ + + def __init__(self): + self.node = None + + def createNode(self, doc, tag, text=""): + """Создает XML элемент без аттрибутов""" + self.node = self._createElement(doc, tag, text) + return self.node + + def getNode(self): + return self.node + + def toxml(self, pretty_print=True): + if(self.node is not None): + return ET.tostring(self.node, encoding="UTF-8", pretty_print=pretty_print) + +class xmlCaption(): + """Класс XML заголовок + + """ + + def __init__(self): + # Заголовок области XML нода + self.caption = False + + def createCaption(self, doc, name, quotes, action=None): + """Создание заголовка области""" + tmpNode = xmlNode() + self.caption = tmpNode.createNode(doc, "caption") + nameNode = tmpNode.createNode(doc, "name", name) + self.caption.append(nameNode) + if action: + actNode = tmpNode.createNode(doc, "action", action) + self.caption.append(actNode) + for q in quotes: + quoteNode = tmpNode.createNode(doc, "quote", q) + self.caption.append(quoteNode) + return self.caption + + def getCaption(self): + """Выдает XML ноду заголовка области""" + return self.caption + + +class xmlField(xmlShare): + """Класс для работы с XML полем + + """ + + def __init__(self): + # XML нода поле + self.field = None + + def createField(self, doc, typeField, quotes, name="", + values=(), action=None): + """Cоздание XML ноды поле""" + self.field = self._createElement(doc, "field", "", {"type": typeField}) + if name: + nameNode = self._createElement(doc, "name", name) + self.field.append(nameNode) + for v in values: + valueNode = self._createElement(doc, "value", v) + self.field.append(valueNode) + if action: + actNode = self._createElement(doc, "action", action) + self.field.append(actNode) + for q in quotes: + quoteNode = self._createElement(doc, "quote", q) + self.field.append(quoteNode) + return self.field + + def toxml(self, pretty_print=True): + if(self.field is not None): + return ET.tostring(self.field, encoding="UTF-8", pretty_print=pretty_print) + + +class xmlFields(): + """Класс, в котором находится список ХМL нод field + + """ + + def __init__(self): + self.fields = [] + + def appendField(self, field): + """Добавить XML ноду field""" + self.fields.append(field) + return self.fields + + def getFields(self): + """Выдать список XML нод""" + return self.fields + + +class xmlArea(): + """Класс для работы с XML областью + + """ + + def __init__(self): + # Область + self.area = None + + def createArea(self, doc, xmlCaption, xmlFields): + """Создание XML области""" + tmpNode = xmlNode() + self.area = tmpNode.createNode(doc, "area") + if xmlCaption and xmlCaption.getCaption() is not None: + self.area.append(xmlCaption.getCaption()) + if xmlFields: + fields = xmlFields.getFields() + for field in fields: + self.area.append(field) + return self.area + + +class xmlDoc(): + """Класс для работы с XML документом + + """ + + def __init__(self): + # документ + self.doc = None + # главная нода + self.root = None + # тело документа + self.body = None + # Заголовок области - временный (в реальности один объект заголовок) + self.tmpCaption = None + # Поля - временные (в реальности один объект поля) + self.tmpFields = None + # Разделитель областей - по умолчанию перевод строки "\n" + self.sepAreas = None + # Разделитель разделенных списков - по умолчанию перевод строки "\n" + # self.sepSplitFields = False + + def toxml(self, pretty_print=True): + if(self.doc is not None): + return ET.tostring(self.doc, encoding="UTF-8", pretty_print=pretty_print) + + def createDoc(self, typeDoc, version): + """Создание нового документа новый документ""" + docTxt = ('' + '{version}' + '{type_doc}' + ''.format(version=version, + type_doc=typeDoc)) + # self.doc = minidom.parseString(docTxt) + # self.root = self.doc.documentElement + # self.body = xpath.Evaluate('child::body', self.root)[0] + + self.doc = str_to_xml_doc(docTxt) + self.root = self.doc + self.body = xpath.Evaluate('child::body', self.root)[0] + # установка разделителя областей + self.sepAreas = self.createField("br", [], "", [], False, False) + # установка разделителя областей разделенных списков + # self.sepSplitFields = self.createField("br",[],"",[],False,False) + return self.doc + + def addField(self, field): + """Добавляет поле во временный список + + Из этого списка в дальнейшем формируется XML область + """ + if not self.tmpFields: + self.tmpFields = xmlFields() + self.tmpFields.appendField(field) + + def createCaption(self, name, quotes, action=False): + """Cоздает заголовок области + + Помещает заголовок в временный артибут + Используется при создании области + """ + self.tmpCaption = xmlCaption() + return self.tmpCaption.createCaption(self.doc, name, quotes, action) + + def createField(self, typeField, quotes=(), name="", + values=(), action=False, addTmpField=True): + """Cоздает поле + + Если установлена переменнная addTmpField + добавляет поле во временный список + """ + fieldObj = xmlField() + field = fieldObj.createField(self.doc, typeField, quotes, name, + values, action) + if addTmpField: + self.addField(field) + return field + + def clearTmpFields(self): + """Очищает временный список""" + self.tmpFields = False + + def createArea(self): + """Cоздает область + + Область создается на основании временного атрибута и временного списка + """ + areaObj = xmlArea() + area = areaObj.createArea(self.doc, self.tmpCaption, self.tmpFields) + self.clearTmpCaptionAndFields() + return area + + def clearTmpCaptionAndFields(self): + """Очищает временный аттрибут и временный список""" + self.tmpCaption = False + self.tmpFields = False + + def getNodeRoot(self): + """Выдает корневую ноду""" + return self.root + + def getNodeBody(self): + """Выдает ноду body""" + return self.body + + def setActionField(self, xmlField, actionTxt): + """Устанавливает свойство action для XML поля""" + xmlActions = xpath.Evaluate('child::action', xmlField) + if xmlActions and firstChild(xmlActions[0]) is not None: + firstChild(xmlActions[0]).text = actionTxt + else: + nodeObj = xmlNode() + newNode = nodeObj.createNode(self.doc, "action", actionTxt) + xmlField.append(newNode) + + def setActionArea(self, xmlArea, actionTxt): + """Устанавливает свойство action для XML области""" + xmlActions = xpath.Evaluate('child::caption/action', xmlArea) + xmlCaptions = xpath.Evaluate('child::caption', xmlArea) + if xmlActions and firstChild(xmlActions[0]) is not None: + firstChild(xmlActions[0]).text = actionTxt + else: + if xmlCaptions: + nodeObj = xmlNode() + newNode = nodeObj.createNode(self.doc, "action", actionTxt) + xmlCaptions[0].append(newNode) + + def joinField(self, xmlArea, xmlNewField): + """Объединяет XML ноду область и XML ноду поле""" + newNameField = self.getNameField(xmlNewField) + if not newNameField or not newNameField.strip(): + return False + fieldsOldComp = xpath.Evaluate("child::field[child::name='%s']" \ + % newNameField, xmlArea) + # Если поле не найдено добавляем его + typeNewField = self.getTypeField(xmlNewField) + if not fieldsOldComp and typeNewField != "seplist": + if self.getActionField(xmlNewField) != "drop": + self.setActionField(xmlNewField, "append") + xmlArea.append(xmlNewField) + return True + newFieldsAction = self.getActionField(xmlNewField) + newValues = self.getFieldValues(xmlNewField) + flagCompare = True + + for nodeFieldOld in fieldsOldComp: + if newFieldsAction == "drop": + if nodeFieldOld.getnext() is not None and \ + self.getTypeField( + nodeFieldOld.getnext()) == "br": + xmlArea.remove(nodeFieldOld.getnext()) + elif nodeFieldOld.getprevious() is not None and \ + self.getTypeField( + nodeFieldOld.getprevious()) == "br": + xmlArea.remove(nodeFieldOld.getprevious()) + xmlArea.remove(nodeFieldOld) + continue + oldValues = self.getFieldValues(nodeFieldOld) + # Сравнение значений переменной шаблона и файла + if set(newValues) != set(oldValues): + flagCompare = False + if self.getActionField(xmlNewField) == "drop": + return True + appSplLst = [] + insSplLst = [] + if typeNewField == "seplist": + if fieldsOldComp: + xmlOldField = fieldsOldComp[-1] + else: + xmlOldField = None + seplistNewXML = self.getSepListToField(xmlNewField) + if seplistNewXML: + for nodeSeplist in seplistNewXML: + if self.getActionField(nodeSeplist) != "drop": + if newFieldsAction == "join": + flagCompareSeplist = False + newValues = self.getFieldValues(nodeSeplist) + for nodeFieldOld in fieldsOldComp: + oldValues = self.getFieldValues(nodeFieldOld) + for newValue in newValues: + if newValue in oldValues: + flagCompareSeplist = True + break + if not flagCompareSeplist: + nextNode = xmlOldField.getnext() + newInsNode = deepcopy(nodeSeplist) + self.setActionField(newInsNode, "append") + + if nextNode is not None: + appSplLst.append((newInsNode, + nextNode, + "insert")) + else: + appSplLst.append((newInsNode, + False, + "append")) + else: + newInsNode = deepcopy(nodeSeplist) + if self.getActionField(newInsNode) == "join": + self.setActionField(newInsNode, "append") + if xmlOldField is not None: + insSplLst.append((newInsNode, + xmlOldField, + "insert")) + else: + insSplLst.append((newInsNode, + False, + "append")) + + # xmlArea.insertBefore(\ + # nodeSeplist.cloneNode(True), + # xmlOldField) + + parentNode = nodeSeplist.getparent() + parentNode.remove(nodeSeplist) + + insNodesRepl = [] + for newNode, nxtNode, app in insSplLst: + flagCompareSeplist = False + newValues = self.getFieldValues(newNode) + for nodeRepl, nxtNode_, app_ in insNodesRepl: + nxtNode, app = nxtNode_, app_ + oldValues = self.getFieldValues(nodeRepl) + for newValue in newValues: + if newValue in oldValues: + flagCompareSeplist = True + break + if not flagCompareSeplist: + if xmlOldField is not None: + insNodesRepl.append((newNode, nxtNode, app)) + + for newNode, nxtNode, app in insNodesRepl: + if app == "insert": + insertBefore(xmlArea, newNode, nxtNode) + elif app == "append": + xmlArea.append(newNode) + if xmlOldField is not None: + parentNode = xmlOldField.getparent() + if parentNode is not None and newFieldsAction != "join": + parentNode.remove(xmlOldField) + + for newNode, nxtNode, app in appSplLst: + if app == "insert": + insertBefore(xmlArea, newNode, nxtNode) + elif app == "append": + xmlArea.append(newNode) + + if not flagCompare and typeNewField != "seplist": + # Устанавливаем action=replace + self.setActionField(xmlNewField, "replace") + # Если параметры поля не сходятся заменяем поле + xmlArea.replace(fieldsOldComp[-1], deepcopy(xmlNewField)) + + if newFieldsAction == "join": + fieldsOldRemove = [] + else: + fieldsOldRemove = fieldsOldComp[:-1] + + for nodeFieldOld in fieldsOldRemove: + actionOldNode = self.getActionField(nodeFieldOld) + if actionOldNode == "insert" or actionOldNode == "append": + pass + else: + if nodeFieldOld.getnext() is not None and \ + self.getTypeField( + nodeFieldOld.getnext()) == "br": + xmlArea.remove(nodeFieldOld.getnext()) + xmlArea.remove(nodeFieldOld) + return True + + def getSepListToField(self, xmlField): + """Выдает элементы распределенного массива + + Область предок поля, в этой области ищутся + элементы распределенного массива + """ + nameField = self.getNameField(xmlField) + if not nameField: + return [] + parentNode = xmlField.getparent() + if parentNode is not None: + fieldsVal = xpath.Evaluate( + "child::field[attribute::type='seplist'][child::name='%s'] " \ + % nameField, parentNode) + return fieldsVal + else: + return [] + + def removeComment(self, xmlArea): + """Удаляет комментарии в XML области""" + fieldNodes = xpath.Evaluate('descendant::field', xmlArea) + for fieldNode in fieldNodes: + if "type" in fieldNode.keys(): + if fieldNode.get("type") == "comment" or \ + fieldNode.get("type") == "br": + parentNode = fieldNode.getparent() + parentNode.remove(fieldNode) + else: + if self.getActionField(fieldNode) == "drop": + pass + elif self.getActionField(fieldNode) == "join": + pass + else: + self.setActionField(fieldNode, "append") + + def joinBody(self, baseBody, newBody): + """Объединяет две области Body""" + newFields = xpath.Evaluate('child::field', newBody) + xmlNewAreas = xpath.Evaluate('child::area', newBody) + for i, xmlNewArea in enumerate(xmlNewAreas): + self.joinArea(baseBody, xmlNewArea) + joinNewFields = xpath.Evaluate("child::field[child::action='join']", + newBody) + self.addNewFielsOldArea(newFields, joinNewFields, baseBody) + + def getRemoveNodeSepList(self, removeNodesDict, baseNode, xmNewlField): + """Находит элементы разделенного списка + + Параметры: + removeNodesDict - Cловарь удаляемых полей разделенного списка + формируется программой + baseNode - Нода в которой идет поиск + xmNewlField - Нода field которая проверяется на принадлежность + к разделенному списку + """ + flagNewNodeSeplist = False + if self.getTypeField(xmNewlField) == "seplist": + flagNewNodeSeplist = True + nameNewField = self.getNameField(xmNewlField) + if nameNewField: + if nameNewField in removeNodesDict: + return removeNodesDict[nameNewField] + else: + oldFields = xpath.Evaluate('child::field', baseNode) + removeNodes = [] + lenOldFields = len(oldFields) + for i in range(lenOldFields): + oldNode = oldFields[i] + flagSep = self.getTypeField(oldNode) == "seplist" + if flagNewNodeSeplist: + flagSep = True + if flagSep and \ + nameNewField == self.getNameField(oldNode): + removeNodes.append(oldNode) + if i + 1 < lenOldFields: + nextNode = oldFields[i + 1] + if self.getTypeField(nextNode) == "br": + removeNodes.append(nextNode) + removeNodesDict[nameNewField] = removeNodes + return removeNodes + + def addNewFielsOldArea(self, newFields, joinNewFields, xmlOldArea): + """Добавляет новые XML поля в область шаблона""" + removeNodesDict = {} + notRemoveNodesDict = {} + for notRemNode in joinNewFields: + nameField = self.getNameField(notRemNode) + if nameField not in notRemoveNodesDict: + notRemoveNodesDict[nameField] = [] + notRemoveNodesDict[nameField].append(notRemNode) + else: + notRemoveNodesDict[nameField].append(notRemNode) + notSepListField = [] + sepListField = [] + for nField in newFields: + if self.getRemoveNodeSepList(removeNodesDict, xmlOldArea, + nField): + sepListField.append(nField) + else: + if self.getNameField(nField): + notSepListField.append(nField) + for name in notRemoveNodesDict: + if name in removeNodesDict: + removeNodesDict[name] = [] + for removeNodes in removeNodesDict.values(): + if removeNodes: + if self.getTypeField(removeNodes[-1]) == "seplist": + removeNodes = removeNodes[:-1] + else: + removeNodes = removeNodes[:-2] + + for removeNode in removeNodes: + xmlOldArea.remove(removeNode) + for node in sepListField: + node.set("type", "seplist") + if not (self.getActionField(node) == "join" or + self.getActionField(node) == "drop"): + self.setActionField(node, "insert") + self.joinField(xmlOldArea, node) + for node in notSepListField: + if self.getTypeField(node) == "seplist": + self.setActionField(node, "append") + xmlOldArea.append(node) + else: + self.joinField(xmlOldArea, node) + + def insertBeforeSepAreas(self, xmlArea): + """Добавляет разделитель областей перед каждой областью""" + if self.sepAreas is None: + return False + areaNodes = xpath.Evaluate('descendant::area', xmlArea) + for areaNode in areaNodes: + prevNode = areaNode.getprevious() + if prevNode is not None: + parentNode = areaNode.getparent() + insertBefore(parentNode, deepcopy(self.sepAreas), + areaNode) + return True + + def getAreaFields(self, nameArea, xmlArea, allVars=False): + """По имени области выводит названия и значения всех переменных + + поиск ведется только в 1-х потомках области xmlArea + на выход словарь переменных {имя:значение} + """ + namesAreaCompareAll = xpath.Evaluate( + "child::area/child::caption[child::name='%s']" % nameArea, + xmlArea) + if not namesAreaCompareAll: + return False + dictVar = {} + for namesAreaCompare in namesAreaCompareAll: + fields = xpath.Evaluate("child::field/child::name", + namesAreaCompare.getparent()) + for fieldName in fields: + nodeField = fieldName.getparent() + fieldValue = xpath.Evaluate("child::value", nodeField) + name = firstChild(fieldName).text + value = "" + if fieldValue and firstChild(fieldValue[0]) is not None: + value = firstChild(fieldValue[0]).text + dictVar[name] = value + if not allVars: + break + return dictVar + + def getAreaFieldValues(self, nameArea, nameField, xmlArea): + """По имени области и имени переменной выводит значениe переменной + + поиск ведется только в 1-х потомках области xmlArea + """ + namesAreaComare = xpath.Evaluate( + "child::area/child::caption[child::name='%s']" % nameArea, + xmlArea) + fieldsVal = False + for areaComp in namesAreaComare: + fieldsVal = xpath.Evaluate( + "child::field[child::name='%s'] " + % nameField, areaComp.getparent()) + if fieldsVal: + break + if not fieldsVal: + return False + fieldValue = xpath.Evaluate("child::value", + fieldsVal[0]) + if not fieldValue: + return False + if firstChild(fieldValue[0]) is not None: + return firstChild(fieldValue[0]).text + else: + return "" + + def getAllAreas(self): + """Выдает все области""" + return xpath.Evaluate('descendant::area', self.body) + + def getArea(self, nameArea, xmlArea): + """По имени области находит области (первый потомок xmlArea)""" + namesAreaComare = xpath.Evaluate( + "child::area/child::caption[child::name='%s']" % nameArea, + xmlArea) + return [x.getparent() for x in namesAreaComare] + + + def joinArea(self, baseNode, xmlNewArea): + """Объединяет область c областью Body (xmlNewArea c baseNode)""" + + def appendArea(baseNode, xmlNewArea): + fieldsRemove = xpath.Evaluate( + "descendant::field[child::action='drop']", xmlNewArea) + for rmNode in fieldsRemove: + parentNode = rmNode.getparent() + parentNode.remove(rmNode) + captionAreasRemove = xpath.Evaluate( + "descendant::area/child::caption[child::action='drop']", + xmlNewArea) + for rmNodeCapt in captionAreasRemove: + rmNode = rmNodeCapt.getparent() + parentNode = rmNode.getparent() + parentNode.remove(rmNode) + self.setActionArea(xmlNewArea, "append") + # Добавляем разделитель областей во вложенные области + areaNodes = xpath.Evaluate('descendant::area', xmlNewArea) + for areaNode in areaNodes: + self.setActionArea(areaNode, "append") + parentNode = areaNode.getparent() + insertBefore(parentNode, deepcopy(self.sepAreas), + areaNode) + baseNode.append(xmlNewArea) + # Добавляем разделитель областей + insertBefore(baseNode, deepcopy(self.sepAreas), xmlNewArea) + + nodesNames = xpath.Evaluate('child::area/caption/name', baseNode) + nodesNewArea = xpath.Evaluate('child::caption/name', xmlNewArea) + if not nodesNames: + # Добавляем область + if nodesNewArea: + newAreaAction = self.getActionArea(xmlNewArea) + if not (newAreaAction == "drop" or newAreaAction == "replace"): + appendArea(baseNode, xmlNewArea) + return True + if not nodesNames or not nodesNewArea: + return False + nameArea = "" + if firstChild(nodesNewArea[0]) is not None: + nameArea = firstChild(nodesNewArea[0]).text.strip() + flagFindArea = False + newAreaAction = None + baseNodes = [] + for oName in nodesNames: + newAreaAction = self.getActionArea(xmlNewArea) + oArea = oName.getparent().getparent() + oNameTxt = "" + + if firstChild(oName) is not None: + + oNameTxt = firstChild(oName).text + if nameArea == oNameTxt: + flagFindArea = True + # При использовании удаления + if newAreaAction == "drop": + prevNode = oName.getparent().getparent().getprevious() + removePrevNodes = [] + while prevNode and self.getTypeField(prevNode) == "br": + removePrevNodes.append(prevNode) + prevNode = prevNode.getprevious() + for removeNode in removePrevNodes: + baseNode.remove(removeNode) + baseNode.remove(oName.getparent().getparent()) + continue + elif newAreaAction == "replace": + oldAreaNode = oName.getparent().getparent() + newAreaCaption = xpath.Evaluate('child::caption', + xmlNewArea)[0] + oldAreaCaption = xpath.Evaluate('child::caption', + oldAreaNode)[0] + if newAreaCaption and oldAreaCaption: + #its was "replace(old, new)" in legacy code, even though + #the func takes (new, old). Mistake, or on purpose? + #xmlNewArea.replaceChild(oldAreaCaption, newAreaCaption) + + xmlNewArea.replace(newAreaCaption, oldAreaCaption) + self.setActionArea(xmlNewArea, "replace") + baseNode.replace(oldAreaNode, xmlNewArea) + continue + baseNodes.append(oName.getparent().getparent()) + newFields = xpath.Evaluate('child::field', xmlNewArea) + + joinNewFields = xpath.Evaluate( + "child::field[child::action='join']", + xmlNewArea) + self.addNewFielsOldArea(newFields, joinNewFields, oArea) + + if not flagFindArea: + # Добавляем область + if not (newAreaAction == "drop" or newAreaAction == "replace"): + appendArea(baseNode, xmlNewArea) + else: + tmpXmlNewAreas = xpath.Evaluate('child::area', xmlNewArea) + for na in tmpXmlNewAreas: + for bn in baseNodes: + self.joinArea(bn, na) + return True + + def joinDoc(self, xmlNewDoc): + """Объединяет два документа""" + newRootNode = xmlNewDoc.getroottree().getroot() + newBodyNode = xpath.Evaluate('child::body', newRootNode)[0] + # newImportBodyNode = self.doc.importNode(newBodyNode, True) + newImportBodyNode = deepcopy(newBodyNode) + # Перед объединение области с документом + # удаляем комментарии + + self.removeComment(newImportBodyNode) + self.joinBody(self.body, newImportBodyNode) + # расставляем BR + self.insertBRtoBody(self.body) + + def getQuoteField(self, xmlField): + """Выдает текст из поля""" + xmlQuotes = xpath.Evaluate('child::quote', xmlField) + br = "" + if (xmlField.get("type") == "br"): + br = "\n" + if xmlQuotes: + field = xmlQuotes[0] + if firstChild(field) is not None: + return firstChild(field).text + br + return "" + br + + def getFieldsArea(self, xmlArea): + """Выдает потомков XML области""" + xmlFields = [] + childNodes = list(xmlArea) + for node in childNodes: + # if node.nodeType == node.ELEMENT_NODE: + if node.tag == "area" or node.tag == "field": + xmlFields.append(node) + return xmlFields + + def getTypeField(self, xmlField): + """Выдает тип поля""" + return xmlField.get("type") + + def getNameField(self, xmlField): + """Выдает имя поля""" + xmlNameFields = xpath.Evaluate('child::name', xmlField) + if xmlNameFields and firstChild(xmlNameFields[0]) is not None: + return firstChild(xmlNameFields[0]).text + else: + return False + + def getNameArea(self, xmlArea): + """Выдает имя области""" + xmlNameAreas = xpath.Evaluate('child::caption/name', xmlArea) + if xmlNameAreas and firstChild(xmlNameAreas[0]) is not None: + return firstChild(xmlNameAreas[0]).text + else: + return False + + def xmlToText(self, xmlAreas, text): + """Преобразует список XML областей в текст""" + + def getQuotesArea(xmlArea): + quotes = [] + xmlQuotes = xpath.Evaluate('child::caption/quote', xmlArea) + for node in xmlQuotes: + if firstChild(node) is not None: + quotes.append(firstChild(node).text) + if len(quotes) == 0: + quotes.append("") + quotes.append("") + elif len(quotes) == 1: + quotes.append("") + return quotes + + for i in xmlAreas: + if i.tag == "area": + quotesI = getQuotesArea(i) + startAreaI = quotesI[0] + endAreaI = quotesI[1] + text.append(startAreaI) + xmlFieldsI = self.getFieldsArea(i) + for f in xmlFieldsI: + if f.tag == "area": + quotesF = getQuotesArea(f) + startAreaF = quotesF[0] + endAreaF = quotesF[1] + text.append(startAreaF) + xmlFieldsF = self.getFieldsArea(f) + self.xmlToText(xmlFieldsF, text) + text.append(endAreaF) + else: + fieldF = self.getQuoteField(f) + text.append(fieldF) + text.append(endAreaI) + else: + fieldI = self.getQuoteField(i) + text.append(fieldI) + + def getActionField(self, xmlField): + """Выдает свойство action XML поля""" + xmlActions = xpath.Evaluate('child::action', xmlField) + if xmlActions and firstChild(xmlActions[0]) is not None: + return firstChild(xmlActions[0]).text + else: + return False + + def getFieldValues(self, xmlField): + """Выдает значения XML поля в виде массива""" + vals = [] + xmlValues = xpath.Evaluate('child::value', xmlField) + if xmlValues: + for node in xmlValues: + if firstChild(node) is not None: + vals.append(firstChild(node).text) + return vals + + def getActionArea(self, xmlArea): + """Выдает свойство action XML области""" + xmlActions = xpath.Evaluate('child::caption/action', xmlArea) + if xmlActions and firstChild(xmlActions[0]) is not None: + return firstChild(xmlActions[0]).text + else: + return False + + def delActionNodeArea(self, xmlArea): + """Удаляет свойство action XML области""" + xmlActions = xpath.Evaluate('child::caption/action', xmlArea) + if xmlActions and firstChild(xmlActions[0]) is not None: + parentNode = xmlActions[0].getparent() + parentNode.remove(xmlActions[0]) + return True + else: + return False + + def delActionNodeField(self, xmlField): + """Удаляет свойство action XML поля""" + xmlActions = xpath.Evaluate('child::action', xmlField) + if xmlActions and firstChild(xmlActions[0]) is not None: + parentNode = xmlActions[0].getparent() + parentNode.remove(xmlActions[0]) + return True + else: + return False + + # Создает распределенные списки + def postParserListSeplist(self, xmlArea): + """Создает распределенные списки из элементов области""" + # Потомки + childNodes = self.getFieldsArea(xmlArea) + # содержит списки нод полей с одинаковыми именами в одной области + fieldsSeplist = {} + for node in childNodes: + if node.tag == "area": + self.postParserListSeplist(node) + else: + fieldName = False + xmlFieldNameNodes = xpath.Evaluate('child::name', node) + if xmlFieldNameNodes and firstChild(xmlFieldNameNodes[0]) is not None: + fieldName = firstChild(xmlFieldNameNodes[0]).text + if fieldName: + if fieldName in fieldsSeplist: + fieldsSeplist[fieldName].append(node) + else: + fieldsSeplist[fieldName] = [] + fieldsSeplist[fieldName].append(node) + for listNodes in fieldsSeplist.values(): + if len(listNodes) > 1: + for node in listNodes: + node.set("type", "seplist") + + def insertBRtoBody(self, xmlArea): + """Добавляет необходимые переводы строк + """ + # Потомки + childNodes = self.getFieldsArea(xmlArea) + # нода BR + fieldXMLBr = self.createField("br", [], "", [], False, False) + + # Предыдущая нода + lastNode = None + lenChildNodes = len(childNodes) + for i in range(lenChildNodes): + node = childNodes[i] + lastTmpNode = node + # Нода area + if node.tag == "area": + if self.getActionArea(node) == "append" or \ + self.getActionArea(node) == "join": + self.delActionNodeArea(node) + if lastNode is not None and lastNode.get("type") == "br" or \ + lastNode is not None and lastNode.get("type") == "comment": + indNext = i + 1 + if indNext == lenChildNodes: + xmlArea.append(deepcopy(fieldXMLBr)) + else: + nextNode = childNodes[indNext] + lastTmpNode = insertBefore(xmlArea, + deepcopy(fieldXMLBr), + nextNode) + else: + insertBefore(xmlArea, deepcopy(fieldXMLBr), + node) + self.insertBRtoBody(node) + # Нода field + else: + if self.getActionField(node) == "append" or \ + self.getActionField(node) == "join": + self.delActionNodeField(node) + if lastNode is not None and lastNode.get("type") == "br" or \ + lastNode is not None and lastNode.get("type") == "comment": + indNext = i + 1 + if indNext == lenChildNodes: + xmlArea.append(deepcopy(fieldXMLBr)) + else: + nextNode = childNodes[indNext] + lastTmpNode = insertBefore(xmlArea, + deepcopy(fieldXMLBr), + nextNode) + else: + insertBefore(xmlArea, deepcopy(fieldXMLBr), node) + lastNode = lastTmpNode + + def postParserList(self): + """Находит подходящие XML области и делаем из них поля-массивы""" + xmlAreas = xpath.Evaluate('descendant::area', self.body) + for xmlArea in xmlAreas: + flagListXml = True + fieldValues = [] + xmlFields = xpath.Evaluate('child::field', xmlArea) + if not xmlFields: + flagListXml = False + lenXmlFields = len(xmlFields) + lenBrArea = 0 + for xmlField in xmlFields: + xmlNames = xpath.Evaluate('child::name', xmlField) + xmlVals = xpath.Evaluate('child::value', xmlField) + # if "type" in xmlField.keys() and \ + # xmlField.get("type") == "br": + if xmlField.get("type") == "br": + lenBrArea += 1 + continue + if not xmlNames and not xmlVals: + flagListXml = False + break + if xmlNames and firstChild(xmlNames[0]) is not None and \ + firstChild(xmlNames[0]).text: + flagListXml = False + break + if not (xmlVals and firstChild(xmlVals[0]) is not None and + firstChild(xmlVals[0]).text): + flagListXml = False + break + else: + fieldValues.append(firstChild(xmlVals[0]).text) + + if lenXmlFields == lenBrArea: + flagListXml = False + if flagListXml: + nameNode = xpath.Evaluate('child::caption/name', xmlArea)[0] + fieldName = "" + if firstChild(nameNode) is not None: + fieldName = firstChild(nameNode).text + listArea = [] + self.xmlToText([xmlArea], listArea) + fieldQuote = "".join(listArea) + fieldXMLBr = False + if fieldQuote and fieldQuote[-1] == "\n": + fieldQuote = fieldQuote[:-1] + fieldXMLBr = self.createField("br", [], "", [], False, + False) + fieldXML = self.createField("list", + [fieldQuote], + fieldName, fieldValues, + False, False) + areaAction = self.getActionArea(xmlArea) + if areaAction: + self.setActionField(fieldXML, areaAction) + parentNode = xmlArea.getparent() + insertBefore(parentNode, fieldXML, xmlArea) + if fieldXMLBr: + insertBefore(parentNode, fieldXMLBr, xmlArea) + parentNode.remove(xmlArea) diff --git a/scripts/cl-dhcp-hostadd b/scripts/cl-dhcp-hostadd index 1807d2a..b23cacc 100644 --- a/scripts/cl-dhcp-hostadd +++ b/scripts/cl-dhcp-hostadd @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление статического хоста в DHСP diff --git a/scripts/cl-dhcp-hostdel b/scripts/cl-dhcp-hostdel index cdded4e..c6928c1 100644 --- a/scripts/cl-dhcp-hostdel +++ b/scripts/cl-dhcp-hostdel @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Удаление статического хоста diff --git a/scripts/cl-dhcp-hostmod b/scripts/cl-dhcp-hostmod index 10caf46..f4542a9 100644 --- a/scripts/cl-dhcp-hostmod +++ b/scripts/cl-dhcp-hostmod @@ -29,8 +29,8 @@ if __name__ == "__main__": optObj = cl_ldap.tsOpt(ldapObj,[],False,False,True) flagError = False # Вывод помощи если нет параметров командной строки - if not optObj.opt and optObj.params.has_key('service'): - print ldapObj.getHelp(ldapObj.relOptions['h']) + if not optObj.opt and 'service' in optObj.params: + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Модификация сети diff --git a/scripts/cl-dhcp-netadd b/scripts/cl-dhcp-netadd index dc1981e..38f3f58 100644 --- a/scripts/cl-dhcp-netadd +++ b/scripts/cl-dhcp-netadd @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление cети diff --git a/scripts/cl-dhcp-netdel b/scripts/cl-dhcp-netdel index 35b31e6..b1eb435 100644 --- a/scripts/cl-dhcp-netdel +++ b/scripts/cl-dhcp-netdel @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Удаление сети diff --git a/scripts/cl-dhcp-netmod b/scripts/cl-dhcp-netmod index 66243a0..c6c0ff2 100644 --- a/scripts/cl-dhcp-netmod +++ b/scripts/cl-dhcp-netmod @@ -30,8 +30,8 @@ if __name__ == "__main__": optObj = cl_ldap.tsOpt(ldapObj,[],False,False,True) flagError = False # Вывод помощи если нет параметров командной строки - if not optObj.opt and optObj.params.has_key('service'): - print ldapObj.getHelp(ldapObj.relOptions['h']) + if not optObj.opt and 'service' in optObj.params: + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Модификация сети diff --git a/scripts/cl-dns-recadd b/scripts/cl-dns-recadd index ea697d7..06fcfc3 100644 --- a/scripts/cl-dns-recadd +++ b/scripts/cl-dns-recadd @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-dns-recdel b/scripts/cl-dns-recdel index 20f3d6a..232f7d4 100644 --- a/scripts/cl-dns-recdel +++ b/scripts/cl-dns-recdel @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-dns-recmod b/scripts/cl-dns-recmod index 2d759fc..700ec2e 100644 --- a/scripts/cl-dns-recmod +++ b/scripts/cl-dns-recmod @@ -30,8 +30,8 @@ if __name__ == "__main__": optObj = cl_ldap.tsOpt(ldapObj,[],False,False,True) flagError = False # Вывод помощи если нет параметров командной строки - if not optObj.opt and optObj.params.has_key('service'): - print ldapObj.getHelp(ldapObj.relOptions['h']) + if not optObj.opt and 'service' in optObj.params: + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-dns-zoneadd b/scripts/cl-dns-zoneadd index 24f9290..b54913d 100644 --- a/scripts/cl-dns-zoneadd +++ b/scripts/cl-dns-zoneadd @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-dns-zonedel b/scripts/cl-dns-zonedel index a3fa8a5..d7d30e6 100644 --- a/scripts/cl-dns-zonedel +++ b/scripts/cl-dns-zonedel @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-dns-zonemod b/scripts/cl-dns-zonemod index e1c0a46..03abafc 100644 --- a/scripts/cl-dns-zonemod +++ b/scripts/cl-dns-zonemod @@ -31,7 +31,7 @@ if __name__ == "__main__": flagError = False # Вывод помощи если нет параметров командной строки if not optObj.opt: - print ldapObj.getHelp(ldapObj.relOptions['h']) + print(ldapObj.getHelp(ldapObj.relOptions['h'])) optObj.flagHelp = True if not optObj.flagHelp: # Добавление записи в DNS diff --git a/scripts/cl-groupadd b/scripts/cl-groupadd index eedf35d..561e15f 100644 --- a/scripts/cl-groupadd +++ b/scripts/cl-groupadd @@ -30,8 +30,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-groupadd") optObj = cl_ldap.tsOpt(ldapObj,['group']) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and \ - optObj.params.has_key('group'): + if not optObj.flagHelp and 'service' in optObj.params and \ + 'group' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() diff --git a/scripts/cl-groupdel b/scripts/cl-groupdel index 9fa2222..c9ffe6d 100644 --- a/scripts/cl-groupdel +++ b/scripts/cl-groupdel @@ -29,8 +29,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-groupdel") optObj = cl_ldap.tsOpt(ldapObj,['group']) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('group'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'group' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() @@ -38,7 +38,7 @@ if __name__ == "__main__": if obj.delGroupUnixServer(optObj.params['group'], optObj.opt): flagError = False - elif optObj.params['service'] == "samba": + elif optObj.params['service'] == "samba": obj = cl_ldap.servSamba() # Удаляем группу if obj.delGroupSambaServer(optObj.params['group'], diff --git a/scripts/cl-groupmod b/scripts/cl-groupmod index 4627c11..362d90d 100644 --- a/scripts/cl-groupmod +++ b/scripts/cl-groupmod @@ -29,8 +29,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-groupmod") optObj = cl_ldap.tsOpt(ldapObj,['group'],True,True) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('group'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'group' in optObj.params: if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() # Модифицируем группу diff --git a/scripts/cl-info b/scripts/cl-info index 2ab346e..2536a47 100644 --- a/scripts/cl-info +++ b/scripts/cl-info @@ -29,7 +29,7 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-info") optObj = cl_ldap.tsOpt(ldapObj,[]) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ + if not optObj.flagHelp and 'service' in optObj.params and\ not optObj.errorOpt: # Информация о сервисах и пользователях flagError = True diff --git a/scripts/cl-passwd b/scripts/cl-passwd index 2648002..fe14b80 100644 --- a/scripts/cl-passwd +++ b/scripts/cl-passwd @@ -29,8 +29,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-passwd") optObj = cl_ldap.tsOpt(ldapObj,['user']) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('user'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'user' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() diff --git a/scripts/cl-replication b/scripts/cl-replication index ad66d02..1c5c4e3 100644 --- a/scripts/cl-replication +++ b/scripts/cl-replication @@ -29,7 +29,7 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-replication") optObj = cl_ldap.tsOpt(ldapObj,[]) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ + if not optObj.flagHelp and 'service' in optObj.params and\ not optObj.errorOpt: # Настройка сервера LDAP flagError = True diff --git a/scripts/cl-setup b/scripts/cl-setup index da84b81..5765713 100644 --- a/scripts/cl-setup +++ b/scripts/cl-setup @@ -29,7 +29,7 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-setup") optObj = cl_ldap.tsOpt(ldapObj,[]) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service'): + if not optObj.flagHelp and 'service' in optObj.params: # Настройка сервера LDAP flagError = True if optObj.params['service'] == "ldap" and \ diff --git a/scripts/cl-update-server b/scripts/cl-update-server index e03fc4d..d47bc54 100644 --- a/scripts/cl-update-server +++ b/scripts/cl-update-server @@ -29,7 +29,7 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-update-server") optObj = cl_ldap.tsOpt(ldapObj,[]) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ + if not optObj.flagHelp and 'service' in optObj.params and\ not optObj.errorOpt: # Настройка сервера LDAP flagError = True diff --git a/scripts/cl-useradd b/scripts/cl-useradd index df9f7de..3455b0d 100644 --- a/scripts/cl-useradd +++ b/scripts/cl-useradd @@ -29,8 +29,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-useradd") optObj = cl_ldap.tsOpt(ldapObj,['user']) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('user'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'user' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() diff --git a/scripts/cl-userdel b/scripts/cl-userdel index 87f757f..562f156 100644 --- a/scripts/cl-userdel +++ b/scripts/cl-userdel @@ -29,8 +29,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-userdel") optObj = cl_ldap.tsOpt(ldapObj,['user']) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('user'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'user' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() diff --git a/scripts/cl-usermod b/scripts/cl-usermod index cac1cc0..5229b83 100644 --- a/scripts/cl-usermod +++ b/scripts/cl-usermod @@ -30,8 +30,8 @@ if __name__ == "__main__": ldapObj = cl_ldap.cl_ldap("cl-usermod") optObj = cl_ldap.tsOpt(ldapObj,['user'],True,True) flagError = False - if not optObj.flagHelp and optObj.params.has_key('service') and\ - optObj.params.has_key('user'): + if not optObj.flagHelp and 'service' in optObj.params and\ + 'user' in optObj.params: flagError = True if optObj.params['service'] == "unix": obj = cl_ldap.servUnix() diff --git a/scripts/dhcp b/scripts/dhcp index 07256ae..e091139 100644 --- a/scripts/dhcp +++ b/scripts/dhcp @@ -45,12 +45,12 @@ if __name__ == "__main__": os.setgid(gid) os.setuid(uid) except: - print _("ERROR: Can not set owner") + \ + print(_("ERROR: Can not set owner") + \ " (dhcp:dhcp uid=%s,gid=%s) "%(uid, gid) +\ - _("the this process") + _("the this process")) sys.exit(1) if os.getuid() != uid: - print _("ERROR: Owner this process not dhcp or root") + print(_("ERROR: Owner this process not dhcp or root")) sys.exit(1) if os.access(logFullFile, os.W_OK): logObj = cl_log.log(logFile) diff --git a/scripts/sortmilter b/scripts/sortmilter index abef8c0..cc43e59 100755 --- a/scripts/sortmilter +++ b/scripts/sortmilter @@ -24,6 +24,7 @@ from os.path import join as pathjoin, exists as pathexists from shutil import copy as copyfile, move as movefile from optparse import OptionParser from threading import Lock +from functools import reduce # fix ecre in email module email.header.ecre = re.compile(r''' @@ -63,7 +64,7 @@ class Logger: self.logfile.flush() except: sys.stderr.write(strftime("%Y%m%d%H%M%S ") + - "".join(apply(traceback.format_exception, sys.exc_info()))) + "".join(traceback.format_exception(*sys.exc_info()))) self.lock.release() def printDEBUG(self,s): @@ -96,7 +97,7 @@ class Logger: def dbg_except(): """Debug function, for try-except block""" Logger().printLOG(strftime("%Y%m%d%H%M%S ") + - "".join(apply(traceback.format_exception, sys.exc_info()))) + "".join(traceback.format_exception(*sys.exc_info()))) def strstime(format="%Y-%m-%d_%H:%M",seconds=0): return strftime(format, localtime(seconds)) @@ -119,7 +120,7 @@ class Letter: self.cacheReceiver = None # letter by filename if file: - content = open(file,"r").read() + content = open(file, "r").read() self.filepath = file self.mail = message_from_string(content) # letter by content @@ -158,7 +159,8 @@ class Letter: resent_to = self.getResentTo() delivered_to = self.getDeliveredTo() if resent_to and delivered_to: - order_field = self.mail.keys() + order_field = list(self.mail.keys()) + #TODO probably will be bugged in py3: order of keys in dict changed if order_field.index("Delivered-To") < order_field.index("Resent-To"): receiver_emails = delivered_to else: @@ -184,9 +186,9 @@ class Letter: charset = self.mail.get_charsets() # if charset specified and it is not utf-8 try: - if charset and charset[0] and not charset[0].lower() in ['utf-8','utf8']: + if charset and charset[0] and not charset[0].lower() in ['utf-8', 'utf8']: letter_text = letter_text.decode(charset[0]).encode('utf-8') - except Exception,e: + except Exception as e: Logger().printDEBUG("wrong decode from %s: %s" % (charset[0], e)) return letter_text @@ -357,7 +359,7 @@ class MailBox: def fixMtime(self): # fix mtime of mailbox directory by date (latest letter) - os.utime(self.getDirectory(),(self.date,)*2) + os.utime(self.getDirectory(),(self.date,) * 2) def getDirectory(self): """Get full path to mail box""" @@ -384,7 +386,7 @@ class MailBox: class MailKeeper: """Object which keep mailboxes (mailboxes union)""" - def __init__(self,storagedir=None,domains=[],errordir=None): + def __init__(self,storagedir=None, domains=None, errordir=None): # root directory for mail keeper self.root = storagedir # root directory for mail keeper @@ -396,7 +398,7 @@ class MailKeeper: # create directory for error letters mkdir_force(self.errordir) #self.initMailBoxes() - self.domains = domains + self.domains = domains if domains is not None else [] self.reInDomain = re.compile(r"@([^@]+)?(%s)$"%"|".join(self.domains),re.S) self.iNum = 2 if "unknown" not in self.mailboxes: @@ -541,7 +543,7 @@ class SortMilter(Milter.Milter): def close(self): """Execute after end of connect (include error disconnect)""" return Milter.CONTINUE - + def getMailFromFolder(dir): # find all files in specified directory and generate list of Letter for root, dirs, files in os.walk(dir): @@ -580,24 +582,24 @@ def main(argv): help="Directory for letters with error"), parser.add_option("--domain", action="append", - default=[], + default= [], dest="domains", metavar="DOMAIN", help="Owner mail domain"), parser.add_option("--letters-dir", action="append", - default = [], + default=[], dest="letters_dir", metavar="DIR", help="Directory which contains letter for performing"), parser.add_option("--remove-success", action="store_true", - default = False, + default=False, dest="remove_success", help="Remove letters from directory if processed success"), parser.add_option("--letter-file", action="append", - default = [], + default=[], dest="letter_file", metavar="FILE", help="Letter file for performing"), diff --git a/setup.py b/setup.py index c32e2de..083075a 100755 --- a/setup.py +++ b/setup.py @@ -25,6 +25,9 @@ from distutils.command.build_scripts import build_scripts from distutils.command.install_scripts import install_scripts from distutils.command.install_data import install_data +def cmp(a, b): + return (a > b) - (b < a) + data_files = [] var_data_files = [("/var/calculate/server-profile",[]), @@ -44,24 +47,24 @@ def scanDirs(profilesDirs): self.baseDir = False self.dirs = [] self.files = [] - def getFilesDir(dirP, dirname,names): - if '/.svn' in dirname: - return False - for nameFile in names: - absNameFile = dirname + "/" + nameFile - if '/.svn' in absNameFile: - continue - if os.path.isfile(absNameFile): - dirP.files.append(absNameFile) - elif os.path.isdir(absNameFile): - dirP.dirs.append(absNameFile) - return True for profileDir in profilesDirs: if profileDir: dirP = dirProf() dirP.baseDir = profileDir + for dirname, dirs, files in os.walk(profileDir): + if '/.svn' in dirname: + return False + for nameFile in files: + absNameFile = dirname + "/" + nameFile + if '/.svn' in absNameFile: + continue + dirP.files.append(absNameFile) + for nameDir in dirs: + absNameDir = dirname + "/" + nameDir + if '/.svn' in absNameDir: + continue + dirP.dirs.append(absNameDir) dirs.append(dirP) - os.path.walk(profileDir,getFilesDir, dirP) return dirs def create_data_files (data_dirs, prefix=""): @@ -82,7 +85,7 @@ def create_data_files (data_dirs, prefix=""): break for files_obj_dir in files_obj_dirs: obj.dirs.remove(files_obj_dir) - files_obj_dirs.sort(lambda x, y: cmp(len(y), len(x))) + files_obj_dirs.sort(key=len, reverse=True) for dir_name in files_obj_dirs: wr_sp = (prefix+dir_name,[]) file_dirs = [] @@ -103,8 +106,8 @@ def create_data_files (data_dirs, prefix=""): test1_files = test2_files + test1_files return test1_files -data_files += create_data_files (data_dirs_local) -data_files += create_data_files (data_dirs_share, share_calculate_dir) +data_files += create_data_files(data_dirs_local) +data_files += create_data_files(data_dirs_share, share_calculate_dir) data_files += [('/etc/conf.d', ['data/sortmilter.conf']), ('/etc/init.d', ['data/sortmilter.init'])] @@ -115,7 +118,7 @@ class cl_build_scripts(build_scripts): './scripts/execserv', './scripts/execsamba'] backup_build_dir = self.build_dir - backup_scripts = filter(lambda x: not x in scripts, self.scripts) + backup_scripts = [x for x in self.scripts if x not in scripts] self.scripts = scripts self.build_dir = self.build_dir + "-bin" build_scripts.run(self) @@ -140,15 +143,11 @@ class cl_install_data(install_data): def run (self): install_data.run(self) data_file = \ - [("/etc/init.d/sortmilter.init","sortmilter",0755), + [("/etc/init.d/sortmilter.init","sortmilter",0o755), ("/etc/conf.d/sortmilter.conf","sortmilter",None)] data_find = \ dict( - map(lambda x:(os.path.basename(x[0]), - [list(reversed(filter(lambda y:y,x[0].split("/")))), - x[1], - x[2]]), - data_file)) + [(os.path.basename(x[0]), [list(reversed([y for y in x[0].split("/") if y])), x[1],x[2]]) for x in data_file]) for path in self.get_outputs(): nameFile = os.path.split(path)[1]