#-*- coding: utf-8 -*-

#Copyright 2009 Calculate Pack, http://www.calculate-linux.ru
#
#  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 sys
import re
import ldap
import  cStringIO, StringIO
from ldif import LDIFParser, LDIFWriter
import cl_base
import cl_profile
import cl_utils2
import cl_utils
# Для подсчета символов
import termios, fcntl, struct
# Ввод pwd
import getpass
# Статистика файла
import stat
import types
import time
# Для ввода символа
import tty
# Работа со временем
import time
import datetime
# Создание временных файлов
import tempfile
# Вывод в строку ввода
import readline

Version = "calculate-server 2.0.10"

tr = cl_base.lang()
tr.setLanguage(sys.modules[__name__])

pcs = cl_utils.prettyColumnStr

class report():
    """Класс для выдачи данных в табличном виде"""
    def __init__(self, title, headerList, dataList):
        # Заголовок
        self.title = title
        # Cписок элементов первой строки таблицы
        self.headerList = headerList
        # Список строк (каждая строка - список элементов)
        self.dataList = dataList
        # Список ширин колонок
        self.columnsWidth = self.getColumsnWidth()

    def getColumsnWidth(self):
        """Находит максимальную ширину каждой колонки

        результат список ширин колонок
        """
        columnsWidth = []
        lenCol = 0 
        for s in self.headerList:
            lenCol += 1
            columnsWidth.append(len(cl_utils._toUNICODE(s)))
        maxLenCol = lenCol
        # Вычисляем максимальное количество столбцов
        for s in self.dataList:
            lenS = len(s)
            if maxLenCol < lenS:
                maxLenCol = lenS
        if maxLenCol > lenCol:
            appCol = maxLenCol - lenCol
            # Добавляем элементы в список ширин
            for i in range(appCol):
                columnsWidth.append(0)
        # Вычисляем ширину столбцов
        for e in self.dataList:
            i = 0
            for s in e:
                lenS = len(cl_utils._toUNICODE(s))
                if columnsWidth[i] < lenS:
                    columnsWidth[i] = lenS
                i += 1
        return columnsWidth

    def createFormatStr(self, listStr):
        """Создает список (текст, ширина ...)"""
        strList = []
        lenStr = len(listStr)
        for i in range(len(self.columnsWidth)):
            if lenStr > i:
                strList.append(listStr[i])
            else:
                strList.append("")
            strList.append(self.columnsWidth[i])
        return strList

    def printReport(self):
        """Напечатать данные в табличном виде"""
        print self.title
        listStrSep = []
        for lenCol in self.columnsWidth:
            listStrSep.append("-"*lenCol)
        printData = ""
        printData += cl_utils.columnStr(*self.createFormatStr(listStrSep))
        printData += cl_utils.columnStr(*self.createFormatStr(self.headerList))
        printData += cl_utils.columnStr(*self.createFormatStr(listStrSep))
        for s in self.dataList:
            printData += cl_utils.columnStr(*self.createFormatStr(s))
        printData += cl_utils.columnStr(*self.createFormatStr(listStrSep))
        if printData[-1] == "\n":
            printData = printData[:-1]
        lines = printData.splitlines()
        lenCols = map(lambda x: len(x), 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 ="-+-"
            convLines.append(self._insertStrChar(lines[i], lenCols, char))
        print "\n".join(convLines)
        return True
    
    def _insertStrChar(self, line, lenCols, char):
        """Вставляет несколько символов char в указанные позиции

        сначала строки будет вставлено char[1:] в конце строки char[:-1]
        """
        lineUnicode = cl_utils._toUNICODE(line)
        prevPos = 0
        convLine = char[1:]
        lenLenCols = len(lenCols)
        for i in range(lenLenCols):
            pos = lenCols[i] + prevPos
            if i == lenLenCols-1:
                insertChar = char[:-1]
            else:
                insertChar = char
            convLine += lineUnicode[prevPos:pos] + insertChar
            prevPos = pos + 1
        return convLine.encode("UTF-8")
        

def adminConnectLdap(fun):
    """Cоединение с LDAP администратором сервиса (декоратор)

    соединение с LDAP и проверка установки необходимых переменных
    """
    def ret (self, *arg, **argv):
        flagError = False
        if not self.clVars:
            self.createClVars()
        if not self.ldapObj:
            if not self.getLdapObjInFile():
                flagError = True
        if not self.baseDN:
            if self.clVars.defined("ld_base_dn"):
                self.baseDN = self.clVars.Get("ld_base_dn")
            if not self.baseDN:
                self.printERROR (_('Not found LDAP base DN'))
        if flagError:
            return False
        else:
            return fun(self, *arg , **argv)
    return ret

class iniLdapParser(cl_base.iniParser):
    """Класс для работы c ini-файлом ldap"""
    def __init__(self):
        # название ini файла
        self.nameIniFile = "/etc/calculate/calculate.ldap"
        cl_base.iniParser.__init__(self, self.nameIniFile)
        # права создаваемого ini-файла
        self.setMode(0600)
        pathIniFile = os.path.split(self.nameIniFile)[0]
        if not os.path.exists(pathIniFile):
            os.makedirs(pathIniFile)

class addLdif(LDIFParser):
    """Класс необходимый для добавления записей в LDAP"""
    def __init__(self, strInput,ldapCon):
        FD = cStringIO.StringIO(strInput)
        LDIFParser.__init__(self, FD)
        self.ldapCon = ldapCon

    def handle(self, dn, entry):
        self.ldapCon.add_s(dn, entry.items())

class ldapFunction(cl_utils2.ldapFun):
    '''Объект для работы с LDAP сервером'''
    def __init__(self, dnUser, password):
        cl_utils2.ldapFun.__init__(self, dnUser, password)

    def ldapAdd(self, strLdif):
        """Добавляем строку содержащую ldif в LDAP

        Если данные существуют - ошибка
        """
        if self.conLdap:
            try:
                # Записываем параметры из ldif файла в LDAP сервер
                parser = addLdif(strLdif,self.conLdap)
                parser.parse()
            except ldap.LDAPError, e:
                self.setError(e[0]['desc'])
                return False
            except:
                self.setError("Error in ldif file")
                return False
            return True
        else:
            self.setError(_("No connect to LDAP server"))
            return False

# Импортированные классы в cl_ldap
# Запись ошибок
imp_cl_err = cl_profile._error
# Работа с XML
imp_cl_xml = cl_profile.xmlShare
# Обработка параметров командной строки
imp_cl_help = cl_utils2.cl_help
# Форматированный вывод
imp_cl_smcon = cl_utils2.cl_smartcon


class shareLdap(imp_cl_err, imp_cl_xml, imp_cl_help, imp_cl_smcon):
    """Класс где храняться общие методы для всех сервисов"""

    # DN сервисов относительно базового
    ServicesDN = "ou=Services"

    def __init__(self):
        # Переменная объект Vars
        self.clVars = False
        # Переменная объект ldapFunction
        self.ldapObj = False
        # Переменная соединение с LDAP сервером
        self.conLdap = False
        # Базовый DN LDAP сервера
        self.baseDN = False
        # Статические группы
        self.staticGroups = {\
            'client':self.addInfoGroup('client',
                                          '900',
                                          'Client samba group'),
            'admin':self.addInfoGroup('admin',
                                          '901',
                                          'Admin samba group'),
            'Computers':self.addInfoGroup('Computers',
                                          '902',
                                          'Computer group')}
        # Статические пользователи
        self.staticUsers = {\
            'client':self.addInfoUser('client',
                                      '900',
                                      '900',
                                      'Client samba user'),
            'admin':self.addInfoUser('admin',
                                      '901',
                                      '901',
                                      'Admin samba user')}

    def reloadDefaultVar(self, nameVar):
        """При получениии значения переменной снова

        вызывается снова метод заполнения переменной"""
        self.clVars.Set(nameVar,"",True)
        self.clVars.__getattribute__(nameVar).countFill = 0
        self.clVars.__getattribute__(nameVar).fillStart = True
        return True

    def addInfoGroup(self, name, gid, comment):
        """Добавляем информацию о группе"""
        class group():
            """Информация о группе"""
            name = ""
            gid = ""
            comment = ""
        gr = group()
        gr.name = name
        gr.gid = gid
        gr.comment = comment
        return gr

    def addInfoUser(self, name, uid, gid, comment):
        """Добавляем информацию о пользователе"""
        class user():
            """Информация о пользователе"""
            name = ""
            uid = ""
            gid = ""
            comment = ""
        us = user()
        us.name = name
        us.uid = uid
        us.gid = gid
        us.comment = comment
        return us

    def chortToFullName(self, listNames, domain):
        """Из списка коротких имен получаем cписок полных имен

        К коротким именам добавляем домен, длинные выдаем как есть
        """
        listFillNames = []
        for name in listNames:
            if "." in name:
                listFillNames.append(name)
            else:
                listFillNames.append("%s.%s" %(name,domain))
        return listFillNames


    def getServiceSetup(self):
        """находит установленные сервисы

        Выдаем список [установленные сервисы]
        """
        # инсталированнные сервисы
        servInstalled = []
        # доступные сервисы
        services = ('ldap', 'unix', 'samba', 'mail', 'jabber', 'ftp')
        for serv in services:
            if self.clVars.Get("sr_%s_set"%serv) == "on":
                servInstalled.append(serv)
        return servInstalled

    def restorePathDelUser(self,userName,destDir,relDir,message,unixObj=False):
        """Восстанавливает директорию удаленного пользователя"""
        removeDir = False
        flagError = False
        resRestore = self.restoreDelUser(userName, relDir,
                                         destDir, message,unixObj)
        # Если ошибка то выходим
        if not resRestore:
            flagError = True
        # Флаг создания директории профиля пользователя
        createDir = destDir
        term = ""
        if resRestore == True:
            term = message
        if not flagError and type(resRestore) == types.TupleType:
            # Если cansel
            if resRestore[0] == "Cancel":
                # Удаляем пользователя
                flagError = True
                term = None
            # Если No
            elif resRestore[0] == "No":
                if not self.removeDir(resRestore[1]):
                    flagError = True
                if not flagError:
                    removeDir = resRestore[1]
                    term = False
            elif resRestore[0] == "Yes":
                createDir = False
                removeDir = resRestore[1]
                term = True
        if flagError or term == "":
            return False
        else:
            return (term, createDir, removeDir)

    @adminConnectLdap
    def restoreDelUser(self,userName,service,srcDir,message,unixObj=False):
        """Возвращаем данные удаленного пользователя"""
        # Ищем Unix пользователя
        if unixObj:
            servUnixObj = unixObj
        else:
            servUnixObj = self.servUnixObj
        searchUnixUser = servUnixObj.searchUnixUser(userName)
        # id пользователя
        strUid = ""
        if searchUnixUser:
            strUid = searchUnixUser[0][0][1]['uidNumber'][0]
        else:
            resPasswd = servUnixObj.searchPasswdUser(userName)
            if resPasswd:
                strUid = resPasswd.split(":")[2]
        if strUid:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s-%s"%(userName,strUid),
                                             service)
        if strUid and os.path.exists(delBackDir) and os.listdir(delBackDir):
            if message == None or type(message) == types.BooleanType:
                dialogRes = message
            else:
                dialogRes = self.dialogYesNo(message)
            if dialogRes and dialogRes == True:
                try:
                    self.copyDir(srcDir, delBackDir)
                except:
                    self.printERROR(_("Not restore user data in dir %s")\
                                    %srcDir)
                    return False
                self.printSUCCESS(_("Restore user data in dir %s")\
                          %srcDir)
                return  "Yes", delBackDir
            elif dialogRes == False:
                return "No", delBackDir
            elif dialogRes == None:
                return "Cancel", delBackDir
        return True

    @adminConnectLdap
    def backupDelUser(self, userName, service, srcDir, unixObj=False):
        """Сохраняем данные удаляемого пользователя"""
        # Ищем Unix пользователя
        if unixObj:
            servUnixObj = unixObj
        else:
            servUnixObj = self.servUnixObj
        searchUnixUser = servUnixObj.searchUnixUser(userName)
        # id пользователя
        strUid = ""
        if searchUnixUser:
            strUid = searchUnixUser[0][0][1]['uidNumber'][0]
        if strUid:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%s-%s"%(userName,strUid),
                                             service)
            if os.path.exists(delBackDir) and os.listdir(delBackDir):
                self.printERROR(_("Found deleted user data dir %s")\
                              %delBackDir)
                self.printERROR(_("Not created deleted user data dir %s")\
                            %delBackDir)
                return False
        else:
            delBackDir =\
                os.path.join(self.clVars.Get("sr_deleted_path"),
                                             "%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)
        # Cоздаем директорию хранения удаленных пользователей
        if not os.path.exists(self.clVars.Get("sr_deleted_path")):
            os.makedirs(self.clVars.Get("sr_deleted_path"))
        #Делаем сохранение директории
        try:
            self.copyDir(delBackDir,srcDir)
        except:
            self.printERROR(_("Can not copy deleted user data in dir %s")\
                            %delBackDir)
            return False
        self.printSUCCESS(_("Created deleted user data dir %s")\
                          %delBackDir)
        return True

    def stringIsJpeg(self, string):
        """Определяет является ли строка jpeg изображением"""
        if len(string)<8:
            return False
        FD = cStringIO.StringIO(string)
        isJpeg = False
        FD.seek(0, 0)
        (firstByte, secondByte) = FD.read(2)
        if (ord(firstByte) == 0xff and ord(secondByte) == 0xd8):
            (firstByte, secondByte) = FD.read(2)
            if (ord(firstByte) == 0xff and ord(secondByte) == 0xe0):
                isJpeg = True
        return isJpeg

    def setDaemonAutostart(self, daemon):
        """Прописывает демона в автозагрузку"""
        execStr = "rc-update add %s default" %daemon
        textLine = self.execProg(execStr)
        if "added to runlevel" in textLine or\
            "already installed in runlevel" in textLine:
            return True
        else:
            self.printError(_("ERROR") + ": " + execStr)
            self.printError(_("Can not add at default runlevel")+ " ...")
            return False

    def delDaemonAutostart(self, daemon):
        """Удаляет демона из автозагрузки"""
        execStr = "rc-update del %s default" %daemon
        textLine = self.execProg(execStr)
        if "removed from the following runlevels" in textLine or\
            "not found in any of the specified runlevels" in textLine:
            return True
        else:
            self.printError(_("ERROR") + ": " + execStr)
            self.printError(_("Not deleted from default runlevel")+ " ...")
            return False

    def runLdapServer(self):
        """Запускает LDAP сервер"""
        textLines = self.execProg("/etc/init.d/slapd start", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            return True
        else:
            self.printNotOK(_("Starting LDAP")+ " ...")
            return False

    def restartLdapServer(self):
        """Запускает LDAP сервер"""
        textLines = self.execProg("/etc/init.d/slapd restart", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            return True
        else:
            self.printNotOK(_("Restarting LDAP")+ " ...")
            return False

    def stopLdapServer(self):
        """Останавливает LDAP сервер"""
        textLines = self.execProg("/etc/init.d/slapd stop", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            #self.printOK(_("LDAP stop")+ " ...")
            return True
        else:
            self.printNotOK(_("Stopping LDAP")+ " ...")
            return False

    def getALLServices(self):
        """Получаем все сервисы которые описаны в профилях"""
        # путь к директории профилей
        profilePath = self.clVars.Get("cl_profile_path")[0]
        data = os.listdir(profilePath)
        service = []
        for fileData in data:
            if os.path.isdir(os.path.join(profilePath, fileData)):
                service.append(fileData)
        if service:
            # После добавления сервисов в класс необходимо удалить
            # apache и jabber
            service.remove('backup')
            service.remove('apache')
        return service

    def applyProfilesFromService(self, service, verbose=False):
        """Применяем профили для данного сервиса"""
        # Cоздаем объект профиль устанавливая директорию
        # service для файлов профилей
        clProf = cl_profile.profile(self.clVars,service)
        # Объединяем профили
        data = clProf.applyProfiles()
        if clProf.getError():
            self.printERROR(clProf.getError())
            return False
        else:
            if verbose and type(data) == types.TupleType:
                dirs, files = data
                return files
            return True

    def searchService(self):
        """Поиск DN сервиса"""
        name, value = self.relServDN.split('=')
        resSearch = self.searchLdapDN(value, self.ServicesDN, name)
        return resSearch

    def delServicesAutostart(self, servInstalled):
        """Удаляет из автозагрузки сервисы

        Входные данные - список названий сервисов
        """
        flagError = False
        flagLdap = False
        for service in servInstalled:
            if service == "unix" or service == "ldap":
                if not self.delDaemonAutostart("slapd"):
                    flagError = True
                    break
                continue
            elif service == "mail":
                if not self.delDaemonAutostart("postfix"):
                    flagError = True
                    break
                if not self.delDaemonAutostart("dovecot"):
                    flagError = True
                    break
                    continue
            elif service == "jabber":
                if not self.delDaemonAutostart("ejabberd"):
                    flagError = True
                    break
                    continue
            else:
                if not self.delDaemonAutostart("service"):
                    flagError = True
                    break
                    continue
        if flagError:
            return False
        else:
            return True

    def startDaemons(self, service, daemons, printSuccess=True):
        """Стартует демонов"""
        flagError = False
        for daemon in daemons:
            if not self.getRunDaemons([daemon]):
                textLines = self.execProg("/etc/init.d/%s start" %(daemon),
                                          False, False)
                if not (textLines and type(textLines) == types.ListType and\
                    "ok" in textLines[-1] or textLines and "ok" in textLines):
                    self.printERROR( _("Daemon %s was not started") %daemon)
                    flagError = True
                    break
        if service == "ldap":
            service = "LDAP"
        if flagError:
            self.printNotOK(_("Starting") + " " + service.capitalize() + " " +\
                            _("service"))
            return False
        else:
            if printSuccess:
                self.printOK(_("Starting") + " " + service.capitalize() + " "+\
                             _("service"))
            return True

    def startServices(self, servInstalled, printSuccess=True):
        """Запускает все сервисы поданные на вход этому методу

        Также прописывает в автозагрузку
        Входные даннные - список названий сервисов
        """
        if 'ldap' in servInstalled:
            if not self.startDaemons('ldap',['slapd'], printSuccess):
                return False
            # Устанавливаем автозапуск демона
            if not self.setDaemonAutostart("slapd"):
                return False
        flagError = False
        for service in servInstalled:
            if service == "unix" or service == "ldap":
                continue
            elif service == "mail":
                if not self.startDaemons('mail',['postfix', 'dovecot'],
                                         printSuccess):
                    flagError = True
                    break
                # Устанавливаем автозапуск демонов
                if not (self.setDaemonAutostart("postfix") and\
                    self.setDaemonAutostart("dovecot")):
                    flagError = True
                    break
            # В случае почтового релея
            elif service == "mail_relay":
                if not self.startDaemons('mail',['postfix'],
                                         printSuccess):
                    flagError = True
                    break
                # Устанавливаем автозапуск демонов
                if not self.setDaemonAutostart("postfix"):
                    flagError = True
                    break
            elif service == "jabber":
                if not self.startDaemons('jabber',['ejabberd'], printSuccess):
                    flagError = True
                    break
                # Устанавливаем автозапуск демона
                if not self.setDaemonAutostart("ejabberd"):
                    flagError = True
                    break
            elif service == "ftp":
                if not self.startDaemons('ftp',['proftpd'], printSuccess):
                    flagError = True
                    break
                # Устанавливаем автозапуск демона
                if not self.setDaemonAutostart("proftpd"):
                    flagError = True
                    break
            else:
                if not self.startDaemons(service,[service], printSuccess):
                    flagError = True
                    break
                # Устанавливаем автозапуск демона
                if not self.setDaemonAutostart(service):
                    return False
        if flagError:
            return False
        else:
            return True

    def stopServices(self, servInstalled):
        """Останавливает все сервисы поданные на вход этому методу

        Входные даннные - список названий сервисов
        """
        flagError = False
        flagLdap = False
        for service in servInstalled:
            if service == "unix" or service == "ldap":
                flagLdap = True
            # В случае почтового релея
            elif service == "mail_relay":
                if self.getRunDaemons(["postfix"]):
                    textLines = self.execProg("/etc/init.d/postfix stop", False,
                                               False)
                    if not (textLines and type(textLines) == types.ListType and\
                            "ok" in textLines[-1] or textLines and\
                            "ok" in textLines):
                        self.printERROR( "Postfix" + " " +
                                _("service is not stopped"))
                        flagError = True
                        break
            elif service == "mail":
                if self.getRunDaemons(["postfix"]):
                    textLines = self.execProg("/etc/init.d/postfix stop", False,
                                             False)
                    if not (textLines and type(textLines) == types.ListType\
                        and "ok" in textLines[-1] or textLines and\
                        "ok" in textLines):
                        self.printERROR( "Postfix" + " " +
                                _("service is not stopped"))
                        flagError = True
                        break
                if self.getRunDaemons(["dovecot"]):
                    textLines = self.execProg("/etc/init.d/dovecot stop", False,
                                              False)
                    if not (textLines and type(textLines) == types.ListType and\
                        "ok" in textLines[-1] or textLines and\
                        "ok" in textLines):
                        self.printERROR(str("Dovecot") + " " +
                                _("service is not stopped"))
                        flagError = True
                        break
            elif service == "jabber":
                if self.getRunService("jabber"):
                    textLines = self.execProg("/etc/init.d/ejabberd stop",False,
                                             False)
                    if not (textLines and type(textLines) == types.ListType and\
                        "ok" in textLines[-1] or textLines and\
                        "ok" in textLines):
                        self.printERROR( "Ejabberd" + " " +
                                _("service is not stopped"))
                        flagError = True
                        break
                    listProcess = self.execProg("ps ax",False,False)
                    killPid = []
                    for process in listProcess:
                        if "erlang" in process:
                            killPid.append(process.split(" ")[0])
                    if killPid and " ".join(killPid).strip():
                        textLine = self.execProg("kill %s" %" ".join(killPid))
                        if not (textLine == None):
                            self.printERROR(_("Can not 'kill %s'")\
                                %" ".join(killPid))
                            flagError = True
                            break
            elif service == "ftp":
                if self.getRunDaemons(["proftpd"]):
                    textLines = self.execProg("/etc/init.d/proftpd stop",False,
                                              False)
                    if not (textLines and type(textLines) == types.ListType and\
                        "ok" in textLines[-1] or textLines and\
                        "ok" in textLines):
                        self.printERROR( "Proftpd" + " " +
                                _("service is not stopped"))
                        flagError = True
                        break
            elif self.getRunService(service):
                stopService = service
                textLines = self.execProg("/etc/init.d/%s stop" %(stopService),
                                          False, False)
                if not (textLines and type(textLines) == types.ListType and\
                    "ok" in textLines[-1] or textLines and "ok" in textLines):
                    self.printERROR( str(service) + " " +
                                _("service is not stopped"))
                    flagError = True
                    break
        if flagLdap:
            if self.getRunService('ldap'):
                textLines = self.execProg("/etc/init.d/slapd stop",False,False)
                if not (textLines and type(textLines) == types.ListType and\
                    "ok" in textLines[-1] or textLines and "ok" in textLines):
                    self.printERROR( "LDAP" + " " +
                                _("service is not stopped"))
                    flagError = True
        if flagError:
            return False
        else:
            return True

    def getUserPassword(self, options, optDialog, optStdIn, pwDialog=False):
        """Получить пароль у пользователя

        options   - полученные опции командной строки
        optDialog - опция командной строки для вывода диалога для получения
                    пароля
        optStdIn  - опция командной строки для получения пароля из
                    стандартного ввода (stdin)
        pwDialog  - структура для вывода приглашения в режиме диалога
        """
        userPwd = ""
        if optStdIn and options.has_key(optStdIn):
            pwdA = sys.stdin.readline().rstrip()
            pwdB = sys.stdin.readline().rstrip()
        elif optDialog and options.has_key(optDialog):
            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 not pwdA or not (pwdA == pwdB):
                self.printERROR (_("ERROR") + ": " +\
                _("password incorrect")+ ": " + _("try again"))
                return False
            userPwd = pwdA
        return userPwd

    def getRunDaemons(self, daemons, printError=False):
        """Проверка, запущены ли демоны"""
        baseDir = "/var/run"
        runDaemons = {}
        for daemon in daemons:
            # Проверка на запуск демона postfix
            if daemon == 'postfix':
                flagRun = False
                listProcess = self.execProg("ps ax",False,False)
                for process in listProcess:
                    if "postfix/master" in process:
                        flagRun = True
                        break
                if flagRun:
                    runDaemons['postfix'] = True
                else:
                    runDaemons['postfix'] = False
                continue
            addDirDict = {"slapd":("openldap","slapd.pid"),
                          "samba":("/var/lib/init.d/daemons","samba"),
                          "dovecot":("dovecot","master.pid"),
                          "ejabberd":("/var/lib/init.d/daemons","ejabberd"),
                          "proftpd":("","proftpd.pid")
                          }
            if addDirDict[daemon][0][:1] == "/":
                pidDir = addDirDict[daemon][0]
            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])):
                runDaemons[daemon] = True
            else:
                runDaemons[daemon] = False
        if printError:
            for daemon in daemons:
                if not runDaemons[daemon]:
                    self.printERROR(_("Daemon %s is not started") %daemon)
        if False in runDaemons.values():
            return False
        else:
            return True
    
    def getHashPasswd(self, password, crypt):
        """Хеш пароля используя slappasswd"""
        if not crypt:
            self.printERROR(_("ERROR") + " getHashPasswd: " +\
                            _("crypto algoritm empty"))
            return False
        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[:lenCryptStr] == cryptStr:
            return pwdHash
        self.printERROR(_("ERROR") + " getHashPasswd: " +\
                        _("create crypto password"))
        return False

    def getRunService(self, nameService, printError=False):
        """Проверка, запущен ли сервис с данным именем"""
        flagError = False
        if nameService == "mail":
            daemons = ['postfix','dovecot']
            if not self.getRunDaemons(daemons,printError):
                flagError = True
        elif nameService == "ldap":
            if not self.getRunDaemons(['slapd'],printError):
                flagError = True
        elif nameService == "jabber":
            if not self.getRunDaemons(['ejabberd'],printError):
                flagError = True
        elif nameService == "ftp":
            if not self.getRunDaemons(['proftpd'],printError):
                flagError = True
        else:
            if not self.getRunDaemons([nameService],printError):
                flagError = True
        if flagError:
            if printError:
                self.printERROR( nameService.capitalize + " " +
                        _("service is not started") + " ...")
            return False
        return True

    def unicList(self, lst):
        """Список уникальных элементов из списка не уникальных"""
        return list(set(lst))

    def setJpegPhotoUser(self, userName, photoPath, attr="uid"):
        """Добавляем jpeg фотографию пользователя в LDAP"""
        import popen2
        try:
            FD = open(photoPath)
            photoData = FD.read()
            FD.close()
        except:
            self.printERROR(_("Not open file") + ": " + str(photoPath))
            return False
        searchUser = self.searchLdapDN(userName, self.relUsersDN, attr)
        if not searchUser:
            self.printERROR(_("User") + " " + str(userName) + " "+\
            _("not found"))
            return False
        modAttrs = []
        if not self.stringIsJpeg(photoData):
            flagError = False
            fOut, fIn, fErr = popen2.popen3("convert '%s' jpg:-" %photoPath)
            fIn.close()
            if fErr.read():
                self.printERROR(_("Can not convert file '%s' in jpeg format")\
                                %photoPath)
                flagError = True
            fErr.close()
            if not flagError:
                photoData = fOut.read()
                if not self.stringIsJpeg(photoData):
                    self.printERROR(\
                    _("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'):
            modAttrs.append((ldap.MOD_REPLACE, 'jpegPhoto', photoData))
        else:
            modAttrs.append((ldap.MOD_ADD, 'jpegPhoto', photoData))
        userDN = self.addDN("%s=%s"%(attr,userName),self.relUsersDN)
        if not self.modAttrsDN(userDN, modAttrs):
            return False
        return True

    def removeDir(self, rmDir):
        """Рекурсивное удаление директории"""
        if not os.path.exists(rmDir):
            self.printERROR(_("Not found remove dir %s") %rmDir)
            return False
        fileObj = cl_profile._file()
        # Сканируем директорию
        scanObjs = fileObj.scanDirs([rmDir])
        for fileRm in scanObjs[0].files:
            # Удаляем файлы
            os.remove(fileRm)
        for socketRm in scanObjs[0].sockets:
            # Удаляем сокеты
            os.remove(socketRm)
        for linkRm in scanObjs[0].links:
            # Удаляем ссылки
            os.unlink(linkRm[1])
        scanObjs[0].dirs.sort(lambda x, y: cmp(len(y), len(x)))
        for dirRm in scanObjs[0].dirs:
            # Удаляем директории
            os.rmdir(dirRm)
        os.rmdir(rmDir)
        return True

    def removeEmptyDir(self, rmDir):
        """Удаление пустых директорий"""
        if not os.path.exists(rmDir):
            self.printERROR(_("Not found remove dir %s") %rmDir)
            return False
        rDir = rmDir
        while os.listdir(rDir) == []:
            os.rmdir(rDir)
            rDir = os.path.split(rDir)[0]
            if rDir == "/":
                break
        return True

    def createUserDir(self, uid, gid, userDir, mode=0700):
        """Создание пользовательской директории"""
        if not os.path.exists(userDir):
            os.makedirs(userDir)
            if mode:
                os.chmod(userDir,mode)
            os.chown(userDir,uid,gid)
            return True
        else:
            self.printERROR(_("Path %s exists") %userDir)
            return False

    def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644):
        """Создает пользовательский файл с содержимым

        Если директория файла не существует то ошибка
        """
        userDir = os.path.split(fileName)[0]
        if not os.path.exists(userDir):
            self.printERROR(_("Path %s not exists") %userDir)
            return False
        fd = os.open(fileName, os.O_CREAT)
        os.close(fd)
        os.chmod(fileName, mode)
        os.chown(fileName,uid,gid)
        FD = open(fileName, "r+")
        FD.write(fileTxt)
        FD.close()
        return True


    def saveVarsClient(self, listVarName):
        """Записывает переменные для клиента calcualte-client"""
        #считаем переменные для клиента
        dictVar = {}
        flagError = False
        for varName in listVarName:
            value = self.clVars.Get(varName)
            if not value and value != "":
                self.printERROR(_("Variables %s is empty")%varName)
                flagError = True
                break
            dictVar[varName] = value
        if flagError:
            return False
        #Запишем переменные в клиентскую секцию
        for name,value in dictVar.items():
            value = str(value)
            if not value.strip():
               self.clVars.Delete(name)
            if not self.clVars.Write(name,value,True,"remote","client"):
                self.printERROR(_("Error writing variable %s")%name)
                flagError = True
                break
        if flagError:
            return False
        return True

    @adminConnectLdap
    def isServiceSetup(self, service, printError=True):
        """Проверяет установлен ли сервис"""
        if self.clVars:
            if self.clVars.Get("sr_%s_set"%service) == "on":
                return True
        if printError:
            self.printERROR(_("Service %s is not installed")%service + " ...")
        return False

    def raw_input(self, promptText="", inputText=""):
        """Создает поле ввода

        promptText - текст перед полем ввода
        inputText - текст в поле ввода
        """
        if inputText:
            # Записываем текст для последующего вывода в строке ввода
            readline.set_pre_input_hook(lambda:\
                                    readline.insert_text(inputText) or\
                                    readline.redisplay())
        strInput = ""
        if promptText:
            # Получаем текст введенный пользователем
            strInput = raw_input(promptText)
        else:
            strInput = raw_input()
        if inputText:
            # Сбрасываем строку ввода
            readline.set_pre_input_hook(None)
        return strInput

    def isCorrectStringNet(self, strNetworks):
        """Проверяет на корректность строку доверительных сетей

        Выводит cписок сетей
        """
        splNet = strNetworks.replace(","," ").split(" ")
        res=re.compile("^\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?(\/\d\d)?$")
        flagError = False
        networks = []
        for i in splNet:
            r = i.strip()
            if not r:
                continue
            find =res.search(r)
            if not find:
                flagError = True
                break
            else:
                splIP = map(lambda x: 255>=int(x.split("/")[0]) and\
                                    x.split("/")[0], find.group().split("."))
                if splIP[0] and int(splIP[0]) == 0 or\
                    splIP[0] and int(splIP[3]) == 255:
                    flagError = True
                    break
                for t in splIP:
                    if t == False:
                        flagError = True
                        break
            if flagError:
                break
            networks.append(r)
        if flagError:
            return False
        else:
            return list(set(networks))

    def getUserAllowNetwork(self, strPrompt, strNetAllow):
        """Получаем от пользователя доверительные сети

        вывод - список доверительных сетей
        """
        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")
        strNet = self.raw_input(strPrompt, strNetAllow)
        i = 0
        while i<3 and not self.isCorrectStringNet(strNet):
            printW()
            strNet = self.raw_input(strPrompt, strNet)
            i +=1
        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"))
            return False
        return self.isCorrectStringNet(strNet)

    def copyDir(self, destDir, srcDir):
        """Копируем директорию в другое место

        При копировании сохраняются владелец, группа, права
        """
        if os.path.exists(destDir) and not os.listdir(destDir):
            os.rmdir(destDir)
        if not os.path.exists(destDir):
            # Создаем директорию
            os.makedirs(destDir)
            # Файловый объект
            fileObj = cl_profile._file()
            # Сканируем директорию
            scanObjs = fileObj.scanDirs([srcDir])
            if not scanObjs:
                return True
            for dirSrc in scanObjs[0].dirs:
                #создаем в домашней директории директории из srcDir
                dirName = destDir + dirSrc.split(srcDir)[1]
                os.mkdir(dirName)
                mode,uid,gid = fileObj.getModeFile(dirSrc)
                os.chown(dirName, uid,gid)
                os.chmod(destDir, mode)
            for fileCopy in scanObjs[0].files:
                oldFile = destDir + fileCopy.split(srcDir)[1]
                #копируем файлы
                fileObj.openFiles(fileCopy, oldFile)
                fileObj.saveOldFile()
                fileObj.oldProfile = False
                fileObj.closeFiles()
                os.chown(oldFile, fileObj._uid, fileObj._gid)
                os.chmod(oldFile, fileObj._mode)
            for linkCreate in scanObjs[0].links:
                #копируем ссылки
                dst = destDir + linkCreate[1].split(srcDir)[1]
                srcDestList = linkCreate[0].split(srcDir)
                if len(srcDestList)>1:
                    src = destDir + srcDestList[1]
                else:
                    src = linkCreate[0]
                os.symlink(src,dst)
                if os.path.exists(dst):
                    mode,uid,gid = fileObj.getModeFile(dst)
                    #Изменение прав на ссылки
                    os.lchown(dst, uid, gid)
            # Удаляем сокеты
            for rmSocket in scanObjs[0].sockets:
                os.remove(rmSocket)
            mode,uid,gid = fileObj.getModeFile(srcDir)
            os.chmod(destDir, mode)
            os.chown(destDir, uid,gid)
        return True

    def addDN(self, *arg):
        """Складывает текстовые элементы DN"""
        DNs = []
        for dn in arg:
            if dn:
                DNs.append(dn)
        return ','.join(DNs)


    @adminConnectLdap
    def initialChecks(self, service, printError=True):
        """Начальная проверка перед запуском методов сервиса"""
        if self.clVars.Get("sr_mail_relay_set") == "on":
            if printError:
                self.printERROR(_("This server is a mail relay. \
This command is not allowed."))
            return False
        if not self.isServiceSetup(service, printError):
                return False
        return True

    def initialChecksSetup(self):
        # Создаем объект переменных
        self.createClVars()
        """Начальная проверка перед запуском метода setup"""
        if self.clVars.Get("sr_mail_relay_set") == "on":
            self.printERROR(_("This server is a mail relay. \
This command is not allowed."))
            return False
        return True


    def chownR(self, directory, uid, gid):
        """изменяет владельца и группу

        для всех файлов и директорий внутри directory
        """
        fileObj = cl_profile._file()
        scanObjs = fileObj.scanDirs([directory])
        # меняем владельца домашней директории
        os.chown(directory, uid,gid)
        # Меняем владельца директорий
        for dirCh in scanObjs[0].dirs:
            os.chown(dirCh, uid,gid)
        # Меняем владельца файлов
        for fileCh in scanObjs[0].files:
            os.chown(fileCh, uid,gid)
        # Меняем владельца ссылок
        for linkCh in scanObjs[0].links:
            os.lchown(linkCh[1], uid, gid)
        return True

    @adminConnectLdap
    def modAttrsDN(self, relDN, modAttrs):
        """Модифицирует аттрибуты DN"""
        DN = self.addDN(relDN,self.baseDN)
        if modAttrs:
            try:
                self.conLdap.modify_s(DN, modAttrs)
            except ldap.LDAPError, e:
                self.printERROR(e[0]['desc'])
                return False
        return True

    @adminConnectLdap
    def modifyElemDN(self, relDN, newFirstDn):
        """Изменяет основной элемент DN (uid, cn и др.)"""
        DN = self.addDN(relDN,self.baseDN)
        try:
            self.conLdap.modrdn_s(DN, newFirstDn)
        except ldap.LDAPError, e:
            self.printERROR(e[0]['desc'])
            return False
        return True

    @adminConnectLdap
    def delDN(self, relDN):
        """Удаляет одиночный DN"""
        DN = self.addDN(relDN,self.baseDN)
        try:
            self.conLdap.delete_s(DN)
        except ldap.LDAPError, e:
            self.printERROR(e[0]['desc'])
            return False
        return True


    def getMaxAttrDN(self, relDN, name, attr, numMin, numMax, attrSearch):
        """Находит максимальный добавленный аттрибут в LDAP DN"""
        resSearch = self.searchLdapDN(name, relDN, attr, [attrSearch])
        lst = []
        lst.append(0)
        if resSearch:
            for scope in resSearch:
                if scope[0][1].has_key(attrSearch):
                    uid = int(scope[0][1][attrSearch][0])
                    if uid<=numMax and uid>=numMin:
                        lst.append(uid)
            return max(lst)
        return False

    @adminConnectLdap
    def fullElementDNtoText(self, relDN="", ldapFilter='(objectclass=*)'):
        """Выводит все внутренние элементы DN виде текста"""
        DN = self.addDN(relDN, self.baseDN)
        listDN=[]
        try:
            dnList = self.conLdap.search_s(DN,
                                            ldap.SCOPE_SUBTREE,
                                            ldapFilter,None)
        except ldap.LDAPError, e:
            self.printERROR("fullElementDN: "+e[0]['desc'])
            return False
        FDOUT = StringIO.StringIO("")
        writer = LDIFWriter(FDOUT)
        for dn, f in dnList:
            writer.unparse(dn, f)
        FDOUT.seek(0)
        return FDOUT.read()

    @adminConnectLdap
    def fullElementSambaDNtoText(self, relDN=""):
        """Выводит все внутренние элементы ветки Samba в виде текста"""
        return self.fullElementDNtoText(relDN,'(|(|(|(|(ou:dn:=Samba)\
(ou:dn:=Unix))(ou:dn:=LDAP))(!(ou:dn:=Services)))(ou=Services))')

    @adminConnectLdap
    def fullElementUnixDNtoText(self, relDN=""):
        """Выводит все внутренние элементы ветки Unix в виде текста"""
        return self.fullElementDNtoText(relDN,'(|(|(|(ou:dn:=Unix)\
(ou:dn:=LDAP))(!(ou:dn:=Services)))(ou=Services))')

    @adminConnectLdap
    def fullElementMailDNtoText(self, relDN=""):
        """Выводит все внутренние элементы ветки Mail в виде текста"""
        baseDN = self.clVars.Get("ld_base_dn")
        baseDNName, baseLogin = baseDN.split(",")[0].split("=")
        proxyDN = self.clVars.Get("ld_bind_dn")
        proxyDNName, proxyLogin = proxyDN.split(",")[0].split("=")
        #return self.fullElementDNtoText(relDN,'(&(|(|(&(ou:dn:=Replication)\
#(ou:dn:=Mail))(!(ou:dn:=Services)))(ou=Services))(!(&(%s:dn:=%s)\
#(%s:dn:=%s))))'%(proxyDNName, proxyLogin, baseDNName, baseLogin))
        return self.fullElementDNtoText(relDN,'(&(&(|(|(|(ou:dn:=LDAP)\
(ou=Mail))(!(ou:dn:=Services)))(ou=Services))(!(&(%s:dn:=%s)(%s:dn:=%s))))\
(!(ou:dn:=Worked)))'%(proxyDNName, proxyLogin, baseDNName, baseLogin))

    @adminConnectLdap
    def fullElementMailSambaDNtoText(self, relDN=""):
        """Выводит все внутренние элементы ветки Samba и Mail в виде текста"""
        return self.fullElementDNtoText(relDN,'(&(|(|(|(|(|(ou:dn:=Samba)\
(ou:dn:=Unix))(ou:dn:=LDAP))(ou:dn:=Mail))(!(ou:dn:=Services)))(ou=Services))\
(!(|(&(&(ou:dn:=Users)(ou:dn:=Mail))(uid=*))(&(&(ou:dn:=Groups)(ou:dn:=Mail))\
(cn=*)))))')

    @adminConnectLdap
    def fullElementMailUnixDNtoText(self, relDN=""):
        """Выводит все внутренние элементы ветки Unix и Mail в виде текста"""
        return self.fullElementDNtoText(relDN,'(&(|(|(|(|(ou:dn:=Unix)\
(ou:dn:=LDAP))(ou:dn:=Mail))(!(ou:dn:=Services)))(ou=Services))\
(!(|(&(&(ou:dn:=Users)(ou:dn:=Mail))(uid=*))(&(&(ou:dn:=Groups)(ou:dn:=Mail))\
(cn=*)))))')

    def deleteServiceVarsInFile(self, service):
        """Удаляет переменные сервиса из ini файлов

        После запуска этого метода объект self.clVars должен быть пересоздан
        """
        importVarsDict = self.createClVars(False,True)
        serviceNameVars = "_%s_" %service
        for location in importVarsDict.keys():
            for nameVar in importVarsDict[location]:
                # Если имя сервиса присутствует в переменной -
                # Удаляем переменную
                if serviceNameVars in nameVar:
                    if not self.clVars.Delete(nameVar, location, "server"):
                        return False
        self.clVars = False
        return True

    @adminConnectLdap
    def deleteDN(self, relDelDN):
        """Удаляет DN и все внутренние элементы"""
        delDN = self.addDN(relDelDN, self.baseDN)
        delListDN=[]
        try:
            dnList = self.conLdap.search_s(delDN,
                                            ldap.SCOPE_SUBTREE,
                                            '(objectclass=*)',
                                            [''])
        except ldap.LDAPError, e:
            self.printERROR("deleteDN: "+e[0]['desc'])
            return False
        for dn, f in dnList:
            delListDN.append(dn)
        delListDN.sort(lambda x, y: cmp(len(y), len(x)))
        for dn in delListDN:
            try:
                self.conLdap.delete_s(dn)
            except ldap.LDAPError, e:
                self.printERROR("deleteDN: "+e[0]['desc'])
                return False
        return True

    def execProg(self, cmdStrProg, inStr=False, retFull=True):
        """Выполняет внешнюю программу

        Параметры:
        cmdStrProg     внешняя программа
        inStr          данные передаваемые программе на страндартный вход.
        Возвращаемые параметры:
        строка которую выведет внешняя программа
        """
        return cl_utils.runOsCommand(cmdStrProg, inStr, retFull)


    def createLdif(self, ldifFile):
        """Cоздает ldif из ldif - профиля"""
        if not os.access(ldifFile, os.F_OK):
            self.setError(_("File not found") + ":\n  " + ldifFile)
            return False
        FD = open (ldifFile)
        ldifProfile = FD.read()
        FD.close()
        clProf = cl_profile.profile(self.clVars)
        # Применяем условия к профилю
        ldifProfile = clProf.applyTermsProfile(ldifProfile,ldifFile)
        # Заменяем переменные
        ldifProfile = clProf.applyVarsProfile(ldifProfile,ldifFile)
        return ldifProfile

    def searchLineInFile(self, name, fileName, numEl=0):
        """Ищет строку в которой есть название разделенное ':'

        в файле похожем на /etc/passwd"""
        if os.path.exists(fileName):
            FD = open(fileName)
            lines = FD.readlines()
            FD.close()
            lineFound = ""
            for line in lines:
                if name == line.split(":")[numEl]:
                    lineFound = line
                    break
        if lineFound:
            return lineFound
        else:
            return False

    def getMaxInFile(self, fileName, numMin, numMax, numEl=2):
        """Получаем максимальный номер из файла похожего на /etc/group"""
        lst = []
        lst.append(0)
        if os.path.exists(fileName):
            FD = open(fileName)
            lines = FD.readlines()
            FD.close()
            for line in lines:
                if not line in ":":
                    continue
                num = int(line.split(":")[numEl])
                if num<=numMax and num>=numMin:
                    lst.append(num)
            return max(lst)
        return False

    def getLdapObjInFile(self, part="admin"):
        """Получаем объект ldapFunction из ini файла

        В выходном объекте есть соединение с LDAP сервером: self.conLdap
        """
        ldapParser = iniLdapParser()
        adminDn = ldapParser.getVar(part,"DN")
        adminPw = ldapParser.getVar(part,"PASS")
        if not (adminDn or adminPw):
            if part == "admin":
                service = "LDAP"
            else:
                service = part
            self.printERROR(\
            _("Admin password for the service %s could not be found")%service+\
              " ...")
            return False
        ldapObj = ldapFunction(adminDn, adminPw)
        if ldapObj.getError():
            self.printERROR (_("LDAP connect error") + ": " +\
                ldapObj.getError().strip())
            return False
        # Устанавливаем у объекта соединение и объект LDAP функций
        self.ldapObj = ldapObj
        self.conLdap = ldapObj.conLdap
        return True

    def dialogYn(self, message):
        def getChar():
            fd = sys.stdin.fileno()
            oldSet = termios.tcgetattr(fd)
            tty.setraw(fd)
            char = sys.stdin.read(1)
            termios.tcsetattr(fd, termios.TCSADRAIN, oldSet)
            return char
        def term(char):
            if ord(char) == 3:
                return None
            if char == "Y":
                return True
            elif char == "n":
                return False
            else:
                char = getChar()
                return term(char)
        sys.stdout.write(message + ":")
        char = getChar()
        res = term(char)
        sys.stdout.write("\n")
        return res

    def dialogYesNo(self, message):
        sys.stdout.write(message + ": ")
        strIn=sys.stdin.readline().lower().strip()
        sys.stdout.write("\n")
        if "yes" == strIn:
            return True
        elif "no" == strIn:
            return False
        else:
            return self.dialogYesNo(message)

    def createClVars(self, clVars=False, returnImportVar=False):
        """Создает объект Vars"""
        # Словарь импортируемых переменных из ini Файлов
        dictImportVars = {}
        if not clVars:
            clVars = cl_base.DataVars()
            clVars.flServer()
            dictImportVars = clVars.flIniFile()
            # Устанавливаем у объекта объект Vars
            self.clVars = clVars
        if returnImportVar:
                return dictImportVars
        return True

    @adminConnectLdap
    def searchLdapDN(self, name, relDN, attr, retAttr=None):
        """Находит DN в LDAP"""
        DN = self.addDN(relDN,self.baseDN)
        #searchScope = ldap.SCOPE_SUBTREE
        searchScope = ldap.SCOPE_ONELEVEL
        searchFilter = "%s=%s" %(attr,name)
        retrieveAttributes = retAttr
        resSearch = self.ldapObj.ldapSearch(DN, searchScope,
                           searchFilter, retrieveAttributes)
        return resSearch

class servUnix(shareLdap):
    """Методы севисa Unix"""

    # минимальное и максимальное значение gid-ов системных групп
    #(Computers, и.т. д)
    maxSysGid = 999
    minSysGid = 900
    relGrDN = 'ou=Groups'
    relUsDN = 'ou=Users'
    relServDN = 'ou=Unix'
    # Коментарий к группе по умолчанию
    groupGecos = "Calculate group"
    # Базовая директория пользователей
    baseDir = "/home"
    # Название пользователя по умолчанию
    fullNameUser = "Calculate user"
    # Оболочка пользователя по умолчанию
    userShell = "/bin/bash"
    # Скелетная директория для создания пользователя
    skelDir = "/etc/skel"
    # Алгоритм шифрования пароля для LDAP пользователя
    userCrypt = "ssha"
    # Используемые 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"

    def __init__(self, smbObj=False):
        shareLdap.__init__(self)
        # максимальный и минимальный uid
        self.maxUid = self.getUidMax()
        self.minUid = self.getUidMin()
        # максимальный и минимальный gid
        self.maxGid = self.maxUid
        self.minGid = self.minUid
        self.relDN = self.addDN(self.relServDN,self.ServicesDN)
        # DN пользователей, относительно базового DN
        self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
        # DN групп пользователей, относительно базового DN
        self.relGroupsDN = self.addDN(self.relGrDN, self.relDN)
        if smbObj:
            # получаем объект сервиса Samba
            self.servSambaObj = smbObj
        else:
            # создаем объект сервиса Samba
            self.servSambaObj = servSamba(self)
        # создаем объект сервиса Mail
        self.servMailObj = servMail(self)
        # DN, компьютеров относительно базового DN
        self.relComputersDN = self.servSambaObj.relComputersDN

    def getLdapObjInFile(self):
        """Cоединение с LDAP администратором Unix сервиса"""
        return shareLdap.getLdapObjInFile(self, "unix")

    def createHomeDir(self, userName, homeDir, skelDir):
        """Создаем домашнюю директорию пользователя

        создание происходит после создания пользователя
        """
        resLdap = self.searchUnixUser(userName)
        if resLdap:
            uid = int(resLdap[0][0][1]['uidNumber'][0])
            gid = int(resLdap[0][0][1]['gidNumber'][0])
        else:
            return False
        if not os.path.exists(homeDir):
            # Создаем домашнюю директорию
            os.makedirs(homeDir)
            # Файловый объект
            fileObj = cl_profile._file()
            # Сканируем скелетную директорию
            scanObjs = fileObj.scanDirs([skelDir])
            if not scanObjs:
                return True
            for dirCreate in scanObjs[0].dirs:
                #создаем в домашней директории директории из /etc/skel
                fileObj.createDir(skelDir, dirCreate, homeDir)
                dirName = homeDir + dirCreate.split(skelDir)[1]
                os.chown(dirName, uid,gid)
            for fileCopy in scanObjs[0].files:
                oldFile = homeDir + fileCopy.split(skelDir)[1]
                #копируем файлы
                fileObj.openFiles(fileCopy, oldFile)
                fileObj.saveOldFile()
                fileObj.oldProfile = False
                fileObj.closeFiles()
                os.chown(oldFile, uid,gid)
            for linkCreate in scanObjs[0].links:
                #копируем ссылки
                dst = homeDir + linkCreate[1].split(skelDir)[1]
                srcHomeList = linkCreate[0].split(skelDir)
                if len(srcHomeList)>1:
                    src = homeDir + srcHomeList[1]
                else:
                    src = linkCreate[0]
                os.symlink(src,dst)
                #Изменение прав на ссылки
                os.lchown(dst, uid, gid)
            os.chmod(homeDir, 0700)
            os.chown(homeDir, uid,gid)
        return True

    def searchPasswdUser(self, userName):
        """Ищет пользователей в /etc/passwd"""
        filePasswd = "/etc/passwd"
        return self.searchLineInFile(userName, filePasswd)

    def searchGroupGid(self, groupId):
        """Ищет gid в /etc/group"""
        gid = str(groupId)
        fileGroup = "/etc/group"
        return self.searchLineInFile(gid, fileGroup, 2)

    def searchGroupGroupName(self, groupName):
        """Ищет имя группы в /etc/group"""
        fileGroup = "/etc/group"
        return self.searchLineInFile(groupName, fileGroup)

    def searchUnixGroupName(self, groupName):
        """Находит группу сервиса Unix по её имени"""
        resSearch = self.searchLdapDN(groupName, self.relGroupsDN, "cn")
        return resSearch

    def searchUnixUser(self, userName):
        """Находит пользователя сервиса Unix"""
        resSearch = self.searchLdapDN(userName, self.relUsersDN, "uid")
        return resSearch

    def searchUnixUserPrimGroup(self, groupId):
        """Находит пользователей с первичной группой groupId"""
        resSearch = self.searchLdapDN(str(groupId), self.relUsersDN,
                                      "gidNumber")
        return resSearch

    def searchUnixGid(self, groupId):
        """Находит группу сервиса Unix по ёе id"""
        resSearch = self.searchLdapDN(str(groupId), self.relGroupsDN,
                                      "gidNumber")
        return resSearch

    def searchUnixMemberGid(self, userName):
        """Ищет группы сервиса Unix в котрых есть данный пользователь"""
        resSearch = self.searchLdapDN(userName, self.relGroupsDN,
                                      "memberUid")
        return resSearch

    def searchUidPasswd(self, userId):
        """Находит пользователя по его идентефикатору из /etc/passwd"""
        filePasswd = "/etc/passwd"
        return self.searchLineInFile(str(userId), filePasswd, 2)


    def searchUidUnix(self, userId):
        """Находит пользователя по его идентефикатору из LDAP"""
        resSearch = self.searchLdapDN(str(userId), self.relUsersDN,
                                      "uidNumber")
        return resSearch

    def searchGroupsUnix(self, userGroups, printError=True):
        """Ищет список групп из списка userGroups в LDAP

        Список групп может состоять из чисел или названий групп
        Возвращает список имен групп
        """
        userGroupNames = []
        flagInt = True
        for gid in userGroups:
            try:
                int(gid)
            except:
                flagInt = False
                break
        flagError = False
        if flagInt:
            for gidNumber in userGroups:
                res = self.searchUnixGid(gidNumber)
                if not res:
                    flagError = True
                    break
                userGroupNames.append(res[0][0][1]['cn'][0])
            if flagError:
                if printError:
                    self.printERROR(\
                        _("Group number %s is not found in Unix service") %\
                                str(gidNumber) + "...")
                return False
        else:
            for groupName in userGroups:
                res = self.searchUnixGroupName(groupName)
                if not res:
                    flagError = True
                    break
            if flagError:
                if printError:
                    self.printERROR(\
                        _("Group name %s is not found in Unix service") %\
                            str(groupName) + "...")
                return False
            userGroupNames = userGroups
        return userGroupNames

    def searchGroupsGroups(self, userGroups, printError=True):
        """Ищет список групп из списка userGroups в /etc/group

        Список групп может состоять из чисел или названий групп
        Возвращает список имен групп
        """
        userGroupNames = []
        flagInt = True
        for gid in userGroups:
            try:
                int(gid)
            except:
                flagInt = False
                break
        flagError = False
        if flagInt:
            for gidNumber in userGroups:
                res = self.searchGroupGid(gidNumber)
                if not res:
                    flagError = True
                    break
                userGroupNames.append(res.split(':')[0])
            if flagError:
                if printError:
                    self.printERROR(
                        _("Group number %s is not found in") %\
                          str(gidNumber) + " /etc/group ...")
                return False
        else:
            for groupName in userGroups:
                res = self.searchGroupGroupName(groupName)
                if not res:
                    flagError = True
                    break
            if flagError:
                if printError:
                    self.printERROR(
                        _("Group name %s is not found in") %\
                          str(groupName) + " /etc/group ...")
                return False
            userGroupNames = userGroups
        return userGroupNames

    def searchUsersInGroupUnix(self, usersNames, groupName):
        """Ищет спиcок пользователей в группе, ищет в Unix

        В случае успеха выводит список найденных пользователей
        если нет группы False
        если ничего не найдено пустой список
        """
        res = self.searchUnixGroupName(groupName)
        if not res:
            return False
        else:
            findUsers = []
            if res[0][0][1].has_key('memberUid'):
                usersInGroup = res[0][0][1]['memberUid']
                for userName in usersNames:
                    if userName in usersInGroup:
                        findUsers.append(userName)
            return findUsers

    def searchUsersInGroupGroup(self, usersNames, groupName):
        """Ищет спиcок пользователей в группе, ищет в /etc/groups

        В случае успеха выводит список найденных пользователей
        если нет группы False
        если ничего не найдено пустой список
        """
        res = self.searchGroupGroupName(groupName)
        if not res:
            return False
        else:
            findUsers = []
            res = res.rstrip()
            usersInGroup = res.split(':')[3]
            if not usersInGroup:
                return findUsers
            usersInGroup = usersInGroup.split(',')
            for userName in usersNames:
                if userName in usersInGroup:
                    findUsers.append(userName)
            return findUsers

    @adminConnectLdap
    def addGroupUnixServer(self, groupName, options, printSuccess=True):
        """Добавляет группу пользователей Unix"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        # Если группа существует выходим без ошибки
        flagSearchGroups = True
        if options.has_key('f'):
            flagSearchGroups = False
        if flagSearchGroups and self.searchGroupGroupName(groupName):
            self.printERROR(\
                    _("group name %s is found in") %  str(groupName) +\
                      " /etc/group ...")
            return False
        if self.searchUnixGroupName(groupName):
            self.printERROR(\
                    _("group name %s is found in Unix service") %\
                    str(groupName) + " ...")
            return False
        self.clVars.Set("ur_group",groupName)
        # номер группы
        gid = str(self.getMaxGid())
        if options.has_key('g'):
            gid = options['g']
            try:
                int(gid)
            except:
                self.printERROR(_("GID must be is number") + " ...")
                return False
        if flagSearchGroups and self.searchGroupGid(gid):
            self.printERROR(_("GID is found in") + " /etc/group ...")
            return False
        if self.searchUnixGid(gid):
            self.printERROR(_("GID is found in Unix service") + " ...")
            return False
        self.clVars.Set("ur_group_id", gid)
        # Коментарий к группе
        gecos = self.groupGecos
        if options.has_key('c'):
            gecos = options['c']
        self.clVars.Set("ur_group_comment",gecos)
        ldifFile = self.ldifFileGroup
        groupLdif = self.createLdif(ldifFile)
        if not groupLdif:
            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()
            return False
        if options.has_key('p'):
            sys.stdout.write(gid)
        else:
            if printSuccess:
                self.printSUCCESS(_("Added group in Unix service") + " ...")
        return True

    @adminConnectLdap
    def addMachineLdapServer(self, machineName, options):
        """Добавляет Unix машину в LDAP-сервер"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        machineLogin = machineName.replace('$','') + "$"
        groupName = self.clVars.Get('sr_samba_machine_group')
        resSearch = self.searchUnixGroupName(groupName)
        if resSearch:
            groupId = resSearch[0][0][1]['gidNumber'][0]
        else:
            gr = self.staticGroups["Computers"]
            groupId = gr.gid
            options = {'g':gr.gid,'c':gr.comment}
            if not self.addGroupUnixServer(groupName, options):
                return False
        self.clVars.Set('sr_samba_machine_login', machineLogin)
        # Находим последний добавленный id
        userIdNumber = str(self.getMaxUid())
        self.clVars.Set('sr_samba_machine_id',userIdNumber)
        self.clVars.Set('sr_samba_machine_gid',groupId)
        ldifFile = self.ldifFileMachine
        userLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            #Добавляем пользователя в LDAP
            self.ldapObj.ldapAdd(userLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        self.printSUCCESS(_("Added machine") + "...")
        return True

    @adminConnectLdap
    def addUserUnixServer(self,userName,options,printSuccess=True,pwd=False):
        """Добавляет Unix пользователя в LDAP-сервер"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        if self.searchUnixUser(userName):
            self.printERROR(_("User exists in Unix service"))
            return False
        elif self.searchPasswdUser(userName):
            self.printERROR(_("User exists in") + " /etc/passwd")
            return False
        # id нового пользователя
        userId = str(self.getMaxUid())
        self.clVars.Set("ur_name", userName)
        baseDir = self.baseDir
        # Базовая домашняя директория
        if options.has_key('b'):
            baseDir = options['b']
        # Устанавливаем скелетную директорию
        if options.has_key('k'):
            skelDir = options['k']
        else:
            skelDir = self.skelDir
        # Устанавливаем домашнюю директорию
        if options.has_key('d'):
            homeDir = options['d']
        else:
            homeDir = os.path.join(baseDir, userName)
        self.clVars.Set("ur_home_path",homeDir)

        fullNameUser = self.fullNameUser
        # Полное имя пользователя
        if options.has_key('c'):
            fullNameUser = options['c']
        self.clVars.Set("ur_fio",fullNameUser)
        # По умолчанию пользователя не видно
        visible = '0'
        if options.has_key('v'):
            visible = '1'
        self.clVars.Set("ur_visible",visible)
        # Оболочка пользователя
        userShell = self.userShell
        if options.has_key('s'):
            userShell = options['s']
        self.clVars.Set("ur_shell", userShell)

        # id пользователя
        if options.has_key('u'):
            userId = options['u']
            try:
                int(userId)
            except:
                self.printERROR(_("UID is not number") + " ...")
                return False
            if self.searchUidUnix(userId):
                self.printERROR("UID %s "%userId + \
                    _("exists in Unix service") + " ...")
                return False
            if self.searchUidPasswd(userId):
                self.printERROR("UID %s "%userId+_("exists in") + \
                        " /etc/passwd"+ " ...")
                return False

        self.clVars.Set("ur_id",userId)

        # Добавляем пользователя в группы (находим имена групп)
        if options.has_key('G'):
            userGroups = options['G'].split(',')
            #список имен добавляемых групп
            userGroupNames = self.searchGroupsUnix(userGroups)
            if not userGroupNames:
                return False

        userGid = str(self.getMaxGid())
        # Группа пользователя
        if options.has_key('g'):
            userGid = options['g']
            userGidNamesLdap = self.searchGroupsUnix([userGid], False)
            userGidNamesPasswd = self.searchGroupsGroups([userGid], False)
            if userGidNamesPasswd:
                #Имя группы пользователя
                groupName = userGidNamesPasswd[0]
            elif userGidNamesLdap:
                #Имя группы пользователя
                groupName = userGidNamesLdap[0]
            else:
                self.printERROR(
                    _("Group %s is not found") % str(userGid) + " ...")
                return False
        else:
            if self.searchGroupGroupName(userName):
                self.printERROR(
                    _("Group name %s is found in")%str(userName) +\
                            " /etc/group ...")
                return False
            if self.searchUnixGroupName(userName):
                self.printERROR(
                    _("Group name %s is found in Unix serivce")%str(userName)+\
                            " ...")
                return False
        if pwd:
            userPwd = pwd
        else:
            userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if not userPwd:
            userPwdHash = "crypt{xxx}"
        else:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
        if not userPwdHash:
            return False
        self.clVars.Set("ur_hash",userPwdHash)
        # флаги добавления
        flagAdd = {}
        # Добавление основной группы пользователя
        if options.has_key('g'):
            resLdap = self.searchUnixGroupName(groupName)
            resGroup = self.searchGroupGroupName(groupName)
            if not (resLdap or resGroup):
                self.printERROR (_("ERROR") + ": " +\
                    "gid=" + userGid + " " + _("is not found"))
                return False
            if resGroup:
                userGid = resGroup.split(":")[2]
            if resLdap:
                userGid = resLdap[0][0][1]['gidNumber'][0]
        else:
            flagAddGroup = self.addGroupUnixServer(userName,{},False)
            flagAdd['group'] = flagAddGroup
            if not flagAddGroup:
                return False
        self.clVars.Set("ur_gid", userGid)

        ldifFile = self.ldifFileUser
        userLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            #Добавляем пользователя в LDAP
            self.ldapObj.ldapAdd(userLdif)
            #ldapObj.ldapAdd(userLdif1)
            #Добавляем его в другие группы (опция G)
            if options.has_key('G') and userGroupNames:
                for group in userGroupNames:
                    self.addUsersGroupUnix([userName],group)
        # не переделывать на else
        flagError = False
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            flagError = True
        removeHomeBack = False
        if not flagError:
            # Востановим (home на сервере) удаленного пользователя
            message = _("Do you want to restore deleted user %s data?")\
                      %userName + "\n" + "'yes', 'no'"
            resHomeDir = self.restorePathDelUser(userName, homeDir,
                                                    "unix/home", message, self)
            if not resHomeDir:
                flagError = True
                createDirHome = False
            else:
                term, createDirHome, removeHomeBack = resHomeDir
        # Удаляем бекап домашней директории на сервере (удаленного польз..)
        if not flagError and removeHomeBack and\
            os.path.exists(removeHomeBack):
            self.removeDir(removeHomeBack)
            self.removeEmptyDir(os.path.split(removeHomeBack)[0])
        # Изменим время последнего измения пароля пользователя
        if not flagError and not self.setShadowLastChange(userName):
            flagError = True
        # Добавим домашнюю директорию
        if not flagError and createDirHome and options.has_key('m'):
            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'):
            photoFile = options['i']
            if not self.setJpegPhotoUser(userName, photoFile):
                self.printERROR(_("Can not add jpeg photo for user") + " " +\
                                str(userName))
                flagError = True
        if flagError:
            self.delUserUnixServer(userName, {}, False, False)
            self.printERROR (_("Can not add user")+ " " + str(userName))
            return False
        if printSuccess:
            if flagAdd.has_key('group'):
                self.printSUCCESS(_("Added group in Unix service") + " ...")
            if createDirHome and options.has_key('m'):
                self.printSUCCESS(_("Created home dir %s")% homeDir+\
                                    " ...")
            if options.has_key('i'):
                self.printSUCCESS(_("Added jpeg photo %s")% photoFile+\
                                    " ...")
            self.printSUCCESS(_("Added user in Unix service") + " ...")
        return True

    def setUserJabberID(self, userName, jabberID):
        """Устанавливает для пользователя jabberID"""
        searchUser = self.searchUnixUser(userName)
        if not searchUser:
            return True
        modAttrs = []
        if searchUser[0][0][1].has_key('registeredAddress'):
            modAttrs.append((ldap.MOD_REPLACE, 'registeredAddress', jabberID))
        else:
            modAttrs.append((ldap.MOD_ADD, 'registeredAddress', jabberID))
        userDN = self.addDN('uid='+userName,self.relUsersDN)
        if not self.modAttrsDN(userDN, modAttrs):
            self.printERROR(_("Can not modify registeredAddress attribute in \
Unix service"))
            return False
        return True

    def getUserJabberID(self, userName):
        """Выдаем jabberID"""
        searchUser = self.searchUnixUser(userName)
        if not searchUser:
            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]
        else:
            return ""

    def deleteUserJabberID(self, userName):
        """Удаляет jabberID пользователя"""
        if self.getUserJabberID(userName):
            modAttrs =[(ldap.MOD_DELETE, 'registeredAddress', None)]
            userDN = self.addDN('uid='+userName,self.relUsersDN)
            if not self.modAttrsDN(userDN, modAttrs):
                self.printERROR(_("Can not delete registeredAddress attribute \
in Unix service"))
                return False
        return True

    def setUserMail(self, userName, mail):
        """Устанавливает для пользователя основной почтовый адрес"""
        searchUser = self.searchUnixUser(userName)
        if not searchUser:
            self.printERROR(_("User %s not found in Unix service")\
                %str(userName))
            return False
        modAttrs = []
        if searchUser[0][0][1].has_key('mail'):
            modAttrs.append((ldap.MOD_REPLACE, 'mail', mail))
        else:
            modAttrs.append((ldap.MOD_ADD, 'mail', mail))
        userDN = self.addDN('uid='+userName,self.relUsersDN)
        if not self.modAttrsDN(userDN, modAttrs):
            self.printERROR(_("Can not modify mail attribute in Unix service"))
            return False
        return True

    def getUserMail(self, userName):
        """Выдаем основной почтовый адрес"""
        searchUser = self.searchUnixUser(userName)
        if not searchUser:
            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]
        else:
            return ""

    def deleteUserMail(self, userName):
        """Удаляет почтовый адрес пользователя"""
        if self.getUserMail(userName):
            modAttrs =[(ldap.MOD_DELETE, 'mail', None)]
            userDN = self.addDN('uid='+userName,self.relUsersDN)
            if not self.modAttrsDN(userDN, modAttrs):
                self.printERROR(_("Can not delete mail attribute in Unix \
service"))
                return False
        return True

    def addUsersGroupUnix(self, users, groupName):
        """Добавляет пользователей из списка в Unix группу"""
        if not self.searchUnixGroupName(groupName):
            self.printERROR(_("group name is not found in Unix service") +\
                              " ...")
            return False
        flagFalse = False
        for userName in users:
            if not (self.searchUnixUser(userName) or\
                self.searchPasswdUser(userName)):
                self.printERROR(\
                     _("User %s is not found")%str(userName) + " ..." )
                flagFalse = True
                break
        if flagFalse:
            return False
        foundUsersLdap = self.searchUsersInGroupUnix(users, groupName)
        foundUsersGroup = self.searchUsersInGroupGroup(users, groupName)
        foundUsers = []
        if foundUsersLdap and foundUsersGroup:
            foundUsers = self.unicList(foundUsersLdap + foundUsersGroup)
        elif foundUsersLdap:
            foundUsers = foundUsersLdap
        elif foundUsersGroup:
            foundUsers = foundUsersGroup
        addUsers = []
        for user in users:
            if not(user in foundUsers):
                addUsers.append(user)
        modAttrs = []
        for userName in addUsers:
            modAttrs.append((ldap.MOD_ADD, 'memberUid', userName))
        if modAttrs:
            groupDN = self.addDN("cn="+groupName, self.relGroupsDN)
            return self.modAttrsDN(groupDN, modAttrs)
        return True

    def getMaxGidUnix(self):
        """Находит максимальный добавленный gid в Unix"""
        return self.getMaxAttrDN(self.relGroupsDN, "*", "cn",
                                 self.minGid, self.maxGid, "gidNumber")

    def getMaxGidUnixSystem(self):
        """Находит максимальный добавленный gid в LDAP системной группы"""
        return self.getMaxAttrDN(self.relGroupsDN, "*", "cn",
                                 self.minSysGid, self.maxSysGid, "gidNumber")

    def getMaxGid(self):
        """Находит максимальный gid +1"""
        maxGidLdap = self.getMaxGidUnix()
        maxGidGroup = self.getMaxGidGroup()
        if maxGidLdap > maxGidGroup:
            maxGid = maxGidLdap
        else:
            maxGid = maxGidGroup
        if maxGid == 0:
            return self.minGid
        else:
            return maxGid+1

    def getMaxGidGroupSystem(self):
        """Получаем максимальный добавленный gid из /etc/group

        системной группы
        """
        fileGroup = "/etc/group"
        return self.getMaxInFile(fileGroup, self.minSysGid, self.maxSysGid)

    def getMaxGidGroup(self):
        """Получаем максимальный добавленный gid из /etc/group"""
        fileGroup = "/etc/group"
        return self.getMaxInFile(fileGroup, self.minGid, self.maxGid)


    def getMaxGidSystem(self):
        """Находит максимальный gid +1 системной группы"""
        maxGidLdap = self.getMaxGidUnixSystem()
        maxGidGroup = self.getMaxGidGroupSystem()
        if maxGidLdap > maxGidGroup:
            maxGid = maxGidLdap
        else:
            maxGid = maxGidGroup
        if maxGid == 0:
            return self.minSysGid
        else:
            return maxGid+1

    def getUidMin(self):
        """Получаем начальный UID пользователя"""
        fileLogin = "/etc/login.defs"
        fileAdduser = "/etc/adduser.conf"
        minUid = 1000
        if os.path.exists(fileLogin):
            FD = open(fileLogin)
            lines = FD.readlines()
            FD.close()
            for line in lines:
                if "UID_MIN" in line and not "#" in line:
                    s = re.compile("\s+")
                    minUid = int(s.split(line)[1])
                    break
        elif os.path.exists(fileAdduser):
            FD = open(fileLogin)
            lines = FD.readlines()
            FD.close()
            for line in lines:
                if "FIRST_UID" in line and not "#" in line:
                    minUid = int(line.split('=')[1])
                    break
        return minUid

    def getUidMax(self):
        """Получаем конечный UID пользователя"""
        fileLogin = "/etc/login.defs"
        fileAdduser = "/etc/adduser.conf"
        maxUid = 29999
        if os.path.exists(fileLogin):
            FD = open(fileLogin)
            lines = FD.readlines()
            FD.close()
            for line in lines:
                if "UID_MAX" in line and not "#" in line:
                    s = re.compile("\s+")
                    maxUid = int(s.split(line)[1])
                    break
        elif os.path.exists(fileAdduser):
            FD = open(fileLogin)
            lines = FD.readlines()
            FD.close()
            for line in lines:
                if "LAST_UID" in line and not "#" in line:
                    maxUid = int(line.split('=')[1])
                    break
        return maxUid

    def getMaxUidPasswd(self):
        """Получаем максимальный добавленный id из /etc/passwd"""
        filePasswd = "/etc/passwd"
        return self.getMaxInFile(filePasswd, self.minUid, self.maxUid)

    def getMaxUidUnix(self, relDn=False):
        """Находит максимальный добавленный id в сервисе Unix"""
        if relDn:
            return self.getMaxAttrDN(relDn, "*", "uid",
                                 self.minUid, self.maxUid, "uidNumber")
        else:
            return self.getMaxAttrDN(self.relUsersDN, "*", "uid",
                                 self.minUid, self.maxUid, "uidNumber")

    def getMaxUid(self):
        """Находит максимальный id +1"""
        # Ветка компьютеры
        maxUidLdapComp = self.getMaxUidUnix(self.relComputersDN)
        maxUidLdap = self.getMaxUidUnix()
        maxUidPasswd = self.getMaxUidPasswd()
        listUid = [maxUidLdapComp, maxUidLdap, maxUidPasswd]
        maxUid = max(listUid)
        if maxUid == 0:
            return self.minUid
        else:
            return maxUid+1

    def delUserUnixServer(self, userName, options, printSuccess=True,
        backup=True):
        """Удаляем Unix пользователя"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        # Ищем пользователя в Samba
        if self.isServiceSetup("samba", False) and\
            self.servSambaObj.searchSambaUser(userName):
            self.printERROR (_("ERROR") + ": " +\
                    _("User %s is found in Samba service") %\
                      str(userName) + " ...")
            self.printWARNING(\
                    _("At first, need remove user from Samba service")
                )
            return False
        # Ищем пользователя в Mail
        if self.isServiceSetup("mail", False) and\
            self.servMailObj.searchMailUserToName(userName):
            self.printERROR (_("ERROR") + ": " +\
                    _("User %s is found in Mail service") %\
                      str(userName) + " ...")
            self.printWARNING(\
                    _("At first, need remove user from Mail service")
                )
            return False
        # Ищем пользователя в Unix
        resLdap = self.searchUnixUser(userName)
        if not resLdap:
            self.printERROR (_("ERROR") + ": " +\
                _("User %s is not found in Unix service") % str(userName) +\
                  " ...")
            return False
        if options.has_key('r'):
            backup = False
        homeDir = False
        if resLdap[0][0][1].has_key('homeDirectory'):
            #Домашняя директория пользователя
            homeDir = resLdap[0][0][1]['homeDirectory'][0]
            if backup and os.path.exists(homeDir) and\
                os.path.isdir(homeDir) and os.listdir(homeDir):
                # Делаем сохранение домашней директории
                if not self.backupDelUser(userName, 'unix/home',
                                          homeDir, self):
                    return False
        # Удаляем пользователя
        delDN = self.addDN("uid=" + userName, self.relUsersDN)
        if not self.delDN(delDN):
            return False
        # Удаляем пользователя из групп
        if not self.delUserInGroup(userName):
            return False
        if resLdap[0][0][1].has_key('gidNumber'):
            gid = resLdap[0][0][1]['gidNumber'][0]
        else:
            resPasswd = self.searchPasswdUser(userName)
            if resPasswd:
                gid = resPasswd.split(":")[3]
        #Находим основную группу пользователя
        resGroup = False
        if gid:
            resGroup = self.searchUnixGid(gid)
        if resGroup:
            # В случае отсутствия других пользователей удаляем основную группу
            if not resGroup[0][0][1].has_key('memberUid'):
                groupName = resGroup[0][0][1]['cn'][0]
                if not self.delGroupUnixServer(groupName, {}, False):
                    return False
        # Удаляем пользователя из ветки Worked в случае репликации
        objRepl = servRepl()
        if not objRepl.delReplWorkedUser(userName):
            self.printERROR (_("ERROR") + ": " +\
                _("Can not remove user %s in the LDAP branch 'Worked'")\
                % str(userName) + " ...")
            return False
        # Удаляем домашнюю директорию
        if homeDir and os.path.exists(homeDir) and os.path.isdir(homeDir)\
            and self.removeDir(homeDir):
            if printSuccess:
                self.printSUCCESS(
                _("Home directory %s is removed")% str(homeDir) + " ...")
        if printSuccess:
            self.printSUCCESS(_("User %s is deleted")%userName + " ...")
        return True

    def delGroupUnixServer(self, groupName, options, printSuccess=True):
        """Удаляет группу пользователей Unix"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        res = self.searchUnixGroupName(groupName)
        if not res:
            self.printERROR(
                _("Group %s is not found in Unix service")%groupName +\
                  " ...")
            return False
        groupId = res[0][0][1]['gidNumber'][0]
        if self.searchUnixUserPrimGroup(groupId):
            self.printWARNING(_("cannot remove user's primary group") + ".")
            return True
        delDN = self.addDN("cn="+groupName, self.relGroupsDN)
        res = self.delDN(delDN)
        if res:
            if printSuccess:
                self.printSUCCESS( _("Group %s is deleted")%groupName+" ...")
            return True
        else:
            self.printERROR(_("Can not delete group") + " " + groupName+\
                              " ...")
            return False

    def modUserUnixServer(self,userName, options, printSuccess=True):
        """Модифицирует настройки пользователя Unix в LDAP"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        res = self.searchUnixUser(userName)
        if not res:
            self.printERROR(
                _("User %s is not found in Unix service")%str(userName)+\
                  "...")
            return False
        # Новые группы в которые входит пользователь
        if options.has_key('G'):
            userGroups = options['G'].split(',')
            #список имен добавляемых групп
            userGroupNames = self.searchGroupsUnix(userGroups)
            if not userGroupNames:
                return False
            # Удаляем пользователя из групп в которые он входит
            if not self.delUserInGroup(userName):
                return False
            flagError = False
            for group in userGroupNames:
                if not self.addUsersGroupUnix([userName], group):
                    flagError = True
                    break
            if flagError:
                return False
            if printSuccess:
                self.printSUCCESS(_("Replaced list of supplementary group")+\
                                    " ...")
        # Добавляем группы в которые входит пользователь
        elif options.has_key('a'):
            userGroups = options['a'].split(',')
            #список имен добавляемых групп
            userGroupNames = self.searchGroupsUnix(userGroups)
            if not userGroupNames:
                return False
            flagError = False
            for group in userGroupNames:
                if not self.addUsersGroupUnix([userName], group):
                    flagError = True
                    break
            if flagError:
                return False
            if printSuccess:
                self.printSUCCESS(\
                _("Appended the user to the supplemental groups") + " ...")
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Изменяем первичную группу пользователя
        if options.has_key('g'):
            newFirstGroup = options['g']
            userGroupNames = self.searchGroupsUnix([newFirstGroup])
            if not userGroupNames:
                return False
            groupName = userGroupNames[0]
            resLdap = self.searchUnixGroupName(groupName)
            resGroup = self.searchGroupGroupName(groupName)
            if not (resLdap or resGroup):
                self.printERROR (_("ERROR") + ": " +\
                    _("not found gid=") + userGid)
                return False
            if resGroup:
                userGid = resGroup.split(":")[2]
            if resLdap:
                userGid = resLdap[0][0][1]['gidNumber'][0]
            modAttrs += [(ldap.MOD_REPLACE, 'gidNumber', userGid)]
        visible = False
        # пользователя видно
        if options.has_key('V'):
            visible = '1'
        # пользователя не видно
        if options.has_key('I'):
            visible = '0'
        if visible:
            modAttrs += [(ldap.MOD_REPLACE, 'shadowFlag', visible)]
        # Изменяем домашнюю директорию
        if options.has_key('d'):
            homeDir = options['d']
            modAttrs += [(ldap.MOD_REPLACE, 'homeDirectory', homeDir)]
        # Включаем пользователя
        if options.has_key('U'):
            modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "-1")]
        # Выключаем пользователя
        if options.has_key('L'):
            modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "1")]
        # Изменяем коментарий к пользователю
        if options.has_key('c'):
            comment = options['c']
            if res[0][0][1].has_key('displayName'):
                modAttrs += [(ldap.MOD_REPLACE, 'displayName', comment),
                            (ldap.MOD_REPLACE, 'cn', comment)]
            else:
                modAttrs += [(ldap.MOD_REPLACE, 'cn', comment)]
        # Изменяем оболочку пользователя
        if options.has_key('s'):
            shell = options['s']
            modAttrs.append((ldap.MOD_REPLACE, 'loginShell', shell))
        # Изменяем пароль пользователя
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if userPwd:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if res[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        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]
                homeDirNew = homeDir
                textLine = self.execProg("mv %s %s" %(homeDirOld, homeDirNew))
                if not (textLine == None):
                    self.printERROR(_("Can not move home directory") + " ...")
                    modAttrs = [(ldap.MOD_REPLACE, 'homeDirectory',
                                homeDirOld)]
                    self.modAttrsDN(DN, modAttrs)
                    return False
                else:
                    if printSuccess:
                        self.printSUCCESS(_("Moved home directory") + " ...")
            if options.has_key('c'):
                if printSuccess:
                    self.printSUCCESS(_("Modified comment") + " ...")
            if options.has_key('s'):
                if printSuccess:
                    self.printSUCCESS(_("Modified shell") + " ...")
            if options.has_key('d'):
                if printSuccess:
                    self.printSUCCESS(_("Modified home directory") + " ...")
            if options.has_key('P') or options.has_key('p'):
                # Изменим время последнего измения пароля пользователя
                if not self.setShadowLastChange(userName):
                    return False
                if printSuccess:
                    self.printSUCCESS(\
                                _("Modified user password of Unix service")+\
                                   " ...")
            if options.has_key('U'):
                if printSuccess:
                    self.printSUCCESS(_("Unlocked user %s")% str(userName) +\
                                      " ...")
            if options.has_key('I'):
                if printSuccess:
                    self.printSUCCESS(\
                            _("User %s is invisible")% str(userName) + " ...")
            if options.has_key('V'):
                if printSuccess:
                    self.printSUCCESS(_("User %s is visible")% str(userName)+\
                                      " ...")
            if options.has_key('L'):
                if printSuccess:
                    self.printSUCCESS(_("Locked user %s")% str(userName) +\
                                      " ...")
        return True

    def modUserUnixPasswd(self, userName, options, pwd=False):
        """Устанавливает пароль LDAP пользователя и меняет его опции"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        res = self.searchUnixUser(userName)
        if not res:
            self.printERROR(
                _("User %s is not found in Unix service")%str(userName) +\
                  " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Удаляем пароль пользователя
        if options.has_key('d'):
            if res[0][0][1].has_key('userPassword'):
                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")]
        # Выключаем пользователя
        elif options.has_key('l'):
            modAttrs += [(ldap.MOD_REPLACE, 'shadowExpire', "1")]
        if not options:
            optPasswd = {"p":""}
            if pwd:
                userPwd = pwd
            else:
                userPwd = self.getUserPassword(optPasswd, "p", False)
            if userPwd == False:
                return False
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if res[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))

        if modAttrs:
            DN = self.addDN("uid="+userName, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if options.has_key('d'):
                self.printSUCCESS(
                    _("Deleted password of Unix service for user") +\
                      str(userName) + " ...")
            if options.has_key('l'):
                self.printSUCCESS(_("Locked user") + " " + str(userName) +\
                    " " +_("of Unix service") + " ...")
            if options.has_key('u'):
                self.printSUCCESS(_("Unlocked user") + " " + str(userName) +\
                    " " +_("of Unix service") + " ...")
            if not options:
                self.printSUCCESS(_("User password of Unix service changed")+\
                    " ...")
                # Изменим время последнего измения пароля пользователя
                if not self.setShadowLastChange(userName):
                    return False
            return True
        return False

    def modGroupUnixServer(self, groupName, options):
        """Модифицирует настройки группы пользователей LDAP"""
        # Проверим установлен ли сервис unix
        if not self.initialChecks("unix"):
            return False
        if not self.searchUnixGroupName(groupName):
            self.printERROR(_("group name not found in Unix service") + " ...")
            return False
        # Добавляем список пользователей в группу
        if options.has_key('a'):
            # добавляемые пользователи в группу
            users = options['a'].split(',')
            res = self.addUsersGroupUnix(users, groupName)
            if res:
                self.printSUCCESS(_("Appended list of users to group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not append list of users to group") +\
                " " + str(groupName) + " ...")
                return False
        # Удаляем список пользователей из группы
        if options.has_key('d'):
            # удаляемые пользователи из группы
            users = options['d'].split(',')
            res = self.delUsersGroupUnix(users, groupName)
            if res:
                self.printSUCCESS(_("Deleted list users from group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not delete list users from group") +\
                                  " " + str(groupName) + " ...")
                return False
        modGroupName = groupName
        # Изменяем имя группы
        if options.has_key('n'):
            newGroupName = options['n']
            if self.searchUnixGroupName(newGroupName):
                self.printERROR(
                    _("group name %s is found in Unix service")%\
                        str(newGroupName) + " ...")
                return False
            newFirstDn = "cn=" + newGroupName
            oldDN = self.addDN("cn=" + groupName, self.relGroupsDN)
            res = self.modifyElemDN(oldDN, newFirstDn)
            if res:
                modGroupName = newGroupName
                self.printSUCCESS(_("Group renamed") + " ...")
            else:
                self.printERROR(_("Can not rename group") + "...")
                return False
        modAttrs = []
        # Изменяем коментарий к группе
        if options.has_key('c'):
            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'):
                    self.printSUCCESS(_("Modified group comment") + " ...")
                return True
            else:
                if options.has_key('c'):
                    self.printSUCCESS(_("Can not modify group comment") +\
                                      " ...")
                return False

        return True

    def delUserInGroup(self, userName):
        """Удаление из групп в которые входит пользователь"""
        userInGroups = self.searchUnixMemberGid(userName)
        modAttrs = [(ldap.MOD_DELETE, 'memberUid', userName)]
        flagError = False
        for group in userInGroups:
            groupName = group[0][1]['cn'][0]
            groupDN = self.addDN("cn=" + groupName, self.relGroupsDN)
            if not self.modAttrsDN(groupDN, modAttrs):
                flagError = True
                break
        if flagError:
            return False
        else:
            return True


    def delUsersGroupUnix(self, users, groupName):
        """Удаление пользователей из списка из группы Unix"""
        res = self.searchUnixGroupName(groupName)
        if not res :
            self.printERROR(_("group name is not found in Unix service") +\
                              " ...")
            return False
        if not res[0][0][1].has_key("memberUid"):
            self.printERROR(
                _("Member list of group %s is empty")%str(groupName) + " ...")
            return False
        memberUsers = res[0][0][1]["memberUid"]
        flagError =False
        for user in users:
            if not user in memberUsers:
                flagError = True
                break
        if flagError:
            self.printERROR(
                _("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)
        return self.modAttrsDN(groupDN, modAttrs)


    def setupUnixServer(self, options):
        """Начальная настройка Unix сервиса"""
        # Принудительная установка
        forceOptions = False
        # Создаем объект переменных и начальная проверка
        if not self.initialChecksSetup():
            return False
        if options.has_key("f"):
            forceOptions = True
        # В случае если сервер установлен
        if self.clVars.Get("sr_unix_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
            _("Unix service already configured")+ ".")
            return True
        if not self.clVars.Get("sr_ldap_set") == "on":
            self.printERROR(_("LDAP service not setuped") +" ...")
            self.printWARNING(_("Setup LDAP service"))
            self.printWARNING("  cl-setup ldap")
            return False
        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы и база данных сервиса LDAP
            self.printWARNING (_("WARNING") + ": " +
                _("Executing of the program will change") + " " +
                _("the configuration files and database of LDAP service")+
                ".")
            # если вы готовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program")+", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
        else:
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            bakupObj = servLdap()
            bakupObj.backupServer()
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","unix")
        self.clVars.Write("sr_unix_set","off")
        # Cоздаем объект профиль устанавливая директорию ldap для
        # файлов профилей
        if not self.applyProfilesFromService('unix'):
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        else:
            if not self.restartLdapServer():
                return False
        #Cоединение с Ldap (администратор)
        if not shareLdap.getLdapObjInFile(self):
            return False
        # Удаляем предыдущую ветку сервиса Unix
        servicesDN = self.relDN
        resSearch = self.searchService()
        ret = True
        if resSearch:
            delDN = self.relDN
            ret = self.deleteDN(delDN)
            if ret:
                self.printOK(_("Removed Unix DN from LDAP database") + " ...")
            else:
                self.printERROR(\
                    _("Can not remove Unix DN from LDAP database") + " ...")
        if not ret:
            return False
        ldifFile = self.ldifFileBase
        baseLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        self.printOK(_("Added ldif file") +" ...")
        # Записываем данные администратора сервиса Unix
        ldapParser = iniLdapParser()
        ldapParser.setVar("unix",
            {"DN":self.clVars.Get("ld_unix_dn"),
             "PASS":self.clVars.Get("ld_unix_pw")})
        self.printOK(_("Unix service configured") +" ...")
        self.clVars.Write("sr_unix_set","on")
        return True

    def setShadowLastChange(self, userName):
        """Изменим последнюю дату измениня пароля на текущую"""
        # число дней от 1970 года
        date = int(time.time()/86400)
        modAttrs = [(ldap.MOD_REPLACE, 'shadowLastChange', str(date))]
        userDN = self.addDN('uid='+userName,self.relUsersDN)
        if not self.modAttrsDN(userDN, modAttrs):
            self.printERROR(_("Can not modify shadowLastChange attribute"))
            return False
        return True

class servMail(shareLdap):
    """Методы сервиса Mail"""

    relGrDN = 'ou=Groups'
    relUsDN = 'ou=Users'
    relServDN = 'ou=Mail'
    ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/mail_base.ldif"
    ldifFileUser = "/usr/lib/calculate/calculate-server/ldif/mail_user.ldif"
    ldifFileGroup = "/usr/lib/calculate/calculate-server/ldif/mail_group.ldif"
    # Алгоритм шифрования пароля для Mail пользователя
    userCrypt = "ssha"

    def __init__(self,  unixObj=False):
        shareLdap.__init__(self)
        # DN сервиса
        self.relDN = self.addDN(self.relServDN,self.ServicesDN)
        # DN пользователей, относительно базового DN
        self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
        # DN групп пользователей, относительно базового DN
        self.relGroupsDN = self.addDN(self.relGrDN, self.relDN)
        # Директория хранения писем
        if unixObj:
            # получаем объект сервиса Unix
            self.servUnixObj = unixObj
        else:
            # создаем объект сервиса Unix
            self.servUnixObj = servUnix()

    def searchGroupsMail(self, userGroups, printError=True):
        """Ищет список групп из списка userGroups в Mail сервисе

        Список групп может состоять из названий групп или их почтовых адресов
        Возвращает список названий групп
        """
        userGroupNames = []
        flagError = False
        searchEmailGroup = True
        searchNameGroup = True
        for userGroup in userGroups:
            if "@" in userGroup:
                searchEmailGroup = self.searchGroupToMail(userGroup)
                if not searchEmailGroup:
                    flagError = True
                    break
                userGroupNames.append(searchEmailGroup[0][0][1]['cn'][0])
            else:
                searchNameGroup = self.searchMailGroupToName(userGroup)
                if not searchNameGroup:
                    flagError = True
                    break
                userGroupNames.append(userGroup)
        if flagError:
            if printError:
                if not searchEmailGroup:
                    self.printERROR(
                        _("Email address %s is not found in Mail service")%\
                            str(userGroup) + " ...")
                elif not searchNameGroup:
                    self.printERROR(
                        _("Group name %s is not found in Mail service")%\
                        str(userGroup) + " ...")
            return False
        return userGroupNames

    def delUserMailServer(self,userName,options,printSuccess=True,backup=True):
        """Удаляем Mail пользователя"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        # Ищем Mail пользователя
        resSearch = self.searchMailUserToName(userName)
        if not resSearch:
            self.printERROR (_("ERROR") + ": " +\
                _("User %s is not found in Mail service") % str(userName) +\
                  " ...")
            return False
        #почтовая директория пользователя
        mailDir = os.path.join(self.clVars.Get("sr_mail_path"),
                               userName)
        if options.has_key('r'):
            backup = False
        # Делаем сохранение данных удаляемого пользователя
        if backup and os.path.exists(mailDir) and os.listdir(mailDir):
            if not self.backupDelUser(userName, 'mail', mailDir):
                return False
        # Удаляем почту из Unix сервиса
        if self.servUnixObj.searchUnixUser(userName):
            if not self.servUnixObj.deleteUserMail(userName):
                return False
        # Удаляем реплицируемый алиас для этого пользователя
        if self.clVars.Get("ld_repl_mail_set") == "on":
            # Объект сервис репликации
            servReplObj = servRepl()
            if not servReplObj.delReplMailAlias(userName):
                self.printERROR (_("ERROR") + ": " +\
                                  _("Cannot delete email alias \
for user %s in 'Replication/Mail' branch ...") %str(userName) + " ...")
                return False
        # Удаляем пользователя из групп
        if not self.delUserInGroup(userName):
            return False
        # Удаляем пользователя
        delDN = self.addDN("uid=" + userName, self.relUsersDN)
        if not self.delDN(delDN):
            return False
        # Удаляем почтовую папку
        if os.path.exists(mailDir) and self.removeDir(mailDir):
            if printSuccess:
                self.printSUCCESS(\
                    _("Mail user directory %s is removed")% str(mailDir) +\
                            " ...")
        if printSuccess:
            self.printSUCCESS(_("Mail user %s is deleted")%userName +\
                            " ...")
        return True

    def searchMailGroupToName(self, groupName):
        """Находит группу сервиса Unix по её имени"""
        resSearch = self.searchLdapDN(groupName, self.relGroupsDN, "cn")
        return resSearch

    def searchMailGroup(self, nameOrMali):
        """Находит группу сервиса Mail по имени или email"""
        if "@" in nameOrMali:
            resSearch = self.searchGroupToMail(nameOrMali)
        else:
            resSearch = self.searchMailGroupToName(nameOrMali)
        return resSearch

    def searchMailMember(self, nameOrMail, printError=True):
        """Ищет группы сервиса Unix в котрых есть данный пользователь

        Поиск происходит по email или имени пользователя
        """
        resSearchUser = self.searchMailUser(nameOrMail)
        if not resSearchUser:
            if printError:
                self.printERROR(\
                    _("Mail user or email %s are not found in Mail service")%\
                        str(nameOrMail) + " ...")
            return False
        userMail = resSearchUser[0][0][1]['mail'][0]
        resSearchGroup = self.searchLdapDN(userMail, self.relGroupsDN,
                                      "rfc822member")
        return (userMail, resSearchGroup)

    def delUserInGroup(self, userName):
        """Удаление из групп в которые входит пользователь"""
        resSearch = self.searchMailMember(userName)
        if not resSearch:
            return False
        userMail = resSearch[0]
        userInGroups = resSearch[1]
        modAttrs = [(ldap.MOD_DELETE, 'rfc822member', userMail)]
        flagError = False
        for group in userInGroups:
            groupName = group[0][1]['cn'][0]
            groupDN = self.addDN("cn=" + groupName, self.relGroupsDN)
            if not self.modAttrsDN(groupDN, modAttrs):
                flagError = True
                break
        if flagError:
            return False
        else:
            return True

    def delUsersGroupMail(self, users, groupName):
        """Удаление пользователей из списка из группы Mail"""
        res = self.searchMailGroupToName(groupName)
        if not res :
            self.printERROR(_("group name is not found in Mail service") +\
                              " ...")
            return False
        if not res[0][0][1].has_key("rfc822member"):
            self.printERROR(\
                _("Member list of group %s is empty")%str(groupName)+" ...")
            return False
        memberMailUsers = res[0][0][1]["rfc822member"]
        flagError = False
        memberUsers = {}
        for mailUser in memberMailUsers:
            userName = mailUser.split("@")[0]
            memberUsers[userName] = mailUser
        for user in users:
            if not user in memberUsers.keys():
                flagError = True
                break
        if flagError:
            self.printERROR(\
                _("User %s is not found in group")%str(user)+" "+\
                str(groupName) + " ...")
            return False
        modAttrs = []
        for user in users:
            mailUser = memberUsers[user]
            modAttrs.append((ldap.MOD_DELETE, 'rfc822member', mailUser))
        groupDN = self.addDN("cn="+groupName, self.relGroupsDN)
        return self.modAttrsDN(groupDN, modAttrs)

    def delGroupMailServer(self, groupName, options):
        """Удаляет группу пользователей Mail"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        res = self.searchMailGroupToName(groupName)
        if not res:
            self.printERROR(
                _("Group %s is not found in Mail service")%groupName +\
                  " ...")
            return False
        delDN = self.addDN("cn="+groupName, self.relGroupsDN)
        res = self.delDN(delDN)
        if res:
            # В случае почтовой репликации удаляем алиас в ветке
            # Replication/Mail
            # Проверяем на включение почтовой репликации
            if self.clVars.Get("ld_repl_mail_set") == "on":
                # Объект сервис репликации
                servReplObj = servRepl()
                if not servReplObj.delReplMailAlias(groupName):
                    self.printERROR (_("ERROR") + ": " +\
                                     _("Cannot delete email alias \
for group %s in 'Replication/Mail' branch ...") %str(userName) + " ...")
                return False
            self.printSUCCESS( _("Mail group %s is deleted")%groupName + \
                                 " ...")
            return True
        else:
            self.printERROR(_("Can not delete Mail group") +\
                              " " + groupName + " ...")
            return False

    def delAlternateAddress(self, userName):
        """Удаление альтернативных адресов пользователя"""
        res = self.searchMailUserToName(userName)
        if not res:
            return False
        if not res[0][0][1].has_key('mailAlternateAddress'):
            return True
        modAttrs = [(ldap.MOD_DELETE, 'mailAlternateAddress', None)]
        userDN = self.addDN("uid=" + userName, self.relUsersDN)
        if not self.modAttrsDN(userDN, modAttrs):
            return False
        return True

    def modGroupMailServer(self, groupName, options):
        """Модифицирует настройки группы пользователей Mail"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        searchGroup = self.searchMailGroupToName(groupName)
        if not searchGroup:
            self.printERROR(_("group name not found in Mail service") +" ...")
            return False
        if options.has_key('n') and options.has_key('e'):
            self.printERROR(_("Command Line Options '-n' and '-e' are \
incompatible, use one of the options"))
            return False
        if options.has_key('hide') and options.has_key('hide-off'):
            self.printERROR(_("Command Line Options '--hide' and '--hide-off' \
are incompatible, use one of the options"))
            return False
        attrDelete = []
        attrDeleteFirst = []
        attrAppend = []
        altMails = []
        # Объект сервис репликации
        servReplObj = False
        if self.clVars.Get("ld_repl_mail_set") == "on":
            # Объект сервис репликации
            servReplObj = servRepl()
        filterHosts = []
        if options.has_key('hide'):
            filterHosts = options['hide'].split(",")
            if searchGroup[0][0][1].has_key('filtersender'):
                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)
            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'):
                attrDeleteFirst.append((ldap.MOD_DELETE, 'filtersender', None))            
        if options.has_key('e'):
            altMails = options['e'].split(",")
            email = searchGroup[0][0][1]["mail"][0]
            altEmails = searchGroup[0][0][1]["mailAlternateAddress"]
            # Удаляем альтернативные адреса, кроме первого
            for altEmail in altEmails:
                if email != altEmail:
                    attrDeleteFirst.append(
                                 (ldap.MOD_DELETE, 'mailAlternateAddress',
                                  altEmail))
            i = 0
            for altMail in altMails:
                if "@" in altMail:
                    if len(altMail.split("@")) != 2:
                        self.printERROR(_("Incorrect alternate adresses \
option '-e'"))
                        return False
                    mail = altMail
                else:
                    mail = "%s@%s" %(altMail,self.clVars.Get("sr_mail_host"))
                searchGroupMail = self.searchGroupToMail(mail)
                if self.searchUserToMail(mail) or (searchGroupMail and\
                    (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) + " ...")
                    return False
                if i == 0:
                    attrAppend.append((ldap.MOD_REPLACE, 'mailAlternateAddress',
                                       mail))
                else:
                    attrAppend.append((ldap.MOD_ADD, 'mailAlternateAddress',
                                       mail))
                i += 1
        if servReplObj:
            if not altMails and filterHosts:
                altMails = searchGroup[0][0][1]["mailAlternateAddress"]
            if altMails:
                if not servReplObj.modReplMailAlias(groupName, altMails,
                                                    filterHosts):
                    errorMsg = _("Can not set replication mail alias,") +\
                                " " + _("for name %s")%groupName + " " +\
                                "(%s)"%", ".join(altMails) + " ..."
                    self.printERROR(errorMsg)
                    return False
            if options.has_key('hide-off'):
                if not servReplObj.deleteHideHosts(groupName):
                    errorMsg = _("Can not delete hide host in mail alias,") +\
                                " " + _("for name %s")%groupName + " ..."
                    self.printERROR(errorMsg)
                    return False
        # Добавляем список пользователей в группу
        if options.has_key('a'):
            # добавляемые пользователи в группу
            users = options['a'].split(',')
            res = self.addUsersGroupMail(users, groupName)
            if res:
                self.printSUCCESS(_("Appended list users to group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not append list users to group") +\
                " " + str(groupName) + " ...")
                return False
        # Удаляем список пользователей из группы
        if options.has_key('d'):
            # удаляемые пользователи из группы
            users = options['d'].split(',')
            res = self.delUsersGroupMail(users, groupName)
            if res:
                self.printSUCCESS(_("Deleted list users from group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not delete list users from group") +\
                                  " " + str(groupName) + " ...")
                return False
        # Изменяем имя группы
        modGroupName = groupName
        if options.has_key('n'):
            newGroupName = options['n']
            if self.searchMailGroupToName(newGroupName):
                self.printERROR(
                    _("group name %s is found in Mail service")%\
                        str(newGroupName) + " ...")
                return False
            # изменяем адрес и альтернативный адрес
            altEmails = searchGroup[0][0][1]["mailAlternateAddress"]
            for altEmail in altEmails:
                splAltEmail = altEmail.split("@")
                grName = splAltEmail[0]
                if groupName == grName:
                    altEmailDomen = ""
                    if len(splAltEmail)==2:
                        altEmailDomen = splAltEmail[1]
                    newAltEmail = "%s@%s" %(newGroupName,altEmailDomen)
                    attrDelete.append(
                                (ldap.MOD_DELETE, 'mailAlternateAddress',
                                 altEmail))
                    attrAppend.append(
                                (ldap.MOD_ADD, 'mailAlternateAddress',
                                 newAltEmail))
                    break
            email = searchGroup[0][0][1]["mail"][0]
            splEmail = email.split("@")
            emailDomen = ""
            if len(splEmail)==2:
                emailDomen = splEmail[1]
            newEmail = "%s@%s" %(newGroupName,emailDomen)
            attrAppend.append((ldap.MOD_REPLACE, 'mail', newEmail))
            attrAppend.append((ldap.MOD_REPLACE, 'mailMessageStore',
                               newGroupName + "/"))

            newFirstDn = "cn=" + newGroupName
            oldDN = self.addDN("cn=" + groupName, self.relGroupsDN)
            res = self.modifyElemDN(oldDN, newFirstDn)
            # Меняем название реплицируемого алиаса
            if servReplObj:
                if not servReplObj.renameReplMailAlias(groupName, newGroupName):
                    self.printERROR(_("Failed modify name '%s' mail alias \
in 'Replication/Mail' branch ...") %groupName)
                    return False
            if res:
                self.printSUCCESS(_("Group renamed") + " ...")
                modGroupName = newGroupName
            else:
                self.printERROR(_("Can not rename group") + "...")
                return False
        modAttrs =  attrDeleteFirst + attrAppend + attrDelete
        # Изменяем коментарий к группе
        if options.has_key('c'):
            gecos = options['c']
            modAttrs.append((ldap.MOD_REPLACE, 'description', gecos))
        if not modAttrs:
            if options.has_key('hide-off'):
                self.printWARNING(\
                        _("Hide mail hosts have already been deleted") + " ...")
                return True
        if modAttrs:
            groupDN = self.addDN("cn=" + modGroupName, self.relGroupsDN)
            res = self.modAttrsDN(groupDN, modAttrs)
            if res:
                if options.has_key('c'):
                    self.printSUCCESS(_("Modified group comment") + " ...")
                if options.has_key('e'):
                    self.printSUCCESS(_("Modified  mail alternate address") +\
                                       " ...")
                if options.has_key('hide'):
                    self.printSUCCESS(_("Modified  hide mail hosts") +\
                                       " ...")
                if options.has_key('hide-off'):
                    self.printSUCCESS(_("Deleted hide mail hosts") +\
                                       " ...")
                return True
            else:
                if options.has_key('c'):
                    self.printERROR(_("Can not modify group comment") +\
                                      " ...")
                if options.has_key('e'):
                    self.printERROR(\
                                   _("Can not modify mail alternate address") +\
                                   " ...")
                if options.has_key('hide'):
                    self.printERROR(_("Can not modify hide mail hosts") +\
                                      " ...")
                if options.has_key('hide-off'):
                    self.printERROR(_("Can not delete hide mail hosts") +\
                                      " ...")
                return False
        return True


    def modUserMailServer(self, userName, options):
        """Модифицирует настройки пользователя Mail в LDAP"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        res = self.searchMailUserToName(userName)
        if not res:
            self.printERROR(
                _("User %s is not found in Mail service")%\
                    str(userName) + " ...")
            return False
        # Новые группы в которые входит пользователь
        if options.has_key('G'):
            userGroups = options['G'].split(',')
            #список имен добавляемых групп
            userGroupNames = self.searchGroupsMail(userGroups)
            if not userGroupNames:
                return False
            # Удаляем пользователя из групп в которые он входит
            if not self.delUserInGroup(userName):
                return False
            flagError = False
            for group in userGroupNames:
                if not self.addUsersGroupMail([userName], group):
                    flagError = True
                    break
            if flagError:
                return False
            self.printSUCCESS(_("Replaced list of supplementary group") +\
                              " ...")
        # Добавляем группы в которые входит пользователь
        elif options.has_key('a'):
            userGroups = options['a'].split(',')
            #список имен добавляемых групп
            userGroupNames = self.searchGroupsMail(userGroups)
            if not userGroupNames:
                return False
            flagError = False
            for group in userGroupNames:
                if not self.addUsersGroupMail([userName], group):
                    flagError = True
                    break
            if flagError:
                return False
            self.printSUCCESS(_("Appended list of supplementary group") +\
                              " ...")
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Включаем пользователя
        if options.has_key('U'):
            modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "active")]
        # Выключаем пользователя
        elif options.has_key('L'):
            modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "passive")]

        # Изменяем коментарий к пользователю
        if options.has_key('c'):
            comment = options['c']
            modAttrs += [(ldap.MOD_REPLACE, 'sn', comment),
                         (ldap.MOD_REPLACE, 'cn', comment)]
        # Изменяем пароль пользователя
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if userPwd:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if res[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        # Заменяем альтернативные почтовые адреса
        # Первичный почтовый адрес
        primaryMail = ""
        altMails = []
        if options.has_key('e'):
            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'"))
                        return False
                    mail = altMail
                else:
                    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)):
                    self.printERROR(
                    _("Alternate email address %s is found in Mail service")%\
                      str(mail) + " ...")
                    return False
                modAttrs.append((ldap.MOD_ADD, 'mailAlternateAddress', mail))
            # Удаляем предыдущие адреса
            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))
                return False
            # Если включена репликация почты
            if self.clVars.Get("ld_repl_mail_set") == "on":
                # Объект сервис репликации
                servReplObj = servRepl()
                if not servReplObj.modReplMailAlias(userName, altMails):
                    self.printERROR(_("Failed modify mail aliases \
for user %s in 'Replication/Mail' branch ...") %userName)
                    return False
        if modAttrs:
            DN = self.addDN("uid="+userName, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if options.has_key('c'):
                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'):
                self.printSUCCESS(_("Modified Mail alternate addresses") +\
                                    "...")
            if options.has_key('P') or options.has_key('p'):
                self.printSUCCESS(_("Modified Mail user password") + " ...")
        return True

    @adminConnectLdap
    def addGroupMailServer(self, groupName, options):
        """Добавляет группу пользователей Mail"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        # Проверяем на включение почтовой репликации
        servReplObj = False
        if self.clVars.Get("ld_repl_mail_set") == "on":
            # Объект сервис репликации
            servReplObj = servRepl()
            if servReplObj.searchMailAlias(groupName):
                    self.printERROR(_("Mail group %s is found in \
'Replication/Mail' branch")%groupName + " ...")
                    return False
        #Проверяем альтернативные почтовые адреса
        modAttrs = []
        altMails = []
        if options.has_key('e'):
            altMails = options['e'].split(",")
            for altMail in altMails:
                if "@" in altMail:
                    if len(altMail.split("@")) != 2:
                        self.printERROR(_("Incorrect alternate adresses \
option '-e'"))
                        return False
                    mail = altMail
                else:
                    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) + " ...")
                    return False
                modAttrs.append('mailAlternateAddress: %s' %mail)
        # Фильтр почты (hostname)
        fHostNames = []
        if options.has_key('hide'):
            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)
        if self.searchMailGroupToName(groupName):
            self.printERROR(
                _("group name %s is found in Mail service")%\
                    str(groupName) + " ...")
            return False
        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")%\
                    str(mail) + " ...")
            return False
        self.clVars.Set("ur_group", groupName)
        # Комментарий к группе
        groupGecos = self.servUnixObj.groupGecos
        if options.has_key('c'):
            groupGecos = options['c']
        self.clVars.Set("ur_group_comment",groupGecos)
        ldifFile = self.ldifFileGroup
        groupRawLdif = self.createLdif(ldifFile)
        if not groupRawLdif:
            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()
            return False
        if servReplObj:
            # Записываем почтовые алиасы в ветку 
            # репликации Replication/Mail
            if altMails and not servReplObj.addReplMailAlias(groupName,
                                                             altMails,
                                                             fHostNames):
                self.printERROR(_("Failed set  mail aliases \
for user %s in 'Replication/Mail' branch ...") %str(primaryMail))
                return False
        self.printSUCCESS(_("Added group in Mail service") + " ...")
        return True


    def modUserMailPasswd(self, userName, options):
        """Устанавливает пароль Mail пользователя и меняет его опции"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        res = self.searchMailUserToName(userName)
        if not res:
            self.printERROR(
                _("User %s is not found in Mail service") % str(userName) +\
                  " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Включаем пользователя
        if options.has_key('u'):
            modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "active")]
        # Выключаем пользователя
        elif options.has_key('l'):
            modAttrs += [(ldap.MOD_REPLACE, 'accountStatus', "passive")]
        if not options:
            optPasswd = {"p":""}
            userPwd = self.getUserPassword(optPasswd, "p", False)
            if userPwd == False:
                return False
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if res[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        if modAttrs:
            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 not options:
                self.printSUCCESS(_("Changed Mail user password") + " ...")
            return True
        return False

    def searchUsersInGroupMail(self, usersNames, groupName):
        """Ищет спиcок пользователей в группе, ищет в LDAP

        В случае успеха выводит список найденных пользователей
        если нет группы False
        если ничего не найдено пустой список
        """
        res = self.searchMailGroupToName(groupName)
        if not res:
            return False
        else:
            findUsers = []
            if res[0][0][1].has_key('rfc822member'):
                usersInGroup = res[0][0][1]['rfc822member']
                for userName in usersNames:
                    userMail = "%s@%s" %(userName,
                                         self.clVars.Get("sr_mail_host"))
                    if userMail in usersInGroup:
                        findUsers.append(userName)
            return findUsers


    def searchMailUserToName(self, userName):
        """Находит пользователя сервиса Mail по имени"""
        resSearch = self.searchLdapDN(userName, self.relUsersDN, "uid")
        return resSearch

    def searchUserToMail(self, mail):
        """Находит пользователя по почтовому адресу в сервисе Mail"""
        resSearch = self.searchLdapDN(mail, self.relUsersDN, "mail")
        if not resSearch:
            resSearch = self.searchLdapDN(mail, self.relUsersDN,
                                          "mailAlternateAddress")
        return resSearch

    def searchMailUser(self, nameOrMali):
        """Находит пользователя сервиса Mail по имени или email"""
        if "@" in nameOrMali:
            resSearch = self.searchUserToMail(nameOrMali)
        else:
            resSearch = self.searchMailUserToName(nameOrMali)
        return resSearch

    def searchGroupToMail(self, mail):
        """Находит группу по ее почтовому адресу"""
        resSearch = self.searchLdapDN(mail, self.relGroupsDN, "mail")
        if not resSearch:
            resSearch = self.searchLdapDN(mail, self.relGroupsDN,
                                          "mailAlternateAddress")
        return resSearch

    def createMailDir(self, userName, uid, gid):
        """Создание пользовательской директории для почты"""
        def createCNT(mailDir, uid, gid):
            """создание cur, new, tmp в текущей директории"""
            appendDirs = ["cur","new","tmp"]
            flagError = False
            for appDir in appendDirs:
                createDir = os.path.join(mailDir, appDir)
                if not self.createUserDir(uid, gid, createDir, False):
                    flagError = True
                    break
            if flagError:
                return False
            return True
        mailDir = os.path.join(self.clVars.Get("sr_mail_path"),
                               userName)
        flagError = False
        if not self.createUserDir(uid, gid, mailDir):
            flagError = True
        if not flagError and not createCNT(mailDir, uid, gid):
            flagError = True
        if not flagError:
            mailDirs = [os.path.join(mailDir,".Drafts"),
                        os.path.join(mailDir,".Sent"),
                        os.path.join(mailDir,".Spam"),
                        os.path.join(mailDir,".Trash")]
            for createDir in mailDirs:
                if not self.createUserDir(uid, gid, createDir, False):
                    flagError = True
                    break
                if not createCNT(createDir, uid, gid):
                    flagError = True
                    break
        if flagError:
            return False
        return True

    def addUsersGroupMail(self, users, groupName):
        """Добавляет пользователей из списка в Mail группу"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        if not self.searchMailGroupToName(groupName):
            self.printERROR(_("Group name is not found in Mail service") +\
                             " ...")
            return False
        flagFalse = False
        for userName in users:
            if not self.searchMailUserToName(userName):
                self.printERROR(
                    _("User %s is not found in Mail service")%\
                        str(userName) + " ...")
                flagFalse = True
                break
        if flagFalse:
            return False
        foundUsersMail = self.searchUsersInGroupMail(users, groupName)
        foundUsers = []
        if foundUsersMail:
            foundUsers = foundUsersMail
        addUsers = []
        for user in users:
            if not(user in foundUsers):
                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))
        if modAttrs:
            groupDN = self.addDN("cn="+groupName, self.relGroupsDN)
            return self.modAttrsDN(groupDN, modAttrs)
        return True

    def delUserInMailAndUnix(self, userName, flagDelUnixUser):
        """Удаляет пользователя без бекапа

        Удаляет из Mail и если установлен флаг из Unix
        """
        if not self.delUserMailServer(userName, {}, False,False):
            return False
        if flagDelUnixUser:
            if not self.servUnixObj.delUserUnixServer(userName, {}, False,
                                                      False):
                return False
        return True

    @adminConnectLdap
    def addUserMailServer(self, userName, options):
        """Добавляет почтового пользователя в LDAP-сервер"""
        # Проверим установлен ли сервис Mail
        if not self.initialChecks("mail"):
            return False
        # Проверяем на включение почтовой репликации
        servReplObj = False
        if self.clVars.Get("ld_repl_mail_set") == "on":
            # Объект сервис репликации
            servReplObj = servRepl()
            if servReplObj.searchMailAlias(userName):
                    self.printERROR(_("Mail user %s is found in \
'Replication/Mail' branch")%userName + " ...")
                    return False
        #Проверяем альтернативные почтовые адреса
        modAttrs = []
        primaryMail = ""
        altMails = []
        if options.has_key('e'):
            altMails = options['e'].split(",")
            for altMail in altMails:
                if "@" in altMail:
                    if len(altMail.split("@")) != 2:
                        self.printERROR(_("Incorrect alternate adresses option \
'-e'"))
                        return False
                    mail = altMail
                else:
                    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) + " ...")
                    return False
                modAttrs.append("mailAlternateAddress: %s" %mail)
        else:
            self.printERROR(\
            _("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"))
            if self.searchUserToMail(mail) or\
                self.searchGroupToMail(mail):
                self.printERROR(
                    _("Email address %s is found in Mail service")%\
                    str(mail) + " ...")
                return False
        resUnix = self.servUnixObj.searchUnixUser(userName)
        resPwd = self.servUnixObj.searchPasswdUser(userName)
        # Пароль пользователя почты
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        flagCreateUnixUser = False
        if not (resUnix or resPwd):
            flagCreateUnixUser = True
            # Добавим пользователя LDAP
            optUnix = {}
            # Группа пользователя
            if options.has_key('g'):
                optUnix['g'] = options['g']
                # Полное имя пользователя
            if options.has_key('c'):
                optUnix['c'] = options['c']
            if not self.servUnixObj.addUserUnixServer(userName, optUnix,
                                                        False):
                self.printERROR (_("Can not add user")+ " " +\
                                 str(userName) + _(" in Unix service"))
                return False
            resUnix = self.servUnixObj.searchUnixUser(userName)
        self.clVars.Set("ur_name", userName)
        #Полное имя пользователя
        fullNameUser = self.servUnixObj.fullNameUser
        if options.has_key('c'):
            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 not userPwd:
            userPwdHash = "crypt{xxx}"
        else:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
        if not userPwdHash:
            if flagCreateUnixUser:
                self.servUnixObj.delUserUnixServer(userName, {}, False, False)
            return False
        self.clVars.Set("ur_hash",userPwdHash)
        ldifFile = self.ldifFileUser
        userRawLdif = self.createLdif(ldifFile)
        if not userRawLdif:
            print self.getError()
            if flagCreateUnixUser:
                self.servUnixObj.delUserUnixServer(userName, {}, False, False)
            return False
        userLdif = userRawLdif.rstrip() + "\n" + "\n".join(modAttrs)
        if not self.ldapObj.getError():
            #Добавляем пользователя в LDAP
            self.ldapObj.ldapAdd(userLdif)
            #ldapObj.ldapAdd(userLdif1)
        # не переделывать на else
        flagError = False
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            flagError = True
        if not flagError:
            if resUnix:
                uid = int(resUnix[0][0][1]['uidNumber'][0])
                gid = int(resUnix[0][0][1]['gidNumber'][0])
            elif resPwd:
                uid = int(resPwd.split(":")[2])
                gid = int(resPwd.split(":")[3])
            else:
                self.printERROR(_("user are not found"))
                flagError = True
        if not flagError:
            # Востановим удаленного пользователя
            # Почтовая директория пользователя
            mailDir = os.path.join(self.clVars.Get("sr_mail_path"),
                                userName)
            message = _("Do you want to restore deleted user %s data?")\
                      %userName + "\n" + "'yes', 'no'"
            resMailDir = self.restorePathDelUser(userName, mailDir,
                                                    "mail", message)
            removeMailDirBack = False
            if not resMailDir:
                flagError = True
                createDirMail = False
            else:
                term, createDirMail, removeMailDirBack = resMailDir
            # Создаем почтовую директорию
            if not flagError and createDirMail:
                if not self.createMailDir(userName, uid, gid):
                    flagError = True
            # Записываем основной почтовый адрес
            if not flagError and primaryMail:
                # Записываем основной почтовый адрес в ветку Unix
                if not self.servUnixObj.setUserMail(userName, primaryMail):
                    self.printERROR(_("Failed set primary email for user %s in \
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)
                        flagError = True
            if not flagError and removeMailDirBack\
                and os.path.exists(removeMailDirBack):
                self.removeDir(removeMailDirBack)
                self.removeEmptyDir(os.path.split(removeMailDirBack)[0])
        if flagError:
            self.delUserInMailAndUnix(userName, flagCreateUnixUser)
            self.printERROR(_("Can not add user") + " ...")
            return False
        if flagCreateUnixUser:
            self.printSUCCESS(_("Added user in Unix service") + " ...")
        self.printSUCCESS(_("Added user in Mail service") + " ...")
        return True

    def getAllowNet(self):
        """Получаем от пользователя доверительные сети

        и устанавливаем переменную профилей sr_mail_net_allow

        self.clVars должен быть определен
        """
        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 = ""
        if netAllow:
            strNetAllow = netAllow.replace(","," ")
        allowNet = self.getUserAllowNetwork(strPrompt, strNetAllow)
        if not allowNet:
            return False
        # Установка переменной доступные сети
        self.clVars.Set("sr_mail_net_allow",",".join(allowNet),True)
        return True

    def getHostName(self):
        """Получаем от пользователя имя почтового хоста

        и устанавливаем переменную профилей sr_mail_host

        self.clVars должен быть определен
        """
        def correctHostname(hostname):
            # Проверяет корректность введенного имени хоста
            reCorrect = re.compile(\
             "([A-Za-z0-9]\.|[A-Za-z0-9][-A-Za-z0-9]{0,61}[-A-Za-z0-9](\.|$))*")
            correctHost = hostname.strip()
            findHost = reCorrect.search(correctHost)
            if findHost and findHost.group() == correctHost:
                return correctHost
            return False

        def printW():
            print _("Incorrect string hostname")
            print _("Try again\n")

        print _("Enter the hostname for %s service")%"Mail"
        strPrompt = _("hostname: ")
        hostname = self.clVars.Get("sr_mail_host")
        hostname = self.raw_input(strPrompt, hostname)
        i = 0
        while i<3 and not correctHostname(hostname):
            printW()
            hostname = self.raw_input(strPrompt, hostname)
            i += 1
        if i == 3 and not correctHostname(hostname):
            printW()
            self.printERROR(_("You used four attempts, \
if you want to continue to run the program again"))
            return False
        # Установка имени хоста
        fullHostName = correctHostname(hostname)
        if not "." in fullHostName:
            fullHostName = "%s.%s" %(fullHostName,
                                     self.clVars.Get('os_net_domain'))
        self.clVars.Set("sr_mail_host", fullHostName, True)
        return True

    def setupMailServer(self, options):
        """Начальная настройка Mail сервиса"""
        # Принудительная установка
        forceOptions = False
        if options.has_key("f"):
            forceOptions = True
        # Создаем объект переменных и начальная проверка
        if not self.initialChecksSetup():
            return False
        if self.clVars.Get("sr_unix_set") != "on":
            self.printERROR(_("Unix service is not setuped"))
            self.printWARNING(_("Setup Unix service"))
            self.printWARNING("  cl-setup unix")
            return False
        # Доверительные сети по умолчанию
        allowNet = self.clVars.Get("os_net_allow")
        # В случае если сервер установлен
        if self.clVars.Get("sr_mail_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
                _("Mail server is configured")+ ".")
            return True

        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы сервиса Mail (программы Postfix и Dovecot)
            self.printWARNING (_("WARNING") + ": " +
                _("Executing of the program will change") + " " +
                _("the configuration files of Mail service") +" ("+
                _("programs Postfix and Dovecot") + ")." )
            # если вы готовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program") + ", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
            if options.has_key("a"):
                # Получаем от пользователя доверительные сети
                allowNet = self.getAllowNet()
                if not allowNet:
                    return False
        else:
            if options.has_key("a"):
                # Получаем от пользователя доверительные сети
                allowNet = self.getAllowNet()
                if not allowNet:
                    return False
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            bakupObj = servLdap()
            bakupObj.backupServer()
        # Удаляем переменные сервиса в ini файлах
        self.deleteServiceVarsInFile("mail")
        # Cоздаем объект переменные
        self.createClVars()
        # Устанавливаем доступные сети
        self.clVars.Set("sr_mail_net_allow",allowNet,True)
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("postfix"):
            return False
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("dovecot"):
            return False
        # останавливаем сервис Mail
        if not self.stopServices(["mail"]):
            return False
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","mail")
        self.clVars.Write("sr_mail_set","off")
        # Почтовый ност
        fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'),
                               self.clVars.Get('os_net_domain'))
        if options.has_key("host"):
            fullHostName = options['host']
            if not "." in fullHostName:
                fullHostName = "%s.%s" %(fullHostName,
                                         self.clVars.Get('os_net_domain'))
        self.clVars.Set("sr_mail_host",fullHostName,True)
        mailType = "imap"
        if options.has_key("t"):
            mailType = options['t']
            if mailType:
                if not set(mailType.split(",")) <= set(["imap","pop3"]):
                    self.printERROR(\
                        _("Мail type not 'imap' or 'pop3' or 'pop3,imap'"))
                    return False
                if len(mailType.split(",")) == 2:
                    mailType = "all"
            else:
                self.printERROR(_("Мail type incorrect"))
                return False
        self.clVars.Set("sr_mail_type", mailType)
        mailCrypt = "tls"
        if options.has_key("c"):
            mailCrypt = options['c']
            if not mailCrypt in ["none", "tls"]:
               self.printERROR(_("Мail encryption not 'none' or 'tls'"))
               return False
            if mailCrypt == "none":
                mailCrypt = ""
        self.clVars.Set("sr_mail_crypt", mailCrypt, True)
        if not self.applyProfilesFromService('mail'):
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        else:
            if not self.restartLdapServer():
                return False
        # Подключаемся к LDAP cерверу
        if not shareLdap.getLdapObjInFile(self):
            return False
        # Находим в LDAP Mail сервис
        resSearch = self.searchService()
        ret = True
        if resSearch:
            delDN = self.relDN
            ret = self.deleteDN(delDN)
            if ret:
                self.printOK(_("Remove Mail DN from LDAP Database") +" ...")
            else:
                self.printERROR(\
                            _("Can not remove Mail DN from LDAP Database")+\
                            " ...")
        if not ret:
            return False
        ldifFile = self.ldifFileBase
        baseLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        # Записываем данные администратора сервиса Mail
        ldapParser = iniLdapParser()
        ldapParser.setVar("mail",
            {"DN":self.clVars.Get("ld_mail_dn"),
             "PASS":self.clVars.Get("ld_mail_pw")})
        self.printOK(_("Added ldif file") +" ...")
        textLine = self.execProg("newaliases")
        if not (textLine == None):
            self.printERROR(_("Can not create Postfix aliases") + " ...")
            return False
        textLines = self.execProg("/etc/init.d/postfix start",False,False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            self.printOK(_("Starting") + " " + "Postfix" + " ...")
        else:
            self.printNotOK(_("Starting") + " " + "Postfix" + " ...")
            return False
        textLines = self.execProg("/etc/init.d/dovecot start", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            self.printOK(_("Starting") + " " + "Dovecot" + " ...")
        else:
            self.printNotOK(_("Starting") + " " + "Dovecot" + " ...")
            return False
        # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("postfix"):
            return False
        # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("dovecot"):
            return False
        #запишем переменные для сервера
        mailHost = self.clVars.Get("sr_mail_host")
        self.clVars.Write("sr_mail_host",mailHost,True,"local")
        self.clVars.Write("sr_mail_type",
                          self.clVars.Get("sr_mail_type"),True,"local")
        self.clVars.Write("sr_mail_crypt",
                          self.clVars.Get("sr_mail_crypt"),True,"local")
        self.clVars.Write("sr_mail_net_allow",
                          self.clVars.Get("sr_mail_net_allow"),True,"local")
        #запишем переменные для клиента
        if mailType == "all":
            self.clVars.Set("sr_mail_type","imap")
        self.clVars.Set("sr_mail_send_host",mailHost)
        clientVars = ["sr_mail_host","sr_mail_crypt", "sr_mail_port",
                      "sr_mail_type","sr_mail_send_crypt","sr_mail_send_port",
                      "sr_mail_send_host"]
        if not self.saveVarsClient(clientVars):
            return False
        self.clVars.Write("sr_mail_set","on")
        self.printOK(_("Mail service configured") + " ...")
        return True


class servJabber(shareLdap):
    """Методы сервиса Jabber"""

    relGrDN = 'ou=Groups'
    relUsDN = 'ou=Users'
    relServDN = 'ou=Jabber'
    ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/jabber_base.ldif"
    ldifFileUser = "/usr/lib/calculate/calculate-server/ldif/jabber_user.ldif"
    ldifFileGroup = "/usr/lib/calculate/calculate-server/ldif/jabber_group.ldif"

    def __init__(self,  unixObj=False):
        shareLdap.__init__(self)
        # DN сервиса
        self.relDN = self.addDN(self.relServDN,self.ServicesDN)
        # DN пользователей, относительно базового DN
        self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
        # DN групп пользователей, относительно базового DN
        self.relGroupsDN = self.addDN(self.relGrDN, self.relDN)
        if unixObj:
            # получаем объект сервиса Unix
            self.servUnixObj = unixObj
        else:
            # создаем объект сервиса Unix
            self.servUnixObj = servUnix()

    def searchGroupToName(self, groupName):
        """Находит группу сервиса Jabber по её имени"""
        resSearch = self.searchLdapDN(groupName, self.relGroupsDN, "cn")
        return resSearch

    def searchUserToId(self, jabberId):
        """Находит пользователя по Jabber ID в сервисе Jabber"""
        resSearch = self.searchLdapDN(jabberId, self.relUsersDN, "mail")
        return resSearch

    def searchUserToName(self, name):
        """Находит пользователя по имени в сервисе Jabber"""
        resSearch = self.searchLdapDN(name, self.relUsersDN, "uid")
        return resSearch

    def searchUsersToGroup(self, descr):
        """Находит пользователей по description"""
        resSearch = self.searchLdapDN(descr, self.relUsersDN,
                                      "departmentNumber")
        return resSearch

    def searchAllUsers(self):
        """Находит у всех пользователей uid и JabberID"""
        resSearch = self.searchLdapDN("*", self.relUsersDN,
                                      "uid",["uid","mail"])
        return resSearch

    def searchUsersToHostName(self, hostName):
        """Находит всех пользователей с данным именем хоста"""
        resSearch = self.searchLdapDN("*@%s" %hostName, self.relUsersDN,
                                      "mail",["uid","mail"])
        return resSearch

    def searchUserToNameOrId(self, nameOrId):
        """Находит пользователя сервиса Jabber по имени или id"""
        resSearch = self.searchUserToName(nameOrId)
        if resSearch:
            return resSearch
        resSearch = self.searchUserToId(nameOrId)
        return resSearch

    def setUserGroup(self, userName, groupName, userS=False, groupS=False):
        """Устанавливает Jabber группу для пользователя"""
        if groupS:
            groupSearch = groupS
        else:
            groupSearch = self.searchGroupToName(groupName)
        if not groupSearch:
            self.printERROR(_("Group name is not found in Jabber service") +\
                             " ...")
            return False
        if userS:
            userSearch = userS
        else:
            userSearch = self.searchUserToNameOrId(userName)
        if not userSearch:
            self.printERROR(_("User %s is not found in Jabber service")%\
                            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))
        else:
            modAttrs.append((ldap.MOD_ADD, 'departmentNumber', descr))
        userDN = self.addDN("uid="+uid, self.relUsersDN)
        return self.modAttrsDN(userDN, modAttrs)

    def renameJabberId(self, userName, newJabberId):
        """Изменяет jabber ID для пользователя"""
        searchUser = self.searchUserToName(userName)
        if not searchUser:
            self.printERROR(_("User %s is not found in Jabber service")%\
                                str(userName) + " ...")
            return False
        modAttrs = []
        if searchUser[0][0][1].has_key('mail'):
            modAttrs.append((ldap.MOD_REPLACE, 'mail', newJabberId))
        else:
            modAttrs.append((ldap.MOD_ADD, 'mail', newJabberId))
        userDN = self.addDN("uid="+userName, self.relUsersDN)
        return self.modAttrsDN(userDN, modAttrs)

    @adminConnectLdap
    def setHostName(self, newHostName, oldHostName):
        """Заменяет пользователям имя хоста на новое"""
        searchUsers = self.searchUsersToHostName(oldHostName)
        if not searchUsers:
            self.printWARNING(_("Host name %s not found in Jabber service")\
                              %oldHostName)
            return True
        flagError = False
        for userFields in searchUsers:
            newJabberId = userFields[0][1]['mail'][0].replace(oldHostName,
                                                              newHostName)
            userName = userFields[0][1]['uid'][0]
            if not self.renameJabberId(userName, newJabberId):
                self.printERROR(_("Can not change host name for user %s \
in Jabber service"))
                flagError = True
                break
        if flagError:
            return False
        return True

    def addUsersGroupJabber(self, users, groupName, replaceFlag=False):
        """Добавляет пользователей из списка в Jabber группу"""
        groupSearch = self.searchGroupToName(groupName)
        if not groupSearch:
            self.printERROR(_("Group name is not found in Jabber service") +\
                             " ...")
            return False
        flagFalse = False
        for userName in users:
            userSearch = self.searchUserToNameOrId(userName)
            if not userSearch:
                self.printERROR(_("User %s is not found in Jabber service")%\
                                str(userName) + " ...")
                flagFalse = True
                break
            if not replaceFlag and\
                userSearch[0][0][1].has_key('departmentNumber'):
                self.printERROR(_("User %s is found in group")%\
                     str(userName) + " " + str(groupName) + " ...")
                flagFalse = True
                break
        if flagFalse:
            return False
        for userName in users:
            if not self.setUserGroup(userName, groupName):
                flagFalse = True
                break
        if flagFalse:
            return False
        return True

    def delUsersGroupJabber(self, users, groupName):
        """Удаляет пользователей из списка в Jabber группе"""
        groupSearch = self.searchGroupToName(groupName)
        if not groupSearch:
            self.printERROR(_("Group name is not found in Jabber service") +\
                             " ...")
            return False
        flagFalse = False
        res = True
        for userName in users:
            userSearch = self.searchUserToNameOrId(userName)
            if userSearch and userSearch[0][0][1].has_key('departmentNumber'):
                if not userSearch[0][0][1]['departmentNumber'][0] == \
                groupSearch[0][0][1]['cn'][0]:
                    self.printERROR(_("User %s is not found in group")%\
                        str(userName) + " " + str(groupName) + " ...")
                    res = False
                    break
            else:
                self.printERROR(_("User %s is not a member of any group")%\
                                str(userName) + " ...")
                res = False
                break
        if not res:
            return False
        for userName in users:
            userSearch = self.searchUserToNameOrId(userName)
            uid = userSearch[0][0][1]['uid'][0]
            modAttrs = [(ldap.MOD_DELETE, 'departmentNumber', None)]
            userDN = self.addDN("uid="+uid, self.relUsersDN)
            res = self.modAttrsDN(userDN, modAttrs)
            if not res:
                break
        return res

    def renameGroup(self, oldName, newName):
        """Изменяет имя группы"""
        searchOldGroup = self.searchGroupToName(oldName)
        if not searchOldGroup:
            self.printERROR(\
        _("Old group name %s not found in Jabber service")%str(oldName)+\
                            " ...")
            return False
        searchNewGroup = self.searchGroupToName(newName)
        if searchNewGroup:
            self.printERROR(\
        _("New group name %s found in Jabber service")%str(newName)+\
                            " ...")
            return False
        groupDN = self.addDN("cn="+oldName, self.relGroupsDN)
        searchUsers = self.searchUsersToGroup(oldName)
        if searchUsers:
            flagError = False
            for data in searchUsers:
                uid = data[0][1]['uid'][0]
                userDN = self.addDN("uid="+uid, self.relUsersDN)
                modAttrs = [(ldap.MOD_REPLACE,
                            'departmentNumber',
                            newName)]
                res = self.modAttrsDN(userDN, modAttrs)
                if not res:
                    flagError = True
                    break
            if flagError:
                return False
        newFirstDn = "cn=" + newName
        oldDN = groupDN
        res = self.modifyElemDN(oldDN, newFirstDn)
        return res


    def modUserJabberPasswd(self, userName, options):
        """Устанавливает пароль Jabber пользователя и меняет его опции"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        resSearch = self.searchUserToNameOrId(userName)
        if not resSearch:
            self.printERROR(
                _("User %s is not found in Jabber service") % str(userName) +\
                  " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Включаем пользователя
        if options.has_key('u'):
            modAttrs += [(ldap.MOD_REPLACE, 'initials', "Yes")]
        # Выключаем пользователя
        elif options.has_key('l'):
            modAttrs += [(ldap.MOD_REPLACE, 'initials', "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'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        if modAttrs:
            uid = resSearch[0][0][1]['uid'][0]
            DN = self.addDN("uid="+userName, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if options.has_key('l'):
                self.printSUCCESS(_("Locked Jabber user %s")% str(userName)+\
                        " ...")
            if options.has_key('u'):
                self.printSUCCESS(_("Unlocked Jabber user %s")%\
                str(userName)+ " ...")
            if not options:
                self.printSUCCESS(_("Changed Jabber user password") + " ...")
            return True
        return False


    def modUserJabberServer(self, userName, options):
        """Модифицирует настройки пользователя Jabber в LDAP"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        res = self.searchUserToNameOrId(userName)
        if not res:
            self.printERROR(_("User %s is not found in Jabber service")%\
                            str(userName) + " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Изменяем Jabber ID
        if options.has_key('j'):
            # Изменяем JID
            jabberId = options['j']
            if not "@" in jabberId:
                jabberId = "%s@%s" %(jabberId,self.clVars.Get("sr_jabber_host"))
            else:
                if len(jabberId.split("@")) != 2:
                    self.printERROR(_("JID %s incorrect") %jabberId + " ...")
                    return False
            searchUser = self.searchUserToId(jabberId)
            if searchUser:
                foundUserName = searchUser[0][0][1]['uid'][0]
                self.printERROR(_("User %s") %str(foundUserName) + " " +\
                                _("has a JID %s") %jabberId + " ...")
                return False
            # добавляем jabberID в Unix
            if self.isServiceSetup("unix",False):
                if not self.servUnixObj.setUserJabberID(userName, jabberId):
                    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))
            else:
                modAttrs.append((ldap.MOD_ADD, 'mail', jabberId))
        # Изменяет группу в которую входит пользователь
        if options.has_key('g'):
            userGroup = options['g']
            if self.setUserGroup(userName, userGroup, res):
                self.printSUCCESS(_("Replaced user group") + " ...")
            else:
                self.printERROR(_("Not replaced user group") + " ...")
                return False
         #загружаем картинку
        if options.has_key('i'):
            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")]
        # Выключаем пользователя
        elif options.has_key('L'):
            modAttrs += [(ldap.MOD_REPLACE, 'initials', "No")]
        # Изменяем коментарий к пользователю
        if options.has_key('c'):
            comment = options['c']
            modAttrs += [(ldap.MOD_REPLACE, 'sn', comment),
                         (ldap.MOD_REPLACE, 'cn', comment)]
        # Изменяем пароль пользователя
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if userPwd:
            userPwdHash = userPwd
            if res[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        if modAttrs:
            uid = res[0][0][1]['uid'][0]
            DN = self.addDN("uid="+uid, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if options.has_key('c'):
                self.printSUCCESS(_("Modified comment (full name)") + " ...")
            if options.has_key('L'):
                self.printSUCCESS(_("Locked Jabber user %s")%str(userName) +
                                  " ...")
            if options.has_key('U'):
                self.printSUCCESS(_("Unlocked Jabber user %s")%str(userName) +
                                  " ...")
            if options.has_key('P') or options.has_key('p'):
                self.printSUCCESS(_("Modified Jabber user password") + " ...")
            if options.has_key('j'):
                self.printSUCCESS(_("Modified JID") + " ...")
        if options.has_key('i'):
                self.printSUCCESS(_("Set image %s for Jabber user")%\
                   str(options['i']) + " " + str(userName) + " ...")
        return True

    def modGroupJabberServer(self, groupName, options):
        """Модифицирует настройки группы пользователей Jabber"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        searchGroup = self.searchGroupToName(groupName)
        if not searchGroup:
            self.printERROR(_("Group name %s is not found in Jabber service")\
            %str(groupName) + " ...")
            return False
        # Добавляем список пользователей в группу
        if options.has_key('a'):
            # добавляемые пользователи в группу
            users = options['a'].split(',')
            res = self.addUsersGroupJabber(users, groupName)
            if res:
                self.printSUCCESS(_("Appended list users to group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not append list users to group") +\
                " " + str(groupName) + " ...")
                return False
        # Удаляем список пользователей из группы
        if options.has_key('d'):
            # удаляемые пользователи из группы
            users = options['d'].split(',')
            res = self.delUsersGroupJabber(users, groupName)
            if res:
                self.printSUCCESS(_("Deleted list users from group") + " " +\
                              str(groupName) + " ...")
            else:
                self.printERROR(_("Can not delete list users from group") +\
                                  " " + str(groupName) + " ...")
                return False
        # Изменяем коментарий к группе
        if options.has_key('c'):
            gecos = options['c']
            modAttrs = [(ldap.MOD_REPLACE, 'description', gecos)]
            groupDN = self.addDN("cn="+groupName, self.relGroupsDN)
            if self.modAttrsDN(groupDN, modAttrs):
                self.printSUCCESS(_("Modified group comment") + " ...")
            else:
                self.printERROR(_("Can not modify comment group") +\
                                  " " + str(groupName) + " ...")
                return False
        # Изменяем имя группы
        if options.has_key('n'):
            newGroupName = options['n']
            oldGroupName = searchGroup[0][0][1]["cn"][0]
            if self.renameGroup(oldGroupName, newGroupName):
                self.printSUCCESS(_("Group renamed") + " ...")
            else:
                self.printERROR(_("Can not rename group") +\
                                  " " + str(groupName) + " ...")
                return False
        return True

    def delUserJabberServer(self, userName, options, printSuccess=True):
        """Удаляем Jabber пользователя"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        # Ищем Jabber пользователя
        resSearch = self.searchUserToNameOrId(userName)
        if not resSearch:
            self.printERROR (_("ERROR") + ": " +\
                _("User %s is not found in Jabber service") % str(userName) +\
                  " ...")
            return False
        uid = resSearch[0][0][1]['uid'][0]
        # Удаляем jabberID из Unix сервиса
        # добавляем jabberID в Unix
        if self.isServiceSetup("unix",False) and\
            self.servUnixObj.searchUnixUser(uid):
            if not self.servUnixObj.deleteUserJabberID(uid):
                return False
        # Удаляем пользователя
        delDN = self.addDN("uid=" + uid, self.relUsersDN)
        if not self.delDN(delDN):
            self.printERROR(_("Jabber user %s is not deleted")%userName +\
                            " ...")
            return False
        if printSuccess:
            self.printSUCCESS(_("Jabber user %s is deleted")%userName +\
                            " ...")
        return True

    def delGroupJabberServer(self, groupName, options):
        """Удаляет группу пользователей Jabber"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        res = self.searchGroupToName(groupName)
        if not res:
            self.printERROR(
                _("Group %s is not found in Jabber service")%groupName +\
                  " ...")
            return False
        users = []
        flagError = False
        searchUsers = self.searchUsersToGroup(groupName)
        if searchUsers:
            for data in searchUsers:
                users.append(data[0][1]['uid'][0])
            if not self.delUsersGroupJabber(users, groupName):
                flagError = True
        if not flagError:
            delDN = self.addDN("cn="+groupName, self.relGroupsDN)
            res = self.delDN(delDN)
            if not res:
                flagError = True
        if flagError:
            self.printERROR(_("Can not delete Jabber group") +\
                              " " + groupName + " ...")
            return False
        else:
            self.printSUCCESS( _("Jabber group %s is deleted")%groupName +\
                                 " ...")
            return True


    @adminConnectLdap
    def addGroupJabberServer(self, groupName, options):
        """Добавляет группу пользователей Jabber"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("jabber"):
            return False
        # Если группа существует выходим без ошибки
        if self.searchGroupToName(groupName):
            self.printERROR(\
                _("group name %s is found in Jabber service") %\
                str(groupName) + " ...")
            return False
        self.clVars.Set("ur_group",groupName)
        # Комментарий к группе
        groupGecos = self.servUnixObj.groupGecos
        if options.has_key('c'):
            groupGecos = options['c']
        self.clVars.Set("ur_group_comment",groupGecos)
        ldifFile = self.ldifFileGroup
        groupLdif = self.createLdif(ldifFile)
        if not groupLdif:
            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()
            return False
        self.printSUCCESS(_("Added group in Jabber service") + " ...")
        return True

    @adminConnectLdap
    def updateJabberIdInUnix(self):
        """Перезаписывает на основании текущих jabberID в Unix сервисе"""
        if not self.isServiceSetup("unix",False):
            return True
        searchUsers = self.searchAllUsers()
        flagError = False
        for fieldUser in searchUsers:
            if fieldUser[0][1].has_key("mail"):
                userName = fieldUser[0][1]['uid'][0]
                jabberId = fieldUser[0][1]['mail'][0]
                if not self.servUnixObj.setUserJabberID(userName, jabberId):
                    self.printERROR(_("Failed set jabberID for user %s \
in Unix service ...") %str(jabberId))
                    flagError = True
                    break
        if flagError:
            return False
        return True

    @adminConnectLdap
    def addUserJabberServer(self, userName, options, checkSetup=True):
        """Добавляет jabber пользователя"""
        # Проверим установлен ли сервис jabber
        if checkSetup and not self.initialChecks("jabber"):
            return False
        #jabber id
        jabberId = "%s@%s" %(userName,self.clVars.Get("sr_jabber_host"))
        if options.has_key('j'):
            # Изменяем JID
            jabberId = options['j']
            if not "@" in jabberId:
                jabberId = "%s@%s" %(jabberId,self.clVars.Get("sr_jabber_host"))
            else:
                if len(jabberId.split("@")) != 2:
                    self.printERROR(_("JID %s incorrect") %jabberId + " ...")
                    return False
        # добавляем jabberID в Unix
        if self.isServiceSetup("unix",False):
            if not self.servUnixObj.setUserJabberID(userName, jabberId):
                self.printERROR(_("Failed set jabberID for user %s \
in Unix service ...") %str(jabberId))
                return False
        self.clVars.Set("sr_jabber_user_id", jabberId)
        if self.searchUserToName(userName):
            self.printERROR(_("User %s exists in Jabber service") %userName)
            return False
        if self.searchUserToId(jabberId):
            self.printERROR(_("JID %s exists in Jabber service") %jabberId)
            return False
        # Пароль пользователя Jabber
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if not userPwd:
            userPwd = "crypt{xxx}"
        self.clVars.Set("ur_hash",userPwd)
        self.clVars.Set("ur_name", userName)
        #Полное имя пользователя
        fullNameUser = self.servUnixObj.fullNameUser
        if options.has_key('c'):
            fullNameUser = options['c']
        else:
            # Проверяем установку сервиса не печатая ошибку в случае
            # если сервис не установлен
            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)
        ldifFile = self.ldifFileUser
        userLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            #Добавляем пользователя в LDAP
            self.ldapObj.ldapAdd(userLdif)
            #ldapObj.ldapAdd(userLdif1)
        # не переделывать на else
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        # загружаем картинку
        if options.has_key('i'):
            photoFile = options['i']
            if not self.setJpegPhotoUser(userName, photoFile):
                self.printERROR(_("Can not add jpeg photo for user") + " " +\
                                str(userName))
                self.delUserJabberServer(userName, options, False)
                return False
        self.printSUCCESS(_("Added user in Jabber service") + " ...")
        return True

    def setupJabberServer(self, options):
        """Начальная настройка Jabber сервиса"""
        # Принудительная установка
        forceOptions = False
        if options.has_key("f"):
            forceOptions = True
        # Создаем объект переменных и начальная проверка
        if not self.initialChecksSetup():
            return False
        #self.clVars.printVars()
        #return True
        if self.clVars.Get("sr_ldap_set") != "on":
            self.printERROR(_("LDAP service is not setuped"))
            self.printWARNING(_("Setup LDAP service"))
            self.printWARNING("  cl-setup ldap")
            return False
        # В случае если сервер установлен
        if self.clVars.Get("sr_jabber_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
                _("Jabber server is configured")+ ".")
            return True

        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы сервиса Mail (программы Postfix и Dovecot)
            self.printWARNING (_("WARNING") + ": " +
                _("Executing of the program will change") + " " +
                _("the configuration files of Jabber service") +" ("+
                _("program Ejabberd") + ")." )
            # если вы готовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program") + ", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
        else:
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            bakupObj = servLdap()
            bakupObj.backupServer()
        # Удаляем переменные сервиса в ini файлах
        self.deleteServiceVarsInFile("jabber")
        # Cоздаем объект переменные
        self.createClVars()
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("ejabberd"):
            return False
        # останавливаем сервис Jabber
        if not self.stopServices(["jabber"]):
            return False
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","jabber")
        self.clVars.Write("sr_jabber_set","off")
        # Jabber host
        fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'),
                               self.clVars.Get('os_net_domain'))
        if options.has_key("host"):
            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)

        if options.has_key("history"):
            history = options["history"].strip()
            if history in ("on", "off"):
                self.clVars.Set("sr_jabber_history", history)
            else :
                self.printERROR(\
                        _("Command line incorrect, \
'history=%s' - error, to use 'history on' or 'history off'")\
                        %str(history) + " ...")
                return False
        # Cоздаем объект профиль устанавливая директорию jabber для
        # файлов профилей
        if not self.applyProfilesFromService('jabber'):
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        else:
            if not self.restartLdapServer():
                return False
        # Подключаемся к LDAP cерверу
        if not shareLdap.getLdapObjInFile(self):
            return False
        # Находим в LDAP Jabber сервис
        resSearch = self.searchService()
        ret = True
        if resSearch:
            delDN = self.relDN
            ret = self.deleteDN(delDN)
            if ret:
                self.printOK(_("Remove Jabber DN from LDAP Database") +" ...")
            else:
                self.printERROR(\
                            _("Can not remove Jabber DN from LDAP Database")+\
                            " ...")
        if not ret:
            return False
        ldifFile = self.ldifFileBase
        baseLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            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)
        if not self.addUserJabberServer(adminName,{'p':""}, False):
            return False
        # Записываем данные администратора сервиса Jabber
        ldapParser = iniLdapParser()
        ldapParser.setVar("jabber",
            {"DN":self.clVars.Get("ld_jabber_dn"),
             "PASS":self.clVars.Get("ld_jabber_pw")})
        self.printOK(_("Added ldif file") +" ...")
        # создаем сертификат если есть используем прежний
        self.execProg("/bin/bash /etc/jabber/self-cert.sh")
        if not os.path.exists("/etc/jabber/ssl.pem"):
            self.printERROR(_("Can not create Jabber certificate") + " ...")
            return False
        textLines = self.execProg("/etc/init.d/ejabberd start", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            self.printOK(_("Starting") + " " + "Ejabberd" + " ...")
        else:
            self.printNotOK(_("Starting") + " " + "Ejabberd" + " ...")
            return False
         # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("ejabberd"):
            return False
        #запишем переменные для сервера
        jabberHost = self.clVars.Get("sr_jabber_host")
        self.clVars.Write("sr_jabber_host",jabberHost,True,"local")
        self.clVars.Write("sr_jabber_history",
                          self.clVars.Get("sr_jabber_history"),
                          True,"local")
        #запишем переменные для клиента
        clientVars = ["sr_jabber_host","sr_jabber_crypt","sr_jabber_port"]
        if not self.saveVarsClient(clientVars):
            return False
        self.clVars.Write("sr_jabber_set","on")
        self.printOK(_("Jabber service configured") + " ...")
        return True

class servSamba(shareLdap):
    """Методы севисa Samba"""

    relGrDN = 'ou=Groups'
    relUsDN = 'ou=Users'
    relCsDN = 'ou=Computers'
    relServDN = 'ou=Samba'
    ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/samba_base.ldif"
    # Файл для определения к какому из серверов 
    # подключился клиент в случае включения репликации
    shareReplFile = ".reprun"

    def __init__(self,  unixObj=False):
        shareLdap.__init__(self)
        self.relDN = self.addDN(self.relServDN,self.ServicesDN)
        # DN пользователей, относительно базового DN
        self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
        # DN групп пользователей, относительно базового DN
        self.relGroupsDN = self.addDN(self.relGrDN, self.relDN)
        # DN, компьютеров относительно базового DN
        self.relComputersDN = self.addDN(self.relCsDN, self.relDN)
        if unixObj:
            # получаем объект сервиса Unix
            self.servUnixObj = unixObj
        else:
            # создаем объект сервиса Unix
            self.servUnixObj = servUnix(self)

    def delReplFile(self, clVars):
        """Удаляем файл из директории share в случае отключения репликации"""
        # Файл для определения к какому из серверов 
        # подключился клиент
        fileReplRun = os.path.join(clVars.Get("sr_samba_share_path"),
                                   self.shareReplFile)
        if os.path.exists(fileReplRun):
            try:
                os.remove(fileReplRun)
            except:
                self.printERROR(_("Can not remove %s")%fileReplRun)
                return False
        return True

    def addReplFile(self, clVars):
        """Добавляем файл в директорию share в случае влючения репликации"""
        fileReplRun = os.path.join(clVars.Get("sr_samba_share_path"),
                                   self.shareReplFile)
        if not os.path.exists(fileReplRun):
            # Создаем файл
            # Текст внутри файла
            warning = _("Please do not remove the file, it was added by \
the calculate-server")
            if not self.createUserFile(fileReplRun,warning,0,0,
                                        mode=0644):
                return False
        return True

    def getLdapObjInFile(self):
        """Cоединение с LDAP администратором Samba сервиса"""
        return shareLdap.getLdapObjInFile(self, "samba")

    def delUserSambaServer(self,userName,options,printSuccess=True,
        backup=True, notDeletedDirs=[]):
        """Удаляем Samba пользователя"""
        # Проверим установлен ли сервис samba
        if not self.initialChecks("samba"):
            return False
        if "$" in userName:
            # удаляемая машина
            delUser = userName.replace('$','') + "$"
            if not self.searchSambaMachine(delUser):
                self.printERROR (_("ERROR") + ": " +\
                    _("Samba machine %s is not found in Samba service")%\
                      str(delUser))
                return False
        else:
            # удаляемый пользователь
            delUser = userName
            if not self.searchSambaUser(delUser):
                self.printERROR (_("ERROR") + ": " +\
                    _("Samba user %s is not found in Samba service") %\
                     str(delUser))
                return False
        winProfDir =\
            os.path.join(self.clVars.Get("sr_samba_winprof_path"),
                                         userName)
        linProfDir =\
                os.path.join(self.clVars.Get("sr_samba_linprof_path"),
                                         userName)
        userHomeDir =\
            os.path.join(self.clVars.Get("sr_samba_home_path"),
                                         userName)
        userNetlogonDir =\
            os.path.join(self.clVars.Get("sr_samba_winlogon_path"),
                                         userName)
        if options.has_key('r'):
            backup = False
        # Делаем сохранение данных удаляемого пользователя
        if backup:
            if os.path.exists(winProfDir) and os.listdir(winProfDir):
                if not self.backupDelUser(userName, 'samba/winprofile',
                                          winProfDir):
                    return False
            if os.path.exists(linProfDir) and os.listdir(linProfDir):
                if not self.backupDelUser(userName, 'samba/linprofile',
                                          linProfDir):
                    return False
            if os.path.exists(userHomeDir)and os.listdir(userHomeDir):
                if not self.backupDelUser(userName, 'samba/home',
                                          userHomeDir):
                    return False
            if os.path.exists(userNetlogonDir) and os.listdir(userNetlogonDir):
                if not self.backupDelUser(userName, 'samba/netlogon',
                                          userNetlogonDir):
                    return False
        textLine = self.execProg("smbpasswd -x %s" %(delUser), False, False)
        flagError = False
        if textLine:
            if type(textLine) == types.ListType:
                listLine = []
                for line in textLine:
                    listLine.append(line.rstrip())
                textLine = " ".join(listLine)
        else:
            flagError = True
        if not "Deleted user %s" %(delUser) in textLine:
            flagError = True
        if flagError:
            self.printERROR(_("ERROR") + ": " +\
                _("Can not delete Samba user") + " " + str(delUser) + " ...")
            return False
        else:
            # Удаляем win профиль
            if not winProfDir in notDeletedDirs and\
                os.path.exists(winProfDir):
                self.removeDir(winProfDir)
            # Удаляем lin профиль
            if not linProfDir in notDeletedDirs and\
                os.path.exists(linProfDir):
                self.removeDir(linProfDir)
            # Удаляем домашнюю директорию
            if not userHomeDir in notDeletedDirs and\
                os.path.exists(userHomeDir):
                self.removeDir(userHomeDir)
            # Удаляем netlogon
            if not userNetlogonDir in notDeletedDirs and\
                os.path.exists(userNetlogonDir):
                self.removeDir(userNetlogonDir)
            if self.servUnixObj.searchUnixUser(userName) and\
            not self.servUnixObj.modUserUnixServer(userName,{"I":""},False):
                return False
            if printSuccess:
                self.printSUCCESS(_("Deleted Samba user %s") % str(delUser) +\
                      " ...")
            return True

    @adminConnectLdap
    def addUserSambaServer(self,userName,options,pwDialog=False,
                           checkSetup=True,pwd=False):
        """Добавляет LDAP пользователя в LDAP-сервер"""
        # Проверим установлен ли сервис samba
        if checkSetup and not self.initialChecks("samba"):
            return False
        # Добавление машины samba
        if options.has_key('w'):
            if self.addMachineSambaServer(userName, options):
                return True
            else:
                return False
        # id пользователя Unix
        uidUnixUser = False
        resSearch = self.servUnixObj.searchUnixUser(userName)
        flagFoundPasswd = False
        if not resSearch:
            resSearch = self.servUnixObj.searchPasswdUser(userName)
            if resSearch:
                flagFoundPasswd = True
        else:
            uidUnixUser = resSearch[0][0][1]['uidNumber'][0]
            ## создание пользователя Unix опция f
            #if not resSearch and not options.has_key('f'):
                #self.printERROR(
                    #_("User %s is not found in Unix service")%\
                    #str(userName) + " ...")
                #return False
        if self.searchSambaUser(userName):
            self.printERROR(_("Samba user exists"))
            return False
        #пароль пользователя
        userPwd = ""
        if pwd:
            userPwd = pwd
        else:
            #диалог ввода пароля
            if not pwDialog:
                pwDialog = [_("New SMB password"),
                            _("Retype new SMB password")]
            userPwd = self.getUserPassword(options, "p", "P", pwDialog)
        if userPwd == False:
            return False
        flagCreateUnixUser = False
        if not resSearch:
            # Добавим пользователя LDAP
            optUnix = {}
            # id пользователя
            if options.has_key('u'):
                optUnix['u'] = options['u']
            # Группа пользователя
            if options.has_key('g'):
                optUnix['g'] = options['g']
            # Группы в которые входит пользователь
            if options.has_key('G'):
                optUnix['G'] = options['G']
            # Полное имя пользователя
            if options.has_key('c'):
                optUnix['c'] = options['c']
            # shell
            if options.has_key('s'):
                optUnix['s'] = options['s']
            # Домашняя директория
            if options.has_key('d'):
                optUnix['d'] = options['d']
            # Cделаем пользователя видимым
            if optUnix.has_key('u'):
                try:
                    int(optUnix['u'])
                except:
                    self.printERROR(_("UID is not number"))
                    return False
                if int(optUnix['u']) >= 1000:
                    optUnix['v'] = ""
            else:
                optUnix['v'] = ""
            if not self.servUnixObj.addUserUnixServer(userName, optUnix,
                                                      False,userPwd):
                self.printERROR (_("Can not add user")+ " " +\
                                 str(userName) + _(" in Unix service"))
                return False
            flagCreateUnixUser = True
        elif not flagFoundPasswd:
            if userPwd:
                # Меняем пароль у пользователя Unix
                if not self.servUnixObj.modUserUnixPasswd(userName,{},userPwd):
                    return False
            # Делаем пользователя видимым
            if uidUnixUser==False or int(uidUnixUser) >=1000:
                if not self.servUnixObj.modUserUnixServer(userName,
                                                          {"V":""},False):
                    return False

        if userPwd:
            textLine = self.execProg("smbpasswd -a -s %s" %(userName),
            "%s\n%s\n" %(userPwd,userPwd))
        else:
            textLine = self.execProg("smbpasswd -a -n %s" %(userName))
        if "Added" in str(textLine):
            flagError = False
            winProfDir =\
                os.path.join(self.clVars.Get("sr_samba_winprof_path"),
                                         userName)
            linProfDir =\
                os.path.join(self.clVars.Get("sr_samba_linprof_path"),
                                         userName)
            userHomeDir =\
                os.path.join(self.clVars.Get("sr_samba_home_path"),
                                         userName)
            userNetlogonDir =\
                os.path.join(self.clVars.Get("sr_samba_winlogon_path"),
                                         userName)
            message = _("Do you want to restore deleted user %s data?")\
                      %userName + "\n" + "'yes', 'no'"
            resWinProf = self.restorePathDelUser(userName, winProfDir,
                                                 "samba/winprofile", message)
            removeProfileBack = False
            if not resWinProf:
                flagError = True
                createDirWinProfile = False
            else:
                term, createDirWinProfile, removeProfileBack = resWinProf

            removeHomeBack = False
            if not flagError:
                resHome = self.restorePathDelUser(userName, userHomeDir,
                                                 "samba/home", term)
                if not resHome:
                    flagError = True
                    createDirHome = False
                else:
                    term, createDirHome, removeHomeBack = resHome

            removeLogonBack = False
            if not flagError:
                resLogon = self.restorePathDelUser(userName, userNetlogonDir,
                                                 "samba/netlogon", term)
                if not resLogon:
                    flagError = True
                    createDirLogon = False
                else:
                    term, createDirLogon, removeLogonBack = resLogon

            removeLinProfileBack = False
            if not flagError:
                resLinProf = self.restorePathDelUser(userName, linProfDir,
                                                    "samba/linprofile", term)
                if not resLinProf:
                    flagError = True
                    createDirLinProfile = False
                else:
                    term,createDirLinProfile,removeLinProfileBack = resLinProf
            # Cоздадим нужные директории
            if not flagError:
                resSearchUnix = self.servUnixObj.searchUnixUser(userName)
                resPasswd = False
                if resSearchUnix:
                    uid = int(resSearchUnix[0][0][1]['uidNumber'][0])
                    gid = int(resSearchUnix[0][0][1]['gidNumber'][0])
                else:
                    resPasswd = self.servUnixObj.searchPasswdUser(userName)
                    if resPasswd:
                        uid = int(resPasswd.split(":")[2])
                        gid = int(resPasswd.split(":")[3])
                # Не удаляемые директории
                notDeletedDirs = []
                if createDirHome and os.path.exists(createDirHome):
                    notDeletedDirs.append(createDirHome)
                if createDirLogon and os.path.exists(createDirLogon):
                    notDeletedDirs.append(createDirLogon)
                if createDirWinProfile and os.path.exists(createDirWinProfile):
                    notDeletedDirs.append(createDirWinProfile)
                if createDirLinProfile and os.path.exists(createDirLinProfile):
                    notDeletedDirs.append(createDirLinProfile)
                if (resPasswd or resSearchUnix) and\
                    (options.has_key('n') or int(uid) >=1000):
                    # Cоздаем домашнюю директорию
                    if createDirHome:
                        if not self.createUserDir(uid, gid, createDirHome):
                            flagError = True
                        # Cоздаем иконку в домашней директории
                        if not flagError:
                            fileTxt = "[Desktop Entry]\nIcon=user-home"
                            fileDirectory = os.path.join(createDirHome,
                                                         ".directory")
                            if not self.createUserFile(fileDirectory,
                                                       fileTxt, uid, gid):
                                flagError = True
                    # Cоздаем директорию netlogon
                    if not flagError and createDirLogon:
                        if not self.createUserDir(uid, gid, createDirLogon):
                            flagError = True
                        # cоздадим cmd файл для монтирования ресурсов в windows
                        if not flagError:
                            netbios = self.clVars.Get("sr_samba_netbios")
                            netbios = netbios.upper()
                            fileTxt='NET USE R: /D\r\nNET USE R: \\\\%s\\share\
\r\nNET USE T: /D\r\nNET VIEW \\\\%s | find "ftp"\r\n\
if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios)
                            fileDirectory = os.path.join(createDirLogon,
                                                         "start.cmd")
                            if not self.createUserFile(fileDirectory,
                                                       fileTxt, uid, gid):
                                flagError = True
                    # Cоздаем директорию профиля win
                    if not flagError and createDirWinProfile:
                        if not self.createUserDir(uid,gid,createDirWinProfile):
                            flagError = True
                    # Создаем директорию профиля lin
                    if not flagError and createDirLinProfile:
                        if not self.createUserDir(uid,gid,createDirLinProfile):
                            flagError = True
            if not flagError:
                # Удаляем директорию бекапа профиля win
                if removeProfileBack and\
                    os.path.exists(removeProfileBack):
                    self.removeDir(removeProfileBack)
                    self.removeEmptyDir(os.path.split(removeProfileBack)[0])
                # Удаляем директорию бекапа профиля lin
                if removeLinProfileBack and\
                    os.path.exists(removeLinProfileBack):
                    self.removeDir(removeLinProfileBack)
                    self.removeEmptyDir(os.path.split(removeLinProfileBack)[0])
                # Удаляем бекап домашней директории
                if removeHomeBack and\
                    os.path.exists(removeHomeBack):
                    self.removeDir(removeHomeBack)
                    self.removeEmptyDir(os.path.split(removeHomeBack)[0])
                # Удалим директорию logon пользователя
                if removeLogonBack and\
                    os.path.exists(removeLogonBack):
                    self.removeDir(removeLogonBack)
                    self.removeEmptyDir(os.path.split(removeLogonBack)[0])
            if flagError:
                self.delUserSambaServer(userName,{},False,False,notDeletedDirs)
                if flagCreateUnixUser:
                    self.servUnixObj.delUserUnixServer(userName, {},
                                                    False, False)
                self.printERROR(_("Can not add user %s")%userName + " ...")
                return False
            if flagCreateUnixUser:
                self.printSUCCESS(_("Added user %s in Unix service")%userName+\
                                  " ...")
            self.printSUCCESS(_("Added user %s in Samba service")%userName +\
                              " ...")
            return True
        else:
            if flagCreateUnixUser:
                self.servUnixObj.delUserUnixServer(userName, {}, False, False)
            self.printERROR(_("Can not add user %s")%userName + " ...")
            return False

    def searchSambaUser(self, userName):
        """Находит пользователя сервиса Samba"""
        resSearch = self.searchLdapDN(userName, self.relUsersDN, "uid")
        return resSearch

    def searchSambaMachine(self, machineName):
        """Находит машину (компьютер) сервиса Samba"""
        resSearch = self.searchLdapDN(machineName, self.relComputersDN, "uid")
        return resSearch

    def addMachineSambaServer(self, machineName, options):
        """Добавляет Samba машину в LDAP-сервер"""
        machineLogin = machineName.replace('$','') + "$"
        res = self.searchSambaMachine(machineLogin)
        if res:
            if res[0][0][1].has_key('sambaSID'):
                self.printERROR(_("machine")+" "+machineLogin+" "+\
                                  "is found in Samba service")
                return True
            # добавляем Samba машину
            textLine = self.execProg("smbpasswd -a -m %s" %machineLogin)
            if "Added" in str(textLine):
                self.printSUCCESS(_("Added machine in Samba service") + " ...")
                return True
            else:
                self.printERROR(_("Can not add machine") + " ...")
                return False
        else:
            # добавляем LDAP машину
            if not self.servUnixObj.addMachineLdapServer(machineLogin,
                                                         options):
                return False
            # добавляем Samba машину
            textLine = self.execProg("smbpasswd -a -m %s" %machineLogin)
            if "Added" in str(textLine):
                self.printSUCCESS(_("Added machine in Samba service") + " ...")
                return True
            else:
                self.printERROR(_("Can not add machine")+ " ...")
                return False

    def getAllowNet(self):
        """Получаем от пользователя доверительные сети

        и устанавливаем переменную профилей sr_samba_net_allow

        self.clVars должен быть определен
        """
        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 = ""
        if netAllow:
            strNetAllow = netAllow.replace(","," ")
        allowNet = self.getUserAllowNetwork(strPrompt, strNetAllow)
        if not allowNet:
            return False
        # Установка переменной доступные сети
        allowNet = ",".join(allowNet)
        self.clVars.Set("sr_samba_net_allow", allowNet ,True)
        return allowNet

    def setupSambaServer(self, options):
        """Начальная настройка Samba сервиса"""
        # Принудительная установка
        forceOptions = False
        # Создаем объект переменных и начальная проверка
        if not self.initialChecksSetup():
            return False
        if options.has_key("f"):
            forceOptions = True
        if self.clVars.Get("sr_unix_set") != "on":
            self.printERROR(_("Unix service is not setuped"))
            self.printWARNING (_("Setup Unix service"))
            self.printWARNING("  cl-setup unix")
            return False
        # В случае если сервер установлен
        if self.clVars.Get("sr_samba_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
            _("Samba server is configured")+ ".")
            return True
        # Доверительные сети по умолчанию
        allowNet = self.clVars.Get("os_net_allow")
        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы сервиса Samba
            self.printWARNING (_("WARNING") + ": " +
                _("Executing of the program will change") + " " +
                _("the configuration files of Samba service") + ".")
            # если вы готовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program")+", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
            if options.has_key("a"):
                # Получаем от пользователя доверительные сети
                allowNet = self.getAllowNet()
                if not allowNet:
                    return False
        else:
            if options.has_key("a"):
                # Получаем от пользователя доверительные сети
                allowNet = self.getAllowNet()
                if not allowNet:
                    return False
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            bakupObj = servLdap()
            bakupObj.backupServer()
        # Удаляем переменные сервиса в ini файлах
        self.deleteServiceVarsInFile("samba")
        # Cоздаем объект переменные
        self.createClVars()
        # Устанавливаем доступные сети
        self.clVars.Set("sr_samba_net_allow",allowNet,True)
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("samba"):
            return False
        # Удаляем из share файл .replrun
        if not self.delReplFile(self.clVars):
            return False
        # останавливаем сервис Samba
        if not self.stopServices(["samba"]):
            return False
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","samba")
        self.clVars.Write("sr_samba_set","off")
        # Задаем рабочую группу
        if options.has_key("w"):
            workgroup = options['w'].strip()
            self.clVars.Set("sr_samba_domain",workgroup)
        # Задаем netbios имя
        if options.has_key("n"):
            netbios = options['n'].strip()
            self.clVars.Set("sr_samba_netbios",netbios)

        # Cоздаем объект профиль устанавливая директорию samba для
        # файлов профилей
        if not self.applyProfilesFromService('samba'):
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        else:
            if not self.restartLdapServer():
                return False
        # Записываем данные администратора сервиса Samba
        ldapParser = iniLdapParser()
        ldapParser.setVar("samba",
            {"DN":self.clVars.Get("ld_samba_dn"),
             "PASS":self.clVars.Get("ld_samba_pw")})
        ldapParser = iniLdapParser()
        pswd = ldapParser.getVar("samba","PASS")
        if not pswd:
            self.printERROR(_("ERROR") + ": " +\
            _("Samba admin password is not found"))
            return False
        textLine = self.execProg("smbpasswd -w %s" %(pswd))
        if not "stored" in textLine:
            self.printERROR(_("ERROR") + ": " +\
                _("Can not add Samba admin password"))
            return False
        textLines = self.execProg("/etc/init.d/slapd restart", False, False)
        if not (textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines):
            self.printNotOK(_("LDAP restart") + " ...")
            return False
        #Cоединение с Ldap (администратор)
        if not shareLdap.getLdapObjInFile(self):
            return False
        resSearch = self.searchService()
        ret = True
        if resSearch:
            delDN = self.relDN
            ret = self.deleteDN(delDN)
            if ret:
                self.printOK(_("Removed Samba DN from LDAP Database") +" ...")
            else:
                self.printERROR(\
                    _("Can not remove Samba DN from LDAP Database") +" ...")
        if not ret:
            return False
        ldifFile = self.ldifFileBase
        baseLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        self.printOK(_("Added ldif file") +" ...")
        textLines = self.execProg("/etc/init.d/samba start", False, False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            self.printOK(_("Starting") + " Samba ...")
        else:
            self.printNotOK(_("Starting") + " Samba ...")
            return False
        cl = self.staticUsers["client"]
        clGr = self.staticGroups["client"]
        adm = self.staticUsers["admin"]
        admGr = self.staticGroups["admin"]
        # Создаем клиента
        # Проверяем на наличие группы client
        resGroupClient = self.servUnixObj.searchUnixGroupName(clGr.name)
        if not resGroupClient:
            # Создаем группу для пользователя client
            if not self.servUnixObj.addGroupUnixServer(clGr.name,
                                                       {'g':clGr.gid,
                                                        'c':clGr.comment},
                                                       False):
                self.printERROR(_("not created unix group 'client'"))
                return False
        # Добавляем пользователя client для smb ресурса [remote]
        if not self.addUserSambaServer('client',{'f':'','u':cl.uid,
            'c':'Client unix workstation','g':clGr.name,
            's':'/bin/false','d':'/dev/null'},False,False):
            self.printERROR(_("not created samba user 'client'"))
            return False
        # Создаем админа
        # Проверяем на наличие группы admin
        resGroupAdmin = self.servUnixObj.searchUnixGroupName(admGr.name)
        if not resGroupAdmin:
            # Создаем группу для пользователя admin
            if not self.servUnixObj.addGroupUnixServer(admGr.name,
                                                       {'g':admGr.gid,
                                                       'c':admGr.comment},
                                                       False):
                self.printERROR(_("not created unix group 'admin'"))
                return False
        # Добавляем пользователя admin
        if not self.addUserSambaServer('admin',{'f':'','u':adm.uid,
            'c':'Administrator samba service','g':admGr.name,
            's':'/bin/false','d':'/dev/null'},False,False):
            self.printERROR(_("not created samba user 'admin'"))
            return False
        # Если нет то создадим директорию /var/calculate/remote
        remoteEnvFile = self.clVars.Get("cl_env_path")[0]
        remotePath = os.path.split(remoteEnvFile)[0]
        if not os.path.exists(remotePath):
            os.makedirs(remotePath)
        # права и владелец /var/calculate/remote
        if os.path.exists(remotePath):
           os.chown(remotePath,0,int(cl.gid))
           os.chmod(remotePath,02750)
        # изменяем владельца remote на client
        if not os.path.exists(remoteEnvFile):
            fd = os.open(remoteEnvFile, os.O_CREAT)
            os.close(fd)
            os.chmod(remoteEnvFile, 0640)
        if os.path.exists(remoteEnvFile):
            os.chown(remoteEnvFile,0,int(cl.gid))
        if not self.setDaemonAutostart("slapd"):
            return False
        # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("samba"):
            return False
        # если нет share то создадим
        sharePath = self.clVars.Get("sr_samba_share_path")
        if not os.path.exists(sharePath):
            os.makedirs(sharePath)
        # Создадим иконку для share
        fileTxt = "[Desktop Entry]\nIcon=folder-bookmarks"
        fileDirectory = os.path.join(sharePath,".directory")
        uid = 0
        gid = 0
        if not self.createUserFile(fileDirectory, fileTxt, uid, gid):
            return False
        #запишем переменные для сервера
        domain = self.clVars.Get("sr_samba_domain")
        self.clVars.Write("sr_samba_domain",domain,True,"local")
        netbios = self.clVars.Get("sr_samba_netbios")
        self.clVars.Write("sr_samba_netbios",netbios,True,"local")
        allow = self.clVars.Get("sr_samba_net_allow")
        self.clVars.Write("sr_samba_net_allow",allow,True,"local")
        #запишем переменные для клиента
        fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'),
                               self.clVars.Get('os_net_domain'))
        self.clVars.Set("sr_samba_host",fullHostName,True)
        clientVars = ["sr_samba_host","ld_services_dn", "ld_unix_dn",
                      "ld_bind_dn","ld_bind_pw","ld_base_dn"]
        if not self.saveVarsClient(clientVars):
            return False
        self.clVars.Write("sr_samba_set","on")
        self.printOK(_("Samba service configured") + " ...")
        return True

    def modUserSambaPasswd(self, userName, options):
        # Проверим установлен ли сервис samba
        if not self.initialChecks("samba"):
            return False
        if not self.searchSambaUser(userName):
            self.printERROR(
                _("Samba user %s is not found")%str(userName) + " ...")
            return False
        # отключаем samba account
        if options.has_key('l'):
            textLine = self.execProg("smbpasswd -d %s" %(userName))
            if "Disabled user %s" %userName in textLine:
                self.printSUCCESS(_("Disabled Samba user %s")%str(userName)+
                        " ...")
            else:
                self.printERROR(_("Can not disable Samba user")+ " "+\
                str(userName) + " ...")
                return False
        # включаем Samba account
        if options.has_key('u'):
            textLine = self.execProg("smbpasswd -e %s" %(userName))
            if "Enabled user %s" %userName in textLine:
                self.printSUCCESS(_("Enabled Samba user %s")%str(userName) +
                        " ...")
            else:
                self.printERROR(_("Can not enable Samba user")+ " "+\
                str(userName) + " ...")
                return False
        if not options or options.has_key('s'):
            optPasswd = {"p":""}
            userPwd = self.getUserPassword(optPasswd, "p", False)
            if userPwd == False:
                return False
            if userPwd:
                # Опция s пароль только для Samba
                if not options.has_key('s'):
                    if not self.servUnixObj.modUserUnixPasswd(userName,{},
                        userPwd):
                        return False
                textLine = self.execProg("smbpasswd -a -s %s" %(userName),
                    "%s\n%s\n" %(userPwd,userPwd))
                if not (textLine == None):
                    self.printERROR(_("Can not change Samba user password") +\
                    " ...")
                    return False
                else:
                    self.printSUCCESS(
                        _("Samba password of user %s is changed")%\
                            str(userName) + " ...")
                    return True
        return True

    def modUserSambaServer (self, userName, options):
        """Модифицирует настройки пользователя Samba в LDAP"""
        # Проверим установлен ли сервис samba
        if not self.initialChecks("samba"):
            return False
        # Находим Samba пользователя
        res = self.searchSambaUser(userName)
        if not res:
            self.printERROR(
                _("Samba user %s is not found in Samba service")%\
                     str(userName) + " ...")
            return False
        # отключаем Samba account
        if options.has_key('L'):
            textLine = self.execProg("smbpasswd -d %s" %(userName))
            if "Disabled user %s" %userName in textLine:
                self.printSUCCESS(_("Disabled Samba user %s")%str(userName) +\
                                " ...")
            else:
                self.printERROR(_("Can not disable Samba user")+ " "+\
                str(userName) + " ...")
                return False
        # включаем samba account
        elif options.has_key('U'):
            textLine = self.execProg("smbpasswd -e %s" %(userName))
            if "Enabled user %s" %userName in textLine:
                self.printSUCCESS(_("Enabled Samba user %s")%str(userName) +\
                                    " ...")
            else:
                self.printERROR(_("Can not enable Samba user")+ " "+\
                                  str(userName) + " ...")
                return False
        # модифицируем пароль
        if options.has_key('P') or options.has_key('p'):
            pwDialog = [_("New SMB password"),
                        _("Retype new SMB password")]
            pwdA = getpass.getpass(pwDialog[0]+":")
            pwdB = getpass.getpass(pwDialog[1]+":")
            if not (pwdA == pwdB):
                self.printERROR (_("ERROR") + ": " +\
                _("password incorrect")+ ": " + _("try again"))
                return False
            userPwd = pwdA
            # Опция s пароль только для Samba
            if not options.has_key('s'):
                if not self.servUnixObj.modUserUnixPasswd(userName,{},
                    userPwd):
                    return False
            textLine = self.execProg("smbpasswd -s %s" %(userName),
            "%s\n%s\n" %(userPwd,userPwd))
            if not (textLine == None):
                self.printERROR(_("Can not modify Samba user password") +\
                                " ...")
                return False
            self.printSUCCESS(_("Modified Samba user password") + " ...")
        # изменяем Unix группы в которые включен пользователь
        if options.has_key("G"):
            strGroups = options["G"]
            optUnix = {'G':strGroups}
            if not self.servUnixObj.modUserUnixServer(userName, optUnix):
                return False
        return True

class filterProfiles(cl_profile.profile):
    """Класс для фильтрации налагаемых профилей"""
    def __init__(self, objVar, servDir=False, dirsFilter=[],
                 filesFilter=[]):
        self.dirsFilter = dirsFilter
        self.filesFilter = filesFilter
        cl_profile.profile.__init__(self, objVar, servDir)
 
    def scanDirs(self, profilesDirs):
        """Измененный метод сканирования директорий"""
        rez = cl_profile.profile.scanDirs(self, profilesDirs)
        if rez and (self.dirsFilter or self.filesFilter):
            for obj in rez:
                dirs = []
                dirsRel = []
                for dirName in obj.dirs:
                    oldDir = dirName.split(obj.baseDir)[1]
                    if not oldDir in self.dirsFilter:
                        dirs.append(dirName)
                        dirsRel.append(oldDir)
        return rez

class servLdap(shareLdap):
    """Методы севисa Ldap"""

    # Базовый ldif файл
    ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/base.ldif"
    # Для backup
    # Директория куда будет сохранен архив
    backupDirectory = "/var/calculate/server-backup/ldap"
    # ldif файл базы LDAP
    archLdifFile = "/tmp/LDAP_DATABASE.ldif"
    # ldif файл базы LDAP для сервиса Unix
    replArchLdifFileUnix = "/tmp/REPL_LDAP_DATABASE_UNIX.ldif"
    # список файлов в архиве для сервиса Unix
    replListFileUnix = "/tmp/REPL_LIST_FILES_UNIX.txt"
    # ldif файл базы LDAP для сервиса Samba
    replArchLdifFileSamba = "/tmp/REPL_LDAP_DATABASE_SAMBA.ldif"
    # список файлов в архиве для сервиса Samba
    replListFileSamba = "/tmp/REPL_LIST_FILES_SAMBA.txt"
    # ldif файл базы LDAP для сервиса Mail
    replArchLdifFileMail="/tmp/REPL_LDAP_DATABASE_MAIL.ldif"
    # список файлов в архиве для сервиса Mail
    replListFileMail = "/tmp/REPL_LIST_FILES_MAIL.txt"
    # ldif файл базы LDAP для сервиса Mail, Samba
    replArchLdifFileMailSamba="/tmp/REPL_LDAP_DATABASE_MAIL_SAMBA.ldif"
    # список файлов в архиве для сервиса Mail, Samba
    replListFileMailSamba = "/tmp/REPL_LIST_FILES_MAIL_SAMBA.txt"
    # ldif файл базы LDAP для сервиса Mail, Unix
    replArchLdifFileMailUnix = "/tmp/REPL_LDAP_DATABASE_MAIL_UNIX.ldif"
    # список файлов в архиве для сервиса Mail, Unix
    replListFileMailUnix = "/tmp/REPL_LIST_FILES_MAIL_UNIX.txt"
    # приватная директория Samba
    sambaPrivate = "/var/lib/samba/private"
    # директория c алиасами сервиса Mail
    mailPrivate = "/etc/mail"
    # название файла где будет храниться список архивируемых файлов
    tmpListFile = "/tmp/list_CDS_files.txt"
    # Директория для хранения профилей backup
    backupDir = "backup"
    # Директории хранения сертификатов сервиса Mail
    sslDirsMail = ["/etc/ssl/dovecot","/etc/ssl/postfix"]
    # Файл сертификата сервиса jabber
    sslJabberFile = "/etc/jabber/ssl.pem"
    # директория для хранения  временных файлов
    tmpEnvDir = "/tmp/tmp_calculate"

    def __init__(self):
        shareLdap.__init__(self)
        # Сервис Samba
        self.servSambaObj = servSamba()
        # Сервис Mail
        self.servMailObj = servMail()
        # Сервис Jabber
        self.servJabberObj = servJabber()

    def savePrivateFile(self, fileName, data):
        """Записать файл с правами 0600"""
        try:
            FD = open (fileName, "w+")
            FD.close()
            os.chmod(fileName,0600)
            FD = open (fileName, "w+")
            FD.write(data)
            FD.close()
        except:
            return False
        return True

    def getServiceSetupPathProfiles(self):
        """Находим пути к профилям установленных сервисов

        Выдаем два списка ([пути к профилям сервисов],[установленные сервисы])
        """
        servicePaths = []
        servInstalled = []
        # Инсталлированные сервисы
        servInst = self.getServiceSetup()
        # пути к директориям профилей
        profilePaths = self.clVars.Get("cl_profile_path")
        for profilePath in profilePaths:
            for serv in servInst:
                if self.clVars.Get("sr_%s_set"%serv) == "on":
                    servPath = os.path.join(profilePath,serv)
                    if os.path.exists(servPath):
                        servicePaths.append(servPath)
                        servInstalled.append(serv)
        return (servicePaths, servInstalled)

    def rebuildServer(self, options):
        """Перегенерирует конфигурационные файлы, и базу данных LDAP"""
        bFile = self.getArchFile()
        if not bFile:
            return False
        self.printSUCCESS(_("Used backup file %s")%str(bFile))
        archFileTime = time.localtime(os.stat(bFile)[stat.ST_MTIME])
        timeFile = datetime.datetime(archFileTime[0],archFileTime[1],
                                     archFileTime[2],archFileTime[3],
                                     archFileTime[4],archFileTime[5])
        localTime = time.localtime()
        timeLocal = datetime.datetime(localTime[0],localTime[1],
                                     localTime[2],localTime[3],
                                     localTime[4],localTime[5])
        if timeLocal < timeFile:
            self.printERROR(_("Incorrect system time or time create file %s")\
                            %bFile)
            return False
        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
            hours = _("hours")
            minutes = _("minutes")
            seconds = _("seconds")
            if dHours:
                timeBackup = "%s %s %s %s %s %s"%\
                              (dHours,hours,dMinutes,minutes,dSeconds,seconds)
            elif dMinutes:
                timeBackup = "%s %s %s %s"%(dMinutes,minutes,dSeconds,seconds)
            elif dSeconds:
                timeBackup = "%s %s"%(dSeconds,seconds)
            self.printWARNING(_("The backup file is created %s ago")%timeBackup)
        else:
            self.printWARNING(_("The backup file is created %s days ago")\
                              %deltaTime.days)
        self.printWARNING(_("cl-rebuld uses a file backup, make sure it is not \
outdated. If the backup is obsolete, use cl-backup."))
        messDialog = \
               _("If you are ready to continue executing the program")+", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
        if not self.dialogYesNo(messDialog):
            return True
        # В случае создания сервера репликации из файла backup c
        # другого компьютера
        replServices = []
        if options.has_key("repl"):
            # Находим имена сервисов р���пликации для этого сервера
            # и инициализируем переменные
            replServices = self.getArchReplServices()
            if not replServices:
                return False
            # Cоздаем объект репликации
            objRepl = servRepl()
            # Определяем поддерживает ли openldap репликацию
            if not objRepl.supportReplOpenldap(self.clVars):
                return False
            if not self.restoreServer(False,replServices):
                return False
            # Изменяем и сохраняем переменные
            if not objRepl.prepAndSaveEnv():
                return False
        else:
            # Восстанавливаем сервисы не запуская их 
            # и не прописывая в автозагрузку
            if not self.restoreServer(False):
                return False
        verbose = False
        opt = {}
        if options.has_key("v"):
            opt['v'] = ''
        if options.has_key("a"):
            opt['a'] = ''
        # Сервисы для которых не будет задаваться вопрос о доступных сетях
        # при включенной опции allow
        noInputAllowNetServices = []
        if "samba" in replServices:
            noInputAllowNetServices = ["samba"]
        if not self.updateServer(opt, "all", False, noInputAllowNetServices):
            return False
        self.printOK(_("Rebuilding all services") + " ...")
        return True

    def rebuildLdapServer(self, options):
        """Перегенерирует конфигурационные файлы, и базу данных LDAP"""
        return self.rebuildServer(options)

    def applyProfilesFromService(self, service, verbose=False, dirsFilter = [],
                                 filesFilter = []):
        """Применяем профили для данного сервиса"""
        # Cоздаем объект профиль устанавливая директорию
        # service для файлов профилей
        clProf = filterProfiles(self.clVars,service, dirsFilter, filesFilter)
        # Объединяем профили
        data = clProf.applyProfiles()
        if clProf.getError():
            self.printERROR(clProf.getError())
            return False
        else:
            if verbose and type(data) == types.TupleType:
                dirs, files = data
                return files
            return True


    def updateServer(self, options, serviceUpdate, clVars=False,
                     noInputAllowNetServices=[], printReplServ=True):
        """Перегенерируем конфигурационные файлы

        определенного или всех сервисов
        """
        # Создаем переменные
        if clVars:
            self.clVars = clVars
        else:
            self.createClVars()
        # В случае некорректно включенной репликации
        if self.clVars.Get("ld_repl_set") == "on" and\
            not self.clVars.Get("ld_repl_id"):
            self.printERROR(_("Incorrect set Replication"))
            self.printERROR(_("Not found 'serverID' this server") + " ...")
            self.printERROR(_("variable 'ld_repl_id' empty") + " ...")
            return False
        if printReplServ and self.clVars.Get("ld_repl_set") == "on":
            # Вывод списка реплицируемых �ерверов
            unixReplServ = self.clVars.Get("ld_repl_unix_servers")
            sambaReplServ = self.clVars.Get("ld_repl_samba_servers")
            mailReplServ = self.clVars.Get("ld_repl_mail_servers")
            if unixReplServ:
                self.printSUCCESS(\
                                _("Replication servers for service Unix: %s")\
                                %", ".join(unixReplServ.split(",")))
            if sambaReplServ:
                self.printSUCCESS(\
                                _("Replication servers for service Samba: %s")\
                                %", ".join(sambaReplServ.split(",")))
            if mailReplServ:
                self.printSUCCESS(_("Replication servers for service Mail: %s")\
                                %", ".join(mailReplServ.split(",")))
        # Настройка почты
        if serviceUpdate in ["all","mail"]:
            if options.has_key("t"):
                mailType = options['t']
                if mailType:
                    if not set(mailType.split(",")) <= set(["imap","pop3"]):
                        self.printERROR(\
                            _("Мail type not 'imap' or 'pop3' or 'pop3,imap'"))
                        return False
                    if len(mailType.split(",")) == 2:
                        mailType = "all"
                else:
                    self.printERROR(_("Мail type incorrect"))
                    return False
                self.clVars.Set("sr_mail_type", mailType)
            if options.has_key("c"):
                mailCrypt = options['c']
                if not mailCrypt in ["none", "tls"]:
                    self.printERROR(_("Мail encryption not 'none' or 'tls'"))
                    return False
                if mailCrypt == "none":
                    mailCrypt = ""
                self.clVars.Set("sr_mail_crypt", mailCrypt, True)
        # Настройка jabber cервиса
        # Предыдущее имя хоста для Jabber
        previousJabberHost = self.clVars.Get("sr_jabber_host")
        if serviceUpdate in ["all","jabber"]:
            # История для jabber
            if options.has_key("history"):
                history = options["history"].strip()
                if history in ("on", "off"):
                    self.clVars.Set("sr_jabber_history", history)
                else:
                    self.printERROR(\
                            _("Command line incorrect, \
'history=%s' - error, to use 'history on' or 'history off'")\
                            %str(history) + " ...")
                    return False
            if options.has_key("host"):
                newHostName = options['host']
                if not "." in newHostName:
                    newHostName = "%s.%s" %(newHostName,
                                            self.clVars.Get('os_net_domain'))
                if newHostName != previousJabberHost:
                    # Устанавливаем перемемнную
                    self.clVars.Set("sr_jabber_host",newHostName,True)
        # находим установленные сервисы
        servInstalled = self.getServiceSetup()
        if not servInstalled:
            self.printERROR("Services are not installed")
            return False
        flagError = False
        if serviceUpdate=="all":
            pass
        elif serviceUpdate in servInstalled:
            servInstalled = [serviceUpdate]
        else:
            if not serviceUpdate:
                self.printERROR(_("Service incorrect"))
            else:
                self.printERROR(_("Service %s not installed")%serviceUpdate)
            return False
        ldapParser = iniLdapParser()
        # Установка переменных
        for service in servInstalled:
            if service == "ldap":
                continue
            adminPw = ldapParser.getVar(service,"PASS")
            if not adminPw:
                self.printERROR(_("Not found password from service %s")%service)
                flagError = True
                break
            self.clVars.Set("ld_%s_pw"%service, adminPw, True)
        # Наложение профилей
        verbose = False
        if options.has_key("v"):
            verbose = True
        # Флаг почтового релея
        flagMailRelay = False
        if not flagError:
            for service in servInstalled:
                if service == "ldap":
                    continue
                if service == "samba":
                    # Получаем от п�льзователя доверительные сети
                    # для сервиса Samba
                    if options.has_key("a") and\
                        not service in noInputAllowNetServices:
                        self.servSambaObj.clVars = self.clVars
                        if not self.servSambaObj.getAllowNet():
                            flagError = True
                            break
                    # Добавляем файл в директорию share в случае репликации
                    # сервиса Samba
                    sharePath = self.clVars.Get("sr_samba_share_path")
                    # Файл для определения к какому из серверов 
                    # подключился клиент
                    fileReplRun = os.path.join(sharePath,".reprun")
                    # если нет share то создадим
                    if not os.path.exists(sharePath):
                        os.makedirs(sharePath)
                    # Создадим иконку для share
                    fileTxt = "[Desktop Entry]\nIcon=folder-bookmarks"
                    fileDirectory = os.path.join(sharePath,".directory")
                    if not os.path.exists(fileDirectory):
                        uid = 0
                        gid = 0
                        if not self.createUserFile(fileDirectory, fileTxt, uid,
                                                gid):
                            flagError = True
                            break
                    if self.clVars.Get("ld_repl_samba_set") == "on":
                        # Добавляем в share файл .reprun
                        if not self.servSambaObj.addReplFile(self.clVars):
                            flagError = True
                            break
                    else:
                        # Удаляем из share файл .reprun
                        if not self.servSambaObj.delReplFile(self.clVars):
                            flagError = True
                            break
                if service == "mail":
                    # Получаем от пользователя доверительные сети
                    # для сервиса Mail
                    if options.has_key("a") and\
                        not service in noInputAllowNetServices:
                        self.servMailObj.clVars = self.clVars
                        if not self.servMailObj.getAllowNet():
                            flagError = True
                            break
                    # В случае почтового релея
                    if self.clVars.Get("ld_repl_mail_set") == "on" and\
                        self.clVars.Get("sr_mail_relay_set") == "on":
                        flagMailRelay = True
                # Наложение профилей
                if not flagError:
                    if flagMailRelay:
                        files = self.applyProfilesFromService(service, verbose,
                                        ["/etc/dovecot",
                                         "/etc/ssl/dovecot"],
                                        ["/etc/procmailrc",
                                         "/etc/postfix/ldap-aliases-gr.cf",
                                         "/etc/postfix/ldap-aliases.cf",
                                         "/etc/postfix/ldap-recipient-gr.cf",
                                         "/etc/postfix/ldap-recipient.cf"])
                    else:
                        files = self.applyProfilesFromService(service, verbose)
                    if not files:
                        flagError = True
                        break
                    if verbose and type(files) == types.ListType:
                        self.printSUCCESS(_("Updating config from service %s")\
                                %service.capitalize())
                        #self.printSUCCESS(_("Updated files:"))
                        for applyFile in files:
                            self.printWARNING(applyFile)
                    else:
                        self.printOK(_("Updating config from service %s")\
                                %service.capitalize())
                if flagMailRelay:
                    service = "mail_relay"
                if not self.stopServices([service]):
                    flagError = True
                    break
                if not self.startServices([service], False):
                    flagError = True
                    break
                if flagMailRelay:
                    service = "mail"
                self.printOK(_("Restarting service %s")%service.capitalize())
        # Перезапускаем ldap
        if not flagError:
            service = "ldap"
            if not self.restartLdapServer():
                return False
            self.printOK(_("Restarting service %s")%"LDAP")
        if not flagError and serviceUpdate in ["all","jabber"]:
            # Замена имени хоста для сервиса Jabber в LDAP
            if options.has_key("host"):
                if self.clVars.Get("sr_jabber_host") != previousJabberHost:
                    # Установка в LDAP ветке Jabber cервиса нового имени хоста
                    if not self.servJabberObj.setHostName(newHostName,
                                                          previousJabberHost):
                        return False
            # Update jabberID записей в сервисе Unix
            if not self.servJabberObj.updateJabberIdInUnix():
                return False
        if not flagError and serviceUpdate in ["all","unix","samba","mail"]:
            # создаем объект репликации
            objRepl = servRepl()
            # В случае репликации
            if self.clVars.Get("ld_repl_id") and\
                self.clVars.Get("ld_repl_set") == "on":
                # Если не почтовый релей
                if not flagMailRelay:
                    # Добавляем в крон скрипт для чистки директорий
                    if not objRepl.cronReplicationON():
                        return False
                else:
                    # Удаляем из крона скрипт для чистки директорий
                    if not objRepl.cronReplicationOFF():
                        return False
                # Добавляем ветку репликации
                if not objRepl.addReplDN(self.clVars):
                    return False
            else:
                # Удаляем из крона скрипт для чистки директорий
                if not objRepl.cronReplicationOFF():
                    return False
                # Удаляем служебную ветку ldap
                if not objRepl.delSysDN():
                    return False
        # запишем переменные для сервера
        if not flagError:
            # Переменные для jabber
            if "jabber" in servInstalled and serviceUpdate in ["all","jabber"]:
                self.clVars.Write("sr_jabber_history",
                                self.clVars.Get("sr_jabber_history"),
                                True,"local")
                self.clVars.Write("sr_jabber_host",
                                self.clVars.Get("sr_jabber_host"),
                                True,"local")
            # Переменные для почты
            if "mail" in servInstalled and serviceUpdate in ["all","mail"]:
                self.clVars.Write("sr_mail_type",
                                self.clVars.Get("sr_mail_type"),
                                True,"local")
                self.clVars.Write("sr_mail_crypt",
                                self.clVars.Get("sr_mail_crypt"),
                                True,"local")
                self.clVars.Write("sr_mail_net_allow",
                                self.clVars.Get("sr_mail_net_allow"),
                                True,"local")
                #запишем переменные для клиента
                if self.clVars.Get("sr_mail_type") == "all":
                    self.clVars.Set("sr_mail_type","imap")
                clientVars = ["sr_mail_type", "sr_mail_crypt"]
                if not self.saveVarsClient(clientVars):
                    return False
            # Переменные для Samba
            if "samba" in servInstalled and serviceUpdate in ["all","samba"]:
                self.clVars.Write("sr_samba_net_allow",
                                self.clVars.Get("sr_samba_net_allow"),
                                True,"local")
        if flagError:
            return False
        else:
            return True

    def updateLdapServer(self, options, serviceUpdate):
        """Обновление сервисов"""
        return self.updateServer(options ,serviceUpdate)
    
    def scanServiceDirs(self, servicePaths):
        """Сканирует пути сервисов и выдает список файлов от корня"""
        allArchFiles = []
        fileObj = cl_profile._file()
        dirObjs = fileObj.scanDirs(servicePaths)
        i = 0
        for dirObj in dirObjs:
            for fileProfile in dirObj.files:
                archFile = fileProfile.split(servicePaths[i])[1]
                if "?" in archFile:
                    dirName, fileName = os.path.split(archFile)
                    fileName = fileName.split("?")[0]
                    archFile = os.path.join(dirName, fileName)
                allArchFiles.append(archFile)
            i += 1
        return allArchFiles

    def backupServer(self):
        """Сохраняет настройки установленных сервисов и базу LDAP"""
        # создаем директорию backup-а
        if not os.path.exists(self.backupDirectory):
            try:
                os.makedirs(self.backupDirectory)
            except os.IOError:
                self.printERROR(_("Can not create directory") + ": " +\
                                str(self.backupDirectory))
                return False
        # Соединяемся с LDAP
        if not shareLdap.getLdapObjInFile(self):
            return False

        # получаем ldif текст всей базы LDAP
        ldifText = self.fullElementDNtoText()
        if not ldifText:
            self.printERROR(_("LDAP database empty"))
            return False
        replServices = []
        # ldif тексты для сервисов
        ldifTextUnix = ""
        ldifTextMailUnix = ""
        ldifTextSamba = ""
        ldifTextMailSamba = ""
        ldifTextMail = ""
        # В случае включения репликации создаем ldif файлы для сервисов
        if self.clVars.Get("ld_repl_set") == "on":
            if self.clVars.Get("sr_mail_set") == "on" and\
                self.clVars.Get("ld_repl_mail_set") == 'on':
                # получаем ldif текст для сервиса Mail
                ldifTextMail = self.fullElementMailDNtoText()
                if not ldifTextMail:
                    self.printERROR(_("LDAP database empty"))
                    return False
                if not 'mail' in replServices:
                    replServices.append('mail')
            if self.clVars.Get("sr_unix_set") == "on" and\
                self.clVars.Get("ld_repl_unix_set") == 'on':
                # получаем ldif текст для сервиса Unix
                ldifTextUnix = self.fullElementUnixDNtoText()
                if not ldifTextUnix:
                    self.printERROR(_("LDAP database empty"))
                    return False
                replServices.append('unix')
                if self.clVars.Get("sr_mail_set") == "on" and\
                    self.clVars.Get("ld_repl_mail_set") == 'on':
                    # получаем ldif текст для сервиса Mail,Unix
                    ldifTextMailUnix = self.fullElementMailUnixDNtoText()
                    if not ldifTextMailUnix:
                        self.printERROR(_("LDAP database empty"))
                        return False
                    if not 'mail' in replServices:
                        replServices.append('mail')
                if self.clVars.Get("sr_samba_set") == "on" and\
                    self.clVars.Get("ld_repl_samba_set") == 'on':
                    # получаем ldif текст для сервиса Samba
                    ldifTextSamba = self.fullElementSambaDNtoText()
                    if not ldifTextSamba:
                        self.printERROR(_("LDAP database empty"))
                        return False
                    replServices.append('samba')
                    if self.clVars.Get("sr_mail_set") == "on" and\
                        self.clVars.Get("ld_repl_mail_set") == 'on':
                        # получаем ldif текст для сервиса Mail,Samba
                        ldifTextMailSamba = self.fullElementMailSambaDNtoText()
                        if not ldifTextMailSamba:
                            self.printERROR(_("LDAP database empty"))
                            return False
                        if not 'mail' in replServices:
                            replServices.append('mail')
        # генерируем название файла архива
        strData = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
        backupFile = "%s.tar.bz2" %strData
        # если существуют удаляем файлы в /tmp
        self.removeTmpFiles()
        # находим пути к профилям установленных сервисов
        servicePaths, servInstalled = self.getServiceSetupPathProfiles()
        if not servicePaths:
            self.printERROR("unable to create a backup")
            self.printERROR("Services are not installed")
            return False
        # Все файлы которые нужно заархивировать
        allArchFiles = self.scanServiceDirs(servicePaths)
        scanPrivDirs = []

        # файлы в архиве для Unix
        replArchFilesUnix = []
        # сканируемые директории для Unix
        replScanPrivDirsUnix = []

        # файлы в aрхиве для Samba
        replArchFilesSamba = []
        # сканируемые директории для Samba
        replScanPrivDirsSamba = []

        # файлы в aрхиве для Mail
        replArchFilesMail = []
        # сканируемые директории для Mail
        replScanPrivDirsMail = []

        # файлы в aрхиве для Mail, Unix
        replArchFilesMailUnix = []

        # файлы в aрхиве для Mail, Samba
        replArchFilesMailSamba = []

        # В случае включения репликации
        if replServices:
            i = 0
            serviceUnixPaths = []
            serviceSambaPaths = []
            serviceMailPaths = []
            for service in servInstalled:
                if service == "unix":
                    serviceUnixPaths.append(servicePaths[i])
                elif service == "samba":
                    serviceSambaPaths.append(servicePaths[i])
                if service == "mail":
                    serviceMailPaths.append(servicePaths[i])
                i += 1
            # файлы в архиве для Unix
            replArchFilesUnix = self.scanServiceDirs(serviceUnixPaths)
            # файлы в aрхиве для Samba
            replArchFilesSamba = self.scanServiceDirs(serviceSambaPaths)
            # файлы в aрхиве для Mail
            replArchFilesMail = self.scanServiceDirs(serviceMailPaths)
        # Cоздаем файловый объект
        fileObj = cl_profile._file()
        if "ldap" in servInstalled:
            # Получаем путь к ini директории
            ldapParser = iniLdapParser()
            #iniPath = ldapParser.pathIniFile
            #scanPrivDirs.append(iniPath)
            ## Добавляем удаленных пользователей
            #dirDelUsers = self.clVars.Get("sr_deleted_path")
            #if os.path.exists(dirDelUsers):
                #scanPrivDirs.append(dirDelUsers)
            # Добавляем calulate.ldap
            allArchFiles.append(ldapParser.nameIniFile)
            if replServices:
                if "unix" in replServices:
                    replArchFilesUnix.append(ldapParser.nameIniFile)
                if "samba" in replServices:
                    replArchFilesSamba.append(ldapParser.nameIniFile)
                if "mail" in replServices:
                    replArchFilesMail.append(ldapParser.nameIniFile)
            # Добавляем calculate.env 
            iniFiles = self.clVars.Get("cl_env_path")
            if iniFiles and len(iniFiles)>1:
                for iniFile in iniFiles:
                    if os.path.exists(iniFile):
                        allArchFiles.append(iniFile)
                        if replServices:
                            if "unix" in replServices:
                                replArchFilesUnix.append(iniFile)
                            if "samba" in replServices:
                                replArchFilesSamba.append(iniFile)
                            if "mail" in replServices:
                                replArchFilesMail.append(iniFile)
            profileDirs = self.clVars.Get("cl_profile_path")
            if len(profileDirs)>1:
                profileDirs = profileDirs[1:]
                if "samba" in servInstalled:
                    # Добавляем в архивацию профили клиента
                    profileDirs.append('/var/calculate/remote/client-profile')
                for pDir in profileDirs:
                    if os.path.exists(pDir):
                        scanPrivDirs.append(pDir)
                        if replServices:
                            if "unix" in replServices:
                                replScanPrivDirsUnix.append(pDir)
                            if "samba" in replServices:
                                replScanPrivDirsSamba.append(pDir)
                            if "mail" in replServices:
                                replScanPrivDirsMail.append(pDir)
        if "samba" in  servInstalled:
            scanPrivDirs.append(self.sambaPrivate)
            if replServices and "samba" in replServices:
                replScanPrivDirsSamba.append(self.sambaPrivate)
        if "mail" in  servInstalled:
            scanPrivDirs.append(self.mailPrivate)
            # Добавляем в директории сканирования директории сертификатов mail
            scanPrivDirs += self.sslDirsMail
            if replServices and "mail" in replServices:
                replScanPrivDirsMail.append(self.mailPrivate)
                # Добавляем в директории сканирования директории сертификатов
                # mail
                replScanPrivDirsMail += self.sslDirsMail
        # При включении репликации сканируем директории
        if replServices:
            if "samba" in replServices and replScanPrivDirsSamba:
                dirObjs = fileObj.scanDirs(replScanPrivDirsSamba)
                for dirObj in dirObjs:
                    for archFile in dirObj.files:
                        replArchFilesSamba.append(archFile)
            if "unix" in replServices and replScanPrivDirsUnix:
                dirObjs = fileObj.scanDirs(replScanPrivDirsUnix)
                for dirObj in dirObjs:
                    for archFile in dirObj.files:
                        replArchFilesUnix.append(archFile)
            if "mail" in replServices and replScanPrivDirsMail:
                dirObjs = fileObj.scanDirs(replScanPrivDirsMail)
                for dirObj in dirObjs:
                    for archFile in dirObj.files:
                        replArchFilesMail.append(archFile)
        # Сканируем директории
        if scanPrivDirs:
            dirObjs = fileObj.scanDirs(scanPrivDirs)
            for dirObj in dirObjs:
                for archFile in dirObj.files:
                    allArchFiles.append(archFile)
        # Добавляем сертификат jabber
        if "jabber" in  servInstalled:
            allArchFiles.append(self.sslJabberFile)
        if replServices:
            additFiles = []
            if "unix" in replServices:
                # Дополнительные файлы добавляемые в архив
                additFilesUnix = [self.replArchLdifFileUnix,
                                  self.replListFileUnix]
                additFiles = list(set(additFilesUnix)|set(additFiles))
                for additFile in additFilesUnix:
                    replArchFilesUnix.append(additFile)
                replArchFilesUnix = self.unicList(replArchFilesUnix)
                # Удаляем начальный "/"
                replArchFilesUnix = map(lambda x:\
                "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesUnix)
                replArchFilesUnix.sort()
            if "samba" in replServices:
                # Дополнительные файлы добавляемые в архив
                additFilesSamba = [self.replArchLdifFileSamba,
                                   self.replListFileSamba]
                additFiles = list(set(additFilesSamba)|set(additFiles))
                for additFile in additFilesSamba:
                    replArchFilesSamba.append(additFile)
                replArchFilesSamba += replArchFilesUnix
                # Удаляем начальный "/"
                replArchFilesSamba = map(lambda x:\
                "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesSamba)
                replArchFilesSamba = self.unicList(replArchFilesSamba)
                replArchFilesSamba.sort()
            if "mail" in replServices:
                # Дополнительные файлы добавляемые в архив
                additFilesMail = [self.replArchLdifFileMail,
                                  self.replListFileMail]
                additFiles = list(set(additFilesMail)|set(additFiles))
                for additFile in additFilesMail:
                    replArchFilesMail.append(additFile)
                if "unix" in replServices:
                    additFilesMailUnix = [self.replArchLdifFileMailUnix,
                                          self.replListFileMailUnix]
                    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 = self.unicList(replArchFilesMailUnix)
                    replArchFilesMailUnix.sort()
                if "samba" in replServices:
                    additFilesMailSamba = [self.replArchLdifFileMailSamba,
                                          self.replListFileMailSamba]
                    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=self.unicList(replArchFilesMailSamba)
                    replArchFilesMailSamba.sort()
                # Удаляем начальный "/"
                replArchFilesMail = map(lambda x:\
                "/".join(filter(lambda y:y ,x.split("/"))),replArchFilesMail)
                replArchFilesMail = self.unicList(replArchFilesMail)
                replArchFilesMail.sort()
            for additFile in additFiles:
                allArchFiles.append(additFile)
        allArchFiles.append(self.archLdifFile)
        allArchFiles = self.unicList(allArchFiles)

        # В случае репликации сохраняем файлы (список файлов, ldif - файл)
        if replServices:
            if "samba" in replServices:
                if not self.savePrivateFile (self.replListFileSamba,
                                     "\n".join(replArchFilesSamba)):
                    self.printERROR(_("Can not create list archive files")+\
                                    ": " + str(self.replListFileSamba))
                    return False
                if not self.savePrivateFile(self.replArchLdifFileSamba,
                                            ldifTextSamba):
                    self.printERROR(_("Can not create ldif file") + ": " +\
                                    str(self.replArchLdifFileSamba))
                    return False
            if "unix" in replServices:
                if not self.savePrivateFile (self.replListFileUnix,
                                     "\n".join(replArchFilesUnix)):
                    self.printERROR(_("Can not create list archive files")+\
                                    ": " + str(self.replListFileUnix))
                    return False
                if not self.savePrivateFile(self.replArchLdifFileUnix,
                                            ldifTextUnix):
                    self.printERROR(_("Can not create ldif file") + ": " +\
                                    str(self.replArchLdifFileUnix))
                    return False
            if "mail" in replServices:
                # в случае включения репликации для сервисов
                # Mail, Unix
                if set(["mail","unix"]) <= set(replServices):
                    replArchFilesMailUnix = list(\
                                set(replArchFilesMail)|set(replArchFilesUnix)|\
                                set(replArchFilesMailUnix))
                    # Сортируем файлы
                    replArchFilesMailUnix.sort()
                    if not self.savePrivateFile(self.replListFileMailUnix,
                                        "\n".join(replArchFilesMailUnix)):
                        self.printERROR(_("Can not create list archive files")+\
                                      ": " + str(self.replListFileMailUnix))
                        return False
                    if not self.savePrivateFile(self.replArchLdifFileMailUnix,
                                                ldifTextMailUnix):
                        self.printERROR(_("Can not create ldif file") + ": " +\
                                        str(self.replArchLdifFileMailUnix))
                        return False
                # в случае включения репликации для сервисов
                # Mail, Samba
                if set(["mail","samba"]) <= set(replServices):
                    replArchFilesMailSamba = list(\
                    set(replArchFilesMail)|set(replArchFilesSamba)|\
                    set(replArchFilesMailSamba))
                    # Сортируем файлы
                    replArchFilesMailSamba.sort()
                    if not self.savePrivateFile(self.replListFileMailSamba,
                                        "\n".join(replArchFilesMailSamba)):
                        self.printERROR(_("Can not create list archive files")+\
                                      ": " + str(self.replListFileMailSamba))
                        return False
                    if not self.savePrivateFile(self.replArchLdifFileMailSamba,
                                                ldifTextMailSamba):
                        self.printERROR(_("Can not create ldif file") + ": " +\
                                        str(self.replArchLdifFileMailSamba))
                        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)))
                if not self.savePrivateFile (self.replListFileMail,
                                     "\n".join(replArchFilesMail)):
                    self.printERROR(_("Can not create list archive files")+\
                                    ": " + str(self.replListFileMail))
                    return False
                if not self.savePrivateFile(self.replArchLdifFileMail,
                                            ldifTextMail):
                    self.printERROR(_("Can not create ldif file") + ": " +\
                                    str(self.archLdifFileMail))
                    return False

        #Сохраняемые файлы в случае почтового релея
        if self.clVars.Get("sr_mail_set") == "on" and\
            self.clVars.Get("ld_repl_mail_set") == 'on' and\
            self.clVars.Get("sr_mail_relay_set") == "on":
            dirsFilter = ["/etc/dovecot",
                          "/etc/ssl/dovecot"]
            filesFilter = ["/etc/procmailrc",
                           "/etc/postfix/ldap-aliases-gr.cf",
                           "/etc/postfix/ldap-aliases.cf",
                           "/etc/postfix/ldap-recipient-gr.cf",
                           "/etc/postfix/ldap-recipient.cf"]
            files = []
            for fileName in allArchFiles:
                dirName, fileN = os.path.split(fileName)
                if not dirName in dirsFilter and\
                    not fileName in filesFilter:
                    files.append(fileName)
            allArchFiles = files

        # Сохраняем файл список архивируемых файлов 
        if not self.savePrivateFile (self.tmpListFile,
                                     "\n".join(allArchFiles)):
            self.printERROR(_("Can not create list archive files") + ": " +\
                            str(self.tmpListFile))
            return False
        # Сохраняем ldif-файл базы LDAP
        if not self.savePrivateFile(self.archLdifFile, ldifText):
            self.printERROR(_("Can not create ldif file") + ": " +\
                            str(self.archLdifFile))
            return False
        bFile = os.path.join(self.backupDirectory, backupFile)
        self.execProg("tar --files-from=%s -cjf %s"\
                        %(self.tmpListFile, bFile))
        # если существуют удаляем файлы в /tmp
        self.removeTmpFiles()
        if os.path.exists(bFile):
            os.chmod(bFile,0600)
            self.printSUCCESS(_("Created archive file") + ": " +\
                                str(bFile))
            return True
        else:
            self.printERROR(_("Can not create archive file") + ": " +\
                                str(bFile))
            return False

    def backupLdapServer(self, options):
        if not options or (options and options.has_key("b")):
            return self.backupServer()
        if options.has_key("r"):
            return self.restoreServer()

    def startAllSetupServices(self):
        """Запускаем все работающие установленные сервисы

        а также прописываем в автозапуск
        """
        # находим установленные сервисы
        servInstalled = self.getServiceSetup()
        # Если почтовый релей  и установлен только Mail сервис то
        # заменяем 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) +\
                ["mail_relay"]
        return self.startServices(servInstalled)

    def getArchFile(self):
        """Возвращает имя архивного файла из директории backup
        """
        if not os.path.exists(self.backupDirectory):
            self.printERROR(_("Path for backup is not found") + ": " +\
                            str(self.backupDirectory))
            return False
        # Получаем номер архивного файла
        archFiles = os.listdir(self.backupDirectory)
        maxFileNumber = 0
        for archFile in archFiles:
            numbTxt = archFile.split(".")[0]
            try:
                numb = int(numbTxt)
            except:
                continue
            if maxFileNumber<numb:
                maxFileNumber = numb
        if not maxFileNumber:
            self.printERROR(_("Backup file is not found") + " ...")
            return False
        archFile = str(maxFileNumber) + ".tar.bz2"
        # Название файла с архивом
        bFile = os.path.join(self.backupDirectory, archFile)
        if not os.path.exists(bFile):
            self.printERROR(_("Backup file is not found") + ": " +\
                            str(bFile))
            return False
        return bFile

    def getArchReplServices(self):
        """Получаем сервис который нужно реплицировать из архивного файла"""
        bFile = self.getArchFile()
        if not bFile:
            return False
        # Получаем список файлов в архиве
        textListFiles = self.execProg("tar -tjf %s" %bFile,False,False)
        # �даляем из элементов переводы строк
        archFiles = map(lambda x: "".join(x.split('\n')),textListFiles)
        flagError = False
        # Находим в списке файлов файлы списки для сервисов
        listReplFiles = list(set([self.replListFileSamba[1:],
                                     self.replListFileUnix[1:],
                                     self.replListFileMail[1:],
                                     self.replListFileMailUnix[1:],
                                     self.replListFileMailSamba[1:]]) &\
                                     set(archFiles))
        if not listReplFiles:
            self.printERROR(_("Inside the archive %s no files \
for running replication")%bFile)
            return False
        # Находим в списке файлов env файлы и проверяем результат
        envFiles = []
        for archFile in archFiles:
            if not "/" in archFile:
                flagError = True
                break
            if len(archFile)>3 and archFile[-4:] == ".env":
                envFiles.append(archFile)
        if not envFiles:
            self.printERROR(_("Inside the archive %s no files with \
the extension '.env'")%bFile)
            return False
        if flagError:
            self.printERROR(_("Can not list the contents of an archive") +\
                              ": " + str(bFile))
            return False
        # Удаляем временные файлы
        self.removeTmpFiles()
        # Сохраняем файл - список извлекаемых файлов 
        if not self.savePrivateFile (self.tmpListFile,
                                    "\n".join(envFiles)):
            self.printERROR(_("Can not create list extract files") + ": " +\
                            str(self.tmpListFile))
            return False
        # Cоздаем временную директорию
        try:
            os.makedirs(self.tmpEnvDir)
        except os.IOError:
            self.printERROR(_("Can not create directory") + ": " +\
                            str(self.tmpEnvDir))
            return False
        # Разархивируем env файлы во временную директорию
        if not (self.execProg("tar -C %s --files-from=%s -xjf %s"\
            %(self.tmpEnvDir,self.tmpListFile, bFile)) == None):
            self.printERROR(_("Can not extract archive") + ": " + str(bFile))
            return False
        # Создаем объект переменных clVars
        self.clVars = cl_base.DataVars()
        self.clVars.flServer()
        #Записываем новые пути к env в переменную
        envPaths = []
        for path in envFiles:
            envPaths.append(os.path.join(self.tmpEnvDir,path))
        self.clVars.Set("cl_env_path", envPaths, True)
        # считаем переменные из ini файлов
        self.clVars.flIniFile()
        servicePaths, servInstalled = self.getServiceSetupPathProfiles()
        if not servicePaths:
            self.printERROR("Services are not installed in archive %s" %bFile)
            return False 
        # Найдем сервисы которые нужно установить
        replSambaServers = self.clVars.Get("ld_repl_samba_servers")
        if replSambaServers:
            replSambaServers = replSambaServers.split(",")
        replUnixServers = self.clVars.Get("ld_repl_unix_servers")
        if replUnixServers:
            replUnixServers = replUnixServers.split(",")
        replMailServers = self.clVars.Get("ld_repl_mail_servers")
        if replMailServers:
            replMailServers = replMailServers.split(",")
        hostName = self.clVars.Get('os_net_hostname')
        domain = self.clVars.Get('os_net_domain')
        services = []
        # Найден ли в списке серверов репликации текущий сервер
        flagFoundReplServer = False
        fullHostName = "%s.%s"%(hostName,domain)
        if not fullHostName in replSambaServers:
            if fullHostName in replUnixServers:
                flagFoundReplServer = True
                if self.replListFileUnix[1:] in listReplFiles:
                    services = ["unix"]
                    if fullHostName in replMailServers:
                        if self.replListFileMailUnix[1:] in listReplFiles:
                            services = ["unix", "mail"]
        else:
            flagFoundReplServer = True
            if self.replListFileSamba[1:] in listReplFiles:
                services = ["unix", "samba"]
                if fullHostName in replMailServers:
                    if self.replListFileMailSamba[1:] in listReplFiles:
                        services = ["unix", "samba", "mail"]
        if not services and fullHostName in replMailServers:
            flagFoundReplServer = True
            if self.replListFileMail[1:] in listReplFiles:
                services = ["mail"]
        # Удаляем временные файлы
        self.removeTmpFiles()
        if flagFoundReplServer:
            if not services:
                self.printERROR(_("Inside the archive %s no files \
for running replication")%bFile)
                return False
        else:
            self.printERROR(\
        _("Not found this replication server %s in backup file")%fullHostName+\
        " ...")
            return False
        return services

    def restoreServer(self, startServices=True, replServices=False):
        """Восстанавливает из архива все установленные сервисы

        Восстановленные сервисы будут запущены
        """
        bFile = self.getArchFile()
        if not bFile:
            return False
        # Создаем объект переменных clVars
        self.createClVars()
        # останавливаем сервисы
        if not self.stopServices(self.getALLServices()):
            return False
        # Удаляем старую базу данных
        self.removeLdapDatabase()
        # Накладываем профили (берем из папки backup)
        if not self.applyProfilesFromService(self.backupDir):
            self.printERROR(_("Can not apply profile")+ ": backup")
            return False
        # Запускаем LDAP сервер
        if not self.runLdapServer():
            return False
        # Соединяемся с LDAP временным пользователем
        if not self.connectLdapServer():
            return False
        # Cписок разахивированных файлов (файл ldif)
        allArchFiles = [self.archLdifFile[1:]]
        if replServices:
            if set(["samba", "mail"]) <= set(replServices):
                allArchFiles = [self.replArchLdifFileMailSamba,
                                self.replListFileMailSamba]
            elif set(["unix", "mail"]) <= set(replServices):
                allArchFiles = [self.replArchLdifFileMailUnix,
                                self.replListFileMailUnix]
            elif "samba" in replServices:
                allArchFiles = [self.replArchLdifFileSamba,
                                self.replListFileSamba]
            elif "unix" in replServices:
                allArchFiles = [self.replArchLdifFileUnix,
                                self.replListFileUnix]
            elif "mail" in replServices:
                allArchFiles = [self.replArchLdifFileMail,
                                self.replListFileMail]
            # Удаляем начальный '/'
            allArchFiles = map(lambda x:\
                "/".join(filter(lambda y:y ,x.split("/"))),allArchFiles)
        # Удаляем временные файлы
        self.removeTmpFiles()
        # Сохраняем файл - список извлекаемых файлов (файл ldif)
        if not self.savePrivateFile (self.tmpListFile,
                                    "\n".join(allArchFiles)):
            self.printERROR(_("Can not create list extract files") + ": " +\
                            str(self.tmpListFile))
            return False
        # Распаковываем ldif файл
        ldifFile = self.archLdifFile
        if replServices:
            if set(["samba", "mail"]) <= set(replServices):
                ldifFile = self.replArchLdifFileMailSamba
            elif set(["unix", "mail"]) <= set(replServices):
                ldifFile = self.replArchLdifFileMailUnix
            elif "samba" in replServices:
                ldifFile = self.replArchLdifFileSamba
            elif "unix" in replServices:
                ldifFile = self.replArchLdifFileUnix
            elif "mail" in replServices:
                ldifFile = self.replArchLdifFileMail
        if not (self.execProg("tar -C / --files-from=%s -xjf %s"\
            %(self.tmpListFile, bFile)) == None):
            self.printERROR(_("Can not extract archive") + ": " + str(bFile))
            return False
        if not os.path.exists(ldifFile):
            self.printERROR(_("Ldif file is not found") + " :" +\
                            str(ldifFile))
            return False
        # Читаем ldif файл
        FD = open (ldifFile, "r")
        ldif = FD.read()
        FD.close()
        # Добавляем в базу из ldif
        self.ldapObj.ldapAdd(ldif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
         # Останавливаем LDAP сервер
        if not self.stopLdapServer():
            return False
        # Удаляем временные файлы нужные для установки сервисов
        self.removeTmpRestoreFile()
        if replServices:
            # Файл - список разархивируемых файлов
            listReplFile = ""
            if set(["samba", "mail"]) <= set(replServices):
                listReplFile = self.replListFileMailSamba
            elif set(["unix", "mail"]) <= set(replServices):
                listReplFile = self.replListFileMailUnix
            elif "samba" in replServices:
                listReplFile = self.replListFileSamba
            elif "unix" in replServices:
                listReplFile = self.replListFileUnix
            elif "mail" in replServices:
                listReplFile = self.replListFileMail
            else:
                self.printError(_("Not supported replication service %s")\
                                %replServices[0])
                return False
            if not (self.execProg("tar -C / --files-from=%s -xjf %s"\
                %(listReplFile, bFile)) == None):
                self.printERROR(_("Can not extract archive") + ": "+str(bFile))
                return False
        else:
            # Распаковываем целиком архив
            if not (self.execProg("tar -C / -xjf %s"\
                %(bFile)) == None):
                self.printERROR(_("Can not extract archive") + ": "+str(bFile))
                return False
        # Удаляем временные файлы
        self.removeTmpFiles()
        # считаем переменные из ini файлов
        self.clVars.flIniFile()
        if startServices:
            # Стартуем все сервисы и прописываем в автозагрузку
            if not self.startAllSetupServices():
                return False
            self.printOK(_("Restored all installed services") + " ...")
        if replServices:
                self.printOK(_("Replication on, for services (%s)")\
                %", ".join(replServices) + " ...")
        return True

    def removeTmpFiles(self):
        """Удаляем временные файлы"""
        removeFiles=[self.tmpListFile,self.archLdifFile,
                     self.replArchLdifFileUnix,self.replListFileUnix,
                     self.replArchLdifFileSamba,self.replListFileSamba,
                     self.replArchLdifFileMail,self.replListFileMail,
                     self.replArchLdifFileMailSamba,self.replListFileMailSamba,
                     self.replArchLdifFileMailUnix,self.replListFileMailUnix]
        for rmFile in removeFiles:
            if os.path.exists(rmFile):
                os.remove(rmFile)
        if os.path.exists(self.tmpEnvDir):
            self.removeDir(self.tmpEnvDir)

    def __del__(self):
        """Удаляем временные файлы"""
        self.removeTmpFiles()

    def removeTmpRestoreFile(self):
        """Удаляем временные файлы нужные для восстановления сервисов"""
        profilePath = self.clVars.Get("cl_profile_path")[0]
        backupDir = os.path.join(profilePath, self.backupDir)
        fileObj = cl_profile._file()
        scanObjs = fileObj.scanDirs([backupDir])
        if not scanObjs:
                return True
        #удаляем файлы
        for fileRemove in scanObjs[0].files:
            rmFile = fileRemove.split(backupDir)[1]
            if os.path.exists(rmFile):
                os.remove(rmFile)
        #удаляем ссылки
        for linkRemove in scanObjs[0].links:
            rmLink = flinkRemove.split(backupDir)[1]
            if os.path.exists(rmLink):
                os.unlink(rmLink)
        return True

    def removeLdapDatabase(self):
        """Удаляем предыдущую базу данных"""
        self.execProg("rm -rf /var/lib/openldap-data/*")
        self.printOK(_("Erased LDAP Database") + " ...")
        return True

    def connectLdapServer(self):
        """Соединяемся с LDAP сервером

         используем DN и пароль временного админстратора
         """
        self.ldapObj = ldapFunction(self.clVars.Get("ld_temp_dn"),
                               self.clVars.Get("ld_temp_pw"))
        self.conLdap = self.ldapObj.conLdap
        if self.ldapObj.getError():
            self.printERROR(_("Can not connected to LDAP server") + " ...")
            return False
        return True


    def setupLdapServer(self, options):
        """Начальная настройка LDAP сервиса"""
        # Принудительная установка
        forceOptions = False
        self.createClVars()
        if options.has_key("f"):
            forceOptions = True
        if self.clVars.Get("sr_ldap_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
            _("LDAP server is configured")+ ".")
            return True
        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы и база данных сервиса LDAP а также
            # конфигурационные файлы установленных сервисов
            self.printWARNING (_("WARNING") + ": " +\
                _("Executing of the program will change") + " " +\
                _("the configuration files and database of LDAP service")+\
                ".")
            # если вы �отовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program")+", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
        else:
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            self.backupServer()
        # останавливаем сервисы
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("slapd"):
            return False
        # Останавливаем все установленные сервисы
        if not self.stopServices(self.getALLServices()):
            return False
        # Удаляем из автозагрузки все установленные сервисы
        if not self.delServicesAutostart(self.getALLServices()):
            return False
        # Удаляем из крона скрипт для чистки удаленых пользователей
        # создаем объект репликации
        objRepl = servRepl()
        if not objRepl.cronReplicationOFF():
            return False
        # Удаляем из share файл .replrun
        if not self.servSambaObj.delReplFile(self.clVars):
            return False
        # Получим пути к ini файлам
        iniFiles = self.clVars.Get("cl_env_path")
        # Удаляем все ini файлы
        for iniFile in iniFiles:
            if os.path.exists(iniFile):
                os.remove(iniFile)
        # Получим путь к ldap файлу
        ldapParser = iniLdapParser()
        ldapFile = ldapParser.nameIniFile
        # Удаляем ldap файл
        if os.path.exists(ldapFile):
            os.remove(ldapFile)
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","ldap")
        self.clVars.Write("sr_ldap_set","off")
        # Первый проход
        self.clVars.Set("cl_pass_step","1",True)
        if not self.applyProfilesFromService('ldap'):
            self.printERROR(_("Can not apply profiles") +":"+ _("first pass"))
            return False
        # Удаляем старую базу данных
        self.removeLdapDatabase()
        # Запускаем LDAP сервер
        if not self.runLdapServer():
            return False
        # Соединяемся с LDAP временным пользователем
        if not self.connectLdapServer():
            return False
        # Получаем текст нужного ldif-a
        baseLdif = self.createLdif(self.ldifFileBase)
        # Если нет ошибок при соединении применяем ldif
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        self.printOK(_("Added ldif file") +" ...")
        # Второй проход,
        # удаляем временного пользователя root из конфигурационного файла
        self.clVars.Set("cl_pass_step","2",True)
        if not self.applyProfilesFromService('ldap'):
            self.printERROR(_("Can not apply profiles") +":"+ _("second pass"))
            return False
        # Перезапускаем LDAP сервер
        if not self.restartLdapServer():
            return False
        # Записываем данные администратора сервера
        ldapParser.setVar("admin",
            {"DN":self.clVars.Get("ld_admin_dn"),
             "PASS":self.clVars.Get("ld_admin_pw")})
        # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("slapd"):
            return False
        # Записываем переменные для пользователя
        clientVars = ["ur_organization", "ur_signature"]
        if not self.saveVarsClient(clientVars):
            return False
        self.clVars.Write("sr_ldap_set","on")
        self.printOK(_("LDAP service configured") + " ...")
        return True

class cl_ldap(shareLdap):
    """Основной класс для работы с LDAP"""
    def __init__(self, cmdName):
        shareLdap.__init__(self)

        # объект для форматированного вывода
        imp_cl_help.__init__(self, cmdName)

        servName = ""
        if "user" in cmdName:
            servName = _("user")
        elif "group" in cmdName:
            servName = _("group")
        elif "setup" in cmdName:
            servName = _("service")
        elif "update" in cmdName:
            servName = _("service")

        self.chapter = [\
            # расположение разделов на странице
            # имя раздела, видимый или невидимый, кол. "\n" после
            # названия раздела, кол. "\n" после раздела
            # тип раздела
            ("Copyright",False,0,2,""),
            (_("Usage"),True,0,1,""),
            ("Function",False,0,2,""),
            (_("Examples"),True,1,1,""),
            (_("Common options"),True,1,1,"options"),
            (_("LDAP service options"),True,1,1,"options"),
            (_("Unix service options"),True,1,1,"options"),
            (_("Samba service options"),True,1,1,"options"),
            (_("Mail service options"),True,1,1,"options"),
            (_("Jabber service options"),True,1,1,"options"),
            (_("FTP service options"),True,1,1,"options"),
            (_("Services"),True,1,0,"")
        ]

        # имена используемых программ и их номера для доступа к переменным
        # self.data
        self.progName = { 'cl-groupadd':0,
                          'cl-groupdel':1,
                          'cl-groupmod':2,
                          'cl-useradd':3,
                          'cl-userdel':4,
                          'cl-usermod':5,
                          'cl-setup':6,
                          'cl-passwd':7,
                          'cl-backup':8,
                          'cl-update':9,
                          'cl-rebuild':10,
                          'repldap':11,
                          'cl-replication':12,
                          'replcron':13,
                          'cl-info':14,
                        }
        # Cвязь сервисов и действующих опций
        self.relServices = {"samba":[_("Common options"),
                                      _("Samba service options")],
                            "ldap":[_("Common options"),
                                      _("LDAP service options")],
                            "unix":[_("Common options"),
                                      _("Unix service options")],
                            "mail":[_("Common options"),
                                      _("Mail service options")],
                            "jabber":[_("Common options"),
                                      _("Jabber service options")],
                            "ftp":[_("Common options"),
                                      _("FTP service options")],
                            }
        # Cвязь длинных опций помощи и выводимых разделов помощи с опциями
        self.relOptions = {"h":[_("Common options")],
                            "help-ldap":[_("Common options"),
                                         _("LDAP service options")],
                            "help-unix":[_("Common options"),
                                         _("Unix service options")],
                            "help-samba":[_("Common options"),
                                          _("Samba service options")],
                            "help-mail": [_("Common options"),
                                          _("Mail service options")],
                            "help-jabber":[_("Common options"),
                                           _("Jabber service options")],
                            "help-ftp":[_("Common options"),
                                           _("FTP service options")],
                            "help-all":[_("Common options"),
                                        _("Samba service options"),
                                        _("LDAP service options"),
                                        _("Unix service options"),
                                        _("Mail service options"),
                                        _("Jabber service options"),
                                        _("FTP service options")
                                      ]
                            }

        # список разделов, которые на наличие в ней информации
        # используется для автоматического отображения/скрытия
        # опций help-имя
        # Пример: self.relOption =
        #      { "help-all":[_("Common options"], _("Unix service options"),
        #             _("Samba service options"), _("LDAP service options")}]
        # self.relChapterPass = (_("Common options"),)
        # это означается что опция будет активна, если только в разделах
        # кроме Common options есть хоть одна доступная опция.
        self.relChapterPass = (_("Common options"),)

        self.data = [\
        # Options
        {'shortOption':"h",
         'longOption':"help",
         'helpChapter':_("Common options"),
         'help':_("display this help and exit")
        },
        {'longOption':"help-all",
         'helpChapter':_("Common options"),
         'help':_("display help for all services options")
        },
        {'longOption':"help-jabber",
         'helpChapter':_("Common options"),
         'help':_("display help for Jabber service options")
        },
        {'progAccess':(6,),
        'longOption':"help-ldap",
         'helpChapter':_("Common options"),
         'help':_("display help for LDAP service options")
        },
        {'longOption':"help-mail",
         'helpChapter':_("Common options"),
         'help':_("display help for Mail service options")
        },
        {'longOption':"help-samba",
         'helpChapter':_("Common options"),
         'help':_("display help for Samba service options")
        },
        {'longOption':"help-unix",
         'helpChapter':_("Common options"),
         'help':_("display help for Unix service options")
        },
        {'longOption':"help-ftp",
         'helpChapter':_("Common options"),
         'help':_("display help for FTP service options")
        },
        {'progAccess':(0,),
         'shortOption':"f",
         'longOption':"force",
         'helpChapter':_("Unix service options"),
         'help':_("does not check system group")
        },
        {'progAccess':(0,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GID",
         'helpChapter':_("Unix service options"),
         'help':_("use GID for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Unix service options"),
         'help':_("set the description field for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Mail service options"),
         'help':_("set the description field for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Jabber service options"),
         'help':_("set the description field for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"p",
         'helpChapter':_("Unix service options"),
         'help':_("print the gidNumber to stdout")
        },
        {'progAccess':(0,),
         'shortOption':"e",
         'longOption':"alt-emails",
         'optVal':"ALT_EMAILS",
         'helpChapter':_("Mail service options"),
         'help':_("set alternate email addresses for the new mail group")
        },
        {'progAccess':(0,),
         'longOption':"hide",
         'optVal':"HIDE_HOSTS",
         'helpChapter':_("Mail service options"),
         'help':_("host names mail servers who have no access to emails \
to this group (comma delimited)")
        },
        {'progAccess':(0,),
         'shortOption':"f",
         'longOption':"force",
         'helpChapter':_("Samba service options"),
         'help':_("does not check system group")
        },
        {'progAccess':(0,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GID",
         'helpChapter':_("Samba service options"),
         'help':_("use GID for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Samba service options"),
         'help':_("set the description field for the new group")
        },
        {'progAccess':(0,),
         'shortOption':"p",
         'helpChapter':_("Samba service options"),
         'help':_("print the gidNumber to stdout")
        },

        {'progAccess':(2,),
         'shortOption':"a",
         'longOption':"add",
         'optVal':"USERS",
         'helpChapter':_("Common options"),
         'help':_("add members (comma delimited)")
        },
        {'progAccess':(2,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Common options"),
         'help':_("set the description field for the new group")
        },
        {'progAccess':(2,),
         'shortOption':"d",
         'longOption':"delete",
         'optVal':"USERS",
         'helpChapter':_("Common options"),
         'help':_("delete members (comma delimted)")
        },
        {'progAccess':(2,),
         'shortOption':"n",
         'longOption':"new-name",
         'optVal':"NEW_GROUP",
         'helpChapter':_("Common options"),
         'help':_("force use NEW_GROUP name by GROUP")
        },
        {'progAccess':(2,),
         'shortOption':"e",
         'longOption':"alt-emails",
         'optVal':"ALT_EMAILS",
         'helpChapter':_("Mail service options"),
         'help':_("set alternate email addresses for the mail group")
        },
        {'progAccess':(2,),
         'longOption':"hide",
         'optVal':"HIDE_HOSTS",
         'helpChapter':_("Mail service options"),
         'help':_("host names mail servers who have no access to emails \
to this group (comma delimited)")
        },
         {'progAccess':(2,),
         'longOption':"hide-off",
         'helpChapter':_("Mail service options"),
         'help':_("clear host names mail servers who have no access to emails \
to this group")
        },
        {'progAccess':(3,),
         'shortOption':"b",
         'longOption':"base-dir",
         'optVal':"BASE_DIR",
         'helpChapter':_("Unix service options"),
         'help':_("base directory for the new user account home directory")
        },
        {'progAccess':(3,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Unix service options"),
         'help':_("set the COMMENT field for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("FTP service options"),
         'help':_("set the COMMENT field for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Samba service options"),
         'help':_("set the COMMENT field for the new unix account")
        },
        {'progAccess':(3,),
         'shortOption':"e",
         'longOption':"alt-emails",
         'optVal':"ALT_EMAILS",
         'helpChapter':_("Mail service options"),
         'help':_("set alternate email addresses for the new mail account")
        },
        {'progAccess':(3,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Mail service options"),
         'help':_("set the COMMENT field for the new account")
        },
        {'progAccess':(3,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Jabber service options"),
         'help':_("set the COMMENT field for the new account")
        },
        {'progAccess':(3,),
         'shortOption':"i",
         'longOption':"image",
         'optVal':"IMAGE",
         'helpChapter':_("Jabber service options"),
         'help':_("set the jpeg image photo for the new account (file)")
        },
        #{'progAccess':(3,),
         #'shortOption':"i",
         #'longOption':"image",
         #'optVal':"IMAGE",
         #'helpChapter':_("Unix service options"),
         #'help':_("set the jpeg image photo for the new account (file)")
        #},
        {'progAccess':(3,),
         'shortOption':"d",
         'longOption':"home-dir",
         'optVal':"HOME_DIR",
         'helpChapter':_("Unix service options"),
         'help':_("home directory for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"d",
         'longOption':"ftp-dir",
         'optVal':"FTP_DIR",
         'helpChapter':_("FTP service options"),
         'help':_("ftp relative directory for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GROUP",
         'helpChapter':_("Samba service options"),
         'help':_("force use GROUP for the new user Unix service account")
        },
        {'progAccess':(3,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GROUP",
         'helpChapter':_("FTP service options"),
         'help':_("force use GROUP for the new user Unix service account")
        },
        {'progAccess':(3,),
         'shortOption':"u",
         'longOption':"uid",
         'optVal':"UID",
         'helpChapter':_("Samba service options"),
         'help':_("force use UID for the new user Unix service account")
        },
        {'progAccess':(3,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GROUP",
         'helpChapter':_("Mail service options"),
         'help':_("force use GROUP for the new user Unix service account")
        },
        {'progAccess':(3,),
         'shortOption':"j",
         'longOption':"jid",
         'optVal':"JID",
         'helpChapter':_("Jabber service options"),
         'help':_("force use JID for the new user Jabber service account")
        },
        {'progAccess':(3,),
         'shortOption':"g",
         'longOption':"gid",
         'optVal':"GROUP",
         'helpChapter':_("Unix service options"),
         'help':_("force use GROUP for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"G",
         'longOption':"groups",
         'optVal':"GROUPS",
         'helpChapter':_("Unix service options"),
         'help':_("list of supplementary groups for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"G",
         'longOption':"groups",
         'optVal':"GROUPS",
         'helpChapter':_("Samba service options"),
         'help':_("list of supplementary groups for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"k",
         'longOption':"skel",
         'optVal':"SKEL_DIR",
         'helpChapter':_("Unix service options"),
         'help':_("specify an alternative skel directory")
        },
        {'progAccess':(3,),
         'shortOption':"m",
         'longOption':"create-home",
         'helpChapter':_("Unix service options"),
         'help':_("create home directory for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"m",
         'longOption':"create-ftp",
         'helpChapter':_("FTP service options"),
         'help':_("create ftp directory for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("Unix service options"),
         'help':_("use password for the user account") +\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"P",
         'helpChapter':_("Unix service options"),
         'help':_("use password for the user account") +\
                 " (" + _("from standard input") + ")"
        },
        #{'progAccess':(3,),
         #'shortOption':"f",
         #'longOption':"force",
         #'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,),
         'shortOption':"n",
         'longOption':"create-profile",
         'helpChapter':_("Samba service options"),
         'help':_("create a directories for storing new user account \
preferences and data (for users with uid<1000)")
        },
        {'progAccess':(3,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("Samba service options"),
         'help':_("use password for the user account") +\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"P",
         'helpChapter':_("Samba service options"),
         'help':_("use password for the user account") +\
                 " (" + _("from standard input") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("Mail service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"P",
         'helpChapter':_("Mail service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from standard input") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("Jabber service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"P",
         'helpChapter':_("Jabber service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from standard input") + ")"
        },
         {'progAccess':(3,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("FTP service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"P",
         'helpChapter':_("FTP service options"),
         'help':_("use password for the user account")+\
                 " (" + _("from standard input") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"w",
         'helpChapter':_("Samba service options"),
         'help':_("set the trust account")+\
                 " (" + _("Windows Workstations") + ")"
        },
        {'progAccess':(3,),
         'shortOption':"s",
         'longOption':"shell",
         'optVal':"SHELL",
         'helpChapter':_("Unix service options"),
         'help':_("the login shell for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"u",
         'longOption':"uid",
         'optVal':"UID",
         'helpChapter':_("Unix service options"),
         'help':_("force use the UID for the new user account")
        },
        {'progAccess':(3,),
         'shortOption':"v",
         'longOption':"visible",
         'helpChapter':_("Unix service options"),
         'help':_("the new user account is visible (default - invisible)")
        },
        {'progAccess':(4,),
         'shortOption':"r",
         'longOption':"remove",
         'helpChapter':_("Unix service options"),
         'help':_("not create backup deleted user data")
        },
        {'progAccess':(4,),
         'shortOption':"r",
         'longOption':"remove",
         'helpChapter':_("Samba service options"),
         'help':_("not create backup deleted user data")
        },
        {'progAccess':(4,),
         'shortOption':"r",
         'longOption':"remove",
         'helpChapter':_("Mail service options"),
         'help':_("not create backup deleted user data")
        },
        {'progAccess':(5,),
         'shortOption':"G",
         'longOption':"groups",
         'optVal':"GROUPS",
         'helpChapter':_("Samba service options"),
         'help':_("new list of supplementary GROUPS (used Unix groups)")
        },
        {'progAccess':(5,),
         'shortOption':"s",
         'longOption':"smb",
         'helpChapter':_("Samba service options"),
         'help':_("used in conjunction with the option '-p', \
the password will be changed only for Samba account")
        },
        {'progAccess':(5,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Unix service options"),
         'help':_("new value of the COMMENT field")
        },
        {'progAccess':(5,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Mail service options"),
         'help':_("new value of the COMMENT field")
        },
        {'progAccess':(5,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("Jabber service options"),
         'help':_("new value of the COMMENT field (full name user)")
        },
         {'progAccess':(5,),
         'shortOption':"c",
         'longOption':"comment",
         'optVal':"COMMENT",
         'helpChapter':_("FTP service options"),
         'help':_("new value of the COMMENT field (full name user)")
        },
        {'progAccess':(5,),
         'shortOption':"e",
         'longOption':"alt-emails",
         'optVal':"ALT_EMAILS",
         'helpChapter':_("Mail service options"),
         'help':_("set alternate email addresses for the mail account")
        },
        {'progAccess':(5,),
         'shortOption':"d",
         'longOption':"home",
         'optVal':"HOME_DIR",
         'helpChapter':_("Unix service options"),
         'help':_("new home directory for the user account")
        },
        {'progAccess':(5,),
        'shortOption':"g",
        'longOption':"gid",
        'optVal':"GROUP",
        'helpChapter':_("Unix service options"),
        'help':_("force use GROUP as new primary group")
        },
        {'progAccess':(5,),
        'shortOption':"g",
        'longOption':"group",
        'optVal':"GROUP",
        'helpChapter':_("Jabber service options"),
        'help':_("force use GROUP as new Jabber group")
        },
        {'progAccess':(5,),
         'shortOption':"j",
         'longOption':"jid",
         'optVal':"JID",
         'helpChapter':_("Jabber service options"),
         'help':_("force use JID for the user Jabber service account")
        },
        {'progAccess':(5,),
         'shortOption':"G",
         'longOption':"groups",
         'optVal':"GROUPS",
         'helpChapter':_("Unix service options"),
         'help':_("new list of supplementary GROUPS")
        },
        {'progAccess':(5,),
         'shortOption':"i",
         'longOption':"image",
         'optVal':"IMAGE",
         'helpChapter':_("Jabber service options"),
         'help':_("set the jpeg image photo for user (file)")
        },
        {'progAccess':(5,),
         'shortOption':"G",
         'longOption':"groups",
         'optVal':"GROUPS",
         'helpChapter':_("Mail service options"),
         'help':_("new list of supplementary email GROUPS")
        },
        {'progAccess':(5,),
         'shortOption':"a",
         'longOption':"append",
         'optVal':"GROUPS",
         'helpChapter':_("Unix service options"),
         'help':_("append the user to the supplemental GROUPS")
        },
        {'progAccess':(5,),
         'shortOption':"a",
         'longOption':"append",
         'optVal':"GROUPS",
         'helpChapter':_("Mail service options"),
         'help':_("append the user to the supplemental email GROUPS")
        },
        {'progAccess':(5,),
         'shortOption':"m",
         'longOption':"move-home",
         'helpChapter':_("Unix service options"),
         'help':_("move contents of the home directory to the new location")+\
                " (" + _("use only with") + " -d)"
        },
        {'progAccess':(5,),
         'shortOption':"p",
         'longOption':"password",
         'helpChapter':_("Common options"),
         'help':_("new password for the user account")+\
                 " (" + _("from dialog") + ")"
        },
        {'progAccess':(5,),
         'shortOption':"P",
         'helpChapter':_("Common options"),
         'help':_("new password for the user account")+\
                 " (" + _("from standard input") + ")"
        },
        {'progAccess':(5,),
         'shortOption':"s",
         'longOption':"shell",
         'optVal':"SHELL",
         'helpChapter':_("Unix service options"),
         'help':_("new login shell for the user account")
        },
        {'progAccess':(5,),
         'shortOption':"L",
         'longOption':"lock",
         'helpChapter':_("Unix service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"U",
         'longOption':"unlock",
         'helpChapter':_("Unix service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"L",
         'longOption':"lock",
         'helpChapter':_("Samba service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"U",
         'longOption':"unlock",
         'helpChapter':_("Samba service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"L",
         'longOption':"lock",
         'helpChapter':_("Mail service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"U",
         'longOption':"unlock",
         'helpChapter':_("Mail service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"L",
         'longOption':"lock",
         'helpChapter':_("Jabber service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"U",
         'longOption':"unlock",
         'helpChapter':_("Jabber service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(5,),
         'shortOption':"V",
         'longOption':"visible",
         'helpChapter':_("Unix service options"),
         'help':_("the user account is visible")
        },
        {'progAccess':(5,),
         'shortOption':"I",
         'longOption':"invisible",
         'helpChapter':_("Unix service options"),
         'help':_("the user account is invisible")
        },
        #{'progAccess':(5,),
         #'shortOption':"u",
         #'longOption':"uid",
         #'optVal':"UID",
         #'helpChapter':_("Common options"),
         #'help':_("new UID for the user account")
        #},
        {'progAccess':(6,),
         'shortOption':"a",
         'longOption':"allow",
         'helpChapter':_("Samba service options"),
         'help':_("enter the allowed ip addresses and network")
        },
        {'progAccess':(6,),
         'shortOption':"f",
         'longOption':"force",
         'helpChapter':_("Common options"),
         'help':_("forced setup service")
        },
        {'progAccess':(6,),
         'shortOption':"n",
         'longOption':"netbios",
         'optVal':"NETBIOS_NAME",
         'helpChapter':_("Samba service options"),
         'help':_("netbios name, default hostname")
        },
        {'progAccess':(6,),
         'shortOption':"w",
         'optVal':"WORKGROUP",
         'longOption':"workgroup",
         'helpChapter':_("Samba service options"),
         'help':_("workgroup, default 'Calculate'")
        },
        {'progAccess':(6,),
         'shortOption':"a",
         'longOption':"allow",
         'helpChapter':_("Mail service options"),
         'help':_("enter the allowed ip addresses and network")
        },
        {'progAccess':(6,),
         'optVal':"HOST",
         'longOption':"host",
         'helpChapter':_("Mail service options"),
         'help':_("mail host, default - hostname")
        },
        {'progAccess':(6,),
         'shortOption':"t",
         'optVal':"TYPE",
         'longOption':"type",
         'helpChapter':_("Mail service options"),
         'help':_("mail type - 'imap', 'pop3', 'pop3,imap' (default - imap)")
        },
        {'progAccess':(6,),
         'shortOption':"c",
         'optVal':"CRYPT",
         'longOption':"crypt",
         'helpChapter':_("Mail service options"),
         'help':_("encryption type - 'none', 'tls' (default - tls)")
        },
        {'progAccess':(6,),
         'optVal':"HOST",
         'longOption':"host",
         'helpChapter':_("Jabber service options"),
         'help':_("jabber host, default - hostname")
        },
        {'progAccess':(6,),
         'optVal':"CONDITION",
         'longOption':"history",
         'helpChapter':_("Jabber service options"),
         'help':_("enabled or disabled jabber history logging, default disable.\
 (on/off)")
        },
        # Опции cl-passwd
        # LDAP пользователь
        {'progAccess':(7,),
         'shortOption':"d",
         'longOption':"delete",
         'helpChapter':_("Unix service options"),
         'help':_("delete the password for the named account")
        },
        {'progAccess':(7,),
         'shortOption':"s",
         'longOption':"smb",
         'helpChapter':_("Samba service options"),
         'help':_("password will be changed only for Samba account")
        },
        {'progAccess':(7,),
         'shortOption':"l",
         'longOption':"lock",
         'helpChapter':_("Unix service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"u",
         'longOption':"unlock",
         'helpChapter':_("Unix service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"l",
         'longOption':"lock",
         'helpChapter':_("Samba service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"u",
         'longOption':"unlock",
         'helpChapter':_("Samba service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"l",
         'longOption':"lock",
         'helpChapter':_("Mail service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"u",
         'longOption':"unlock",
         'helpChapter':_("Mail service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"l",
         'longOption':"lock",
         'helpChapter':_("Jabber service options"),
         'help':_("lock the user account")
        },
        {'progAccess':(7,),
         'shortOption':"u",
         'longOption':"unlock",
         'helpChapter':_("Jabber service options"),
         'help':_("unlock the user account")
        },
        {'progAccess':(8,),
         'shortOption':"b",
         'longOption':"backup",
         'helpChapter':_("Common options"),
         'help':_("backup services configuration files and LDAP branches")+\
                 " (" + _("default option") + ")"
        },
        {'progAccess':(8,),
         'shortOption':"r",
         'longOption':"restore",
         'helpChapter':_("Common options"),
         'help':_("restore services configuration files and LDAP branches")
        },

        {'progAccess':(9,),
         'optVal':"CONDITION",
         'longOption':"history",
         'helpChapter':_("Jabber service options"),
         'help':_("enabled or disabled jabber history logging, default disable.\
 (on/off)")
        },
        {'progAccess':(9,),
         'optVal':"HOST",
         'longOption':"host",
         'helpChapter':_("Jabber service options"),
         'help':_("jabber host, default - hostname")
        },
        {'progAccess':(9,),
         'shortOption':"a",
         'longOption':"allow",
         'helpChapter':_("Mail service options"),
         'help':_("enter the allowed ip addresses and network")
        },
        {'progAccess':(9,),
         'shortOption':"t",
         'optVal':"TYPE",
         'longOption':"type",
         'helpChapter':_("Mail service options"),
         'help':_("mail type - 'imap', 'pop3', 'pop3,imap'")
        },
        {'progAccess':(9,),
         'shortOption':"c",
         'optVal':"CRYPT",
         'longOption':"crypt",
         'helpChapter':_("Mail service options"),
         'help':_("encryption type - 'none', 'tls'")
        },
        {'progAccess':(9,),
         'shortOption':"a",
         'longOption':"allow",
         'helpChapter':_("Samba service options"),
         'help':_("enter the allowed ip addresses and network")
        },
        {'progAccess':(10,),
         'shortOption':"a",
         'longOption':"allow",
         'helpChapter':_("Common options"),
         'help':_("enter the allowed ip addresses and network\
 for installed services")
        },
        {'progAccess':(9,10),
         'shortOption':"v",
         'longOption':"verbose",
         'helpChapter':_("Common options"),
         'help':_("display additional information")
        },
        {'progAccess':(10,),
         'longOption':"repl",
         'helpChapter':_("Common options"),
         'help':_("using the backup of another server,\
 replicate runs on the server")
        },
         {'progAccess':(11,),
         'shortOption':"l",
         'optVal':"LOGIN",
         'longOption':"login",
         'helpChapter':_("Common options"),
         'help':_("user name the logged on in server")
        },
        {'progAccess':(11,),
         'shortOption':"s",
         'longOption':"silent",
         'helpChapter':_("Common options"),
         'help':_("silent mode messages")
        },
        {'progAccess':(12,),
         'shortOption':"r",
         'optVal':"R_HOSTS",
         'longOption':"rhosts",
         'helpChapter':_("Common options"),
         'help':_("servers replication (comma delimited)")
        },
        {'progAccess':(12,),
         'longOption':"off",
         'helpChapter':_("Common options"),
         'help':_("replication off")
        },
        {'progAccess':(14,),
         'shortOption':"m",
         'longOption':"machines",
         'helpChapter':_("Samba service options"),
         'help':_("information about all machines")
        },
        {'progAccess':(14,),
         'shortOption':"M",
         'optVal':"MACHINE",
         'helpChapter':_("Samba service options"),
         'help':_("information about the machine")
        },
        {'progAccess':(14,),
         'shortOption':"u",
         'longOption':"users",
         'helpChapter':_("Common options"),
         'help':_("information about all users")
        },
        {'progAccess':(14,),
         'shortOption':"U",
         'optVal':"LOGIN",
         'helpChapter':_("Common options"),
         'help':_("information about the user")
        },
        {'progAccess':(14,),
         'shortOption':"g",
         'longOption':"groups",
         'helpChapter':_("Unix service options"),
         'help':_("information about all groups")
        },
         {'progAccess':(14,),
         'shortOption':"G",
         'optVal':"GROUP",
         'helpChapter':_("Unix service options"),
         'help':_("information about the group")
        },
        {'progAccess':(14,),
         'shortOption':"g",
         'longOption':"groups",
         'helpChapter':_("Mail service options"),
         'help':_("information about all groups")
        },
         {'progAccess':(14,),
         'shortOption':"G",
         'optVal':"GROUP",
         'helpChapter':_("Mail service options"),
         'help':_("information about the group")
        },
        {'progAccess':(14,),
         'shortOption':"g",
         'longOption':"groups",
         'helpChapter':_("Jabber service options"),
         'help':_("information about all groups")
        },
         {'progAccess':(14,),
         'shortOption':"G",
         'optVal':"GROUP",
         'helpChapter':_("Jabber service options"),
         'help':_("information about the group")
        },
        {'progAccess':(14,),
         'longOption':"full",
         'helpChapter':_("Common options"),
         'help':_("full information (all fields)")
        },
        #{'progAccess':(0,1,2,4,5,6),
         #'shortOption':"s",
         #'longOption':"set",
         #'optVal':"<name>=<val>",
         #'helpChapter':_("Common options"),
         #'help':_("change enviroment values")
        #},
        #{'shortOption':"e",
         #'longOption':"env",
         #'optVal':"filter",
         #'helpChapter':_("Common options"),
         #'help':_("show enviroment values (filter for type, all - no filter)")
        #},
        # Services
        {'progAccess':(6,),
        'helpChapter':_("Services"),
        'help':pcs("  ldap", self.column_width,
                    "ldap " + servName, self.consolewidth-self.column_width)
        },

        {'progAccess':(0,1,2,3,4,5,6,7,9,12,14),
        'helpChapter':_("Services"),
        'help':pcs("  unix", self.column_width,
                    "unix " + servName, self.consolewidth-self.column_width)
        },
        {'progAccess':(3,4,5,6,7,9,12,14),
        'helpChapter':_("Services"),
        'help':pcs("  samba", self.column_width,
                    "samba " + servName, self.consolewidth-self.column_width)
        },
        {'progAccess':(0,1,2,),
        'helpChapter':_("Services"),
        'help':pcs("  samba", self.column_width,
                    _("using unix group"),
                     self.consolewidth-self.column_width)
        },
        {'progAccess':(0,1,2,3,4,5,6,7,9,12,14),
        'helpChapter':_("Services"),
        'help':pcs("  mail", self.column_width,
                    "mail " + servName, self.consolewidth-self.column_width)
        },
        {'progAccess':(0,1,2,3,4,5,6,7,9,14),
        'helpChapter':_("Services"),
        'help':pcs("  jabber", self.column_width,
                    "jabber " + servName, self.consolewidth-self.column_width)
        },
        {'progAccess':(3,4,5,6,7,9,14),
        'helpChapter':_("Services"),
        'help':pcs("  ftp", self.column_width,
                    "ftp " + servName, self.consolewidth-self.column_width)
        },
        ##{'helpChapter':_("Services"),
         ##'help':"  mail \t\t\tmail " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  ftp \t\t\tftp " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  proxy \t\tproxy " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  radius \t\tradius " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  jabber \t\tjabber " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  addressbook \t\taddressbook " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  dhcp \t\t\tdhcp " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  named \t\tnamed " + servName + "\n"
        ##},
        ##{'helpChapter':_("Services"),
        ##'help':"  wiki \t\t\twiki " + servName + "\n"
        ##},
        # Informative output
        {
         #'progAccess':(3,),
         'helpChapter':"Copyright",
         'help':Version
        },
        # Использование
        {
         'progAccess':(1,),
         'helpChapter':_("Usage"),
         'help': cmdName + "  " +_("group") + " " + _("service")
        },
        {
         'progAccess':(0,2),
         'helpChapter':_("Usage"),
         'help': cmdName + "  [" + _("options") + "] " +\
         _("group") + " " + _("service")
        },
        {
         'progAccess':(3,4,5,7),
         'helpChapter':_("Usage"),
         'help': cmdName  + "  [" + _("options") + "] " + _("user") +\
         " " + _("service")
        },
        {
         'progAccess':(6,12,14),
         'helpChapter':_("Usage"),
         'help': cmdName  + "  [" + _("options") + "] "+\
         " " + _("service")
        },
        {
         'progAccess':(8,11),
         'helpChapter':_("Usage"),
         'help': cmdName  + "  [" + _("options") + "]"
        },
        {
         'progAccess':(9,),
         'helpChapter':_("Usage"),
         'help': cmdName + " " + _("service")
        },
        {
         'progAccess':(10,13),
         'helpChapter':_("Usage"),
         'help': cmdName
        },
        # Function
        {
         'progAccess':(0,),
         'helpChapter':"Function",
         'help':_("Add group in LDAP directory service")
        },
        {
         'progAccess':(1,),
         'helpChapter':"Function",
         'help':_("Delete group from LDAP directory service")
        },
        {
         'progAccess':(2,),
         'helpChapter':"Function",
         'help':_("Modify group profiles in LDAP directory service")
        },
        {
         'progAccess':(3,),
         'helpChapter':"Function",
         'help':_("Add user in LDAP directory service")
        },
        {
         'progAccess':(4,),
         'helpChapter':"Function",
         'help':_("Delete user from LDAP directory service")
        },
        {
         'progAccess':(5,),
         'helpChapter':"Function",
         'help':_("Modify user profiles in LDAP directory service")
        },
        {
         'progAccess':(6,),
         'helpChapter':"Function",
         'help':_("Sets service in the system")
        },
        {
         'progAccess':(7,),
         'helpChapter':"Function",
         'help':_("Change user password")
        },
        {
         'progAccess':(8,),
         'helpChapter':"Function",
         'help':_("Backup or restore installed services")
        },
        {
         'progAccess':(9,),
         'helpChapter':"Function",
         'help':_("Updates configuration files for the service")
        },
        {
         'progAccess':(10,),
         'helpChapter':"Function",
         'help':_("Rebuild configuration files and LDAP database for all \
services")
        },
        {
         'progAccess':(11,),
         'helpChapter':"Function",
         'help':_("Writes information about the user in the LDAP branch \
'Replication'")
        },
        {
         'progAccess':(12,),
         'helpChapter':"Function",
         'help':_("Setup and configure replication between LDAP servers")
        },
        {
         'progAccess':(13,),
         'helpChapter':"Function",
         'help':_("Deletes the users directories, which had been previously \
removed from the LDAP using replication")
        },
        {
         'progAccess':(14,),
         'helpChapter':"Function",
         'help':_("Information about all services")
        },
        # Примеры
        {
         'progAccess':(0,),
         'helpChapter':_("Examples"),
         'help':pcs( "  cl-groupadd guest ldap", self.column_width,
             "# " + _("add group guest in LDAP service"),
             self.consolewidth-self.column_width )
        },
        {
         'progAccess':(1,),
         'helpChapter':_("Examples"),
         'help':pcs( "  cl-groupdel guest unix", self.column_width,
             "# " + _("delete group guest from Unix service") + "."
            , self.consolewidth-self.column_width)
        },
        {
         'progAccess':(2,),
         'helpChapter':_("Examples"),
         'help':pcs( "  cl-groupmod -a guest test unix", self.column_width,
             "# " + _("add user test to group guest in Unix service"),
             self.consolewidth-self.column_width )
        },
        {
         'progAccess':(3,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-useradd guest samba", self.column_width,
                "# " +_("add user guest in Samba service") + ".",
                self.consolewidth - self.column_width)
        },
        {
         'progAccess':(4,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-userdel guest samba", self.column_width,
             "# " + _("delete user guest from Samba service") + ".",
            self.consolewidth-self.column_width)
        },
        {
         'progAccess':(5,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-usermod -a test guest unix",
            self.column_width,
            "# " + _("append user guest to the supplemental group test") +\
            ".",
            self.consolewidth-self.column_width)
        },
        {
         'progAccess':(6,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-setup samba", self.column_width,
             "# "+_("set Samba service in the system") + ".",
             self.consolewidth-self.column_width)
        },
        {
         'progAccess':(7,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-passwd test samba", self.column_width,
             "# "+_("change password of user test for Samba service") + ".",
             self.consolewidth-self.column_width)
        },
        {
         'progAccess':(8,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-backup -r", self.column_width,
             "# "+_("restore all services") + ".",
             self.consolewidth-self.column_width)
        },
        {
         'progAccess':(9,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-update samba", self.column_width,
             "# "+_("update config files Samba services") + ".",
             self.consolewidth-self.column_width)
        },
        {
         'progAccess':(10,),
         'helpChapter':_("Examples"),
         'help':pcs("  cl-rebuild", self.column_width,
             "# "+_("rebuild all services") + ".",
             self.consolewidth-self.column_width)
        },
        {
         'progAccess':(11,),
         'helpChapter':_("Examples"),
         'help':pcs("  repldap -l test", self.column_width,
             "# "+_("user information 'test' is recorded in the branch \
'Replication'") + ".",
             self.consolewidth-self.column_width)
        },
        #{
         #'helpChapter':_("Examples"),
         #'help':pcs("  " + cmdName + " --env boot", self.column_width,
             #"# "+_("show enviroment varibles which has type")+" 'boot'" +\
             #".",
             #self.consolewidth-self.column_width)
        #},
        #{'progAccess':(0,1,2,4,5,6),
         #'helpChapter':_("Examples"),
         #'help':pcs("  " + cmdName + " \\\n    --set setup_march=x86_64",
             #self.column_width, "# "+ _("modify some env") + ".",
             #self.consolewidth-self.column_width)
        #},
        ]

        self._cl_help__setParamHelp()

        # Удаляем ненужный аттрибут класса cl_profile.xmlShare
        self._createElement = False
        delattr(self, "_createElement")

        #Название всех сервисов
        self.allServ = []
        self.__setAllServ()

    def processOptionsForDatavars(self, options, datavars):
        '''Обработать опции связанные с переменными окружения

        Параметры:
        options     словарь опций ( <буква опции>:<значение>
                   обрабатывает буквы 's' для установки параметров
                   'e' для отображения)
        datavars   объект-хранилище переменных окружнения

        Возвращаемые значения:
        True       удалось установить указанные параметры
        False      метод вызван для просмотра переменных окружения, или
                   установка переменных окружения прошла с ошибками.
        '''
        # если это установка параметров
        if 's' in options:
            # если установки параметрв не произошло
            if not datavars.flFromCmdParam(options['s']):
                # вывод
                print _("Bad enviroment parameters")
                return False
        # если опция отображения параметров
        if 'e' in options:
            # вывод всех параметров
            if options['e'] == '*':
                datavars.printVars()
            # вывод параметров, используюя фильтр
            else:
                datavars.printVars(
                    [i.strip() for i in options['e'].split(':')])
            return False
        return True

    def handleCheckAccess(self,dataHash):
        """Дополнительная проверка опций-справок - опция доступна только если
        в разделах этой справки есть хотябы одна опция

        Входные параметры:
        dataHash      словарь из списка self.data
        """
        # если эта опция для реализации справки
        if 'longOption' in dataHash \
            and dataHash['longOption'] in self.relOptions:
            # составляем список разделов которые должны быть не пустые
            # разделы из relOptions относящиеся к этой опции за исключением
            # разделов которые надо пропустить (relChapterPass)
            trueChapters = \
                set(self.relOptions[dataHash['longOption']]).difference( \
                                                self.relChapterPass)
            # перебираем все опции
            for unit in self.data:
                # если опция не отностится к выполняемой программе, то
                # ее пропустить
                if 'progAccess' in unit and \
                    not self.progName[self.cmdName] in unit['progAccess']:
                    continue
                # если опция отностится к необходмой справки
                if unit['helpChapter'] in trueChapters:
                    # опция справки - доступна
                    return True
            # если не оказалось не одной опция для разделов этой справки
            return False
        # опция доступна, так как не справочная
        return True

    def __setAllServ(self):
        """Записывает в аттрибут self.allServ названия всех сервисов"""
        sServ = re.compile("\s*([^\s]+)\s*")
        for par in self.data:
            if par.has_key('helpChapter') and\
                par['helpChapter'] == _("Services") and\
                par.has_key('help') and self.access(par):
                res = sServ.search(par['help'])
                if res:
                    self.allServ.append(res.group(1))

class servFtp(shareLdap):
    """Методы севисa Ftp"""

    relUsDN = 'ou=Users'
    relServDN = 'ou=Ftp'
    # Алгоритм шифрования пароля для LDAP пользователя
    userCrypt = "ssha"
    # Используемые ldif файлы
    ldifFileUser = "/usr/lib/calculate/calculate-server/ldif/ftp_user.ldif"
    ldifFileBase ="/usr/lib/calculate/calculate-server/ldif/ftp_base.ldif"

    def __init__(self):
        shareLdap.__init__(self)
        self.relDN = self.addDN(self.relServDN,self.ServicesDN)
        # DN пользователей, относительно базового DN
        self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
        self.servUnixObj = servUnix()

    def setupFtpServer(self, options):
        """Начальная настройка FTP сервиса"""
        # Принудительная установка
        forceOptions = False
        if options.has_key("f"):
            forceOptions = True
        # Создаем объект переменных и начальная проверка
        if not self.initialChecksSetup():
            return False
        if self.clVars.Get("sr_unix_set") != "on":
            self.printERROR(_("Unix service is not setuped"))
            self.printWARNING(_("Setup Unix service"))
            self.printWARNING("  cl-setup unix")
            return False
        # В случае если сервер установлен
        if self.clVars.Get("sr_ftp_set") == "on" and\
            not forceOptions:
            self.printWARNING (_("WARNING") + ": " +\
                _("FTP server is configured")+ ".")
            return True

        if not forceOptions:
            # предупреждение  при выполнении этой программы будут изменены
            # конфигурационные файлы сервиса FTP (программа proftpd)
            self.printWARNING (_("WARNING") + ": " +
                _("Executing of the program will change") + " " +
                _("the configuration files of FTP service") +" ("+
                _("program proftpd") + ")." )
            # если вы готовы продолжить работу программы нажмите Y если нет n
            messDialog = \
               _("If you are ready to continue executing the program") + ", "+\
               _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
        else:
            # делаем backup
            # Проверим запущен ли ldap
            if not self.getRunService("ldap"):
                # Запускаем LDAP сервер
                if not self.runLdapServer():
                    return False
            bakupObj = servLdap()
            bakupObj.backupServer()
        # Удаляем переменные сервиса в ini файлах
        self.deleteServiceVarsInFile("ftp")
        # Cоздаем объект переменные
        self.createClVars()
        # Удаляем из автозапуска демона
        if not self.delDaemonAutostart("proftpd"):
            return False
        # останавливаем сервис Mail
        if not self.stopServices(["ftp"]):
            return False
        # Имя устанавливаемого сервиса
        self.clVars.Set("cl_pass_service","ftp")
        self.clVars.Write("sr_ftp_set","off")
        if not self.applyProfilesFromService('ftp'):
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        else:
            if not self.restartLdapServer():
                return False
        # В случае если сервис Samba установлен перезапускаем его
        if self.clVars.Get("sr_samba_set") == "on":
            if self.getRunService('samba'):
                textLines = self.execProg("/etc/init.d/samba restart",
                                          False, False)
                if not (textLines and type(textLines) == types.ListType and\
                    "ok" in textLines[-1] or textLines and "ok" in textLines):
                    self.printNotOK(_("Restarting") + " Samba ...")
                    return False
            else:
                textLines = self.execProg("/etc/init.d/samba start",False,False)
                if not (textLines and type(textLines) == types.ListType and\
                    "ok" in textLines[-1] or textLines and "ok" in textLines):
                    self.printNotOK(_("Starting") + " Samba ...")
                    return False
        # Подключаемся к LDAP cерверу
        if not shareLdap.getLdapObjInFile(self):
            return False
        # Находим в LDAP FTP сервис
        resSearch = self.searchService()
        ret = True
        if resSearch:
            delDN = self.relDN
            ret = self.deleteDN(delDN)
            if ret:
                self.printOK(_("Remove FTP DN from LDAP Database") +" ...")
            else:
                self.printERROR(\
                            _("Can not remove FTP DN from LDAP Database")+\
                            " ...")
        if not ret:
            return False
        ldifFile = self.ldifFileBase
        baseLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            self.ldapObj.ldapAdd(baseLdif)
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        # Записываем данные администратора сервиса FTP
        ldapParser = iniLdapParser()
        ldapParser.setVar("ftp",
            {"DN":self.clVars.Get("ld_ftp_dn"),
             "PASS":self.clVars.Get("ld_ftp_pw")})
        self.printOK(_("Added ldif file") +" ...")
        textLines = []
        if self.getRunService('ftp'):
            textLines = self.execProg("/etc/init.d/proftpd restart",False,False)
        else:
            textLines = self.execProg("/etc/init.d/proftpd start",False,False)
        if textLines and type(textLines) == types.ListType and\
            "ok" in textLines[-1] or textLines and "ok" in textLines:
            self.printOK(_("Starting") + " " + "Proftpd" + " ...")
        else:
            self.printNotOK(_("Starting") + " " + "Proftpd" + " ...")
            return False
        # Устанавливаем автозапуск демона
        if not self.setDaemonAutostart("proftpd"):
            return False
        # Устанавливаем переменную для клиента
        fullHostName = "%s.%s"%(self.clVars.Get('os_net_hostname'),
                                    self.clVars.Get('os_net_domain'))
        self.clVars.Set("cl_remote_ftp",fullHostName,True)
        #cоздаем рабочую ftp директорию
        ftpPath = self.clVars.Get("sr_ftp_path")
        if not os.path.exists(ftpPath):
            os.makedirs(ftpPath)
            # Создадим иконку для share
            fileTxt = "[Desktop Entry]\nIcon=folder-downloads"
            fileDirectory = os.path.join(ftpPath,".directory")
            uid = 0
            gid = 0
            if not self.createUserFile(fileDirectory, fileTxt, uid, gid):
                return False
        #cоздаем директорию tmp
        ftpTmpPath = os.path.join(ftpPath,"tmp")
        if not os.path.exists(ftpTmpPath):
            os.makedirs(ftpTmpPath)
            os.chmod(ftpTmpPath,0777)
        #cоздаем директорию pub
        ftpPubPath = os.path.join(ftpPath,"pub")
        if not os.path.exists(ftpPubPath):
            os.makedirs(ftpPubPath)
            os.chmod(ftpPubPath,0755)
        #запишем переменные для клиента
        clientVars = ["cl_remote_ftp"]
        if not self.saveVarsClient(clientVars):
            return False
        self.clVars.Write("sr_ftp_set","on")
        self.printOK(_("FTP service configured") + " ...")
        return True

    def searchFtpUser(self, userName):
        """Находит пользователя сервиса FTP"""
        resSearch = self.searchLdapDN(userName, self.relUsersDN, "uid")
        return resSearch

    def delUserInFtpAndUnix(self, userName, flagDelUnixUser):
        """Удаляет пользователя

        Удаляет из FTP и если установлен флаг из Unix
        """
        if self.searchFtpUser(userName):
            if not self.delUserFtpServer(userName, {}, False):
                return False
        if flagDelUnixUser:
            if not self.servUnixObj.delUserUnixServer(userName, {}, False,
                                                      False):
                return False
        return True

    def modUserFtpServer(self, userName, options):
        """Модифицирует настройки пользователя FTP в LDAP"""
        # Проверим установлен ли сервис FTP
        if not self.initialChecks("ftp"):
            return False
        resSearch = self.searchFtpUser(userName)
        if not resSearch:
            self.printERROR(
                _("User %s is not found in FTP service") % str(userName) +\
                  " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        # Изменяем коментарий к пользователю
        if options.has_key('c'):
            comment = options['c']
            modAttrs += [(ldap.MOD_REPLACE, 'sn', comment),
                         (ldap.MOD_REPLACE, 'cn', comment)]
        # Изменяем пароль пользователя
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        if userPwd:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if resSearch[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        if modAttrs:
            uid = resSearch[0][0][1]['uid'][0]
            DN = self.addDN("uid="+uid, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if options.has_key('c'):
                self.printSUCCESS(_("Modified comment (full name)") + " ...")
            if options.has_key('P') or options.has_key('p'):
                self.printSUCCESS(_("Modified FTP user password") + " ...")
        return True

    def modUserFtpPasswd(self, userName, options):
        """Устанавливает пароль Ftp пользователя и меняет его опции"""
        # Проверим установлен ли сервис jabber
        if not self.initialChecks("ftp"):
            return False
        resSearch = self.searchFtpUser(userName)
        if not resSearch:
            self.printERROR(
                _("User %s is not found in FTP service") % str(userName) +\
                  " ...")
            return False
        # Изменяемые аттрибуты пользователя
        modAttrs = []
        if not options:
            optPasswd = {"p":""}
            userPwd = self.getUserPassword(optPasswd, "p", False)
            if userPwd == False:
                return False
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
            if not userPwdHash:
                return False
            if resSearch[0][0][1].has_key('userPassword'):
                modAttrs.append((ldap.MOD_REPLACE, 'userPassword',
                                userPwdHash))
            else:
                modAttrs.append((ldap.MOD_ADD, 'userPassword',
                                userPwdHash))
        if modAttrs:
            uid = resSearch[0][0][1]['uid'][0]
            DN = self.addDN("uid="+userName, self.relUsersDN)
            if not self.modAttrsDN(DN, modAttrs):
                return False
            if not options:
                self.printSUCCESS(_("Changed FTP user password") + " ...")
            return True
        return False


    @adminConnectLdap
    def delUserFtpServer(self,userName,options,printSuccess=True):
        """Удаляем FTP пользователя"""
        # Проверим установлен ли сервис FTP
        if not self.initialChecks("ftp"):
            return False
        # Ищем FTP пользователя
        resFtp = self.searchFtpUser(userName)
        if not resFtp:
            self.printERROR(_("User not exists in FTP service"))
            return False
        # FTP директория пользователя
        ftpUserDir = resFtp[0][0][1]['homeDirectory'][0]
        ftpPath = self.clVars.Get("sr_ftp_path")
        if ftpUserDir == ftpPath:
            ftpUserDir = os.path.join(ftpPath,"pub/users",userName)
        # Удаляем пользователя
        delDN = self.addDN("uid=" + userName, self.relUsersDN)
        if not self.delDN(delDN):
            return False
        # Удаляем FTP папку
        if os.path.exists(ftpUserDir):
            if self.removeDir(ftpUserDir):
                if printSuccess:
                    self.printSUCCESS(\
                        _("FTP user directory %s is removed")%str(ftpUserDir)+\
                                " ...")
        if printSuccess:
            self.printSUCCESS(_("FTP user %s is deleted")%userName +\
                            " ...")
        return True

    @adminConnectLdap
    def addUserFtpServer(self, userName, options):
        """Добавляет пользователя FTP"""
        # Проверим установлен ли сервис FTP
        if not self.initialChecks("ftp"):
            return False
        if self.searchFtpUser(userName):
            self.printERROR(_("User exists in FTP service"))
            return False
        resUnix = self.servUnixObj.searchUnixUser(userName)
        resPwd = self.servUnixObj.searchPasswdUser(userName)
        # Пароль пользователя FTP
        userPwd = self.getUserPassword(options, "p", "P")
        if userPwd == False:
            return False
        flagCreateUnixUser = False
        if not (resUnix or resPwd):
            flagCreateUnixUser = True
            # Добавим пользователя LDAP
            optUnix = {}
            # Группа пользователя
            if options.has_key('g'):
                optUnix['g'] = options['g']
                # Полное имя пользователя
            if options.has_key('c'):
                optUnix['c'] = options['c']
            if not self.servUnixObj.addUserUnixServer(userName, optUnix,
                                                        False):
                self.printERROR (_("Can not add user")+ " " +\
                                 str(userName) + _(" in Unix service"))
                return False
            resUnix = self.servUnixObj.searchUnixUser(userName)
        self.clVars.Set("ur_name", userName)
        #Полное имя пользователя
        fullNameUser = self.servUnixObj.fullNameUser
        if options.has_key('c'):
            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 not userPwd:
            userPwdHash = "crypt{xxx}"
        else:
            userPwdHash = self.getHashPasswd(userPwd, self.userCrypt)
        if not userPwdHash:
            if flagCreateUnixUser:
                self.servUnixObj.delUserUnixServer(userName, {}, False, False)
            return False
        self.clVars.Set("ur_hash",userPwdHash)
        # Находим uid и gid пользователя
        if resUnix:
            uid = int(resUnix[0][0][1]['uidNumber'][0])
            gid = int(resUnix[0][0][1]['gidNumber'][0])
        elif resPwd:
            uid = int(resPwd.split(":")[2])
            gid = int(resPwd.split(":")[3])
        else:
            self.printERROR(_("user are not found"))
            flagError = True
        self.clVars.Set("ur_id",str(uid))
        self.clVars.Set("ur_gid",str(gid))
        # Корневая FTP директория
        ftpDir = self.clVars.Get("sr_ftp_path")
        # FTP директория пользователя
        if options.has_key('d') and options.has_key('m'):
            ftpUserDir = options['d']
            if ftpUserDir[0] == "/":
                ftpUserDir = ftpUserDir[1:]
            ftpUserDir = os.path.join(ftpDir,ftpUserDir)
            self.clVars.Set("ur_home_path", ftpUserDir)
        else:
            self.clVars.Set("ur_home_path", ftpDir)
        ldifFile = self.ldifFileUser
        userLdif = self.createLdif(ldifFile)
        if not self.ldapObj.getError():
            #Добавляем пользователя в LDAP
            self.ldapObj.ldapAdd(userLdif)
        # не переделывать на else
        if self.ldapObj.getError():
            print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
            return False
        flagError = False
        # FTP директория пользователя
        if not options.has_key('d'):
            ftpUserDir = os.path.join(ftpDir,"pub/users",userName)
        # Создаем FTP директорию пользователя
        if options.has_key('m'):
            if not self.createUserDir(uid, gid, ftpUserDir):
                flagError = True
        if flagError:
            self.delUserInFtpAndUnix(userName, flagCreateUnixUser)
            self.printERROR(_("Can not add user") + " ...")
            return False
        if flagCreateUnixUser:
            self.printSUCCESS(_("Added user in Unix service") + " ...")
        self.printSUCCESS(_("Added user in FTP service") + " ...")
        return True


class servRepl(shareLdap):
    """Методы для работы с репликацией"""

    # Используемые ldif файлы
    # Cлужебная ветка: LDAP
    ldifFileBase = "/usr/lib/calculate/calculate-server/ldif/ldap_base.ldif"
    # Ветки репликации: Access, Worked 
    ldifFileRepl = "/usr/lib/calculate/calculate-server/ldif/ldap_repl.ldif"
    # Имя пользователя, машина на которой хостимся
    ldifFileWorkedUser =\
        "/usr/lib/calculate/calculate-server/ldif/ldap_repl_worked_user.ldif"
    # Реплицируемые почтовые алиасы
    ldifFileMailUser =\
        "/usr/lib/calculate/calculate-server/ldif/ldap_repl_mail.ldif"
    # Файл для определения выхода пользователя.
    logOutFile = ".logout"
    # Переменные (/etc/calculate/calculate.env)
    # которые будут сохранены при rebuild
    restoreDefaultVar =["sr_ldap_set", "ld_repl_pw", "ld_repl_set",
                        "sr_unix_set", "sr_samba_set","sr_mail_set"]
    # Переменные (/var/calculate/calculate.env)
    # которые будут сохранены при rebuild
    restoreLocalVar = ["sr_samba_domain","sr_samba_netbios",
                       "ld_repl_servers","ld_repl_unix_servers",
                       "ld_repl_samba_servers","ld_repl_ids",
                       "sr_samba_net_allow", "sr_mail_host",
                       "sr_mail_type", "sr_mail_crypt",
                       "sr_mail_relay_set","ld_repl_mail_servers"]
    # Переменные клиента (/var/calculate/remote/calculate.env)
    # которые будут сохранены при rebuild
    restoreRemoteClientVar = ["ld_base_dn", "ld_bind_dn",
                              "ld_bind_pw", "ld_services_dn",
                              "ld_unix_dn", "sr_jabber_crypt",
                              "sr_jabber_host", "sr_jabber_port",
                              "sr_mail_crypt", "sr_mail_host",
                              "sr_mail_port", "sr_mail_send_crypt",
                              "sr_mail_send_host", "sr_mail_send_port",
                              "sr_mail_type", "sr_samba_host",
                              "ur_organization", "ur_signature"]
    # файл для удаления данных несуществущих пользователей по cron
    replCronFile = "replcron"

    def __init__(self):
        shareLdap.__init__(self)
        # Сервис LDAP
        self.servLdapObj = servLdap()
        # Сервис Samba
        self.servSambaObj = servSamba()
        # Сервис Unix
        self.servUnixObj = self.servSambaObj.servUnixObj
        # Сервис Mail
        self.servMailObj = servMail()
        # Cервис Jabber
        self.servJabberObj = servJabber()
        # DN ветки Worked
        self.relWorkedDN = False
        # DN ветки Replication/Mail
        self.relMailDN = False

    def createClientEnv(self):
        """Создает объект с клиентскими переменными"""
        clVars = cl_base.DataVars()
        clVars.flServer()
        calculate_ini = self.clVars.Get("cl_env_path")
        remoteIni = ""
        if calculate_ini and type(calculate_ini) == types.ListType:
            remoteIni = calculate_ini[0]
        if remoteIni:
            # проверить сущестование ini файла
            if os.path.exists(remoteIni):
                # получаем активную секцию
                set_act_section = set(['client'])
                # получить объект настроенный на ini
                config = cl_base.iniParser(remoteIni)
                # получаем все секции из конфигурационного файла
                allsect = config.getAllSectionNames()
                if not allsect:
                    return (True, clVars)
                # находим встречающиеся у обоих секции
                act_sect = tuple(set(allsect)& set_act_section)
                # получаем все переменные из всех секций
                for section in act_sect:
                    allvars = config.getAreaVars(section)
                    if allvars == False:
                        return (False, remoteIni)
                    # принудительно переписать все переменные окружения
                    # полученные из ini
                    for (k,v) in allvars.items():
                        k = k.encode("UTF-8")
                        v = v.encode("UTF-8")
                        clVars.Set(k, cl_utils.convertStrListDict(v), True)
        return (True, clVars)

    def prepAndSaveEnv(self):
        """Подготовка переменных и их запись в файлы в случае rebuild"""
        # Cоздаем объект переменные
        def removeNameFoundText(findText, listName):
            """Удаляет элементы списка.

            Будут удалены элементы названии которых присутствует текст
            (findText)
            """
            outListName = []
            for name in listName:
                if not findText in name:
                    outListName.append(name)
            return outListName
        # Cоздаем объект переменные
        self.createClVars()
        if self.clVars.Get("ld_repl_set") != "on":
            self.printERROR(_("Replication off in backup file") + " ...")
            return False
        # Cоздание объекта клиентских переменных
        cond, clVarsClient = self.createClientEnv()
        if not cond:
            self.printERROR(_("Variable incorrect in file %s")%clVarsClient +\
                        " ...")
            return False
        # Записываем переменные клиента в переменные сервера
        for varName in self.restoreRemoteClientVar:
            self.clVars.Set(varName, clVarsClient.Get(varName), True)
        clVarsClient.Get("ur_organization")
        # Модификация переменных
        replSambaServers = self.clVars.Get("ld_repl_samba_servers")
        if replSambaServers:
            replSambaServers = replSambaServers.split(",")
        replUnixServers = self.clVars.Get("ld_repl_unix_servers")
        if replUnixServers:
            replUnixServers = replUnixServers.split(",")
        replMailServers = self.clVars.Get("ld_repl_mail_servers")
        if replMailServers:
            replMailServers = replMailServers.split(",")
        hostName = self.clVars.Get('os_net_hostname')
        domain = self.clVars.Get('os_net_domain')
        serviceRepl = ""
        fullHostName = "%s.%s"%(hostName,domain)
        if not fullHostName in replSambaServers:
            if fullHostName in replUnixServers:
                serviceRepl = "unix"
                if fullHostName in replMailServers:
                    serviceRepl = "unix_mail"
        else:
            serviceRepl = "samba"
            if fullHostName in replMailServers:
                    serviceRepl = "samba_mail"
        if not serviceRepl and fullHostName in replMailServers:
            serviceRepl = "mail"
        if not serviceRepl:
            self.printERROR(\
        _("Not found this replication server %s in backup file")%fullHostName+\
          " ...")
            return False
        if serviceRepl == "unix":
            self.restoreDefaultVar = removeNameFoundText("samba",
                                                         self.restoreDefaultVar)
            self.restoreDefaultVar = removeNameFoundText("mail",
                                                         self.restoreDefaultVar)
            self.restoreLocalVar = removeNameFoundText("mail",
                                                       self.restoreLocalVar)
            self.restoreLocalVar = removeNameFoundText("samba",
                                                       self.restoreLocalVar)
            self.restoreRemoteClientVar = []
            # Очищаем переменные
            self.clVars.Set("ld_repl_mail_servers","",True)
            self.clVars.Set("ld_repl_samba_servers","",True)
            # Устанавливаем переменную серверы репликации
            # равной почтовым серверам репликации - Mail серверы репликации
            allReplServers = \
                list(set(self.clVars.Get("ld_repl_servers").split(",")) -\
                     set(self.clVars.Get("ld_repl_mail_servers").split(",")))
            self.clVars.Set("ld_repl_servers" ,",".join(allReplServers), True)
            # При вызове значения переменной будет перезапущен метод заполнения
            self.reloadDefaultVar("ld_repl_ids")

        elif serviceRepl == "samba":
            self.clVars.Set('sr_samba_netbios', "%s-cds"%hostName, True)
            self.clVars.Set('sr_samba_host',fullHostName, True)
            self.restoreDefaultVar = removeNameFoundText("mail",
                                                         self.restoreDefaultVar)
            self.restoreLocalVar = removeNameFoundText("mail",
                                                       self.restoreLocalVar)
            # Получаем от пользователя доверительные сети для сервиса Samba
            # Переназначаем объект переменных
            print _("Replications servers for Samba: %s")\
                    % " ".join(replSambaServers)
            self.servSambaObj.clVars = self.clVars
            if not self.servSambaObj.getAllowNet():
                return False
            # Очищаем переменные
            self.clVars.Set("ld_repl_mail_servers","",True)
            # Устанавливаем переменную серверы репликации
            # равной почтовым серверам репликации - Mail серверы репликации
            allReplServers = \
                list(set(self.clVars.Get("ld_repl_servers").split(",")) -\
                     set(self.clVars.Get("ld_repl_mail_servers").split(",")))
            self.clVars.Set("ld_repl_servers" ,",".join(allReplServers), True)
            # При вызове значения переменной будет перезапущен метод заполнения
            self.reloadDefaultVar("ld_repl_ids")

        elif serviceRepl == "mail":
            self.restoreDefaultVar = removeNameFoundText("samba",
                                                         self.restoreDefaultVar)
            self.restoreDefaultVar = removeNameFoundText("unix",
                                                         self.restoreDefaultVar)
            self.restoreLocalVar = removeNameFoundText("unix",
                                                       self.restoreLocalVar)
            self.restoreLocalVar = removeNameFoundText("samba",
                                                       self.restoreLocalVar)
            self.restoreRemoteClientVar = []
            # Получаем от пользователя доверительные сети для сервиса Mail
            # Переназначаем объект переменных
            print _("Replications servers for Mail: %s")\
                    % " ".join(replMailServers)
            self.servMailObj.clVars = self.clVars
            if not self.servMailObj.getAllowNet():
                return False
            self.clVars.Set('sr_mail_host', fullHostName, True)
            # Получаем имя хоста для сервиса Mail
            if not self.servMailObj.getHostName():
                return False
            # Указываем что это почтовый релей
            self.clVars.Set('sr_mail_relay_set', "on", True)
            # Устанавливаем переменную серверы репликации
            # равной почтовым серверам репликации
            self.clVars.Set("ld_repl_servers",
                            self.clVars.Get("ld_repl_mail_servers"), True)
            # Обнуляем ненужные переменные
            self.clVars.Set("ld_repl_samba_servers","",True)
            self.clVars.Set("ld_repl_unix_servers","",True)
            # При вызове значения переменной будет перезапущен метод заполнения
            self.reloadDefaultVar("ld_repl_ids")

        elif serviceRepl == "unix_mail":
            self.restoreDefaultVar = removeNameFoundText("samba",
                                                         self.restoreDefaultVar)
            self.restoreLocalVar = removeNameFoundText("samba",
                                                       self.restoreLocalVar)
            self.restoreLocalVar = removeNameFoundText("sr_mail_relay_set",
                                                       self.restoreLocalVar)
            self.restoreRemoteClientVar = []
            # Получаем от пользователя доверительные сети для сервиса Mail
            # Переназначаем объект переменных
            print _("Replications servers for Mail: %s")\
                    % " ".join(replMailServers)
            self.servMailObj.clVars = self.clVars
            if not self.servMailObj.getAllowNet():
                return False
            self.clVars.Set('sr_mail_host', fullHostName, True)
            # Получаем имя хоста для сервиса Mail
            if not self.servMailObj.getHostName():
                return False
 
        elif serviceRepl == "samba_mail":
            self.clVars.Set('sr_samba_netbios', "%s-cds"%hostName, True)
            self.clVars.Set('sr_samba_host',fullHostName, True)
            self.restoreLocalVar = removeNameFoundText("sr_mail_relay_set",
                                                       self.restoreLocalVar)
            # Получаем от пользователя доверительные сети для сервиса Samba
            # Переназначаем объект переменных
            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)
            self.servMailObj.clVars = self.clVars
            if not self.servMailObj.getAllowNet():
                return False
            self.clVars.Set('sr_mail_host', fullHostName, True)
            # Получаем имя хоста для сервиса Mail
            if not self.servMailObj.getHostName():
                return False
        # Находим пути к env файлам
        envPaths = self.clVars.Get("cl_env_path")
        # Удаляем env файлы
        for path in envPaths:
            if os.path.exists(path):
                os.remove(path)
        flagError = False
        # Записываем переменные сервера
        for varName in self.restoreDefaultVar:
            if not self.clVars.Write(varName,self.clVars.Get(varName),True):
                flagError = True
                break
        if flagError:
            self.printERROR(_("Variable '%s'")%varName + " " +\
                _("can not be recorded in the file %s") %envPaths[2]+\
                   " ...")
            return False
        for varName in self.restoreLocalVar:
            if not self.clVars.Write(varName,
                                     self.clVars.Get(varName),True,'local'):
                flagError = True
                break
        if flagError:
            self.printERROR(_("Variable '%s'")%varName + " " +\
                _("can not be recorded in the file %s") %envPaths[2]+\
                   " ...")
            return False
        # Записываем переменные клиента
        if self.restoreRemoteClientVar:
            if not self.saveVarsClient(self.restoreRemoteClientVar):
                return False
        # Выставляем права на ресурс remote
        if "samba" in serviceRepl:
            cl = self.staticUsers["client"]
            # Если нет то создадим директорию /var/calculate/remote
            remoteEnvFile = self.clVars.Get("cl_env_path")[0]
            remotePath = os.path.split(remoteEnvFile)[0]
            if not os.path.exists(remotePath):
                os.makedirs(remotePath)
            # права и владелец /var/calculate/remote
            if os.path.exists(remotePath):
                os.chown(remotePath,0,int(cl.gid))
                os.chmod(remotePath,02750)
            # изменяем владельца remote на client
            if not os.path.exists(remoteEnvFile):
                fd = os.open(remoteEnvFile, os.O_CREAT)
                os.close(fd)
                os.chmod(remoteEnvFile, 0640)
            if os.path.exists(remoteEnvFile):
                os.chown(remoteEnvFile,0,int(cl.gid))
        return True

    @adminConnectLdap
    def isSysDNExists(self):
        """Существует ли служебная ветка LDAP"""
        sysLogin = self.clVars.Get("ld_ldap_login")
        searchDN = self.searchLdapDN(sysLogin, self.ServicesDN, 'ou')
        if searchDN:
            return True
        else:
            return False

    @adminConnectLdap
    def isExistsLogout(self, userName):
        """Проверяет существует ли в директории профиля пользователя
        файл .logout"""
        logoutFile = os.path.join(self.clVars.Get("sr_samba_linprof_path"),
                                   userName,self.logOutFile)
        if os.path.exists(logoutFile):
            return True
        else:
            return False

    @adminConnectLdap
    def deleteLogoutFile(self, userName, logoutFile):
        """Удаляет .logout файл"""
        if os.path.exists(logoutFile):
            try:
                FD = open(logoutFile)
                exitStr = FD.read()
                FD.close()
            except:
                return False
            if exitStr:
                exitStr = exitStr.strip()
            else:
                exitStr = "EMPTY"
            try:
                os.remove(logoutFile)
            except:
                return False
            return exitStr
        return "NOFILE"

    def createUserDirs(self, userName):
        """Если пользовательские директории не существуют то создаем их
        """
        resSearchUnix = self.servUnixObj.searchUnixUser(userName)
        resPasswd = False
        uid = None
        gid = None
        if resSearchUnix:
            uid = int(resSearchUnix[0][0][1]['uidNumber'][0])
            gid = int(resSearchUnix[0][0][1]['gidNumber'][0])
        else:
            resPasswd = self.servUnixObj.searchPasswdUser(userName)
            if resPasswd:
                uid = int(resPasswd.split(":")[2])
                gid = int(resPasswd.split(":")[3])
        if uid == None or gid == None:
            print _("User %s not found in Unix service")
            return False
        winProfDir =\
                os.path.join(self.clVars.Get("sr_samba_winprof_path"),
                                             userName)
        linProfDir =\
                os.path.join(self.clVars.Get("sr_samba_linprof_path"),
                                             userName)
        userHomeDir =\
                os.path.join(self.clVars.Get("sr_samba_home_path"),
                                             userName)
        userNetlogonDir =\
                os.path.join(self.clVars.Get("sr_samba_winlogon_path"),
                                             userName)
        userDirs = [("home",userHomeDir),
                    ("netlogon",userNetlogonDir),
                    ("win_prof",winProfDir),
                    ('lin_prof',linProfDir)]
        flagError = False
        for name, userDir in userDirs:
            if not os.path.exists(userDir):
                if not self.createUserDir(uid, gid, userDir):
                    flagError = True
                    break
                if name == "home":
                    # Cоздаем иконку в домашней директории
                    fileTxt = "[Desktop Entry]\nIcon=user-home"
                    fileDirectory = os.path.join(userDir,".directory")
                    if not self.createUserFile(fileDirectory,
                                               fileTxt, uid, gid):
                        flagError = True
                        break
                elif name == "netlogon":
                    # Создаем start.cmd
                    netbios = self.clVars.Get("sr_samba_netbios")
                    netbios = netbios.upper()
                    fileTxt='NET USE R: /D\r\nNET USE R: \\\\%s\\share\
\r\nNET USE T: /D\r\nNET VIEW \\\\%s | find "ftp"\r\n\
if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios)
                    fileDirectory = os.path.join(userDir,"start.cmd")
                    if not self.createUserFile(fileDirectory,
                                               fileTxt, uid, gid):
                        flagError = True
                        break
        if flagError:
            return False
        return True

    def isLoginUser(self, userName):
        """Логинится ли пользователь"""
        if self.isExistsLogout(userName):
            return False
        else:
            return True

    @adminConnectLdap
    def isReplDNExists(self):
        """Существуют ли ветка репликации LDAP"""
        if not self.isSysDNExists():
            return False
        sysLogin = self.clVars.Get("ld_ldap_login")
        replLogin = self.clVars.Get("ld_repl_login")
        relSysDn = "ou=%s,%s"%(sysLogin,self.ServicesDN)
        searchReplDN = self.searchLdapDN(replLogin, relSysDn, 'ou')
        if not searchReplDN:
            return False
        else:
            return True

    @adminConnectLdap
    def isReplMailDNExists(self):
        """Существуют ли ветка репликации  Replication/Mail"""
        if not self.isReplDNExists():
            return False
        sysLogin = self.clVars.Get("ld_ldap_login")
        replLogin = self.clVars.Get("ld_repl_login")
        replMailLogin = self.clVars.Get("ld_repl_mail_login")
        relSysDn = "ou=%s,ou=%s,%s"%(replLogin,sysLogin,self.ServicesDN)
        searchReplDN = self.searchLdapDN(replMailLogin, relSysDn, 'ou')
        if not searchReplDN:
            return False
        else:
            return True

    @adminConnectLdap
    def addSysDN(self):
        """Добавляет служебную ветку в LDAP если она не существует"""
        if not self.isSysDNExists():
            ldifFile = self.ldifFileBase
            baseLdif = self.createLdif(ldifFile)
            if not self.ldapObj.getError():
                self.ldapObj.ldapAdd(baseLdif)
            if self.ldapObj.getError():
                print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
                return False
        return True

    @adminConnectLdap
    def delSysDN(self):
        """Удаляет служебную ветку в LDAP если она существует"""
        if self.isSysDNExists():
            sysLdapOU = "ou=%s"%self.clVars.Get("ld_ldap_login")
            sysLdapRelDN = self.addDN(sysLdapOU, self.ServicesDN)
            if not self.deleteDN(sysLdapRelDN):
                self.printERROR(_("Can not remove 'Services/LDAP' DN")+" ...")
                return False
        return True

    @adminConnectLdap
    def addReplDN(self, clVars=False):
        """Добавляет ветки репликации в LDAP"""
        if clVars:
            self.clVars = clVars
        #Добавляем служебную ветку
        if not self.addSysDN():
            return False
        #Если ветка репликации не существует добавляем её
        if not self.isReplDNExists():
            ldifFile = self.ldifFileRepl
            baseLdif = self.createLdif(ldifFile)
            if not self.ldapObj.getError():
                self.ldapObj.ldapAdd(baseLdif)
            if self.ldapObj.getError():
                print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
                return False
        # Если ветка Replication/Mail не существует - добавляем ее
        if not self.isReplMailDNExists():
            errorMessage = _("Can not append Replication/Mail branch in LDAP")
            entry = [('objectclass', ['top','organizationalUnit']),
                     ('ou', ['%s' %self.clVars.Get("ld_repl_mail_login")])]
            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())
                self.printERROR(errorMessage)
                return False
            except:
                self.printERROR(errorMessage)
                return False
        return True

    @adminConnectLdap
    def getRelWorkedDN(self):
        """Получаем относительный DN ветки Worked"""
        if not self.relWorkedDN:
            sysLogin = self.clVars.Get("ld_ldap_login")
            replLogin = self.clVars.Get("ld_repl_login")
            repWorkedlLogin = self.clVars.Get("ld_repl_worked_login")
            self.relWorkedDN = "ou=%s,ou=%s,ou=%s,%s" %(repWorkedlLogin,\
            replLogin,sysLogin,self.ServicesDN)
        return self.relWorkedDN

    @adminConnectLdap
    def getRelMailDN(self):
        """Получаем относительный DN ветки Replication/Mail"""
        if not self.relMailDN:
            sysLogin = self.clVars.Get("ld_ldap_login")
            replLogin = self.clVars.Get("ld_repl_login")
            replMailLogin = self.clVars.Get("ld_repl_mail_login")
            self.relMailDN = "ou=%s,ou=%s,ou=%s,%s" %(replMailLogin,\
            replLogin,sysLogin,self.ServicesDN)
        return self.relMailDN

    def searchWorkedUser(self,userName):
        """Находит пользователя в ветке Worked"""
        relWorkedDN = self.getRelWorkedDN()
        resSearch = self.searchLdapDN(userName, relWorkedDN, "uid")
        return resSearch

    def searchMailAlias(self,userName):
        """Находит alias пользователя в ветке Replication/Mail"""
        relMailDN = self.getRelMailDN()
        resSearch = self.searchLdapDN(userName, relMailDN, "cn")
        return resSearch

    @adminConnectLdap
    def delReplWorkedUser(self, userName):
        """Удаляет пользователя из ветки Worked"""
        if self.searchWorkedUser(userName):
            relWorkedDN = self.getRelWorkedDN()
            delDN = self.addDN("uid=" + userName, relWorkedDN)
            if not self.delDN(delDN):
                return False
        return True

    @adminConnectLdap
    def delReplMailAlias(self, userName):
        """Удаляет почтовый алиас"""
        rez = self.searchMailAlias(userName)
        if rez:
            relMailDN = self.getRelMailDN()
            delDN = self.addDN("cn=" + userName, relMailDN)
            if not self.delDN(delDN):
                return False
        return True

    @adminConnectLdap
    def renameReplMailAlias(self, oldName, newName):
        """Изменяем название алиаса в Replication/Mail"""
        rez = self.searchMailAlias(oldName)
        if not rez:
            return True
        email = rez[0][0][1]["rfc822member"][0]
        splEmail = email.split("@")
        attrAppend = []
        relMailDN = self.getRelMailDN()
        oldDN = self.addDN("cn=" + oldName, relMailDN)
        if len(splEmail)==2:
            emailDomen = splEmail[1]
            newEmail = "%s@%s" %(newName,emailDomen)
            attrAppend.append((ldap.MOD_REPLACE, 'rfc822member', newEmail))
            attrAppend.append((ldap.MOD_REPLACE, 'mailMessageStore',
                            newName + "/"))
            if not self.modAttrsDN(oldDN, attrAppend):
                return False
        newFirstDn = "cn=" + newName
        res = self.modifyElemDN(oldDN, newFirstDn)
        if not res:
            return False
        return True

    @adminConnectLdap
    def deleteHideHosts(self, aliasName):
        """Удаляет свойство алиаса фильтр хостов"""
        rez = self.searchMailAlias(aliasName)
        if not rez:
            return True
        if rez[0][0][1].has_key('filtersender'):
            attrDelete = []
            relMailDN = self.getRelMailDN()
            aliasDN = self.addDN("cn=%s"%aliasName, relMailDN)
            attrDelete.append((ldap.MOD_DELETE, 'filtersender', None))
            if not self.modAttrsDN(aliasDN, attrDelete):
                return False
        return True

    @adminConnectLdap
    def modReplMailAlias(self, userName, srcMails, filterHosts=[]):
        """Изменяем запись в Replication/Mail 

        (имя пользователя, список почтовых адресов пользователя"""
        rez = self.searchMailAlias(userName)
        if not rez:
            # Если алиас не найден создаем его
            return self.addReplMailAlias(userName, srcMails, filterHosts)
        mailHost = self.clVars.Get('sr_mail_host')
        if not mailHost:
            hostName = self.clVars.Get('os_net_hostname')
            domain = self.clVars.Get('os_net_domain')
            fullHostName = "%s.%s"%(hostName,domain)
            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))
        if userMails:
            # Внешний почтовый адрес пользователя (первый в списке)
            userMail = userMails[0]
            # Убираем первый адрес из списка
            userMails = list(set(filter(lambda x: x != userMail,
                                        userMails)))
            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)
                for host in fHosts:
                    attrAppend.append((ldap.MOD_ADD, 'filtersender', host))
                if rez[0][0][1].has_key('filtersender'):
                    attrDelete.append((ldap.MOD_DELETE, 'filtersender', None))
            email = rez[0][0][1]["mail"][0]
            altEmails = rez[0][0][1]["mailAlternateAddress"]
            # Удаляем альтернативные адреса, кроме первого
            for altEmail in altEmails:
                if email != altEmail:
                    attrDelete.append(
                                (ldap.MOD_DELETE, 'mailAlternateAddress',
                                 altEmail))
            # Заменяем первый адрес
            attrReplace.append((ldap.MOD_REPLACE, 'mail',userMail))
            attrReplace.append((ldap.MOD_REPLACE, 'mailAlternateAddress',
                                userMail))
            relMailDN = self.getRelMailDN()
            aliasDN = self.addDN("cn=%s"%userName,relMailDN)
            # Добавляем альтернативные адреса
            for mail in userMails:
                attrAppend.append((ldap.MOD_ADD, 'mailAlternateAddress',
                                    mail))
            modAttrs = attrDelete + attrReplace + attrAppend
            if not self.modAttrsDN(aliasDN, modAttrs):
                return False
        else:
            relMailDN = self.getRelMailDN()
            aliasDN = self.addDN("cn=%s"%userName,relMailDN)
            # Удаляем почтовый алиас
            if not self.delDN(aliasDN):
                return False
        return True

    @adminConnectLdap
    def addReplMailAlias(self, userName, srcMails , filterHosts=[]):
        """Добавляем запись в Replication/Mail 

        (имя пользователя, список почтовых адресов пользователя"""
        rez = self.searchMailAlias(userName)
        if not rez:
            ldifFile = self.ldifFileMailUser
            self.clVars.Set("ur_name", userName)
            mailHost = self.clVars.Get('sr_mail_host')
            if not mailHost:
                hostName = self.clVars.Get('os_net_hostname')
                domain = self.clVars.Get('os_net_domain')
                fullHostName = "%s.%s"%(hostName,domain)
                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))
            if userMails:
                 # Внешний почтовый адрес пользователя (первый в списке)
                userMail = userMails[0]
                # Убираем первый адрес из списка
                userMails = list(set(filter(lambda x: x != userMail,
                                            userMails)))
                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()
                    return False
                modAttrs = []
                relMailDN = self.getRelMailDN()
                aliasDN = self.addDN("cn=%s"%userName,relMailDN)
                for mail in userMails:
                    modAttrs.append((ldap.MOD_ADD, 'mailAlternateAddress',
                                     mail))
                if filterHosts:
                    domain = self.clVars.Get('os_net_domain')
                    # Если необходимо добавляем домен к именам хостов
                    fHosts = map(lambda x: (not '.' in x and x+"."+domain) or x,
                                 filterHosts)
                    for host in fHosts:
                        modAttrs.append((ldap.MOD_ADD, 'filtersender',
                                        host))
                res = self.modAttrsDN(aliasDN, modAttrs)
                # Если ошибка то удаляем почтовый алиас
                if not res:
                    self.delReplMailAlias(userName)
                    return False
        return True


    @adminConnectLdap
    def addReplWorkedUser(self, userName):
        """Добавляем запись в Worked ветку (uid, имя сервера)"""
        rez = self.searchWorkedUser(userName)
        if not rez:
            ldifFile = self.ldifFileWorkedUser
            self.clVars.Set("ur_name", userName)
            baseLdif = self.createLdif(ldifFile)
            if not self.ldapObj.getError():
                self.ldapObj.ldapAdd(baseLdif)
            if self.ldapObj.getError():
                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")
            return False
        if rez:
            host = rez[0][0][1]['host'][0]
            if host != replHost:
                # Изменяемые аттрибуты
                modAttrs = [(ldap.MOD_REPLACE, 'host', replHost)]
                relWorkedDN = self.getRelWorkedDN()
                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
            return False
        return True

    @adminConnectLdap
    def addUserReplServer(self, options, logObj=False):
        verboseMode = True
        errMessage = ""
        errorFlag = False
        # Опция выключает вывод cообщений на экран
        if options.has_key('s'):
            verboseMode = False
        login = ""
        # Если нет логина пользователя - ошибка
        if not options.has_key('l'):
            errorFlag = True
            errMessage = _("command line option '-l, --login' is not set")
        else:
            login = options['l']
        # Проверка установку сервиса LDAP
        if not errorFlag and self.clVars.Get("sr_ldap_set") != "on":
            errorFlag = True
            errMessage = _("LDAP service not setuped")
        # Проверка на установку samba
        if not errorFlag and self.clVars.Get("sr_samba_set") != "on":
            errorFlag = True
            errMessage = _("Samba service not setuped")
        # Проверка на включение репликации
        if not errorFlag and self.clVars.Get("ld_repl_set") != "on":
            errorFlag = True
            errMessage = _("Replication off")
        flagLogOut = False
        retStr = ""
        if not errorFlag:
            if self.servSambaObj.searchSambaUser(login):
                if self.isLoginUser(login):
                    if not self.createUserDirs(login):
                        errorFlag = True
                        errMessage = \
                            _("Can not create user %s directories")%str(login)
                else:
                    flagLogOut = True
                    # Удаляем файл .logout
                    logoutFile =\
                          os.path.join(self.clVars.Get("sr_samba_linprof_path"),
                                       login,self.logOutFile)
                    retStr = self.deleteLogoutFile(login, logoutFile)
                    if not retStr:
                        errorFlag = True
                        errMessage = \
                            _("No access to the file %s")%logoutFile
                    if retStr == "SUCCESS":
                        # Добавляем пользователя в ветку репликации
                        if not self.addReplWorkedUser(login):
                            errorFlag = True
                            errMessage = _("Can not add user %s in LDAP branch \
'Replication'")%str(login)
            else:
                errorFlag = True
                errMessage = _("Samba user %s is not found")%str(login)
        if errorFlag:
            if errMessage:
                if verboseMode:
                    self.printERROR(errMessage)
                if logObj:
                    logObj.writeError(errMessage)
            return False
        messages = ""
        if flagLogOut:
            messages += _("User %s logout")%login + " %s"%retStr
        else:
            messages += _("User %s login")%login
        if verboseMode:
            self.printSUCCESS(messages)
        if logObj:
            logObj.writeSuccess(messages)
        return True

    def genReplServers(self, replServers, hostName, fullHostName):
        """Находим текущий сервер в серверах репликации
        и удаляем его из списка, так же удаляются одинаковые названия"""
        replServersList = list(set(replServers))
        lenRelpServers = len(replServersList)
        i=0
        while(i<lenRelpServers):
            replServer = replServersList[i]
            elemReplServer = replServer.split(".")
            if len(elemReplServer)==1:
                if replServer == hostName or not replServer.strip():
                    replServersList.remove(replServer)
                    lenRelpServers -= 1
                else:
                    i+=1
            else:
                if replServer == fullHostName:
                    replServersList.remove(fullHostName)
                    lenRelpServers -= 1
                else:
                    i+=1
        return replServersList


    def deleteNotFoundUserData(self, options, logObj=False):
        """Удаляет пользовательские данные если пользователь не найден

        Используется для крона
        """
        if logObj:
            logObj.writeSuccess(_("start script"))
        # Cоздаем объект переменные
        self.createClVars()
        # Проверим установлен ли сервис unix
        if not self.isServiceSetup("unix", False):
            errMessage = _("Service %s is not installed")%"unix" + " ..."
            if logObj:
                logObj.writeError(errMessage)
            self.printERROR(errMessage)
            return False
        # Проверяем соединение с LDAP
        if not self.servUnixObj.getLdapObjInFile():
            errMessage = _("Can not connect Unix service to LDAP server")
            if logObj:
                logObj.writeError(errMessage)
            self.printERROR(errMessage)
            return False
                #logObj.writeSuccess(messages)
                #logObj.writeError(errMessage)
        # Пути в которых есть данные пользователей
        foundPaths = [self.clVars.Get("sr_samba_winprof_path"),
                      self.clVars.Get("sr_samba_linprof_path"),
                      self.clVars.Get("sr_samba_home_path"),
                      self.clVars.Get("sr_samba_winlogon_path"),
                      self.clVars.Get("sr_mail_path"),
                      os.path.join(self.clVars.Get("sr_ftp_path"), "pub/users")]
        pathProg = os.getcwd()
        flagError = False
        for path in foundPaths:
            if os.path.isdir(path):
                os.chdir(path)
                users = os.listdir(".")
                users = filter(lambda x: os.path.isdir(x), users)
                for userName in users:
                    if not self.servUnixObj.searchUnixUser(userName) and\
                        not self.servUnixObj.searchPasswdUser(userName):
                            # Удаляем пользователя из ветки Worked
                            if not self.delReplWorkedUser(userName):
                                errMessage = _("Can not remove user %s \
in the LDAP branch 'Worked'")%userName
                                if logObj:
                                    logObj.writeError(errMessage)
                                self.printERROR(errMessage)
                                flagError = True
                                break
                            # Удаляем директорию пользователя
                            self.removeDir(userName)
                            message = _("deleted %s")\
                                %os.path.join(path,userName)
                            if logObj:
                                logObj.writeSuccess(message)
                            self.printWARNING(message)
                            # Удаляем пользователя из почтовой ветки
                            if self.isServiceSetup("mail") and\
                                self.servMailObj.searchMailUser(userName):
                                if self.servMailObj.delUserMailServer(\
                                    userName,{"r":""},False):
                                    message = _("deleted mail user %s")%userName
                                    if logObj:
                                        logObj.writeSuccess(message)
                                    self.printWARNING(message)
                                else:
                                    errMessage = _("Can not delete mail user \
%s")%userName
                                    if logObj:
                                        logObj.writeError(errMessage)
                                    self.printERROR(errMessage)
                                    flagError = True
                                    break
                            # Удаляем пользователя из Jabber
                            if self.isServiceSetup("jabber") and\
                                self.servJabberObj.searchUserToName(userName):
                                if self.servJabberObj.delUserJabberServer(\
                                                           userName, {}, False):
                                    message = _("deleted jabber user %s")\
                                                %userName
                                    if logObj:
                                        logObj.writeSuccess(message)
                                    self.printWARNING(message)
                                else:
                                    errMessage = _("Can not delete jabber user \
%s")%userName
                                    if logObj:
                                        logObj.writeError(errMessage)
                                    self.printERROR(errMessage)
                                    flagError = True
                                    break
        if os.path.exists(pathProg):
            os.chdir(pathProg)
        if flagError:
            return False
        else:
            if logObj:
                logObj.writeSuccess(_("end script ... [ok]"))
        return True

    def cronReplicationON(self):
        """Включаем выполнение скрипта крона - replcron, для репликации"""
        # Очищаем crontab (для совместимости с предыдущей версией)
        if not self.crontabClear():
            return False
        cronWeeklyFile = os.path.join("/etc/cron.weekly",self.replCronFile)
        # Предупреждение
        warning = _("Please do not delete this file, it was created \
calculate-server")
        # содержимое файла запускающегося по крону
        replCronFileContent = "#!/bin/bash\n# %s\n%s\n"\
            %(warning, os.path.join("/usr/bin",self.replCronFile))
        if os.path.exists(cronWeeklyFile):
            try:
                FD = open(cronWeeklyFile,"w")
                FD.write(replCronFileContent)
                FD.close()
            except:
                self.printERROR(_("Can not write %s")%cronWeeklyFile)
                return False
            return True
       
        if not self.createUserFile(cronWeeklyFile, replCronFileContent,
                                   0, 0, 0744):
            return False
        return True

    def cronReplicationOFF(self):
        """Отключаем выполнение скрипта крона - replcron, для репликации"""
        # Очищаем crontab (для совместимости с предыдущей версией)
        if not self.crontabClear():
            return False
        cronWeeklyFile = os.path.join("/etc/cron.weekly",self.replCronFile)
        if os.path.exists(cronWeeklyFile):
            # Удаляем файл из /etc/cron.weekly
            try:
                os.remove(cronWeeklyFile)
            except:
                self.printERROR(_("Can not delete %s") %cronWeeklyFile)
                return False
        return True

    def crontabClear(self):
        """Отключает в crontab обработку файла replcron"""
        replCronFile = os.path.join("/usr/bin",self.replCronFile)
        fileNameCron = tempfile.mktemp(".cron")
        listCronLines = self.execProg("crontab -l",False,False)
        # Удаляем из элементов переводы строк
        listCronLinesSrc = map(lambda x: x.split('\n')[0],listCronLines)
        # Удаляем из элементов все начиная с #
        listCronLines = map(lambda x: x.split("#")[0].strip(), listCronLinesSrc)
        listCronLinesOut = []
        i = 0
        for textCron in listCronLines:
            if not textCron.strip():
                i +=1
                continue
            elemLine=re.split(\
                "[^\t ]+\s+[^\t ]+\s+[^\t ]+\s+[^\t ]+\s+[^\t ]+\s+" ,textCron)
            if len(elemLine) == 2 and elemLine[1] == replCronFile:
                i +=1
                continue
            listCronLinesOut.append(listCronLinesSrc[i])
            i += 1
        if not os.path.exists("/var/spool/cron/crontabs/root"):
            return True
        if listCronLinesOut:
            self.createUserFile(fileNameCron,
                                "\n".join(listCronLinesOut)+"\n",
                                0,0)
        else:
            self.createUserFile(fileNameCron,
                                "\n",
                                0,0)
        textLine = self.execProg("crontab %s"%fileNameCron)
        if not (textLine == None):
            self.printERROR(_("Can not add crontab file"))
            if os.path.exists(fileNameCron):
                os.remove(fileNameCron)
            return False
        if os.path.exists(fileNameCron):
                os.remove(fileNameCron)
        return True

    def supportReplOpenldap(self, clVars):
        """Определяем поддерживает ли openldap репликацию"""
        clProf = cl_profile.profile(clVars)
        openLdapVesion = clProf.applyFuncProfile("#-pkg(openldap)-#","","")
        vesionInst, versionComp = clProf._convertVers(openLdapVesion, "2.4")
        if vesionInst <= versionComp:
            self.printERROR(_("openldap-%s does not support replication, \
use the new version. (openldap > 2.4)")%openLdapVesion)
            return False
        return True

    @adminConnectLdap
    def getUsersMail(self):
        """Находит пользователей в Mail сервисе

        Вывод  список [(имя пользователя, [почтовые адреса пользователя])...)]
        """
        # Проверим установлен ли сервис Mail
        if not self.isServiceSetup("mail"):
            return False
        # ищем пользователей в ветке Mail
        resSearch = self.searchLdapDN("*", self.servMailObj.relUsersDN,
                                      "mailAlternateAddress",
                                      ["uid","mailAlternateAddress"])
        if not resSearch:
            return False
        listUserMail = []
        for i in resSearch:
            listUserMail.append((i[0][1]["uid"][0],
                                i[0][1]["mailAlternateAddress"]))
        return listUserMail

    @adminConnectLdap
    def getGroupsMail(self):
        """Находит группы в Mail сервисе

        Вывод  список [(группа, [почтовые адреса группы],[невидимые хосты])...)]
        """
        # Проверим установлен ли сервис Mail
        if not self.isServiceSetup("mail"):
            return False
        # ищем группы в ветке Mail
        resSearch = self.searchLdapDN("*", self.servMailObj.relGroupsDN,
                                      "mailAlternateAddress",
                                      ["cn","mailAlternateAddress",
                                        "filtersender"])
        if not resSearch:
            return False
        listGroupMail = []
        for i in resSearch:
            if i[0][1].has_key('filtersender'):
                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"],[]))
        return listGroupMail

    def setupReplServer(self, options, service):
        """Начальная настройка репликации"""
        # Cоздаем объект переменные
        self.createClVars()
        # Определяем поддерживает ли openldap репликацию
        if not self.supportReplOpenldap(self.clVars):
            return False
        if options.has_key('off'):
            if self.clVars.Get("ld_repl_set") == "off":
                self.printWARNING(_("Replication off for all services"))
                return True
            elif service == "unix" and\
                self.clVars.Get("ld_repl_unix_set") == "off":
                self.printWARNING(_("Replication off for service %s")%"Unix")
                return True
            elif service == "samba" and\
                self.clVars.Get("ld_repl_samba_set") == "off":
                self.printWARNING(_("Replication off for service %s")%"Samba")
                return True
            elif service == "mail" and\
                self.clVars.Get("ld_repl_mail_set") == "off":
                self.printWARNING(_("Replication off for service %s")%"Mail")
                return True
            self.printWARNING(_("Undo can be achieved by executing a command"))
            self.printWARNING(_("when the backup was created on this server \
'cl-rebuild',"))
            self.printWARNING(_("if taken from another server \
'cl-rebuild --repl'"))
            bFile = self.servLdapObj.getArchFile()
            if not bFile:
                return Falses
            archFileTime = time.localtime(os.stat(bFile)[stat.ST_MTIME])
            timeFile = datetime.datetime(archFileTime[0],archFileTime[1],
                                        archFileTime[2],archFileTime[3],
                                        archFileTime[4],archFileTime[5])
            localTime = time.localtime()
            timeLocal = datetime.datetime(localTime[0],localTime[1],
                                        localTime[2],localTime[3],
                                        localTime[4],localTime[5])
            if timeLocal < timeFile:
                self.printERROR(_("Incorrect system time or time create \
file %s")%bFile)
                return False
            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
                hours = _("hours")
                minutes = _("minutes")
                seconds = _("seconds")
                if dHours:
                    timeBackup = "%s %s %s %s %s %s"%\
                                (dHours,hours,dMinutes,minutes,dSeconds,seconds)
                elif dMinutes:
                    timeBackup = "%s %s %s %s"%(dMinutes,minutes,dSeconds,\
                                                seconds)
                elif dSeconds:
                    timeBackup = "%s %s"%(dSeconds,seconds)
                self.printWARNING(_("The backup file is created %s ago")\
                                  %timeBackup)
            else:
                self.printWARNING(_("The backup file is created %s days ago")\
                                %deltaTime.days)
            self.printWARNING(_("If the backup is obsolete, use cl-backup."))
            messDialog = \
                _("If you are ready to continue executing the program")+", "+\
                _("input 'yes'") +", "+ _("if not 'no'")
            if not self.dialogYesNo(messDialog):
                return True
        # Удаляем переменную из /var/calculate.calculate.env
        self.clVars.Delete("ld_repl_ids","local","server")
        # Cоздаем объект переменные
        self.createClVars()
        # Записываем что репликация отключена
        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']):
            self.printERROR(\
                _("Not specified replication servers \
(command line option '-r')") + " ...")
            return False
        if options.has_key('off') and options.has_key('r'):
            self.printERROR(\
                _("You can not use the option to '--off', \
together with option '-r'") + " ...")
            return False
        replServers = []
        if options.has_key('r'):
            replServers = options['r'].split(',')
            # Преобразуем короткие имена в длинные
            hostName = self.clVars.Get('os_net_hostname')
            domain = self.clVars.Get('os_net_domain')
            replServers = self.chortToFullName(replServers, domain)
            fullHostName = "%s.%s"%(hostName,domain)
            # Удаляем похожие сервера и текущий сервер из списка
            replServers = self.genReplServers(replServers, hostName,
                                              fullHostName)
            # Если серверы отсуствуют - ошибка
            if not replServers:
                self.printERROR(\
                _("Not a valid list of servers replication") + " ...")
                return False
            # Добавляем текущий сервер в серверы репликации
            replServers.insert(0,fullHostName)
        # В случае если сервер установлен
        if self.clVars.Get("sr_ldap_set") != "on":
            self.printERROR(\
                _("Set Replication error, LDAP service not setuped") + " ...")
            return False
        if service == "unix":
            if self.clVars.Get("sr_unix_set") != "on":
                self.printERROR(\
                 _("Set Replication error, Unix service not setuped") + " ...")
                return False
            if options.has_key('r'):
                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()))
                # Все серверы репликации
                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])
                # Устанавливаем переменную серверы репл. для 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'):
                # Выключаем репликацию для сервисов Samba и Mail
                if self.clVars.Get("ld_repl_mail_set") == "on" and\
                    self.clVars.Get("ld_repl_mail_servers"):
                    self.clVars.Set("ld_repl_set", "on", True)
                     # Устанавливаем переменную серверы репл. для всех сервисов
                    self.clVars.Set("ld_repl_servers",
                                self.clVars.Get("ld_repl_mail_servers"),True)
                else:
                    self.clVars.Set("ld_repl_set", "off", True)
                    self.clVars.Delete("ld_repl_mail_servers","local","server")
                self.clVars.Set("ld_repl_samba_set", "off", True)
                self.clVars.Set("ld_repl_unix_set", "off", True)
                self.clVars.Set("ld_repl_unix_servers", "", True)
                self.clVars.Set("ld_repl_samba_servers", "", True)
                self.clVars.Delete("ld_repl_unix_servers","local","server")
                self.clVars.Delete("ld_repl_samba_servers","local","server")
        elif service == "samba":
            if self.clVars.Get("sr_samba_set") != "on":
                self.printERROR(\
                 _("Set Replication error, Samba service not setuped") + " ...")
                return False
            replUnixServers = self.clVars.Get("ld_repl_unix_servers")
            if replUnixServers:
                replUnixServers = replUnixServers.split(",")
            if options.has_key('off'):
                # Очищаем cерверы репликации Samba
                self.clVars.Set("ld_repl_samba_servers", "", True)
                self.clVars.Delete("ld_repl_samba_servers","local","server")
                replServers = []
            replSambaServers = self.clVars.Get("ld_repl_samba_servers")
            if replSambaServers:
                replSambaServers = replSambaServers.split(",")
            replMailServers = self.clVars.Get("ld_repl_mail_servers")
            # Находим разницу между серверами Samba и Unix
            diffReplServers = list(set(replSambaServers)^set(replUnixServers))
            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()))
            # Все серверы репликации
            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])
            # Серверы репликации для ветки Samba
            replSambaServers = list(reduce(lambda x,y: ('',x[1]|y[1]),
                                   filter(lambda x: x[0] in ['samba'],
                                          listServersRepl),("",set()))[1])
            # Устанавливаем переменную серверы репл. для Samba сервиса
            self.clVars.Set("ld_repl_samba_servers",
                            ",".join(replSambaServers),True)
             # Устанавливаем переменную серверы репл. для Unix сервиса
            self.clVars.Set("ld_repl_unix_servers",
                            ",".join(replUnixServers),True)
            # Устанавливаем переменную серверы репл. для всех сервисов
            self.clVars.Set("ld_repl_servers",
                            ",".join(replAllServers),True)
            if not self.clVars.Get("ld_repl_id"):
                # Вылючаем репликацию
                self.clVars.Set("ld_repl_set", "off")
        elif service == "mail":
            if self.clVars.Get("sr_mail_set") != "on":
                self.printERROR(\
                 _("Set Replication error, Mail service not setuped") + " ...")
                return False
            replUnixServers = self.clVars.Get("ld_repl_unix_servers")
            if options.has_key('off'):
                # Очищаем cерверы репликации Mail
                self.clVars.Set("ld_repl_mail_servers", "", True)
                self.clVars.Delete("ld_repl_mail_servers","local","server")
                replServers = []
            replSambaServers = self.clVars.Get("ld_repl_samba_servers")
            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()))
            # Все серверы репликации
            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])
            # Устанавливаем переменную серверы репл. для Mail сервиса
            self.clVars.Set("ld_repl_mail_servers",
                            ",".join(replMailServers),True)
            # Устанавливаем переменную серверы репл. для всех сервисов
            self.clVars.Set("ld_repl_servers",
                            ",".join(replAllServers),True)
            if not self.clVars.Get("ld_repl_id"):
                # Вылючаем репликацию
                self.clVars.Set("ld_repl_set", "off")
        else:
            self.printERROR(\
          _("incorrect service '%s' in method setupReplServer")%service+" ...")
            return False
        # Проверим запущен ли ldap
        if not self.getRunService("ldap"):
            # Запускаем LDAP сервер
            if not self.runLdapServer():
                return False
        #Cоединение с Ldap (администратор)
        if not shareLdap.getLdapObjInFile(self):
            return False
        if options.has_key('r'):
            # Проверяем существует ли id текущего сервера
            if not self.clVars.Get("ld_repl_id"):
                self.printERROR(_("Not found 'serverID' this server") + " ...")
                self.printERROR(_("variable 'ld_repl_id' empty") + " ...")
                return False
        # Делаем update cервиса Samba в случае опции off и не показываем
        # реплицируемые серверы
        if service == "unix" and self.clVars.Get("sr_samba_set") == "on" and\
            options.has_key('off'):
            if not self.servLdapObj.updateServer({},"samba",self.clVars,
                                                  [],False):
                return False
        # Делаем update сервиса если нет ветки репликации она создается
        if not self.servLdapObj.updateServer({},service,self.clVars):
            return False
        if self.clVars.Get("ld_repl_set") != "on":
            # Удаляем переменные
            self.clVars.Delete("ld_repl_servers","local","server")
            self.clVars.Delete("ld_repl_samba_servers","local","server")
            self.clVars.Delete("ld_repl_mail_servers","local","server")
            self.clVars.Delete("ld_repl_unix_servers","local","server")
            self.clVars.Delete("ld_repl_pw")
            self.clVars.Delete("ld_repl_set")
            self.printOK(_("Replication off for all services") + " ...")
            return True
        #запишем переменные для сервера
        # в /etc/calculate.env
        self.clVars.Write("ld_repl_pw",
                          self.clVars.Get("ld_repl_pw"),True)
        # в /var/calculate/calculate.env
        if service == "unix":
            self.clVars.Write("ld_repl_unix_servers",
                          self.clVars.Get("ld_repl_unix_servers"),
                          True,"local")
        elif service == "samba":
            self.clVars.Write("ld_repl_unix_servers",
                          self.clVars.Get("ld_repl_unix_servers"),
                          True,"local")
            smbServers = self.clVars.Get("ld_repl_samba_servers")
            if smbServers:
                self.clVars.Write("ld_repl_samba_servers", smbServers,
                                  True, "local")
        elif service == "mail":
            # Cчитаем почтовых пользователей и заполним ветку алиасов
            # Переподсоединяемся к LDAP
            self.ldapObj = False
            # Получаем почтовых пользователей
            usersMail = self.getUsersMail()
            # Получаем почтовые группы
            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]),[]))
            if usersAndGroupsMail:
                flagError = False
                for name, mails, hosts in usersAndGroupsMail:
                    if self.searchMailAlias(name):
                        if not self.modReplMailAlias(name, mails, hosts):
                            flagError = True
                            break
                    else:
                        if not self.addReplMailAlias(name, mails, hosts):
                            flagError = True
                            break
                if flagError:
                    self.printERROR(_("Can not set replication mail alias,") +\
                                    " " + _("for name %s")%name + " " +\
                                    "(%s)"%", ".join(mails) + " ...")
                    return False
            mailServers = self.clVars.Get("ld_repl_mail_servers")
            if mailServers:
                self.clVars.Write("ld_repl_mail_servers", mailServers,
                                  True, "local")
        # Серверы репликации
        self.clVars.Write("ld_repl_servers",
                          self.clVars.Get("ld_repl_servers"),
                          True,"local")
        # Id серверов репликации
        self.clVars.Write("ld_repl_ids",
                          self.clVars.Get("ld_repl_ids"),
                          True,"local")
        ldapParser = iniLdapParser()
        ldapParser.setVar("replication",
                          {"DN":self.clVars.Get("ld_repl_dn"),
                           "PASS":self.clVars.Get("ld_repl_pw")})
        #Записываем что репликация включена
        self.clVars.Write("ld_repl_set", "on")
        self.printOK(_("Replication setuped") + " ...")
        return True

class cl_info(cl_utils2.cl_smartcon):
    """Класс для вывода информации"""

    def getInfoServer(self, options, service):
        """Выводит на печать информацию"""
        strService = service.capitalize()
        if service == "ftp":
            strService = service.upper()
        # Информация о компьютере
        if options.has_key("M"):
            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
        # Информация о пользователе
        elif options.has_key("U"):
            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
        # Информация о группе
        elif options.has_key("G"):
            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

         # Информация о компьютерах
        elif options.has_key("m"):
            fields = "short"
            if options.has_key("full"):
                fields = "full"
            data = self.getAllMachines(fields, service)
            if not data:
                return False
            headerList, dataList = data
            title=_("All machines in LDAP for service %s")%strService
        # Информация о пользователях
        elif options.has_key("u"):
            fields = "short"
            if options.has_key("full"):
                fields = "full"
            data = self.getAllUsers(fields, service)
            if not data:
                return False
            headerList, dataList = data
            title=_("All users in LDAP for service %s")%strService
        # Информация о группах
        elif options.has_key("g"):
            fields = "short"
            if options.has_key("full"):
                fields = "full"
            data = self.getAllGroups(fields, service)
            if not data:
                return False
            headerList, dataList = data
            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"):
            repObj = report(title, headerList, dataList)
            repObj.printReport()
            #print users
            return True

        if len(options) == 1 and options.has_key("full"):
  
            self.printERROR(_("Can not use a single command line option \
'full'."))
            self.printERROR(_("This option should be used in conjunction \
with another option."))
            self.printWARNING(_("Example"))
            self.printWARNING("  cl-info -u -full %s" %service)
        return False

    def getQueryLDAP(self, service, branch, searchAttr, searchStr,
                     retrAttrs=None, returnClVars=False):
        """Выдает данные из LDAP"""
        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)
            return False
        relAttr = branchData[branch]
        try:
            exec ("servObj=serv%s()" %service.capitalize())
        except:
            self.printERROR(\
                _("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)
            return False
        searchRes = servObj.searchLdapDN(searchStr, getattr(servObj, relAttr), 
                                         searchAttr, retrAttrs)
        if returnClVars:
            return (servObj.clVars, searchRes)
        return searchRes


    def getMachine(self, machineName, service):
        """Информация о компьютере"""
        searchAttr = "uid"
        machName = machineName.split("$")
        machName = "".join(machName)
        machName += "$"
        searchStr = machName
        data, delData = self.genDataMachines(service)
        if not data:
            self.printERROR(_("Incorrect service %s") %service.capitalize())
            return False
        headers = [_("Field"),_("Value")]
        attributes = map(lambda x: x[0], data)
        retrAttrs = map(lambda x: x[1], data)
        retClVars=False
        searchRes = self.getQueryLDAP(service, "computers", searchAttr,
                                      searchStr, retrAttrs)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        data = []
        lenRetrAttrs = len(retrAttrs)
        for info in searchRes:
            for i in range(lenRetrAttrs):
                attr = retrAttrs[i]
                attrName = attributes[i]
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    # Изменяем значения аттрибутов для вывода на печать
                    serviceMod = service
                    if service == "samba":
                        serviceMod = "unix"
                    ldapValue[0] = self.modUserAttr(attr, ldapValue[0],
                                                    serviceMod)
                    flagFirst = False
                    for value in ldapValue:
                        if not flagFirst: 
                            data.append((attrName, value))
                            flagFirst = True
                        else:
                            data.append(("", value))
                else:
                    data.append((attrName, _("No")))
        return (headers, data)

    def getGroup(self, groupName, service):
        """Информация о группе"""
        searchAttr = "cn"
        searchStr = groupName
        data, delData = self.genDataGroups(service)
        if not data:
            self.printERROR(_("Incorrect service %s") %service.capitalize())
            return False
        headers = [_("Field"),_("Value")]
        attributes = map(lambda x: x[0], data)
        retrAttrs = map(lambda x: x[1], data)
        retClVars=False
        searchRes = self.getQueryLDAP(service, "groups", searchAttr,
                                      searchStr, retrAttrs)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        if service == "jabber":
            servObj = servJabber()
            resMemberSearch = servObj.searchUsersToGroup(groupName)
            if resMemberSearch:
                memberUid = []
                for dataGroup in resMemberSearch:
                    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 = []
        lenRetrAttrs = len(retrAttrs)
        for info in searchRes:
            for i in range(lenRetrAttrs):
                attr = retrAttrs[i]
                attrName = attributes[i]
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    # Изменяем значения аттрибутов для вывода на печать
                    ldapValue[0] = self.modGroupAttr(attr, ldapValue[0], service)
                    flagFirst = False
                    for value in ldapValue:
                        if not flagFirst: 
                            data.append((attrName, value))
                            flagFirst = True
                        else:
                            data.append(("", value))
                else:
                    data.append((attrName, _("No")))
        return (headers, data)


    def getUser(self, userName, service):
        """Информация о пользователе"""
        searchAttr = "uid"
        searchStr = userName
        data, delData = self.genDataUsers(service)
        if not data:
            self.printERROR(_("Incorrect service %s") %service.capitalize())
            return False
        headers = [_("Field"), _("Value")]
        attributes = map(lambda x: x[0], data)
        retrAttrs = map(lambda x: x[1], data)
        retClVars=False
        if service in ["mail", "samba"]:
            retClVars=True
        searchRes = self.getQueryLDAP(service, "users", searchAttr,
                                      searchStr, retrAttrs, retClVars)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        if service in ["mail", "samba"]:
            clVars, searchRes = searchRes
            if not searchRes:
                return (headers , [])
            # Добавляем директорию хранения писем для сервиса mail
            if service == "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"))
            if service == "samba":
                for i in searchRes:
                    homePath = os.path.join(\
                                           clVars.Get("sr_samba_home_path"),
                                           i[0][1]['uid'][0])
                    if os.path.exists(homePath):
                        i[0][1]['homePath'] = [homePath]
                        data.append((_("Home directory"),"homePath"))
                    sharePath = clVars.Get("sr_samba_share_path")
                    if os.path.exists(sharePath):
                        i[0][1]['sharePath'] = [sharePath]
                        data.append((_("Share directory"),"sharePath"))
                    linProfPath = os.path.join(\
                                           clVars.Get("sr_samba_linprof_path"),
                                           i[0][1]['uid'][0])
                    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])
                    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])
                    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)

        data = []
        lenRetrAttrs = len(retrAttrs)
        for info in searchRes:
            for i in range(lenRetrAttrs):
                attr = retrAttrs[i]
                attrName = attributes[i]
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    # Изменяем значения аттрибутов для вывода на печать
                    ldapValue[0] = self.modUserAttr(attr, ldapValue[0], service)
                    flagFirst = False
                    for value in ldapValue:
                        if not flagFirst: 
                            data.append((attrName, value))
                            flagFirst = True
                        else:
                            data.append(("", value))
                    if (service == "unix" and attr == "gidNumber") or\
                       (service == "mail" and attr == "mailAlternateAddress"):
                        memberGroups = self._getUserMemberGroups(userName,
                                                                 service)
                        attrApp = _("Supplementary groups")
                        if service == "unix":
                            memberGroups.insert(0,value)
                        elif service == "mail":
                            attrApp = _("Group mail")
                        flagFirst = False
                        for value in memberGroups:
                            if not flagFirst: 
                                data.append((attrApp, value))
                                flagFirst = True
                            else:
                                data.append(("", value))
                else:
                    data.append((attrName, _("No")))
        return (headers, data)

    def getAllMachines(self, fields, service):
        """Выдает список компьютеров"""
        searchAttr = "uid"
        searchStr = "*"
        data, delData = self.genDataMachines(service, fields)
        if not data:
            self.printWARNING(_("Service %s has no machines")\
                              %service.capitalize())
            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)
        machines = []
        searchRes = self.getQueryLDAP(service, "computers", searchAttr,
                                      searchStr, retrAttrs)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        for info in searchRes:
            listAttr = []
            for attr in retrAttrs:
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    # Изменяем значения аттрибутов для вывода на печать
                    serviceMod = service
                    if service == "samba":
                        serviceMod = "unix"
                    ldapValue[0] = self.modUserAttr(attr, ldapValue[0],
                                                    serviceMod)
                    # Если несколько значений то разделяем их запятыми
                    value = reduce(lambda x,y: ",".join([x,y])[0] == "," and\
                                   ",".join([x,y])[1:] or ",".join([x,y])[1:]\
                                   and ",".join([x,y]) , ldapValue, "")
                    listAttr.append(value)
                else:
                    listAttr.append(_("No"))
            machines.append(listAttr)
        return (headers, machines)

    def getAllGroups(self, fields, service):
        """Выдает список всех групп и пользователей"""
        searchAttr = "cn"
        searchStr = "*"
        data, delData = self.genDataGroups(service, fields)
        if not data:
            self.printWARNING(_("Service %s has no groups")\
                              %service.capitalize())
            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)
        groups = []
        searchRes = self.getQueryLDAP(service, "groups", searchAttr,
                                      searchStr, retrAttrs)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        for info in searchRes:
            listAttr = []
            for attr in retrAttrs:
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    #Если несколько значений то разделяем их запятыми
                    value = reduce(lambda x,y: ",".join([x,y])[0] == "," and\
                                   ",".join([x,y])[1:] or ",".join([x,y])[1:]\
                                   and ",".join([x,y]) , ldapValue, "")
                    listAttr.append(value)
                else:
                    listAttr.append(_("No"))
            groups.append(listAttr)
        return (headers, groups)

    def genDataGroups(self, service, fields='full'):
        """Формирует поля нужные для вывода информации о группе"""
        data = []
        delData = []
        if service == "unix":
            data = [(_("Group"),"cn"),
                    (_("Name"),"description"),
                    ("gid","gidNumber"),
                    (_("Member UID"),"memberUid")]
            if fields == "short":
                delData = [_("Member UID")]
        elif service == "mail":
            data = [(_("Group"),"cn"),
                    (_("Name"),"description"),
                    (_("Mail"),"mail"),
                    (_("Alternate mail"),"mailAlternateAddress"),
                    (_("Member UID"),"rfc822member")]
            if fields == "short":
                delData = [_("Mail"), _("Member UID")]
        elif service == "jabber":
            data = [(_("Group"),"cn"),
                    (_("Comment"),"description")]
        return (data, delData)

    def genDataMachines(self, service, fields='full'):
        """Формирует поля нужные для вывода информации о компьютере"""
        data = []
        delData = []
        if service == "samba":
            data = [(_("ID"),"uidNumber"),
                    (_("Login"),"uid"),
                    (_("Name"),"cn"),
                    (_("Primary group"),"gidNumber"),
                    (_("Home directory"),"homeDirectory"),
                    (_("Password"),"sambaNTPassword"),
                    (_("Last change password"),"sambaPwdLastSet")]
            if fields == "short":
                delData = [_("Name"), _("Home directory"), _("Password"),
                           _("Last change password")]
        return (data, delData)

    def genDataUsers(self, service, fields='full'):
        """Формирует поля нужные для вывода информации о пользователе"""
        data = []
        delData = []
        if service == "unix":
            data = [(_("ID"),"uidNumber"),
                    (_("Login"),"uid"),
                    (_("Name"),"cn"),
                    (_("Lock"),"shadowExpire"),
                    (_("Visible"),"shadowFlag"),
                    (_("Primary group"),"gidNumber"),
                    (_("Home directory"),"homeDirectory"),
                    (_("Password"),"userPassword"),
                    (_("Last change password"),"shadowLastChange"),
                    (_("Jabber ID"),"registeredAddress"),
                    (_("Mail"),"mail")]
            if fields == "short":
                delData = [_("Lock"),_("Visible"),_("Password"),
                           _("Last change password"),_("Jabber ID"),_("Mail")]
        elif service == "samba":
            data = [(_("Login"),"uid"),
                    (_("Name"),"displayName"),
                    (_("Lock"),"accountStatus"),
                    (_("Password"),"sambaNTPassword"),
                    (_("Last change password"),"sambaPwdLastSet")]
            if fields == "short":
                delData = [_("Last change password")]
        elif service == "mail":
            data = [(_("Login"),"uid"),
                    (_("Name"),"cn"),
                    (_("Lock"),"accountStatus"),
                    (_("Password"),"userPassword"),
                    (_("Mail"),"mail"),
                    (_("Alternate mail"),"mailAlternateAddress")]
            if fields == "short":
                delData = [_("Lock"), _("Password"), _("Mail")]
        elif service == "jabber":
            data = [(_("Login"),"uid"),
                    (_("Name"),"cn"),
                    (_("Group"),"departmentNumber"),
                    (_("Jabber ID"),"mail"),
                    (_("Lock"),"initials"),
                    (_("Password"),"userPassword"),
                    ]
            if fields == "short":
                delData = [_("Lock"), _("Group"), _("Password")]
        elif service == "ftp":
            data = [(_("ID"),"uidNumber"),
                    (_("Login"),"uid"),
                    (_("Name"),"cn"),
                    (_("Primary group"),"gidNumber"),
                    (_("Home directory"),"homeDirectory"),
                    (_("Password"),"userPassword")]
            if fields == "short":
                delData = [_("ID"), _("Password"), _("Group")]
        return (data, delData)

    def getAllUsers(self, fields, service):
        """Выдает список login-ов всех пользователей сервиса"""
        searchAttr = "uid"
        searchStr = "*"
        data, delData = self.genDataUsers(service, fields)
        if not data:
            self.printERROR(_("Incorrect service %s") %service.capitalize())
            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)

        loginsUsers = []
        retClVars=False
        if service == "mail":
            retClVars=True
        searchRes = self.getQueryLDAP(service, "users", searchAttr,
                                      searchStr, retrAttrs, retClVars)
        if searchRes == False:
            return False
        if not searchRes:
            return (headers , [])
        if service == "mail":
            clVars, searchRes = searchRes
            if not searchRes:
                return (headers , [])
            # Добавляем директорию хранения писем для сервиса 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"))
            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)
        for info in searchRes:
            listAttr = []
            for attr in retrAttrs:
                if attr in info[0][1]:
                    ldapValue = info[0][1][attr]
                    # Изменяем значения аттрибутов для вывода на печать
                    ldapValue[0] = self.modUserAttr(attr, ldapValue[0], service)
                    # Если несколько значений то разделяем их запятыми
                    value = reduce(lambda x,y: ",".join([x,y])[0] == "," and\
                                   ",".join([x,y])[1:] or ",".join([x,y])[1:]\
                                   and ",".join([x,y]) , ldapValue, "")
                    listAttr.append(value)
                else:
                    listAttr.append(_("No"))
            loginsUsers.append(listAttr)
        return (headers, loginsUsers)

    def modGroupAttr(self, attr, value, service):
        """Модифицирует аттрибуты группы для вывода на печать"""
        retValue = value
        # Заменяем mail на имя пользователя
        if service == "mail" and attr == "rfc822member":
            servObj = servMail()
            searchUser = servObj.searchUserToMail(value)
            if searchUser:
                retValue = searchUser[0][0][1]['uid'][0]
            else:
                retValue = "Not found"
        return retValue

    def modUserAttr(self, attr, value, service):
        """Модифицирует аттрибуты пользователя для вывода на печать"""
        # Конвертируем время в текстовый формат
        retValue = value
        if attr == "shadowLastChange" or\
            attr == "sambaPwdLastSet":
            retValue = self._convDatatoStr(value)
        # Находим имя группы
        elif attr == "gidNumber" and service in ("unix", "ftp"):
            retValue = self._getUserGroupName(value, "unix")
        # Ставим Y в случае выставленного флага
        elif attr == "initials":
            if value == _("No"):
                retValue = _("Yes")
            else:
                retValue = _("No")
        elif attr == "accountStatus":
            if value == "passive":
                retValue = _("Yes")
            else:
                retValue = _("No")
        elif attr == "shadowExpire":
            if value == "1":
                retValue = _("Yes")
            else:
                retValue = _("No")
        elif attr == "sambaAcctFlags":
            if value == "[DU         ]":
                retValue = _("Yes")
            else:
                retValue = _("No")
        elif attr == "userPassword":
            if value == "crypt{xxx}":
                retValue = _("No")
            else:
                retValue = _("Yes")
        elif attr == "shadowFlag":
            if value == "1":
                retValue = _("Yes")
            else:
                retValue = _("No")
        elif attr == "sambaNTPassword":
            retValue = _("Yes")
        return retValue

    def _convDatatoStr(self, dataDays):
        """Конвертирует количество дней или секунд с 1970, в строку даты"""
        if dataDays:
            if len(str(dataDays)) <= 6:
                value = long(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]))
        return ""

    def _getUserGroupName(self, userGid, service):
        """Находит имя группы по ее номеру"""
        try:
            exec ("servObj=serv%s()" %service.capitalize())
        except:
            self.printERROR(\
                _("ERROR: _getUserGroupName incorrect service=%s")%service)
            return False
        if service == "unix":
            userGidNamesLdap = servObj.searchGroupsUnix([userGid], False)
            userGidNamesPasswd = servObj.searchGroupsGroups([userGid], False)
            if userGidNamesPasswd:
                #Имя группы пользователя
                groupName = userGidNamesPasswd[0]
            elif userGidNamesLdap:
                #Имя группы пользователя
                groupName = userGidNamesLdap[0]
            else:
                groupName = userGid
            return groupName
        return userGid

    def _getUserMemberGroups(self, userName, service):
        """Находит имена групп в которые входит пользователь"""
        try:
            exec ("servObj=serv%s()" %service.capitalize())
        except:
            self.printERROR(\
                _("ERROR: _getUserGroupsNames incorrect service=%s")%service)
            return False
        memberGroups = []
        if service == "unix":
            userInGroups = servObj.searchUnixMemberGid(userName)
            for group in userInGroups:
                memberGroups.append(group[0][1]['cn'][0])
        if service == "mail":
            resSearch = servObj.searchMailMember(userName)
            if not resSearch:
                return []
            userMail, userInGroups = resSearch
            for group in userInGroups:
                mailGroup = group[0][1]['mail']
                altMailGroup = group[0][1]['mailAlternateAddress']
                listMail = mailGroup + altMailGroup
                for mail in listMail:
                    if not mail in memberGroups:
                        memberGroups.append(mail)
        return memberGroups

class tsOpt(cl_base.opt):
    """Класс для обработки параметров и вывода help

    Параметры:
    helpObj           объект-справка содержащий необходимые опции
    parBeforeService  дополнительные необходимые параметры перед указанным
                      сервисом. (например "group" или "user")
    optService        проверять хвост командной строки на наличие сервиса
    notOptError       выдавать ошибку при отсутствии опций командной строки
    """
    def __init__(self, helpObj, parBeforeService,optService=True,
                notOptError=False):
        # последний параметр является сервисом
        service = sys.argv[-1:][0].rstrip()
        # от cl_help получаем короткие и длинные опции
        if service in helpObj.allServ:
            shortOpt, longOpt = helpObj.getAllOpt('all',
                                                helpObj.relServices[service])
        else:
            shortOpt,longOpt = helpObj.getAllOpt('all',
                                                helpObj.relOptions['h'])
        # вызвать конструктор объекта, распознающего опции
        cl_base.opt.__init__(self,shortOpt,longOpt)

        self.nameParams = parBeforeService + ['service']
        self.sysArgv = sys.argv[1:]
        self.helpObj = helpObj
        self.__iter = 0
        self.opt = {}
        self.params = {}
        self.getopt()
        # Обработка help
        self.flagHelp = False
        # Ошибка в опциях
        self.errorOpt = False
        # определяем есть ли среди опций опции, которые влияют на показ
        # опциональных разделов (метод пересечения множеств)
        helpopt = \
            tuple(set(self.opt.keys()).intersection(helpObj.relOptions.keys()))
        #Если есть опции help
        if len(helpopt) > 0:
            print helpObj.getHelp(helpObj.relOptions[helpopt[0]])
            self.flagHelp = True
        #Если нет хвостов
        elif not self.params:
            if optService:
                print helpObj.getHelp(helpObj.relOptions['h'])
                self.flagHelp = True
        else:
            if self.params.has_key('service'):
                if not (self.params['service'] in helpObj.allServ) or\
                len(self.nameParams) != self.__iter:
                    self.handlerErrOpt()
            else:
                self.handlerErrOpt()
        # В случае остсутствия опций командной строки
        if notOptError and not self.opt and self.params.has_key('service'):
            self.printErrorNotOpt()
            self.flagHelp = True

    def printErrorNotOpt(self):
        """Сообщение в случае отсутствия опций"""
        print _("Options are absent.")

    def handlerOpt(self,option,value):
        # Обработчик (опция значение)
        #print option, value
        shortOpt = self.helpObj.getShortOpt(option)
        if not shortOpt:
            shortOpt = option
        if not shortOpt in self.opt:
            self.opt[shortOpt] = value

    def handlerErrOpt(self):
        # Обработчик ошибок
        self.errorOpt = True
        argv = " ".join(sys.argv[1:])
        print _("Unrecognized option") + ' "' + argv + '"\n' + \
_("Try") + ' "' + sys.argv[0].split("/")[-1] + ' --help" ' +\
_("for more information.")

    def handlerParam(self,param):
        # Обработчик хвостов (значение)
        self.__iter += 1
        if self.__iter<=len(self.nameParams):
            self.params[self.nameParams[self.__iter-1]] = param
