#! /usr/bin/env python3
import gi, os, re, gettext, sys, locale, subprocess, datetime, shutil

gi.require_version('Gtk', '3.0')

from gi.repository import Gtk, GdkPixbuf
translate = gettext.translation(os.path.basename(__file__), '/usr/share/locale', fallback=True)
i18n = translate.gettext

if not os.geteuid() == 0:
    print(i18n("Attention: The script is started from the user, restart from root!"))
    os.execv('/usr/bin/pkexec', ['pkexec -W ignore'] + sys.argv)

class Main:
    def __init__(self):
        self.language_sys=locale.getdefaultlocale()

        self.selectedUser = None
        self.selectedUserIter = None
        self.selectedGrp = None
        self.selectedGrpIter = None
        self.checkMkpasswd = False

        if subprocess.getstatusoutput("which mkpasswd")[0] == 0:
            strTypes = "{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}".format("bcrypt", "bcrypt(obsolete)", "scrypt", "md5",i18n("sha512 (Default)"), "sha256", "gost-yescrypt", "yescrypt", i18n("BSDI extended DES-based"), i18n("Standard 56 bit DES-based"))
            self.checkMkpasswd = True
        else:
            strTypes = "{0}|{1}|{2}|{3}|{4}".format("md5", "md5(Apache variant)", "AIX md5", "sha256", i18n("sha512 (Default)"))

        self.checkSmbpasswd = True if subprocess.getstatusoutput("command -v smbpasswd && exit 0 || exit 1")[0] == 0 else False

        gladeFile = "/usr/share/ubuser/ui/ubuser.glade"
        self.builder = Gtk.Builder()
        self.builder.add_from_file(gladeFile)
        self.builder.connect_signals(self)
        filename = "/home/hahafreshmeat/Загрузки/dancing-cat-53.gif"

        btnClose = self.builder.get_object("btnClose")
        btnBoxHeader = self.builder.get_object("btnBoxHeader")
        btnBoxHeader.set_homogeneous(False)
        self.ntbkMain = self.builder.get_object("ntbkMain")
        self.txtSerach = self.builder.get_object("txtSerach")
        btnClose.connect("clicked", Gtk.main_quit)
        self.btnSettings = self.builder.get_object("btnSettings")
        self.btnDelete = self.builder.get_object("btnDelete")
        self.btnSettings.set_sensitive(False)
        self.btnDelete.set_sensitive(False)
        self.btnSaveChange = self.builder.get_object("btnSaveChange")

        self.tvUsers = self.builder.get_object("tvUsers")
        self.listUsers = Gtk.ListStore(int, str, str, str, str, str)
        self.tvGrp = self.builder.get_object("tvGrp")
        self.listGroups = Gtk.ListStore(int, str, str)
        
        self.listToggleGrps = Gtk.ListStore(bool, str)
        self.listComboGrps = Gtk.ListStore(int, str)
        self.listShell = self.builder.get_object("listShell")

        self.lblErrorMsg = self.builder.get_object("lblErrorMsg")
        self.txtGroupName = self.builder.get_object("txtGroupName")
        self.cbxGrpUid = self.builder.get_object("cbxGrpUid")
        self.numUidGrp = self.builder.get_object("numUidGrp")

        self.cbxDelSamba = self.builder.get_object("cbxDelSamba")
        self.cbxDelFilesUser = self.builder.get_object("cbxDelFilesUser")
        self.cbxDelHomeAndMail = self.builder.get_object("cbxDelHomeAndMail")
        self.cbxDelPrimGrp = self.builder.get_object("cbxDelPrimGrp")

        self.cbxSaveRc = self.builder.get_object("cbxSaveRc")
        self.cbxSaveMd = self.builder.get_object("cbxSaveMd")

        self.lblAlgHash = self.builder.get_object("lblAlgHash")
        self.cbAlgHash = self.builder.get_object("cbAlgHash")
        self.lblAlgEditHash = self.builder.get_object("lblAlgEditHash")
        self.cbAlgEditHash = self.builder.get_object("cbAlgEditHash")
        self.listAlgHash = self.builder.get_object("listAlgHash")
        iterTypeHash = 0
        if strTypes:
            for i in strTypes.split("|"):
                self.listAlgHash.append([iterTypeHash, i])
                iterTypeHash+=1

        self.lblErrorMsg1 = self.builder.get_object("lblErrorMsg1")

        self.loadUsers('')
        self.load_grps('')
        self.check_writable_rc_md()

        self.popAdditionMenuSettings = self.builder.get_object("popAdditionMenuSettings")
        self.window = self.builder.get_object("mainWin")
        self.window.connect("delete-event", Gtk.main_quit)
        self.wndAddUser = self.builder.get_object("wndAddUser")
        self.wndErrorMsg = self.builder.get_object("wndErrorMsg")
        self.wndAddGroup = self.builder.get_object("wndAddGroup")
        self.wndDelUser = self.builder.get_object("wndDelUser")
        self.wndDelGrp = self.builder.get_object("wndDelGrp")
        self.wndSettUser = self.builder.get_object("wndSettUser")
        self.wndSettGrp = self.builder.get_object("wndSettGrp")
        self.wndAbout = self.builder.get_object("wndAbout")
        self.wndSaveChanges = self.builder.get_object("wndSaveChanges")
        self.wndErrorMsg1 = self.builder.get_object("wndErrorMsg1")
        self.btnBox = self.builder.get_object("btnBox")
        self.btnBox.set_visible(False)        

        self.wndAbout.connect("delete-event", self.on_destroy)
        self.wndErrorMsg.connect("delete-event", self.on_destroy)
        self.wndErrorMsg1.connect("delete-event", self.on_destroy_first_warn)
        self.wndAddGroup.connect("delete-event", self.on_destroy)
        self.wndDelUser.connect("delete-event", self.on_destroy)
        self.wndDelGrp.connect("delete-event", self.on_destroy)
        self.wndSettUser.connect("delete-event", self.on_destroy)
        self.wndSettGrp.connect("delete-event", self.on_destroy)
        self.wndSaveChanges.connect("delete-event", self.on_destroy)
        self.wndAddUser.connect("delete-event", self.on_destroy)

        self.wndErrorMsg1.set_title(i18n("Warning!"))
        errorMsg = i18n("This program works only in save mode!")
        self.lblErrorMsg1.set_label(errorMsg)
        self.wndErrorMsg1.show()

    # Функция, запрещающая удалять окно (только скрытие)
    def on_destroy(self, widget, *data):
        widget.hide()
        return True
    
    # Функция, запрещающая удалять окно, появляющиеся на старте программы (только скрытие)
    def on_destroy_first_warn(self, widget, *data):
        self.window.show()
        widget.hide()
        return True
    
    def combo_scrolling(self, combobox, event):
        """Prevent the comboboxes from scrolling."""

        combobox.emit_stop_by_name("scroll-event")
    
    def crypt_pass(self, passwdStr, methodHash):
        if self.checkMkpasswd:
            allHashMethods = ["bcrypt", "bcrypt-a", "scrypt", "md5crypt", "sha512crypt", "sha256crypt", "gost-yescrypt", "yescrypt", "bsdicrypt", "descrypt"]
            if methodHash >= 0 and methodHash <= 9:
                return str(subprocess.getstatusoutput("mkpasswd -m {0} {1}".format(allHashMethods[methodHash], str(passwdStr)))[1])
            else:
                return str(subprocess.getstatusoutput("mkpasswd -m sha512crypt {0}".format(str(passwdStr)))[1])
        else:
            if methodHash == 0:
                return str(subprocess.getstatusoutput("openssl passwd -1 -salt ubsalt {0}".format(str(passwdStr)))[1])
            elif methodHash == 1:
                return str(subprocess.getstatusoutput("openssl passwd -apr1 -salt ubsalt {0}".format(str(passwdStr)))[1])
            elif methodHash == 2:
                return str(subprocess.getstatusoutput("openssl passwd -aixmd5 -salt ubsalt {0}".format(str(passwdStr)))[1])
            elif methodHash == 3:
                return str(subprocess.getstatusoutput("openssl passwd -5 -salt ubsalt {0}".format(str(passwdStr)))[1])
            elif methodHash == 4:
                return str(subprocess.getstatusoutput("openssl passwd -6 -salt ubsalt {0}".format(str(passwdStr)))[1])
            else:
                return str(subprocess.getstatusoutput("openssl passwd -6 -salt ubsalt {0}".format(str(passwdStr)))[1])
    
    def show_pass(self, entry, icon_pos, event):
        entry.props.visibility = not entry.props.visibility
        if entry.get_icon_name(icon_pos) == "show-pass-icon":
            entry.set_icon_from_icon_name(icon_pos, "hide-pass-icon")
            entry.set_icon_tooltip_text(icon_pos, i18n("Show password"))
        else:
            entry.set_icon_from_icon_name(icon_pos, "show-pass-icon")
            entry.set_icon_tooltip_text(icon_pos, i18n("Hide password"))

    # Загрузка таблицы Пользователей
    # Сначала создаеся пустой список, там наполняется данными
    # После сортируется и вносится в GtkList, который выводится в таблицу
    def loadUsers(self, search):
        usrGrp = ""
        primGrp = ""

        tmpListUser = [[]]
        with open('/etc/passwd') as f:
            dataUsrs=f.read().split('\n')

        with open('/etc/group') as f:
            dataGrps=f.read().split('\n')

        # наполнение даными
        # также тут идет рекурсивный перебор списка групп, дабы отобразить как первичную
        # так и вторичные гуппы пользователя
        for users in dataUsrs:
            if users and search in users[:-1].split(':')[0]:
                for groups in dataGrps:
                    if groups:
                        if users.split(':')[0] in groups.split(':')[3]:
                            usrGrp+=groups.split(':')[0]+', '
                        if groups.split(':')[2] == users.split(':')[3]:
                            primGrp = groups.split(':')[0]
                usrGrp = '{}, {}'.format(primGrp, usrGrp)
                if usrGrp:
                    tmpListUser.append([int(users[:-1].split(':')[2]), users[:-1].split(':')[0], usrGrp[:-2], users[:-1].split(':')[5], users.split(':')[6], users.split(':')[4]])
                else:
                    tmpListUser.append([int(users[:-1].split(':')[2]), users[:-1].split(':')[0], usrGrp, users[:-1].split(':')[5], users.split(':')[6], users.split(':')[4]])
                usrGrp=""
        
        # удалить первый элемент (т.к. он пустой)
        tmpListUser.pop(0)
        # сортировка вложенного списка по uid
        tmpListUser.sort(key=lambda x: x[0])

        for tmp in tmpListUser:
            self.listUsers.append(tmp)

        # рендеринг столбцов
        uid_renderer = Gtk.CellRendererText()
        self.uid_column = Gtk.TreeViewColumn(title="UID", cell_renderer=uid_renderer, text=0)
        self.uid_column.set_sort_column_id(0)
        self.tvUsers.append_column(self.uid_column)

        name_renderer = Gtk.CellRendererText()
        self.name_column = Gtk.TreeViewColumn(title=i18n("Login"), cell_renderer=name_renderer, text=1)
        self.name_column.set_sort_column_id(1)
        self.name_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.name_column.set_resizable(True)
        self.name_column.set_expand(True)
        self.tvUsers.append_column(self.name_column)

        grps_renderer = Gtk.CellRendererText()
        self.grps_column = Gtk.TreeViewColumn(title=i18n("Groups"), cell_renderer=grps_renderer, text=2)
        self.grps_column.set_sort_column_id(2)
        self.grps_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.grps_column.set_resizable(True)
        self.grps_column.set_expand(True)
        self.tvUsers.append_column(self.grps_column)

        hdir_renderer = Gtk.CellRendererText()
        self.hdir_column = Gtk.TreeViewColumn(title=i18n("Home Directory"), cell_renderer=hdir_renderer, text=3)
        self.hdir_column.set_sort_column_id(3)
        self.hdir_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.hdir_column.set_resizable(True)
        self.hdir_column.set_expand(True)
        self.tvUsers.append_column(self.hdir_column)

        shell_renderer = Gtk.CellRendererText()
        self.shell_column = Gtk.TreeViewColumn(title=i18n("Shell"), cell_renderer=shell_renderer, text=4)
        self.shell_column.set_sort_column_id(4)
        self.shell_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.shell_column.set_resizable(True)
        self.shell_column.set_expand(True)
        self.tvUsers.append_column(self.shell_column)

        fName_renderer = Gtk.CellRendererText()
        self.fName_column = Gtk.TreeViewColumn(title=i18n("Full Name"), cell_renderer=fName_renderer, text=5)
        self.fName_column.set_sort_column_id(5)
        self.fName_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.fName_column.set_resizable(True)
        self.fName_column.set_expand(True)
        self.tvUsers.append_column(self.fName_column)

        self.tvUsers.set_model(self.listUsers)

    # Загрузка групп в таблицу
    def load_grps(self, search):
        tmpListGrp = [[]]

        with open('/etc/group') as f:
            dataGrps=f.read().split('\n')
        
        for grp in dataGrps:
            if grp and search in grp.split(':')[0]:
                tmpListGrp.append([int(grp.split(':')[2]), grp.split(':')[0], grp.split(':')[3]])
        
        tmpListGrp.pop(0)
        tmpListGrp.sort(key=lambda x: x[0])

        for grp in tmpListGrp:
            self.listGroups.append(grp)
        
        uid_renderer = Gtk.CellRendererText()
        self.uid_column_grp = Gtk.TreeViewColumn(title="UID", cell_renderer=uid_renderer, text=0)
        self.uid_column_grp.set_sort_column_id(0)
        self.tvGrp.append_column(self.uid_column_grp)

        name_renderer = Gtk.CellRendererText()
        self.name_column_grp = Gtk.TreeViewColumn(title=i18n("Group"), cell_renderer=name_renderer, text=1)
        self.name_column_grp.set_sort_column_id(1)
        self.name_column_grp.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.name_column_grp.set_resizable(True)
        self.name_column_grp.set_expand(True)
        self.tvGrp.append_column(self.name_column_grp)

        usrs_renderer = Gtk.CellRendererText()
        self.usr_grps_column= Gtk.TreeViewColumn(title=i18n("Users"), cell_renderer=usrs_renderer, text=2)
        self.usr_grps_column.set_sort_column_id(2)
        self.usr_grps_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.usr_grps_column.set_resizable(True)
        self.usr_grps_column.set_expand(True)
        self.tvGrp.append_column(self.usr_grps_column)

        self.tvGrp.set_model(self.listGroups)

    #  Проверка, являются ли каталоги rootcope и modules
    # Доступными на запись
    def check_writable_rc_md(self):
        check = False

        try:
            rcFileCheck = open('/mnt/livemedia/ublinux-data/rootcopy/file.txt', "w")
            rcFileCheck.write("test")
            rcFileCheck.close()
            mdFileCheck = open('/mnt/livemedia/ublinux-data/modules/file.txt', "w")
            mdFileCheck.write("test")
            mdFileCheck.close()
            check = True
        except:
            check = False
        finally:
            if check:
                os.remove('/mnt/livemedia/ublinux-data/rootcopy/file.txt')
                os.remove('/mnt/livemedia/ublinux-data/modules/file.txt')

        self.btnSaveChange.set_sensitive(check)

    # отображение поп-апа с меню Добавить группы/обносить
    def show_menu_settings(self, button):
        self.popAdditionMenuSettings.show()

    # Очистка таблицы при закрытии окна
    def clear_users(self):
        self.listUsers.clear()
        self.tvUsers.set_model(None)
        self.tvUsers.remove_column(self.uid_column)
        self.tvUsers.remove_column(self.name_column)
        self.tvUsers.remove_column(self.grps_column)
        self.tvUsers.remove_column(self.hdir_column)
        self.tvUsers.remove_column(self.shell_column)
        self.tvUsers.remove_column(self.fName_column)

    def clear_grps(self):
        self.listGroups.clear()
        self.tvGrp.set_model(None)
        self.tvGrp.remove_column(self.uid_column_grp)
        self.tvGrp.remove_column(self.name_column_grp)
        self.tvGrp.remove_column(self.usr_grps_column)

    # функция поиска
    # реализовывает обычную подгрузку данных во вложенный список (loadl_users)
    # При это фильтрует его
    def searching(self, button):
        if self.ntbkMain.get_current_page() == 0:
            self.clear_users()
            self.loadUsers(self.txtSerach.get_text())
        elif self.ntbkMain.get_current_page() == 1:
            self.clear_grps()
            self.load_grps(self.txtSerach.get_text())

    # Просто повторная подгрузка
    def refresh_all_tables(self, button):
        self.clear_users()
        self.clear_grps()
        self.loadUsers('')
        self.load_grps('')

    # вывод окна "Добавить пользователя"
    def show_add_new_user(self, button):
        self.wndAddUser.set_transient_for(self.window)
        self.wndAddUser.show()

    # скрытие окна "Добавить пользователя"
    def hide_add_new_user(self, button):
        self.wndAddUser.hide()

    # Скрытие сообщений об ошибке
    def hide_error(self, button):
        self.wndErrorMsg.hide()

    def hide_error_firs_warn(self, button):
        self.window.show()
        self.wndErrorMsg1.hide()

    # подгрущка окна "Добавление пользователя"
    def load_add_new_user(self, window):
        self.iterUids = 0
        renderer= Gtk.CellRendererText()

        self.txtLogin = self.builder.get_object("txtLogin")
        self.txtFullName = self.builder.get_object("txtFullName")
        self.txtPass = self.builder.get_object("txtPass")
        self.txtConfirmPass = self.builder.get_object("txtConfirmPass")
        self.cbShell = self.builder.get_object("cbShell")
        self.txtHomeDir = self.builder.get_object("txtHomeDir")
        self.numUid = self.builder.get_object("numUid")
        self.cbxAddSamba = self.builder.get_object("cbxAddSamba")
        self.cbxHomeDir = self.builder.get_object("cbxHomeDir")
        self.cbxUid = self.builder.get_object("cbxUid")
        self.cbxPrtGrp = self.builder.get_object("cbxPrtGrp")

        self.cbxAddSamba.set_active(True)
        self.txtHomeDir.set_sensitive(True)
        self.txtHomeDir.set_editable(True)
        self.cbxHomeDir.set_active(True)
        self.cbxPrtGrp.set_active(True)
        self.numUid.set_sensitive(False)

        with open('/etc/passwd') as fuser:
            dataUsrs=fuser.read().split('\n')
        
        for usr in dataUsrs:
            if usr and int(usr.split(':')[2]) >= 1000:
                self.iterUids = int(usr.split(':')[2])

        self.numUid.set_increments(1, 10)
        self.numUid.set_range(self.iterUids+1, 9999)
        self.numUid.set_value(self.iterUids+1)

        self.cbShell.pack_start(renderer, True)
        self.cbShell.add_attribute(renderer, "text", 1)

        self.cbShell.set_active(0)

        self.cbAlgHash.pack_start(renderer, True)
        self.cbAlgHash.add_attribute(renderer, "text", 1)
        self.cbAlgHash.set_active(4)

    # Очистка при скрытии окна "Добавление пользователя"
    def clear_add_new_user(self, widget):
        self.txtLogin.set_text("")
        self.txtFullName.set_text("")
        self.txtPass.set_text("")
        self.txtConfirmPass.set_text("")
        self.txtHomeDir.set_text("")
        self.cbxHomeDir.set_active(True)
        self.cbxUid.set_active(False)
        self.cbxPrtGrp.set_active(True)
        self.cbAlgHash.clear()
        self.cbShell.clear()

    # событие при нажатии на чекбокс (Создать home)
    def toggle_home_dir(self, toggle):
        self.txtHomeDir.set_sensitive(toggle.get_active())

    def toggle_uid(self, toggle):
        if toggle.get_active():
            self.numUid.set_sensitive(True)
        else:
            self.numUid.set_sensitive(False)
            self.numUid.set_value(self.iterUids+1)

    # задание базавого дом. каталога (/home/*USER*)
    def set_home_dir(self, editable):
        if editable.get_chars(0, -1):
            home = '/home/{0}'.format(editable.get_chars(0, -1))
            self.txtHomeDir.set_text(home)
        else:
            self.txtHomeDir.set_text('')

    # Добавление нового пользователя
    # Сначала читаются все поля
    # Затем создаеся строка команды (cmd)
    # После выполняется, с получеием результата и кода ошибки
    # затем в зависимости от полученного результата вывод нужное сообщение
    # (Так будут работать все основные действия)
    def add_new_user(self, button):
        login = self.txtLogin.get_text()
        passwordRef = self.txtPass.get_text()
        confPassword = self.txtConfirmPass.get_text()
        if passwordRef == confPassword:
            if login and passwordRef:
                fullName = self.txtFullName.get_text()

                getIterShell = self.cbShell.get_active_iter()
                if getIterShell:
                    modelShell = self.cbShell.get_model()
                    shell = modelShell[getIterShell][1]

                hashPass = ''
                getIterHashPass = self.cbAlgHash.get_active_iter()
                if getIterHashPass:
                    modelHashPass = self.cbAlgHash.get_model()
                    hashType = int(modelHashPass[getIterHashPass][0])
                    hashPass = self.crypt_pass(passwordRef, hashType)
    
                homeDir = '-d {}'.format(self.txtHomeDir.get_text()) if self.cbxHomeDir.get_active() else ''

                uid = '-u {}'.format(str(self.numUid.get_value())[:-2]) if self.cbxUid.get_active() else ''

                shell = '-s {}'.format(shell) if shell else ''
                fullName = '-c \'{}\''.format(fullName) if fullName else ''
                password = '-p \'{}\''.format(hashPass) if hashPass else ''
                if self.cbxHomeDir.get_active():
                    if self.cbxUid.get_active():
                        if self.cbxPrtGrp.get_active():
                            cmd = 'useradd -m -U --badnames -o {0} {1} {2} {3} {4} {5}'.format(homeDir, uid, shell, fullName, password, login)
                        else:
                            cmd = 'useradd -m -N --badnames -o {0} {1} {2} {3} {4} {5}'.format(homeDir, uid, shell, fullName, password, login)
                    else:
                        if self.cbxPrtGrp.get_active():
                            cmd = 'useradd -m -U --badnames {0} {1} {2} {3} {4}'.format(homeDir, shell, fullName, password, login)
                        else:
                            cmd = 'useradd -m -N --badnames {0} {1} {2} {3} {4}'.format(homeDir, shell, fullName, password, login)
                else:
                    if self.cbxUid.get_active():
                        if self.cbxPrtGrp.get_active():
                            cmd = 'useradd -M -U --badnames -o {0} {1} {2} {3} {4}'.format(uid, shell, fullName, password, login)
                        else:
                            cmd = 'useradd -M -N --badnames -o {0} {1} {2} {3} {4}'.format(uid, shell, fullName, password, login)
                    else:
                        if self.cbxPrtGrp.get_active():
                            cmd = 'useradd -M -U --badnames {0} {1} {2} {3}'.format(shell, fullName, password, login)
                        else:
                            cmd = 'useradd -M -N --badnames {0} {1} {2} {3}'.format(shell, fullName, password, login)

                errorCode = subprocess.getstatusoutput(cmd)
                if errorCode[0] == 0 and self.checkSmbpasswd and self.cbxAddSamba.get_active():
                    if login != None and password != None:
                        subprocess.getstatusoutput("(echo \"{0}\"; echo \"{0}\") | sudo smbpasswd -Lsa {1}".format(password, login))

                if int(errorCode[0]) != 0:
                    self.wndErrorMsg.set_title(i18n("Error!"))
                    errorMsg = str(i18n("The user was not added")) + '\n\n' + errorCode[1]
                    self.lblErrorMsg.set_label(errorMsg)
                    self.wndErrorMsg.set_transient_for(self.wndAddUser)
                    self.wndErrorMsg.show()
                elif int(errorCode[0]) != 1:
                    self.wndErrorMsg.set_title(i18n("Complete!"))
                    errorMsg = str(i18n("User added"))
                    self.lblErrorMsg.set_label(errorMsg)
                    self.wndErrorMsg.set_transient_for(self.wndAddUser)
                    self.wndErrorMsg.show()

                    self.clear_users()
                    self.loadUsers('')
                    self.clear_grps()
                    self.load_grps('')

                    self.clear_add_new_user('')

                    self.wndAddUser.hide()
            else:
                self.wndErrorMsg.set_title(i18n("Warning!"))
                lbltext = i18n("Fields <b><i>Login</i></b> and <b><i>Password</i></b>\nmust be filled in!")
                self.lblErrorMsg.set_markup(lbltext)
                self.wndErrorMsg.set_transient_for(self.wndAddUser)
                self.wndErrorMsg.show()
        else:
            self.wndErrorMsg.set_title(i18n("Warning!"))
            self.lblErrorMsg.set_label(i18n("Passwords don't match"))
            self.wndErrorMsg.set_transient_for(self.wndAddUser)
            self.wndErrorMsg.show()

    def show_add_new_group(self, button):
        self.wndAddGroup.set_transient_for(self.window)
        self.wndAddGroup.show()

    def hide_add_new_group(self, window):
        self.wndAddGroup.hide()
    
    def clear_add_new_group(self, widget):
        self.txtGroupName.set_text('')
        self.cbxGrpUid.set_active(False)

    def load_add_new_grp(self, window):
        self.numUidGrp.set_sensitive(False)

        listUidGrp = []
        with open('/etc/group') as fuser:
            dataGrp=fuser.read().split('\n')
        
        for grp in dataGrp:
            if grp and grp.split(':')[0] != 'nobody':
                listUidGrp.append(int(grp.split(':')[2]))

        listUidGrp.sort()

        self.uidGrp = int(listUidGrp[len(listUidGrp) - 1]) + 1

        self.numUidGrp.set_increments(1, 10)
        self.numUidGrp.set_range(self.uidGrp, 9999)
        self.numUidGrp.set_value(self.uidGrp)

    def add_new_group(self, button):
        nameGrp = self.txtGroupName.get_text()
        if nameGrp:
            uid = '-g {}'.format(str(self.numUidGrp.get_value())[:-2])
            if self.cbxGrpUid.get_active():
                cmd = 'groupadd -o {0} {1}'.format(uid, nameGrp)
            else:
                cmd = 'groupadd {0}'.format(nameGrp)

            errorCode = subprocess.getstatusoutput(cmd)

            if int(errorCode[0]) != 0:
                self.wndErrorMsg.set_title(i18n("Error!"))
                errorMsg = str(i18n("The group was not added")) + '\n\n' + errorCode[1]
            else:
                self.wndErrorMsg.set_title(i18n("Complete!"))
                errorMsg = str(i18n("Group added"))
                self.clear_users()
                self.loadUsers('')
                self.clear_grps()
                self.load_grps('')

                self.txtGroupName.set_text('')
                self.wndAddGroup.hide()

            self.lblErrorMsg.set_label(errorMsg)
            self.wndErrorMsg.set_transient_for(self.wndAddGroup)
            self.wndErrorMsg.show()
        else:
            self.wndErrorMsg.set_title(i18n("Warning!"))
            lbltext = i18n("Field <b><i>Group Name</i></b>\nmust be filled in!")
            self.lblErrorMsg.set_markup(lbltext)
            self.wndErrorMsg.set_transient_for(self.wndAddGroup)
            self.wndErrorMsg.show()

    def toggle_uid_grp(self, toggle):
        if toggle.get_active():
            self.numUidGrp.set_sensitive(True)
        else:
            self.numUidGrp.set_value(self.uidGrp)
            self.numUidGrp.set_sensitive(False)

    def set_select_user(self, select):
        if self.ntbkMain.get_current_page() == 0:
            if select.get_selected()[1]:
                self.selectedUser = self.listUsers[select.get_selected()[1]]
                self.selectedUserIter = select.get_selected()[1]
                self.btnSettings.set_sensitive(True)
                self.btnDelete.set_sensitive(True)

    def set_select_grp(self, select):
        if self.ntbkMain.get_current_page() == 1:
            if select.get_selected()[1]:
                self.selectedGrp = self.listGroups[select.get_selected()[1]]
                self.selectedGrpIter = select.get_selected()[1]
                self.btnSettings.set_sensitive(True)
                self.btnDelete.set_sensitive(True)

    def show_delete(self, button):
        if self.ntbkMain.get_current_page() == 0:
            self.wndDelUser.set_transient_for(self.window)
            self.wndDelUser.show()
        elif self.ntbkMain.get_current_page() == 1:
            self.wndDelGrp.set_transient_for(self.window)
            self.wndDelGrp.show()

    def hide_delete_user(self, button):
        self.wndDelUser.hide()
    
    def clear_delete_user(self, widget):
        self.cbxDelFilesUser.set_active(False)
        self.cbxDelHomeAndMail.set_active(False)

    def hide_delete_grp(self, button):
        self.wndDelGrp.hide()
    
    def clear_delete_grp(self, widget):
        self.cbxDelPrimGrp.set_active(False)

    def delete_user(self, button):
        cmd = ''
        if self.cbxDelFilesUser.get_active():
            if self.cbxDelHomeAndMail.get_active():
                cmd = 'userdel -f -r {}'.format(self.selectedUser[1])
            else:
                cmd = 'userdel -f {}'.format(self.selectedUser[1])
        else:
            if self.cbxDelHomeAndMail.get_active():
                cmd = 'userdel -r {}'.format(self.selectedUser[1])
            else:
                cmd = 'userdel {}'.format(self.selectedUser[1])

        errorCode = subprocess.getstatusoutput(cmd)
        if errorCode[0] == 0 and self.checkSmbpasswd and self.cbxDelSamba.get_active():
            subprocess.getstatusoutput("sudo samba-tool user delete {0}".format(self.selectedUser[1]))

        if int(errorCode[0]) != 0:
            self.wndErrorMsg.set_title(i18n("Error!"))
            errorMsg = str(i18n("The user was not deleted")) + '\n\n' + errorCode[1]
        elif int(errorCode[0]) != 1:
            self.wndErrorMsg.set_title(i18n("Complete!"))
            errorMsg = str(i18n("User deleted"))

            self.cbxDelFilesUser.set_active(False)
            self.cbxDelHomeAndMail.set_active(False)

            self.clear_users()
            self.loadUsers('')
            self.clear_grps()
            self.load_grps('')

            self.wndDelUser.hide()

        self.lblErrorMsg.set_label(errorMsg)
        self.wndErrorMsg.set_transient_for(self.wndDelUser)
        self.wndErrorMsg.show()

    def delete_grp(self, button):
        cmd = ''
        if self.cbxDelPrimGrp.get_active():
            cmd = 'groupdel -f {}'.format(self.selectedGrp[1])
        else:
            cmd = 'groupdel {}'.format(self.selectedGrp[1])

        errorCode = subprocess.getstatusoutput(cmd)
        if int(errorCode[0]) != 0:
            self.wndErrorMsg.set_title(i18n("Error!"))
            errorMsg = str(i18n("The group was not deleted")) + '\n\n' + errorCode[1]
        elif int(errorCode[0]) != 1:
            self.wndErrorMsg.set_title(i18n("Complete!"))
            errorMsg = str(i18n("Group deleted"))
            self.cbxDelPrimGrp.set_active(False)

            self.clear_users()
            self.loadUsers('')
            self.clear_grps()
            self.load_grps('')

            self.wndDelGrp.hide()

        self.lblErrorMsg.set_label(errorMsg)
        self.wndErrorMsg.set_transient_for(self.wndDelGrp)
        self.wndErrorMsg.show()

    def show_settings(self, button):
        if self.ntbkMain.get_current_page() == 0:
            self.wndSettUser.set_transient_for(self.window)
            self.wndSettUser.show()
        elif self.ntbkMain.get_current_page() == 1:
            self.wndSettGrp.set_transient_for(self.window)
            self.wndSettGrp.show()

    def hide_sett_user(self, button):
        self.wndSettUser.hide()
    
    def clear_sett_user(self, widget):
        self.cbNewShell.clear()
        self.cbPrimGrp.clear()
        self.listComboGrps.clear()
        self.clear_toggle_grps()
        self.ntbkSettUsers.set_current_page(0)
        self.txtNewLogin.set_text('')
        self.txtNewFullName.set_text('')
        self.txtNewPass.set_text('')
        self.txtConfirmNewPass.set_text('')
        self.txtNewHome.set_text('')
        self.cbxEditSambaUser.set_active(True)
        self.cbxMoveHome.set_active(False)
        self.cbxNewUid.set_active(False)
        self.cbAlgEditHash.clear()

    def load_sett_user(self, window):
        renderer= Gtk.CellRendererText()

        self.txtNewLogin = self.builder.get_object("txtNewLogin")
        self.txtNewFullName = self.builder.get_object("txtNewFullName")
        self.txtNewPass = self.builder.get_object("txtNewPass")
        self.txtConfirmNewPass = self.builder.get_object("txtConfirmNewPass")
        self.txtNewHome = self.builder.get_object("txtNewHome")
        self.cbxEditSambaUser = self.builder.get_object("cbxEditSambaUser")
        self.cbxMoveHome = self.builder.get_object("cbxMoveHome")
        self.cbNewShell = self.builder.get_object("cbNewShell")
        self.cbxNewUid = self.builder.get_object("cbxNewUid")
        self.numNewUid = self.builder.get_object("numNewUid")
        self.tvTgglGrp = self.builder.get_object("tvTgglGrp")
        self.cbPrimGrp = self.builder.get_object("cbPrimGrp")
        self.ntbkSettUsers = self.builder.get_object("ntbkSettUsers")

        self.cbxMoveHome.set_sensitive(False)
        self.numNewUid.set_sensitive(False)

        login = self.selectedUser[1]
        fName = self.selectedUser[5]
        homeDir = self.selectedUser[3]
        shell = self.selectedUser[4]
        uid = int(self.selectedUser[0])
        primGrp = ''
        listGrpAll = str(self.selectedUser[2]).split(', ') if self.selectedUser[2] else list('')
        if listGrpAll:
            primGrp = listGrpAll[0]
            listGrpAll.pop(0)
        
        self.load_toggle_groups(listGrpAll)
        self.load_combo_grp(primGrp)

        self.txtNewLogin.set_text(login)
        self.txtNewFullName.set_text(fName)
        self.txtNewHome.set_text(homeDir)
        self.numNewUid.set_increments(1, 10)
        self.numNewUid.set_range(uid, 9999)
        self.numNewUid.set_value(uid)
        
        self.cbNewShell.pack_start(renderer, True)
        self.cbNewShell.add_attribute(renderer, "text", 1)

        self.cbAlgEditHash.pack_start(renderer, True)
        self.cbAlgEditHash.add_attribute(renderer, "text", 1)
        self.cbAlgEditHash.set_active(4)

        for sh in self.listShell:
            if sh[1] == shell:
                self.cbNewShell.set_active(sh[0])
        
        if subprocess.getstatusoutput("who | grep {0}".format(login))[0] == 0:
            self.txtNewLogin.set_sensitive(False)

    def on_cell_toggled_grp(self, widget, path):
        chooseGrp = ''
        getIter = self.cbPrimGrp.get_active_iter()
        if getIter:
            model = self.cbPrimGrp.get_model()
            chooseGrp = model[getIter][1]
        if self.listToggleGrps[path][1] != chooseGrp:
            self.listToggleGrps[path][0] = not self.listToggleGrps[path][0]

    def load_toggle_groups(self, listGrpAll):
        tmpListGrp = []
        checkGrp = False

        with open('/etc/group') as fGrp:
            dataGrp = fGrp.read().split('\n')
        
        for grp in dataGrp:
            if grp:
                tmpListGrp.append(grp.split(':')[0])
        
        tmpListGrp.sort()

        for grp in tmpListGrp:
            if grp:
                for tmpGrp in listGrpAll:
                    if tmpGrp == grp:
                        checkGrp = True
                        break
                self.listToggleGrps.append([checkGrp, grp])
                if checkGrp:
                    checkGrp = False

        self.tvTgglGrp.set_model(self.listToggleGrps)
        renderer_toggle = Gtk.CellRendererToggle()
        renderer_toggle.connect("toggled", self.on_cell_toggled_grp)
        self.columnToggleGrps = Gtk.TreeViewColumn("", renderer_toggle, active=0)
        self.columnToggleGrps.set_sort_column_id(0)
        self.tvTgglGrp.append_column(self.columnToggleGrps)

        renderer_text = Gtk.CellRendererText()
        self.columnNameGrps = Gtk.TreeViewColumn(i18n("Group"), renderer_text, text=1)
        self.columnNameGrps.set_sort_column_id(1)
        self.columnNameGrps.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
        self.columnNameGrps.set_resizable(True)
        self.columnNameGrps.set_expand(True)
        self.tvTgglGrp.append_column(self.columnNameGrps)

    def load_combo_grp(self, primGrp):
        tmpListGrp = []
        iterGrp = 0
        renderer= Gtk.CellRendererText()

        with open('/etc/group') as fGrp:
            dataGrp = fGrp.read().split('\n')
        
        for grp in dataGrp:
            if grp:
                tmpListGrp.append(grp.split(':')[0])
        
        tmpListGrp.sort()

        for grp in tmpListGrp:
            if grp:
                self.listComboGrps.append([iterGrp, grp])
                iterGrp += 1
        
        for grp in self.listComboGrps:
            if grp[1] == primGrp:
                self.cbPrimGrp.set_active(grp[0])
        
        self.cbPrimGrp.set_model(self.listComboGrps)
        self.cbPrimGrp.pack_start(renderer, True)
        self.cbPrimGrp.add_attribute(renderer, "text", 1)

    def clear_toggle_grps(self):
        self.listToggleGrps.clear()
        self.tvTgglGrp.set_model(model=None)
        self.tvTgglGrp.remove_column(self.columnToggleGrps)
        self.tvTgglGrp.remove_column(self.columnNameGrps)

    def save_sett_user(self, button):
        login = self.txtNewLogin.get_text()
        passwordRef = self.txtNewPass.get_text()
        confPass = self.txtConfirmNewPass.get_text()
        
        if passwordRef == confPass:
            if login:
                cmd = ''
                
                oldLogin = self.selectedUser[1]
                allOldGrp = str(self.selectedUser[2]).split(', ')
                oldPrimGrp = allOldGrp[0]
                allOldGrp.pop(0)
                oldSecGrp = ''
                for grp in allOldGrp:
                    if grp:
                        oldSecGrp += grp + ','
                if oldSecGrp:
                    oldSecGrp = oldSecGrp[:-1]

                login = '' if login == oldLogin else login
                fName = self.txtNewFullName.get_text() if self.txtNewFullName.get_text() else ''
                homeDir = self.txtNewHome.get_text() if self.txtNewHome.get_text() != self.selectedUser[3] else ''
                primGrp = ''
                secGrp = ''
                shell = ''
                uid = ''
                if self.cbxNewUid.get_active() and str(self.numNewUid.get_value())[:-2] != str(self.selectedUser[0]):
                    uid = str(self.numNewUid.get_value())[:-2]
                else:
                    uid = ''

                getIterPrinGrp = self.cbPrimGrp.get_active_iter()
                if getIterPrinGrp:
                    modelPrimGrp = self.cbPrimGrp.get_model()
                    primGrp = modelPrimGrp[getIterPrinGrp][1] if modelPrimGrp[getIterPrinGrp][1] != oldPrimGrp else ''

                getIterShell = self.cbNewShell.get_active_iter()
                if getIterShell:
                    modelShell = self.cbNewShell.get_model()
                    shell = modelShell[getIterShell][1] if modelShell[getIterShell][1] != self.selectedUser[4] else ''
                
                for grp in self.listToggleGrps:
                    if grp[0]:
                        secGrp += grp[1] + ','

                if secGrp:
                    secGrp = secGrp[:-1]
                else:
                    secGrp = '\"\"'
                
                if secGrp == oldSecGrp:
                    secGrp = ''
                
                hashPass = ''
                getIterHashPass = self.cbAlgEditHash.get_active_iter()
                if getIterHashPass:
                    modelHashPass = self.cbAlgEditHash.get_model()
                    hashType = int(modelHashPass[getIterHashPass][0])
                    hashPass = self.crypt_pass(passwordRef, hashType)

                login = '-l {}'.format(login) if login else ''
                fName = '-c \'{}\''.format(fName)
                primGrp = '-g {}'.format(primGrp) if primGrp else ''
                secGrp = '-G {}'.format(secGrp) if secGrp else ''
                shell = '-s {}'.format(shell) if shell else ''
                password = '-p \'{}\''.format(hashPass) if hashPass else ''
                homeDir = '-d {}'.format(homeDir) if homeDir else ''
                uid = '-u {}'.format(uid) if uid else ''
                if self.cbxMoveHome.get_active():
                    if self.cbxNewUid.get_active():
                        cmd = 'usermod -m --badnames -o {0} {1} {2} {3} {4} {5} {6} {7} {8}'.format(login, fName, primGrp, secGrp, shell, password, homeDir, uid, oldLogin)
                    else:
                        cmd = 'usermod -m --badnames {0} {1} {2} {3} {4} {5} {6} {7}'.format(login, fName, primGrp, secGrp, shell, password, homeDir, oldLogin)
                else:
                    if self.cbxNewUid.get_active():
                        cmd = 'usermod --badnames -o {0} {1} {2} {3} {4} {5} {6} {7} {8}'.format(login, fName, primGrp, secGrp, shell, password, homeDir, uid, oldLogin)
                    else:
                        cmd = 'usermod --badnames {0} {1} {2} {3} {4} {5} {6} {7}'.format(login, fName, primGrp, secGrp, shell, password, homeDir, oldLogin)
                
                errorCode = subprocess.getstatusoutput(cmd)
                if errorCode[0] == 0 and self.checkSmbpasswd and self.cbxEditSambaUser.get_active():
                    if login != None and password != None:
                        subprocess.getstatusoutput("(echo \"{0}\"; echo \"{0}\") | sudo smbpasswd -Lsa {1}".format(password, login))

                if int(errorCode[0]) == 1:
                    self.wndErrorMsg.set_title(i18n("Error!"))
                    errorMsg = str(i18n("The user has not been changed")) + '\n\n' + errorCode[1]
                    self.lblErrorMsg.set_label(errorMsg)
                    self.wndErrorMsg.set_transient_for(self.wndSettUser)
                    self.wndErrorMsg.show()
                else:
                    if int(errorCode[0]) == 0:
                        self.wndErrorMsg.set_title(i18n("Complete!"))
                        errorMsg = str(i18n("The user has been changed"))
                        self.lblErrorMsg.set_label(errorMsg)
                        self.wndErrorMsg.set_transient_for(self.wndSettUser)
                        self.wndErrorMsg.show()

                        self.clear_users()
                        self.loadUsers('')
                        self.clear_grps()
                        self.load_grps('')

                    self.cbNewShell.clear()
                    self.cbPrimGrp.clear()
                    self.listComboGrps.clear()
                    self.clear_toggle_grps()
                    self.ntbkSettUsers.set_current_page(0)
                    self.txtNewLogin.set_text('')
                    self.txtNewFullName.set_text('')
                    self.txtNewPass.set_text('')
                    self.txtConfirmNewPass.set_text('')
                    self.txtNewHome.set_text('')
                    self.cbxMoveHome.set_active(False)
                    self.cbxNewUid.set_active(False)
                    self.wndSettUser.hide()
            else:
                self.wndErrorMsg.set_title(i18n("Warning!"))
                lbltext = i18n("Field <b><i>Login</i></b>\nmust be filled in!")
                self.lblErrorMsg.set_markup(lbltext)
                self.wndErrorMsg.set_transient_for(self.wndSettUser)
                self.wndErrorMsg.show()
        else:
            self.wndErrorMsg.set_title(i18n("Warning!"))
            self.lblErrorMsg.set_label(i18n("Passwords don't match"))
            self.wndErrorMsg.set_transient_for(self.wndSettUser)
            self.wndErrorMsg.show()
            
            
            # self.wndSettUser.set_keep_below(True)

    def toggle_edit_new_uid(self, toggle):
        self.numNewUid.set_sensitive(toggle.get_active())

    def edit_new_home(self, editable):
        if editable.get_text():
            self.cbxMoveHome.set_sensitive(str(editable.get_chars(0, -1)) != self.selectedUser[3])

    def load_grp_sett(self, window):
        grpName = self.selectedGrp[1]
        gid = self.selectedGrp[0]

        self.txtNewGroupName = self.builder.get_object("txtNewGroupName")
        self.cbxNewGrpUid = self.builder.get_object("cbxNewGrpUid")
        self.numNewUidGrp = self.builder.get_object("numNewUidGrp")

        self.numNewUidGrp.set_sensitive(False)

        self.numNewUidGrp.set_increments(1, 10)
        self.numNewUidGrp.set_range(gid, 9999)
        self.numNewUidGrp.set_value(gid)

        self.txtNewGroupName.set_text(grpName)
    
    def hide_sett_grp(self, button):
        self.wndSettGrp.hide()
    
    def clear_sett_gtp(self, widget):
        self.cbxNewGrpUid.set_active(False)
 
    def toggle_edit_grp_gid(self, toggle):
        self.numNewUidGrp.set_sensitive(toggle.get_active())

    def save_sett_grp(self, button):
        cmd = ''
        grpName = self.selectedGrp[1]
        gid = self.selectedGrp[0]

        newName = self.txtNewGroupName.get_text()
        newGid = str(self.numNewUidGrp.get_value())[:-2]

        if newName:
            name = '-n {}'.format(newName)
            newGid = '-g {}'.format(newGid)

            if self.cbxNewGrpUid.get_active():
                cmd = 'groupmod -o {0} {1} {2}'.format(name, newGid, grpName)
            else:
                cmd = 'groupmod {0} {1}'.format(name, grpName)

            errorCode = subprocess.getstatusoutput(cmd)
            if int(errorCode[0]) == 1:
                self.wndErrorMsg.set_title(i18n("Error!"))
                errorMsg = str(i18n("The group has not been changed")) + '\n\n' + errorCode[1]
                self.lblErrorMsg.set_label(errorMsg)
                self.wndErrorMsg.set_transient_for(self.wndSettGrp)
                self.wndErrorMsg.show()
            elif int(errorCode[0]) == 0:
                self.wndErrorMsg.set_title(i18n("Complete!"))
                errorMsg = str(i18n("The group has been changed"))
                self.lblErrorMsg.set_label(errorMsg)
                self.wndErrorMsg.set_transient_for(self.wndSettGrp)
                self.wndErrorMsg.show()

                self.clear_users()
                self.loadUsers('')
                self.clear_grps()
                self.load_grps('')
                self.cbxNewGrpUid.set_active(False)
                self.wndSettGrp.hide()
            elif int(errorCode[0]) == 2:
                self.cbxNewGrpUid.set_active(False)
                self.wndSettGrp.hide()
        else:
            self.wndErrorMsg.set_title(i18n("Warning!"))
            lbltext = i18n("Field <b><i>Group Name</i></b>\nmust be filled in!")
            self.lblErrorMsg.set_markup(lbltext)
            self.wndErrorMsg.set_transient_for(self.wndSettGrp)
            self.wndErrorMsg.show()

    def show_about(self, button):
        self.wndAbout.show()
        self.popAdditionMenuSettings.hide()
    
    def hide_about(self, button):
        self.wndAbout.hide()

    def open_sett_users(self, treeview, path, view_column):
        self.wndSettUser.set_transient_for(self.window)
        self.wndSettUser.show()
    
    def open_sett_group(self, treeview, path, view_column):
        self.wndSettGrp.set_transient_for(self.window)
        self.wndSettGrp.show()

    def show_save_changes(self, button):
        self.wndSaveChanges.set_transient_for(self.window)
        self.wndSaveChanges.show()

    def hide_save_changes(self, button):
        self.wndSaveChanges.hide()
    
    def clear_save_changes(self, widget):
        self.cbxSaveRc.set_active(False)
        self.cbxSaveMd.set_active(False)
    
    # Сохранение изменений в rootcopy/modules
    # при выбранных чекбоксах, вызываются конкретные функции (save_rc_users и save_md_users)
    # Получение от них либо 0 (удачно), либо списко с кодом ошибки и текстом ошибки
    def save_changes(self, button):
        errorCodeRc = 0
        errorCodeMd = 0

        saveMd = self.cbxSaveMd.get_active()
        saveRc = self.cbxSaveRc.get_active()

        if saveMd or saveRc:
            if saveRc: errorCodeRc = self.save_rc_users()
            if saveMd: errorCodeMd = self.save_md_users()

            if errorCodeRc == 0 and errorCodeMd == 0:
                self.wndErrorMsg.set_title(i18n("Complete!"))
                errorMsg = str(i18n("Saving is complete!"))
            else: 
                self.wndErrorMsg.set_title(i18n("Error!"))
                if saveMd or saveRc: errorMsg = str(i18n("Saving failed with an error!")) + '\n\n' + errorCodeRc[1] + '\n\n' + errorCodeMd[1]
                elif saveRc: errorMsg = str(i18n("Saving failed with an error!")) + '\n\n' + errorCodeRc[1]
                elif saveMd: errorMsg = str(i18n("Saving failed with an error!")) + '\n\n' + errorCodeMd[1]

            self.cbxSaveMd.set_active(False)
            self.cbxSaveRc.set_active(False)
            self.wndSaveChanges.hide()
        else:
            self.wndErrorMsg.set_title(i18n("Warning!"))
            errorMsg = str(i18n("Choose at least one item!"))
            
        self.lblErrorMsg.set_label(errorMsg)
        self.wndErrorMsg.set_transient_for(self.wndSaveChanges)
        self.wndErrorMsg.show()

    def save_rc_users(self):
        rcPath = '/mnt/livemedia/ublinux-data/rootcopy'
        path = '/memory/changes'

        # переход в рабочую директорию
        os.chdir(path)

        # создание строк команд для каждого файла
        cmdGp = 'rsync -aAXruR {0} {1}'.format('etc/group', rcPath)
        cmdPswd = 'rsync -aAXruR {0} {1}'.format('etc/passwd', rcPath)
        cmdShdw = 'rsync -aAXruR {0} {1}'.format('etc/shadow', rcPath)
        # объединение строк в ону
        cmd = '{0} && {1} && {2}'.format(cmdGp, cmdPswd, cmdShdw)

        errorCodeRc = subprocess.getstatusoutput(cmd)

        # При удачном копировании - отправить 0, иначе - список[КодОшибки, ТекстОшибки]
        if errorCodeRc[0] == 0:
            return 0
        elif errorCodeRc[0] >= 1:
            return errorCodeRc
    
    def save_md_users(self):
        currDate = re.sub('-', '.', str(datetime.date.today()))
        mdPath = '/mnt/livemedia/ublinux-data/modules'
        mdTmpPath = '/tmp/ublinux/changes/' + currDate + '-users-groups'
        path = '/memory/changes'
        
        # Проверка на существование каталога сurrDate-users-groups
        if not os.path.exists(mdTmpPath):
            os.makedirs(mdTmpPath)

        os.chdir(path)

        cmdGp = 'rsync -aAXruR {0} {1}'.format('etc/group', mdTmpPath)
        cmdPswd = 'rsync -aAXruR {0} {1}'.format('etc/passwd', mdTmpPath)
        cmdShdw = 'rsync -aAXruR {0} {1}'.format('etc/shadow', mdTmpPath)
        cmd = '{0} && {1} && {2}'.format(cmdGp, cmdPswd, cmdShdw)

        errorCodeCopyMd = subprocess.getstatusoutput(cmd)

        # Если копирование удалось - создать ubm
        if errorCodeCopyMd[0] == 0:
            cmdMkubm = 'mkubm -l $(find /tmp/ublinux/changes -iname \'*users-groups\' -maxdepth 1 -mindepth 1) -o {0}/{1}-users-groups.ubm'.format(mdPath, currDate)
            errorCodeMkubm = subprocess.getstatusoutput(cmdMkubm)
        else:
            return errorCodeCopyMd

        # Удалть рабочую папку
        shutil.rmtree(mdTmpPath)

        # При удачном создании модуля - отправить 0, иначе - список[КодОшибки, ТекстОшибки]
        if errorCodeMkubm[0] == 0:
            return 0
        elif errorCodeMkubm[0] >= 1:
            return errorCodeMkubm

if __name__ == '__main__':
    main=Main()
    Gtk.main()